2015-10-05 4 views
9

Ich habe gerade CABTMIDILocalPeripheralViewController für iOS, die behandelt Benutzereinstellungen zum Aktivieren von Bluetooth MIDI Discoverability. Dies ist gut und gut, aber um Bluetooth in den Rest meiner App Netzwerk-MIDI-Konnektivität zu integrieren, wäre es gut, in der Lage zu sein, mit der direkt von meiner App Code zu ermöglichen, anstatt auf diese undurchsichtige VC verlassen. Weiß jemand, ob das möglich ist?Werben Bluetooth MIDI auf iOS manuell, ohne CABTMIDILocalPeripheralViewController

+0

Hast du jemals herausgefunden, wie man diese Dinge benutzt? Ich verwende CABTMIDICentralViewController und ich möchte wirklich überprüfen, welches MIDI-Gerät der Benutzer in meinem Code angeschlossen hat (damit ich mich automatisch mit dem richtigen MIDI-Gerät verbinden kann). Gibt es eine Möglichkeit, das zu tun, oder sollten wir einige Fehler bei Apple einreichen? – phreakhead

+0

Ich benutze die Peripheral-Version, aber basierend darauf würde ich vermuten, dass es sobald es verbunden ist ein MIDIEndpointRef wird, so dass Sie es mit der CoreMIDI API abfragen können. Es sollte den Namen "Hari Karams iPhone Bluetooth Connection" haben. Sie können die Interna des VC überhaupt nicht optimieren. Und es gibt keine andere 'CABTMIDI ...' API soweit ich sehen kann –

+0

Ok. Ich habe eine schreckliche Hack-Lösung zusammengestellt, die ich im Folgenden veröffentlichen werde. – phreakhead

Antwort

1

Es gibt keine öffentliche API, um diese Funktionalität zu verwalten. Bei Untersuchungen mit Instrumenten scheint es, dass der Schalter eine Instanziierung von CBPeripheralManager verursacht. Ich nehme an, dass es das Gerät als ein Bluetooth-Peripheriegerät einrichtet und die Daten zu und von einem MIDIEndpointRef, der ebenfalls erstellt wurde, manuell kanalisiert.

Mit anderen Worten, es gibt keine Einzellinienlösung. Wenn ich diesen Weg gehen weiter werde ich nach dem Code, es sei denn jemand anderes will einen gehen müssen ...

UPDATE

Die Magie 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]; 
} 

Es sind diese IDs, die ein MIDI-Peripheriegerät definieren. Weitere Informationen:

von Apple verwendet, um ein Dokument zu haben, bei

... was nicht mehr ist. Ich würde gerne eine alte Kopie finden, wie sich herausstellt, der Empfänger-Code (emulieren CABTMIDICentralViewController) ist noch schwieriger zu knacken ...

0

Ich glaube, Sie könnten für diese suchen: CABTMIDICentralViewController weitere Informationen auf dieser Seite: https://developer.apple.com/library/ios/qa/qa1831/_index.html basicaly dies hilft Ihnen, zu scannen und zu Geräten über Ihre App verbinden. Ich bin mir nicht sicher, ob Sie nur entdeckt werden wollen oder auch derjenige, der scannt. Ich hoffe, dies hilft

+0

Das ist, wo ich gelernt habe über 'CABTMIDILocalPeripheralViewController', die definitiv in meinem Fall zu verwenden ist. Wie auch immer, diese Seite beschreibt nicht, wie die Aufgabe zu erledigen ist, ohne diese VCs zu verwenden, was ich wissen möchte. –

+0

Es ist eigentlich ziemlich begrenzt, vielleicht aufgrund von Sicherheitsmaßnahmen. –

+0

Es gibt Apps (z. B. Apollo Bluetooth), die dies erreichen. Ich vermute, sie tun es manuell ohne die 'CABT ...' VCs –

1

Also habe ich zusammen eine ziemlich hacky Lösung zu finden, welche MIDI-Gerät der Benutzer einmal angeklickt innerhalb des CABTMIDICentralViewControllers. Ich bin nicht sicher, ob das eine gute Idee ist - wenn Apple die Interna des Controllers ändert, wird es nicht mehr funktionieren. Ich bin mir auch nicht sicher, ob es "legal" bezüglich App Store Richtlinien ist. Wer weiß mehr Infos dazu?

DPBleMidiDeviceManager.h:

#import <CoreAudioKit/CoreAudioKit.h> 

@protocol MidiDeviceConnectedDelegate <NSObject> 

-(void) onMidiDeviceConnected: (NSString*) deviceName; 

@end 


@interface DPBleMidiDeviceManager : CABTMIDICentralViewController 

@property (weak, nonatomic) id<MidiDeviceConnectedDelegate> midiDeviceDelegate; 

@end 

DPBleMidiDeviceManager.m:

#import "DPBleMidiDeviceManager.h" 

@implementation DPBleMidiDeviceManager 


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSLog(@"midi device selected %@", indexPath); 

    [super tableView:tableView didSelectRowAtIndexPath:indexPath]; 

    // TODO: this is very bad. apple may change their internal API and this will break. 
    UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath]; 
    if ([cell respondsToSelector:@selector(deviceNameLabel)]) { 
     UILabel* deviceLabel = [cell performSelector:@selector(deviceNameLabel)]; 

     NSLog(@"midi device named %@", deviceLabel.text); 

     // must wait a couple seconds for it to actually connect. 
     [self performSelector:@selector(sendMidiDeviceConnected:) withObject:deviceLabel.text afterDelay: 3]; 
    } 
} 


- (void) sendMidiDeviceConnected: (NSString*) deviceName 
{ 
    [self.midiDeviceDelegate onMidiDeviceConnected:deviceName]; 
} 
@end 

Dann in Ihren Eltern-View-Controller, können Sie das Ergebnis von den Delegierten erhalten und für ein neues MIDI-Gerät suchen, diesen Namen übereinstimmt, gefunden

... 
    DPBleMidiDeviceManager *controller = [DPBleMidiDeviceManager new]; 
    controller.midiDeviceDelegate = self; 
    // now present the VC as usual 
... 


-(void) onMidiDeviceConnected: (NSString*) deviceName 
{ 
    [self connectMidiDevice: deviceName]; 
} 


/** 
Connects to a MIDI source with the given name, 
and interprets all notes from that source as notes; 

*/ 
- (void) connectMidiDevice: (NSString*) deviceName 
{ 
    NSLog(@"Connecting to MIDI device: %@", deviceName); 

    PGMidi* midi = [[PGMidi alloc] init]; 

    if (midi != NULL) { 
     NSArray* sources = midi.sources; 
     for (PGMidiSource* src in sources) { 
      NSLog(@"Found midi source: %@", src.name); 

      if ([src.name containsString: deviceName]) { 

       NSLog(@"Connecting to midi source: %@", src.name); 
       [src addDelegate:self]; 
      } 
     } 
    } 

} 

Die einzige andere Alternative kann ich Denken Sie daran, nach MIDI-Geräten zu suchen, bevor Sie den Controller anzeigen, speichern Sie die Liste der Geräte und öffnen Sie dann den Controller. Wenn es geschlossen wird, scannen Sie die MIDI-Geräte erneut und verschmelzen Sie die neue Liste mit der alten. Alle neuen MIDI-Geräte, die angezeigt werden, sind diejenigen, die der Benutzer ausgewählt hat. Nicht sicher, warum Apple uns das nicht leichter gemacht hat ...

Verwandte Themen