static void setUniqueIdForMidiPort (MIDIObjectRef device, const String& portName, bool isInput) { String portUniqueId; #if defined (JucePlugin_CFBundleIdentifier) portUniqueId = JUCE_STRINGIFY (JucePlugin_CFBundleIdentifier); #else File appBundle (File::getSpecialLocation (File::currentApplicationFile)); CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, appBundle.getFullPathName().toCFString(), kCFURLPOSIXPathStyle, true); if (bundleURL != nullptr) { CFBundleRef bundleRef = CFBundleCreate (kCFAllocatorDefault, bundleURL); CFRelease (bundleURL); if (bundleRef != nullptr) { if (auto bundleId = CFBundleGetIdentifier (bundleRef)) portUniqueId = String::fromCFString (bundleId); CFRelease (bundleRef); } } #endif if (portUniqueId.isNotEmpty()) { portUniqueId += (String ("." + portName + String (isInput ? ".input" : ".output"))); CHECK_ERROR (MIDIObjectSetStringProperty (device, kMIDIPropertyUniqueID, portUniqueId.toCFString())); } }
OSStatus USBMIDIDeviceManager::UseDeviceAndInterface(USBDevice * usbDevice, USBInterface * usbInterface) { // Match the device that was just located with what is in the current state MIDIDeviceRef midiDevice = NULL; IOUSBDeviceInterface **devIntf = usbDevice->GetPluginInterface(); const IOUSBDeviceDescriptor *devDesc = usbDevice->GetDeviceDescriptor(); bool deviceInSetup = false; UInt32 vendorProduct = ((UInt32)USBToHostWord(devDesc->idVendor) << 16) | USBToHostWord(devDesc->idProduct); CFStringRef serialNumber = usbDevice->GetString(devDesc->iSerialNumber); OSStatus err; UInt32 locationID; require_noerr(err = (*devIntf)->GetLocationID(devIntf, &locationID), errexit); { // See if it's already in the setup MIDIDeviceListRef curDevices = MIDIGetDriverDeviceList(mDriver->Self()); int nDevices = MIDIDeviceListGetNumberOfDevices(curDevices), firstPass, lastPass; if (serialNumber == NULL) { firstPass = 2; lastPass = 3; } else { firstPass = 1; lastPass = 1; } for (int pass = firstPass; pass <= lastPass && !deviceInSetup; ++pass) { // pass 1: match by serial number if present (skipped if not) // pass 2: match by locationID // pass 3: match by order found for (int iDevice = 0; iDevice < nDevices; ++iDevice) { SInt32 prevLocation, prevVendorProduct, isOffline; midiDevice = MIDIDeviceListGetDevice(curDevices, iDevice); err = MIDIObjectGetIntegerProperty(midiDevice, kUSBVendorProductProperty, &prevVendorProduct); if (!err && UInt32(prevVendorProduct) == vendorProduct) { switch (pass) { case 1: { CFStringRef prevSerial; err = MIDIObjectGetStringProperty(midiDevice, kSerialNumberProperty, &prevSerial); if (!err) { if (CFEqual(prevSerial, serialNumber)) deviceInSetup = true; CFRelease(prevSerial); } } break; case 2: err = MIDIObjectGetIntegerProperty(midiDevice, kUSBLocationProperty, &prevLocation); if (!err && UInt32(prevLocation) == locationID) deviceInSetup = true; break; case 3: err = MIDIObjectGetIntegerProperty(midiDevice, kMIDIPropertyOffline, &isOffline); if (!err && isOffline) deviceInSetup = true; break; } } if (deviceInSetup) break; } } MIDIDeviceListDispose(curDevices); } if (!deviceInSetup) { #if VERBOSE printf("creating new device\n"); #endif midiDevice = mDriver->CreateDevice(usbDevice, usbInterface); require_noerr(err = MIDISetupAddDevice(midiDevice), errexit); } else { #if VERBOSE printf("old device found\n"); #endif mDriver->PreExistingDeviceFound(midiDevice, usbDevice, usbInterface); } // set device properties unconditionally MIDIObjectSetIntegerProperty(midiDevice, kUSBVendorProductProperty, vendorProduct); MIDIObjectSetIntegerProperty(midiDevice, kUSBLocationProperty, locationID); if (serialNumber != NULL) MIDIObjectSetStringProperty(midiDevice, kSerialNumberProperty, serialNumber); // Create a USBMIDIDevice (or subclass), starting it for I/O { USBMIDIDevice *ioDev = mDriver->CreateUSBMIDIDevice(usbDevice, usbInterface, midiDevice); if (ioDev == NULL) goto errexit; if (!ioDev->Initialize()) delete ioDev; else { if (mUSBMIDIDeviceList.size() == 0) mUSBMIDIDeviceList.reserve(4); mUSBMIDIDeviceList.push_back(ioDev); MIDIObjectSetIntegerProperty(midiDevice, kMIDIPropertyOffline, false); } } errexit: if (serialNumber != NULL) CFRelease(serialNumber); return err; }