2 * PROJECT: ReactOS Sound System
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/wdmaud.drv/wdmaud.c
6 * PURPOSE: WDM Audio Driver (User-mode part)
7 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
9 * NOTES: Looking for wodMessage & co? You won't find them here. Try
10 * the MME Buddy library, which is where these routines are
11 * actually implemented.
18 #define KERNEL_DEVICE_NAME L"\\\\.\\wdmaud"
20 PWSTR UnknownWaveIn
= L
"Wave Input";
21 PWSTR UnknownWaveOut
= L
"Wave Output";
22 PWSTR UnknownMidiIn
= L
"Midi Input";
23 PWSTR UnknownMidiOut
= L
"Midi Output";
26 HANDLE KernelHandle
= INVALID_HANDLE_VALUE
;
31 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
34 IN PSOUND_OVERLAPPED Overlap
,
35 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
);
42 IN MMDEVICE_TYPE DeviceType
,
43 OUT DWORD
* DeviceCount
)
49 case MIXER_DEVICE_TYPE
:
50 *DeviceCount
= WdmAudGetMixerCount();
52 case WAVE_OUT_DEVICE_TYPE
:
53 *DeviceCount
= WdmAudGetWaveOutCount();
55 case WAVE_IN_DEVICE_TYPE
:
56 *DeviceCount
= WdmAudGetWaveInCount();
61 return MMSYSERR_NOERROR
;
65 WDMAUD_DEVICE_INFO DeviceInfo
;
67 VALIDATE_MMSYS_PARAMETER( Handle
!= INVALID_HANDLE_VALUE
);
68 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
69 VALIDATE_MMSYS_PARAMETER( DeviceCount
);
71 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
72 DeviceInfo
.DeviceType
= DeviceType
;
74 Result
= SyncOverlappedDeviceIoControl(Handle
,
75 IOCTL_GETNUMDEVS_TYPE
,
77 sizeof(WDMAUD_DEVICE_INFO
),
79 sizeof(WDMAUD_DEVICE_INFO
),
82 if ( ! MMSUCCESS( Result
) )
84 SND_ERR(L
"Call to IOCTL_GETNUMDEVS_TYPE failed\n");
86 return TranslateInternalMmResult(Result
);
89 *DeviceCount
= DeviceInfo
.DeviceCount
;
91 return MMSYSERR_NOERROR
;
96 GetWdmDeviceCapabilities(
97 IN PSOUND_DEVICE SoundDevice
,
99 OUT PVOID Capabilities
,
100 IN DWORD CapabilitiesSize
)
102 /* NOTE - At this time, WDMAUD does not support this properly */
105 MMDEVICE_TYPE DeviceType
;
106 WDMAUD_DEVICE_INFO DeviceInfo
;
108 SND_ASSERT( SoundDevice
);
109 SND_ASSERT( Capabilities
);
111 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
112 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
114 if ( ! MMSUCCESS(Result
) )
117 SND_TRACE(L
"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType
, DeviceId
);
119 #ifdef USE_MMIXER_LIB
120 if (DeviceType
== MIXER_DEVICE_TYPE
)
122 return WdmAudGetMixerCapabilities(DeviceId
, (LPMIXERCAPSW
)Capabilities
);
124 else if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
126 return WdmAudGetWaveOutCapabilities(DeviceId
, (LPWAVEOUTCAPSW
)Capabilities
);
128 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
130 return WdmAudGetWaveInCapabilities(DeviceId
, (LPWAVEINCAPSW
)Capabilities
);
136 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
137 DeviceInfo
.DeviceType
= DeviceType
;
138 DeviceInfo
.DeviceIndex
= DeviceId
;
140 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
141 IOCTL_GETCAPABILITIES
,
142 (LPVOID
) &DeviceInfo
,
143 sizeof(WDMAUD_DEVICE_INFO
),
144 (LPVOID
) &DeviceInfo
,
145 sizeof(WDMAUD_DEVICE_INFO
),
148 if ( ! MMSUCCESS(Result
) )
150 return TranslateInternalMmResult(Result
);
153 /* This is pretty much a big hack right now */
154 switch ( DeviceType
)
156 case MIXER_DEVICE_TYPE
:
158 LPMIXERCAPS MixerCaps
= (LPMIXERCAPS
) Capabilities
;
160 DeviceInfo
.u
.MixCaps
.szPname
[MAXPNAMELEN
-1] = L
'\0';
161 CopyWideString(MixerCaps
->szPname
, DeviceInfo
.u
.MixCaps
.szPname
);
163 MixerCaps
->cDestinations
= DeviceInfo
.u
.MixCaps
.cDestinations
;
164 MixerCaps
->fdwSupport
= DeviceInfo
.u
.MixCaps
.fdwSupport
;
165 MixerCaps
->vDriverVersion
= DeviceInfo
.u
.MixCaps
.vDriverVersion
;
166 MixerCaps
->wMid
= DeviceInfo
.u
.MixCaps
.wMid
;
167 MixerCaps
->wPid
= DeviceInfo
.u
.MixCaps
.wPid
;
170 case WAVE_OUT_DEVICE_TYPE
:
172 LPWAVEOUTCAPS WaveOutCaps
= (LPWAVEOUTCAPS
) Capabilities
;
174 DeviceInfo
.u
.WaveOutCaps
.szPname
[MAXPNAMELEN
-1] = L
'\0';
175 WaveOutCaps
->wMid
= DeviceInfo
.u
.WaveOutCaps
.wMid
;
176 WaveOutCaps
->wPid
= DeviceInfo
.u
.WaveOutCaps
.wPid
;
178 WaveOutCaps
->vDriverVersion
= 0x0001;
179 CopyWideString(WaveOutCaps
->szPname
, DeviceInfo
.u
.WaveOutCaps
.szPname
);
181 WaveOutCaps
->dwFormats
= DeviceInfo
.u
.WaveOutCaps
.dwFormats
;
182 WaveOutCaps
->wChannels
= DeviceInfo
.u
.WaveOutCaps
.wChannels
;
183 WaveOutCaps
->dwSupport
= DeviceInfo
.u
.WaveOutCaps
.dwSupport
;
186 case WAVE_IN_DEVICE_TYPE
:
188 LPWAVEINCAPSW WaveInCaps
= (LPWAVEINCAPSW
) Capabilities
;
190 DeviceInfo
.u
.WaveInCaps
.szPname
[MAXPNAMELEN
-1] = L
'\0';
192 WaveInCaps
->wMid
= DeviceInfo
.u
.WaveInCaps
.wMid
;
193 WaveInCaps
->wPid
= DeviceInfo
.u
.WaveInCaps
.wPid
;
195 WaveInCaps
->vDriverVersion
= 0x0001;
196 CopyWideString(WaveInCaps
->szPname
, DeviceInfo
.u
.WaveInCaps
.szPname
);
198 WaveInCaps
->dwFormats
= DeviceInfo
.u
.WaveInCaps
.dwFormats
;
199 WaveInCaps
->wChannels
= DeviceInfo
.u
.WaveInCaps
.wChannels
;
200 WaveInCaps
->wReserved1
= 0;
205 return MMSYSERR_NOERROR
;
211 IN
struct _SOUND_DEVICE
* SoundDevice
, /* NOT USED */
214 /* Only open this if it's not already open */
215 if ( KernelHandle
== INVALID_HANDLE_VALUE
)
217 SND_TRACE(L
"Opening wdmaud device\n");
218 KernelHandle
= CreateFileW(KERNEL_DEVICE_NAME
,
219 GENERIC_READ
| GENERIC_WRITE
,
223 FILE_FLAG_OVERLAPPED
,
227 if ( KernelHandle
== INVALID_HANDLE_VALUE
)
228 return MMSYSERR_ERROR
;
230 SND_ASSERT( Handle
);
232 *Handle
= KernelHandle
;
235 return MMSYSERR_NOERROR
;
240 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
243 WDMAUD_DEVICE_INFO DeviceInfo
;
245 MMDEVICE_TYPE DeviceType
;
246 PSOUND_DEVICE SoundDevice
;
248 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
250 if ( ! MMSUCCESS(Result
) )
252 return TranslateInternalMmResult(Result
);
255 if ( OpenCount
== 0 )
257 return MMSYSERR_NOERROR
;
260 SND_ASSERT( KernelHandle
!= INVALID_HANDLE_VALUE
);
262 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
263 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
265 if (SoundDeviceInstance
->Handle
!= (PVOID
)KernelHandle
)
267 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
269 DeviceInfo
.DeviceType
= DeviceType
;
270 DeviceInfo
.hDevice
= SoundDeviceInstance
->Handle
;
272 /* First stop the stream */
273 if (DeviceType
!= MIXER_DEVICE_TYPE
)
275 DeviceInfo
.u
.State
= KSSTATE_STOP
;
276 SyncOverlappedDeviceIoControl(KernelHandle
,
277 IOCTL_SETDEVICE_STATE
,
278 (LPVOID
) &DeviceInfo
,
279 sizeof(WDMAUD_DEVICE_INFO
),
280 (LPVOID
) &DeviceInfo
,
281 sizeof(WDMAUD_DEVICE_INFO
),
284 #ifdef USE_MMIXER_LIB
285 if (DeviceType
== MIXER_DEVICE_TYPE
)
287 return WdmAudCloseMixer(SoundDeviceInstance
->Handle
, SoundDeviceInstance
->hNotifyEvent
);
291 SyncOverlappedDeviceIoControl(KernelHandle
,
293 (LPVOID
) &DeviceInfo
,
294 sizeof(WDMAUD_DEVICE_INFO
),
295 (LPVOID
) &DeviceInfo
,
296 sizeof(WDMAUD_DEVICE_INFO
),
300 if (DeviceType
== MIXER_DEVICE_TYPE
)
302 SetEvent(SoundDeviceInstance
->hStopEvent
);
303 CloseHandle(SoundDeviceInstance
->hStopEvent
);
304 CloseHandle(SoundDeviceInstance
->hNotifyEvent
);
311 CloseHandle(KernelHandle
);
312 KernelHandle
= INVALID_HANDLE_VALUE
;
315 return MMSYSERR_NOERROR
;
320 QueryWdmWaveDeviceFormatSupport(
321 IN PSOUND_DEVICE Device
,
322 IN PWAVEFORMATEX WaveFormat
,
323 IN DWORD WaveFormatSize
)
326 return MMSYSERR_NOERROR
;
332 MixerEventThreadRoutine(
335 HANDLE WaitObjects
[2];
338 WDMAUD_DEVICE_INFO DeviceInfo
;
339 PSOUND_DEVICE_INSTANCE Instance
= (PSOUND_DEVICE_INSTANCE
)Parameter
;
341 /* setup wait objects */
342 WaitObjects
[0] = Instance
->hNotifyEvent
;
343 WaitObjects
[1] = Instance
->hStopEvent
;
345 /* zero device info */
346 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
348 DeviceInfo
.hDevice
= Instance
->Handle
;
349 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
353 dwResult
= WaitForMultipleObjects(2, WaitObjects
, FALSE
, INFINITE
);
355 if (dwResult
== WAIT_OBJECT_0
+ 1)
357 /* stop event was signalled */
363 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
364 IOCTL_GET_MIXER_EVENT
,
365 (LPVOID
) &DeviceInfo
,
366 sizeof(WDMAUD_DEVICE_INFO
),
367 (LPVOID
) &DeviceInfo
,
368 sizeof(WDMAUD_DEVICE_INFO
),
371 if (Result
== MMSYSERR_NOERROR
)
373 DriverCallback(Instance
->WinMM
.ClientCallback
,
374 HIWORD(Instance
->WinMM
.Flags
),
375 Instance
->WinMM
.Handle
,
376 DeviceInfo
.u
.MixerEvent
.NotificationType
,
377 Instance
->WinMM
.ClientCallbackInstanceData
,
378 (DWORD_PTR
)DeviceInfo
.u
.MixerEvent
.Value
,
381 }while(Result
== MMSYSERR_NOERROR
);
390 SetWdmMixerDeviceFormat(
391 IN PSOUND_DEVICE_INSTANCE Instance
,
393 IN PWAVEFORMATEX WaveFormat
,
394 IN DWORD WaveFormatSize
)
397 WDMAUD_DEVICE_INFO DeviceInfo
;
401 Instance
->hNotifyEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
402 if ( ! Instance
->hNotifyEvent
)
403 return MMSYSERR_NOMEM
;
405 #ifdef USE_MMIXER_LIB
406 return WdmAudOpenMixer(&Instance
->Handle
, DeviceId
, Instance
->hNotifyEvent
);
409 if (Instance
->Handle
!= KernelHandle
)
411 /* device is already open */
412 return MMSYSERR_NOERROR
;
415 Instance
->hStopEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
416 if ( ! Instance
->hStopEvent
)
417 return MMSYSERR_NOMEM
;
419 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
420 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
421 DeviceInfo
.DeviceIndex
= DeviceId
;
422 DeviceInfo
.u
.hNotifyEvent
= Instance
->hNotifyEvent
;
424 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
426 (LPVOID
) &DeviceInfo
,
427 sizeof(WDMAUD_DEVICE_INFO
),
428 (LPVOID
) &DeviceInfo
,
429 sizeof(WDMAUD_DEVICE_INFO
),
432 if ( ! MMSUCCESS(Result
) )
434 CloseHandle(Instance
->hNotifyEvent
);
435 CloseHandle(Instance
->hStopEvent
);
436 return TranslateInternalMmResult(Result
);
439 hThread
= CreateThread(NULL
, 0, MixerEventThreadRoutine
, (LPVOID
)Instance
, 0, NULL
);
442 CloseHandle(hThread
);
445 /* Store sound device handle instance handle */
446 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
448 return MMSYSERR_NOERROR
;
452 SetWdmWaveDeviceFormat(
453 IN PSOUND_DEVICE_INSTANCE Instance
,
455 IN PWAVEFORMATEX WaveFormat
,
456 IN DWORD WaveFormatSize
)
459 PSOUND_DEVICE SoundDevice
;
461 WDMAUD_DEVICE_INFO DeviceInfo
;
462 MMDEVICE_TYPE DeviceType
;
464 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
466 if ( ! MMSUCCESS(Result
) )
468 return TranslateInternalMmResult(Result
);
471 Result
= GetSoundDeviceIdentifier(SoundDevice
, &Identifier
);
473 if ( ! MMSUCCESS(Result
) )
475 return TranslateInternalMmResult(Result
);
478 if (Instance
->Handle
!= KernelHandle
)
480 /* device is already open */
481 return MMSYSERR_NOERROR
;
484 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
486 #ifdef USE_MMIXER_LIB
487 return WdmAudOpenWavePin(Instance
, DeviceId
, WaveFormat
, DeviceType
);
491 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
493 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
494 DeviceInfo
.DeviceType
= DeviceType
;
495 DeviceInfo
.DeviceIndex
= DeviceId
;
496 DeviceInfo
.u
.WaveFormatEx
.cbSize
= sizeof(WAVEFORMATEX
); //WaveFormat->cbSize;
497 DeviceInfo
.u
.WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
498 #ifdef USERMODE_MIXER
499 DeviceInfo
.u
.WaveFormatEx
.nChannels
= 2;
500 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= 44100;
501 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= 4;
502 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= 176400;
503 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= 16;
505 DeviceInfo
.u
.WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
506 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
507 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
508 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
509 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
512 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
514 (LPVOID
) &DeviceInfo
,
515 sizeof(WDMAUD_DEVICE_INFO
),
516 (LPVOID
) &DeviceInfo
,
517 sizeof(WDMAUD_DEVICE_INFO
),
520 if ( ! MMSUCCESS(Result
) )
522 return TranslateInternalMmResult(Result
);
526 Instance
->WaveFormatEx
.cbSize
= WaveFormat
->cbSize
;
527 Instance
->WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
528 Instance
->WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
529 Instance
->WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
530 Instance
->WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
531 Instance
->WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
532 Instance
->WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
534 /* Store sound device handle instance handle */
535 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
537 /* Now determine framing requirements */
538 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
540 (LPVOID
) &DeviceInfo
,
541 sizeof(WDMAUD_DEVICE_INFO
),
542 (LPVOID
) &DeviceInfo
,
543 sizeof(WDMAUD_DEVICE_INFO
),
546 if ( MMSUCCESS(Result
) )
548 if (DeviceInfo
.u
.FrameSize
)
550 Instance
->FrameSize
= DeviceInfo
.u
.FrameSize
* 2;
551 Instance
->BufferCount
= WaveFormat
->nAvgBytesPerSec
/ Instance
->FrameSize
;
552 SND_TRACE(L
"FrameSize %u BufferCount %u\n", Instance
->FrameSize
, Instance
->BufferCount
);
557 // use a default of 100 buffers
558 Instance
->BufferCount
= 100;
561 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
563 /* Now start the stream */
564 DeviceInfo
.u
.State
= KSSTATE_RUN
;
565 SyncOverlappedDeviceIoControl(KernelHandle
,
566 IOCTL_SETDEVICE_STATE
,
567 (LPVOID
) &DeviceInfo
,
568 sizeof(WDMAUD_DEVICE_INFO
),
569 (LPVOID
) &DeviceInfo
,
570 sizeof(WDMAUD_DEVICE_INFO
),
574 return MMSYSERR_NOERROR
;
578 WriteFileEx_Committer2(
579 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
582 IN PSOUND_OVERLAPPED Overlap
,
583 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
)
587 WDMAUD_DEVICE_INFO DeviceInfo
;
588 PSOUND_DEVICE SoundDevice
;
589 MMDEVICE_TYPE DeviceType
;
592 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance
);
593 VALIDATE_MMSYS_PARAMETER( OffsetPtr
);
594 VALIDATE_MMSYS_PARAMETER( Overlap
);
595 VALIDATE_MMSYS_PARAMETER( CompletionRoutine
);
597 GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
600 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
602 if ( ! MMSUCCESS(Result
) )
604 return TranslateInternalMmResult(Result
);
607 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
608 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
612 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
614 DeviceInfo
.Header
.FrameExtent
= Length
;
615 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
617 DeviceInfo
.Header
.DataUsed
= Length
;
619 DeviceInfo
.Header
.Data
= OffsetPtr
;
620 DeviceInfo
.Header
.Size
= sizeof(WDMAUD_DEVICE_INFO
);
621 DeviceInfo
.Header
.PresentationTime
.Numerator
= 1;
622 DeviceInfo
.Header
.PresentationTime
.Denominator
= 1;
623 DeviceInfo
.hDevice
= Handle
;
624 DeviceInfo
.DeviceType
= DeviceType
;
626 Overlap
->Standard
.hEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
628 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
630 Ret
= WriteFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
);
632 WaitForSingleObjectEx (KernelHandle
, INFINITE
, TRUE
);
634 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
636 Ret
= ReadFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
);
638 // WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
641 return MMSYSERR_NOERROR
;
646 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
650 PSOUND_DEVICE SoundDevice
;
651 WDMAUD_DEVICE_INFO DeviceInfo
;
652 MMDEVICE_TYPE DeviceType
;
655 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
657 if ( ! MMSUCCESS(Result
) )
659 return TranslateInternalMmResult(Result
);
662 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
663 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
665 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
666 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
668 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
669 DeviceInfo
.hDevice
= Handle
;
670 DeviceInfo
.DeviceType
= DeviceType
;
673 DeviceInfo
.u
.State
= KSSTATE_RUN
;
675 DeviceInfo
.u
.State
= KSSTATE_PAUSE
;
676 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
677 IOCTL_SETDEVICE_STATE
,
678 (LPVOID
) &DeviceInfo
,
679 sizeof(WDMAUD_DEVICE_INFO
),
680 (LPVOID
) &DeviceInfo
,
681 sizeof(WDMAUD_DEVICE_INFO
),
688 GetDeviceInterfaceString(
689 IN MMDEVICE_TYPE DeviceType
,
692 IN DWORD InterfaceLength
,
693 OUT DWORD
* InterfaceSize
)
695 WDMAUD_DEVICE_INFO DeviceInfo
;
698 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
699 DeviceInfo
.DeviceType
= DeviceType
;
700 DeviceInfo
.DeviceIndex
= DeviceId
;
703 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
704 IOCTL_QUERYDEVICEINTERFACESTRING
,
705 (LPVOID
) &DeviceInfo
,
706 sizeof(WDMAUD_DEVICE_INFO
),
707 (LPVOID
) &DeviceInfo
,
708 sizeof(WDMAUD_DEVICE_INFO
),
712 if ( ! MMSUCCESS(Result
) )
714 return TranslateInternalMmResult(Result
);
720 SND_ASSERT(InterfaceSize
);
722 *InterfaceSize
= DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
;
723 return MMSYSERR_NOERROR
;
726 if (InterfaceLength
< DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
)
728 /* buffer is too small */
729 return MMSYSERR_MOREDATA
;
732 DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
= InterfaceLength
;
733 DeviceInfo
.u
.Interface
.DeviceInterfaceString
= Interface
;
735 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
736 IOCTL_QUERYDEVICEINTERFACESTRING
,
737 (LPVOID
) &DeviceInfo
,
738 sizeof(WDMAUD_DEVICE_INFO
),
739 (LPVOID
) &DeviceInfo
,
740 sizeof(WDMAUD_DEVICE_INFO
),
743 if ( MMSUCCESS(Result
) && InterfaceLength
> 2)
745 Interface
[1] = L
'\\';
746 Interface
[InterfaceLength
-1] = L
'\0';
754 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
758 PSOUND_DEVICE SoundDevice
;
759 WDMAUD_DEVICE_INFO DeviceInfo
;
760 MMDEVICE_TYPE DeviceType
;
763 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
765 if ( ! MMSUCCESS(Result
) )
767 return TranslateInternalMmResult(Result
);
770 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
771 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
773 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
774 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
776 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
777 DeviceInfo
.hDevice
= Handle
;
778 DeviceInfo
.DeviceType
= DeviceType
;
780 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
782 (LPVOID
) &DeviceInfo
,
783 sizeof(WDMAUD_DEVICE_INFO
),
784 (LPVOID
) &DeviceInfo
,
785 sizeof(WDMAUD_DEVICE_INFO
),
788 if ( ! MMSUCCESS(Result
) )
790 return TranslateInternalMmResult(Result
);
793 Time
->wType
= TIME_BYTES
;
794 Time
->u
.cb
= (DWORD
)DeviceInfo
.u
.Position
;
796 return MMSYSERR_NOERROR
;
801 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
802 IN MMDEVICE_TYPE DeviceType
,
803 IN BOOLEAN bStartReset
)
807 WDMAUD_DEVICE_INFO DeviceInfo
;
809 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
810 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
812 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
813 DeviceInfo
.hDevice
= Handle
;
814 DeviceInfo
.DeviceType
= DeviceType
;
815 DeviceInfo
.u
.ResetStream
= (bStartReset
? KSRESET_BEGIN
: KSRESET_END
);
817 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
819 (LPVOID
) &DeviceInfo
,
820 sizeof(WDMAUD_DEVICE_INFO
),
821 (LPVOID
) &DeviceInfo
,
822 sizeof(WDMAUD_DEVICE_INFO
),
830 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
836 WDMAUD_DEVICE_INFO DeviceInfo
;
839 LPMIXERLINEW MixLine
;
840 LPMIXERLINECONTROLSW MixControls
;
841 LPMIXERCONTROLDETAILS MixDetails
;
843 SND_TRACE(L
"uMsg %x Flags %x\n", uMsg
, Flags
);
845 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
846 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
848 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
849 DeviceInfo
.hDevice
= Handle
;
850 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
851 DeviceInfo
.Flags
= Flags
;
853 MixLine
= (LPMIXERLINEW
)Parameter
;
854 MixControls
= (LPMIXERLINECONTROLSW
)Parameter
;
855 MixDetails
= (LPMIXERCONTROLDETAILS
)Parameter
;
857 #ifdef USE_MMIXER_LIB
860 case MXDM_GETLINEINFO
:
861 return WdmAudGetLineInfo(SoundDeviceInstance
->Handle
, MixLine
, Flags
);
862 case MXDM_GETLINECONTROLS
:
863 return WdmAudGetLineControls(SoundDeviceInstance
->Handle
, MixControls
, Flags
);
864 case MXDM_SETCONTROLDETAILS
:
865 return WdmAudSetControlDetails(SoundDeviceInstance
->Handle
, MixDetails
, Flags
);
867 case MXDM_GETCONTROLDETAILS
:
868 return WdmAudGetControlDetails(SoundDeviceInstance
->Handle
, MixDetails
, Flags
);
872 return MMSYSERR_NOTSUPPORTED
;
879 case MXDM_GETLINEINFO
:
880 RtlCopyMemory(&DeviceInfo
.u
.MixLine
, MixLine
, sizeof(MIXERLINEW
));
881 IoControlCode
= IOCTL_GETLINEINFO
;
883 case MXDM_GETLINECONTROLS
:
884 RtlCopyMemory(&DeviceInfo
.u
.MixControls
, MixControls
, sizeof(MIXERLINECONTROLSW
));
885 IoControlCode
= IOCTL_GETLINECONTROLS
;
887 case MXDM_SETCONTROLDETAILS
:
888 RtlCopyMemory(&DeviceInfo
.u
.MixDetails
, MixDetails
, sizeof(MIXERCONTROLDETAILS
));
889 IoControlCode
= IOCTL_SETCONTROLDETAILS
;
891 case MXDM_GETCONTROLDETAILS
:
892 RtlCopyMemory(&DeviceInfo
.u
.MixDetails
, MixDetails
, sizeof(MIXERCONTROLDETAILS
));
893 IoControlCode
= IOCTL_GETCONTROLDETAILS
;
897 return MMSYSERR_NOTSUPPORTED
;
900 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
902 (LPVOID
) &DeviceInfo
,
903 sizeof(WDMAUD_DEVICE_INFO
),
904 (LPVOID
) &DeviceInfo
,
905 sizeof(WDMAUD_DEVICE_INFO
),
908 if ( ! MMSUCCESS(Result
) )
915 case MXDM_GETLINEINFO
:
917 RtlCopyMemory(MixLine
, &DeviceInfo
.u
.MixLine
, sizeof(MIXERLINEW
));
927 PopulateWdmDeviceList(
929 MMDEVICE_TYPE DeviceType
)
932 DWORD DeviceCount
= 0;
933 PSOUND_DEVICE SoundDevice
= NULL
;
934 MMFUNCTION_TABLE FuncTable
;
937 VALIDATE_MMSYS_PARAMETER( Handle
!= INVALID_HANDLE_VALUE
);
938 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
940 Result
= GetNumWdmDevs(Handle
, DeviceType
, &DeviceCount
);
942 if ( ! MMSUCCESS(Result
) )
944 SND_ERR(L
"Error %d while obtaining number of devices\n", Result
);
945 return TranslateInternalMmResult(Result
);
948 SND_TRACE(L
"%d devices of type %d found\n", DeviceCount
, DeviceType
);
951 for ( i
= 0; i
< DeviceCount
; ++ i
)
953 Result
= ListSoundDevice(DeviceType
, UlongToPtr(i
), &SoundDevice
);
955 if ( ! MMSUCCESS(Result
) )
957 SND_ERR(L
"Failed to list sound device - error %d\n", Result
);
958 return TranslateInternalMmResult(Result
);
961 /* Set up our function table */
962 ZeroMemory(&FuncTable
, sizeof(MMFUNCTION_TABLE
));
963 FuncTable
.GetCapabilities
= GetWdmDeviceCapabilities
;
964 FuncTable
.QueryWaveFormatSupport
= QueryWdmWaveDeviceFormatSupport
;
965 if (DeviceType
== MIXER_DEVICE_TYPE
)
967 FuncTable
.SetWaveFormat
= SetWdmMixerDeviceFormat
;
968 FuncTable
.QueryMixerInfo
= QueryMixerInfo
;
972 FuncTable
.SetWaveFormat
= SetWdmWaveDeviceFormat
;
975 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
977 FuncTable
.SetState
= SetWdmWaveState
;
978 FuncTable
.ResetStream
= ResetStream
;
981 FuncTable
.Open
= OpenWdmSoundDevice
;
982 FuncTable
.Close
= CloseWdmSoundDevice
;
983 FuncTable
.GetDeviceInterfaceString
= GetDeviceInterfaceString
;
984 #ifndef USERMODE_MIXER
985 FuncTable
.CommitWaveBuffer
= WriteFileEx_Committer2
;
987 FuncTable
.CommitWaveBuffer
= WriteFileEx_Remixer
;
989 FuncTable
.GetPos
= GetWdmPosition
;
991 SetSoundDeviceFunctionTable(SoundDevice
, &FuncTable
);
994 return MMSYSERR_NOERROR
;
1003 HANDLE DriverHandle
,
1015 SND_TRACE(L
"DRV_LOAD\n");
1017 Result
= InitEntrypointMutexes();
1019 if ( ! MMSUCCESS(Result
) )
1022 OpenWdmSoundDevice(NULL
, &Handle
);
1024 if ( Handle
== INVALID_HANDLE_VALUE
)
1026 SND_ERR(L
"Failed to open %s\n", KERNEL_DEVICE_NAME
);
1027 CleanupEntrypointMutexes();
1029 //UnlistAllSoundDevices();
1034 /* Populate the device lists */
1035 SND_TRACE(L
"Populating device lists\n");
1036 PopulateWdmDeviceList(KernelHandle
, WAVE_OUT_DEVICE_TYPE
);
1037 PopulateWdmDeviceList(KernelHandle
, WAVE_IN_DEVICE_TYPE
);
1038 PopulateWdmDeviceList(KernelHandle
, MIDI_OUT_DEVICE_TYPE
);
1039 PopulateWdmDeviceList(KernelHandle
, MIDI_IN_DEVICE_TYPE
);
1040 PopulateWdmDeviceList(KernelHandle
, AUX_DEVICE_TYPE
);
1041 PopulateWdmDeviceList(KernelHandle
, MIXER_DEVICE_TYPE
);
1043 SND_TRACE(L
"Initialisation complete\n");
1050 SND_TRACE(L
"DRV_FREE\n");
1052 if ( KernelHandle
!= INVALID_HANDLE_VALUE
)
1054 CloseHandle(KernelHandle
);
1055 KernelHandle
= INVALID_HANDLE_VALUE
;
1058 /* TODO: Clean up the path names! */
1059 UnlistAllSoundDevices();
1061 CleanupEntrypointMutexes();
1063 SND_TRACE(L
"Unfreed memory blocks: %d\n",
1064 GetMemoryAllocationCount());
1072 SND_TRACE(L
"DRV_ENABLE / DRV_DISABLE\n");
1079 SND_TRACE(L
"DRV_OPEN / DRV_CLOSE\n");
1083 case DRV_QUERYCONFIGURE
:
1085 SND_TRACE(L
"DRV_QUERYCONFIGURE\n");
1088 case DRV_CONFIGURE
:
1092 SND_TRACE(L
"Unhandled message %d\n", Message
);
1093 return DefDriverProc(DriverId
,
1102 BOOL WINAPI
DllMain(
1107 switch ( fdwReason
)
1109 case DLL_PROCESS_ATTACH
:
1110 #ifdef USE_MMIXER_LIB
1111 WdmAudInitUserModeMixer();
1113 SND_TRACE(L
"WDMAUD.DRV - Process attached\n");
1115 case DLL_PROCESS_DETACH
:
1116 SND_TRACE(L
"WDMAUD.DRV - Process detached\n");
1118 case DLL_THREAD_ATTACH
:
1119 SND_TRACE(L
"WDMAUD.DRV - Thread attached\n");
1121 case DLL_THREAD_DETACH
:
1122 SND_TRACE(L
"WDMAUD.DRV - Thread detached\n");