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 |