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 + -
显示快捷键?