1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file. 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "media/midi/midi_manager.h" 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/bind.h" 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/debug/trace_event.h" 9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/message_loop/message_loop.h" 10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace media { 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MidiManager::MidiManager() 15a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : initialized_(false), 16a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch result_(MIDI_NOT_SUPPORTED) { 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MidiManager::~MidiManager() { 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(USE_ALSA) && \ 23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) !defined(OS_ANDROID) && !defined(OS_CHROMEOS) 24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)MidiManager* MidiManager::Create() { 25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return new MidiManager; 26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 29a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid MidiManager::StartSession(MidiManagerClient* client, int client_id) { 30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool session_is_ready; 31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool session_needs_initialization = false; 32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool too_many_pending_clients_exist = false; 33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) { 35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::AutoLock auto_lock(lock_); 36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) session_is_ready = initialized_; 37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!session_is_ready) { 38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Do not accept a new request if the pending client list contains too 39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // many clients. 40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) too_many_pending_clients_exist = 41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) pending_clients_.size() >= kMaxPendingClientCount; 42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!too_many_pending_clients_exist) { 44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Call StartInitialization() only for the first request. 45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) session_needs_initialization = pending_clients_.empty(); 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pending_clients_.insert(std::make_pair(client, client_id)); 47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Lazily initialize the MIDI back-end. 52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!session_is_ready) { 53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (session_needs_initialization) { 54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) TRACE_EVENT0("midi", "MidiManager::StartInitialization"); 55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) session_thread_runner_ = 56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::MessageLoop::current()->message_loop_proxy(); 57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) StartInitialization(); 58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (too_many_pending_clients_exist) { 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Return an error immediately if there are too many requests. 61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) client->CompleteStartSession(client_id, MIDI_INITIALIZATION_ERROR); 62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // CompleteInitialization() will be called asynchronously when platform 65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // dependent initialization is finished. 66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 67a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Platform dependent initialization was already finished for previously 70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // initialized clients. 71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) MidiResult result; 72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) { 73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::AutoLock auto_lock(lock_); 74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (result_ == MIDI_OK) 75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) clients_.insert(client); 76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) result = result_; 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) client->CompleteStartSession(client_id, result); 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MidiManager::EndSession(MidiManagerClient* client) { 82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::AutoLock auto_lock(lock_); 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) clients_.erase(client); 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pending_clients_.erase(client); 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MidiManager::DispatchSendMidiData(MidiManagerClient* client, 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32 port_index, 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::vector<uint8>& data, 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) double timestamp) { 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MidiManager::StartInitialization() { 95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CompleteInitialization(MIDI_NOT_SUPPORTED); 96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MidiManager::CompleteInitialization(MidiResult result) { 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(session_thread_runner_.get()); 100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // It is safe to post a task to the IO thread from here because the IO thread 101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // should have stopped if the MidiManager is going to be destructed. 102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) session_thread_runner_->PostTask( 103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) FROM_HERE, 104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::Bind(&MidiManager::CompleteInitializationInternal, 105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::Unretained(this), 106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) result)); 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MidiManager::AddInputPort(const MidiPortInfo& info) { 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch input_ports_.push_back(info); 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MidiManager::AddOutputPort(const MidiPortInfo& info) { 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch output_ports_.push_back(info); 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MidiManager::ReceiveMidiData( 118424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint32 port_index, 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const uint8* data, 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t length, 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double timestamp) { 122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::AutoLock auto_lock(lock_); 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (ClientList::iterator i = clients_.begin(); i != clients_.end(); ++i) 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*i)->ReceiveMidiData(port_index, data, length, timestamp); 126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MidiManager::CompleteInitializationInternal(MidiResult result) { 129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) TRACE_EVENT0("midi", "MidiManager::CompleteInitialization"); 130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::AutoLock auto_lock(lock_); 132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(clients_.empty()); 133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(!initialized_); 134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) initialized_ = true; 135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) result_ = result; 136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (PendingClientMap::iterator it = pending_clients_.begin(); 138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) it != pending_clients_.end(); 139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ++it) { 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (result_ == MIDI_OK) 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) clients_.insert(it->first); 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) it->first->CompleteStartSession(it->second, result_); 143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) pending_clients_.clear(); 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace media 148