2015-10-05 10 views
9

Właśnie odkryłem CABTMIDILocalPeripheralViewController dla systemu iOS, który obsługuje ustawienia użytkownika umożliwiające wykrywanie interfejsu Bluetooth MIDI. Jest to dobry i niezły wynik, ale aby zintegrować bluetooth z resztą interfejsu sieciowego MIDI mojej aplikacji, dobrze byłoby móc włączyć obsługę kodu bezpośrednio z kodu mojej aplikacji, zamiast polegać na tym nieprzejrzystym VC. Czy ktoś wie, czy to jest możliwe?Można ręcznie reklamować interfejs Bluetooth MIDI na urządzeniu z systemem iOS, bez aplikacji CABTMIDILocalPeripheralViewController

+0

Czy kiedykolwiek zastanawiałeś się, jak używać tych rzeczy? Używam CABTMIDICentralViewController i naprawdę chcę sprawdzić, które urządzenie MIDI użytkownik podłączył w moim kodzie (dzięki czemu mogę automatycznie połączyć się z właściwym urządzeniem MIDI). Czy jest jakiś sposób, aby to zrobić, czy powinniśmy zgłosić błędy w Apple? – phreakhead

+0

Używam wersji peryferyjnej, ale na podstawie tego założę, że po podłączeniu staje się MIDIEndpointRef, dzięki czemu można zapytać o to za pomocą interfejsu API CoreMIDI. Powinien mieć nazwę "Połączenie Bluetooth iPhone'a Hari Karama". Nie możesz w ogóle modyfikować wewnętrznych elementów VC. I nie ma innych "CABTMIDI ..." api, o ile widzę, –

+0

Ok. Złożyłem razem straszne rozwiązanie, które opiszę poniżej. – phreakhead

Odpowiedz

1

Brak publicznego interfejsu API do zarządzania tą funkcją. Po przeprowadzeniu dochodzenia w sprawie Instrumentów okazuje się, że przełącznik powoduje utworzenie instancji CBPeripheralManager. Zakładam, że konfiguruje to urządzenie jako urządzenie peryferyjne Bluetooth i ręcznie przekazuje dane do i z utworzonego również MIDIEndpointRef.

Innymi słowy, nie ma jednego rozwiązania liniowego. Jeśli pójdę tą drogą dalszej będę pisać kod, chyba że ktoś chce mieć go ...

UPDATE

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

To te identyfikatory definiują urządzenie peryferyjne MIDI. Więcej informacji:

Jabłko wykorzystywane mieć doc na

... co nie jest. Chciałbym znaleźć starą kopię, ponieważ okazuje się, że kod odbiornika (emulując CABTMIDICentralViewController) jest jeszcze trudniejszy do złamania ...

0

myślę, że może być patrząc na to: CABTMIDICentralViewController więcej informacji na tej stronie: https://developer.apple.com/library/ios/qa/qa1831/_index.html basicaly ten pozwala skanować i łączyć się z urządzeniami za pośrednictwem aplikacji. Nie jestem pewien, czy chcesz tylko zostać odkrytym, czy też być tym, który skanuje. Mam nadzieję, że pomoże to

+0

To tam dowiedziałem się o 'CABTMIDILocalPeripheralViewController', który jest z pewnością tym, którego użyję w moim przypadku. Tak czy inaczej, ta strona nie opisuje, jak wykonać zadanie bez używania tych VC, co chcę poznać. –

+0

W rzeczywistości jest to dość ograniczone, być może ze względu na zabezpieczenia. –

+0

Istnieją aplikacje (np. Apollo Bluetooth), które to umożliwiają. Podejrzewam, że robią to ręcznie bez "CABT ..." VC –

1

Więc połączyłem ze sobą dość hackowate rozwiązanie do wykrywania, które urządzenie MIDI użytkownik kliknął raz wewnątrz obiektu CABTMIDICentralViewController. Nie jestem pewien, czy to dobry pomysł - jeśli Apple zmieni wewnętrzne elementy kontrolera, przestanie działać. Ponadto nie jestem pewien, czy jest "legalny" w odniesieniu do wytycznych App Store. Czy ktoś wie więcej informacji na ten temat?

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 

Następnie w swojej macierzystej widoku kontrolera, można uzyskać wynik z delegatem i szukać nowego urządzenia MIDI odpowiadających tej nazwie:

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

} 

jedyną inną alternatywę mogę pomyśl o skanowaniu urządzeń MIDI przed wyświetleniem kontrolera, zapisz listę urządzeń, a następnie otwórz kontroler. Kiedy się zamknie, zeskanuj urządzenia MIDI i zmień tę listę na starszą. Wszystkie nowe urządzenia MIDI, które się pojawią, będą tymi, które wybrał użytkownik. Nie wiem, dlaczego Apple nam to nie ułatwiło ...

Powiązane problemy