1 // Copyright (c) 2013 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.
5 #include "media/midi/midi_manager.h"
8 #include "base/debug/trace_event.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/message_loop/message_loop_proxy.h"
14 MidiManager::MidiManager()
15 : initialized_(false),
16 result_(MIDI_NOT_SUPPORTED
) {
19 MidiManager::~MidiManager() {
22 #if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(USE_ALSA) && \
23 !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
24 MidiManager
* MidiManager::Create() {
25 return new MidiManager
;
29 void MidiManager::StartSession(MidiManagerClient
* client
, int client_id
) {
30 bool session_is_ready
;
31 bool session_needs_initialization
= false;
32 bool too_many_pending_clients_exist
= false;
35 base::AutoLock
auto_lock(lock_
);
36 session_is_ready
= initialized_
;
37 if (!session_is_ready
) {
38 // Do not accept a new request if the pending client list contains too
40 too_many_pending_clients_exist
=
41 pending_clients_
.size() >= kMaxPendingClientCount
;
43 if (!too_many_pending_clients_exist
) {
44 // Call StartInitialization() only for the first request.
45 session_needs_initialization
= pending_clients_
.empty();
46 pending_clients_
.insert(
47 std::pair
<int, MidiManagerClient
*>(client_id
, client
));
52 // Lazily initialize the MIDI back-end.
53 if (!session_is_ready
) {
54 if (session_needs_initialization
) {
55 TRACE_EVENT0("midi", "MidiManager::StartInitialization");
56 session_thread_runner_
=
57 base::MessageLoop::current()->message_loop_proxy();
58 StartInitialization();
60 if (too_many_pending_clients_exist
) {
61 // Return an error immediately if there are too many requests.
62 client
->CompleteStartSession(client_id
, MIDI_INITIALIZATION_ERROR
);
65 // CompleteInitialization() will be called asynchronously when platform
66 // dependent initialization is finished.
70 // Platform dependent initialization was already finished for previously
71 // initialized clients.
74 base::AutoLock
auto_lock(lock_
);
75 if (result_
== MIDI_OK
)
76 clients_
.insert(client
);
79 client
->CompleteStartSession(client_id
, result
);
82 void MidiManager::EndSession(MidiManagerClient
* client
) {
83 base::AutoLock
auto_lock(lock_
);
84 ClientList::iterator i
= clients_
.find(client
);
85 if (i
!= clients_
.end())
89 void MidiManager::DispatchSendMidiData(MidiManagerClient
* client
,
91 const std::vector
<uint8
>& data
,
96 void MidiManager::StartInitialization() {
97 CompleteInitialization(MIDI_NOT_SUPPORTED
);
100 void MidiManager::CompleteInitialization(MidiResult result
) {
101 DCHECK(session_thread_runner_
.get());
102 // It is safe to post a task to the IO thread from here because the IO thread
103 // should have stopped if the MidiManager is going to be destructed.
104 session_thread_runner_
->PostTask(
106 base::Bind(&MidiManager::CompleteInitializationInternal
,
107 base::Unretained(this),
111 void MidiManager::AddInputPort(const MidiPortInfo
& info
) {
112 input_ports_
.push_back(info
);
115 void MidiManager::AddOutputPort(const MidiPortInfo
& info
) {
116 output_ports_
.push_back(info
);
119 void MidiManager::ReceiveMidiData(
124 base::AutoLock
auto_lock(lock_
);
126 for (ClientList::iterator i
= clients_
.begin(); i
!= clients_
.end(); ++i
)
127 (*i
)->ReceiveMidiData(port_index
, data
, length
, timestamp
);
130 void MidiManager::CompleteInitializationInternal(MidiResult result
) {
131 TRACE_EVENT0("midi", "MidiManager::CompleteInitialization");
133 base::AutoLock
auto_lock(lock_
);
134 DCHECK(clients_
.empty());
135 DCHECK(!pending_clients_
.empty());
136 DCHECK(!initialized_
);
140 for (PendingClientMap::iterator it
= pending_clients_
.begin();
141 it
!= pending_clients_
.end();
143 if (result_
== MIDI_OK
)
144 clients_
.insert(it
->second
);
145 it
->second
->CompleteStartSession(it
->first
, result_
);
147 pending_clients_
.clear();