mididd.c
来自「Windows NT声卡驱动VXD」· C语言 代码 · 共 1,581 行 · 第 1/4 页
C
1,581 行
//
// Failed to add our buffer so give up and
// get our buffers back !
//
pClient->Mid->Bad = TRUE;
break;
}
}
//
// Set Device state. By issuing state changes on THIS
// thread the calling thread can be sure that all Apc's
// generated by buffer completions will complete
// BEFORE this function completes.
//
pClient->AuxReturnCode =
midiSetState(pClient, pClient->AuxParam.State);
//
// If this failed then get our buffers back,
// otherwise set our new state
//
if (pClient->AuxReturnCode != MMSYSERR_NOERROR) {
pClient->Mid->Bad = TRUE;
} else {
pClient->Mid->fMidiInStarted = TRUE;
}
} else {
//
// Already started or bad
//
}
break;
case MIDI_DD_STOP:
//
// Set Device state. By issuing state changes on THIS
// thread the calling thread can be sure that all Apc's
// generated by buffer completions will complete
// BEFORE this function completes.
//
if (pClient->Mid->fMidiInStarted) {
pClient->Mid->fMidiInStarted = FALSE;
//
// RESET so we get our buffers back
//
pClient->AuxReturnCode =
midiSetState(pClient, MIDI_DD_RESET);
WinAssert(!pClient->Mid->DeviceQueue);
if (pClient->AuxReturnCode == MMSYSERR_NOERROR) {
midSendPartBuffer(pClient);
}
}
break;
case MIDI_DD_RESET:
//
// Set Device state. By issuing state changes on THIS
// thread the calling thread can be sure that all Apc's
// generated by buffer completions will complete
// BEFORE this function completes.
//
if (pClient->Mid->fMidiInStarted) {
pClient->Mid->fMidiInStarted = FALSE;
pClient->AuxReturnCode =
midiSetState(pClient, pClient->AuxParam.State);
WinAssert(!pClient->Mid->DeviceQueue);
if (pClient->AuxReturnCode == MMSYSERR_NOERROR) {
pClient->Mid->Bad = FALSE; // Recovered !!
midSendPartBuffer(pClient);
}
}
//
// We zero the input queue anyway - compatibility with
// windows 3.1
//
midFreeQ(pClient);
break;
}
break;
case MidiThreadSetData:
{
pClient->AuxReturnCode =
sndSetHandleData(pClient->hDev,
pClient->AuxParam.GetSetData.DataLen,
pClient->AuxParam.GetSetData.pData,
pClient->AuxParam.GetSetData.Function,
pClient->Event);
}
break;
case MidiThreadClose:
//
// Try to complete.
// If we're completed all our buffers then we can.
// otherwise we can't
//
if (pClient->lpMIQueue == NULL) {
pClient->AuxReturnCode = MMSYSERR_NOERROR;
Close = TRUE;
} else {
pClient->AuxReturnCode = MIDIERR_STILLPLAYING;
}
break;
default:
WinAssert(FALSE); // Invalid call
break;
}
//
// Trap invalid callers
//
pClient->AuxFunction = MidiThreadInvalid;
//
// See if apcs completed
//
midiFlush(pClient);
//
// Release the caller
//
SetEvent(pClient->AuxEvent2);
//
// Complete ?
//
if (Close) {
break;
}
//
// Wait for more !
//
while (WaitForSingleObjectEx(pClient->AuxEvent1, INFINITE, TRUE) ==
WAIT_IO_COMPLETION) {
//
// Complete buffers whose Apcs ran
//
midiFlush(pClient);
}
}
//
// We've been asked to terminte
//
return 1;
}
/****************************************************************************
* @doc INTERNAL
*
* @api void | midiCallback | This calls DriverCallback for a MIDIHDR.
*
* @parm PMIDIALLOC | pMidi | Pointer to midi device.
*
* @parm DWORD | msg | The message.
*
* @parm DWORD | dw1 | message DWORD (dw2 is always set to 0).
*
* @rdesc There is no return value.
***************************************************************************/
void midiCallback(PMIDIALLOC pMidi, DWORD msg, DWORD dw1, DWORD dw2)
{
// invoke the callback function, if it exists. dwFlags contains
// midi driver specific flags in the LOWORD and generic driver
// flags in the HIWORD
if (pMidi->dwCallback)
DriverCallback(pMidi->dwCallback, // user's callback DWORD
HIWORD(pMidi->dwFlags), // callback flags
(HDRVR)pMidi->hMidi, // handle to the midi device
msg, // the message
pMidi->dwInstance, // user's instance data
dw1, // first DWORD
dw2); // second DWORD
}
/****************************************************************************
This function conforms to the standard Midi input driver message proc
(midMessage), which is documented in mmddk.d.
****************************************************************************/
DWORD APIENTRY midMessage(DWORD id, DWORD msg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
{
PMIDIALLOC pInClient;
switch (msg) {
case MIDM_GETNUMDEVS:
D2(("MIDM_GETNUMDEVS"));
return 0;
case MIDM_GETDEVCAPS:
D2(("MIDM_GETDEVCAPS"));
return midiGetDevCaps(id, MidiInDevice, (LPBYTE)dwParam1,
(DWORD)dwParam2);
case MIDM_OPEN:
D2(("MIDM_OPEN"));
return midiOpen(MidiInDevice, id, dwUser, dwParam1, dwParam2);
case MIDM_CLOSE:
D2(("MIDM_CLOSE"));
pInClient = (PMIDIALLOC)dwUser;
//
// Call our task to see if it's ready to complete
//
if (midiThreadCall(MidiThreadClose, pInClient) != 0L) {
return MIDIERR_STILLPLAYING;
}
//
// Wait for our thread to terminate and close our device
//
WaitForSingleObject(pInClient->ThreadHandle, INFINITE);
CloseHandle(pInClient->ThreadHandle);
//
// Tell the caller we're done
//
midiCallback(pInClient, MIM_CLOSE, 0L, 0L);
midiCleanUp(pInClient);
return MMSYSERR_NOERROR;
case MIDM_ADDBUFFER:
D2(("MIDM_ADDBUFFER"));
// check if it's been prepared
if (!(((LPMIDIHDR)dwParam1)->dwFlags & MHDR_PREPARED))
return MIDIERR_UNPREPARED;
WinAssert(!(((LPMIDIHDR)dwParam1)->dwFlags & MHDR_INQUEUE));
// if it is already in our Q, then we cannot do this
if ( ((LPMIDIHDR)dwParam1)->dwFlags & MHDR_INQUEUE )
return ( MIDIERR_STILLPLAYING );
// store the pointer to my MIDIALLOC structure in the midihdr
pInClient = (PMIDIALLOC)dwUser;
((LPMIDIHDR)dwParam1)->reserved = (DWORD)(LPSTR)pInClient;
return midiInWrite((LPMIDIHDR)dwParam1, pInClient);
case MIDM_STOP:
D2(("MIDM_PAUSE"));
pInClient = (PMIDIALLOC)dwUser;
pInClient->AuxParam.State = MIDI_DD_STOP;
return midiThreadCall(MidiThreadSetState, pInClient);
case MIDM_START:
D2(("MIDM_RESTART"));
pInClient = (PMIDIALLOC)dwUser;
pInClient->AuxParam.State = MIDI_DD_RECORD;
return midiThreadCall(MidiThreadSetState, pInClient);
case MIDM_RESET:
D2(("MIDM_RESET"));
pInClient = (PMIDIALLOC)dwUser;
pInClient->AuxParam.State = MIDI_DD_RESET;
return midiThreadCall(MidiThreadSetState, pInClient);
default:
return MMSYSERR_NOTSUPPORTED;
}
//
// Should not get here
//
WinAssert(0);
return MMSYSERR_NOTSUPPORTED;
}
/****************************************************************************
This function conforms to the standard Midi output driver message proc
(modMessage), which is documented in mmddk.d.
****************************************************************************/
DWORD APIENTRY modMessage(DWORD id, DWORD msg, DWORD dwUser, DWORD dwParam1,
DWORD dwParam2)
{
PMIDIALLOC pOutClient;
switch (msg) {
case MODM_GETNUMDEVS:
return 0;
// D2(("MODM_GETNUMDEVS"));
// return sndGetNumDevs(MidiOutDevice);
case MODM_GETDEVCAPS:
D2(("MODM_GETDEVCAPS"));
return midiGetDevCaps(id, MidiOutDevice, (LPBYTE)dwParam1,
(DWORD)dwParam2);
case MODM_OPEN:
D2(("MODM_OPEN"));
return midiOpen(MidiOutDevice, id, dwUser, dwParam1, dwParam2);
case MODM_CLOSE:
D2(("MODM_CLOSE"));
pOutClient = (PMIDIALLOC)dwUser;
midiCallback(pOutClient, MOM_CLOSE, 0L, 0L);
//
// Close our device
//
midiCleanUp(pOutClient);
return MMSYSERR_NOERROR;
case MODM_DATA:
D2(("MODM_DATA"));
{
int i;
BYTE b[4];
for (i = 0; i < 4; i ++) {
b[i] = (BYTE)(dwParam1 % 256);
dwParam1 /= 256;
}
return midiOutWrite(b, modMIDIlength((PMIDIALLOC)dwUser, b[0]),
(PMIDIALLOC)dwUser);
}
case MODM_LONGDATA:
D2(("MODM_LONGDATA"));
pOutClient = (PMIDIALLOC)dwUser;
{
LPMIDIHDR lpHdr;
MMRESULT mRet;
//
// check if it's been prepared
//
lpHdr = (LPMIDIHDR)dwParam1;
if (!(lpHdr->dwFlags & MHDR_PREPARED)) {
return MIDIERR_UNPREPARED;
}
//
//
//
mRet = midiOutWrite(lpHdr->lpData, lpHdr->dwBufferLength,
pOutClient);
// note that clearing the done bit or setting the inqueue bit
// isn't necessary here since this function is synchronous -
// the client will not get control back until it's done.
lpHdr->dwFlags |= MHDR_DONE;
// notify client
if (mRet == MMSYSERR_NOERROR) {
midiCallback(pOutClient, MOM_DONE, (DWORD)lpHdr, 0L);
}
return mRet;
}
case MODM_RESET:
D2(("MODM_RESET"));
return midiSetState((PMIDIALLOC)dwUser, MIDI_DD_RESET);
case MODM_SETVOLUME:
D2(("MODM_SETVOLUME"));
//pOutClient = (PMIDIALLOC)dwUser;
//pOutClient->AuxParam.GetSetData.pData = *(PBYTE *)&dwParam1;
//pOutClient->AuxParam.GetSetData.DataLen = sizeof(DWORD);
//pOutClient->AuxParam.GetSetData.Function = IOCTL_MIDI_SET_VOLUME;
//return midiThreadCall(MidiThreadSetData, pOutClient);
return sndSetData(MidiOutDevice, id, sizeof(DWORD),
(PBYTE)&dwParam1, IOCTL_MIDI_SET_VOLUME);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?