#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"
+
#include <CoreAudio/HostTime.h>
using base::IntToString;
namespace media {
-MIDIManager* MIDIManager::Create() {
- return new MIDIManagerMac();
+MidiManager* MidiManager::Create() {
+ return new MidiManagerMac();
}
-MIDIManagerMac::MIDIManagerMac()
+MidiManagerMac::MidiManagerMac()
: midi_client_(0),
coremidi_input_(0),
coremidi_output_(0),
packet_list_(NULL),
- midi_packet_(NULL) {
+ midi_packet_(NULL),
+ send_thread_("MidiSendThread") {
}
-bool 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 false;
+ return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
coremidi_input_ = 0;
result = MIDIInputPortCreate(
midi_client_,
CFSTR("MIDI Input"),
- ReadMIDIDispatch,
+ ReadMidiDispatch,
this,
&coremidi_input_);
if (result != noErr)
- return false;
+ return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
result = MIDIOutputPortCreate(
midi_client_,
CFSTR("MIDI Output"),
&coremidi_output_);
if (result != noErr)
- return false;
+ return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
uint32 destination_count = MIDIGetNumberOfDestinations();
destinations_.resize(destination_count);
// Cache to avoid any possible overhead in calling MIDIGetDestination().
destinations_[i] = destination;
- MIDIPortInfo info = GetPortInfoFromEndpoint(destination);
+ MidiPortInfo info = GetPortInfoFromEndpoint(destination);
AddOutputPort(info);
}
// Keep track of all sources (known as inputs in Web MIDI API terminology).
source_map_[src] = i;
- MIDIPortInfo info = GetPortInfoFromEndpoint(src);
+ MidiPortInfo info = GetPortInfoFromEndpoint(src);
AddInputPort(info);
}
- // TODO(crogers): Fix the memory management here!
packet_list_ = reinterpret_cast<MIDIPacketList*>(midi_buffer_);
midi_packet_ = MIDIPacketListInit(packet_list_);
- return true;
+ CompleteInitialization(MIDI_OK);
}
-MIDIManagerMac::~MIDIManagerMac() {
+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_)
}
// static
-void MIDIManagerMac::ReadMIDIDispatch(const MIDIPacketList* packet_list,
+void MidiManagerMac::ReadMidiDispatch(const MIDIPacketList* packet_list,
void* read_proc_refcon,
void* src_conn_refcon) {
- MIDIManagerMac* manager = static_cast<MIDIManagerMac*>(read_proc_refcon);
+ MidiManagerMac* manager = static_cast<MidiManagerMac*>(read_proc_refcon);
#if __LP64__
MIDIEndpointRef source = reinterpret_cast<uintptr_t>(src_conn_refcon);
#else
#endif
// Dispatch to class method.
- manager->ReadMIDI(source, packet_list);
+ manager->ReadMidi(source, packet_list);
}
-void MIDIManagerMac::ReadMIDI(MIDIEndpointRef source,
+void MidiManagerMac::ReadMidi(MIDIEndpointRef source,
const MIDIPacketList* packet_list) {
// Lookup the port index based on the source.
SourceMap::iterator j = source_map_.find(source);
const MIDIPacket &packet = packet_list->packet[i];
double timestamp_seconds = MIDITimeStampToSeconds(packet.timeStamp);
- ReceiveMIDIData(
+ ReceiveMidiData(
port_index,
packet.data,
packet.length,
}
}
-void MIDIManagerMac::SendMIDIData(MIDIManagerClient* client,
+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);
// Re-initialize for next time.
midi_packet_ = MIDIPacketListInit(packet_list_);
- client->AccumulateMIDIBytesSent(data.size());
+ client->AccumulateMidiBytesSent(data.size());
}
// static
-MIDIPortInfo MIDIManagerMac::GetPortInfoFromEndpoint(
+MidiPortInfo MidiManagerMac::GetPortInfoFromEndpoint(
MIDIEndpointRef endpoint) {
SInt32 id_number = 0;
MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyUniqueID, &id_number);
<< result;
}
- return MIDIPortInfo(id, manufacturer, name, version);
+ return MidiPortInfo(id, manufacturer, name, version);
}
// static
-double MIDIManagerMac::MIDITimeStampToSeconds(MIDITimeStamp timestamp) {
+double MidiManagerMac::MIDITimeStampToSeconds(MIDITimeStamp timestamp) {
UInt64 nanoseconds = AudioConvertHostTimeToNanos(timestamp);
return static_cast<double>(nanoseconds) / 1.0e9;
}
// static
-MIDITimeStamp MIDIManagerMac::SecondsToMIDITimeStamp(double seconds) {
+MIDITimeStamp MidiManagerMac::SecondsToMIDITimeStamp(double seconds) {
UInt64 nanos = UInt64(seconds * 1.0e9);
return AudioConvertNanosToHostTime(nanos);
}