summaryrefslogtreecommitdiffstats
path: root/media/midi
diff options
context:
space:
mode:
authortoyoshim@chromium.org <toyoshim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-01 17:17:32 +0000
committertoyoshim@chromium.org <toyoshim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-01 17:17:32 +0000
commit2b5376897c5d21b15c350383f810a9e0bb975ae3 (patch)
tree4f427897983803937129966dfbeb0e1f250925ab /media/midi
parent6e9f63759e3b56ebedfd511f7735df949e2d5267 (diff)
downloadchromium_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/midi')
-rw-r--r--media/midi/midi_manager.cc64
-rw-r--r--media/midi/midi_manager.h23
-rw-r--r--media/midi/midi_manager_alsa.cc21
-rw-r--r--media/midi/midi_manager_alsa.h2
-rw-r--r--media/midi/midi_manager_mac.cc22
-rw-r--r--media/midi/midi_manager_mac.h2
-rw-r--r--media/midi/midi_manager_unittest.cc187
-rw-r--r--media/midi/midi_manager_usb.cc27
-rw-r--r--media/midi/midi_manager_usb.h8
-rw-r--r--media/midi/midi_manager_usb_unittest.cc85
-rw-r--r--media/midi/midi_manager_win.cc6
-rw-r--r--media/midi/midi_manager_win.h2
12 files changed, 347 insertions, 102 deletions
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,