Search code examples
iosswiftmidicoremidi

Is there a way to tell if a MIDI-Device is connected via USB on iOS?


I'm using CoreMIDI to receive messages from a MIDI-Keyboard via Camera Connection Kit on iOS-Devices. My App is about pitch recognition. I want the following functionality to be automatic:

By default use the microphone (already implemented), if a MIDI-Keyboard is connected use that instead.

I could find out how to tell if it is a USB-Keyboard using the default driver. Just ask for the device called "USB-MIDI":

private func getUSBDeviceReference() -> MIDIDeviceRef? {
    for index in 0..<MIDIGetNumberOfDevices() {
        let device = MIDIGetDevice(index)
        var name : Unmanaged<CFString>?
        MIDIObjectGetStringProperty(device, kMIDIPropertyName, &name)
        if name!.takeRetainedValue() as String == "USB-MIDI" {
            return device
        }
    }
    return nil
}

But unfortunately there are USB-Keyboards that use a custom driver. How can I tell if I'm looking at one of these? Standard Bluetooth- and Network-Devices seem to be always online. Even if Wifi and Bluetooth are turned off on the device (strange?).


Solution

  • I ended up using the USBLocationID. It worked with any device I tested so far and none of the users complained.But I don't expect many users to use the MIDI-Features of my app.

    /// Filters all `MIDIDeviceRef`'s for USB-Devices
    private func getUSBDeviceReferences() -> [MIDIDeviceRef] {
            var devices = [MIDIDeviceRef]()
            for index in 0..<MIDIGetNumberOfDevices() {
                let device = MIDIGetDevice(index)
                var list: Unmanaged<CFPropertyList>?
                MIDIObjectGetProperties(device, &list, true)
                if let list = list {
                    let dict = list.takeRetainedValue() as! NSDictionary
                    if dict["USBLocationID"] != nil {
                        devices.append(device)
                    }
                }
            }
            return devices
        }