2

我有以下代码,我希望调用函数 MyMIDINotifyProc 来通知我连接到 iOS 设备的 midi 设备的更改。然而,奇怪的是,当我连接或断开设备时,它从来没有被调用过——这可能是什么问题?

谢谢你。非常感谢帮助。

void MyMIDINotifyProc (const MIDINotification  *message, void *refCon) {
    printf("MIDI Notify, messageId=%d,", (int)message->messageID);

}

/* csound MIDI input open callback, sets the device for input */ 
static int MidiInDeviceOpen(CSOUND *csound, void **userData, const char *dev)
{

    int k = 0;
    //6counter++;
    endpoints = 0;

    CFStringRef name = NULL, cname = NULL, pname = NULL;
    CFStringEncoding defaultEncoding = CFStringGetSystemEncoding();
    MIDIClientRef mclient = NULL;
    MIDIPortRef mport = NULL;
    MIDIEndpointRef endpoint;
    MIDIdata *mdata = (MIDIdata *) malloc(DSIZE*sizeof(MIDIdata));
    OSStatus ret;
    cdata *refcon = (cdata *) malloc(sizeof(cdata));
    memset(mdata, 0, sizeof(MIDIdata)*DSIZE);
    refcon->mdata = mdata;
    refcon->p = 0;
    refcon->q = 0;
    refcon->pnot = refcon->pchn = 0;

    cname = CFStringCreateWithCString(NULL, "my client", defaultEncoding);
    ret = MIDIClientCreate(cname, MyMIDINotifyProc, refcon, &mclient);

    if(!ret){
        /* MIDI output port */
        pname = CFStringCreateWithCString(NULL, "outport", defaultEncoding);
        ret = MIDIInputPortCreate(mclient, pname, ReadProc, refcon, &mport);
        if(!ret){
            /* sources, we connect to all available input sources */
            endpoints = MIDIGetNumberOfSources();
            csoundMessage(csound, "midi srcs %d\n", endpoints);
            midiDevicesArray = malloc(endpoints*sizeof(CFStringRef));

            for(k=0; k < endpoints; k++){
                endpoint = MIDIGetSource(k);
                void *srcRefCon = endpoint;
                MIDIPortConnectSource(mport, endpoint, srcRefCon);
                // insert into dictionary instead ?
                midiDevicesArray[k] = ConnectedEndpointName(endpoint);

            }
        }
    }
    refcon->mclient = mclient;
    *userData = (void*) refcon;
    if(name) CFRelease(name);
    if(pname) CFRelease(pname);
    if(cname) CFRelease(cname); 
    /* report success */
    return 0;
}
4

1 回答 1

2

我刚刚在 Mac OS X 上遇到了同样的问题。原因是我没有运行循环。CoreMIDI 的文档不是很广泛,但 MIDIClientCreate 文档表明通知是使用运行循环源发送的:

请注意 notifyProc 将始终在第一次调用 MIDIClientCreate 时的当前运行循环上调用。Apple MIDI 服务参考:MIDIClientCreate

所以一个解决方案是调用CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true)我的自定义运行循环。由于我在MIDIClientRef辅助线程上创建了,我还必须将此调用添加到我的主线程的运行循环中(最终这需要为所有父线程完成)。CFRunLoopRunInMode将处理运行循环的输入源并在我的情况下立即退出(第三个参数是true),但您也可以选择阻塞线程直到运行循环停止(CFRunLoopRun),也许在一个新线程上,只要最适合您的设计.

如果你还不熟悉 Apple 的 Core Foundation 和 Cocoa Run Loops,下面的指南应该是一个很好的介绍:Apple Threading Programming Guide : Run Loops

于 2013-12-04T05:53:50.657 回答