Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "media/midi/midi_manager_mac.h" | |
| 6 | |
| 7 #include "base/time.h" | |
| 8 #include <CoreAudio/HostTime.h> | |
| 9 | |
| 10 namespace media { | |
| 11 | |
| 12 MIDIManager* MIDIManager::Create() { | |
| 13 return new MIDIManagerMac(); | |
| 14 } | |
| 15 | |
| 16 MIDIManagerMac::MIDIManagerMac() { | |
|
scherkus (not reviewing)
2013/06/03 22:44:59
FYI this will be executed on the main UI thread wh
| |
| 17 OSStatus result = noErr; | |
| 18 | |
| 19 // Create client and ports. | |
| 20 midi_client_ = NULL; | |
| 21 result = MIDIClientCreate(CFSTR("Google Chrome"), NULL, NULL, &midi_client_); | |
| 22 | |
| 23 input_port_ = NULL; | |
| 24 | |
| 25 result = MIDIInputPortCreate(midi_client_, | |
| 26 CFSTR("MIDI Input"), | |
| 27 ReadMidiDispatch, | |
| 28 this, | |
| 29 &input_port_); | |
| 30 | |
| 31 result = MIDIOutputPortCreate(midi_client_, | |
| 32 CFSTR("MIDI Output"), | |
| 33 &output_port_); | |
| 34 | |
| 35 int m = MIDIGetNumberOfDestinations(); | |
| 36 | |
| 37 for (int i = 0; i < m ; i++) { | |
| 38 MIDIEndpointRef destination = MIDIGetDestination(i); | |
| 39 CFStringRef deviceName = GetDeviceNameFromEndpoint(destination); | |
| 40 | |
| 41 printf("%d: ", i); | |
| 42 CFShow(deviceName); | |
| 43 } | |
| 44 | |
| 45 // Use first destination as default. | |
| 46 destination_ = MIDIGetDestination(0); | |
| 47 | |
| 48 // Open connections from all sources | |
| 49 int n = MIDIGetNumberOfSources(); | |
| 50 | |
| 51 for (int i = 0; i < n; ++i) { | |
| 52 // Receive from all sources | |
| 53 MIDIEndpointRef src = MIDIGetSource(i); | |
| 54 MIDIPortConnectSource(input_port_, src, src); | |
| 55 | |
| 56 // Keep track of all sources (known as inputs in Web MIDI API terminology). | |
| 57 source_map_[src] = i; | |
| 58 | |
| 59 // CFStringRef deviceName = GetDeviceNameFromEndpoint(src); | |
| 60 | |
| 61 CFStringRef midiSourceNameRef; | |
| 62 MIDIObjectGetStringProperty(src, kMIDIPropertyName, &midiSourceNameRef); | |
| 63 | |
| 64 CFShow(midiSourceNameRef); | |
| 65 } | |
| 66 | |
| 67 // init MIDIPacketList | |
| 68 packet_list_ = reinterpret_cast<MIDIPacketList*>(mMIDIBuffer); | |
| 69 midi_packet_ = MIDIPacketListInit(packet_list_); | |
| 70 } | |
| 71 | |
| 72 MIDIManagerMac::~MIDIManagerMac() { | |
| 73 MIDIPortDispose(input_port_); | |
| 74 MIDIPortDispose(output_port_); | |
| 75 } | |
| 76 | |
| 77 void MIDIManagerMac::ReadMidiDispatch(const MIDIPacketList* packet_list, | |
| 78 void* read_proc_refcon, | |
| 79 void* src_conn_refcon) { | |
| 80 MIDIManagerMac* manager = static_cast<MIDIManagerMac*>(read_proc_refcon); | |
| 81 MIDIEndpointRef source = static_cast<MIDIEndpointRef>(src_conn_refcon); | |
| 82 | |
| 83 // Dispatch to class method. | |
| 84 manager->ReadMidi(source, packet_list); | |
| 85 } | |
| 86 | |
| 87 void MIDIManagerMac::ReadMidi(MIDIEndpointRef source, | |
| 88 const MIDIPacketList* packet_list) { | |
| 89 // Lookup the port index based on the source. | |
| 90 SourceMap::iterator j = source_map_.find(source); | |
| 91 if (j == source_map_.end()) | |
| 92 return; | |
| 93 int port_index = source_map_[source]; | |
| 94 // printf("port_index = %d\n", port_index); | |
| 95 | |
| 96 // Go through each packet and process separately. | |
| 97 for(size_t i = 0; i < packet_list->numPackets; i++) { | |
| 98 // Each packet contains MIDI data for one or more messages (like note-on). | |
| 99 const MIDIPacket &packet = packet_list->packet[i]; | |
| 100 double timestamp_seconds = MIDITimeStampToSeconds(packet.timeStamp); | |
| 101 | |
| 102 // TODO(crogers): handle port index properly at Blink layer. | |
| 103 // Right now it only allows a value of 0. | |
| 104 port_index = 0; | |
| 105 | |
| 106 ReceiveMIDIData( | |
| 107 port_index, | |
| 108 packet.data, | |
| 109 packet.length, | |
| 110 timestamp_seconds); | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 void MIDIManagerMac::SendMIDI(UInt8 *midi_data, | |
| 115 UInt32 length, | |
| 116 MIDITimeStamp timestamp) { | |
| 117 midi_packet_ = MIDIPacketListAdd( | |
| 118 packet_list_, | |
| 119 kMaxPacketListSize, | |
| 120 midi_packet_, | |
| 121 timestamp, | |
| 122 length, | |
| 123 midi_data); | |
| 124 | |
| 125 MIDISend(output_port_, destination_, packet_list_); | |
| 126 | |
| 127 // Re-initialize for next time. | |
| 128 midi_packet_ = MIDIPacketListInit(packet_list_); | |
| 129 } | |
| 130 | |
| 131 double MIDIManagerMac::MIDITimeStampToSeconds(MIDITimeStamp timestamp) | |
| 132 { | |
| 133 UInt64 nanos = AudioConvertHostTimeToNanos(timestamp ); | |
| 134 | |
| 135 double seconds = double(nanos) / 1.0e9; | |
| 136 return seconds; | |
| 137 } | |
| 138 | |
| 139 MIDITimeStamp MIDIManagerMac::SecondsToMIDITimeStamp(double seconds) { | |
| 140 UInt64 nanos = UInt64(seconds * 1.0e9); | |
| 141 MIDITimeStamp timeStamp = AudioConvertNanosToHostTime(nanos); | |
| 142 return timeStamp; | |
| 143 } | |
| 144 | |
| 145 CFStringRef MIDIManagerMac::GetDeviceNameFromEndpoint( | |
| 146 MIDIEndpointRef endpoint) { | |
| 147 MIDIEntityRef entity; | |
| 148 MIDIEndpointGetEntity(endpoint, &entity); | |
| 149 | |
| 150 MIDIDeviceRef device; | |
| 151 MIDIEntityGetDevice(entity, &device); | |
| 152 | |
| 153 CFStringRef device_name_ref; | |
| 154 MIDIObjectGetStringProperty(device, kMIDIPropertyName, &device_name_ref); | |
| 155 | |
| 156 return device_name_ref; | |
| 157 } | |
| 158 | |
| 159 } // namespace media | |
| 160 | |
| OLD | NEW |