Получение имени внешнего MIDI-устройства от Конечной точки MIDI
Q: Как я получаю имя внешнего MIDI-устройства от Конечной точки MIDI?
A: CoreMIDI поддерживает внешние MIDI-устройства с многократными портами, например синтезатор больше чем с одним вводом MIDI. Внешние MIDI-устройства могут иметь многократные конечные точки и объекты. Поэтому вместо того, чтобы запросить просто Объект MIDI для имени устройства, конечные точки MIDI, объекты и внешние устройства должны все быть проверены для получения надлежащего имени устройства.
Начиная с выпуска OS X 10.4, MIDIServices.h включал свойство kMIDIPropertyDisplayName который может использоваться с этой целью. Это свойство обеспечивает рекомендуемое Apple видимое пользователем имя для конечной точки путем объединения устройства и имен конечной точки для Вас. Для объектов кроме конечных точек имя дисплея совпадает с именем.
Перечисление 1 , Получающее конечную точку, выводит на экран имя.
// ____________________________________________________________________________ |
// Obtain the name of an endpoint without regard for whether it has connections. |
// The result should be released by the caller. |
static CFStringRef GetEndpointDisplayName(MIDIEndpointRef endpoint) |
{ |
CFStringRef result = CFSTR(""); // default |
MIDIObjectGetStringProperty(endpoint, kMIDIPropertyDisplayName, &result); |
return result; |
} |
Перечисление 2 , Получающее имя конечной точки после соединений.
// Obtain the name of an endpoint, following connections. |
// The result should be released by the caller. |
static CFStringRef CreateConnectedEndpointName(MIDIEndpointRef endpoint) |
{ |
CFMutableStringRef result = CFStringCreateMutable(NULL, 0); |
CFStringRef str; |
OSStatus err; |
// Does the endpoint have connections? |
CFDataRef connections = NULL; |
int nConnected = 0; |
bool anyStrings = false; |
err = MIDIObjectGetDataProperty(endpoint, kMIDIPropertyConnectionUniqueID, &connections); |
if (connections != NULL) { |
// It has connections, follow them |
// Concatenate the names of all connected devices |
nConnected = CFDataGetLength(connections) / sizeof(MIDIUniqueID); |
if (nConnected) { |
const SInt32 *pid = reinterpret_cast<const SInt32 *>(CFDataGetBytePtr(connections)); |
for (int i = 0; i < nConnected; ++i, ++pid) { |
MIDIUniqueID id = EndianS32_BtoN(*pid); |
MIDIObjectRef connObject; |
MIDIObjectType connObjectType; |
err = MIDIObjectFindByUniqueID(id, &connObject, &connObjectType); |
if (err == noErr) { |
if (connObjectType == kMIDIObjectType_ExternalSource || |
connObjectType == kMIDIObjectType_ExternalDestination) { |
// Connected to an external device's endpoint (10.3 and later). |
str = EndpointName(static_cast<MIDIEndpointRef>(connObject), true); |
} else { |
// Connected to an external device (10.2) (or something else, catch-all) |
str = NULL; |
MIDIObjectGetStringProperty(connObject, kMIDIPropertyName, &str); |
} |
if (str != NULL) { |
if (anyStrings) |
CFStringAppend(result, CFSTR(", ")); |
else anyStrings = true; |
CFStringAppend(result, str); |
CFRelease(str); |
} |
} |
} |
} |
CFRelease(connections); |
} |
if (anyStrings) |
return result; |
else |
CFRelease(result); |
// Here, either the endpoint had no connections, or we failed to obtain names for any of them. |
return CreateEndpointName(endpoint, false); |
} |
////////////////////////////////////// |
// Obtain the name of an endpoint without regard for whether it has connections. |
// The result should be released by the caller. |
static CFStringRef CreateEndpointName(MIDIEndpointRef endpoint, bool isExternal) |
{ |
CFMutableStringRef result = CFStringCreateMutable(NULL, 0); |
CFStringRef str; |
// begin with the endpoint's name |
str = NULL; |
MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &str); |
if (str != NULL) { |
CFStringAppend(result, str); |
CFRelease(str); |
} |
MIDIEntityRef entity = NULL; |
MIDIEndpointGetEntity(endpoint, &entity); |
if (entity == NULL) |
// probably virtual |
return result; |
if (CFStringGetLength(result) == 0) { |
// endpoint name has zero length -- try the entity |
str = NULL; |
MIDIObjectGetStringProperty(entity, kMIDIPropertyName, &str); |
if (str != NULL) { |
CFStringAppend(result, str); |
CFRelease(str); |
} |
} |
// now consider the device's name |
MIDIDeviceRef device = NULL; |
MIDIEntityGetDevice(entity, &device); |
if (device == NULL) return result; |
str = NULL; |
MIDIObjectGetStringProperty(device, kMIDIPropertyName, &str); |
if (str != NULL) { |
// if an external device has only one entity, throw away |
// the endpoint name and just use the device name |
if (isExternal && MIDIDeviceGetNumberOfEntities(device) < 2) { |
CFRelease(result); |
return str; |
} else { |
// does the entity name already start with the device name? |
// (some drivers do this though they shouldn't) |
// if so, do not prepend |
if (CFStringCompareWithOptions(str /* device name */, |
result /* endpoint name */, |
CFRangeMake(0, CFStringGetLength(str)), 0) != kCFCompareEqualTo) { |
// prepend the device name to the entity name |
if (CFStringGetLength(result) > 0) |
CFStringInsert(result, 0, CFSTR(" ")); |
CFStringInsert(result, 0, str); |
} |
CFRelease(str); |
} |
} |
return result; |
} |
История версии документа
| Дата | Примечания |
|---|---|
| 24.03.2014 | Передовая статья |
| 21.01.2014 | Передовая статья |
| 06.08.2013 | Передовая статья |
| 01.12.2004 | Новый документ, которые получают имена внешних MIDI-устройств от Конечных точек MIDI. |