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

📄 wave.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
        if (dwSize + pClient->BytesOutstanding <= MAX_WAVE_BYTES) 
        {
            PWAVEOVL pWaveOvl;

            if (pClient->BufferPosition == 0) 
            {
                if (pClient->NextBuffer && (pClient->NextBuffer->dwFlags & WHDR_BEGINLOOP) &&
                    pClient->NextBuffer != pClient->LoopHead) 
                {
                    pClient->LoopCount = pClient->NextBuffer->dwLoops;
                    pClient->LoopHead = pClient->NextBuffer;                    
                    if (pClient->LoopCount > 0)                     
                        pClient->LoopCount--;                    
                }
                
                if (pClient->LoopCount == 0)                 
                    pClient->LoopHead = NULL;                
            }

            pWaveOvl = (PWAVEOVL)HeapAlloc(Heap, HEAP_ZERO_MEMORY, sizeof(*pWaveOvl));

            if (pWaveOvl == NULL) 
                return MMSYSERR_NOMEM;
            
            pWaveOvl->WaveHdr = pHdr;

            if (pClient->DeviceType == WaveOutDevice) 
            {
                Result =  WriteFileEx(pClient->hDev, 
                                      (PBYTE)pHdr->lpData + pClient->BufferPosition, 
                                      dwSize,
                                     (LPOVERLAPPED)pWaveOvl,
                                     (LPOVERLAPPED_COMPLETION_ROUTINE)
                                      (pHdr->dwBufferLength != 
                                      pClient->BufferPosition + dwSize ? wavePartialOvl : NULL != pClient->LoopHead ?
                                      waveLoopOvl : waveOvl));
            } 
            else if (pClient->DeviceType == WaveInDevice) 
            {
                Result =  ReadFileEx(pClient->hDev, (PBYTE)pHdr->lpData + pClient->BufferPosition,
                                     dwSize, (LPOVERLAPPED)pWaveOvl, 
                                     (LPOVERLAPPED_COMPLETION_ROUTINE)
                                     (pHdr->dwBufferLength !=
                                     pClient->BufferPosition + dwSize ? wavePartialOvl : NULL != pClient->LoopHead ?
                                     waveLoopOvl :  waveOvl));
            }

            
            if (!Result && GetLastError() != ERROR_IO_PENDING) 
            {
               HeapFree(Heap, 0, (LPSTR)pWaveOvl);
               
                if (pClient->BytesOutstanding == 0) 
                {
                    PWAVEHDR pHdr;
                    for (pHdr = pClient->DeviceQueue; pHdr != NULL; pHdr = pHdr->lpNext) 
                    {
                        pHdr->dwFlags |= WHDR_COMPLETE;
                    }
        
                    pClient->NextBuffer = NULL;
                    pClient->BufferPosition = 0;
                    
                }
                return TranslateStatus();

            } 
            else 
            {
                pClient->BufferPosition += dwSize;
                pClient->BytesOutstanding += dwSize;                
                if (pClient->BufferPosition == pHdr->dwBufferLength) 
                {
                
                    if (!pClient->LoopHead || !(pHdr->dwFlags & WHDR_ENDLOOP))                     
                        pClient->NextBuffer = pHdr->lpNext;                    
                    else 
                    {                    
                        if (pClient->LoopCount != 0) 
                        {                            
                            pClient->NextBuffer = pClient->LoopHead;
                            pClient->LoopCount--;
                        } 
                        else 
                        {
                            pClient->DummyWaveOvl.WaveHdr = pClient->LoopHead;

                            Result = WriteFileEx(pClient->hDev, (PVOID)pHdr->lpData, 0,
                                                 &pClient->DummyWaveOvl.Ovl, 
                                                 (LPOVERLAPPED_COMPLETION_ROUTINE)waveBreakOvl);

                            if (Result || GetLastError() == ERROR_IO_PENDING) 
                            {
                                pClient->NextBuffer = pHdr->lpNext;
                                pClient->LoopHead = NULL;
                                
                            }
                        }
                    }
                    pClient->BufferPosition = 0;
                }
            }
            

        } 
        else                         
          break;        
     }
    return MMSYSERR_NOERROR;
}
static MMRESULT waveSetState(PWAVEALLOC pClient, ULONG State)
{    
    OVERLAPPED Overlap;
    DWORD BytesReturned;

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

    Overlap.hEvent = pClient->Event;
    
    if (!DeviceIoControl(pClient->hDev, IOCTL_WAVE_SET_STATE, 
                         &State,  sizeof(State), NULL, 0, &BytesReturned, &Overlap)) 
    {
         DWORD cbTransfer;        
         if (GetLastError() == ERROR_IO_PENDING) 
         {
             if (!GetOverlappedResult(pClient->hDev, &Overlap, &cbTransfer, TRUE))             
                  return TranslateStatus();             
         } 
         else              
             return TranslateStatus();
         
    }

    while (SleepEx(0, TRUE) == WAIT_IO_COMPLETION) {}
    return MMSYSERR_NOERROR;
}

void wavePartialOvl(DWORD dwErrorCode, DWORD BytesTransferred, LPOVERLAPPED pOverlapped)
{
    LPWAVEHDR pHdr;
    PWAVEALLOC pClient;

    pHdr = ((PWAVEOVL)pOverlapped)->WaveHdr;    
    pClient = (PWAVEALLOC)pHdr->reserved;

  
    /* FIXME
    Assert(pHdr->dwFlags & WHDR_INQUEUE);
    Assert(!(pHdr->dwFlags & WHDR_COMPLETE));
    */    

    pClient->BytesOutstanding -= MAX_BUFFER_SIZE;

    if (pClient->DeviceType == WaveInDevice)     
        pHdr->dwBytesRecorded += BytesTransferred;
    HeapFree(Heap, 0, (LPSTR)pOverlapped);
}

void waveBreakOvl(DWORD dwErrorCode, DWORD BytesTransferred, LPOVERLAPPED pOverlapped)
{
    ((PWAVEOVL)pOverlapped)->WaveHdr->dwFlags |= WHDR_COMPLETE;
}

void waveLoopOvl(DWORD dwErrorCode, DWORD BytesTransferred, LPOVERLAPPED pOverlapped)
{
    DWORD dwFlags;
    PWAVEHDR pHdr;
    
    pHdr = ((PWAVEOVL)pOverlapped)->WaveHdr;
    dwFlags = pHdr->dwFlags;
    waveOvl(dwErrorCode, BytesTransferred, pOverlapped);
    pHdr->dwFlags = dwFlags;
}

void waveOvl(DWORD dwErrorCode, DWORD BytesTransferred, LPOVERLAPPED pOverlapped)
{
    PWAVEHDR pHdr;
    PWAVEALLOC pClient;

    pHdr = ((PWAVEOVL)pOverlapped)->WaveHdr;    
    pClient = (PWAVEALLOC)pHdr->reserved;

    /* FIXME
       Assert(pHdr->dwFlags & WHDR_INQUEUE);
       Assert(!(pHdr->dwFlags & WHDR_COMPLETE));
    */
   
    pHdr->dwFlags |= WHDR_COMPLETE;

    if (pHdr->dwFlags & WHDR_BEGINLOOP) 
    {
        PWAVEHDR pHdrSearch;
        for (pHdrSearch = pClient->DeviceQueue ; pHdrSearch != pHdr ; pHdrSearch = pHdrSearch->lpNext) 
        {
            //Assert(pHdrSearch != NULL);
            pHdrSearch->dwFlags |= WHDR_COMPLETE;
        }
    }
   
    if (pHdr->dwBufferLength)     
        pClient->BytesOutstanding -= (pHdr->dwBufferLength - 1) % MAX_BUFFER_SIZE + 1;
    
    if (pClient->DeviceType == WaveInDevice)     
        pHdr->dwBytesRecorded += BytesTransferred;
    
    HeapFree(Heap, 0, (LPSTR)pOverlapped);

}





static MMRESULT OpenWaveDevice(UINT  DeviceType,
								DWORD id,
								DWORD dwUser,
								DWORD dwParam1,
								DWORD dwParam2)
{
	// TODO: Implement
    PWAVEALLOC     pClient = (PWAVEALLOC)dwUser;  
    MMRESULT mResult;
    BOOL Result;
    DWORD BytesReturned;
    LPWAVEFORMATEX pFormats;
    PWAVEALLOC *pUserHandle = NULL;
    HANDLE hDevice;

    pFormats = (LPWAVEFORMATEX)((LPWAVEOPENDESC)dwParam1)->lpFormat;

    if (dwParam2 & WAVE_FORMAT_QUERY) 
    {        
        mResult = OpenDevice(DeviceType, id, &hDevice, GENERIC_READ);
        if (mResult != MMSYSERR_NOERROR) 
            return mResult;
        
        Result = DeviceIoControl(hDevice, IOCTL_WAVE_QUERY_FORMAT, (PVOID)pFormats,
                                 pFormats->wFormatTag == WAVE_FORMAT_PCM ?
                                 sizeof(PCMWAVEFORMAT) : sizeof(WAVEFORMATEX) + pFormats->cbSize,                        
                                 NULL, 0, &BytesReturned, NULL);
        CloseHandle(hDevice);
        return Result ? MMSYSERR_NOERROR : GetLastError() == ERROR_NOT_SUPPORTED ? WAVERR_BADFORMAT : TranslateStatus();
    }

    EnterCriticalSection(&CS);

    for (pClient = WaveLists; pClient != NULL; pClient = pClient->Next) 
    {
        if (pClient->DeviceNumber == id && pClient->DeviceType == DeviceType) 
        {        
            if (pClient->hDev != INVALID_HANDLE_VALUE) 
            {
                LeaveCriticalSection(&CS);
                return MMSYSERR_ALLOCATED;
            }
            break;
        }
    }

    if (pClient == NULL) 
    {
        pClient = (PWAVEALLOC)HeapAlloc(Heap, HEAP_ZERO_MEMORY, sizeof(WAVEALLOC));
        if (pClient == NULL) 
        {
            LeaveCriticalSection(&CS);
            return MMSYSERR_NOMEM;
        }
        
        pClient->DeviceNumber = id;
        pClient->Next = WaveLists;
        pClient->DeviceType = DeviceType;
        
        WaveLists = pClient;
    }

    pClient->hWave       = ((LPWAVEOPENDESC)dwParam1)->hWave;
    pClient->dwInstance  = ((LPWAVEOPENDESC)dwParam1)->dwInstance;
    pClient->dwFlags     = dwParam2;
    pClient->dwCallback  = ((LPWAVEOPENDESC)dwParam1)->dwCallback;
    pClient->hDev = INVALID_HANDLE_VALUE;
    pClient->NextBuffer  = NULL;
    pClient->DeviceQueue = NULL;
    pClient->LoopHead    = NULL;
    pClient->LoopCount   = 0;
    pClient->BytesOutstanding = 0;
    pClient->BufferPosition = 0;
    
    
    

    mResult = OpenDevice(DeviceType, id, &pClient->hDev, (GENERIC_READ | GENERIC_WRITE));

    if (mResult != MMSYSERR_NOERROR) 
    {    
        LeaveCriticalSection(&CS);
        return mResult;
    }

     if (!DeviceIoControl(pClient->hDev,IOCTL_WAVE_SET_FORMAT, (PVOID)pFormats,
                             pFormats->wFormatTag == WAVE_FORMAT_PCM ?
                             sizeof(PCMWAVEFORMAT) : sizeof(WAVEFORMATEX) + pFormats->cbSize,
                             NULL, 0, &BytesReturned, NULL))
    {
        CloseHandle(pClient->hDev);
        pClient->hDev = INVALID_HANDLE_VALUE;
        LeaveCriticalSection(&CS);
        return GetLastError() == ERROR_NOT_SUPPORTED ? WAVERR_BADFORMAT : TranslateStatus();
    }

    LeaveCriticalSection(&CS);

    if (!pClient->Event) 
    {
        pClient->Event = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (pClient->Event == NULL) 
        {
            // Cleanup
            return MMSYSERR_NOMEM;
        }

        pClient->AuxEvent1 = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (!pClient->AuxEvent1) 
        {
           // Cleanup
            return MMSYSERR_NOMEM;
        }

        pClient->AuxEvent2 = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (!pClient->AuxEvent2) 
        {
            // Cleanup
            return MMSYSERR_NOMEM;
        }


        mResult = mmTaskCreate((LPTASKCALLBACK)waveThread, &pClient->ThreadHandle, (DWORD)pClient);
        if ( mResult != MMSYSERR_NOERROR) 
        {
            // Cleanup
            return MMSYSERR_NOMEM;
        }

        WaitForSingleObject(pClient->AuxEvent2, INFINITE);
     }
     
     *pUserHandle = pClient;
      pUserHandle = (PWAVEALLOC *)dwUser;
   

     if (pClient->dwCallback)

⌨️ 快捷键说明

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