关于iOS CoreMIDI库中MIDIServices 相关API解读
一.获取可用MIDI列表
// 获取可用MIDI列表的数量
ItemCount deviceCount = MIDIGetNumberOfDevices();
// 遍历MIDI列表,可以获取到设备
for (ItemCount i = 0 ; i < deviceCount ; ++i) {
MIDIDeviceRef device = MIDIGetDevice(i);
}
二.获取设备相关信息
通过1中遍历MIDI列表,可以拿到设备的指针,即可获取到相关的midi信息
1.获取MIDI设备相关信息
NSString *getPropatyString(MIDIObjectRef object, CFStringRef property )
{
CFStringRef name = nil;
if (noErr != MIDIObjectGetStringProperty(object, property, &name))
return nil;
return (NSString *)CFBridgingRelease(name);
}
kMIDIPropertyName
设备、实体和端点都可能有名称。 显示端点名称的推荐方法是询问端点名称,如果该名称是唯一的,则仅显示该名称。 如果它不是唯一的,则在设备名称前添加。
其他相关想要获取的可以查阅文档,列举几个常用的
kMIDIPropertyManufacturer
kMIDIPropertyUniqueID
kMIDIPropertyDeviceID
kMIDIPropertyDisplayName
调用方法
getPropatyString(device, kMIDIPropertyManufacturer )
2.查看设备是否在线
SInt32 isOffline = 0;
MIDIObjectGetIntegerProperty(device, kMIDIPropertyOffline, &isOffline);
isOffline == 0为离线
3.获取设备的实体数量
// 获取设备的实体数量
ItemCount entityCount = MIDIDeviceGetNumberOfEntities(device);
// 遍历设备的实体数量
for (ItemCount j = 0 ; j < entityCount ; ++j) {
MIDIEntityRef entity = MIDIDeviceGetEntity(device, j);
// 同样可以获取实体的名称,可以调这个方法是应该他们都是指针对象
getPropatyString(entity, kMIDIPropertyName) ;
}
3.1 获取设备的源端口数量
// 获取源端口的数量
ItemCount sourceCount = MIDIEntityGetNumberOfSources(entity);
for (ItemCount k = 0 ; k < sourceCount ; ++k) {
MIDIEndpointRef source = MIDIEntityGetSource(entity, k);
// 同样可以获取实体的名称
getPropatyString(entity, kMIDIPropertyName) ;
}
3.2 获取设备目的端口的数量
// 获取目的端口的数量
ItemCount destCount = MIDIEntityGetNumberOfDestinations(entity);
for (ItemCount k = 0 ; k < destCount ; ++k) {
MIDIEndpointRef dest = MIDIEntityGetDestination(entity, k);
// 同样可以获取实体的名称
getPropatyString(entity, kMIDIPropertyName) ;
}
4.直接获取系统源端口
// 获取源端口的数量
ItemCount sourceCount = MIDIGetNumberOfSources();
for (NSInteger i = 0; i < sourceCount; i++) {
MIDIEndpointRef endPointRef = MIDIGetSource(i);
// 同样可以获取实体的名称
getPropatyString(endPointRef, kMIDIPropertyName) ;
}
三、创建MIDI Client 和Port
要使用 CoreMIDI,应用程序会创建一个 MIDIClientRef,它可以向其中添加MIDIPortRef,通过它可以发送和接收 MIDI。
OSStatus err;
MIDIClientRef clientRef;
MIDIPortRef inputPortRef;
NSString *clientName = @"inputClient";
err = MIDIClientCreate((CFStringRef)CFBridgingRetain(clientName), NULL, NULL, &clientRef);
if (err != noErr) {
NSLog(@"MIDIClientCreate err = %d", err);
return ;
}
NSString *inputPortName = @"inputPort";
err = MIDIInputPortCreate(
clientRef, (CFStringRef)CFBridgingRetain(inputPortName),
MIDIInputProc, NULL, &inputPortRef);
if (err != noErr) {
NSLog(@"MIDIInputPortCreate err = %d", err);
return ;
}
ItemCount sourceCount = MIDIGetNumberOfSources();
NSLog( @"errsourceCount = %lu", sourceCount );
for (ItemCount i = 0; i < sourceCount; i++) {
MIDIEndpointRef sourcePointRef = MIDIGetSource(i);
err = MIDIPortConnectSource(inputPortRef, sourcePointRef, NULL);
if (err != noErr) {
NSLog(@"MIDIPortConnectSource err = %d", err);
return ;
}
}
static void
MIDIInputProc(const MIDIPacketList *pktlist,
void *readProcRefCon, void *srcConnRefCon)
{
MIDIPacket *packet = (MIDIPacket *)&(pktlist->packet[0]);
UInt32 packetCount = pktlist->numPackets;
for (NSInteger i = 0; i < packetCount; i++) {
Byte mes = packet->data[0] & 0xF0;
Byte ch = packet->data[0] & 0x0F;
if ((mes == 0x90) && (packet->data[2] != 0)) {
NSLog(@"note on number = %2.2x / velocity = %2.2x / channel = %2.2x",
packet->data[1], packet->data[2], ch);
} else if (mes == 0x80 || mes == 0x90) {
NSLog(@"note off number = %2.2x / velocity = %2.2x / channel = %2.2x",
packet->data[1], packet->data[2], ch);
} else if (mes == 0xB0) {
NSLog(@"cc number = %2.2x / data = %2.2x / channel = %2.2x",
packet->data[1], packet->data[2], ch);
} else {
NSLog(@"etc");
}
packet = MIDIPacketNext(packet);
}
}