OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/midi/midi_manager_mac.h" | 5 #include "media/midi/midi_manager_mac.h" |
6 | 6 |
7 #include <algorithm> | |
7 #include <string> | 8 #include <string> |
8 | 9 |
9 #include "base/bind.h" | 10 #include "base/bind.h" |
10 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
11 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
12 #include "base/strings/sys_string_conversions.h" | 13 #include "base/strings/sys_string_conversions.h" |
13 | 14 |
14 #include <CoreAudio/HostTime.h> | 15 #include <CoreAudio/HostTime.h> |
15 | 16 |
16 using base::IntToString; | 17 using base::IntToString; |
17 using base::SysCFStringRefToUTF8; | 18 using base::SysCFStringRefToUTF8; |
18 using std::string; | 19 using std::string; |
19 | 20 |
20 // NB: System MIDI types are pointer types in 32-bit and integer types in | 21 // NB: System MIDI types are pointer types in 32-bit and integer types in |
21 // 64-bit. Therefore, the initialization is the simplest one that satisfies both | 22 // 64-bit. Therefore, the initialization is the simplest one that satisfies both |
22 // (if possible). | 23 // (if possible). |
23 | 24 |
24 namespace media { | 25 namespace media { |
25 | 26 |
26 namespace { | 27 namespace { |
27 | 28 |
28 MidiPortInfo GetPortInfoFromEndpoint( | 29 MidiPortInfo GetPortInfoFromEndpoint(MIDIEndpointRef endpoint) { |
29 MIDIEndpointRef endpoint) { | |
30 SInt32 id_number = 0; | 30 SInt32 id_number = 0; |
31 MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyUniqueID, &id_number); | 31 MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyUniqueID, &id_number); |
32 string id = IntToString(id_number); | 32 string id = IntToString(id_number); |
33 | 33 |
34 string manufacturer; | 34 string manufacturer; |
35 CFStringRef manufacturer_ref = NULL; | 35 CFStringRef manufacturer_ref = NULL; |
36 OSStatus result = MIDIObjectGetStringProperty( | 36 OSStatus result = MIDIObjectGetStringProperty( |
37 endpoint, kMIDIPropertyManufacturer, &manufacturer_ref); | 37 endpoint, kMIDIPropertyManufacturer, &manufacturer_ref); |
38 if (result == noErr) { | 38 if (result == noErr) { |
39 manufacturer = SysCFStringRefToUTF8(manufacturer_ref); | 39 manufacturer = SysCFStringRefToUTF8(manufacturer_ref); |
(...skipping 18 matching lines...) Expand all Loading... | |
58 endpoint, kMIDIPropertyDriverVersion, &version_number); | 58 endpoint, kMIDIPropertyDriverVersion, &version_number); |
59 if (result == noErr) { | 59 if (result == noErr) { |
60 version = IntToString(version_number); | 60 version = IntToString(version_number); |
61 } else { | 61 } else { |
62 // kMIDIPropertyDriverVersion is not supported in IAC driver providing | 62 // kMIDIPropertyDriverVersion is not supported in IAC driver providing |
63 // endpoints, and the result will be kMIDIUnknownProperty (-10835). | 63 // endpoints, and the result will be kMIDIUnknownProperty (-10835). |
64 DLOG(WARNING) << "Failed to get kMIDIPropertyDriverVersion with status " | 64 DLOG(WARNING) << "Failed to get kMIDIPropertyDriverVersion with status " |
65 << result; | 65 << result; |
66 } | 66 } |
67 | 67 |
68 return MidiPortInfo(id, manufacturer, name, version); | 68 const MidiPortState state = MIDI_PORT_OPENED; |
69 return MidiPortInfo(id, manufacturer, name, version, state); | |
69 } | 70 } |
70 | 71 |
71 double MIDITimeStampToSeconds(MIDITimeStamp timestamp) { | 72 double MIDITimeStampToSeconds(MIDITimeStamp timestamp) { |
72 UInt64 nanoseconds = AudioConvertHostTimeToNanos(timestamp); | 73 UInt64 nanoseconds = AudioConvertHostTimeToNanos(timestamp); |
73 return static_cast<double>(nanoseconds) / 1.0e9; | 74 return static_cast<double>(nanoseconds) / 1.0e9; |
74 } | 75 } |
75 | 76 |
76 MIDITimeStamp SecondsToMIDITimeStamp(double seconds) { | 77 MIDITimeStamp SecondsToMIDITimeStamp(double seconds) { |
77 UInt64 nanos = UInt64(seconds * 1.0e9); | 78 UInt64 nanos = UInt64(seconds * 1.0e9); |
78 return AudioConvertNanosToHostTime(nanos); | 79 return AudioConvertNanosToHostTime(nanos); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
133 client_thread_.message_loop()->PostTask(FROM_HERE, closure); | 134 client_thread_.message_loop()->PostTask(FROM_HERE, closure); |
134 } | 135 } |
135 | 136 |
136 void MidiManagerMac::InitializeCoreMIDI() { | 137 void MidiManagerMac::InitializeCoreMIDI() { |
137 DCHECK(client_thread_.message_loop_proxy()->BelongsToCurrentThread()); | 138 DCHECK(client_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
138 | 139 |
139 // CoreMIDI registration. | 140 // CoreMIDI registration. |
140 // TODO(toyoshim): Set MIDINotifyProc to receive CoreMIDI event notifications. | 141 // TODO(toyoshim): Set MIDINotifyProc to receive CoreMIDI event notifications. |
141 midi_client_ = 0; | 142 midi_client_ = 0; |
142 OSStatus result = | 143 OSStatus result = |
143 MIDIClientCreate(CFSTR("Chrome"), NULL, NULL, &midi_client_); | 144 MIDIClientCreate(CFSTR("Chrome"), ReceiveMidiNotifyDispatch, this, |
145 &midi_client_); | |
144 | 146 |
145 if (result != noErr) | 147 if (result != noErr) |
146 return CompleteInitialization(MIDI_INITIALIZATION_ERROR); | 148 return CompleteInitialization(MIDI_INITIALIZATION_ERROR); |
147 | 149 |
148 coremidi_input_ = 0; | 150 coremidi_input_ = 0; |
149 | 151 |
150 // Create input and output port. | 152 // Create input and output port. |
151 result = MIDIInputPortCreate( | 153 result = MIDIInputPortCreate( |
152 midi_client_, | 154 midi_client_, |
153 CFSTR("MIDI Input"), | 155 CFSTR("MIDI Input"), |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 AddInputPort(info); | 195 AddInputPort(info); |
194 } | 196 } |
195 | 197 |
196 packet_list_ = reinterpret_cast<MIDIPacketList*>(midi_buffer_); | 198 packet_list_ = reinterpret_cast<MIDIPacketList*>(midi_buffer_); |
197 midi_packet_ = MIDIPacketListInit(packet_list_); | 199 midi_packet_ = MIDIPacketListInit(packet_list_); |
198 | 200 |
199 CompleteInitialization(MIDI_OK); | 201 CompleteInitialization(MIDI_OK); |
200 } | 202 } |
201 | 203 |
202 // static | 204 // static |
205 void MidiManagerMac::ReceiveMidiNotifyDispatch(const MIDINotification* message, | |
206 void* refcon) { | |
207 MidiManagerMac* manager = static_cast<MidiManagerMac*>(refcon); | |
208 manager->ReceiveMidiNotify(message); | |
209 } | |
210 | |
211 void MidiManagerMac::ReceiveMidiNotify(const MIDINotification* message) { | |
212 DCHECK(client_thread_.message_loop_proxy()->BelongsToCurrentThread()); | |
213 | |
214 if (kMIDIMsgObjectAdded == message->messageID) { | |
215 const MIDIObjectAddRemoveNotification* notification = | |
216 reinterpret_cast<const MIDIObjectAddRemoveNotification*>(message); | |
217 MIDIEndpointRef endpoint = | |
218 static_cast<MIDIEndpointRef>(notification->child); | |
219 if (notification->childType == kMIDIObjectType_Source) { | |
220 SourceMap::iterator it = source_map_.find(endpoint); | |
221 if (it == source_map_.end()) { | |
222 uint32 index = source_map_.size(); | |
223 source_map_[endpoint] = index; | |
224 MidiPortInfo info = GetPortInfoFromEndpoint(endpoint); | |
225 AddInputPort(info); | |
226 } else { | |
227 uint32 index = source_map_[endpoint]; | |
yhirano
2015/02/19 02:40:45
s/source_map_[endpoint]/it->second/
Takashi Toyoshima
2015/02/19 02:58:32
Done.
| |
228 SetInputPortState(index, MIDI_PORT_OPENED); | |
229 } | |
230 } else if (notification->childType == kMIDIObjectType_Destination) { | |
231 auto i = std::find(destinations_.begin(), destinations_.end(), endpoint); | |
232 if (i != destinations_.end()) { | |
233 SetOutputPortState(i - destinations_.begin(), MIDI_PORT_OPENED); | |
234 } else { | |
235 destinations_.push_back(endpoint); | |
236 MidiPortInfo info = GetPortInfoFromEndpoint(endpoint); | |
237 AddOutputPort(info); | |
238 } | |
239 } | |
240 } else if (kMIDIMsgObjectRemoved == message->messageID) { | |
241 const MIDIObjectAddRemoveNotification* notification = | |
242 reinterpret_cast<const MIDIObjectAddRemoveNotification*>(message); | |
243 MIDIEndpointRef endpoint = | |
244 static_cast<MIDIEndpointRef>(notification->child); | |
245 if (notification->childType == kMIDIObjectType_Source) { | |
246 SourceMap::iterator it = source_map_.find(endpoint); | |
247 if (it != source_map_.end()) { | |
248 uint32 index = source_map_[endpoint]; | |
yhirano
2015/02/19 02:40:45
ditto
Takashi Toyoshima
2015/02/19 02:58:32
Done.
| |
249 SetInputPortState(index, MIDI_PORT_DISCONNECTED); | |
250 } | |
251 } else if (notification->childType == kMIDIObjectType_Destination) { | |
252 auto i = std::find(destinations_.begin(), destinations_.end(), endpoint); | |
253 if (i != destinations_.end()) | |
254 SetOutputPortState(i - destinations_.begin(), MIDI_PORT_DISCONNECTED); | |
255 } | |
256 } | |
257 } | |
258 | |
259 // static | |
203 void MidiManagerMac::ReadMidiDispatch(const MIDIPacketList* packet_list, | 260 void MidiManagerMac::ReadMidiDispatch(const MIDIPacketList* packet_list, |
204 void* read_proc_refcon, | 261 void* read_proc_refcon, |
205 void* src_conn_refcon) { | 262 void* src_conn_refcon) { |
206 // This method is called on a separate high-priority thread owned by CoreMIDI. | 263 // This method is called on a separate high-priority thread owned by CoreMIDI. |
207 | 264 |
208 MidiManagerMac* manager = static_cast<MidiManagerMac*>(read_proc_refcon); | 265 MidiManagerMac* manager = static_cast<MidiManagerMac*>(read_proc_refcon); |
209 #if __LP64__ | 266 #if __LP64__ |
210 MIDIEndpointRef source = reinterpret_cast<uintptr_t>(src_conn_refcon); | 267 MIDIEndpointRef source = reinterpret_cast<uintptr_t>(src_conn_refcon); |
211 #else | 268 #else |
212 MIDIEndpointRef source = static_cast<MIDIEndpointRef>(src_conn_refcon); | 269 MIDIEndpointRef source = static_cast<MIDIEndpointRef>(src_conn_refcon); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
268 | 325 |
269 MIDISend(coremidi_output_, destination, packet_list_); | 326 MIDISend(coremidi_output_, destination, packet_list_); |
270 | 327 |
271 // Re-initialize for next time. | 328 // Re-initialize for next time. |
272 midi_packet_ = MIDIPacketListInit(packet_list_); | 329 midi_packet_ = MIDIPacketListInit(packet_list_); |
273 | 330 |
274 client->AccumulateMidiBytesSent(data.size()); | 331 client->AccumulateMidiBytesSent(data.size()); |
275 } | 332 } |
276 | 333 |
277 } // namespace media | 334 } // namespace media |
OLD | NEW |