3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS Multimedia
5 * FILE: lib/mmdrv/wave.c
6 * PURPOSE: Multimedia User Mode Driver
7 * PROGRAMMER: Andrew Greenwood
8 * Aleksey Bragin (aleksey at studiocerebral.com)
10 * Jan 30, 2004: Imported into ReactOS tree (Greenwood)
11 * Mar 16, 2004: Implemented some funcs (Bragin)
20 #define WHDR_COMPLETE 0x80000000
21 #define MAX_BUFFER_SIZE 8192
22 #define MAX_WAVE_BYTES 5*MAX_BUFFER_SIZE
26 static MMRESULT
waveReadWrite(PWAVEALLOC pClient
);
27 void wavePartialOvl(DWORD dwErrorCode
, DWORD BytesTransferred
, LPOVERLAPPED pOverlapped
);
28 void waveOvl(DWORD dwErrorCode
, DWORD BytesTransferred
, LPOVERLAPPED pOverlapped
);
29 void waveLoopOvl(DWORD dwErrorCode
, DWORD BytesTransferred
, LPOVERLAPPED pOverlapped
);
30 void waveBreakOvl(DWORD dwErrorCode
, DWORD BytesTransferred
, LPOVERLAPPED pOverlapped
);
31 static MMRESULT
waveSetState(PWAVEALLOC pClient
, ULONG State
);
33 /* ============================
35 * functions start here
36 * ============================
39 MMRESULT
GetDeviceCapabilities(DWORD ID
, UINT DeviceType
,
40 LPBYTE pCaps
, DWORD Size
)
42 HANDLE DeviceHandle
= NULL
;
43 MMRESULT Result
= MMSYSERR_NOERROR
;
44 DWORD BytesReturned
= 0;
46 // Open the wave device
48 Result
= OpenDevice(DeviceType
, ID
, &DeviceHandle
, GENERIC_READ
);
49 if (Result
!= MMSYSERR_NOERROR
)
52 if ((DeviceType
== WaveOutDevice
) || (DeviceType
== WaveInDevice
))
54 Result
= DeviceIoControl(DeviceHandle
, IOCTL_WAVE_GET_CAPABILITIES
,
55 NULL
, 0, (LPVOID
)pCaps
, Size
,
56 &BytesReturned
, NULL
) ? MMSYSERR_NOERROR
: TranslateStatus();
59 else if ((DeviceType
== MidiInDevice
) || (DeviceType
== MidiOutDevice
))
61 Result
= DeviceIoControl(DeviceHandle
, IOCTL_MIDI_GET_CAPABILITIES
,
62 NULL
, 0, (LPVOID
)pCaps
, Size
,
63 &BytesReturned
, NULL
) ? MMSYSERR_NOERROR
: TranslateStatus();
66 else if (DeviceType
== AuxDevice
)
68 Result
= DeviceIoControl(DeviceHandle
, IOCTL_AUX_GET_CAPABILITIES
,
69 NULL
, 0, (LPVOID
)pCaps
, Size
,
70 &BytesReturned
, NULL
) ? MMSYSERR_NOERROR
: TranslateStatus();
73 // Close the handle and return the result code
74 CloseHandle(DeviceHandle
);
79 static DWORD
waveThread(LPVOID lpParameter
)
82 PWAVEALLOC pClient
= (PWAVEALLOC
)lpParameter
;
83 BOOL Terminate
= FALSE
;
85 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
);
86 SetEvent(pClient
->AuxEvent2
);
87 WaitForSingleObject(pClient
->AuxEvent1
, INFINITE
);
91 switch (pClient
->AuxFunction
)
93 case WaveThreadAddBuffer
:
95 LPWAVEHDR
*pHdrSearching
;
97 if (pClient
->DeviceType
== WaveInDevice
)
98 pClient
->AuxParam
.pHdr
->dwBytesRecorded
= 0;
100 pHdrSearching
= &pClient
->DeviceQueue
;
101 pClient
->AuxParam
.pHdr
->lpNext
= NULL
;
103 while (*pHdrSearching
)
105 pHdrSearching
= &(*pHdrSearching
)->lpNext
;
108 if (pClient
->NextBuffer
== NULL
)
110 pClient
->BufferPosition
= 0;
111 pClient
->NextBuffer
= pClient
->AuxParam
.pHdr
;
115 *pHdrSearching
= pClient
->AuxParam
.pHdr
;
117 pClient
->AuxReturnCode
= waveReadWrite(pClient
);
121 case WaveThreadSetState
:
122 pClient
->AuxReturnCode
= waveSetState(pClient
, pClient
->AuxParam
.State
);
124 if (pClient
->AuxParam
.State
== WAVE_DD_RESET
)
128 pClient
->LoopHead
= NULL
;
129 pClient
->AuxReturnCode
= MMSYSERR_NOERROR
;
130 for (pHdr
= pClient
->DeviceQueue
; pHdr
!= NULL
; pHdr
= pHdr
->lpNext
)
132 pHdr
->dwFlags
|= WHDR_COMPLETE
;
135 pClient
->BufferPosition
= 0;
136 pClient
->NextBuffer
= NULL
;
140 if (pClient
->DeviceType
== WaveInDevice
&& pClient
->AuxReturnCode
== MMSYSERR_NOERROR
)
142 if (pClient
->AuxParam
.State
== WAVE_DD_STOP
)
144 if (pClient
->DeviceQueue
)
146 while (!(pClient
->DeviceQueue
->dwFlags
& WHDR_COMPLETE
) &&
147 pClient
->BytesOutstanding
!= 0)
149 waveSetState(pClient
, WAVE_DD_RECORD
);
150 pClient
->AuxReturnCode
= waveSetState(pClient
, WAVE_DD_STOP
);
151 if (pClient
->AuxReturnCode
!= MMSYSERR_NOERROR
)
155 if (pClient
->AuxReturnCode
== MMSYSERR_NOERROR
)
157 pClient
->DeviceQueue
->dwFlags
|= WHDR_COMPLETE
;
158 if (pClient
->NextBuffer
== pClient
->DeviceQueue
)
160 pClient
->NextBuffer
= pClient
->DeviceQueue
->lpNext
;
161 pClient
->BufferPosition
= 0;
168 if (pClient
->AuxParam
.State
== WAVE_DD_RECORD
)
169 pClient
->AuxReturnCode
= waveReadWrite(pClient
);
176 case WaveThreadGetData
:
182 // Assert(hDev != NULL);
184 memset(&Overlap
, 0, sizeof(Overlap
));
186 Overlap
.hEvent
= pClient
->Event
;
188 if (!DeviceIoControl(pClient
->hDev
, pClient
->AuxParam
.GetSetData
.Function
, NULL
, 0,
189 pClient
->AuxParam
.GetSetData
.pData
, pClient
->AuxParam
.GetSetData
.DataLen
,
190 &BytesReturned
, &Overlap
))
194 if (GetLastError() != ERROR_IO_PENDING
)
195 pClient
->AuxReturnCode
= TranslateStatus();
199 if (!GetOverlappedResult(pClient
->hDev
, &Overlap
, &cbTransfer
, TRUE
))
200 pClient
->AuxReturnCode
= TranslateStatus();
205 while (SetEvent(pClient
->Event
) && WaitForSingleObjectEx(pClient
->Event
, 0, TRUE
) ==
206 WAIT_IO_COMPLETION
) {}
208 pClient
->AuxReturnCode
= MMSYSERR_NOERROR
;
213 case WaveThreadSetData
:
217 memset((PVOID
)&Overlap
, 0, sizeof(Overlap
));
218 Overlap
.hEvent
= pClient
->Event
;
220 if (!DeviceIoControl(pClient
->hDev
, pClient
->AuxParam
.GetSetData
.Function
,
221 pClient
->AuxParam
.GetSetData
.pData
, pClient
->AuxParam
.GetSetData
.DataLen
,
222 NULL
, 0, &BytesReturned
, &Overlap
))
225 if (GetLastError() == ERROR_IO_PENDING
)
227 if (!GetOverlappedResult(pClient
->hDev
, &Overlap
, &cbTransfer
, TRUE
))
228 pClient
->AuxReturnCode
= TranslateStatus();
231 pClient
->AuxReturnCode
= TranslateStatus();
236 while (SleepEx(0, TRUE
) == WAIT_IO_COMPLETION
) {}
238 pClient
->AuxReturnCode
= MMSYSERR_NOERROR
;
243 case WaveThreadBreakLoop
:
244 pClient
->AuxReturnCode
= MMSYSERR_NOERROR
;
245 if (pClient
->LoopHead
)
246 pClient
->LoopCount
= 0;
249 case WaveThreadClose
:
250 if (pClient
->DeviceQueue
!= NULL
)
251 pClient
->AuxReturnCode
= WAVERR_STILLPLAYING
;
253 pClient
->AuxReturnCode
= MMSYSERR_NOERROR
;
256 case WaveThreadTerminate
:
261 DPRINT("WaveThread Error");
266 pClient
->AuxFunction
= WaveThreadInvalid
;
268 while (pClient
->DeviceQueue
&& (pClient
->DeviceQueue
->dwFlags
& WHDR_COMPLETE
))
273 pHdr
= pClient
->DeviceQueue
;
274 pClient
->DeviceQueue
= pHdr
->lpNext
;
276 pHdr
->dwFlags
&= ~WHDR_COMPLETE
;
277 pHdr
->dwFlags
&= ~WHDR_INQUEUE
;
279 pHdr
->dwFlags
|= WHDR_DONE
;
281 pWav
= (PWAVEALLOC
)pHdr
->reserved
;
283 if (pWav
->dwCallback
)
285 DriverCallback(pWav
->dwCallback
, HIWORD(pWav
->dwFlags
), (HDRVR
)pWav
->hWave
,
286 pClient
->DeviceType
== WaveOutDevice
? WOM_DONE
: WIM_DATA
,
287 pWav
->dwInstance
, (DWORD
)pHdr
, 0L);
291 waveReadWrite(pClient
);
293 if (Terminate
) return 1;
294 SetEvent(pClient
->AuxEvent2
);
295 while (WaitForSingleObjectEx(pClient
->AuxEvent1
, INFINITE
, TRUE
) == WAIT_IO_COMPLETION
)
297 while (pClient
->DeviceQueue
&& (pClient
->DeviceQueue
->dwFlags
& WHDR_COMPLETE
))
302 pHdr
= pClient
->DeviceQueue
;
303 pClient
->DeviceQueue
= pHdr
->lpNext
;
305 pHdr
->dwFlags
&= ~WHDR_COMPLETE
;
306 pHdr
->dwFlags
&= ~WHDR_INQUEUE
;
308 pHdr
->dwFlags
|= WHDR_DONE
;
310 pWav
= (PWAVEALLOC
)pHdr
->reserved
;
312 if (pWav
->dwCallback
)
314 DriverCallback(pWav
->dwCallback
, HIWORD(pWav
->dwFlags
), (HDRVR
)pWav
->hWave
,
315 pClient
->DeviceType
== WaveOutDevice
? WOM_DONE
: WIM_DATA
,
316 pWav
->dwInstance
, (DWORD
)pHdr
, 0L);
320 waveReadWrite(pClient
);
325 return MMSYSERR_NOERROR
;
329 static MMRESULT
waveReadWrite(PWAVEALLOC pClient
)
335 while (pClient
->NextBuffer
)
339 pHdr
= pClient
->NextBuffer
;
342 //assert(!(pHdr->dwFlags & (WHDR_DONE | WHDR_COMPLETE)));
343 //assert(pClient->DeviceQueue != NULL);
346 dwSize
= pHdr
->dwBufferLength
- pClient
->BufferPosition
;
347 if (dwSize
> MAX_BUFFER_SIZE
)
348 dwSize
= MAX_BUFFER_SIZE
;
351 if (dwSize
+ pClient
->BytesOutstanding
<= MAX_WAVE_BYTES
)
355 if (pClient
->BufferPosition
== 0)
357 if (pClient
->NextBuffer
&& (pClient
->NextBuffer
->dwFlags
& WHDR_BEGINLOOP
) &&
358 pClient
->NextBuffer
!= pClient
->LoopHead
)
360 pClient
->LoopCount
= pClient
->NextBuffer
->dwLoops
;
361 pClient
->LoopHead
= pClient
->NextBuffer
;
362 if (pClient
->LoopCount
> 0)
363 pClient
->LoopCount
--;
366 if (pClient
->LoopCount
== 0)
367 pClient
->LoopHead
= NULL
;
370 pWaveOvl
= (PWAVEOVL
)HeapAlloc(Heap
, HEAP_ZERO_MEMORY
, sizeof(*pWaveOvl
));
372 if (pWaveOvl
== NULL
)
373 return MMSYSERR_NOMEM
;
375 pWaveOvl
->WaveHdr
= pHdr
;
377 if (pClient
->DeviceType
== WaveOutDevice
)
379 Result
= WriteFileEx(pClient
->hDev
,
380 (PBYTE
)pHdr
->lpData
+ pClient
->BufferPosition
,
382 (LPOVERLAPPED
)pWaveOvl
,
383 (LPOVERLAPPED_COMPLETION_ROUTINE
)
384 (pHdr
->dwBufferLength
!=
385 pClient
->BufferPosition
+ dwSize
? wavePartialOvl
: NULL
!= pClient
->LoopHead
?
386 waveLoopOvl
: waveOvl
));
388 else if (pClient
->DeviceType
== WaveInDevice
)
390 Result
= ReadFileEx(pClient
->hDev
, (PBYTE
)pHdr
->lpData
+ pClient
->BufferPosition
,
391 dwSize
, (LPOVERLAPPED
)pWaveOvl
,
392 (LPOVERLAPPED_COMPLETION_ROUTINE
)
393 (pHdr
->dwBufferLength
!=
394 pClient
->BufferPosition
+ dwSize
? wavePartialOvl
: NULL
!= pClient
->LoopHead
?
395 waveLoopOvl
: waveOvl
));
399 if (!Result
&& GetLastError() != ERROR_IO_PENDING
)
401 HeapFree(Heap
, 0, (LPSTR
)pWaveOvl
);
403 if (pClient
->BytesOutstanding
== 0)
406 for (pHdr
= pClient
->DeviceQueue
; pHdr
!= NULL
; pHdr
= pHdr
->lpNext
)
408 pHdr
->dwFlags
|= WHDR_COMPLETE
;
411 pClient
->NextBuffer
= NULL
;
412 pClient
->BufferPosition
= 0;
415 return TranslateStatus();
420 pClient
->BufferPosition
+= dwSize
;
421 pClient
->BytesOutstanding
+= dwSize
;
422 if (pClient
->BufferPosition
== pHdr
->dwBufferLength
)
425 if (!pClient
->LoopHead
|| !(pHdr
->dwFlags
& WHDR_ENDLOOP
))
426 pClient
->NextBuffer
= pHdr
->lpNext
;
429 if (pClient
->LoopCount
!= 0)
431 pClient
->NextBuffer
= pClient
->LoopHead
;
432 pClient
->LoopCount
--;
436 pClient
->DummyWaveOvl
.WaveHdr
= pClient
->LoopHead
;
438 Result
= WriteFileEx(pClient
->hDev
, (PVOID
)pHdr
->lpData
, 0,
439 &pClient
->DummyWaveOvl
.Ovl
,
440 (LPOVERLAPPED_COMPLETION_ROUTINE
)waveBreakOvl
);
442 if (Result
|| GetLastError() == ERROR_IO_PENDING
)
444 pClient
->NextBuffer
= pHdr
->lpNext
;
445 pClient
->LoopHead
= NULL
;
450 pClient
->BufferPosition
= 0;
459 return MMSYSERR_NOERROR
;
461 static MMRESULT
waveSetState(PWAVEALLOC pClient
, ULONG State
)
466 memset((PVOID
)&Overlap
, 0, sizeof(Overlap
));
468 Overlap
.hEvent
= pClient
->Event
;
470 if (!DeviceIoControl(pClient
->hDev
, IOCTL_WAVE_SET_STATE
,
471 &State
, sizeof(State
), NULL
, 0, &BytesReturned
, &Overlap
))
474 if (GetLastError() == ERROR_IO_PENDING
)
476 if (!GetOverlappedResult(pClient
->hDev
, &Overlap
, &cbTransfer
, TRUE
))
477 return TranslateStatus();
480 return TranslateStatus();
484 while (SleepEx(0, TRUE
) == WAIT_IO_COMPLETION
) {}
485 return MMSYSERR_NOERROR
;
488 void wavePartialOvl(DWORD dwErrorCode
, DWORD BytesTransferred
, LPOVERLAPPED pOverlapped
)
493 pHdr
= ((PWAVEOVL
)pOverlapped
)->WaveHdr
;
494 pClient
= (PWAVEALLOC
)pHdr
->reserved
;
498 Assert(pHdr->dwFlags & WHDR_INQUEUE);
499 Assert(!(pHdr->dwFlags & WHDR_COMPLETE));
502 pClient
->BytesOutstanding
-= MAX_BUFFER_SIZE
;
504 if (pClient
->DeviceType
== WaveInDevice
)
505 pHdr
->dwBytesRecorded
+= BytesTransferred
;
506 HeapFree(Heap
, 0, (LPSTR
)pOverlapped
);
509 void waveBreakOvl(DWORD dwErrorCode
, DWORD BytesTransferred
, LPOVERLAPPED pOverlapped
)
511 ((PWAVEOVL
)pOverlapped
)->WaveHdr
->dwFlags
|= WHDR_COMPLETE
;
514 void waveLoopOvl(DWORD dwErrorCode
, DWORD BytesTransferred
, LPOVERLAPPED pOverlapped
)
519 pHdr
= ((PWAVEOVL
)pOverlapped
)->WaveHdr
;
520 dwFlags
= pHdr
->dwFlags
;
521 waveOvl(dwErrorCode
, BytesTransferred
, pOverlapped
);
522 pHdr
->dwFlags
= dwFlags
;
525 void waveOvl(DWORD dwErrorCode
, DWORD BytesTransferred
, LPOVERLAPPED pOverlapped
)
530 pHdr
= ((PWAVEOVL
)pOverlapped
)->WaveHdr
;
531 pClient
= (PWAVEALLOC
)pHdr
->reserved
;
534 Assert(pHdr->dwFlags & WHDR_INQUEUE);
535 Assert(!(pHdr->dwFlags & WHDR_COMPLETE));
538 pHdr
->dwFlags
|= WHDR_COMPLETE
;
540 if (pHdr
->dwFlags
& WHDR_BEGINLOOP
)
543 for (pHdrSearch
= pClient
->DeviceQueue
; pHdrSearch
!= pHdr
; pHdrSearch
= pHdrSearch
->lpNext
)
545 //Assert(pHdrSearch != NULL);
546 pHdrSearch
->dwFlags
|= WHDR_COMPLETE
;
550 if (pHdr
->dwBufferLength
)
551 pClient
->BytesOutstanding
-= (pHdr
->dwBufferLength
- 1) % MAX_BUFFER_SIZE
+ 1;
553 if (pClient
->DeviceType
== WaveInDevice
)
554 pHdr
->dwBytesRecorded
+= BytesTransferred
;
556 HeapFree(Heap
, 0, (LPSTR
)pOverlapped
);
564 static MMRESULT
OpenWaveDevice(UINT DeviceType
,
571 PWAVEALLOC pClient
= (PWAVEALLOC
)dwUser
;
575 LPWAVEFORMATEX pFormats
;
576 PWAVEALLOC
*pUserHandle
= NULL
;
579 pFormats
= (LPWAVEFORMATEX
)((LPWAVEOPENDESC
)dwParam1
)->lpFormat
;
581 if (dwParam2
& WAVE_FORMAT_QUERY
)
583 mResult
= OpenDevice(DeviceType
, id
, &hDevice
, GENERIC_READ
);
584 if (mResult
!= MMSYSERR_NOERROR
)
587 Result
= DeviceIoControl(hDevice
, IOCTL_WAVE_QUERY_FORMAT
, (PVOID
)pFormats
,
588 pFormats
->wFormatTag
== WAVE_FORMAT_PCM
?
589 sizeof(PCMWAVEFORMAT
) : sizeof(WAVEFORMATEX
) + pFormats
->cbSize
,
590 NULL
, 0, &BytesReturned
, NULL
);
591 CloseHandle(hDevice
);
592 return Result
? MMSYSERR_NOERROR
: GetLastError() == ERROR_NOT_SUPPORTED
? WAVERR_BADFORMAT
: TranslateStatus();
595 EnterCriticalSection(&CS
);
597 for (pClient
= WaveLists
; pClient
!= NULL
; pClient
= pClient
->Next
)
599 if (pClient
->DeviceNumber
== id
&& pClient
->DeviceType
== DeviceType
)
601 if (pClient
->hDev
!= INVALID_HANDLE_VALUE
)
603 LeaveCriticalSection(&CS
);
604 return MMSYSERR_ALLOCATED
;
612 pClient
= (PWAVEALLOC
)HeapAlloc(Heap
, HEAP_ZERO_MEMORY
, sizeof(WAVEALLOC
));
615 LeaveCriticalSection(&CS
);
616 return MMSYSERR_NOMEM
;
619 pClient
->DeviceNumber
= id
;
620 pClient
->Next
= WaveLists
;
621 pClient
->DeviceType
= DeviceType
;
626 pClient
->hWave
= ((LPWAVEOPENDESC
)dwParam1
)->hWave
;
627 pClient
->dwInstance
= ((LPWAVEOPENDESC
)dwParam1
)->dwInstance
;
628 pClient
->dwFlags
= dwParam2
;
629 pClient
->dwCallback
= ((LPWAVEOPENDESC
)dwParam1
)->dwCallback
;
630 pClient
->hDev
= INVALID_HANDLE_VALUE
;
631 pClient
->NextBuffer
= NULL
;
632 pClient
->DeviceQueue
= NULL
;
633 pClient
->LoopHead
= NULL
;
634 pClient
->LoopCount
= 0;
635 pClient
->BytesOutstanding
= 0;
636 pClient
->BufferPosition
= 0;
641 mResult
= OpenDevice(DeviceType
, id
, &pClient
->hDev
, (GENERIC_READ
| GENERIC_WRITE
));
643 if (mResult
!= MMSYSERR_NOERROR
)
645 LeaveCriticalSection(&CS
);
649 if (!DeviceIoControl(pClient
->hDev
,IOCTL_WAVE_SET_FORMAT
, (PVOID
)pFormats
,
650 pFormats
->wFormatTag
== WAVE_FORMAT_PCM
?
651 sizeof(PCMWAVEFORMAT
) : sizeof(WAVEFORMATEX
) + pFormats
->cbSize
,
652 NULL
, 0, &BytesReturned
, NULL
))
654 CloseHandle(pClient
->hDev
);
655 pClient
->hDev
= INVALID_HANDLE_VALUE
;
656 LeaveCriticalSection(&CS
);
657 return GetLastError() == ERROR_NOT_SUPPORTED
? WAVERR_BADFORMAT
: TranslateStatus();
660 LeaveCriticalSection(&CS
);
664 pClient
->Event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
665 if (pClient
->Event
== NULL
)
668 return MMSYSERR_NOMEM
;
671 pClient
->AuxEvent1
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
672 if (!pClient
->AuxEvent1
)
675 return MMSYSERR_NOMEM
;
678 pClient
->AuxEvent2
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
679 if (!pClient
->AuxEvent2
)
682 return MMSYSERR_NOMEM
;
686 mResult
= mmTaskCreate((LPTASKCALLBACK
)waveThread
, &pClient
->ThreadHandle
, (DWORD
)pClient
);
687 if ( mResult
!= MMSYSERR_NOERROR
)
690 return MMSYSERR_NOMEM
;
693 WaitForSingleObject(pClient
->AuxEvent2
, INFINITE
);
696 *pUserHandle
= pClient
;
697 pUserHandle
= (PWAVEALLOC
*)dwUser
;
700 if (pClient
->dwCallback
)
702 DriverCallback(pClient
->dwCallback
, HIWORD(pClient
->dwFlags
),
703 (HDRVR
)pClient
->hWave
, DeviceType
== WaveOutDevice
? WOM_OPEN
: WIM_OPEN
,
704 pClient
->dwInstance
, 0L, 0L);
707 return MMSYSERR_NOERROR
;
711 //FIXME: MS-specific code, except for name of the func!
712 MMRESULT
GetPositionWaveDevice(PWAVEALLOC pClient
, LPMMTIME lpmmt
, DWORD dwSize
)
715 WAVE_DD_POSITION PositionData;
718 if (dwSize < sizeof(MMTIME))
719 return MMSYSERR_ERROR;
722 // Get the current position from the driver
724 mErr = sndGetHandleData(pClient->hDev,
725 sizeof(PositionData),
727 IOCTL_WAVE_GET_POSITION,
730 if (mErr == MMSYSERR_NOERROR) {
731 if (lpmmt->wType == TIME_BYTES) {
732 lpmmt->u.cb = PositionData.ByteCount;
735 // default is samples.
737 lpmmt->wType = TIME_SAMPLES;
738 lpmmt->u.sample = PositionData.SampleCount;
742 return mErr;*/ return MMSYSERR_NOERROR
;
747 MMRESULT
soundSetData(UINT DeviceType
, UINT DeviceId
, UINT Length
, PBYTE Data
,
754 Result
= OpenDevice(DeviceType
, DeviceId
, &hDevcie
, GENERIC_READ
);
755 if (Result
!= MMSYSERR_NOERROR
)
758 Result
= DeviceIoControl(hDevcie
, Ioctl
, Data
, Length
, NULL
, 0, &BytesReturned
, NULL
) ?
759 MMSYSERR_NOERROR
: TranslateStatus();
760 CloseHandle(hDevcie
);
765 MMRESULT
soundGetData(UINT DeviceType
, UINT DeviceId
, UINT Length
, PBYTE Data
,
772 Result
= OpenDevice(DeviceType
, DeviceId
, &hDevice
, GENERIC_READ
);
773 if (Result
!= MMSYSERR_NOERROR
)
776 Result
= DeviceIoControl(hDevice
, Ioctl
, NULL
, 0, (LPVOID
)Data
, Length
,
777 &BytesReturned
, NULL
) ? MMSYSERR_NOERROR
: TranslateStatus();
778 CloseHandle(hDevice
);
783 /* ============================
785 * functions start here
786 * ============================
792 APIENTRY DWORD
wodMessage(DWORD dwId
, DWORD dwMessage
, DWORD dwUser
, DWORD dwParam1
, DWORD dwParam2
)
794 PWAVEALLOC pTask
= (PWAVEALLOC
)dwUser
;
797 case WODM_GETNUMDEVS
:
798 DPRINT("WODM_GETNUMDEVS");
799 return GetDeviceCount(WaveOutDevice
);
801 case WODM_GETDEVCAPS
:
802 DPRINT("WODM_GETDEVCAPS");
803 return GetDeviceCapabilities(dwId
, WaveOutDevice
, (LPBYTE
)dwParam1
,
808 return OpenWaveDevice(WaveOutDevice
, dwId
, dwUser
, dwParam1
, dwParam2
);
812 DPRINT("WODM_CLOSE");
814 // 1. Check if the task is ready to complete
815 pTask
->AuxFunction
= WaveThreadClose
;
816 SetEvent(pTask
->AuxEvent1
);
817 WaitForSingleObject(pTask
->AuxEvent2
, INFINITE
);
819 if ( pTask
->AuxReturnCode
!= MMSYSERR_NOERROR
)
821 return pTask
->AuxReturnCode
;
826 if (pTask
->dwCallback
)
828 DriverCallback(pTask
->dwCallback
, HIWORD(pTask
->dwFlags
), (HDRVR
)pTask
->hWave
,
829 WOM_CLOSE
, pTask
->dwInstance
, 0L, 0L);
834 // 2. Close the device
835 if (pTask
->hDev
!= INVALID_HANDLE_VALUE
) {
836 CloseHandle(pTask
->hDev
);
838 EnterCriticalSection(&CS
);
839 pTask
->hDev
= INVALID_HANDLE_VALUE
;
840 LeaveCriticalSection(&CS
);
843 return MMSYSERR_NOERROR
;
848 LPWAVEHDR pWaveHdr
= (LPWAVEHDR
)dwParam1
;
850 DPRINT("WODM_WRITE");
853 return MMSYSERR_INVALPARAM
;
855 if ((pWaveHdr
->dwFlags
& ~(WHDR_INQUEUE
|WHDR_DONE
|WHDR_PREPARED
|WHDR_BEGINLOOP
|WHDR_ENDLOOP
)))
856 return MMSYSERR_INVALPARAM
;
858 pWaveHdr
->dwFlags
&= (WHDR_INQUEUE
|WHDR_DONE
|WHDR_PREPARED
|WHDR_BEGINLOOP
|WHDR_ENDLOOP
);
860 if ((pWaveHdr
->dwFlags
& WHDR_PREPARED
) == 0)
861 return MMSYSERR_INVALPARAM
;
863 // Check, if the wave header is already prepared
864 if (!(pWaveHdr
->dwFlags
& WHDR_PREPARED
))
865 return WAVERR_UNPREPARED
;
867 // If it's already located in the queue, this op is impossible
868 if (pWaveHdr
->dwFlags
& WHDR_INQUEUE
)
869 return ( WAVERR_STILLPLAYING
);
871 // save WAVEALLOC pointer in the WaveHeader
872 pWaveHdr
->reserved
= dwUser
;
875 pWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
876 pWaveHdr
->dwFlags
&= ~WHDR_DONE
;
877 pTask
->AuxParam
.pHdr
= pWaveHdr
;
879 pTask
->AuxFunction
= WaveThreadAddBuffer
;
880 SetEvent(pTask
->AuxEvent1
);
881 WaitForSingleObject(pTask
->AuxEvent2
, INFINITE
);
882 return pTask
->AuxReturnCode
;
886 DPRINT("WODM_PAUSE");
887 pTask
->AuxParam
.State
= WAVE_DD_STOP
;
889 pTask
->AuxFunction
= WaveThreadSetState
;
890 SetEvent(pTask
->AuxEvent1
);
891 WaitForSingleObject(pTask
->AuxEvent2
, INFINITE
);
892 return pTask
->AuxReturnCode
;
895 DPRINT("WODM_RESTART");
896 pTask
->AuxParam
.State
= WAVE_DD_PLAY
;
898 pTask
->AuxFunction
= WaveThreadSetState
;
899 SetEvent(pTask
->AuxEvent1
);
900 WaitForSingleObject(pTask
->AuxEvent2
, INFINITE
);
901 return pTask
->AuxReturnCode
;
904 DPRINT("WODM_RESET");
905 pTask
->AuxParam
.State
= WAVE_DD_RESET
;
907 pTask
->AuxFunction
= WaveThreadSetState
;
908 SetEvent(pTask
->AuxEvent1
);
909 WaitForSingleObject(pTask
->AuxEvent2
, INFINITE
);
910 return pTask
->AuxReturnCode
;
913 DPRINT("WODM_BREAKLOOP");
915 pTask
->AuxFunction
= WaveThreadBreakLoop
;
916 SetEvent(pTask
->AuxEvent1
);
917 WaitForSingleObject(pTask
->AuxEvent2
, INFINITE
);
918 return pTask
->AuxReturnCode
;
921 DPRINT("WODM_GETPOS");
922 return GetPositionWaveDevice(pTask
, (LPMMTIME
)dwParam1
, dwParam2
);
925 DPRINT("WODM_SETPITCH");
926 pTask
->AuxParam
.GetSetData
.pData
= (PBYTE
)&dwParam1
;
927 pTask
->AuxParam
.GetSetData
.DataLen
= sizeof(DWORD
);
928 pTask
->AuxParam
.GetSetData
.Function
= IOCTL_WAVE_SET_PITCH
;
930 pTask
->AuxFunction
= WaveThreadSetData
;
931 SetEvent(pTask
->AuxEvent1
);
932 WaitForSingleObject(pTask
->AuxEvent2
, INFINITE
);
933 return pTask
->AuxReturnCode
;
936 DPRINT("WODM_SETVOLUME");
939 Vol
.Left
= LOWORD(dwParam1
) << 16;
940 Vol
.Right
= HIWORD(dwParam1
) << 16;
942 return soundSetData(WaveOutDevice
, dwId
, sizeof(Vol
),
943 (PBYTE
)&Vol
, IOCTL_WAVE_SET_VOLUME
);
946 case WODM_SETPLAYBACKRATE
:
947 DPRINT("WODM_SETPLAYBACKRATE");
948 pTask
->AuxParam
.GetSetData
.pData
= (PBYTE
)&dwParam1
;
949 pTask
->AuxParam
.GetSetData
.DataLen
= sizeof(DWORD
);
950 pTask
->AuxParam
.GetSetData
.Function
= IOCTL_WAVE_SET_PLAYBACK_RATE
;
952 pTask
->AuxFunction
= WaveThreadSetData
;
953 SetEvent(pTask
->AuxEvent1
);
954 WaitForSingleObject(pTask
->AuxEvent2
, INFINITE
);
955 return pTask
->AuxReturnCode
;
959 DPRINT("WODM_GETPITCH");
960 pTask
->AuxParam
.GetSetData
.pData
= (PBYTE
)dwParam1
;
961 pTask
->AuxParam
.GetSetData
.DataLen
= sizeof(DWORD
);
962 pTask
->AuxParam
.GetSetData
.Function
= IOCTL_WAVE_GET_PITCH
;
964 pTask
->AuxFunction
= WaveThreadGetData
;
965 SetEvent(pTask
->AuxEvent1
);
966 WaitForSingleObject(pTask
->AuxEvent2
, INFINITE
);
967 return pTask
->AuxReturnCode
;
970 DPRINT("WODM_GETVOLUME");
972 WAVE_DD_VOLUME Vol
= {};
975 res
= soundGetData(WaveOutDevice
, dwId
, sizeof(Vol
),
976 (PBYTE
)&Vol
, IOCTL_WAVE_GET_VOLUME
);
978 if (res
== MMSYSERR_NOERROR
)
979 *(LPDWORD
)dwParam1
= (DWORD
)MAKELONG(HIWORD(Vol
.Left
), HIWORD(Vol
.Right
));
984 case WODM_GETPLAYBACKRATE
:
985 DPRINT("WODM_GETPLAYBACKRATE");
986 pTask
->AuxParam
.GetSetData
.pData
= (PBYTE
)dwParam1
;
987 pTask
->AuxParam
.GetSetData
.DataLen
= sizeof(DWORD
);
988 pTask
->AuxParam
.GetSetData
.Function
= IOCTL_WAVE_GET_PLAYBACK_RATE
;
990 pTask
->AuxFunction
= WaveThreadGetData
;
991 SetEvent(pTask
->AuxEvent1
);
992 WaitForSingleObject(pTask
->AuxEvent2
, INFINITE
);
993 return pTask
->AuxReturnCode
;
996 return MMSYSERR_NOTSUPPORTED
;
999 // This point of execution should never be reached
1000 return MMSYSERR_NOTSUPPORTED
;
1007 APIENTRY DWORD
widMessage(DWORD dwId
, DWORD dwMessage
, DWORD dwUser
, DWORD dwParam1
, DWORD dwParam2
)
1009 DPRINT("widMessage\n");
1013 case WIDM_GETNUMDEVS
:
1014 DPRINT("WIDM_GETNUMDEVS");
1015 return GetDeviceCount(WaveInDevice
);
1017 case WIDM_GETDEVCAPS
:
1018 DPRINT("WODM_GETDEVCAPS");
1019 return GetDeviceCapabilities(dwId
, WaveInDevice
, (LPBYTE
)dwParam1
, (DWORD
)dwParam2
);
1022 DPRINT("WIDM_OPEN");
1023 return OpenWaveDevice(WaveInDevice
, dwId
, dwUser
, dwParam1
, dwParam2
);
1026 return MMSYSERR_NOERROR
;
1028 case WIDM_ADDBUFFER
:
1029 return MMSYSERR_NOERROR
;
1032 return MMSYSERR_NOERROR
;
1035 return MMSYSERR_NOERROR
;
1038 return MMSYSERR_NOERROR
;
1041 return MMSYSERR_NOERROR
;
1045 return MMSYSERR_NOTSUPPORTED
;