| 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 = it->second; |
| 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 = it->second; |
| 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 |