代码之家  ›  专栏  ›  技术社区  ›  lppier

未调用MidiClientCreate notifyproc

  •  2
  • lppier  · 技术社区  · 11 年前

    我有以下代码,我希望在其中调用函数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;
    }
    
    1 回复  |  直到 11 年前
        1
  •  2
  •   vosc    10 年前

    我刚刚在Mac OS X上遇到了同样的问题。原因是我没有设置运行循环。CoreMDI的文档并不十分丰富,但MIDIClientCreate文档表明通知是使用运行循环源发送的:

    请注意,notifyProc将始终在首次调用MIDIClientCreate时的当前运行循环上调用。 Apple MIDI Services Reference : MIDIClientCreate

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

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