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
Odpowiedz
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 ...
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
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ć. –
W rzeczywistości jest to dość ograniczone, być może ze względu na zabezpieczenia. –
Istnieją aplikacje (np. Apollo Bluetooth), które to umożliwiają. Podejrzewam, że robią to ręcznie bez "CABT ..." VC –
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 ...
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
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ę, –
Ok. Złożyłem razem straszne rozwiązanie, które opiszę poniżej. – phreakhead