⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wave.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 *
 * COPYRIGHT:            See COPYING in the top level directory
 * PROJECT:              ReactOS Multimedia
 * FILE:                 lib/mmdrv/wave.c
 * PURPOSE:              Multimedia User Mode Driver
 * PROGRAMMER:           Andrew Greenwood
 *                       Aleksey Bragin (aleksey at studiocerebral.com)
 * UPDATE HISTORY:
 *                       Jan 30, 2004: Imported into ReactOS tree (Greenwood)
 *                       Mar 16, 2004: Implemented some funcs (Bragin)
 */

#include "mmdrv.h"
#include "wave.h"

#define NDEBUG
#include <debug.h>

#define WHDR_COMPLETE 0x80000000
#define MAX_BUFFER_SIZE           8192  
#define MAX_WAVE_BYTES          5*MAX_BUFFER_SIZE  

PWAVEALLOC WaveLists; 

static MMRESULT waveReadWrite(PWAVEALLOC pClient);
void wavePartialOvl(DWORD dwErrorCode, DWORD BytesTransferred, LPOVERLAPPED pOverlapped);
void waveOvl(DWORD dwErrorCode, DWORD BytesTransferred, LPOVERLAPPED pOverlapped);
void waveLoopOvl(DWORD dwErrorCode, DWORD BytesTransferred, LPOVERLAPPED pOverlapped);
void waveBreakOvl(DWORD dwErrorCode, DWORD BytesTransferred, LPOVERLAPPED pOverlapped);
static MMRESULT waveSetState(PWAVEALLOC pClient, ULONG State);

/* ============================
 *  INTERNAL
 *  functions start here
 * ============================
 */

MMRESULT GetDeviceCapabilities(DWORD ID, UINT DeviceType,
                                      LPBYTE pCaps, DWORD Size)
{
    HANDLE DeviceHandle = NULL;
    MMRESULT Result = MMSYSERR_NOERROR;
    DWORD BytesReturned = 0;

    // Open the wave device

    Result = OpenDevice(DeviceType, ID, &DeviceHandle, GENERIC_READ);
    if (Result != MMSYSERR_NOERROR)
         return Result;

	if ((DeviceType == WaveOutDevice) || (DeviceType == WaveInDevice))
	{
		Result = DeviceIoControl(DeviceHandle, IOCTL_WAVE_GET_CAPABILITIES,
                            NULL, 0, (LPVOID)pCaps, Size,
                  &BytesReturned, NULL) ? MMSYSERR_NOERROR : TranslateStatus();
	}

	else if ((DeviceType == MidiInDevice) || (DeviceType == MidiOutDevice))
	{
	    Result = DeviceIoControl(DeviceHandle, IOCTL_MIDI_GET_CAPABILITIES,
                            NULL, 0, (LPVOID)pCaps, Size,
                  &BytesReturned, NULL) ? MMSYSERR_NOERROR : TranslateStatus();
	}

    else if (DeviceType == AuxDevice)
	{
	    Result = DeviceIoControl(DeviceHandle, IOCTL_AUX_GET_CAPABILITIES,
                            NULL, 0, (LPVOID)pCaps, Size,
                  &BytesReturned, NULL) ? MMSYSERR_NOERROR : TranslateStatus();
	}

    // Close the handle and return the result code
    CloseHandle(DeviceHandle);

    return Result;
}

static DWORD waveThread(LPVOID lpParameter)
{

    PWAVEALLOC pClient = (PWAVEALLOC)lpParameter;
    BOOL Terminate = FALSE;

    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
    SetEvent(pClient->AuxEvent2);
    WaitForSingleObject(pClient->AuxEvent1, INFINITE);

    for (;;) 
    {
        switch (pClient->AuxFunction) 
        {
            case WaveThreadAddBuffer:
                {
                 LPWAVEHDR *pHdrSearching;

                 if (pClient->DeviceType == WaveInDevice)             
                     pClient->AuxParam.pHdr->dwBytesRecorded = 0;
            
                 pHdrSearching = &pClient->DeviceQueue;
                 pClient->AuxParam.pHdr->lpNext = NULL;
                 
                 while (*pHdrSearching) 
                 {
                    pHdrSearching = &(*pHdrSearching)->lpNext;
                 }
                   
                 if (pClient->NextBuffer == NULL) 
                 {
                     pClient->BufferPosition = 0;
                     pClient->NextBuffer = pClient->AuxParam.pHdr;
                        
                 }

                 *pHdrSearching = pClient->AuxParam.pHdr;

                 pClient->AuxReturnCode = waveReadWrite(pClient);
                }
                 break;
                 
            case WaveThreadSetState:
                 pClient->AuxReturnCode = waveSetState(pClient, pClient->AuxParam.State);

                 if (pClient->AuxParam.State == WAVE_DD_RESET) 
                 {
                    PWAVEHDR pHdr;
              
                    pClient->LoopHead = NULL;
                    pClient->AuxReturnCode = MMSYSERR_NOERROR;                               
                    for (pHdr = pClient->DeviceQueue; pHdr != NULL; pHdr = pHdr->lpNext) 
                    {
                        pHdr->dwFlags |= WHDR_COMPLETE;
                    }
        
                    pClient->BufferPosition = 0;
                    pClient->NextBuffer = NULL;                    
                } 
                else 
                {
                    if (pClient->DeviceType == WaveInDevice && pClient->AuxReturnCode == MMSYSERR_NOERROR) 
                    {
                        if (pClient->AuxParam.State == WAVE_DD_STOP) 
                        {                        
                            if (pClient->DeviceQueue) 
                            {
                                while (!(pClient->DeviceQueue->dwFlags & WHDR_COMPLETE) &&
                                        pClient->BytesOutstanding != 0) 
                                {
                                    waveSetState(pClient, WAVE_DD_RECORD);
                                    pClient->AuxReturnCode = waveSetState(pClient, WAVE_DD_STOP);
                                    if (pClient->AuxReturnCode != MMSYSERR_NOERROR)                                     
                                        break;
                                    
                                }
                                if (pClient->AuxReturnCode == MMSYSERR_NOERROR) 
                                {
                                    pClient->DeviceQueue->dwFlags |= WHDR_COMPLETE;
                                    if (pClient->NextBuffer == pClient->DeviceQueue) 
                                    {
                                        pClient->NextBuffer = pClient->DeviceQueue->lpNext;
                                        pClient->BufferPosition = 0;
                                    }
                                }
                            }
                      } 
                      else 
                      {                      
                        if (pClient->AuxParam.State == WAVE_DD_RECORD) 
                                pClient->AuxReturnCode = waveReadWrite(pClient);                        
                      }
                    }
                 }

                 break;

            case WaveThreadGetData:                 
                 {
                    OVERLAPPED Overlap;
                    DWORD BytesReturned;

                    // FIXME
                    // Assert(hDev != NULL);

                    memset(&Overlap, 0, sizeof(Overlap));

                    Overlap.hEvent = pClient->Event;

                    if (!DeviceIoControl(pClient->hDev, pClient->AuxParam.GetSetData.Function, NULL, 0,
                         pClient->AuxParam.GetSetData.pData, pClient->AuxParam.GetSetData.DataLen,
                         &BytesReturned, &Overlap)) 
                    {
                        DWORD cbTransfer;

                        if (GetLastError() != ERROR_IO_PENDING) 
                            pClient->AuxReturnCode = TranslateStatus();
                        else
                        {

                            if (!GetOverlappedResult(pClient->hDev, &Overlap, &cbTransfer, TRUE))                         
                                pClient->AuxReturnCode = TranslateStatus();                        
                        } 
                    }
                    else
                    {
                        while (SetEvent(pClient->Event) && WaitForSingleObjectEx(pClient->Event, 0, TRUE) == 
                            WAIT_IO_COMPLETION) {}

                        pClient->AuxReturnCode = MMSYSERR_NOERROR;
                    }
                 }
                 break;

            case WaveThreadSetData:
                 {
                    OVERLAPPED Overlap;
                    DWORD BytesReturned;
                    memset((PVOID)&Overlap, 0, sizeof(Overlap));
                    Overlap.hEvent = pClient->Event;
    
                    if (!DeviceIoControl(pClient->hDev, pClient->AuxParam.GetSetData.Function, 
                                      pClient->AuxParam.GetSetData.pData, pClient->AuxParam.GetSetData.DataLen, 
                                      NULL, 0, &BytesReturned, &Overlap)) 
                    {
                        DWORD cbTransfer;
                        if (GetLastError() == ERROR_IO_PENDING) 
                        {
                            if (!GetOverlappedResult(pClient->hDev, &Overlap, &cbTransfer, TRUE))             
                                pClient->AuxReturnCode = TranslateStatus();             
                        } 
                        else              
                            pClient->AuxReturnCode = TranslateStatus();
         
                    }
                    else
                    { 
                        while (SleepEx(0, TRUE) == WAIT_IO_COMPLETION) {}

                        pClient->AuxReturnCode = MMSYSERR_NOERROR;
                    }
                 }                
                 break;

            case WaveThreadBreakLoop:
                 pClient->AuxReturnCode = MMSYSERR_NOERROR;
                 if (pClient->LoopHead)                 
                    pClient->LoopCount = 0;                          
                 break;

            case WaveThreadClose:
                 if (pClient->DeviceQueue != NULL)                  
                    pClient->AuxReturnCode = WAVERR_STILLPLAYING;                 
                 else                 
                    pClient->AuxReturnCode = MMSYSERR_NOERROR;                
                 break;

            case WaveThreadTerminate:
                 Terminate = TRUE;
                 break;

            default:
                 DPRINT("WaveThread Error");
                 break;

        }

        pClient->AuxFunction = WaveThreadInvalid;

        while (pClient->DeviceQueue && (pClient->DeviceQueue->dwFlags & WHDR_COMPLETE)) 
        {
            PWAVEHDR pHdr;        
            PWAVEALLOC pWav;

            pHdr = pClient->DeviceQueue;        
            pClient->DeviceQueue = pHdr->lpNext;
    
            pHdr->dwFlags &= ~WHDR_COMPLETE;
            pHdr->dwFlags &= ~WHDR_INQUEUE;
            pHdr->lpNext = NULL;
            pHdr->dwFlags |= WHDR_DONE;

            pWav = (PWAVEALLOC)pHdr->reserved;
                
            if (pWav->dwCallback)
            {
                DriverCallback(pWav->dwCallback, HIWORD(pWav->dwFlags), (HDRVR)pWav->hWave,  
                           pClient->DeviceType == WaveOutDevice ? WOM_DONE : WIM_DATA, 
                           pWav->dwInstance, (DWORD)pHdr, 0L); 
            }
        }

        waveReadWrite(pClient);

        if (Terminate) return 1; 
        SetEvent(pClient->AuxEvent2);
        while (WaitForSingleObjectEx(pClient->AuxEvent1, INFINITE, TRUE) == WAIT_IO_COMPLETION) 
        {
           while (pClient->DeviceQueue && (pClient->DeviceQueue->dwFlags & WHDR_COMPLETE)) 
           {
                PWAVEHDR pHdr;        
                PWAVEALLOC pWav;

                pHdr = pClient->DeviceQueue;        
                pClient->DeviceQueue = pHdr->lpNext;
    
                pHdr->dwFlags &= ~WHDR_COMPLETE;
                pHdr->dwFlags &= ~WHDR_INQUEUE;
                pHdr->lpNext = NULL;
                pHdr->dwFlags |= WHDR_DONE;

                pWav = (PWAVEALLOC)pHdr->reserved;
                
                if (pWav->dwCallback)
                {
                    DriverCallback(pWav->dwCallback, HIWORD(pWav->dwFlags), (HDRVR)pWav->hWave,  
                           pClient->DeviceType == WaveOutDevice ? WOM_DONE : WIM_DATA, 
                           pWav->dwInstance, (DWORD)pHdr, 0L); 
                }
            }

        waveReadWrite(pClient);
        }
    }


  return MMSYSERR_NOERROR;
}


static MMRESULT waveReadWrite(PWAVEALLOC pClient)
{
    DWORD dwSize;
    BOOL Result = FALSE;

   
    while (pClient->NextBuffer) 
    {
        PWAVEHDR pHdr;

        pHdr = pClient->NextBuffer;
        
        //FIXME
        //assert(!(pHdr->dwFlags & (WHDR_DONE | WHDR_COMPLETE)));
        //assert(pClient->DeviceQueue != NULL);
        

        dwSize = pHdr->dwBufferLength - pClient->BufferPosition;
        if (dwSize > MAX_BUFFER_SIZE)         
            dwSize = MAX_BUFFER_SIZE;
        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -