toyoshim | 14a3234 | 2016-12-14 22:18:29 -0800 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "media/midi/midi_service.h" |
| 6 | |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 7 | #include "base/feature_list.h" |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 8 | #include "base/strings/stringprintf.h" |
Takashi Toyoshima | b3ec89a | 2017-11-09 14:02:48 +0000 | [diff] [blame] | 9 | #include "build/build_config.h" |
toyoshim | 14a3234 | 2016-12-14 22:18:29 -0800 | [diff] [blame] | 10 | #include "media/midi/midi_manager.h" |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 11 | #include "media/midi/midi_switches.h" |
toyoshim | ccb8ff9 | 2017-06-13 05:31:46 -0700 | [diff] [blame] | 12 | #include "media/midi/task_service.h" |
toyoshim | 14a3234 | 2016-12-14 22:18:29 -0800 | [diff] [blame] | 13 | |
| 14 | namespace midi { |
| 15 | |
Takashi Toyoshima | a88997d | 2017-09-07 08:30:18 +0000 | [diff] [blame] | 16 | std::unique_ptr<MidiManager> MidiService::ManagerFactory::Create( |
| 17 | MidiService* service) { |
| 18 | return std::unique_ptr<MidiManager>(MidiManager::Create(service)); |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 19 | } |
| 20 | |
Takashi Toyoshima | afb27d5 | 2017-09-13 11:50:41 +0000 | [diff] [blame] | 21 | // static |
tzik | 925e2c6 | 2018-02-02 07:39:45 +0000 | [diff] [blame] | 22 | base::TimeDelta MidiService::TimestampToTimeDeltaDelay( |
| 23 | base::TimeTicks timestamp) { |
| 24 | if (timestamp.is_null()) |
| 25 | return base::TimeDelta(); |
| 26 | return std::max(timestamp - base::TimeTicks::Now(), base::TimeDelta()); |
Takashi Toyoshima | afb27d5 | 2017-09-13 11:50:41 +0000 | [diff] [blame] | 27 | } |
| 28 | |
Takashi Toyoshima | bc959ee | 2018-01-09 16:04:04 +0900 | [diff] [blame] | 29 | MidiService::MidiService() : MidiService(std::make_unique<ManagerFactory>()) {} |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 30 | |
Takashi Toyoshima | a88997d | 2017-09-07 08:30:18 +0000 | [diff] [blame] | 31 | MidiService::MidiService(std::unique_ptr<ManagerFactory> factory) |
Takashi Toyoshima | a88997d | 2017-09-07 08:30:18 +0000 | [diff] [blame] | 32 | : manager_factory_(std::move(factory)), |
Takashi Toyoshima | bc959ee | 2018-01-09 16:04:04 +0900 | [diff] [blame] | 33 | task_service_(std::make_unique<TaskService>()) {} |
toyoshim | 14a3234 | 2016-12-14 22:18:29 -0800 | [diff] [blame] | 34 | |
| 35 | MidiService::~MidiService() { |
| 36 | base::AutoLock lock(lock_); |
Takashi Toyoshima | 5a6e6a3 | 2018-09-27 11:20:52 +0000 | [diff] [blame] | 37 | DCHECK(!manager_); |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 38 | base::AutoLock threads_lock(threads_lock_); |
| 39 | threads_.clear(); |
toyoshim | 14a3234 | 2016-12-14 22:18:29 -0800 | [diff] [blame] | 40 | } |
| 41 | |
| 42 | void MidiService::Shutdown() { |
| 43 | base::AutoLock lock(lock_); |
Takashi Toyoshima | f563b61 | 2017-05-26 20:19:00 +0900 | [diff] [blame] | 44 | if (manager_) { |
Adithya Srinivasan | c262ed3 | 2018-12-26 06:20:53 +0000 | [diff] [blame] | 45 | manager_->EndAllSessions(); |
Takashi Toyoshima | bc959ee | 2018-01-09 16:04:04 +0900 | [diff] [blame] | 46 | DCHECK(manager_destructor_runner_); |
Takashi Toyoshima | bc959ee | 2018-01-09 16:04:04 +0900 | [diff] [blame] | 47 | manager_destructor_runner_->DeleteSoon(FROM_HERE, std::move(manager_)); |
Takashi Toyoshima | f563b61 | 2017-05-26 20:19:00 +0900 | [diff] [blame] | 48 | manager_destructor_runner_ = nullptr; |
| 49 | } |
toyoshim | 14a3234 | 2016-12-14 22:18:29 -0800 | [diff] [blame] | 50 | } |
| 51 | |
| 52 | void MidiService::StartSession(MidiManagerClient* client) { |
| 53 | base::AutoLock lock(lock_); |
Takashi Toyoshima | f563b61 | 2017-05-26 20:19:00 +0900 | [diff] [blame] | 54 | if (!manager_) { |
Takashi Toyoshima | a88997d | 2017-09-07 08:30:18 +0000 | [diff] [blame] | 55 | manager_ = manager_factory_->Create(this); |
Takashi Toyoshima | bc959ee | 2018-01-09 16:04:04 +0900 | [diff] [blame] | 56 | DCHECK(!manager_destructor_runner_); |
| 57 | manager_destructor_runner_ = base::ThreadTaskRunnerHandle::Get(); |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 58 | } |
toyoshim | 14a3234 | 2016-12-14 22:18:29 -0800 | [diff] [blame] | 59 | manager_->StartSession(client); |
| 60 | } |
| 61 | |
Takashi Toyoshima | bc959ee | 2018-01-09 16:04:04 +0900 | [diff] [blame] | 62 | bool MidiService::EndSession(MidiManagerClient* client) { |
toyoshim | 14a3234 | 2016-12-14 22:18:29 -0800 | [diff] [blame] | 63 | base::AutoLock lock(lock_); |
Takashi Toyoshima | a15a222 | 2017-08-18 12:58:48 +0000 | [diff] [blame] | 64 | |
Takashi Toyoshima | 150b443 | 2017-08-21 12:08:09 +0000 | [diff] [blame] | 65 | // |client| does not seem to be valid. |
| 66 | if (!manager_ || !manager_->EndSession(client)) |
Takashi Toyoshima | bc959ee | 2018-01-09 16:04:04 +0900 | [diff] [blame] | 67 | return false; |
Takashi Toyoshima | f563b61 | 2017-05-26 20:19:00 +0900 | [diff] [blame] | 68 | |
Takashi Toyoshima | 9051b55 | 2017-11-27 10:00:16 +0000 | [diff] [blame] | 69 | // Do not destruct MidiManager on macOS to avoid a Core MIDI issue that |
| 70 | // MIDIClientCreate starts failing with the OSStatus -50 after repeated calls |
| 71 | // of MIDIClientDispose. It rarely happens, but once it starts, it will never |
| 72 | // get back to be sane. See https://crbug.com/718140. |
Avi Drissman | 56d38b6 | 2020-07-29 19:29:27 +0000 | [diff] [blame] | 73 | #if !defined(OS_MAC) |
Takashi Toyoshima | bc959ee | 2018-01-09 16:04:04 +0900 | [diff] [blame] | 74 | if (!manager_->HasOpenSession()) { |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 75 | // MidiManager for each platform should be able to shutdown correctly even |
Takashi Toyoshima | bc959ee | 2018-01-09 16:04:04 +0900 | [diff] [blame] | 76 | // if following destruction happens in the middle of StartInitialization(). |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 77 | manager_.reset(); |
Takashi Toyoshima | bc959ee | 2018-01-09 16:04:04 +0900 | [diff] [blame] | 78 | DCHECK(manager_destructor_runner_); |
| 79 | DCHECK(manager_destructor_runner_->BelongsToCurrentThread()); |
Takashi Toyoshima | f563b61 | 2017-05-26 20:19:00 +0900 | [diff] [blame] | 80 | manager_destructor_runner_ = nullptr; |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 81 | } |
Takashi Toyoshima | 9051b55 | 2017-11-27 10:00:16 +0000 | [diff] [blame] | 82 | #endif |
Takashi Toyoshima | bc959ee | 2018-01-09 16:04:04 +0900 | [diff] [blame] | 83 | return true; |
toyoshim | 14a3234 | 2016-12-14 22:18:29 -0800 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | void MidiService::DispatchSendMidiData(MidiManagerClient* client, |
| 87 | uint32_t port_index, |
| 88 | const std::vector<uint8_t>& data, |
tzik | 925e2c6 | 2018-02-02 07:39:45 +0000 | [diff] [blame] | 89 | base::TimeTicks timestamp) { |
toyoshim | 14a3234 | 2016-12-14 22:18:29 -0800 | [diff] [blame] | 90 | base::AutoLock lock(lock_); |
Takashi Toyoshima | a15a222 | 2017-08-18 12:58:48 +0000 | [diff] [blame] | 91 | |
| 92 | // MidiService needs to consider invalid DispatchSendMidiData calls without |
| 93 | // an open session that could be sent from a broken renderer. |
| 94 | if (manager_) |
| 95 | manager_->DispatchSendMidiData(client, port_index, data, timestamp); |
toyoshim | 14a3234 | 2016-12-14 22:18:29 -0800 | [diff] [blame] | 96 | } |
| 97 | |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 98 | scoped_refptr<base::SingleThreadTaskRunner> MidiService::GetTaskRunner( |
| 99 | size_t runner_id) { |
| 100 | base::AutoLock lock(threads_lock_); |
| 101 | if (threads_.size() <= runner_id) |
| 102 | threads_.resize(runner_id + 1); |
Takashi Toyoshima | f563b61 | 2017-05-26 20:19:00 +0900 | [diff] [blame] | 103 | if (!threads_[runner_id]) { |
Takashi Toyoshima | a88997d | 2017-09-07 08:30:18 +0000 | [diff] [blame] | 104 | threads_[runner_id] = std::make_unique<base::Thread>( |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 105 | base::StringPrintf("MidiServiceThread(%zu)", runner_id)); |
toyoshim | d28b59c | 2017-02-20 11:07:37 -0800 | [diff] [blame] | 106 | #if defined(OS_WIN) |
| 107 | threads_[runner_id]->init_com_with_mta(true); |
| 108 | #endif |
toyoshim | f4d6152 | 2017-02-10 02:03:32 -0800 | [diff] [blame] | 109 | threads_[runner_id]->Start(); |
| 110 | } |
| 111 | return threads_[runner_id]->task_runner(); |
| 112 | } |
| 113 | |
toyoshim | 14a3234 | 2016-12-14 22:18:29 -0800 | [diff] [blame] | 114 | } // namespace midi |