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