예제 #1
0
MMRESULT Midi_InOpen(MIDI *midi)
{
    MMRESULT error;
    int i;

    if (midi->inPort == -1) {
        return MMSYSERR_NOERROR;
    }
    /*
     * Open the port.
     */
    m_closing = FALSE;
    error = midiInOpen(&midi->midiIn, midi->inPort
            , (DWORD) m_MidiInProc, (DWORD) midi, CALLBACK_FUNCTION);
    if (error != MMSYSERR_NOERROR) {
        return error;
    }
    /*
     * Initialize the midi header array.
     */
    for (i = 0; i < midi->bufCnt; i++) {
        error = midiInPrepareHeader(midi->midiIn, &midi->midiHdrs[i]
                , sizeof(MIDIHDR));
        if (error != MMSYSERR_NOERROR) {
            for (i--; i >= 0; i--) {
                midiInUnprepareHeader(midi->midiIn, &midi->midiHdrs[i]
                        , sizeof(MIDIHDR));
            }
            midiInClose(midi->midiIn);
            return error;
        }
        error = midiInAddBuffer(midi->midiIn, &midi->midiHdrs[i]
                , sizeof(MIDIHDR));
        if (error != MMSYSERR_NOERROR) {
            midiInReset(midi->midiIn);
            for ( ; i >= 0; i--) {
                midiInUnprepareHeader(midi->midiIn, &midi->midiHdrs[i]
                        , sizeof(MIDIHDR));
            }
            midiInClose(midi->midiIn);
            return error;
        }
    }
    /*
     * Initiate MIDI input.
     */
    error = midiInStart(midi->midiIn);
    if (error != MMSYSERR_NOERROR) {
        midiInReset(midi->midiIn);
        midiInClose(midi->midiIn);
        return error;
    }

    return error;
}
예제 #2
0
boolean JMIDIInObj::auxNotify(JEvent& e, void* pdata) {
#if defined(WIN32)
  cs.lock();
  MMRESULT rc;
  MIDIHDR *mhdr;
  if (!connected) goto CSEND;
  mhdr = (MIDIHDR*)(char*)data;
  if ((void*)mhdr != pdata) goto CSEND;
  if (!(mhdr->dwFlags & MHDR_DONE)) goto CSEND;
  if (mhdr->dwBytesRecorded > 0) {}
  rc = midiInUnprepareHeader((HMIDIIN)handle, 
    mhdr, sizeof(MIDIHDR));
  if (rc == MMSYSERR_NOERROR)
    rc = midiInPrepareHeader((HMIDIIN)handle, 
      mhdr, sizeof(MIDIHDR));
  if (rc == MMSYSERR_NOERROR)
    rc = midiInAddBuffer((HMIDIIN)handle,
      mhdr, sizeof(MIDIHDR));
  if (rc != MMSYSERR_NOERROR) close();
#endif
  cs.unlock();
  return true;
CSEND:
  cs.unlock();
  return false;
}
예제 #3
0
static void midirelease(COMMNG self) {

	CMMIDI	midi;

	midi = (CMMIDI)(self + 1);
	midiallnoteoff(midi);
	if (midi->opened & CMMIDI_MIDIOUT) {
		waitlastexclusiveout(midi);
		midiOutReset(midi->out.win32.hmidiout);
		midiOutClose(midi->out.win32.hmidiout);
	}
	if (midi->opened & CMMIDI_MIDIIN) {
		if (midi->opened & CMMIDI_MIDIINSTART) {
			midiInStop(midi->hmidiin);
			midiInUnprepareHeader(midi->hmidiin,
										&midi->hmidiinhdr, sizeof(MIDIHDR));
		}
		midiInReset(midi->hmidiin);
		midiInClose(midi->hmidiin);
		midiinhdlunreg(midi);
	}
#if defined(VERMOUTH_LIB)
	if (midi->opened & CMMIDI_VERMOUTH) {
		midiout_destroy(midi->out.vermouth);
	}
#endif
#if defined(MT32SOUND_DLL)
	if (midi->opened & CMMIDI_MT32SOUND) {
		mt32sound_close();
	}
#endif
	_MFREE(self);
}
예제 #4
0
		void Close()
		{
			if (handle)
			{
				midiInUnprepareHeader(handle, &header, sizeof(MIDIHDR));
				midiInClose(handle);
			}
		}
예제 #5
0
 void writeIfFinished (HMIDIIN deviceHandle)
 {
     if ((hdr.dwFlags & WHDR_DONE) != 0)
     {
         MMRESULT res = midiInUnprepareHeader (deviceHandle, &hdr, sizeof (hdr));
         (void) res;
         write (deviceHandle);
     }
 }
예제 #6
0
int rtsyn_synth_start(){
	int i;
	UINT port;

#ifdef __W32__
	DWORD processPriority;
	processPriority = GetPriorityClass(GetCurrentProcess());
#endif

	
	port=0;
	sleep(2);
	for(port=0;port<rtsyn_portnumber;port++){
		for (i=0;i<MAX_EXBUF;i++){
			IMidiHdr[port][i] = (MIDIHDR *)sIMidiHdr[port][i];
			memset(IMidiHdr[port][i],0,sizeof(MIDIHDR));
			IMidiHdr[port][i]->lpData = sImidiHdr_data[port][i];
			memset((IMidiHdr[port][i]->lpData),0,BUFF_SIZE);
			IMidiHdr[port][i]->dwBufferLength = BUFF_SIZE;
		}
	}
	evbwpoint=0;
	evbrpoint=0;
	mvbuse=0;

	for(port=0;port<rtsyn_portnumber;port++){
		midiInOpen(&hMidiIn[port],portID[port],(DWORD)MidiInProc,(DWORD)port,CALLBACK_FUNCTION);
		for (i=0;i<MAX_EXBUF;i++){
			midiInUnprepareHeader(hMidiIn[port],IMidiHdr[port][i],sizeof(MIDIHDR));
			midiInPrepareHeader(hMidiIn[port],IMidiHdr[port][i],sizeof(MIDIHDR));
			midiInAddBuffer(hMidiIn[port],IMidiHdr[port][i],sizeof(MIDIHDR));
		}
	}

#ifdef __W32__
	// HACK:midiInOpen()でリセットされてしまうため、再設定
	SetPriorityClass(GetCurrentProcess(), processPriority);
#endif
	for(port=0;port<rtsyn_portnumber;port++){
		if(MMSYSERR_NOERROR !=midiInStart(hMidiIn[port])){
			int i;
			for(i=0;i<port;i++){
				midiInStop(hMidiIn[i]);
				midiInReset(hMidiIn[i]);
				midiInClose(hMidiIn[i]);
			}
			goto winmmerror;
		}
	}
	mim_start_time = get_current_calender_time();
	InitializeCriticalSection(&mim_section);
	return ~0;

winmmerror:
	ctl->cmsg(  CMSG_ERROR, VERB_NORMAL, "midiInStarterror\n" );
	return 0;
}
예제 #7
0
int rtsyn_play_some_data(void){
	UINT wMsg;
	DWORD	dwInstance;
	DWORD	dwParam1;
	DWORD	dwParam2;
	DWORD	timestamp;
	MidiEvent ev;
	MidiEvent evm[260];
	int port;
	UINT evbpoint;
	MIDIHDR *IIMidiHdr;
	int exlen;
	char *sysexbuffer;
	int ne,i,j,chk,played;
		
	played=0;
		if( !rtsyn_buf_check() ){ 
			played=~0;
			return played;
		}
		do{
			EnterCriticalSection(&mim_section);
			evbpoint=evbrpoint;
			if (++evbrpoint >= EVBUFF_SIZE)
					evbrpoint -= EVBUFF_SIZE;

			wMsg=evbuf[evbpoint].wMsg;
			dwInstance=evbuf[evbpoint].dwInstance;
			dwParam1=evbuf[evbpoint].dwParam1;
			dwParam2=evbuf[evbpoint].dwParam2;
			LeaveCriticalSection(&mim_section);
		    
			port=(UINT)dwInstance;
			switch (wMsg) {
			case MIM_DATA:
				rtsyn_play_one_data (port, dwParam1, mim_start_time+(double)dwParam2/1000.0);
				break;
			case MIM_LONGDATA:
				IIMidiHdr = (MIDIHDR *) dwParam1;
				exlen=(int)IIMidiHdr->dwBytesRecorded;
				sysexbuffer=IIMidiHdr->lpData;
				rtsyn_play_one_sysex (sysexbuffer,exlen, mim_start_time+(double)dwParam2/1000.0);
				if (MMSYSERR_NOERROR != midiInUnprepareHeader(
						hMidiIn[port], IIMidiHdr, sizeof(MIDIHDR)))
					ctl->cmsg(  CMSG_ERROR, VERB_NORMAL,"error1\n");
				if (MMSYSERR_NOERROR != midiInPrepareHeader(
						hMidiIn[port], IIMidiHdr, sizeof(MIDIHDR)))
					ctl->cmsg(  CMSG_ERROR, VERB_NORMAL,"error5\n");
				if (MMSYSERR_NOERROR != midiInAddBuffer(
						hMidiIn[port], IIMidiHdr, sizeof(MIDIHDR)))
					ctl->cmsg(  CMSG_ERROR, VERB_NORMAL,"error6\n");
				break;
			}
		}while(rtsyn_buf_check());	
	return played;
}
    /***
     * Closes the MME MIDI Input port in a safe way
     */
void MidiInputDeviceMme::MidiInputPortMme::CloseMmeMidiPort(void) {
    int res;
    if (MidiInOpened == true) {
        ExitFlag = true;
        midiInReset(MidiInHandle);
        while ((res = midiInClose(MidiInHandle)) == MIDIERR_STILLPLAYING) Sleep(100);
        midiInUnprepareHeader(MidiInHandle, &midiHdr, sizeof(MIDIHDR));
        MidiInOpened = false;
    }
}
예제 #9
0
void CALLBACK midiCallback(HMIDIIN handle, UINT uMsg, DWORD dwInstance,
			   DWORD dwParam1, DWORD dwParam2) {
  debugPrintf(1, "callback called %d, handle %p\n", uMsg, handle);
  
  switch (uMsg) {
  case MIM_DATA:
    midiReceive(SHORT_MSG_STATUS(dwParam1));
    midiReceive(SHORT_MSG_BYTE1(dwParam1));
    midiReceive(SHORT_MSG_BYTE2(dwParam1));
    break;

  case MIM_LONGDATA:
    {
      MIDIHDR *midiHdr = (MIDIHDR *)dwParam1;
      if (midiHdr->dwBytesRecorded == 0) {
	return;
      }
      unsigned int len = 0;
      sleepCount = 0;
      for (len = 0; len < midiHdr->dwBufferLength; len++) {
	midiReceive(midiHdr->lpData[len]);
	if (((unsigned char)midiHdr->lpData[len]) == 0xF7)
	  break;
      }
      midiInUnprepareHeader(handle, midiHdr, sizeof(*midiHdr));
      midiInPrepareHeader(handle, midiHdr, sizeof(*midiHdr));
      midiInAddBuffer(handle, midiHdr, sizeof(*midiHdr));
    }
    break;

  case MIM_MOREDATA:
      // XXX set IO_STATUS flag to midiInOpen()
    debugPrintf(1, "midi driver is throwing away received data: %x %x %x\n",
	      SHORT_MSG_STATUS(dwParam1), SHORT_MSG_BYTE1(dwParam1),
	      SHORT_MSG_BYTE2(dwParam1));
    break;
    
  case MIM_ERROR:
    logPrintf(LOG_ERROR, "error\n");
    break;
    
  case MIM_LONGERROR:
    {
      logPrintf(LOG_ERROR, "long error\n");
    }
    break;

  default:
    debugPrintf(1, "received event %x\n", uMsg);

    /* ignore */
    return;
  }
}
예제 #10
0
static void test_midiIn_device(UINT udev, HWND hwnd)
{
    HMIDIIN hm;
    MMRESULT rc;
    MIDIINCAPSA capsA;
    MIDIHDR mhdr;

    rc = midiInGetDevCapsA(udev, &capsA, sizeof(capsA));
    ok((MIDIMAPPER==udev) ? (rc==MMSYSERR_BADDEVICEID || broken(rc==MMSYSERR_NODRIVER /*nt,w2k*/)) : rc==0,
       "midiInGetDevCaps(dev=%d) rc=%s\n", udev, mmsys_error(rc));
    if (!rc) {
        /* MIDI IN capsA.dwSupport may contain garbage, absent in old MS-Windows */
        trace("* %s: manufacturer=%d, product=%d, support=%X\n", capsA.szPname, capsA.wMid, capsA.wPid, capsA.dwSupport);
    }

    if (hwnd)
        rc = midiInOpen(&hm, udev, (DWORD_PTR)hwnd, (DWORD_PTR)MYCBINST, CALLBACK_WINDOW);
    else
        rc = midiInOpen(&hm, udev, (DWORD_PTR)callback_func, (DWORD_PTR)MYCBINST, CALLBACK_FUNCTION);
    ok((MIDIMAPPER!=udev) ? rc==0 : (rc==MMSYSERR_BADDEVICEID || broken(rc==MMSYSERR_NODRIVER /*nt,w2k*/)),
       "midiInOpen(dev=%d) rc=%s\n", udev, mmsys_error(rc));
    if (rc) return;

    test_notification(hwnd, "midiInOpen", MIM_OPEN, 0);

    memset(&mhdr, 0, sizeof(mhdr));
    mhdr.dwFlags = 0;
    mhdr.dwUser = 0x56FA552C;
    mhdr.dwBufferLength = 70000; /* > 64KB! */
    mhdr.lpData = HeapAlloc(GetProcessHeap(), 0 , mhdr.dwBufferLength);
    ok(mhdr.lpData!=NULL, "No %d bytes of memory!\n", mhdr.dwBufferLength);
    if (mhdr.lpData) {
        rc = midiInPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset)-1);
        ok(rc==MMSYSERR_INVALPARAM, "midiInPrepare tiny rc=%s\n", mmsys_error(rc));
        rc = midiInPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiInPrepare old size rc=%s\n", mmsys_error(rc));
        rc = midiInPrepareHeader(hm, &mhdr, sizeof(mhdr));
        ok(!rc, "midiInPrepare rc=%s\n", mmsys_error(rc));
        rc = midiInUnprepareHeader(hm, &mhdr, sizeof(mhdr));
        ok(!rc, "midiInUnprepare rc=%s\n", mmsys_error(rc));
        trace("MIDIHDR flags=%x when unsent\n", mhdr.dwFlags);

        HeapFree(GetProcessHeap(), 0, mhdr.lpData);
    }
    ok(mhdr.dwUser==0x56FA552C, "MIDIHDR.dwUser changed to %lx\n", mhdr.dwUser);

    rc = midiInReset(hm); /* Return any pending buffer */
    ok(!rc, "midiInReset rc=%s\n", mmsys_error(rc));

    rc = midiInClose(hm);
    ok(!rc, "midiInClose rc=%s\n", mmsys_error(rc));
    test_notification(hwnd, "midiInClose", MIM_CLOSE, 0);
    test_notification(hwnd, "midiIn over", 0, WHATEVER);
}
예제 #11
0
        void unprepare (HMIDIIN deviceHandle)
        {
            if ((hdr.dwFlags & WHDR_DONE) != 0)
            {
                int c = 10;
                while (--c >= 0 && midiInUnprepareHeader (deviceHandle, &hdr, sizeof (hdr)) == MIDIERR_STILLPLAYING)
                    Thread::sleep (20);

                jassert (c >= 0);
            }
        }
예제 #12
0
void cmmidi_recvexcv(HMIDIIN hdr, MIDIHDR *data) {

	CMMIDI	midi;

	midi = midiinhdlget(hdr);
	if (midi) {
		midiinrecv(midi, (UINT8 *)data->lpData, data->dwBytesRecorded);
		midiInUnprepareHeader(midi->hmidiin,
										&midi->hmidiinhdr, sizeof(MIDIHDR));
		midiInPrepareHeader(midi->hmidiin,
										&midi->hmidiinhdr, sizeof(MIDIHDR));
		midiInAddBuffer(midi->hmidiin, &midi->hmidiinhdr, sizeof(MIDIHDR));
	}
}
예제 #13
0
void JMIDIInObj::close() {
  cs.lock();
  if (!connected) goto CSEND;
  connected = false;
#if defined(WIN32)
  midiInStop((HMIDIIN)handle);
  midiInReset((HMIDIIN)handle);
  midiInUnprepareHeader((HMIDIIN)handle, 
    (MIDIHDR*)(char*)data, sizeof(MIDIHDR));
  midiInClose((HMIDIIN)handle);
#endif
  handle = -1;
  data.Release();
  repaint();
CSEND:;
  cs.unlock();
}
예제 #14
0
MidiUartWinClass::~MidiUartWinClass() {
  if (inHandle != (HMIDIIN)-1) {
    if (midiInStop(inHandle) != MMSYSERR_NOERROR) {
      throw "Could not stop MIDI input";
    }
    if (midiInReset(inHandle) != MMSYSERR_NOERROR) {
      throw "Could reset MIDI input";
    }
    if (midiInClose(inHandle) != MMSYSERR_NOERROR) {
      throw "Could not close MIDI input";
    }
		
    midiInUnprepareHeader(inHandle, &midiHdr, sizeof(MIDIHDR));
  }

  if (outHandle != (HMIDIOUT)-1) {
    midiOutClose(outHandle);
  }
}
예제 #15
0
파일: Win32Driver.cpp 프로젝트: Wyvan/munt
bool Win32MidiIn::close() {
	int wResult;

	wResult = midiInReset(hMidiIn);
	if (wResult != MMSYSERR_NOERROR) {
		qDebug() << "Win32MidiIn: Failed to reset MIDI input port";
	}

	wResult = midiInUnprepareHeader(hMidiIn, &MidiInHdr, sizeof(MIDIHDR));
	if (wResult != MMSYSERR_NOERROR) {
		qDebug() << "Win32MidiIn: Failed to unprepare MIDI header";
	}

	wResult = midiInClose(hMidiIn);
	if (wResult != MMSYSERR_NOERROR) {
		qDebug() << "Win32MidiIn: Failed to close MIDI input port";
	}

	return true;
}
예제 #16
0
void midiClose(void) {
  MMRESULT res;
  
  //  printf("stop\n");
  if (MMSYSERR_NOERROR != midiInStop(inHandle)) {
    logPrintf(LOG_ERROR, "input stop error\n");
  }
  //  printf("reset\n");
  if (MMSYSERR_NOERROR != midiInReset(inHandle)) {
    logPrintf(LOG_ERROR, "input reset error\n");
  }

  int retry = 0;
  do {
    res = midiInClose(inHandle);
    if (res != MMSYSERR_NOERROR) {
      logPrintf(LOG_ERROR, "input close error\n");
    }
    if (res == MIDIERR_STILLPLAYING) {
      midiInReset(inHandle);
    }
    Sleep(10);
    retry++;
  } while ((res == MIDIERR_STILLPLAYING) && (retry < 10));
  
  midiInUnprepareHeader(inHandle, &midiHdr, sizeof(MIDIHDR));

  retry = 0;
  res = midiOutReset(outHandle);
  if (res != MMSYSERR_NOERROR) {
    logPrintf(LOG_ERROR, "output reset error\n");
  }
  do {
    res = midiOutClose(outHandle);
    if (res != MMSYSERR_NOERROR) {
      logPrintf(LOG_ERROR, "output close error\n");
    }
    Sleep(10);
    retry++;
  } while ((res == MIDIERR_STILLPLAYING) && (retry < 10));
}
예제 #17
0
MF_API void MFMidi_CloseInput(MFDevice *pDevice)
{
	MFMidiPC_MidiInputDevice *pMidi = (MFMidiPC_MidiInputDevice*)pDevice->pInternal;

	if (!pMidi->hMidiIn)
	{
		MFDebug_Warn(1, "Midi input device not opened!");
		return;
	}

	midiInReset(pMidi->hMidiIn);

	midiInUnprepareHeader(pMidi->hMidiIn, &pMidi->sysexRecv, sizeof(pMidi->sysexRecv));

	midiInClose(pMidi->hMidiIn);
	pMidi->hMidiIn = NULL;

	MFHeap_Free(pMidi->pEvents);

	pDevice->state = MFDevState_Available;
}
예제 #18
0
void RtMidiIn :: closePort( void )
{
  if ( connected_ ) {
    WinMidiData *data = static_cast<WinMidiData *> (apiData_);
    midiInReset( data->inHandle );
    midiInStop( data->inHandle );

    for ( int i=0; i<RT_SYSEX_BUFFER_COUNT; ++i ) {
      int result = midiInUnprepareHeader(data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR));
      delete [] data->sysexBuffer[i]->lpData;
      delete [] data->sysexBuffer[i];
      if ( result != MMSYSERR_NOERROR ) {
        midiInClose( data->inHandle );
        errorString_ = "RtMidiIn::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader).";
        error( RtError::DRIVER_ERROR );
      }
    }

    midiInClose( data->inHandle );
    connected_ = false;
  }
}
예제 #19
0
void JackWinMMEDriver::CloseInput(MidiSlot* slot)
{
    MMRESULT res;
    int retry = 0;

    if (slot->fHandle == 0)
        return;

    HMIDIIN handle = (HMIDIIN)slot->fHandle;
    slot->fHeader->dwUser = 0;
    res = midiInStop(handle);
    if (res != MMSYSERR_NOERROR) {
        jack_error("midiInStop error");
    }
    res = midiInReset(handle);
    if (res != MMSYSERR_NOERROR) {
        jack_error("midiInReset error");
    }
    res = midiInUnprepareHeader(handle, slot->fHeader, sizeof(MIDIHDR));
    if (res != MMSYSERR_NOERROR) {
        jack_error("midiInUnprepareHeader error");
    }
    do {
        res = midiInClose(handle);
        if (res != MMSYSERR_NOERROR) {
            jack_error("midiInClose error");
        }
        if (res == MIDIERR_STILLPLAYING)
            midiInReset(handle);
        Sleep (10);
        retry++;
    } while ((res == MIDIERR_STILLPLAYING) && (retry < 10));

    if (slot->fHeader) {
        GlobalFreePtr(slot->fHeader);
    }
}
예제 #20
0
MMRESULT Midi_InClose(MIDI *midi)
{
    MMRESULT error;
    int i;

    if (midi->inPort == -1) {
        return MMSYSERR_NOERROR;
    }
    m_closing = TRUE;
    error = midiInReset(midi->midiIn);
    if (error != MMSYSERR_NOERROR) {
        return error;
    }
    /*
     * Unprepare the pending midi buffer header.
     */
    for (i = 0; i < midi->bufCnt; i++) {
UnprepareHeader:
        error = midiInUnprepareHeader(midi->midiIn, &midi->midiHdrs[i]
                , sizeof(MIDIHDR));
        if (error == MIDIERR_STILLPLAYING) {
            midiInReset(midi->midiIn);
            SleepEx(50, FALSE);
            goto UnprepareHeader;
        }
    }
CloseMidi:
    error = midiInClose(midi->midiIn);
    if (error == MIDIERR_STILLPLAYING) {
        midiInReset(midi->midiIn);
        SleepEx(50, FALSE);
        goto CloseMidi;
    }
    midi->midiIn = NULL;

    return error;
}
예제 #21
0
void CALLBACK midiCallback(HMIDIIN handle, UINT uMsg, DWORD dwInstance,
                           DWORD dwParam1, DWORD dwParam2) {
  MidiUartWinClass *uart = (MidiUartWinClass *)dwInstance;
  if (uart == NULL)
    return;

  //	printf("dwParam1: %lx, dwParam2: %lx\n", dwParam1, dwParam2);
  switch (uMsg) {
  case MIM_DATA:
    {
      uint8_t status = SHORT_MSG_STATUS(dwParam1);
      if (MIDI_IS_REALTIME_STATUS_BYTE(status)) {
        if (status >= 0xF8) {
          uart->rxRb.put(status);
        } else {
          switch (status) {
          case MIDI_MTC_QUARTER_FRAME:
          case MIDI_SONG_SELECT:
            uart->rxRb.put(SHORT_MSG_STATUS(dwParam1));
            uart->rxRb.put(SHORT_MSG_BYTE1(dwParam1));
            break;

          case MIDI_SONG_POSITION_PTR:
            uart->rxRb.put(SHORT_MSG_STATUS(dwParam1));
            uart->rxRb.put(SHORT_MSG_BYTE1(dwParam1));
            uart->rxRb.put(SHORT_MSG_BYTE2(dwParam1));
            break;

          default:
            printf("unknown status: %x\n", status);
            break;
          }
        }
      } else {
        switch (status & 0xF0) {
        case MIDI_NOTE_OFF:
        case MIDI_NOTE_ON:
        case MIDI_AFTER_TOUCH:
        case MIDI_CONTROL_CHANGE:
        case MIDI_PITCH_WHEEL:
          uart->rxRb.put(SHORT_MSG_STATUS(dwParam1));
          uart->rxRb.put(SHORT_MSG_BYTE1(dwParam1));
          uart->rxRb.put(SHORT_MSG_BYTE2(dwParam1));
          break;

        case MIDI_PROGRAM_CHANGE:
        case MIDI_CHANNEL_PRESSURE:
          uart->rxRb.put(SHORT_MSG_STATUS(dwParam1));
          uart->rxRb.put(SHORT_MSG_BYTE1(dwParam1));
          break;

        default:
          printf("unknown midi status: %x\n", status);
          break;
        }
      }
    }
    break;

  case MIM_LONGDATA:
    {
      MIDIHDR *midiHdr = (MIDIHDR *)dwParam1;
      if (midiHdr->dwBytesRecorded == 0) {
	return;
      }
      int len = 0;
      for (len = 0; len < midiHdr->dwBufferLength; len++) {
        uart->rxRb.put(midiHdr->lpData[len]);
        if (((unsigned char)midiHdr->lpData[len]) == 0xF7)
          break;
      }
      midiInUnprepareHeader(handle, midiHdr, sizeof(*midiHdr));
      midiInPrepareHeader(handle, midiHdr, sizeof(*midiHdr));
      midiInAddBuffer(handle, midiHdr, sizeof(*midiHdr));
    }			
    break;

  case MIM_MOREDATA:
    printf("midi driver is throwing away received data: %x %x %x\n",
           SHORT_MSG_STATUS(dwParam1), SHORT_MSG_BYTE1(dwParam1),
           SHORT_MSG_BYTE2(dwParam1));
    break;

  case MIM_ERROR:
    printf("callback error\n");
    break;

  case MIM_LONGERROR:
    printf("callback long error");
    break;

  default:
    printf("received unknown event %x\n", uMsg);
    return;
  }
}
예제 #22
0
/* Callback function executed via midiInput SW interrupt (via midiInOpen). */
static void FAR PASCAL winmm_in_callback(
    HMIDIIN hMidiIn,       /* midiInput device Handle */
    UINT wMsg,             /* midi msg */
    DWORD_PTR dwInstance,  /* application data */
    DWORD_PTR dwParam1,    /* MIDI data */
    DWORD_PTR dwParam2)    /* device timestamp (wrt most recent midiInStart) */
{
    static int entry = 0;
    PmInternal *midi = (PmInternal *) dwInstance;
    midiwinmm_type m = (midiwinmm_type) midi->descriptor;

    /* NOTE: we do not just EnterCriticalSection() here because an
     * MIM_CLOSE message arrives when the port is closed, but then
     * the m->lock has been destroyed.
     */

    switch (wMsg) {
    case MIM_DATA: {
        /* if this callback is reentered with data, we're in trouble. 
         * It's hard to imagine that Microsoft would allow callbacks 
         * to be reentrant -- isn't the model that this is like a 
         * hardware interrupt? -- but I've seen reentrant behavior 
         * using a debugger, so it happens.
         */
        EnterCriticalSection(&m->lock);

        /* dwParam1 is MIDI data received, packed into DWORD w/ 1st byte of
                message LOB;
           dwParam2 is time message received by input device driver, specified
            in [ms] from when midiInStart called.
           each message is expanded to include the status byte */

        if ((dwParam1 & 0x80) == 0) {
            /* not a status byte -- ignore it. This happened running the
               sysex.c test under Win2K with MidiMan USB 1x1 interface,
               but I can't reproduce it. -RBD
             */
            /* printf("non-status byte found\n"); */
        } else { /* data to process */
            PmEvent event;
            if (midi->time_proc)
                dwParam2 = (*midi->time_proc)(midi->time_info);
            event.timestamp = (PmTimestamp)dwParam2;
            event.message = (PmMessage)dwParam1;
            pm_read_short(midi, &event);
        }
        LeaveCriticalSection(&m->lock);
        break;
    }
    case MIM_LONGDATA: {
        MIDIHDR *lpMidiHdr = (MIDIHDR *) dwParam1;
        unsigned char *data = (unsigned char *) lpMidiHdr->lpData;
        unsigned int processed = 0;
        int remaining = lpMidiHdr->dwBytesRecorded;

        EnterCriticalSection(&m->lock);
        /* printf("midi_in_callback -- lpMidiHdr %x, %d bytes, %2x...\n", 
                lpMidiHdr, lpMidiHdr->dwBytesRecorded, *data); */
        if (midi->time_proc)
            dwParam2 = (*midi->time_proc)(midi->time_info);
        /* can there be more than one message in one buffer? */
        /* assume yes and iterate through them */
        while (remaining > 0) {
            unsigned int amt = pm_read_bytes(midi, data + processed, 
                                             remaining, (PmTimestamp)dwParam2);
            remaining -= amt;
            processed += amt;
        }

        /* when a device is closed, the pending MIM_LONGDATA buffers are
           returned to this callback with dwBytesRecorded == 0. In this
           case, we do not want to send them back to the interface (if
           we do, the interface will not close, and Windows OS may hang). */
        if (lpMidiHdr->dwBytesRecorded > 0) {
            MMRESULT rslt;
            lpMidiHdr->dwBytesRecorded = 0;
            lpMidiHdr->dwFlags = 0;
			
            /* note: no error checking -- can this actually fail? */
            rslt = midiInPrepareHeader(hMidiIn, lpMidiHdr, sizeof(MIDIHDR));
            assert(rslt == MMSYSERR_NOERROR);
            /* note: I don't think this can fail except possibly for
             * MMSYSERR_NOMEM, but the pain of reporting this
             * unlikely but probably catastrophic error does not seem
             * worth it.
             */
            rslt = midiInAddBuffer(hMidiIn, lpMidiHdr, sizeof(MIDIHDR));
            assert(rslt == MMSYSERR_NOERROR);
            LeaveCriticalSection(&m->lock);
        } else {
            midiInUnprepareHeader(hMidiIn,lpMidiHdr,sizeof(MIDIHDR));
            LeaveCriticalSection(&m->lock);
            pm_free(lpMidiHdr);
        }
        break;
    }
    case MIM_OPEN:
        break;
    case MIM_CLOSE:
        break;
    case MIM_ERROR:
        /* printf("MIM_ERROR\n"); */
        break;
    case MIM_LONGERROR:
        /* printf("MIM_LONGERROR\n"); */
        break;
    default:
        break;
    }
}