Connect an iPad via BT MIDI as Peripheral (CABTMidiLocalPeripheralViewController)

574 Views Asked by At

I am programming a MIDI tool on my iPad which connects to a synthesizer using Bluetooth.

First thing I did was to use the iPad as Central controller with the CABTMidiCentralViewController - if I connect to a Bluetooth device here I immediately get a notification that a new MIDI device has connected and everything's fine.

Now to support another Bluetooth dongle I need to config the iPad as peripheral, for that I use CABTMidiLocalPeripheralViewController. On the other side of BT (the central device which is NOT the iPad) I see the iPad advertising its service and I can connect to it, however I have no idea how to recognize this connection on the iPad side - I don't get any notification about new devices. Probably I'm missing something here?

I use CABTMidiLocalPeripheralViewController just like in the documentation example for CABTMidiCentralViewController, so that's the code (it's just displaying the vc anyway, isn't it?):

 - (void)configCABTMIDIPeripheral:(id)sender
{
    CABTMIDILocalPeripheralViewController *viewController =[CABTMIDILocalPeripheralViewController new];
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];

    viewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemDone                                                                                         target: self                                                                                           action: @selector(didConfigCABTMIDIPeripheral:)];

    navController.modalPresentationStyle = UIModalPresentationPopover;

    UIPopoverPresentationController *popC = navController.popoverPresentationController;
    popC.permittedArrowDirections = UIPopoverArrowDirectionAny;
    popC.sourceRect = [sender frame];

    UIButton *button = (UIButton *)sender;
    popC.sourceView = button.superview;

    [self.delegateBaseViewController presentViewController:navController animated:YES completion:nil];
}

As for the notifications I register a static callback function when I create a MIDI client - my guess is that as a peripheral device this works different, maybe someone here can point me in the right direction:

        OSStatus s = 0;
        s = MIDIClientCreate((CFStringRef)@"MIDI Client", PGMIDINotifyProc, arc_cast<void>(self), &_client);                // Create MIDI Client
        s = MIDIOutputPortCreate(_client, (CFStringRef)@"Output Port", &_outputPort);                                       // Create MIDI output port
        s = MIDIInputPortCreate(_client, (CFStringRef)@"Input Port", PGMIDIReadProc, arc_cast<void>(self), &_inputPort);    // Create MIDI input port

...with PGMIDINotifyProc looking like...

void PGMIDINotifyProc(const MIDINotification *message, void *refCon)
{
    NSLog(@"PGMIDINotifyProc");
    PGMidi *self = arc_cast<PGMidi>(refCon);
    [self midiNotify:message];
}

(Credits to PGMidi at https://github.com/petegoodliffe/PGMidi)

So... how can I see if my peripheral iPad did connect to a MIDI device?


UPDATE

After a long break I decided to give it another try, this time I made some tests by implementing a CBPeripheralManager and a CBCentralManager on two devices (one peripheral and one central) to have a closer look on what's going on behind the scenes:

Without going too much into detail, here are some observations:

  • if the peripheral device doesn't power on the CBPeripheralManager, no Bluetooth services are offered. Makes sense.

  • if the peripheral device offers some random service, the central device will discover this service they connect and can exchange data. Great.

  • if the peripheral device still offers some random service while the central specifically looks for the MIDI service / characteristics, it will find the MIDI service and connect to it. I don't get any notifications about this on the peripheral side, since I'm just the delegate of the peripheral offering some random service.

  • if both the peripheral device and the central offer / scan for the MIDI service / characteristics, they don't find anything.

It's like the MIDI service appears on it's own if I offer some other service but is not there if I offer no service. Moreover the iPad seems to block or catch the MIDI service / characteristic if I try to offer it myself.

Any ideas here? Come on :) :)

1

There are 1 best solutions below

0
On

Assuming you use CABTMIDILocalPeripheralViewController to connect, try replace arc_cast<void>(self) with (__bridge void*)self as the current PGMidi library does, but if you use this library you should not write this client initialization yourself, it is created inside the [[PGMidi alloc] init] call. anyway can you see the PGMIDINotifyProc is been called? let me know