Chromium Code Reviews| Index: media/midi/midi_manager_mac.cc |
| diff --git a/media/midi/midi_manager_mac.cc b/media/midi/midi_manager_mac.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c2285dd52e45ca9d601c5701f1cbeaaa2db72d88 |
| --- /dev/null |
| +++ b/media/midi/midi_manager_mac.cc |
| @@ -0,0 +1,160 @@ |
| +// Copyright (c) 2013 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_mac.h" |
| + |
| +#include "base/time.h" |
| +#include <CoreAudio/HostTime.h> |
| + |
| +namespace media { |
| + |
| +MIDIManager* MIDIManager::Create() { |
| + return new MIDIManagerMac(); |
| +} |
| + |
| +MIDIManagerMac::MIDIManagerMac() { |
|
scherkus (not reviewing)
2013/06/03 22:44:59
FYI this will be executed on the main UI thread wh
|
| + OSStatus result = noErr; |
| + |
| + // Create client and ports. |
| + midi_client_ = NULL; |
| + result = MIDIClientCreate(CFSTR("Google Chrome"), NULL, NULL, &midi_client_); |
| + |
| + input_port_ = NULL; |
| + |
| + result = MIDIInputPortCreate(midi_client_, |
| + CFSTR("MIDI Input"), |
| + ReadMidiDispatch, |
| + this, |
| + &input_port_); |
| + |
| + result = MIDIOutputPortCreate(midi_client_, |
| + CFSTR("MIDI Output"), |
| + &output_port_); |
| + |
| + int m = MIDIGetNumberOfDestinations(); |
| + |
| + for (int i = 0; i < m ; i++) { |
| + MIDIEndpointRef destination = MIDIGetDestination(i); |
| + CFStringRef deviceName = GetDeviceNameFromEndpoint(destination); |
| + |
| + printf("%d: ", i); |
| + CFShow(deviceName); |
| + } |
| + |
| + // Use first destination as default. |
| + destination_ = MIDIGetDestination(0); |
| + |
| + // Open connections from all sources |
| + int n = MIDIGetNumberOfSources(); |
| + |
| + for (int i = 0; i < n; ++i) { |
| + // Receive from all sources |
| + MIDIEndpointRef src = MIDIGetSource(i); |
| + MIDIPortConnectSource(input_port_, src, src); |
| + |
| + // Keep track of all sources (known as inputs in Web MIDI API terminology). |
| + source_map_[src] = i; |
| + |
| + // CFStringRef deviceName = GetDeviceNameFromEndpoint(src); |
| + |
| + CFStringRef midiSourceNameRef; |
| + MIDIObjectGetStringProperty(src, kMIDIPropertyName, &midiSourceNameRef); |
| + |
| + CFShow(midiSourceNameRef); |
| + } |
| + |
| + // init MIDIPacketList |
| + packet_list_ = reinterpret_cast<MIDIPacketList*>(mMIDIBuffer); |
| + midi_packet_ = MIDIPacketListInit(packet_list_); |
| +} |
| + |
| +MIDIManagerMac::~MIDIManagerMac() { |
| + MIDIPortDispose(input_port_); |
| + MIDIPortDispose(output_port_); |
| +} |
| + |
| +void MIDIManagerMac::ReadMidiDispatch(const MIDIPacketList* packet_list, |
| + void* read_proc_refcon, |
| + void* src_conn_refcon) { |
| + MIDIManagerMac* manager = static_cast<MIDIManagerMac*>(read_proc_refcon); |
| + MIDIEndpointRef source = static_cast<MIDIEndpointRef>(src_conn_refcon); |
| + |
| + // Dispatch to class method. |
| + manager->ReadMidi(source, packet_list); |
| +} |
| + |
| +void MIDIManagerMac::ReadMidi(MIDIEndpointRef source, |
| + const MIDIPacketList* packet_list) { |
| + // Lookup the port index based on the source. |
| + SourceMap::iterator j = source_map_.find(source); |
| + if (j == source_map_.end()) |
| + return; |
| + int port_index = source_map_[source]; |
| + // printf("port_index = %d\n", port_index); |
| + |
| + // Go through each packet and process separately. |
| + for(size_t i = 0; i < packet_list->numPackets; i++) { |
| + // Each packet contains MIDI data for one or more messages (like note-on). |
| + const MIDIPacket &packet = packet_list->packet[i]; |
| + double timestamp_seconds = MIDITimeStampToSeconds(packet.timeStamp); |
| + |
| + // TODO(crogers): handle port index properly at Blink layer. |
| + // Right now it only allows a value of 0. |
| + port_index = 0; |
| + |
| + ReceiveMIDIData( |
| + port_index, |
| + packet.data, |
| + packet.length, |
| + timestamp_seconds); |
| + } |
| +} |
| + |
| +void MIDIManagerMac::SendMIDI(UInt8 *midi_data, |
| + UInt32 length, |
| + MIDITimeStamp timestamp) { |
| + midi_packet_ = MIDIPacketListAdd( |
| + packet_list_, |
| + kMaxPacketListSize, |
| + midi_packet_, |
| + timestamp, |
| + length, |
| + midi_data); |
| + |
| + MIDISend(output_port_, destination_, packet_list_); |
| + |
| + // Re-initialize for next time. |
| + midi_packet_ = MIDIPacketListInit(packet_list_); |
| +} |
| + |
| +double MIDIManagerMac::MIDITimeStampToSeconds(MIDITimeStamp timestamp) |
| +{ |
| + UInt64 nanos = AudioConvertHostTimeToNanos(timestamp ); |
| + |
| + double seconds = double(nanos) / 1.0e9; |
| + return seconds; |
| +} |
| + |
| +MIDITimeStamp MIDIManagerMac::SecondsToMIDITimeStamp(double seconds) { |
| + UInt64 nanos = UInt64(seconds * 1.0e9); |
| + MIDITimeStamp timeStamp = AudioConvertNanosToHostTime(nanos); |
| + return timeStamp; |
| +} |
| + |
| +CFStringRef MIDIManagerMac::GetDeviceNameFromEndpoint( |
| + MIDIEndpointRef endpoint) { |
| + MIDIEntityRef entity; |
| + MIDIEndpointGetEntity(endpoint, &entity); |
| + |
| + MIDIDeviceRef device; |
| + MIDIEntityGetDevice(entity, &device); |
| + |
| + CFStringRef device_name_ref; |
| + MIDIObjectGetStringProperty(device, kMIDIPropertyName, &device_name_ref); |
| + |
| + return device_name_ref; |
| +} |
| + |
| +} // namespace media |
| + |