📄 wave.c
字号:
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 + -