OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/midi/midi_service.h" | 5 #include "media/midi/midi_service.h" |
6 | 6 |
| 7 #include "base/feature_list.h" |
| 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/strings/stringprintf.h" |
7 #include "media/midi/midi_manager.h" | 10 #include "media/midi/midi_manager.h" |
| 11 #include "media/midi/midi_switches.h" |
8 | 12 |
9 namespace midi { | 13 namespace midi { |
10 | 14 |
| 15 namespace { |
| 16 |
| 17 // TODO(toyoshim): Support on all platforms. See https://crbug.com/672793. |
| 18 #if defined(OS_LINUX) |
| 19 constexpr bool kIsDynamicInstantiationSupported = true; |
| 20 #else |
| 21 constexpr bool kIsDynamicInstantiationSupported = false; |
| 22 #endif |
| 23 |
| 24 MidiService* g_midi_service = nullptr; |
| 25 |
| 26 } // namespace |
| 27 |
11 MidiService::MidiService(std::unique_ptr<MidiManager> manager) { | 28 MidiService::MidiService(std::unique_ptr<MidiManager> manager) { |
12 base::AutoLock lock(lock_); | 29 base::AutoLock lock(lock_); |
13 if (manager.get()) | 30 |
| 31 CHECK(!g_midi_service); |
| 32 g_midi_service = this; |
| 33 |
| 34 is_dynamic_instantiation_enabled_ = false; |
| 35 active_clients_ = 0u; |
| 36 if (manager.get()) { |
14 manager_ = std::move(manager); | 37 manager_ = std::move(manager); |
15 else | 38 } else if (kIsDynamicInstantiationSupported && |
16 manager_.reset(MidiManager::Create()); | 39 base::FeatureList::IsEnabled( |
| 40 features::kMidiManagerDynamicInstantiation)) { |
| 41 is_dynamic_instantiation_enabled_ = true; |
| 42 } else { |
| 43 manager_ = base::WrapUnique(MidiManager::Create()); |
| 44 } |
17 } | 45 } |
18 | 46 |
19 MidiService::~MidiService() { | 47 MidiService::~MidiService() { |
20 base::AutoLock lock(lock_); | 48 base::AutoLock lock(lock_); |
| 49 |
21 manager_.reset(); | 50 manager_.reset(); |
| 51 |
| 52 CHECK(g_midi_service); |
| 53 g_midi_service = nullptr; |
| 54 |
| 55 base::AutoLock threads_lock(threads_lock_); |
| 56 threads_.clear(); |
22 } | 57 } |
23 | 58 |
24 void MidiService::Shutdown() { | 59 void MidiService::Shutdown() { |
25 base::AutoLock lock(lock_); | 60 base::AutoLock lock(lock_); |
26 manager_->Shutdown(); | 61 if (manager_.get()) |
| 62 manager_->Shutdown(); |
27 } | 63 } |
28 | 64 |
29 void MidiService::StartSession(MidiManagerClient* client) { | 65 void MidiService::StartSession(MidiManagerClient* client) { |
30 base::AutoLock lock(lock_); | 66 base::AutoLock lock(lock_); |
| 67 if (!manager_.get()) { |
| 68 CHECK(is_dynamic_instantiation_enabled_); |
| 69 CHECK_EQ(0u, active_clients_); |
| 70 manager_.reset(MidiManager::Create()); |
| 71 } |
| 72 active_clients_++; |
31 manager_->StartSession(client); | 73 manager_->StartSession(client); |
32 } | 74 } |
33 | 75 |
34 void MidiService::EndSession(MidiManagerClient* client) { | 76 void MidiService::EndSession(MidiManagerClient* client) { |
35 base::AutoLock lock(lock_); | 77 base::AutoLock lock(lock_); |
| 78 CHECK(manager_.get()); |
| 79 CHECK_NE(0u, active_clients_); |
36 manager_->EndSession(client); | 80 manager_->EndSession(client); |
| 81 active_clients_--; |
| 82 if (is_dynamic_instantiation_enabled_ && !active_clients_) { |
| 83 // MidiManager for each platform should be able to shutdown correctly even |
| 84 // if following Shutdown() call happens in the middle of |
| 85 // StartInitialization() to support the dynamic instantiation feature. |
| 86 manager_->Shutdown(); |
| 87 manager_.reset(); |
| 88 } |
37 } | 89 } |
38 | 90 |
39 void MidiService::DispatchSendMidiData(MidiManagerClient* client, | 91 void MidiService::DispatchSendMidiData(MidiManagerClient* client, |
40 uint32_t port_index, | 92 uint32_t port_index, |
41 const std::vector<uint8_t>& data, | 93 const std::vector<uint8_t>& data, |
42 double timestamp) { | 94 double timestamp) { |
43 base::AutoLock lock(lock_); | 95 base::AutoLock lock(lock_); |
44 manager_->DispatchSendMidiData(client, port_index, data, timestamp); | 96 manager_->DispatchSendMidiData(client, port_index, data, timestamp); |
45 } | 97 } |
46 | 98 |
| 99 // static |
| 100 scoped_refptr<base::SingleThreadTaskRunner> MidiService::GetTaskRunner( |
| 101 size_t runner_id) { |
| 102 // MidiService outlives MidiManager that could call GetTaskRunner(). |
| 103 return g_midi_service->GetTaskRunnerImpl(runner_id); |
| 104 } |
| 105 |
| 106 scoped_refptr<base::SingleThreadTaskRunner> MidiService::GetTaskRunnerImpl( |
| 107 size_t runner_id) { |
| 108 base::AutoLock lock(threads_lock_); |
| 109 if (threads_.size() <= runner_id) |
| 110 threads_.resize(runner_id + 1); |
| 111 if (!threads_[runner_id].get()) { |
| 112 threads_[runner_id] = base::MakeUnique<base::Thread>( |
| 113 base::StringPrintf("MidiServiceThread(%zu)", runner_id)); |
| 114 threads_[runner_id]->Start(); |
| 115 } |
| 116 return threads_[runner_id]->task_runner(); |
| 117 } |
| 118 |
47 } // namespace midi | 119 } // namespace midi |
OLD | NEW |