diff options
author | toyoshim@chromium.org <toyoshim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-01 17:17:32 +0000 |
---|---|---|
committer | toyoshim@chromium.org <toyoshim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-01 17:17:32 +0000 |
commit | 2b5376897c5d21b15c350383f810a9e0bb975ae3 (patch) | |
tree | 4f427897983803937129966dfbeb0e1f250925ab /media | |
parent | 6e9f63759e3b56ebedfd511f7735df949e2d5267 (diff) | |
download | chromium_src-2b5376897c5d21b15c350383f810a9e0bb975ae3.zip chromium_src-2b5376897c5d21b15c350383f810a9e0bb975ae3.tar.gz chromium_src-2b5376897c5d21b15c350383f810a9e0bb975ae3.tar.bz2 |
Web MIDI: make platform dependent initialization asynchronous
Since Android port needs asynchronous initialization, MIDIManager
should provide asynchronous initialization scheme for platform
dependent initialization.
BUG=339746
TEST=out/Debug/media_unittests --gtest_filter='Midi*.*'
Review URL: https://codereview.chromium.org/253493008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267555 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/media.gyp | 1 | ||||
-rw-r--r-- | media/midi/midi_manager.cc | 64 | ||||
-rw-r--r-- | media/midi/midi_manager.h | 23 | ||||
-rw-r--r-- | media/midi/midi_manager_alsa.cc | 21 | ||||
-rw-r--r-- | media/midi/midi_manager_alsa.h | 2 | ||||
-rw-r--r-- | media/midi/midi_manager_mac.cc | 22 | ||||
-rw-r--r-- | media/midi/midi_manager_mac.h | 2 | ||||
-rw-r--r-- | media/midi/midi_manager_unittest.cc | 187 | ||||
-rw-r--r-- | media/midi/midi_manager_usb.cc | 27 | ||||
-rw-r--r-- | media/midi/midi_manager_usb.h | 8 | ||||
-rw-r--r-- | media/midi/midi_manager_usb_unittest.cc | 85 | ||||
-rw-r--r-- | media/midi/midi_manager_win.cc | 6 | ||||
-rw-r--r-- | media/midi/midi_manager_win.h | 2 |
13 files changed, 348 insertions, 102 deletions
diff --git a/media/media.gyp b/media/media.gyp index 3e215b1..557ebaa 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -1053,6 +1053,7 @@ 'filters/video_frame_scheduler_unittest.cc', 'filters/video_frame_stream_unittest.cc', 'filters/video_renderer_impl_unittest.cc', + 'midi/midi_manager_unittest.cc', 'midi/midi_manager_usb_unittest.cc', 'midi/midi_message_queue_unittest.cc', 'midi/midi_message_util_unittest.cc', diff --git a/media/midi/midi_manager.cc b/media/midi/midi_manager.cc index 7384703..67845ce 100644 --- a/media/midi/midi_manager.cc +++ b/media/midi/midi_manager.cc @@ -4,8 +4,6 @@ #include "media/midi/midi_manager.h" -#include "base/bind.h" -#include "base/bind_helpers.h" #include "base/debug/trace_event.h" namespace media { @@ -26,18 +24,41 @@ MidiManager::~MidiManager() { } void MidiManager::StartSession(MidiManagerClient* client, int client_id) { + bool session_is_ready; + bool session_needs_initialization = false; + + { + base::AutoLock auto_lock(clients_lock_); + session_is_ready = initialized_; + if (!session_is_ready) { + // Call StartInitialization() only for the first request. + session_needs_initialization = pending_clients_.empty(); + pending_clients_.insert( + std::pair<int, MidiManagerClient*>(client_id, client)); + } + } + // Lazily initialize the MIDI back-end. - if (!initialized_) { - initialized_ = true; - result_ = Initialize(); + if (!session_is_ready) { + if (session_needs_initialization) { + TRACE_EVENT0("midi", "MidiManager::StartInitialization"); + StartInitialization(); + } + // CompleteInitialization() will be called asynchronously when platform + // dependent initialization is finished. + return; } - if (result_ == MIDI_OK) { + // Platform dependent initialization was already finished for previously + // initialized clients. + MidiResult result; + { base::AutoLock auto_lock(clients_lock_); - clients_.insert(client); + if (result_ == MIDI_OK) + clients_.insert(client); + result = result_; } - // TODO(toyoshim): Make Initialize() asynchronous. - client->CompleteStartSession(client_id, result_); + client->CompleteStartSession(client_id, result); } void MidiManager::EndSession(MidiManagerClient* client) { @@ -54,9 +75,28 @@ void MidiManager::DispatchSendMidiData(MidiManagerClient* client, NOTREACHED(); } -MidiResult MidiManager::Initialize() { - TRACE_EVENT0("midi", "MidiManager::Initialize"); - return MIDI_NOT_SUPPORTED; +void MidiManager::StartInitialization() { + CompleteInitialization(MIDI_NOT_SUPPORTED); +} + +void MidiManager::CompleteInitialization(MidiResult result) { + TRACE_EVENT0("midi", "MidiManager::CompleteInitialization"); + + base::AutoLock auto_lock(clients_lock_); + DCHECK(clients_.empty()); + DCHECK(!pending_clients_.empty()); + DCHECK(!initialized_); + initialized_ = true; + result_ = result; + + for (PendingClientMap::iterator it = pending_clients_.begin(); + it != pending_clients_.end(); + ++it) { + if (result_ == MIDI_OK) + clients_.insert(it->second); + it->second->CompleteStartSession(it->first, result_); + } + pending_clients_.clear(); } void MidiManager::AddInputPort(const MidiPortInfo& info) { diff --git a/media/midi/midi_manager.h b/media/midi/midi_manager.h index c21c66a..156a246 100644 --- a/media/midi/midi_manager.h +++ b/media/midi/midi_manager.h @@ -5,6 +5,7 @@ #ifndef MEDIA_MIDI_MIDI_MANAGER_H_ #define MEDIA_MIDI_MIDI_MANAGER_H_ +#include <map> #include <set> #include <vector> @@ -89,9 +90,19 @@ class MEDIA_EXPORT MidiManager { const MidiPortInfoList& output_ports() { return output_ports_; } protected: - // Initializes the MIDI system, returning |true| on success. - // The default implementation is for unsupported platforms. - virtual MidiResult Initialize(); + friend class MidiManagerUsb; + + // Initializes the platform dependent MIDI system. It will call + // CompleteInitialization() asynchronously when initialization is finished. + // |result| of CompleteInitialization() will be MIDI_OK on success. + // MidiManager has a default implementation that calls + // CompleteInitialization() with MIDI_NOT_SUPPORTED. + virtual void StartInitialization(); + + // Called from a platform dependent implementation of StartInitialization(). + // It will distribute |result| to MIDIManagerClient objects in + // |pending_clients_|. + void CompleteInitialization(MidiResult result); void AddInputPort(const MidiPortInfo& info); void AddOutputPort(const MidiPortInfo& info); @@ -119,7 +130,11 @@ class MEDIA_EXPORT MidiManager { typedef std::set<MidiManagerClient*> ClientList; ClientList clients_; - // Protects access to our clients. + // Keeps track of all clients who are waiting for CompleteStartSession(). + typedef std::map<int, MidiManagerClient*> PendingClientMap; + PendingClientMap pending_clients_; + + // Protects access to our clients, |clients_| and |pending_clients_|. base::Lock clients_lock_; MidiPortInfoList input_ports_; diff --git a/media/midi/midi_manager_alsa.cc b/media/midi/midi_manager_alsa.cc index dd12fc0..c4be32f 100644 --- a/media/midi/midi_manager_alsa.cc +++ b/media/midi/midi_manager_alsa.cc @@ -10,7 +10,6 @@ #include <string> #include "base/bind.h" -#include "base/debug/trace_event.h" #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" @@ -129,11 +128,7 @@ MidiManagerAlsa::MidiManagerAlsa() pipe_fd_[i] = -1; } -MidiResult MidiManagerAlsa::Initialize() { - // TODO(toyoshim): Make Initialize() asynchronous. - // See http://crbug.com/339746. - TRACE_EVENT0("midi", "MidiManagerAlsa::Initialize"); - +void MidiManagerAlsa::StartInitialization() { // Enumerate only hardware MIDI devices because software MIDIs running in // the browser process is not secure. snd_ctl_card_info_t* card; @@ -190,14 +185,14 @@ MidiResult MidiManagerAlsa::Initialize() { if (pipe(pipe_fd_) < 0) { VPLOG(1) << "pipe() failed"; - return MIDI_INITIALIZATION_ERROR; + CompleteInitialization(MIDI_INITIALIZATION_ERROR); + } else { + event_thread_.Start(); + event_thread_.message_loop()->PostTask( + FROM_HERE, + base::Bind(&MidiManagerAlsa::EventReset, base::Unretained(this))); + CompleteInitialization(MIDI_OK); } - event_thread_.Start(); - event_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&MidiManagerAlsa::EventReset, base::Unretained(this))); - - return MIDI_OK; } MidiManagerAlsa::~MidiManagerAlsa() { diff --git a/media/midi/midi_manager_alsa.h b/media/midi/midi_manager_alsa.h index 803496b..04e1d09 100644 --- a/media/midi/midi_manager_alsa.h +++ b/media/midi/midi_manager_alsa.h @@ -21,7 +21,7 @@ class MidiManagerAlsa : public MidiManager { virtual ~MidiManagerAlsa(); // MidiManager implementation. - virtual MidiResult Initialize() OVERRIDE; + virtual void StartInitialization() OVERRIDE; virtual void DispatchSendMidiData(MidiManagerClient* client, uint32 port_index, const std::vector<uint8>& data, diff --git a/media/midi/midi_manager_mac.cc b/media/midi/midi_manager_mac.cc index 0c9c869..c1302e6 100644 --- a/media/midi/midi_manager_mac.cc +++ b/media/midi/midi_manager_mac.cc @@ -6,7 +6,7 @@ #include <string> -#include "base/debug/trace_event.h" +#include "base/bind.h" #include "base/message_loop/message_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/sys_string_conversions.h" @@ -36,19 +36,14 @@ MidiManagerMac::MidiManagerMac() send_thread_("MidiSendThread") { } -MidiResult MidiManagerMac::Initialize() { - TRACE_EVENT0("midi", "MidiManagerMac::Initialize"); - +void MidiManagerMac::StartInitialization() { // CoreMIDI registration. midi_client_ = 0; - OSStatus result = MIDIClientCreate( - CFSTR("Google Chrome"), - NULL, - NULL, - &midi_client_); + OSStatus result = + MIDIClientCreate(CFSTR("Chrome"), NULL, NULL, &midi_client_); if (result != noErr) - return MIDI_INITIALIZATION_ERROR; + return CompleteInitialization(MIDI_INITIALIZATION_ERROR); coremidi_input_ = 0; @@ -60,14 +55,14 @@ MidiResult MidiManagerMac::Initialize() { this, &coremidi_input_); if (result != noErr) - return MIDI_INITIALIZATION_ERROR; + return CompleteInitialization(MIDI_INITIALIZATION_ERROR); result = MIDIOutputPortCreate( midi_client_, CFSTR("MIDI Output"), &coremidi_output_); if (result != noErr) - return MIDI_INITIALIZATION_ERROR; + return CompleteInitialization(MIDI_INITIALIZATION_ERROR); uint32 destination_count = MIDIGetNumberOfDestinations(); destinations_.resize(destination_count); @@ -98,11 +93,10 @@ MidiResult MidiManagerMac::Initialize() { AddInputPort(info); } - // TODO(toyoshim): Fix the memory management here! packet_list_ = reinterpret_cast<MIDIPacketList*>(midi_buffer_); midi_packet_ = MIDIPacketListInit(packet_list_); - return MIDI_OK; + CompleteInitialization(MIDI_OK); } void MidiManagerMac::DispatchSendMidiData(MidiManagerClient* client, diff --git a/media/midi/midi_manager_mac.h b/media/midi/midi_manager_mac.h index 5bd072d..5c514ff 100644 --- a/media/midi/midi_manager_mac.h +++ b/media/midi/midi_manager_mac.h @@ -24,7 +24,7 @@ class MEDIA_EXPORT MidiManagerMac : public MidiManager { virtual ~MidiManagerMac(); // MidiManager implementation. - virtual MidiResult Initialize() OVERRIDE; + virtual void StartInitialization() OVERRIDE; virtual void DispatchSendMidiData(MidiManagerClient* client, uint32 port_index, const std::vector<uint8>& data, diff --git a/media/midi/midi_manager_unittest.cc b/media/midi/midi_manager_unittest.cc new file mode 100644 index 0000000..178b0f6 --- /dev/null +++ b/media/midi/midi_manager_unittest.cc @@ -0,0 +1,187 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/midi/midi_manager.h" + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +namespace { + +class FakeMidiManager : public MidiManager { + public: + FakeMidiManager() + : start_initialization_is_called_(false), + complete_initialization_synchronously_(false) {} + virtual ~FakeMidiManager() {} + + // MidiManager implementation. + virtual void StartInitialization() OVERRIDE { + start_initialization_is_called_ = true; + if (complete_initialization_synchronously_) + CompleteInitialization(MIDI_OK); + } + + virtual void DispatchSendMidiData(MidiManagerClient* client, + uint32 port_index, + const std::vector<uint8>& data, + double timestamp) OVERRIDE {} + + // Utility functions for testing. + void CallCompleteInitialization(MidiResult result) { + CompleteInitialization(result); + } + + size_t GetClientCount() { + return clients_.size(); + } + + size_t GetPendingClientCount() { + return pending_clients_.size(); + } + + bool start_initialization_is_called_; + bool complete_initialization_synchronously_; + + private: + DISALLOW_COPY_AND_ASSIGN(FakeMidiManager); +}; + +class FakeMidiManagerClient : public MidiManagerClient { + public: + FakeMidiManagerClient(int client_id) : client_id_(client_id) {} + virtual ~FakeMidiManagerClient() {} + + // MidiManagerClient implementation. + virtual void CompleteStartSession(int client_id, MidiResult result) OVERRIDE { + DCHECK_EQ(client_id_, client_id); + result_ = result; + } + + virtual void ReceiveMidiData(uint32 port_index, const uint8* data, + size_t size, double timestamp) OVERRIDE {} + virtual void AccumulateMidiBytesSent(size_t size) OVERRIDE {} + + int GetClientId() { + return client_id_; + } + + MidiResult GetResult() { + return result_; + } + + private: + int client_id_; + MidiResult result_; + + DISALLOW_COPY_AND_ASSIGN(FakeMidiManagerClient); +}; + +class MidiManagerTest : public ::testing::Test { + public: + MidiManagerTest() : manager_(new FakeMidiManager) {} + virtual ~MidiManagerTest() {} + + protected: + void StartTheFirstSession(FakeMidiManagerClient* client, + bool complete_initialization_synchronously) { + manager_->complete_initialization_synchronously_ = + complete_initialization_synchronously; + EXPECT_FALSE(manager_->start_initialization_is_called_); + EXPECT_EQ(0U, manager_->GetClientCount()); + EXPECT_EQ(0U, manager_->GetPendingClientCount()); + manager_->StartSession(client, client->GetClientId()); + if (complete_initialization_synchronously) { + EXPECT_EQ(1U, manager_->GetClientCount()); + EXPECT_EQ(0U, manager_->GetPendingClientCount()); + EXPECT_TRUE(manager_->start_initialization_is_called_); + EXPECT_EQ(MIDI_OK, client->GetResult()); + } else { + EXPECT_EQ(0U, manager_->GetClientCount()); + EXPECT_EQ(1U, manager_->GetPendingClientCount()); + EXPECT_TRUE(manager_->start_initialization_is_called_); + EXPECT_EQ(0U, manager_->GetClientCount()); + EXPECT_EQ(1U, manager_->GetPendingClientCount()); + EXPECT_TRUE(manager_->start_initialization_is_called_); + } + } + + void StartTheSecondSession(FakeMidiManagerClient* client) { + EXPECT_TRUE(manager_->start_initialization_is_called_); + EXPECT_EQ(0U, manager_->GetClientCount()); + EXPECT_EQ(1U, manager_->GetPendingClientCount()); + + // StartInitialization() should not be called for the second session. + manager_->start_initialization_is_called_ = false; + manager_->StartSession(client, client->GetClientId()); + EXPECT_FALSE(manager_->start_initialization_is_called_); + } + + void EndSession(FakeMidiManagerClient* client, size_t before, size_t after) { + EXPECT_EQ(before, manager_->GetClientCount()); + manager_->EndSession(client); + EXPECT_EQ(after, manager_->GetClientCount()); + } + + void CompleteInitialization(MidiResult result) { + manager_->CallCompleteInitialization(result); + } + + private: + scoped_ptr<FakeMidiManager> manager_; + + DISALLOW_COPY_AND_ASSIGN(MidiManagerTest); +}; + +// Check if calling CompleteInitialization() does not acquire the same lock +// on the same thread. +TEST_F(MidiManagerTest, StartAndEndSessionSynchronously) { + scoped_ptr<FakeMidiManagerClient> client; + client.reset(new FakeMidiManagerClient(0)); + + StartTheFirstSession(client.get(), true); + EndSession(client.get(), 1U, 0U); +} + +TEST_F(MidiManagerTest, StartAndEndSession) { + scoped_ptr<FakeMidiManagerClient> client; + client.reset(new FakeMidiManagerClient(0)); + + StartTheFirstSession(client.get(), false); + CompleteInitialization(MIDI_OK); + EXPECT_EQ(MIDI_OK, client->GetResult()); + EndSession(client.get(), 1U, 0U); +} + +TEST_F(MidiManagerTest, StartAndEndSessionWithError) { + scoped_ptr<FakeMidiManagerClient> client; + client.reset(new FakeMidiManagerClient(1)); + + StartTheFirstSession(client.get(), false); + CompleteInitialization(MIDI_INITIALIZATION_ERROR); + EXPECT_EQ(MIDI_INITIALIZATION_ERROR, client->GetResult()); + EndSession(client.get(), 0U, 0U); +} + +TEST_F(MidiManagerTest, StartMultipleSessions) { + scoped_ptr<FakeMidiManagerClient> client1; + scoped_ptr<FakeMidiManagerClient> client2; + client1.reset(new FakeMidiManagerClient(0)); + client2.reset(new FakeMidiManagerClient(1)); + + StartTheFirstSession(client1.get(), false); + StartTheSecondSession(client2.get()); + CompleteInitialization(MIDI_OK); + EXPECT_EQ(MIDI_OK, client1->GetResult()); + EXPECT_EQ(MIDI_OK, client2->GetResult()); + EndSession(client1.get(), 2U, 1U); + EndSession(client2.get(), 1U, 0U); +} + +} // namespace + +} // namespace media diff --git a/media/midi/midi_manager_usb.cc b/media/midi/midi_manager_usb.cc index 3ac1dda..f2cf866 100644 --- a/media/midi/midi_manager_usb.cc +++ b/media/midi/midi_manager_usb.cc @@ -5,7 +5,6 @@ #include "media/midi/midi_manager_usb.h" #include "base/callback.h" -#include "base/debug/trace_event.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" @@ -17,16 +16,6 @@ namespace media { -namespace { - -// Noop callback for (sync) Initialize. -// TODO(yhirano): This function should go away when -// MidiManager::Initialize() becomes asynchronous. See http://crbug.com/339746. -void Noop(bool result) { -} - -} // namespace - MidiManagerUsb::MidiManagerUsb(scoped_ptr<UsbMidiDevice::Factory> factory) : device_factory_(factory.Pass()) { } @@ -34,13 +23,13 @@ MidiManagerUsb::MidiManagerUsb(scoped_ptr<UsbMidiDevice::Factory> factory) MidiManagerUsb::~MidiManagerUsb() { } -MidiResult MidiManagerUsb::Initialize() { - TRACE_EVENT0("midi", "MidiManagerUsb::Initialize"); - Initialize(base::Bind(Noop)); - return MIDI_OK; +void MidiManagerUsb::StartInitialization() { + Initialize( + base::Bind(&MidiManager::CompleteInitialization, base::Unretained(this))); } -void MidiManagerUsb::Initialize(base::Callback<void(bool result)> callback) { +void MidiManagerUsb::Initialize( + base::Callback<void(MidiResult result)> callback) { initialize_callback_ = callback; // This is safe because EnumerateDevices cancels the operation on destruction. device_factory_->EnumerateDevices( @@ -83,7 +72,7 @@ void MidiManagerUsb::OnReceivedData(size_t jack_index, void MidiManagerUsb::OnEnumerateDevicesDone(bool result, UsbMidiDevice::Devices* devices) { if (!result) { - initialize_callback_.Run(false); + initialize_callback_.Run(MIDI_INITIALIZATION_ERROR); return; } devices->swap(devices_); @@ -97,7 +86,7 @@ void MidiManagerUsb::OnEnumerateDevicesDone(bool result, descriptor.size(), &jacks); if (!parse_result) { - initialize_callback_.Run(false); + initialize_callback_.Run(MIDI_INITIALIZATION_ERROR); return; } std::vector<UsbMidiJack> input_jacks; @@ -115,7 +104,7 @@ void MidiManagerUsb::OnEnumerateDevicesDone(bool result, } input_stream_.reset(new UsbMidiInputStream(input_jacks, this)); } - initialize_callback_.Run(true); + initialize_callback_.Run(MIDI_OK); } } // namespace media diff --git a/media/midi/midi_manager_usb.h b/media/midi/midi_manager_usb.h index 59548dd..694a051 100644 --- a/media/midi/midi_manager_usb.h +++ b/media/midi/midi_manager_usb.h @@ -32,7 +32,7 @@ class MEDIA_EXPORT MidiManagerUsb : public MidiManager, virtual ~MidiManagerUsb(); // MidiManager implementation. - virtual MidiResult Initialize() OVERRIDE; + virtual void StartInitialization() OVERRIDE; virtual void DispatchSendMidiData(MidiManagerClient* client, uint32 port_index, const std::vector<uint8>& data, @@ -61,7 +61,9 @@ class MEDIA_EXPORT MidiManagerUsb : public MidiManager, // result. // When this factory is destroyed during the operation, the operation // will be canceled silently (i.e. |callback| will not be called). - void Initialize(base::Callback<void(bool result)> callback); + // The function is public just for unit tests. Do not call this function + // outside code for testing. + void Initialize(base::Callback<void(MidiResult result)> callback); private: void OnEnumerateDevicesDone(bool result, UsbMidiDevice::Devices* devices); @@ -71,7 +73,7 @@ class MEDIA_EXPORT MidiManagerUsb : public MidiManager, ScopedVector<UsbMidiOutputStream> output_streams_; scoped_ptr<UsbMidiInputStream> input_stream_; - base::Callback<void(bool result)> initialize_callback_; + base::Callback<void(MidiResult result)> initialize_callback_; // A map from <endpoint_number, cable_number> to the index of input jacks. base::hash_map<std::pair<int, int>, size_t> input_jack_dictionary_; diff --git a/media/midi/midi_manager_usb_unittest.cc b/media/midi/midi_manager_usb_unittest.cc index 4acc4c9..b9a2732 100644 --- a/media/midi/midi_manager_usb_unittest.cc +++ b/media/midi/midi_manager_usb_unittest.cc @@ -71,10 +71,15 @@ class FakeUsbMidiDevice : public UsbMidiDevice { class FakeMidiManagerClient : public MidiManagerClient { public: - explicit FakeMidiManagerClient(Logger* logger) : logger_(logger) {} + explicit FakeMidiManagerClient(Logger* logger) + : complete_start_session_(false), + result_(MIDI_NOT_SUPPORTED), + logger_(logger) {} virtual ~FakeMidiManagerClient() {} virtual void CompleteStartSession(int client_id, MidiResult result) OVERRIDE { + complete_start_session_ = true; + result_ = result; } virtual void ReceiveMidiData(uint32 port_index, @@ -95,6 +100,9 @@ class FakeMidiManagerClient : public MidiManagerClient { static_cast<unsigned>(size))); } + bool complete_start_session_; + MidiResult result_; + private: Logger* logger_; @@ -116,14 +124,28 @@ class TestUsbMidiDeviceFactory : public UsbMidiDevice::Factory { DISALLOW_COPY_AND_ASSIGN(TestUsbMidiDeviceFactory); }; +class MidiManagerUsbForTesting : public MidiManagerUsb { + public: + explicit MidiManagerUsbForTesting( + scoped_ptr<UsbMidiDevice::Factory> device_factory) + : MidiManagerUsb(device_factory.PassAs<UsbMidiDevice::Factory>()) {} + virtual ~MidiManagerUsbForTesting() {} + + void CallCompleteInitialization(MidiResult result) { + CompleteInitialization(result); + } + + private: + DISALLOW_COPY_AND_ASSIGN(MidiManagerUsbForTesting); +}; + class MidiManagerUsbTest : public ::testing::Test { public: - MidiManagerUsbTest() - : initialize_callback_run_(false), initialize_result_(false) { + MidiManagerUsbTest() { scoped_ptr<TestUsbMidiDeviceFactory> factory(new TestUsbMidiDeviceFactory); factory_ = factory.get(); manager_.reset( - new MidiManagerUsb(factory.PassAs<UsbMidiDevice::Factory>())); + new MidiManagerUsbForTesting(factory.PassAs<UsbMidiDevice::Factory>())); } virtual ~MidiManagerUsbTest() { std::string leftover_logs = logger_.TakeLog(); @@ -134,19 +156,24 @@ class MidiManagerUsbTest : public ::testing::Test { protected: void Initialize() { - manager_->Initialize(base::Bind(&MidiManagerUsbTest::OnInitializeDone, - base::Unretained(this))); + client_.reset(new FakeMidiManagerClient(&logger_)); + manager_->StartSession(client_.get(), 0); + } + + void Finalize() { + manager_->EndSession(client_.get()); } - void OnInitializeDone(bool result) { - initialize_callback_run_ = true; - initialize_result_ = result; + bool IsInitializationCallbackInvoked() { + return client_->complete_start_session_; } - bool initialize_callback_run_; - bool initialize_result_; + MidiResult GetInitializationResult() { + return client_->result_; + } - scoped_ptr<MidiManagerUsb> manager_; + scoped_ptr<MidiManagerUsbForTesting> manager_; + scoped_ptr<FakeMidiManagerClient> client_; // Owned by manager_. TestUsbMidiDeviceFactory* factory_; Logger logger_; @@ -179,10 +206,10 @@ TEST_F(MidiManagerUsbTest, Initialize) { Initialize(); ScopedVector<UsbMidiDevice> devices; devices.push_back(device.release()); - EXPECT_FALSE(initialize_callback_run_); + EXPECT_FALSE(IsInitializationCallbackInvoked()); factory_->callback_.Run(true, &devices); - EXPECT_TRUE(initialize_callback_run_); - EXPECT_TRUE(initialize_result_); + EXPECT_TRUE(IsInitializationCallbackInvoked()); + EXPECT_EQ(MIDI_OK, GetInitializationResult()); ASSERT_EQ(1u, manager_->input_ports().size()); ASSERT_EQ(2u, manager_->output_ports().size()); @@ -201,10 +228,10 @@ TEST_F(MidiManagerUsbTest, Initialize) { TEST_F(MidiManagerUsbTest, InitializeFail) { Initialize(); - EXPECT_FALSE(initialize_callback_run_); + EXPECT_FALSE(IsInitializationCallbackInvoked()); factory_->callback_.Run(false, NULL); - EXPECT_TRUE(initialize_callback_run_); - EXPECT_FALSE(initialize_result_); + EXPECT_TRUE(IsInitializationCallbackInvoked()); + EXPECT_EQ(MIDI_INITIALIZATION_ERROR, GetInitializationResult()); } TEST_F(MidiManagerUsbTest, InitializeFailBecauseOfInvalidDescriptor) { @@ -215,10 +242,10 @@ TEST_F(MidiManagerUsbTest, InitializeFailBecauseOfInvalidDescriptor) { Initialize(); ScopedVector<UsbMidiDevice> devices; devices.push_back(device.release()); - EXPECT_FALSE(initialize_callback_run_); + EXPECT_FALSE(IsInitializationCallbackInvoked()); factory_->callback_.Run(true, &devices); - EXPECT_TRUE(initialize_callback_run_); - EXPECT_FALSE(initialize_result_); + EXPECT_TRUE(IsInitializationCallbackInvoked()); + EXPECT_EQ(MIDI_INITIALIZATION_ERROR, GetInitializationResult()); EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_.TakeLog()); } @@ -251,10 +278,10 @@ TEST_F(MidiManagerUsbTest, Send) { Initialize(); ScopedVector<UsbMidiDevice> devices; devices.push_back(device.release()); - EXPECT_FALSE(initialize_callback_run_); + EXPECT_FALSE(IsInitializationCallbackInvoked()); factory_->callback_.Run(true, &devices); - ASSERT_TRUE(initialize_callback_run_); - ASSERT_TRUE(initialize_result_); + EXPECT_TRUE(IsInitializationCallbackInvoked()); + EXPECT_EQ(MIDI_OK, GetInitializationResult()); ASSERT_EQ(2u, manager_->output_streams().size()); manager_->DispatchSendMidiData(&client, 1, ToVector(data), 0); @@ -269,7 +296,6 @@ TEST_F(MidiManagerUsbTest, Send) { TEST_F(MidiManagerUsbTest, Receive) { scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_)); - FakeMidiManagerClient client(&logger_); uint8 descriptor[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, @@ -299,15 +325,14 @@ TEST_F(MidiManagerUsbTest, Receive) { ScopedVector<UsbMidiDevice> devices; UsbMidiDevice* device_raw = device.get(); devices.push_back(device.release()); - EXPECT_FALSE(initialize_callback_run_); + EXPECT_FALSE(IsInitializationCallbackInvoked()); factory_->callback_.Run(true, &devices); - ASSERT_TRUE(initialize_callback_run_); - ASSERT_TRUE(initialize_result_); + EXPECT_TRUE(IsInitializationCallbackInvoked()); + EXPECT_EQ(MIDI_OK, GetInitializationResult()); - manager_->StartSession(&client, 0); manager_->ReceiveUsbMidiData(device_raw, 2, data, arraysize(data), base::TimeTicks()); - manager_->EndSession(&client); + Finalize(); EXPECT_EQ("UsbMidiDevice::GetDescriptor\n" "MidiManagerClient::ReceiveMidiData port_index = 0 " diff --git a/media/midi/midi_manager_win.cc b/media/midi/midi_manager_win.cc index d556e3a..a422299 100644 --- a/media/midi/midi_manager_win.cc +++ b/media/midi/midi_manager_win.cc @@ -21,7 +21,6 @@ #include <algorithm> #include <string> #include "base/bind.h" -#include "base/debug/trace_event.h" #include "base/message_loop/message_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -497,8 +496,7 @@ MidiManagerWin::MidiManagerWin() : send_thread_("MidiSendThread") { } -MidiResult MidiManagerWin::Initialize() { - TRACE_EVENT0("midi", "MidiManagerWin::Initialize"); +void MidiManagerWin::StartInitialization() { const UINT num_in_devices = midiInGetNumDevs(); in_devices_.reserve(num_in_devices); for (UINT device_id = 0; device_id < num_in_devices; ++device_id) { @@ -544,7 +542,7 @@ MidiResult MidiManagerWin::Initialize() { out_devices_.push_back(out_port.Pass()); } - return MIDI_OK; + CompleteInitialization(MIDI_OK); } MidiManagerWin::~MidiManagerWin() { diff --git a/media/midi/midi_manager_win.h b/media/midi/midi_manager_win.h index 7b38ab4b..8a951f8 100644 --- a/media/midi/midi_manager_win.h +++ b/media/midi/midi_manager_win.h @@ -20,7 +20,7 @@ class MidiManagerWin : public MidiManager { virtual ~MidiManagerWin(); // MidiManager implementation. - virtual MidiResult Initialize() OVERRIDE; + virtual void StartInitialization() OVERRIDE; virtual void DispatchSendMidiData(MidiManagerClient* client, uint32 port_index, const std::vector<uint8>& data, |