diff options
author | yukawa@chromium.org <yukawa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-04 15:42:41 +0000 |
---|---|---|
committer | yukawa@chromium.org <yukawa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-04 15:42:41 +0000 |
commit | c395a3a6a87f4096cbb11df7833336389b041e5b (patch) | |
tree | 5833d5a20b5c9a3b3ccc942ff8fc9ee33e45295b /media/midi | |
parent | 3ef32f15ca6c87b6375dd9b96f4adfa07e844361 (diff) | |
download | chromium_src-c395a3a6a87f4096cbb11df7833336389b041e5b.zip chromium_src-c395a3a6a87f4096cbb11df7833336389b041e5b.tar.gz chromium_src-c395a3a6a87f4096cbb11df7833336389b041e5b.tar.bz2 |
Make MIDIManager::DispatchSendMIDIData pure virtual.
With this CL, each OS-specific implementation of MIDIManager is responsible for implementing DispatchSendMIDIData() as a non-blocking function.
Main motivations of this change are:
- Whether non-blocking implementation of DispatchSendMIDIData() requires a background thread or not depends on MIDI APIs on each platform.
- If the base class owns a background thread and the actual dispatch method is overridden by each implementation class, such background thread must be terminated *before* the subclass destructor() is finished to avoid pure virtual function call. This is a trick requirement in resource cleanup order that we'd like to avoid.
BUG=303599
TEST=manually done on Mac
Review URL: https://codereview.chromium.org/97583002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238703 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/midi')
-rw-r--r-- | media/midi/midi_manager.cc | 26 | ||||
-rw-r--r-- | media/midi/midi_manager.h | 34 | ||||
-rw-r--r-- | media/midi/midi_manager_mac.cc | 24 | ||||
-rw-r--r-- | media/midi/midi_manager_mac.h | 18 |
4 files changed, 45 insertions, 57 deletions
diff --git a/media/midi/midi_manager.cc b/media/midi/midi_manager.cc index b3262e4..ef9f473 100644 --- a/media/midi/midi_manager.cc +++ b/media/midi/midi_manager.cc @@ -6,8 +6,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/message_loop/message_loop.h" -#include "base/threading/thread.h" namespace media { @@ -22,7 +20,8 @@ MIDIManager::MIDIManager() : initialized_(false) { } -MIDIManager::~MIDIManager() {} +MIDIManager::~MIDIManager() { +} bool MIDIManager::StartSession(MIDIManagerClient* client) { // Lazily initialize the MIDI back-end. @@ -63,25 +62,4 @@ void MIDIManager::ReceiveMIDIData( (*i)->ReceiveMIDIData(port_index, data, length, timestamp); } -bool MIDIManager::CurrentlyOnMIDISendThread() { - return send_thread_->message_loop() == base::MessageLoop::current(); -} - -void MIDIManager::DispatchSendMIDIData(MIDIManagerClient* client, - uint32 port_index, - const std::vector<uint8>& data, - double timestamp) { - // Lazily create the thread when first needed. - if (!send_thread_) { - send_thread_.reset(new base::Thread("MIDISendThread")); - send_thread_->Start(); - send_message_loop_ = send_thread_->message_loop_proxy(); - } - - send_message_loop_->PostTask( - FROM_HERE, - base::Bind(&MIDIManager::SendMIDIData, base::Unretained(this), - client, port_index, data, timestamp)); -} - } // namespace media diff --git a/media/midi/midi_manager.h b/media/midi/midi_manager.h index 6a301a9..f42a40d 100644 --- a/media/midi/midi_manager.h +++ b/media/midi/midi_manager.h @@ -9,16 +9,10 @@ #include <vector> #include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop_proxy.h" #include "base/synchronization/lock.h" #include "media/base/media_export.h" #include "media/midi/midi_port_info.h" -namespace base { -class Thread; -} - namespace media { // A MIDIManagerClient registers with the MIDIManager to receive MIDI data. @@ -63,17 +57,18 @@ class MEDIA_EXPORT MIDIManager { // A client calls ReleaseSession() to stop receiving MIDI data. void EndSession(MIDIManagerClient* client); - // DispatchSendMIDIData() schedules one or more messages to be sent - // at the given time on a dedicated thread. + // DispatchSendMIDIData() is called when MIDI data should be sent to the MIDI + // system. + // This method is supposed to return immediately and should not block. // |port_index| represents the specific output port from output_ports(). // |data| represents a series of bytes encoding one or more MIDI messages. // |length| is the number of bytes in |data|. // |timestamp| is the time to send the data, in seconds. A value of 0 // means send "now" or as soon as possible. - void DispatchSendMIDIData(MIDIManagerClient* client, - uint32 port_index, - const std::vector<uint8>& data, - double timestamp); + virtual void DispatchSendMIDIData(MIDIManagerClient* client, + uint32 port_index, + const std::vector<uint8>& data, + double timestamp) = 0; // input_ports() is a list of MIDI ports for receiving MIDI data. // Each individual port in this list can be identified by its @@ -89,13 +84,6 @@ class MEDIA_EXPORT MIDIManager { // Initializes the MIDI system, returning |true| on success. virtual bool Initialize() = 0; - // Implements the platform-specific details of sending MIDI data. - // This function runs on MIDISendThread. - virtual void SendMIDIData(MIDIManagerClient* client, - uint32 port_index, - const std::vector<uint8>& data, - double timestamp) = 0; - void AddInputPort(const MIDIPortInfo& info); void AddOutputPort(const MIDIPortInfo& info); @@ -105,9 +93,6 @@ class MEDIA_EXPORT MIDIManager { size_t length, double timestamp); - // Checks if current thread is MIDISendThread. - bool CurrentlyOnMIDISendThread(); - bool initialized_; // Keeps track of all clients who wish to receive MIDI data. @@ -120,11 +105,6 @@ class MEDIA_EXPORT MIDIManager { MIDIPortInfoList input_ports_; MIDIPortInfoList output_ports_; - // |send_thread_| is used to send MIDI data by calling the platform-specific - // API. - scoped_ptr<base::Thread> send_thread_; - scoped_refptr<base::MessageLoopProxy> send_message_loop_; - DISALLOW_COPY_AND_ASSIGN(MIDIManager); }; diff --git a/media/midi/midi_manager_mac.cc b/media/midi/midi_manager_mac.cc index 0294024..8fd0065 100644 --- a/media/midi/midi_manager_mac.cc +++ b/media/midi/midi_manager_mac.cc @@ -7,8 +7,10 @@ #include <string> #include "base/debug/trace_event.h" +#include "base/message_loop/message_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/sys_string_conversions.h" + #include <CoreAudio/HostTime.h> using base::IntToString; @@ -30,7 +32,8 @@ MIDIManagerMac::MIDIManagerMac() coremidi_input_(0), coremidi_output_(0), packet_list_(NULL), - midi_packet_(NULL) { + midi_packet_(NULL), + send_thread_("MIDISendThread") { } bool MIDIManagerMac::Initialize() { @@ -102,7 +105,24 @@ bool MIDIManagerMac::Initialize() { return true; } +void MIDIManagerMac::DispatchSendMIDIData(MIDIManagerClient* client, + uint32 port_index, + const std::vector<uint8>& data, + double timestamp) { + if (send_thread_.IsRunning()) + send_thread_.Start(); + + // OK to use base::Unretained(this) since we join to thread in dtor(). + send_thread_.message_loop()->PostTask( + FROM_HERE, + base::Bind(&MIDIManagerMac::SendMIDIData, base::Unretained(this), + client, port_index, data, timestamp)); +} + MIDIManagerMac::~MIDIManagerMac() { + // Wait for the termination of |send_thread_| before disposing MIDI ports. + send_thread_.Stop(); + if (coremidi_input_) MIDIPortDispose(coremidi_input_); if (coremidi_output_) @@ -150,7 +170,7 @@ void MIDIManagerMac::SendMIDIData(MIDIManagerClient* client, uint32 port_index, const std::vector<uint8>& data, double timestamp) { - DCHECK(CurrentlyOnMIDISendThread()); + DCHECK(send_thread_.message_loop_proxy()->BelongsToCurrentThread()); // System Exclusive has already been filtered. MIDITimeStamp coremidi_timestamp = SecondsToMIDITimeStamp(timestamp); diff --git a/media/midi/midi_manager_mac.h b/media/midi/midi_manager_mac.h index 2397b80..cc8bf74 100644 --- a/media/midi/midi_manager_mac.h +++ b/media/midi/midi_manager_mac.h @@ -12,6 +12,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/threading/thread.h" #include "media/midi/midi_manager.h" #include "media/midi/midi_port_info.h" @@ -24,10 +25,10 @@ class MEDIA_EXPORT MIDIManagerMac : public MIDIManager { // MIDIManager implementation. virtual bool Initialize() OVERRIDE; - virtual void SendMIDIData(MIDIManagerClient* client, - uint32 port_index, - const std::vector<uint8>& data, - double timestamp) OVERRIDE; + virtual void DispatchSendMIDIData(MIDIManagerClient* client, + uint32 port_index, + const std::vector<uint8>& data, + double timestamp) OVERRIDE; private: // CoreMIDI callback for MIDI data. @@ -39,6 +40,12 @@ class MEDIA_EXPORT MIDIManagerMac : public MIDIManager { void *src_conn_refcon); virtual void ReadMIDI(MIDIEndpointRef source, const MIDIPacketList *pktlist); + // An internal callback that runs on MIDISendThread. + void SendMIDIData(MIDIManagerClient* client, + uint32 port_index, + const std::vector<uint8>& data, + double timestamp); + // Helper static media::MIDIPortInfo GetPortInfoFromEndpoint(MIDIEndpointRef endpoint); static double MIDITimeStampToSeconds(MIDITimeStamp timestamp); @@ -62,6 +69,9 @@ class MEDIA_EXPORT MIDIManagerMac : public MIDIManager { // Keeps track of all destinations. std::vector<MIDIEndpointRef> destinations_; + // |send_thread_| is used to send MIDI data. + base::Thread send_thread_; + DISALLOW_COPY_AND_ASSIGN(MIDIManagerMac); }; |