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); | |
yhirano
2017/02/08 03:50:24
Is it possible to store a MidiService pointer in M
| |
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 |