2015-10-05 13 views
9

Ho appena scoperto CABTMIDILocalPeripheralViewController per iOS che gestisce le impostazioni utente per abilitare la rilevabilità MIDI Bluetooth. Questo è fine e buono, ma per integrare il bluetooth nel resto della connettività MIDI di rete della mia app sarebbe bene essere in grado di gestire l'abilitazione direttamente dal codice della mia app piuttosto che fare affidamento su questo VC opaco. Qualcuno sa se è possibile?Pubblicare manualmente MIDI MIDI su iOS, senza CABTMIDILocalPeripheralViewController

+0

Hai mai capito come usare queste cose? Sto usando CABTMIDICentralViewController e voglio veramente controllare quale dispositivo MIDI l'utente ha collegato nel mio codice (così posso collegarmi automaticamente al dispositivo MIDI corretto). C'è un modo per farlo, o dovremmo presentare alcuni bug con Apple? – phreakhead

+0

Sto usando la versione Peripheral ma sulla base di ciò suppongo che una volta connessa diventi MIDIEndpointRef in modo che tu possa eseguire una query con l'API CoreMIDI. Dovrebbe avere il nome come "Connessione Bluetooth dell'iPhone di Hari Karam". Non è possibile modificare l'interno del VC. E non c'è altra API "CABTMIDI ..." per quanto posso vedere –

+0

Ok. Ho messo insieme una terribile soluzione di hacking che posterò qui sotto. – phreakhead

risposta

1

Non ci sono API pubbliche per gestire questa funzionalità. Dopo un'indagine con gli strumenti, sembra che l'interruttore causi un'istanza di CBPeripheralManager. Presumo che esso configuri il dispositivo come una periferica Bluetooth e canali manualmente i dati da e verso uno MIDIEndpointRef che è stato anche creato.

In altre parole, non esiste una soluzione di un solo liner. Se vado su questa strada ulteriormente vi posterò il codice meno che qualcun altro vuole avere un andare ...

UPDATE

Il codice magia ...

- (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]; 
} 

Sono quegli ID che definiscono una periferica MIDI. Per saperne di più:

Apple ha usato per avere un documento a

... che non è più. Mi piacerebbe trovare una vecchia copia in quanto risulta essere più difficile da decifrare ...

0

Penso che si potrebbe essere alla ricerca di questo: CABTMIDICentralViewController più informazioni in questa pagina: https://developer.apple.com/library/ios/qa/qa1831/_index.html basicaly questo consente di acquisire e connettersi a dispositivi tramite la vostra applicazione. Non sono sicuro se vuoi solo essere scoperto o anche essere quello che esegue la scansione. Spero che questo aiuti

+0

Ecco dove ho imparato a conoscere "CABTMIDILocalPeripheralViewController', che è sicuramente quello da usare nel mio caso. Ad ogni modo, questa pagina non descrive come eseguire l'attività senza utilizzare questi VC, che è ciò che voglio sapere. –

+0

In realtà è piuttosto limitato a questi, forse a causa di misure di sicurezza. –

+0

Ci sono app (ad es. Apollo Bluetooth) che lo fanno. Ho il sospetto che lo facciano manualmente senza il 'CABT ...' VC –

1

Quindi ho messo insieme una soluzione piuttosto hacky per scoprire quale dispositivo MIDI l'utente ha fatto clic una volta all'interno di CABTMIDICentralViewController. Non sono sicuro che questa sia una buona idea: se Apple cambia i componenti interni del controller, non funzionerà più. Inoltre, non sono sicuro che sia "legale" in merito alle linee guida sull'App Store. Qualcuno sa più informazioni su questo?

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 

Poi, nel vostro controller della vista genitore, è possibile ottenere il risultato dal delegato e cercare un nuovo dispositivo MIDI corrispondenza quel nome:

... 
    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]; 
      } 
     } 
    } 

} 

L'unica altra alternativa che posso è necessario cercare i dispositivi MIDI prima di mostrare il controller, salvare l'elenco dei dispositivi, quindi aprire il controller. Quando si chiude, scansiona di nuovo i dispositivi MIDI e diff quel nuovo elenco con quello vecchio. Qualsiasi nuovo dispositivo MIDI visualizzato sarà quello selezionato dall'utente. Non sei sicuro del motivo per cui Apple non ci abbia reso più facile ...