Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Advertise Bluetooth MIDI on iOS manually, without CABTMIDILocalPeripheralViewController

I've just discovered CABTMIDILocalPeripheralViewController for iOS which handles user settings for enabling Bluetooth MIDI discoverability. This is fine and good but in order to integrate bluetooth into the rest of my app's Network MIDI connectivity it would be good to be able to handle the enabling directly from my app's code rather than rely on this opaque VC. Does anyone know whether that is possible?

like image 715
Hari Honor Avatar asked Oct 05 '15 20:10

Hari Honor


1 Answers

There's no public API to manage this functionality. Upon investigation with Instruments, it appears that the switch causes an instantiation of CBPeripheralManager. I presume it sets up the device as a Bluetooth peripheral and manually channels the data to and from a MIDIEndpointRef which is has also created.

In other words, there's no one-liner solution. If I go down this route further I'll post the code unless someone else wants to have a go...

UPDATE

The magic code...

- (instancetype)init
{
    self = [super init];
    if (self) {
        _peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
    }
    return self;
}

//---------------------------------------------------------------------

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
{
    if (peripheral.state != CBPeripheralManagerStatePoweredOn) {
        return;
    }

    info(@"_peripheralManager powered on.");

//    CBMutableCharacteristic *tx = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:RBL_TX_UUID] properties:CBCharacteristicPropertyWriteWithoutResponse value:nil permissions:CBAttributePermissionsWriteable];
//    
    rx = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:@"7772E5DB-3868-4112-A1A9-F2669D106BF3"] properties:CBCharacteristicPropertyRead|CBCharacteristicPropertyWriteWithoutResponse|CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable|CBAttributePermissionsWriteable];

    CBMutableService *s = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:@"03B80E5A-EDE8-4B33-A751-6CE34EC4C700"] primary:YES];
    s.characteristics = @[rx];

    [_peripheralManager addService:s];

    NSDictionary *advertisingData = @{CBAdvertisementDataLocalNameKey : BLE_NAME, CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:@"03B80E5A-EDE8-4B33-A751-6CE34EC4C700"]]};
    [_peripheralManager startAdvertising:advertisingData];
}

It's those IDs that define a MIDI peripheral. More info:

  • http://community.silabs.com/t5/Bluetooth-Wi-Fi-Knowledge-Base/Midi-over-BLE/ta-p/170804

Apple used to have a doc at

  • https://developer.apple.com/bluetooth/Apple-Bluetooth-Low-Energy-MIDI-Specification.pdf

...which is no longer. I'd love to find an old copy as it turns out the receiver code (emulating CABTMIDICentralViewController) is even harder to crack...

like image 82
Hari Honor Avatar answered Sep 24 '22 02:09

Hari Honor