1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file. 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "media/midi/midi_manager_mac.h" 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string> 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/bind.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/message_loop/message_loop.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/string_number_conversions.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/sys_string_conversions.h" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <CoreAudio/HostTime.h> 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::IntToString; 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::SysCFStringRefToUTF8; 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing std::string; 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// NB: System MIDI types are pointer types in 32-bit and integer types in 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 64-bit. Therefore, the initialization is the simplest one that satisfies both 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// (if possible). 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace media { 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MidiManager* MidiManager::Create() { 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return new MidiManagerMac(); 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MidiManagerMac::MidiManagerMac() 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : midi_client_(0), 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch coremidi_input_(0), 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch coremidi_output_(0), 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch packet_list_(NULL), 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) midi_packet_(NULL), 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) send_thread_("MidiSendThread") { 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MidiManagerMac::StartInitialization() { 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // CoreMIDI registration. 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch midi_client_ = 0; 42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) OSStatus result = 43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) MIDIClientCreate(CFSTR("Chrome"), NULL, NULL, &midi_client_); 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (result != noErr) 46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return CompleteInitialization(MIDI_INITIALIZATION_ERROR); 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch coremidi_input_ = 0; 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Create input and output port. 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result = MIDIInputPortCreate( 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch midi_client_, 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CFSTR("MIDI Input"), 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReadMidiDispatch, 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this, 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &coremidi_input_); 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (result != noErr) 58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return CompleteInitialization(MIDI_INITIALIZATION_ERROR); 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result = MIDIOutputPortCreate( 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch midi_client_, 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CFSTR("MIDI Output"), 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &coremidi_output_); 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (result != noErr) 65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return CompleteInitialization(MIDI_INITIALIZATION_ERROR); 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 67424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint32 destination_count = MIDIGetNumberOfDestinations(); 683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) destinations_.resize(destination_count); 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 70424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) for (uint32 i = 0; i < destination_count ; i++) { 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MIDIEndpointRef destination = MIDIGetDestination(i); 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Keep track of all destinations (known as outputs by the Web MIDI API). 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Cache to avoid any possible overhead in calling MIDIGetDestination(). 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch destinations_[i] = destination; 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MidiPortInfo info = GetPortInfoFromEndpoint(destination); 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddOutputPort(info); 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Open connections from all sources. 82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint32 source_count = MIDIGetNumberOfSources(); 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) for (uint32 i = 0; i < source_count; ++i) { 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Receive from all sources. 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MIDIEndpointRef src = MIDIGetSource(i); 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MIDIPortConnectSource(coremidi_input_, src, reinterpret_cast<void*>(src)); 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Keep track of all sources (known as inputs in Web MIDI API terminology). 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch source_map_[src] = i; 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MidiPortInfo info = GetPortInfoFromEndpoint(src); 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddInputPort(info); 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch packet_list_ = reinterpret_cast<MIDIPacketList*>(midi_buffer_); 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch midi_packet_ = MIDIPacketListInit(packet_list_); 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CompleteInitialization(MIDI_OK); 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MidiManagerMac::DispatchSendMidiData(MidiManagerClient* client, 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint32 port_index, 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<uint8>& data, 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) double timestamp) { 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!send_thread_.IsRunning()) 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) send_thread_.Start(); 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // OK to use base::Unretained(this) since we join to thread in dtor(). 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) send_thread_.message_loop()->PostTask( 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FROM_HERE, 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&MidiManagerMac::SendMidiData, base::Unretained(this), 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client, port_index, data, timestamp)); 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MidiManagerMac::~MidiManagerMac() { 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Wait for the termination of |send_thread_| before disposing MIDI ports. 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) send_thread_.Stop(); 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (coremidi_input_) 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MIDIPortDispose(coremidi_input_); 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (coremidi_output_) 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MIDIPortDispose(coremidi_output_); 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MidiManagerMac::ReadMidiDispatch(const MIDIPacketList* packet_list, 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void* read_proc_refcon, 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void* src_conn_refcon) { 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MidiManagerMac* manager = static_cast<MidiManagerMac*>(read_proc_refcon); 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if __LP64__ 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MIDIEndpointRef source = reinterpret_cast<uintptr_t>(src_conn_refcon); 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#else 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MIDIEndpointRef source = static_cast<MIDIEndpointRef>(src_conn_refcon); 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Dispatch to class method. 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) manager->ReadMidi(source, packet_list); 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MidiManagerMac::ReadMidi(MIDIEndpointRef source, 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const MIDIPacketList* packet_list) { 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Lookup the port index based on the source. 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SourceMap::iterator j = source_map_.find(source); 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (j == source_map_.end()) 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 147424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint32 port_index = source_map_[source]; 148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Go through each packet and process separately. 1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (size_t i = 0; i < packet_list->numPackets; i++) { 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Each packet contains MIDI data for one or more messages (like note-on). 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const MIDIPacket &packet = packet_list->packet[i]; 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double timestamp_seconds = MIDITimeStampToSeconds(packet.timeStamp); 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReceiveMidiData( 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch port_index, 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch packet.data, 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch packet.length, 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch timestamp_seconds); 160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MidiManagerMac::SendMidiData(MidiManagerClient* client, 164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint32 port_index, 165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const std::vector<uint8>& data, 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double timestamp) { 167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(send_thread_.message_loop_proxy()->BelongsToCurrentThread()); 168424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 169a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // System Exclusive has already been filtered. 170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MIDITimeStamp coremidi_timestamp = SecondsToMIDITimeStamp(timestamp); 171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch midi_packet_ = MIDIPacketListAdd( 173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch packet_list_, 174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kMaxPacketListSize, 175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch midi_packet_, 176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch coremidi_timestamp, 177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) data.size(), 178424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) &data[0]); 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Lookup the destination based on the port index. 181424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (static_cast<size_t>(port_index) >= destinations_.size()) 182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MIDIEndpointRef destination = destinations_[port_index]; 185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MIDISend(coremidi_output_, destination, packet_list_); 187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Re-initialize for next time. 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch midi_packet_ = MIDIPacketListInit(packet_list_); 190a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) client->AccumulateMidiBytesSent(data.size()); 192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MidiPortInfo MidiManagerMac::GetPortInfoFromEndpoint( 196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MIDIEndpointRef endpoint) { 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SInt32 id_number = 0; 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyUniqueID, &id_number); 199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch string id = IntToString(id_number); 200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) string manufacturer; 202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CFStringRef manufacturer_ref = NULL; 2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) OSStatus result = MIDIObjectGetStringProperty( 204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch endpoint, kMIDIPropertyManufacturer, &manufacturer_ref); 2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (result == noErr) { 2061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) manufacturer = SysCFStringRefToUTF8(manufacturer_ref); 2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } else { 2081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // kMIDIPropertyManufacturer is not supported in IAC driver providing 2091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // endpoints, and the result will be kMIDIUnknownProperty (-10835). 2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DLOG(WARNING) << "Failed to get kMIDIPropertyManufacturer with status " 2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) << result; 2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) string name; 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CFStringRef name_ref = NULL; 2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result = MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &name_ref); 2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (result == noErr) 2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) name = SysCFStringRefToUTF8(name_ref); 2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) else 2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DLOG(WARNING) << "Failed to get kMIDIPropertyName with status " << result; 221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) string version; 223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SInt32 version_number = 0; 2241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result = MIDIObjectGetIntegerProperty( 225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch endpoint, kMIDIPropertyDriverVersion, &version_number); 2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (result == noErr) { 2271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) version = IntToString(version_number); 2281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } else { 2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // kMIDIPropertyDriverVersion is not supported in IAC driver providing 2301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // endpoints, and the result will be kMIDIUnknownProperty (-10835). 2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DLOG(WARNING) << "Failed to get kMIDIPropertyDriverVersion with status " 2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) << result; 2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return MidiPortInfo(id, manufacturer, name, version); 236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)double MidiManagerMac::MIDITimeStampToSeconds(MIDITimeStamp timestamp) { 240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UInt64 nanoseconds = AudioConvertHostTimeToNanos(timestamp); 241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return static_cast<double>(nanoseconds) / 1.0e9; 242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MIDITimeStamp MidiManagerMac::SecondsToMIDITimeStamp(double seconds) { 246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UInt64 nanos = UInt64(seconds * 1.0e9); 247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return AudioConvertNanosToHostTime(nanos); 248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace media 251