wavedd.c
来自「Windows NT声卡驱动VXD」· C语言 代码 · 共 1,954 行 · 第 1/5 页
C
1,954 行
//
// Check the format
//
// FIXME
// Result = DeviceIoControl(
// hDev,
// IOCTL_WAVE_QUERY_FORMAT,
// (PVOID)Format,
// Format->wFormatTag == WAVE_FORMAT_PCM ?
// sizeof(PCMWAVEFORMAT) :
// sizeof(WAVEFORMATEX) + Format->cbSize,
// // Input buffer size
// NULL, // Output buffer
// 0, // Output buffer size
// &BytesReturned,
// NULL);
//
// Only a query so close the device
//
// CloseHandle(hDev);
Result = MMSYSERR_NOERROR;
return Result;
// ? MMSYSERR_NOERROR :
// GetLastError() == ERROR_NOT_SUPPORTED ? WAVERR_BADFORMAT :
// sndTranslateStatus();
}
//
// See if we've got this device already in our list (in
// which case we have a thread and events for it already made)
//
EnterCriticalSection(&esdDrvCritSec);
for (pClient = WaveHandleList;
pClient != NULL;
pClient = pClient->Next) {
if (pClient->DeviceNumber == id &&
pClient->DeviceType == DeviceType) {
//
// We already have a thread and resources for this device
//
if (pClient->hDev != INVALID_SOCKET) {
//
// Someone else is using it!
//
LeaveCriticalSection(&esdDrvCritSec);
return MMSYSERR_ALLOCATED;
}
break;
}
}
//
// allocate my per-client structure and zero it (LPTR).
//
if (pClient == NULL) {
pClient = (PWAVEALLOC)HeapAlloc(hHeap, 0, sizeof(WAVEALLOC));
if (pClient == NULL) {
LeaveCriticalSection(&esdDrvCritSec);
return MMSYSERR_NOMEM;
}
dprintf2(("Creating new device resource for device id %d, type %s",
id,
DeviceType == WaveInDevice ? "Wave Input" : "Wave Output"));
memset((PVOID)pClient, 0, sizeof(WAVEALLOC));
//
// Add it to the list
//
pClient->DeviceNumber = id;
pClient->DeviceType = DeviceType;
pClient->Next = WaveHandleList;
WaveHandleList = pClient;
}
//
// and fill it with info
//
pClient->dwCallback = ((LPWAVEOPENDESC)dwParam1)->dwCallback;
pClient->dwInstance = ((LPWAVEOPENDESC)dwParam1)->dwInstance;
pClient->hWave = ((LPWAVEOPENDESC)dwParam1)->hWave;
pClient->dwFlags = dwParam2;
pClient->hDev = INVALID_SOCKET;
pClient->DeviceQueue = NULL;
pClient->NextBuffer = NULL;
pClient->BufferPosition = 0;
pClient->BytesOutstanding = 0;
pClient->LoopHead = NULL;
pClient->LoopCount = 0;
//
// See if we can open our device
// We could get ERROR_BUSY if someone else is has the device open
// for writing.
//
// no critical section for this....
LeaveCriticalSection(&esdDrvCritSec);
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 2, 2 );
WSAStartup( wVersionRequested, &wsaData );
}
if (pClient->DeviceType == WaveOutDevice)
{
esd_format_t t;
t = 0;
if (Format->nChannels == 2)
t |= ESD_STEREO;
else
t |= ESD_MONO;
if (Format->wBitsPerSample == 8)
t |= ESD_BITS8;
else
if (Format->wBitsPerSample == 16)
t |= ESD_BITS16;
else
{
t |= ESD_BITS16;
}
pClient->hDev = esd_play_stream((t | ESD_STREAM | ESD_PLAY), Format->nSamplesPerSec, NULL, "WinESD");
}
else
{
esd_format_t t;
t = 0;
if (Format->nChannels == 2)
t |= ESD_STEREO;
else
t |= ESD_MONO;
if (Format->wBitsPerSample == 8)
t |= ESD_BITS8;
else
if (Format->wBitsPerSample == 16)
t |= ESD_BITS16;
else
{
t |= ESD_BITS8;
}
pClient->hDev = esd_record_stream((t | ESD_STREAM | ESD_PLAY), Format->nSamplesPerSec, NULL, "WinESD");
}
// mRet = sndOpenDev(DeviceType,
// id,
// &pClient->hDev,
// (GENERIC_READ | GENERIC_WRITE));
// if (mRet != MMSYSERR_NOERROR) {
if(pClient->hDev == INVALID_SOCKET)
return ERROR_BUSY;
Result = 1;
//
// Create our event for synchronization with the kernel driver
//
if (!pClient->Event) {
pClient->Event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pClient->Event == NULL) {
waveCleanUp(pClient);
return MMSYSERR_NOMEM;
}
//
// Create our event for our thread to wait on
//
pClient->AuxEvent1 = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!pClient->AuxEvent1) {
waveCleanUp(pClient);
return MMSYSERR_NOMEM;
}
//
// Create our event for waiting for the auxiliary thread
//
pClient->AuxEvent2 = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!pClient->AuxEvent2) {
waveCleanUp(pClient);
return MMSYSERR_NOMEM;
}
//
// Create our auxiliary thread for sending buffers to the driver
// and collecting Apcs
//
mRet = mmTaskCreate((LPTASKCALLBACK)waveThread,
&pClient->ThreadHandle,
(DWORD)pClient);
if (mRet != MMSYSERR_NOERROR) {
waveCleanUp(pClient);
return MMSYSERR_NOMEM;
}
//
// Make sure the thread has really started
//
WaitForSingleObject(pClient->AuxEvent2, INFINITE);
}
//
// give the client my driver dw
//
{
PWAVEALLOC *pUserHandle;
pUserHandle = (PWAVEALLOC *)dwUser;
*pUserHandle = pClient;
}
//
// sent client his OPEN callback message
//
waveCallback(pClient, DeviceType == WaveOutDevice ? WOM_OPEN : WIM_OPEN, 0L);
return MMSYSERR_NOERROR;
}
/****************************************************************************
* @doc INTERNAL
*
* @api void | waveCleanUp | Free resources for a wave device
*
* @parm PWAVEALLOC | pClient | Pointer to a WAVEALLOC structure describing
* resources to be freed.
*
* @rdesc There is no return value.
*
* @comm If the pointer to the resource is NULL then the resource has not
* been allocated.
***************************************************************************/
STATIC void waveCleanUp(PWAVEALLOC pClient)
{
EnterCriticalSection(&esdDrvCritSec);
if (pClient->hDev != INVALID_SOCKET) {
closesocket(pClient->hDev);
pClient->hDev = INVALID_SOCKET;
}
if (pClient->AuxEvent1) {
CloseHandle(pClient->AuxEvent1);
pClient->AuxEvent1 = NULL;
}
if (pClient->AuxEvent2) {
CloseHandle(pClient->AuxEvent2);
pClient->AuxEvent2 = NULL;
}
if (pClient->Event) {
CloseHandle(pClient->Event);
pClient->Event = NULL;
}
LeaveCriticalSection(&esdDrvCritSec);
}
/****************************************************************************
* @doc INTERNAL
*
* @api MMRESULT | waveWrite | Pass a new buffer to the Auxiliary thread for
* a wave device.
*
* @parm LPWAVEHDR | pHdr | Pointer to a wave buffer
*
* @parm PWAVEALLOC | pClient | The data associated with the logical wave
* device.
*
* @rdesc A MMSYS... type return code for the application.
*
* @comm The buffer flags are set and the buffer is passed to the auxiliary
* device task for processing.
***************************************************************************/
STATIC MMRESULT waveWrite(LPWAVEHDR pHdr, PWAVEALLOC pClient)
{
//
// Put the request at the end of our queue.
//
pHdr->dwFlags |= WHDR_INQUEUE;
pHdr->dwFlags &= ~WHDR_DONE;
pClient->AuxParam.pHdr = pHdr;
return waveThreadCall(WaveThreadAddBuffer, pClient);
}
/****************************************************************************
* @doc INTERNAL
*
* @api MMRESULT | waveSetState | Set a wave device to a given state
* This function is executed on the Auxiliary thread to synchronize
* correctly.
*
* @parm PWAVEALLOC | pClient | The data associated with the logical wave
* output device.
*
* @parm ULONG | State | The new state
*
* @rdesc A MMSYS... type return code for the application.
***************************************************************************/
STATIC MMRESULT waveSetState(PWAVEALLOC pClient, ULONG State)
{
// return sndSetHandleData(pClient->hDev,
// sizeof(State),
// &State,
// IOCTL_WAVE_SET_STATE,
// pClient->Event);
return MMSYSERR_NOERROR;
}
/****************************************************************************
* @doc INTERNAL
*
* @api void | waveBlockFinished | This function sets the done bit and invokes
* the callback function if there is one.
*
* @parm LPWAVEHDR | lpHdr | Far pointer to the header.
*
* @rdesc There is no return value.
***************************************************************************/
STATIC void waveBlockFinished(LPWAVEHDR lpHdr, DWORD MsgId)
{
PWAVEALLOC pWav;
D3(("blkfin: lpHdr = %x", lpHdr));
// Clear our private flag
lpHdr->dwFlags &= ~WHDR_COMPLETE;
// We are giving the block back to the application. The header is no
// longer in our queue, so we reset the WHDR_INQUEUE bit. Also, we
// clear our driver specific bit and cauterize the lpNext pointer.
lpHdr->dwFlags &= ~WHDR_INQUEUE;
lpHdr->lpNext = NULL;
pWav = (PWAVEALLOC)(lpHdr->reserved);
// set the 'done' bit - note that some people poll this bit.
lpHdr->dwFlags |= WHDR_DONE;
// invoke the callback function
waveCallback(pWav, MsgId, (DWORD)lpHdr);
}
/****************************************************************************
* @doc INTERNAL
*
* @api MMRESULT | waveThreadCall | Set the function for the thread to perform
* and 'call' the thread using the event pair mechanism.
*
* @parm WAVETHREADFUNCTION | Function | The function to perform
*
* @parm PWAVEALLOC | Our logical device data
*
* @rdesc An MMSYS... type return value suitable for returning to the
* application
*
* @comm The AuxParam field in the device data is the 'input' to
* the function processing loop in WaveThread().
***************************************************************************/
STATIC MMRESULT waveThreadCall(WAVETHREADFUNCTION Function, PWAVEALLOC pClient)
{
//
// Trap any failures
//
WinAssert(pClient->hDev != INVALID_SOCKET);
//
// Set the function code
//
pClient->AuxFunction = Function;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?