Основная проблема, с которой вы столкнулись, заключается в том, что вы предполагаете, что функция обратного вызова MIDI «знает» о вашем классе MyDocument
и может получить доступ к его свойствам.К сожалению, это не так.Функции C не имеют встроенной информации о состоянии, единственный способ передать информацию в функцию - это передать ее в качестве аргумента.
Это то, что все аргументы void* refCon
содержатся в документации.refCon
- это общий указатель, который можно использовать для передачи ссылки на какой-либо другой объект в вашу функцию.
Например, документы показывают подпись для функции MIDIInputPortCreate()
следующим образом:
extern OSStatus MIDIInputPortCreate(
MIDIClientRef client,
CFStringRef portName,
MIDIReadProc readProc,
void *refCon,
MIDIPortRef *outPort );
В вашем конкретном случае вы должны передать ссылку на ваш MyDocument
объект в качестве параметра refCon
.В настоящее время вы передаете NULL
.
MIDIPortRef inputPort;
result = MIDIInputPortCreate(midiClient,
CFSTR("Input"),
midiInputCallback,
myDocument, //note the change
&inputPort);
Затем в вашем обратном вызове вы можете получить доступ к объекту документа и, следовательно, к его свойствам:
void midiInputCallback (const MIDIPacketList *list, void *procRef, void *srcRef)
{
//do some MIDI stuff here
//get a reference to your document by casting the void* pointer
MyDocument* myDocument = (MyDocument*)procRef;
//log the message to the text field
[myDocument.test_messages setStringValue:@"TEST TEST"];
}
Так и должно быть.,Однако в приведенном выше коде у вас, похоже, есть main()
функция внутри вашего MyDocument.m
файла.Это полностью и совершенно неверно .Если вы используете приложение на основе документов Какао, вам вообще не следует изменять функцию main()
, за исключением очень редких случаев.
Вместо этого вы должны выполнить все настройки MIDI в ‑windowControllerDidLoadNib:
метод NSDocument
, который вызывается, когда окно документа загружено и выходы гарантированно будут готовы.
Примерно так:
@implementation MyDocument
@synthesize test_messages;
void midiInputCallback (const MIDIPacketList *list, void *procRef, void *srcRef)
{
//do some MIDI stuff here
//get a reference to your document by casting the void* pointer
MyDocument* myDocument = (MyDocument*)procRef;
//log the message to the text field
[myDocument.test_messages setStringValue:@"TEST TEST"];
}
‑ (void)windowControllerDidLoadNib:(NSWindowController*)windowController
{
//set up midi input
MIDIClientRef midiClient;
MIDIEndpointRef src;
OSStatus result;
result = MIDIClientCreate(CFSTR("MIDI client"), NULL, NULL, &midiClient);
if (result != noErr) {
NSLog(@"Errore : %s - %s",
GetMacOSStatusErrorString(result),
GetMacOSStatusCommentString(result));
return 0;
}
//note the use of "self" to send the reference to this document object
result = MIDIDestinationCreate(midiClient, CFSTR("Porta virtuale"), midiInputCallback, self, &src);
if (result != noErr ) {
NSLog(@"Errore : %s - %s",
GetMacOSStatusErrorString(result),
GetMacOSStatusCommentString(result));
return 0;
}
MIDIPortRef inputPort;
//and again here
result = MIDIInputPortCreate(midiClient, CFSTR("Input"), midiInputCallback, self, &inputPort);
ItemCount numOfDevices = MIDIGetNumberOfDevices();
for (int i = 0; i < numOfDevices; i++) {
MIDIDeviceRef midiDevice = MIDIGetDevice(i);
NSDictionary *midiProperties;
MIDIObjectGetProperties(midiDevice, (CFPropertyListRef *)&midiProperties, YES);
MIDIEndpointRef src = MIDIGetSource(i);
MIDIPortConnectSource(inputPort, src, NULL);
}
}
@end