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 :) :)
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 thePGMIDINotifyProc
is been called? let me know