void MidiInputDeviceMme::MidiInputPortMme::ConnectToMmeMidiSource(const char* MidiSource) {

    // close the old MIDI Input port if it was already opened
    CloseMmeMidiPort();

    MIDIINCAPS midiincaps;
    int NumDevs = midiInGetNumDevs();

    int FoundMidiInDeviceId = -1;
    for(int i=0;i<NumDevs;i++) {
        int res = midiInGetDevCaps(i, &midiincaps, sizeof(MIDIINCAPS));
        if(res == MMSYSERR_NOERROR) {
            if(!strcmp(midiincaps.szPname, MidiSource)) {
                FoundMidiInDeviceId = i;
                break;
            }
        }
    }

    if(FoundMidiInDeviceId == -1) throw MidiInputException("MIDI port connect failed");

    int res;
    res = midiInOpen(&MidiInHandle, FoundMidiInDeviceId, (DWORD_PTR)win32_midiin_callback, (DWORD_PTR)this, CALLBACK_FUNCTION);
    if(res != MMSYSERR_NOERROR) {
        throw MidiInputException("MIDI port connect failed. midiInOpen error");
    }

    MidiInOpened = true;

    /* Store pointer to our input buffer for System Exclusive messages in MIDIHDR */
    midiHdr.lpData = &TmpSysExBuf[0];

    /* Store its size in the MIDIHDR */
    midiHdr.dwBufferLength = MME_MAX_SYSEX_BUF_SIZE;

    /* Flags must be set to 0 */
    midiHdr.dwFlags = 0;

    /* Prepare the buffer and MIDIHDR */
    res = midiInPrepareHeader(MidiInHandle, &midiHdr, sizeof(MIDIHDR));
    if(res != MMSYSERR_NOERROR) {
        CloseMmeMidiPort();
        throw MidiInputException("MIDI port connect failed. midiInPrepareHeader error");
    }

    /* Queue MIDI input buffer */
    res = midiInAddBuffer(MidiInHandle, &midiHdr, sizeof(MIDIHDR));
    if(res != MMSYSERR_NOERROR) {
        CloseMmeMidiPort();
        throw MidiInputException("MIDI port connect failed. midiInAddBuffer error");
    }


    res = midiInStart(MidiInHandle);
    if(res != MMSYSERR_NOERROR) {
        CloseMmeMidiPort();
        throw MidiInputException("MIDI port connect failed, midiInStart failed.");
    }

}
Parameter::Parameter(void)
{
	/* Initialize values */
	for (int i = 0; i < NUM_PARAMETERS; i++)
	{
		value[i] = 0.0f;
		changed[i] = false;
	}

	/* Open Midi device */
	numDevices = midiInGetNumDevs();
	if (numDevices > MAX_NUM_DEVICES) numDevices = MAX_NUM_DEVICES;
	for (unsigned int devID = 0; devID < numDevices; devID++)
	{
		MMRESULT rc;
		rc = midiInOpen(&(midiInDevice[devID]), devID, (DWORD_PTR)MidiInProc, NULL, CALLBACK_FUNCTION);
		/* Create input buffers */
		midiInHeader[devID].lpData = (LPSTR)midiData[devID];
		midiInHeader[devID].dwBufferLength = MIDI_DATA_SIZE;
		midiInHeader[devID].dwFlags = 0;
		rc = midiInPrepareHeader(midiInDevice[devID], &midiInHeader[devID], sizeof(midiInHeader[devID]));
		rc = midiInAddBuffer(midiInDevice[devID], &midiInHeader[devID], sizeof(midiInHeader[devID]));
		rc = midiInStart(midiInDevice[devID]);
	}
}
Exemple #3
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;
}
Exemple #4
0
void CALLBACK Win32MidiIn::midiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
	Q_UNUSED(dwParam2);

	MidiSession *midiSession = (MidiSession *)dwInstance;

	LPMIDIHDR pMIDIhdr = (LPMIDIHDR)dwParam1;
	if (wMsg == MIM_LONGDATA) {
		if (pMIDIhdr->dwBytesRecorded == 0) {
			// 0 length means returning the buffer to the application when closing
			return;
		}
		// Use QMidiStreamParser to extract well-formed SysEx messages from buffer
		QMidiStreamParser &qMidiStreamParser = *midiSession->getQMidiStreamParser();
		qMidiStreamParser.setTimestamp(MasterClock::getClockNanos());
		qMidiStreamParser.parseStream((BYTE *)pMIDIhdr->lpData, pMIDIhdr->dwBytesRecorded);

		// Add SysEx Buffer for reuse
		if (midiInAddBuffer(hMidiIn, pMIDIhdr, sizeof(MIDIHDR)) != MMSYSERR_NOERROR) {
			QMessageBox::critical(NULL, "Win32MidiIn Error", "Failed to add SysEx Buffer for reuse");
			return;
		}
		return;
	}
	if (wMsg == MIM_DATA) {
		// No need to use QMidiStreamParser for short messages: they are guaranteed to have explicit status byte
		// if ((dwParam1 & 0xF8) == 0xF8) // No support for System Realtime yet
		midiSession->getSynthRoute()->pushMIDIShortMessage(dwParam1, MasterClock::getClockNanos());
	}
}
Exemple #5
0
bool Win32MidiIn::open(MidiSession *midiSession, unsigned int midiDevID) {
	int wResult;

	// Init midiIn port
	wResult = midiInOpen(&hMidiIn, midiDevID, (DWORD_PTR)midiInProc, (DWORD_PTR)midiSession, CALLBACK_FUNCTION);
	if (wResult != MMSYSERR_NOERROR) {
		QMessageBox::critical(NULL, "Win32MidiIn Error", "Failed to open MIDI input port");
		return false;
	}

	// Prepare SysEx midiIn buffer
	MidiInHdr.lpData = (LPSTR)sysexbuf;
	MidiInHdr.dwBufferLength = 4096;
	MidiInHdr.dwFlags = 0L;
	wResult = midiInPrepareHeader(hMidiIn, &MidiInHdr, sizeof(MIDIHDR));
	if (wResult != MMSYSERR_NOERROR) {
		QMessageBox::critical(NULL, "Win32MidiIn Error", "Failed to prepare MIDI buffer header");
		return false;
	}

	// Add SysEx Buffer
	wResult = midiInAddBuffer(hMidiIn, &MidiInHdr, sizeof(MIDIHDR));
	if (wResult != MMSYSERR_NOERROR) {
		QMessageBox::critical(NULL, "Win32MidiIn Error", "Failed to add SysEx buffer");
		return false;
	}
	return midiInStart(hMidiIn) == MMSYSERR_NOERROR;
}
Exemple #6
0
/*
 * Procedure definitions
 */
MMRESULT Midi_BufferDone(MIDI *midi, MIDIHDR *midiHdr)
{
    MMRESULT error;

    midiHdr->dwBytesRecorded = 0;
    error = midiInAddBuffer(midi->midiIn, midiHdr, sizeof(MIDIHDR));

    return error;
}
Exemple #7
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;
}
Exemple #8
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;
}
Exemple #9
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;
}
Exemple #10
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;
  }
}
Exemple #11
0
static PmError allocate_input_buffer(HMIDIIN h, long buffer_len)
{
    LPMIDIHDR hdr = allocate_buffer(buffer_len);
    if (!hdr) return pmInsufficientMemory;
    pm_hosterror = midiInPrepareHeader(h, hdr, sizeof(MIDIHDR));
    if (pm_hosterror) {
        pm_free(hdr);
        return pm_hosterror;
    }
    pm_hosterror = midiInAddBuffer(h, hdr, sizeof(MIDIHDR));
    return pm_hosterror;
}
Exemple #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));
	}
}
Exemple #13
0
void midiInitialize(char *inputDeviceStr, char *outputDeviceStr) {
  int inputDevice = atoi(inputDeviceStr);
  int outputDevice = atoi(outputDeviceStr);
  char name[256];
  getOutDeviceName(outputDevice, name, sizeof(name));
  unsigned long result = midiOutOpen(&outHandle, outputDevice, 0, 0, CALLBACK_NULL);
  if (result) {
    logPrintf(LOG_ERROR,
	      "Error opening output device %s with ID %d, aborting\n", name, outputDevice);
    exit(-1);
  } else {
    debugPrintf(1, "Opened output device %s.\n", name);
  }

  getInDeviceName(inputDevice, name, sizeof(name));
  result = midiInOpen(&inHandle, inputDevice, (DWORD)midiCallback, 0, CALLBACK_FUNCTION);
  if (result) {
    logPrintf(LOG_ERROR,
	      "Error opening input device %s with ID %d, aborting\n", name, inputDevice);
    exit(-1);
  } else {
    debugPrintf(1, "Opened input device %s.\n", name);
  }

  sleepCount = 0;
  
  midiHdr.lpData = inputBuffer;
  midiHdr.dwBufferLength = sizeof(inputBuffer);
  midiHdr.dwFlags = 0;
  result = midiInPrepareHeader(inHandle, &midiHdr, sizeof(MIDIHDR));

  if (result) {
    logPrintf(LOG_ERROR, "Could not prepare input buffer\n");
    exit(-1);
  }

  result = midiInAddBuffer(inHandle, &midiHdr, sizeof(MIDIHDR));

  if (result) {
    logPrintf(LOG_ERROR, "could not add input buffer\n");
    exit(-1);
  }

  result = midiInStart(inHandle);
  if (result) {
    logPrintf(LOG_ERROR, "Could not start recording on input\n");
    exit(-1);
  }
}
void MidiInputDeviceMme::MidiInputPortMme::MmeCallbackDispatcher(HMIDIIN handle, UINT uMsg, DWORD dwParam1, DWORD dwParam2) {

    unsigned char *DataPtr; // pointer to SysEx data
    unsigned char *data;  // pointer to standard MIDI messages which are not sysex data(max 3 bytes long)

    data = (unsigned char *)&dwParam1;

    switch(uMsg) {
        case MIM_DATA:
            DispatchRaw(data);
            break;

        case MIM_LONGDATA:
            if(!ExitFlag) {
                LPMIDIHDR lpMIDIHeader = (LPMIDIHDR)dwParam1;
                DataPtr = (unsigned char *)(lpMIDIHeader->lpData);
                if(lpMIDIHeader->dwBytesRecorded == 0) break;

                if(FirstSysExBlock) {
                    SysExOffset = 0;
                    FirstSysExBlock = false;
                }

                if( DataPtr[lpMIDIHeader->dwBytesRecorded - 1] == 0xF7) {
                        SysExMsgComplete = true;
                        FirstSysExBlock = true;
                }
                else {
                        SysExMsgComplete = false;
                }

                if(SysExOffset + lpMIDIHeader->dwBytesRecorded <= MME_MAX_SYSEX_BUF_SIZE) {
                    memcpy(&SysExBuf[SysExOffset], DataPtr, lpMIDIHeader->dwBytesRecorded);
                    SysExOffset += lpMIDIHeader->dwBytesRecorded;
                }

                if(SysExMsgComplete) DispatchSysex(SysExBuf, SysExOffset);

                /* Queue the MIDIHDR for more input, only if ExitFlag was not set otherwise we risk an infinite loop
                because when we call midiInReset() below, Windows will send a final  MIM_LONGDATA message to that callback.
    */
                midiInAddBuffer(MidiInHandle, lpMIDIHeader, sizeof(MIDIHDR));
            }
            break;
    }

}
Exemple #15
0
void CALLBACK Win32MidiIn::midiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
	Q_UNUSED(dwParam2);

	SynthRoute *synthRoute = (SynthRoute *)dwInstance;

	LPMIDIHDR pMIDIhdr = (LPMIDIHDR)dwParam1;
	if (wMsg == MIM_LONGDATA) {
		if (pMIDIhdr->dwBytesRecorded == 0) {
			// 0 length means returning the buffer to the application when closing
			return;
		}
		synthRoute->pushMIDISysex((BYTE *)pMIDIhdr->lpData, pMIDIhdr->dwBytesRecorded, MasterClock::getClockNanos());

		//	Add SysEx Buffer for reuse
		if (midiInAddBuffer(hMidiIn, pMIDIhdr, sizeof(MIDIHDR)) != MMSYSERR_NOERROR) {
			QMessageBox::critical(NULL, "Win32MidiIn Error", "Failed to add SysEx Buffer for reuse");
			return;
		}
		return;
	}
	if (wMsg == MIM_DATA) synthRoute->pushMIDIShortMessage(dwParam1, MasterClock::getClockNanos());
}
Exemple #16
0
void MidiUartWinClass::init(int _inputDevice, int _outputDevice) {
  MidiUartHostParent::init(_inputDevice, _outputDevice);
	
  unsigned long result;
  char name[256];
  getOutputDeviceName(outputDevice, name, sizeof(name));
  result = midiOutOpen(&outHandle, outputDevice, 0, 0, CALLBACK_NULL);
  if (result) {
    throw "Error opening utput device";
  } else {
    printf("Opened output device %s\n", name);
  }

  getInputDeviceName(inputDevice, name, sizeof(name));
  result = midiInOpen(&inHandle, inputDevice, (DWORD)midiCallback, (DWORD)this, CALLBACK_FUNCTION);
  if (result) {
    throw "Error opening input devic";
  } else {
    printf("Opening input device %s\n", name);
  }

  midiHdr.lpData = inputBuffer;
  midiHdr.dwBufferLength = sizeof(inputBuffer);
  midiHdr.dwFlags = 0;
  result = midiInPrepareHeader(inHandle, &midiHdr, sizeof(MIDIHDR));
  if (result) {
    throw "Could not prepare input buffer";
  }

  result = midiInAddBuffer(inHandle, &midiHdr, sizeof(MIDIHDR));
  if (result) {
    throw "Could not add input buffer";
  }

  result = midiInStart(inHandle);
  if (result) {
    throw "Could not start recording on input";
  }
}
Exemple #17
0
		MMRESULT Open(unsigned int deviceId)
		{
			// open midi input
			MMRESULT mmResult;
			mmResult = midiInOpen(&handle, deviceId, DWORD_PTR(Proc), NULL, CALLBACK_FUNCTION);
			if (mmResult)
			{
				char buf[256];
				GetLastErrorMessage(buf, 256);
				DebugPrint("Error opening MIDI input: %s", buf);
				return mmResult;
			}

			// prepare input buffer
			header.lpData = sysexbuffer;
			header.dwBufferLength = sizeof(sysexbuffer);
			header.dwFlags = 0;
			mmResult = midiInPrepareHeader(handle, &header, sizeof(MIDIHDR));
			if (mmResult)
			{
				char buf[256];
				GetLastErrorMessage(buf, 256);
				DebugPrint("Error preparing MIDI header: %s", buf);
				return mmResult;
			}

			// queue input buffer
			mmResult = midiInAddBuffer(handle, &header, sizeof(MIDIHDR));
			if (mmResult)
			{
				char buf[256];
				GetLastErrorMessage(buf, 256);
				DebugPrint("Error adding MIDI input buffer: %s", buf);
				return mmResult;
			}

			return mmResult;
		}
Exemple #18
0
static PmError winmm_in_open(PmInternal *midi, void *driverInfo)
{
    DWORD dwDevice;
    int i = midi->device_id;
    midiwinmm_type m;
    LPMIDIHDR hdr;
    dwDevice = (DWORD) descriptors[i].descriptor;

    /* create system dependent device data */
    m = (midiwinmm_type) pm_alloc(sizeof(midiwinmm_node)); /* create */
    midi->descriptor = m;
    if (!m) goto no_memory;
    m->handle.in = NULL;
    m->buffers = NULL;
    m->num_buffers = 0;
    m->next_buffer = 0;
    m->last_time = 0;
    m->first_message = TRUE; /* not used for input */
    m->sysex_mode = FALSE;
    m->sysex_word = 0;
    m->sysex_byte_count = 0;
    m->sync_time = 0;
    m->delta = 0;
    m->error = MMSYSERR_NOERROR;
    m->callback_error = MMSYSERR_NOERROR;

    /* open device */
    pm_hosterror = midiInOpen(&(m->handle.in), /* input device handle */
                      dwDevice, /* device ID */
                      (DWORD) winmm_in_callback, /* callback address */
                      (DWORD) midi, /* callback instance data */
                      CALLBACK_FUNCTION); /* callback is a procedure */
    if (pm_hosterror) goto free_descriptor;

    /* allocate first buffer for sysex data */
    hdr = allocate_buffer(PM_DEFAULT_SYSEX_BUFFER_SIZE);
    if (!hdr) goto close_device;
    pm_hosterror = midiInPrepareHeader(m->handle.in, hdr, sizeof(MIDIHDR));
    if (pm_hosterror) {
        pm_free(hdr);
        goto close_device;
    }
    pm_hosterror = midiInAddBuffer(m->handle.in, hdr, sizeof(MIDIHDR));
    if (pm_hosterror) goto close_device;

    /* allocate second buffer */
    hdr = allocate_buffer(PM_DEFAULT_SYSEX_BUFFER_SIZE);
    if (!hdr) goto close_device;
    pm_hosterror = midiInPrepareHeader(m->handle.in, hdr, sizeof(MIDIHDR));
    if (pm_hosterror) {
        pm_free(hdr);
        goto reset_device; /* because first buffer was added */
    }
    pm_hosterror = midiInAddBuffer(m->handle.in, hdr, sizeof(MIDIHDR));
    if (pm_hosterror) goto reset_device;

    /* start device */
    pm_hosterror = midiInStart(m->handle.in);
    if (pm_hosterror) goto reset_device;
    return pmNoError;

    /* undo steps leading up to the detected error */
reset_device:
    /* ignore return code (we already have an error to report) */
    midiInReset(m->handle.in); 
close_device:
    midiInClose(m->handle.in); /* ignore return code */
free_descriptor:
    midi->descriptor = NULL;
    pm_free(m);
no_memory:
    if (pm_hosterror) {
        int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, 
                                     PM_HOST_ERROR_MSG_LEN);
        assert(err == MMSYSERR_NOERROR);
        return pmHostError;
    }
    /* if !pm_hosterror, then the error must be pmInsufficientMemory */
    return pmInsufficientMemory;
    /* note: if we return an error code, the device will be
       closed and memory will be freed. It's up to the caller
       to free the parameter midi */
}
Exemple #19
0
/* Callback function executed via midiInput SW interrupt (via midiInOpen). */
static void FAR PASCAL winmm_in_callback(
     HMIDIIN hMidiIn,   /* midiInput device Handle */
     WORD wMsg,         /* midi msg */
     DWORD dwInstance,  /* application data */
     DWORD dwParam1,    /* MIDI data */
     DWORD dwParam2)    /* device timestamp (wrt most recent midiInStart) */
{
    static int entry = 0;   
    PmInternal *midi = (PmInternal *) dwInstance;
    midiwinmm_type m = (midiwinmm_type) midi->descriptor;

    if (++entry > 1) {
        assert(FALSE);
    } 

    /* for simplicity, this logic perhaps overly conservative */
    /* note also that this might leak memory if buffers are being
       returned as a result of midiInReset */
    if (m->callback_error) {
        entry--;
        return;
    }

    switch (wMsg) {
      case MIM_DATA: {
        /* 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 */

        long new_driver_time = dwParam2;

        if ((dwParam1 & 0x80) == 0) {
            /* not a status byte -- ignore it. This happens running the 
               sysex.c test under Win2K with MidiMan USB 1x1 interface.
               Is it a driver bug or a Win32 bug? If not, there's a bug
               here somewhere. -RBD
             */
        } else { /* data to process */
            PmEvent event;
            if (midi->time_proc) 
                dwParam2 = (*midi->time_proc)(midi->time_info);
            event.timestamp = dwParam2;
            event.message = dwParam1;
            pm_read_short(midi, &event);
        }
        break;  
      }
      case MIM_LONGDATA: {
        MIDIHDR *lpMidiHdr = (MIDIHDR *) dwParam1;
        unsigned char *data = lpMidiHdr->lpData;
        unsigned int i = 0;
        long size = sizeof(MIDIHDR) + lpMidiHdr->dwBufferLength;
        /* ignore sysex data, but free returned buffers */
        if (lpMidiHdr->dwBytesRecorded > 0 &&
            midi->filters & PM_FILT_SYSEX) {
                m->callback_error = midiInAddBuffer(hMidiIn, lpMidiHdr, 
                                                    sizeof(MIDIHDR));
                break; 
        }
        if (midi->time_proc)
            dwParam2 = (*midi->time_proc)(midi->time_info);

        while (i < lpMidiHdr->dwBytesRecorded) {
            /* collect bytes from *data into a word */
            pm_read_byte(midi, *data, dwParam2);
            data++;
            i++;
        }
        /* 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) {
            m->callback_error = midiInAddBuffer(hMidiIn, lpMidiHdr, 
                                                sizeof(MIDIHDR));
        } else {
            pm_free(lpMidiHdr);
        }
        break;
      }
      case MIM_OPEN: /* fall thru */
      case MIM_CLOSE:
      case MIM_ERROR: 
      case MIM_LONGERROR: 
      default:
        break;
    }
    entry--;
}
Exemple #20
0
static void CALLBACK MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
	MFDevice *pDevice = (MFDevice*)dwInstance;
	MFMidiPC_MidiInputDevice *pMidi = (MFMidiPC_MidiInputDevice*)pDevice->pInternal;

	switch(wMsg)
	{
		case MIM_OPEN:
			MFDebug_Log(0, MFStr("Opened MIDI input device: %s", pDevice->strings[MFDS_ID]));
			break;
		case MIM_CLOSE:
			MFDebug_Log(0, MFStr("Closed MIDI input device: %s", pDevice->strings[MFDS_ID]));
			break;
		case MIM_MOREDATA:
			MFDebug_Log(0, "MIDI message: MIM_MOREDATA");
			break;
		case MIM_DATA:
		{
			MFMidiEvent ev;
			MFMidi_DecodeShortMessage((uint32)dwParam1, &ev, (uint32)dwParam2);

			switch(ev.ev)
			{
				case MFMET_NoteOff:
					pMidi->channels[ev.channel].notes[ev.noteOff.note] = 0;
					break;
				case MFMET_NoteOn:
				case MFMET_NoteAftertouch:
					pMidi->channels[ev.channel].notes[ev.noteOn.note] = ev.noteOn.velocity;
					break;
				case MFMET_ControlChange:
					pMidi->channels[ev.channel].control[ev.controlChange.control] = ev.controlChange.value;
					break;
				case MFMET_ProgramChange:
					pMidi->channels[ev.channel].program = ev.programChange.program;
					break;
				case MFMET_ChannelAftertouch:
					// TODO: ... what is this?
					break;
				case MFMET_PitchBend:
					pMidi->channels[ev.channel].pitch = ev.pitchBend.value;
					break;
				default:
					MFDebug_Assert(false, "Why are we getting sys events?");
					break;
			}

			if (pMidi->bBuffered || pMidi->pEventCallback)
			{
				if (pMidi->bBuffered)
				{
					if (pMidi->numEvents >= pMidi->numAllocated)
					{
						pMidi->numAllocated *= 2;
						pMidi->pEvents = (MFMidiEvent*)MFHeap_Realloc(pMidi->pEvents, sizeof(MFMidiEvent)*pMidi->numAllocated);
					}

					pMidi->pEvents[pMidi->numEvents++] = ev;
				}
				if (pMidi->pEventCallback)
				{
					pMidi->pEventCallback(pDevice, &ev);
				}
			}
			break;
		}
		case MIM_LONGDATA:
		{
			MIDIHDR *pHdr = (MIDIHDR*)dwParam1;

			MFMidiEvent ev;
			MFMidi_DecodePacket((const uint8*)pHdr->lpData, pHdr->dwBytesRecorded, &ev, (uint32)dwParam2);

			if (pMidi->bBuffered || pMidi->pEventCallback)
			{
				if (pMidi->bBuffered)
				{
					if (pMidi->numEvents >= pMidi->numAllocated)
					{
						pMidi->numAllocated *= 2;
						pMidi->pEvents = (MFMidiEvent*)MFHeap_Realloc(pMidi->pEvents, sizeof(MFMidiEvent)*pMidi->numAllocated);
					}

					pMidi->pEvents[pMidi->numEvents++] = ev;
				}
				if (pMidi->pEventCallback)
				{
					pMidi->pEventCallback(pDevice, &ev);
				}
			}

			MMRESULT r = midiInAddBuffer(pMidi->hMidiIn, pHdr, sizeof(*pHdr));
			if (r != MMSYSERR_NOERROR)
			{
				wchar_t errorBuffer[256];
				midiInGetErrorText(r, errorBuffer, sizeof(errorBuffer));
				MFDebug_Warn(1, MFStr("Failed to open MIDI input device: %s", MFString_WCharAsUTF8(errorBuffer)));
			}
			break;
		}
		case MIM_ERROR:
		case MIM_LONGERROR:
		{
			MFDebug_Log(0, MFStr("MIDI input error: %d, 0x%08X : 0x%08X", wMsg, dwParam1, dwParam2));
			break;
		}
	}
}
Exemple #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;
  }
}
Exemple #22
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 = MHDR_DONE;
    mhdr.dwUser = 0x56FA552C;
    mhdr.dwBufferLength = 70000; /* > 64KB! */
    mhdr.dwBytesRecorded = 5;
    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));
        ok(mhdr.dwFlags == MHDR_DONE, "dwFlags=%x\n", mhdr.dwFlags);

        mhdr.dwFlags |= MHDR_INQUEUE;
        rc = midiInPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiInPrepare old size rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_INQUEUE|MHDR_DONE)/*w9x*/ ||
           mhdr.dwFlags == MHDR_PREPARED, "dwFlags=%x\n", mhdr.dwFlags);
        trace("MIDIHDR flags=%x when unsent\n", mhdr.dwFlags);

        mhdr.dwFlags |= MHDR_INQUEUE|MHDR_DONE;
        rc = midiInPrepareHeader(hm, &mhdr, sizeof(mhdr));
        ok(!rc, "midiInPrepare rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_INQUEUE|MHDR_DONE), "dwFlags=%x\n", mhdr.dwFlags);

        mhdr.dwFlags &= ~MHDR_INQUEUE;
        rc = midiInUnprepareHeader(hm, &mhdr, sizeof(mhdr));
        ok(!rc, "midiInUnprepare rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == MHDR_DONE, "dwFlags=%x\n", mhdr.dwFlags);

        mhdr.dwFlags &= ~MHDR_DONE;
        rc = midiInUnprepareHeader(hm, &mhdr, sizeof(mhdr));
        ok(!rc, "midiInUnprepare rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == 0, "dwFlags=%x\n", mhdr.dwFlags);

        rc = midiInPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiInPrepare rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == MHDR_PREPARED, "dwFlags=%x\n", mhdr.dwFlags);

        mhdr.dwFlags |= MHDR_DONE;
        rc = midiInPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiInPrepare rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwBytesRecorded == 5, "BytesRec=%u\n", mhdr.dwBytesRecorded);

        mhdr.dwFlags |= MHDR_DONE;
        rc = midiInAddBuffer(hm, &mhdr, sizeof(mhdr));
        ok(!rc, "midiAddBuffer rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_INQUEUE), "dwFlags=%x\n", mhdr.dwFlags);

        /* w95 does not set dwBytesRecorded=0 within midiInAddBuffer.  Wine does. */
        if (mhdr.dwBytesRecorded != 0)
            trace("dwBytesRecorded %u\n", mhdr.dwBytesRecorded);

        rc = midiInAddBuffer(hm, &mhdr, sizeof(mhdr));
        ok(rc==MIDIERR_STILLPLAYING, "midiAddBuffer rc=%s\n", mmsys_error(rc));

        rc = midiInPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiInPrepare rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_INQUEUE), "dwFlags=%x\n", mhdr.dwFlags);
    }
    rc = midiInReset(hm); /* Return any pending buffer */
    ok(!rc, "midiInReset rc=%s\n", mmsys_error(rc));
    test_notification(hwnd, "midiInReset", MIM_LONGDATA, (DWORD_PTR)&mhdr);

    ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_DONE), "dwFlags=%x\n", mhdr.dwFlags);
    rc = midiInUnprepareHeader(hm, &mhdr, sizeof(mhdr));
    ok(!rc, "midiInUnprepare rc=%s\n", mmsys_error(rc));

    ok(mhdr.dwBytesRecorded == 0, "Did some MIDI HW send %u bytes?\n", mhdr.dwBytesRecorded);

    rc = midiInClose(hm);
    ok(!rc, "midiInClose rc=%s\n", mmsys_error(rc));

    ok(mhdr.dwUser==0x56FA552C, "MIDIHDR.dwUser changed to %lx\n", mhdr.dwUser);
    HeapFree(GetProcessHeap(), 0, mhdr.lpData);
    test_notification(hwnd, "midiInClose", MIM_CLOSE, 0);
    test_notification(hwnd, "midiIn over", 0, WHATEVER);
}
//$$fb dwParam1 holds a pointer for long messages. How can that be a DWORD then ???
void CALLBACK MIDI_IN_PutMessage( HMIDIIN hMidiIn, UINT wMsg, UINT_PTR dwInstance, UINT_PTR dwParam1, UINT_PTR dwParam2 ) {

    MidiDeviceHandle* handle = (MidiDeviceHandle*) dwInstance;

    TRACE3("> MIDI_IN_PutMessage, hMidiIn: %x, wMsg: %x, dwInstance: %x\n", hMidiIn, wMsg, dwInstance);
    TRACE2("                      dwParam1: %x, dwParam2: %x\n", dwParam1, dwParam2);

    switch(wMsg) {

    case MIM_OPEN:
        TRACE0("< MIDI_IN_PutMessage: MIM_OPEN\n");
        break;

    case MIM_CLOSE:
        TRACE0("< MIDI_IN_PutMessage: MIM_CLOSE\n");
        break;

    case MIM_MOREDATA:
    case MIM_DATA:
        TRACE3("  MIDI_IN_PutMessage: MIM_MOREDATA or MIM_DATA. status=%x  data1=%x  data2=%x\n",
               dwParam1 & 0xFF, (dwParam1 & 0xFF00)>>8, (dwParam1 & 0xFF0000)>>16);
        if (handle!=NULL && handle->queue!=NULL && handle->platformData) {
            MIDI_QueueAddShort(handle->queue,
                               // queue stores packedMsg in big endian
                               //(dwParam1 << 24) | ((dwParam1 << 8) & 0xFF0000) | ((dwParam1 >> 8) & 0xFF00),
                               (UINT32) dwParam1,
                               // queue uses microseconds
                               ((INT64) dwParam2)*1000,
                               // overwrite if queue is full
                               TRUE);
            SetEvent((HANDLE) handle->platformData);
        }
        TRACE0("< MIDI_IN_PutMessage\n");
        break;

    case MIM_LONGDATA:
        TRACE1("  MIDI_IN_PutMessage: MIM_LONGDATA (%d bytes recorded)\n", (int) (((MIDIHDR*) dwParam1)->dwBytesRecorded));
        if (handle!=NULL && handle->queue!=NULL && handle->platformData) {
            MIDIHDR* hdr = (MIDIHDR*) dwParam1;
            TRACE2("  MIDI_IN_PutMessage: Adding to queue: index %d, %d bytes\n", (INT32) hdr->dwUser, hdr->dwBytesRecorded);
            MIDI_QueueAddLong(handle->queue,
                              (UBYTE*) hdr->lpData,
                              (UINT32) hdr->dwBytesRecorded,
                              // sysex buffer index
                              (INT32) hdr->dwUser,
                              // queue uses microseconds
                              ((INT64) dwParam2)*1000,
                              // overwrite if queue is full
                              TRUE);
            SetEvent((HANDLE) handle->platformData);
        }
        TRACE0("< MIDI_IN_PutMessage\n");
        break;

    case MIM_ERROR:
        ERROR0("< MIDI_IN_PutMessage: MIM_ERROR!\n");
        break;

    case MIM_LONGERROR:
        if (dwParam1 != 0) {
            MIDIHDR* hdr = (MIDIHDR*) dwParam1;
#ifdef USE_TRACE
            if (hdr->dwBytesRecorded > 0) {
                TRACE2("  MIDI_IN_PutMessage: MIM_LONGERROR! recorded: %d bytes with status 0x%2x\n",
                        hdr->dwBytesRecorded, (int) (*((UBYTE*) hdr->lpData)));
            }
#endif
            // re-add hdr to device query
            hdr->dwBytesRecorded = 0;
            midiInAddBuffer((HMIDIIN)handle->deviceHandle, hdr, sizeof(MIDIHDR));
        }
        ERROR0("< MIDI_IN_PutMessage: MIM_LONGERROR!\n");
        break;

    default:
        ERROR1("< MIDI_IN_PutMessage: ERROR unknown message %d!\n", wMsg);
        break;

    } // switch (wMsg)
}
Exemple #24
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;
    }
}
Exemple #25
0
COMMNG cmmidi_create(const OEMCHAR *midiout, const OEMCHAR *midiin,
													const OEMCHAR *module) {

	UINT		opened;
	UINT		id;
	void		(*shortout)(CMMIDI self, UINT32 msg);
	void		(*longout)(CMMIDI self, const UINT8 *msg, UINT leng);
	HMIDIFNOUT	out;
	HMIDIIN		hmidiin = NULL;
	COMMNG		ret;
	CMMIDI		midi;

	opened = 0;
	ZeroMemory(&out, sizeof(out));
	shortout = midi_ncshort;
	longout = midi_nclong;
	if (getmidioutid(midiout, &id) == SUCCESS) {
		if (midiOutOpen(&out.win32.hmidiout, id, 0, 0, CALLBACK_NULL)
														== MMSYSERR_NOERROR) {
			midiOutReset(out.win32.hmidiout);
			shortout = midi_win32short;
			longout = midi_win32long;
			opened |= CMMIDI_MIDIOUT;
		}
	}
	if (getmidiinid(midiin, &id) == SUCCESS) {
		if (midiInOpen(&hmidiin, id, (DWORD)g_hWndMain, 0, CALLBACK_WINDOW)
														== MMSYSERR_NOERROR) {
			midiInReset(hmidiin);
			opened |= CMMIDI_MIDIIN;
		}
	}
#if defined(VERMOUTH_LIB)
	else if (!milstr_cmp(midiout, cmmidi_vermouth)) {
		out.vermouth = midiout_create(vermouth_module, 512);
		if (out.vermouth != NULL) {
			shortout = midi_vermouthshort;
			longout = midi_vermouthlong;
			opened |= CMMIDI_VERMOUTH;
		}
	}
#endif
#if defined(MT32SOUND_DLL)
	else if (!milstr_cmp(midiout, cmmidi_mt32sound)) {
		if (mt32sound_open() == SUCCESS) {
			shortout = midi_mt32short;
			longout = midi_mt32long;
			opened |= CMMIDI_MT32SOUND;
		}
	}
#endif
	if (!opened) {
		goto cmcre_err1;
	}
	ret = (COMMNG)_MALLOC(sizeof(_COMMNG) + sizeof(_CMMIDI), "MIDI");
	if (ret == NULL) {
		goto cmcre_err2;
	}
	ret->connect = COMCONNECT_MIDI;
	ret->read = midiread;
	ret->write = midiwrite;
	ret->getstat = midigetstat;
	ret->msg = midimsg;
	ret->release = midirelease;
	midi = (CMMIDI)(ret + 1);
	ZeroMemory(midi, sizeof(_CMMIDI));
	midi->opened = opened;
	midi->shortout = shortout;
	midi->longout = longout;
	midi->out = out;
	midi->midictrl = MIDICTRL_READY;
#if 1
	midi->hmidiin = hmidiin;
	if (opened & CMMIDI_MIDIIN) {
		if (midiinhdlreg(midi, hmidiin) == SUCCESS) {
			midi->opened |= CMMIDI_MIDIINSTART;
			midi->hmidiinhdr.lpData = (char *)midi->midiinbuf;
			midi->hmidiinhdr.dwBufferLength = MIDI_BUFFER;
			midiInPrepareHeader(hmidiin, &midi->hmidiinhdr, sizeof(MIDIHDR));
			midiInAddBuffer(hmidiin, &midi->hmidiinhdr, sizeof(MIDIHDR));
			midiInStart(hmidiin);
		}
	}
#endif
#if defined(VERMOUTH_LIB)
	if (opened & CMMIDI_VERMOUTH) {
		sound_streamregist((void *)out.vermouth, (SOUNDCB)vermouth_getpcm);
	}
#endif
#if defined(MT32SOUND_DLL)
	if (opened & CMMIDI_MT32SOUND) {
		sound_streamregist(NULL, (SOUNDCB)mt32_getpcm);
	}
#endif
//	midi->midisyscnt = 0;
//	midi->mpos = 0;

	midi->midilast = 0x80;
//	midi->midiexcvwait = 0;
	midi->midimodule = (UINT8)module2number(module);
	FillMemory(midi->mch, sizeof(midi->mch), 0xff);
	return(ret);

cmcre_err2:
	if (opened & CMMIDI_MIDIOUT) {
		midiOutReset(out.win32.hmidiout);
		midiOutClose(out.win32.hmidiout);
	}
#if defined(VERMOUTH_LIB)
	if (opened & CMMIDI_VERMOUTH) {
		midiout_destroy(out.vermouth);
	}
#endif
#if defined(MT32SOUND_DLL)
	if (opened & CMMIDI_MT32SOUND) {
		mt32sound_close();
	}
#endif

cmcre_err1:
	return(NULL);
}
Exemple #26
0
 void write (HMIDIIN deviceHandle)
 {
     hdr.dwBytesRecorded = 0;
     MMRESULT res = midiInPrepareHeader (deviceHandle, &hdr, sizeof (hdr));
     res = midiInAddBuffer (deviceHandle, &hdr, sizeof (hdr));
 }
Exemple #27
0
static void CALLBACK midiInputCallback( HMIDIOUT hmin,
                                        UINT inputStatus, 
                                        DWORD instancePtr,
                                        DWORD midiMessage,
                                        DWORD timestamp )
{
  if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return;

  //RtMidiIn::RtMidiInData *data = static_cast<RtMidiIn::RtMidiInData *> (instancePtr);
  RtMidiIn::RtMidiInData *data = (RtMidiIn::RtMidiInData *)instancePtr;
  WinMidiData *apiData = static_cast<WinMidiData *> (data->apiData);

  // Calculate time stamp.
  apiData->message.timeStamp = 0.0;
  if ( data->firstMessage == true ) data->firstMessage = false;
  else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001;
  apiData->lastTime = timestamp;

  if ( inputStatus == MIM_DATA ) { // Channel or system message

    // Make sure the first byte is a status byte.
    unsigned char status = (unsigned char) (midiMessage & 0x000000FF);
    if ( !(status & 0x80) ) return;

    // Determine the number of bytes in the MIDI message.
    unsigned short nBytes = 1;
    if ( status < 0xC0 ) nBytes = 3;
    else if ( status < 0xE0 ) nBytes = 2;
    else if ( status < 0xF0 ) nBytes = 3;
    else if ( status < 0xF3 ) {
      // A MIDI time code message and we're ignoring it.
      if ( status == 0xF1 && (data->ignoreFlags & 0x02) ) return;
      nBytes = 3;
    }
    else if ( status == 0xF3 ) nBytes = 2;
    else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) {
      // A MIDI timing tick message and we're ignoring it.
      return;
    }
    else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) {
      // A MIDI active sensing message and we're ignoring it.
      return;
    }

    // Copy bytes to our MIDI message.
    unsigned char *ptr = (unsigned char *) &midiMessage;
    for ( int i=0; i<nBytes; ++i ) apiData->message.bytes.push_back( *ptr++ );
  }
  else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR )
    MIDIHDR *sysex = ( MIDIHDR *) midiMessage; 
    if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) {  
      // Sysex message and we're not ignoring it
      for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i )
        apiData->message.bytes.push_back( sysex->lpData[i] );
    }

    // The WinMM API requires that the sysex buffer be requeued after
    // input of each sysex message.  Even if we are ignoring sysex
    // messages, we still need to requeue the buffer in case the user
    // decides to not ignore sysex messages in the future.  However,
    // it seems that WinMM calls this function with an empty sysex
    // buffer when an application closes and in this case, we should
    // avoid requeueing it, else the computer suddenly reboots after
    // one or two minutes.
	if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) {
    //if ( sysex->dwBytesRecorded > 0 ) {
      MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) );
      if ( result != MMSYSERR_NOERROR )
        std::cerr << "\nRtMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n";

      if ( data->ignoreFlags & 0x01 ) return;
    }
    else return;
  }

  if ( data->usingCallback ) {
    RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
    callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData );
  }
  else {
    // As long as we haven't reached our queue size limit, push the message.
    if ( data->queueLimit > data->queue.size() )
      data->queue.push( apiData->message );
    else
      std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n";
  }

  // Clear the vector for the next input message.
  apiData->message.bytes.clear();
}
Exemple #28
0
MOboolean
moMidiDevice::Init( moText devicetext ) {

	SetName(devicetext);


#ifdef WIN32
/*
	BOOL		result;
	GUID		hidGUID;
	HDEVINFO	hardwareDeviceInfoSet;
	SP_DEVICE_INTERFACE_DATA	deviceInterfaceData;
	DWORD Index = 0;
	DWORD requiredSize;

	//Get the HID GUID value - used as mask to get list of devices
	HidD_GetHidGuid ( &hidGUID );

	//Get a list of devices matching the criteria (hid interface, present)
	hardwareDeviceInfoSet = SetupDiGetClassDevs (&hidGUID,
					NULL, // Define no enumerator (global)
					NULL, // Define no
					(DIGCF_PRESENT | DIGCF_ALLCLASSES |DIGCF_DEVICEINTERFACE));


	deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

	//Go through the list and get the interface data
	for(int i = 0; i < 10; i++)
	{
		result = SetupDiEnumDeviceInterfaces (hardwareDeviceInfoSet,
					NULL, //infoData,
					&hidGUID, //interfaceClassGuid,
					Index,
					&deviceInterfaceData);
		if (result == FALSE) {
			Index++;
		}
	}

	// Failed to get a device - possibly the index is larger than the number of devices
	if (result == FALSE) {
		SetupDiDestroyDeviceInfoList (hardwareDeviceInfoSet);
		return;// INVALID_HANDLE_VALUE;
	}

	//Get the details with null values to get the required size of the buffer
	SetupDiGetDeviceInterfaceDetail (hardwareDeviceInfoSet,
				&deviceInterfaceData,
				NULL, //interfaceDetail,
				0, //interfaceDetailSize,
				&requiredSize,
				0); //infoData))
*/

	MIDIINCAPS     moc;
	unsigned long   iNumDevs, i;



	/* Get the number of MIDI Out devices in this computer */
	iNumDevs = midiInGetNumDevs();

	if (iNumDevs==0) {
	    MODebug2->Message( moText("ERROR! NO MIDI DEVICES FOUND"));
    }

	/* Go through all of those devices, displaying their names */
	for (i = 0; i < iNumDevs; i++)
	{
		/* Get info about the next device */
		if (!midiInGetDevCaps(i, &moc, sizeof(MIDIINCAPS)))
		{
			/* Display its Device ID and name */
			MODebug2->Message( moText("Device ID #") + IntToStr(i) + moText(":") + moText(moc.szPname));
			if ( !stricmp(moc.szPname, devicetext) ) {
				m_DeviceId = i;
				break;
			}
		}
	}


	/*
	unsigned long result;
	HMIDIOUT      outHandle;

	// Open the MIDI Mapper
	result = midiOutOpen(&outHandle, i, 0, 0, CALLBACK_WINDOW);
	if (!result)
	{
		// Output the C note (ie, sound the note)
		midiOutShortMsg(outHandle, 0x00403C90);

		// Output the E note
		midiOutShortMsg(outHandle, 0x00404090);

		// Output the G note
		midiOutShortMsg(outHandle, 0x00404390);

		// Here you should insert a delay so that you can hear the notes sounding
		Sleep(1000);

		// Now let's turn off those 3 notes
		midiOutShortMsg(outHandle, 0x00003C90);
		midiOutShortMsg(outHandle, 0x00004090);
		midiOutShortMsg(outHandle, 0x00004390);

		 // Close the MIDI device
		 midiOutClose(outHandle);
	} else {
		printf("There was an error opening MIDI Mapper!\r\n");
	}
	*/
	HMIDIIN			handle;
	MIDIHDR			midiHdr;
	unsigned long	err;

	if (m_DeviceId!=-1) {
		/* Open default MIDI In device */
		if (!(err = midiInOpen(&handle, m_DeviceId, (DWORD)midiCallback, (DWORD)this, CALLBACK_FUNCTION)))
		{
			// Store pointer to our input buffer for System Exclusive messages in MIDIHDR
			midiHdr.lpData = (LPSTR)&SysXBuffer[0];

			// Store its size in the MIDIHDR
			midiHdr.dwBufferLength = sizeof(SysXBuffer);

			// Flags must be set to 0
			midiHdr.dwFlags = 0;

			// Prepare the buffer and MIDIHDR
			err = midiInPrepareHeader(handle, &midiHdr, sizeof(MIDIHDR));
			if (!err)
			{
				// Queue MIDI input buffer
				err = midiInAddBuffer(handle, &midiHdr, sizeof(MIDIHDR));
				if (!err)
				{
					// Start recording Midi
					err = midiInStart(handle);
					m_bInit = true;
					return true;
					/*
					if (!err)
					{
						// Wait for user to abort recording
						printf("Press any key to stop recording...\r\n\n");
						_getch();

						// We need to set a flag to tell our callback midiCallback()
						// not to do any more midiInAddBuffer(), because when we
						// call midiInReset() below, Windows will send a final
						// MIM_LONGDATA message to that callback. If we were to
						// allow midiCallback() to midiInAddBuffer() again, we'd
						// never get the driver to finish with our midiHdr

						SysXFlag |= 0x80;
						printf("\r\nRecording stopped!\n");
					}*/

					/* Stop recording */
					//midiInReset(handle);
				}
			}
	/*
			// If there was an error above, then print a message
			if (err) PrintMidiInErrorMsg(err);

			// Close the MIDI In device
			while ((err = midiInClose(handle)) == MIDIERR_STILLPLAYING) Sleep(0);
			if (err) PrintMidiInErrorMsg(err);

			// Unprepare the buffer and MIDIHDR. Unpreparing a buffer that has not been prepared is ok
			midiInUnprepareHeader(handle, &midiHdr, sizeof(MIDIHDR));
			*/
		}
		else
		{
			printf("Error opening the default MIDI In Device!\r\n");
			PrintMidiInErrorMsg(err);
			return false;
		}
	}

#else

#endif
		return false;
}
Exemple #29
0
void RtMidiIn :: openPort( unsigned int portNumber, const std::string /*portName*/ )
{
  if ( connected_ ) {
    errorString_ = "RtMidiIn::openPort: a valid connection already exists!";
    error( RtError::WARNING );
    return;
  }

  unsigned int nDevices = midiInGetNumDevs();
  if (nDevices == 0) {
    errorString_ = "RtMidiIn::openPort: no MIDI input sources found!";
    error( RtError::NO_DEVICES_FOUND );
  }

  std::ostringstream ost;
  if ( portNumber >= nDevices ) {
    ost << "RtMidiIn::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
    errorString_ = ost.str();
    error( RtError::INVALID_PARAMETER );
  }

  WinMidiData *data = static_cast<WinMidiData *> (apiData_);
  MMRESULT result = midiInOpen( &data->inHandle,
                                portNumber,
                                (DWORD)&midiInputCallback,
                                (DWORD)&inputData_,
                                CALLBACK_FUNCTION );
  if ( result != MMSYSERR_NOERROR ) {
    errorString_ = "RtMidiIn::openPort: error creating Windows MM MIDI input port.";
    error( RtError::DRIVER_ERROR );
  }

  // Allocate and init the sysex buffers.
  for ( int i=0; i<RT_SYSEX_BUFFER_COUNT; ++i ) {
    data->sysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ];
    data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ];
    data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE;
    data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator
    data->sysexBuffer[i]->dwFlags = 0;

    result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) );
    if ( result != MMSYSERR_NOERROR ) {
      midiInClose( data->inHandle );
      errorString_ = "RtMidiIn::openPort: error starting Windows MM MIDI input port (PrepareHeader).";
      error( RtError::DRIVER_ERROR );
    }

    // Register the buffer.
    result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) );
    if ( result != MMSYSERR_NOERROR ) {
      midiInClose( data->inHandle );
      errorString_ = "RtMidiIn::openPort: error starting Windows MM MIDI input port (AddBuffer).";
      error( RtError::DRIVER_ERROR );
    }
  }

  result = midiInStart( data->inHandle );
  if ( result != MMSYSERR_NOERROR ) {
    midiInClose( data->inHandle );
    errorString_ = "RtMidiIn::openPort: error starting Windows MM MIDI input port.";
    error( RtError::DRIVER_ERROR );
  }

  connected_ = true;
}
Exemple #30
0
void moMidiDevice::midiCallback(HMIDIIN handle, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
	LPMIDIHDR		lpMIDIHeader;
	unsigned char *	ptr;
	TCHAR			buffer[80];
	unsigned char 	bytes;
	moMidiDevice*	pMidiDevice = NULL;
	pMidiDevice = (moMidiDevice*)dwInstance;

	/* Determine why Windows called me */
	switch (uMsg)
	{
		/* Received some regular MIDI message */
		case MIM_DATA:
		{
			/* Display the time stamp, and the bytes. (Note: I always display 3 bytes even for
			Midi messages that have less) */
			sprintf(&buffer[0], "0x%08X 0x%02X 0x%02X 0x%02X\0", dwParam2, dwParam1 & 0x000000FF, (dwParam1>>8) & 0x000000FF, (dwParam1>>16) & 0x000000FF);

			_cputs(&buffer[0]);


			moMidiData		mididata;

			mididata.m_Type = MOMIDI_ROTARY;//????
			mididata.m_Channel = (dwParam1 & 0x000000FF) - 175;//channel 1 = 0xB0
			mididata.m_CC = (dwParam1>>8) & 0x000000FF;
			mididata.m_Val = (dwParam1>>16) & 0x000000FF;

			if (pMidiDevice) pMidiDevice->NewData( mididata );

			break;
		}

		/* Received all or part of some System Exclusive message */
		case MIM_LONGDATA:
		{
			/* If this application is ready to close down, then don't midiInAddBuffer() again */
			if (!(pMidiDevice->SysXFlag & 0x80))
			{
				/*	Assign address of MIDIHDR to a LPMIDIHDR variable. Makes it easier to access the
					field that contains the pointer to our block of MIDI events */
				lpMIDIHeader = (LPMIDIHDR)dwParam1;

				/* Get address of the MIDI event that caused this call */
				ptr = (unsigned char *)(lpMIDIHeader->lpData);

				/* Is this the first block of System Exclusive bytes? */
				if (!pMidiDevice->SysXFlag)
				{
					/* Print out a noticeable heading as well as the timestamp of the first block.
						(But note that other, subsequent blocks will have their own time stamps). */
					printf("*************** System Exclusive **************\r\n0x%08X ", dwParam2);

					/* Indicate we've begun handling a particular System Exclusive message */
					pMidiDevice->SysXFlag |= 0x01;
				}

				/* Is this the last block (ie, the end of System Exclusive byte is here in the buffer)? */
				if (*(ptr + (lpMIDIHeader->dwBytesRecorded - 1)) == 0xF7)
				{
					/* Indicate we're done handling this particular System Exclusive message */
					pMidiDevice->SysXFlag &= (~0x01);
				}

				/* Display the bytes -- 16 per line */
				bytes = 16;

				while((lpMIDIHeader->dwBytesRecorded--))
				{
					if (!(--bytes))
					{
						sprintf(&buffer[0], "0x%02X\r\n", *(ptr)++);
						bytes = 16;
					}
					else
						sprintf(&buffer[0], "0x%02X ", *(ptr)++);

					_cputs(&buffer[0]);
				}

				/* Was this the last block of System Exclusive bytes? */
				if (!pMidiDevice->SysXFlag)
				{
					/* Print out a noticeable ending */
					_cputs("\r\n******************************************\r\n");
				}

				/* Queue the MIDIHDR for more input */
				midiInAddBuffer(handle, lpMIDIHeader, sizeof(MIDIHDR));
			}

			break;
		}

		/* Process these messages if you desire */
/*
		case MIM_OPEN:
        case MIM_CLOSE:
        case MIM_ERROR:
        case MIM_LONGERROR:
        case MIM_MOREDATA:

			break;
*/
  }
}