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.
23 #include "interface.h"
25 #define KERNEL_DEVICE_NAME L"\\\\.\\wdmaud"
27 PWSTR UnknownWaveIn
= L
"Wave Input";
28 PWSTR UnknownWaveOut
= L
"Wave Output";
29 PWSTR UnknownMidiIn
= L
"Midi Input";
30 PWSTR UnknownMidiOut
= L
"Midi Output";
32 HANDLE KernelHandle
= INVALID_HANDLE_VALUE
;
37 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
40 IN PSOUND_OVERLAPPED Overlap
,
41 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
);
48 IN MMDEVICE_TYPE DeviceType
,
49 OUT DWORD
* DeviceCount
)
52 WDMAUD_DEVICE_INFO DeviceInfo
;
54 VALIDATE_MMSYS_PARAMETER( Handle
!= INVALID_HANDLE_VALUE
);
55 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
56 VALIDATE_MMSYS_PARAMETER( DeviceCount
);
58 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
59 DeviceInfo
.DeviceType
= DeviceType
;
61 Result
= SyncOverlappedDeviceIoControl(Handle
,
62 IOCTL_GETNUMDEVS_TYPE
,
64 sizeof(WDMAUD_DEVICE_INFO
),
66 sizeof(WDMAUD_DEVICE_INFO
),
69 if ( ! MMSUCCESS( Result
) )
71 SND_ERR(L
"Call to IOCTL_GETNUMDEVS_TYPE failed\n");
73 return TranslateInternalMmResult(Result
);
76 *DeviceCount
= DeviceInfo
.DeviceCount
;
78 return MMSYSERR_NOERROR
;
82 GetWdmDeviceCapabilities(
83 IN PSOUND_DEVICE SoundDevice
,
85 OUT PVOID Capabilities
,
86 IN DWORD CapabilitiesSize
)
88 /* NOTE - At this time, WDMAUD does not support this properly */
91 MMDEVICE_TYPE DeviceType
;
92 WDMAUD_DEVICE_INFO DeviceInfo
;
94 SND_ASSERT( SoundDevice
);
95 SND_ASSERT( Capabilities
);
97 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
98 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
100 if ( ! MMSUCCESS(Result
) )
103 SND_TRACE(L
"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType
, DeviceId
);
105 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
106 DeviceInfo
.DeviceType
= DeviceType
;
107 DeviceInfo
.DeviceIndex
= DeviceId
;
109 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
110 IOCTL_GETCAPABILITIES
,
111 (LPVOID
) &DeviceInfo
,
112 sizeof(WDMAUD_DEVICE_INFO
),
113 (LPVOID
) &DeviceInfo
,
114 sizeof(WDMAUD_DEVICE_INFO
),
117 if ( ! MMSUCCESS(Result
) )
119 return TranslateInternalMmResult(Result
);
122 /* This is pretty much a big hack right now */
123 switch ( DeviceType
)
125 case MIXER_DEVICE_TYPE
:
127 LPMIXERCAPS MixerCaps
= (LPMIXERCAPS
) Capabilities
;
129 DeviceInfo
.u
.MixCaps
.szPname
[MAXPNAMELEN
-1] = L
'\0';
130 CopyWideString(MixerCaps
->szPname
, DeviceInfo
.u
.MixCaps
.szPname
);
132 MixerCaps
->cDestinations
= DeviceInfo
.u
.MixCaps
.cDestinations
;
133 MixerCaps
->fdwSupport
= DeviceInfo
.u
.MixCaps
.fdwSupport
;
134 MixerCaps
->vDriverVersion
= DeviceInfo
.u
.MixCaps
.vDriverVersion
;
135 MixerCaps
->wMid
= DeviceInfo
.u
.MixCaps
.wMid
;
136 MixerCaps
->wPid
= DeviceInfo
.u
.MixCaps
.wPid
;
139 case WAVE_OUT_DEVICE_TYPE
:
141 LPWAVEOUTCAPS WaveOutCaps
= (LPWAVEOUTCAPS
) Capabilities
;
143 DeviceInfo
.u
.WaveOutCaps
.szPname
[MAXPNAMELEN
-1] = L
'\0';
144 WaveOutCaps
->wMid
= DeviceInfo
.u
.WaveOutCaps
.wMid
;
145 WaveOutCaps
->wPid
= DeviceInfo
.u
.WaveOutCaps
.wPid
;
147 WaveOutCaps
->vDriverVersion
= 0x0001;
148 CopyWideString(WaveOutCaps
->szPname
, DeviceInfo
.u
.WaveOutCaps
.szPname
);
150 WaveOutCaps
->dwFormats
= DeviceInfo
.u
.WaveOutCaps
.dwFormats
;
151 WaveOutCaps
->wChannels
= DeviceInfo
.u
.WaveOutCaps
.wChannels
;
152 WaveOutCaps
->dwSupport
= DeviceInfo
.u
.WaveOutCaps
.dwSupport
;
155 case WAVE_IN_DEVICE_TYPE
:
157 LPWAVEINCAPSW WaveInCaps
= (LPWAVEINCAPSW
) Capabilities
;
159 DeviceInfo
.u
.WaveInCaps
.szPname
[MAXPNAMELEN
-1] = L
'\0';
161 WaveInCaps
->wMid
= DeviceInfo
.u
.WaveInCaps
.wMid
;
162 WaveInCaps
->wPid
= DeviceInfo
.u
.WaveInCaps
.wPid
;
164 WaveInCaps
->vDriverVersion
= 0x0001;
165 CopyWideString(WaveInCaps
->szPname
, DeviceInfo
.u
.WaveInCaps
.szPname
);
167 WaveInCaps
->dwFormats
= DeviceInfo
.u
.WaveInCaps
.dwFormats
;
168 WaveInCaps
->wChannels
= DeviceInfo
.u
.WaveInCaps
.wChannels
;
169 WaveInCaps
->wReserved1
= 0;
174 return MMSYSERR_NOERROR
;
180 IN
struct _SOUND_DEVICE
* SoundDevice
, /* NOT USED */
183 /* Only open this if it's not already open */
184 if ( KernelHandle
== INVALID_HANDLE_VALUE
)
186 SND_TRACE(L
"Opening wdmaud device\n");
187 KernelHandle
= CreateFileW(KERNEL_DEVICE_NAME
,
188 GENERIC_READ
| GENERIC_WRITE
,
192 FILE_FLAG_OVERLAPPED
,
196 if ( KernelHandle
== INVALID_HANDLE_VALUE
)
197 return MMSYSERR_ERROR
;
199 SND_ASSERT( Handle
);
201 *Handle
= KernelHandle
;
204 return MMSYSERR_NOERROR
;
209 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
212 WDMAUD_DEVICE_INFO DeviceInfo
;
214 MMDEVICE_TYPE DeviceType
;
215 PSOUND_DEVICE SoundDevice
;
217 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
219 if ( ! MMSUCCESS(Result
) )
221 return TranslateInternalMmResult(Result
);
224 if ( OpenCount
== 0 )
226 return MMSYSERR_NOERROR
;
229 SND_ASSERT( KernelHandle
!= INVALID_HANDLE_VALUE
);
231 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
232 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
234 if (SoundDeviceInstance
->Handle
!= (PVOID
)KernelHandle
)
236 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
238 DeviceInfo
.DeviceType
= DeviceType
;
239 DeviceInfo
.hDevice
= SoundDeviceInstance
->Handle
;
241 /* First stop the stream */
242 if (DeviceType
!= MIXER_DEVICE_TYPE
)
244 DeviceInfo
.u
.State
= KSSTATE_STOP
;
245 SyncOverlappedDeviceIoControl(KernelHandle
,
246 IOCTL_SETDEVICE_STATE
,
247 (LPVOID
) &DeviceInfo
,
248 sizeof(WDMAUD_DEVICE_INFO
),
249 (LPVOID
) &DeviceInfo
,
250 sizeof(WDMAUD_DEVICE_INFO
),
254 SyncOverlappedDeviceIoControl(KernelHandle
,
256 (LPVOID
) &DeviceInfo
,
257 sizeof(WDMAUD_DEVICE_INFO
),
258 (LPVOID
) &DeviceInfo
,
259 sizeof(WDMAUD_DEVICE_INFO
),
263 if (DeviceType
== MIXER_DEVICE_TYPE
)
265 SetEvent(SoundDeviceInstance
->hStopEvent
);
266 CloseHandle(SoundDeviceInstance
->hStopEvent
);
267 CloseHandle(SoundDeviceInstance
->hNotifyEvent
);
274 CloseHandle(KernelHandle
);
275 KernelHandle
= INVALID_HANDLE_VALUE
;
278 return MMSYSERR_NOERROR
;
283 QueryWdmWaveDeviceFormatSupport(
284 IN PSOUND_DEVICE Device
,
285 IN PWAVEFORMATEX WaveFormat
,
286 IN DWORD WaveFormatSize
)
289 return MMSYSERR_NOERROR
;
295 MixerEventThreadRoutine(
298 HANDLE WaitObjects
[2];
301 WDMAUD_DEVICE_INFO DeviceInfo
;
302 PSOUND_DEVICE_INSTANCE Instance
= (PSOUND_DEVICE_INSTANCE
)Parameter
;
304 /* setup wait objects */
305 WaitObjects
[0] = Instance
->hNotifyEvent
;
306 WaitObjects
[1] = Instance
->hStopEvent
;
308 /* zero device info */
309 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
311 DeviceInfo
.hDevice
= Instance
->Handle
;
312 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
316 dwResult
= WaitForMultipleObjects(2, WaitObjects
, FALSE
, INFINITE
);
318 if (dwResult
== WAIT_OBJECT_0
+ 1)
320 /* stop event was signalled */
324 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
325 IOCTL_GET_MIXER_EVENT
,
326 (LPVOID
) &DeviceInfo
,
327 sizeof(WDMAUD_DEVICE_INFO
),
328 (LPVOID
) &DeviceInfo
,
329 sizeof(WDMAUD_DEVICE_INFO
),
332 if (Result
== MMSYSERR_NOERROR
)
334 DriverCallback(Instance
->WinMM
.ClientCallback
,
335 HIWORD(Instance
->WinMM
.Flags
),
336 Instance
->WinMM
.Handle
,
337 DeviceInfo
.u
.MixerEvent
.NotificationType
,
338 Instance
->WinMM
.ClientCallbackInstanceData
,
339 (DWORD_PTR
)DeviceInfo
.u
.MixerEvent
.Value
,
350 SetWdmMixerDeviceFormat(
351 IN PSOUND_DEVICE_INSTANCE Instance
,
353 IN PWAVEFORMATEX WaveFormat
,
354 IN DWORD WaveFormatSize
)
357 WDMAUD_DEVICE_INFO DeviceInfo
;
360 if (Instance
->Handle
!= KernelHandle
)
362 /* device is already open */
363 return MMSYSERR_NOERROR
;
366 Instance
->hNotifyEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
367 if ( ! Instance
->hNotifyEvent
)
368 return MMSYSERR_NOMEM
;
370 Instance
->hStopEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
371 if ( ! Instance
->hStopEvent
)
372 return MMSYSERR_NOMEM
;
374 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
375 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
376 DeviceInfo
.DeviceIndex
= DeviceId
;
377 DeviceInfo
.u
.hNotifyEvent
= Instance
->hNotifyEvent
;
379 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
381 (LPVOID
) &DeviceInfo
,
382 sizeof(WDMAUD_DEVICE_INFO
),
383 (LPVOID
) &DeviceInfo
,
384 sizeof(WDMAUD_DEVICE_INFO
),
387 if ( ! MMSUCCESS(Result
) )
389 CloseHandle(Instance
->hNotifyEvent
);
390 CloseHandle(Instance
->hStopEvent
);
391 return TranslateInternalMmResult(Result
);
394 hThread
= CreateThread(NULL
, 0, MixerEventThreadRoutine
, (LPVOID
)Instance
, 0, NULL
);
397 CloseHandle(hThread
);
400 /* Store sound device handle instance handle */
401 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
403 return MMSYSERR_NOERROR
;
407 SetWdmWaveDeviceFormat(
408 IN PSOUND_DEVICE_INSTANCE Instance
,
410 IN PWAVEFORMATEX WaveFormat
,
411 IN DWORD WaveFormatSize
)
414 PSOUND_DEVICE SoundDevice
;
416 WDMAUD_DEVICE_INFO DeviceInfo
;
417 MMDEVICE_TYPE DeviceType
;
419 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
421 if ( ! MMSUCCESS(Result
) )
423 return TranslateInternalMmResult(Result
);
426 Result
= GetSoundDeviceIdentifier(SoundDevice
, &Identifier
);
428 if ( ! MMSUCCESS(Result
) )
430 return TranslateInternalMmResult(Result
);
433 if (Instance
->Handle
!= KernelHandle
)
435 /* device is already open */
436 return MMSYSERR_NOERROR
;
440 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
441 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
443 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
444 DeviceInfo
.DeviceType
= DeviceType
;
445 DeviceInfo
.DeviceIndex
= DeviceId
;
446 DeviceInfo
.u
.WaveFormatEx
.cbSize
= WaveFormat
->cbSize
;
447 DeviceInfo
.u
.WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
448 #ifdef USERMODE_MIXER
449 DeviceInfo
.u
.WaveFormatEx
.nChannels
= 2;
450 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= 44100;
451 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= 4;
452 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= 176400;
453 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= 16;
455 DeviceInfo
.u
.WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
456 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
457 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
458 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
459 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
462 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
464 (LPVOID
) &DeviceInfo
,
465 sizeof(WDMAUD_DEVICE_INFO
),
466 (LPVOID
) &DeviceInfo
,
467 sizeof(WDMAUD_DEVICE_INFO
),
470 if ( ! MMSUCCESS(Result
) )
472 return TranslateInternalMmResult(Result
);
476 Instance
->WaveFormatEx
.cbSize
= WaveFormat
->cbSize
;
477 Instance
->WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
478 Instance
->WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
479 Instance
->WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
480 Instance
->WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
481 Instance
->WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
482 Instance
->WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
484 /* Store sound device handle instance handle */
485 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
487 /* Now determine framing requirements */
488 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
490 (LPVOID
) &DeviceInfo
,
491 sizeof(WDMAUD_DEVICE_INFO
),
492 (LPVOID
) &DeviceInfo
,
493 sizeof(WDMAUD_DEVICE_INFO
),
496 if ( MMSUCCESS(Result
) )
498 if (DeviceInfo
.u
.FrameSize
)
500 Instance
->FrameSize
= DeviceInfo
.u
.FrameSize
* 2;
501 Instance
->BufferCount
= WaveFormat
->nAvgBytesPerSec
/ Instance
->FrameSize
;
502 SND_TRACE(L
"FrameSize %u BufferCount %u\n", Instance
->FrameSize
, Instance
->BufferCount
);
507 // use a default of 100 buffers
508 Instance
->BufferCount
= 100;
511 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
513 /* Now start the stream */
514 DeviceInfo
.u
.State
= KSSTATE_RUN
;
515 SyncOverlappedDeviceIoControl(KernelHandle
,
516 IOCTL_SETDEVICE_STATE
,
517 (LPVOID
) &DeviceInfo
,
518 sizeof(WDMAUD_DEVICE_INFO
),
519 (LPVOID
) &DeviceInfo
,
520 sizeof(WDMAUD_DEVICE_INFO
),
524 return MMSYSERR_NOERROR
;
528 WriteFileEx_Committer2(
529 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
532 IN PSOUND_OVERLAPPED Overlap
,
533 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
)
537 WDMAUD_DEVICE_INFO DeviceInfo
;
538 PSOUND_DEVICE SoundDevice
;
539 MMDEVICE_TYPE DeviceType
;
542 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance
);
543 VALIDATE_MMSYS_PARAMETER( OffsetPtr
);
544 VALIDATE_MMSYS_PARAMETER( Overlap
);
545 VALIDATE_MMSYS_PARAMETER( CompletionRoutine
);
547 GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
550 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
552 if ( ! MMSUCCESS(Result
) )
554 return TranslateInternalMmResult(Result
);
557 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
558 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
562 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
564 DeviceInfo
.Header
.FrameExtent
= Length
;
565 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
567 DeviceInfo
.Header
.DataUsed
= Length
;
569 DeviceInfo
.Header
.Data
= OffsetPtr
;
570 DeviceInfo
.Header
.Size
= sizeof(WDMAUD_DEVICE_INFO
);
571 DeviceInfo
.Header
.PresentationTime
.Numerator
= 1;
572 DeviceInfo
.Header
.PresentationTime
.Denominator
= 1;
573 DeviceInfo
.hDevice
= Handle
;
574 DeviceInfo
.DeviceType
= DeviceType
;
576 Overlap
->Standard
.hEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
578 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
580 Ret
= WriteFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
);
582 WaitForSingleObjectEx (KernelHandle
, INFINITE
, TRUE
);
584 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
586 Ret
= ReadFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
);
588 // WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
591 return MMSYSERR_NOERROR
;
596 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
600 PSOUND_DEVICE SoundDevice
;
601 WDMAUD_DEVICE_INFO DeviceInfo
;
602 MMDEVICE_TYPE DeviceType
;
605 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
607 if ( ! MMSUCCESS(Result
) )
609 return TranslateInternalMmResult(Result
);
612 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
613 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
615 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
616 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
618 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
619 DeviceInfo
.hDevice
= Handle
;
620 DeviceInfo
.DeviceType
= DeviceType
;
623 DeviceInfo
.u
.State
= KSSTATE_RUN
;
625 DeviceInfo
.u
.State
= KSSTATE_PAUSE
;
626 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
627 IOCTL_SETDEVICE_STATE
,
628 (LPVOID
) &DeviceInfo
,
629 sizeof(WDMAUD_DEVICE_INFO
),
630 (LPVOID
) &DeviceInfo
,
631 sizeof(WDMAUD_DEVICE_INFO
),
638 GetDeviceInterfaceString(
639 IN MMDEVICE_TYPE DeviceType
,
642 IN DWORD InterfaceLength
,
643 OUT DWORD
* InterfaceSize
)
645 WDMAUD_DEVICE_INFO DeviceInfo
;
648 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
649 DeviceInfo
.DeviceType
= DeviceType
;
650 DeviceInfo
.DeviceIndex
= DeviceId
;
653 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
654 IOCTL_QUERYDEVICEINTERFACESTRING
,
655 (LPVOID
) &DeviceInfo
,
656 sizeof(WDMAUD_DEVICE_INFO
),
657 (LPVOID
) &DeviceInfo
,
658 sizeof(WDMAUD_DEVICE_INFO
),
662 if ( ! MMSUCCESS(Result
) )
664 return TranslateInternalMmResult(Result
);
670 SND_ASSERT(InterfaceSize
);
672 *InterfaceSize
= DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
;
673 return MMSYSERR_NOERROR
;
676 if (InterfaceLength
< DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
)
678 /* buffer is too small */
679 return MMSYSERR_MOREDATA
;
682 DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
= InterfaceLength
;
683 DeviceInfo
.u
.Interface
.DeviceInterfaceString
= Interface
;
685 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
686 IOCTL_QUERYDEVICEINTERFACESTRING
,
687 (LPVOID
) &DeviceInfo
,
688 sizeof(WDMAUD_DEVICE_INFO
),
689 (LPVOID
) &DeviceInfo
,
690 sizeof(WDMAUD_DEVICE_INFO
),
693 if ( MMSUCCESS(Result
) && InterfaceLength
> 2)
695 Interface
[1] = L
'\\';
696 Interface
[InterfaceLength
-1] = L
'\0';
704 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
708 PSOUND_DEVICE SoundDevice
;
709 WDMAUD_DEVICE_INFO DeviceInfo
;
710 MMDEVICE_TYPE DeviceType
;
713 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
715 if ( ! MMSUCCESS(Result
) )
717 return TranslateInternalMmResult(Result
);
720 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
721 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
723 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
724 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
726 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
727 DeviceInfo
.hDevice
= Handle
;
728 DeviceInfo
.DeviceType
= DeviceType
;
730 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
732 (LPVOID
) &DeviceInfo
,
733 sizeof(WDMAUD_DEVICE_INFO
),
734 (LPVOID
) &DeviceInfo
,
735 sizeof(WDMAUD_DEVICE_INFO
),
738 if ( ! MMSUCCESS(Result
) )
740 return TranslateInternalMmResult(Result
);
743 Time
->wType
= TIME_BYTES
;
744 Time
->u
.cb
= (DWORD
)DeviceInfo
.u
.Position
;
746 return MMSYSERR_NOERROR
;
751 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
757 WDMAUD_DEVICE_INFO DeviceInfo
;
760 LPMIXERLINEW MixLine
;
761 LPMIXERLINECONTROLSW MixControls
;
762 LPMIXERCONTROLDETAILS MixDetails
;
764 SND_TRACE(L
"uMsg %x Flags %x\n", uMsg
, Flags
);
766 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
767 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
769 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
770 DeviceInfo
.hDevice
= Handle
;
771 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
772 DeviceInfo
.Flags
= Flags
;
774 MixLine
= (LPMIXERLINEW
)Parameter
;
775 MixControls
= (LPMIXERLINECONTROLSW
)Parameter
;
776 MixDetails
= (LPMIXERCONTROLDETAILS
)Parameter
;
780 case MXDM_GETLINEINFO
:
781 RtlCopyMemory(&DeviceInfo
.u
.MixLine
, MixLine
, sizeof(MIXERLINEW
));
782 IoControlCode
= IOCTL_GETLINEINFO
;
784 case MXDM_GETLINECONTROLS
:
785 RtlCopyMemory(&DeviceInfo
.u
.MixControls
, MixControls
, sizeof(MIXERLINECONTROLSW
));
786 IoControlCode
= IOCTL_GETLINECONTROLS
;
788 case MXDM_SETCONTROLDETAILS
:
789 RtlCopyMemory(&DeviceInfo
.u
.MixDetails
, MixDetails
, sizeof(MIXERCONTROLDETAILS
));
790 IoControlCode
= IOCTL_SETCONTROLDETAILS
;
792 case MXDM_GETCONTROLDETAILS
:
793 RtlCopyMemory(&DeviceInfo
.u
.MixDetails
, MixDetails
, sizeof(MIXERCONTROLDETAILS
));
794 IoControlCode
= IOCTL_GETCONTROLDETAILS
;
798 return MMSYSERR_NOTSUPPORTED
;
801 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
803 (LPVOID
) &DeviceInfo
,
804 sizeof(WDMAUD_DEVICE_INFO
),
805 (LPVOID
) &DeviceInfo
,
806 sizeof(WDMAUD_DEVICE_INFO
),
809 if ( ! MMSUCCESS(Result
) )
811 return TranslateInternalMmResult(Result
);
816 case MXDM_GETLINEINFO
:
818 RtlCopyMemory(MixLine
, &DeviceInfo
.u
.MixLine
, sizeof(MIXERLINEW
));
828 PopulateWdmDeviceList(
830 MMDEVICE_TYPE DeviceType
)
833 DWORD DeviceCount
= 0;
834 PSOUND_DEVICE SoundDevice
= NULL
;
835 MMFUNCTION_TABLE FuncTable
;
838 VALIDATE_MMSYS_PARAMETER( Handle
!= INVALID_HANDLE_VALUE
);
839 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
841 Result
= GetNumWdmDevs(Handle
, DeviceType
, &DeviceCount
);
843 if ( ! MMSUCCESS(Result
) )
845 SND_ERR(L
"Error %d while obtaining number of devices\n", Result
);
846 return TranslateInternalMmResult(Result
);
849 SND_TRACE(L
"%d devices of type %d found\n", DeviceCount
, DeviceType
);
852 for ( i
= 0; i
< DeviceCount
; ++ i
)
854 Result
= ListSoundDevice(DeviceType
, (PVOID
) i
, &SoundDevice
);
856 if ( ! MMSUCCESS(Result
) )
858 SND_ERR(L
"Failed to list sound device - error %d\n", Result
);
859 return TranslateInternalMmResult(Result
);
862 /* Set up our function table */
863 ZeroMemory(&FuncTable
, sizeof(MMFUNCTION_TABLE
));
864 FuncTable
.GetCapabilities
= GetWdmDeviceCapabilities
;
865 FuncTable
.QueryWaveFormatSupport
= QueryWdmWaveDeviceFormatSupport
;
866 if (DeviceType
== MIXER_DEVICE_TYPE
)
868 FuncTable
.SetWaveFormat
= SetWdmMixerDeviceFormat
;
869 FuncTable
.QueryMixerInfo
= QueryMixerInfo
;
873 FuncTable
.SetWaveFormat
= SetWdmWaveDeviceFormat
;
876 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
878 FuncTable
.SetState
= SetWdmWaveState
;
881 FuncTable
.Open
= OpenWdmSoundDevice
;
882 FuncTable
.Close
= CloseWdmSoundDevice
;
883 FuncTable
.GetDeviceInterfaceString
= GetDeviceInterfaceString
;
884 #ifndef USERMODE_MIXER
885 FuncTable
.CommitWaveBuffer
= WriteFileEx_Committer2
;
887 FuncTable
.CommitWaveBuffer
= WriteFileEx_Remixer
;
889 FuncTable
.GetPos
= GetWdmPosition
;
891 SetSoundDeviceFunctionTable(SoundDevice
, &FuncTable
);
894 return MMSYSERR_NOERROR
;
915 SND_TRACE(L
"DRV_LOAD\n");
917 Result
= InitEntrypointMutexes();
919 if ( ! MMSUCCESS(Result
) )
922 OpenWdmSoundDevice(NULL
, &Handle
);
924 if ( Handle
== INVALID_HANDLE_VALUE
)
926 SND_ERR(L
"Failed to open %s\n", KERNEL_DEVICE_NAME
);
927 CleanupEntrypointMutexes();
929 //UnlistAllSoundDevices();
934 /* Populate the device lists */
935 SND_TRACE(L
"Populating device lists\n");
936 PopulateWdmDeviceList(KernelHandle
, WAVE_OUT_DEVICE_TYPE
);
937 PopulateWdmDeviceList(KernelHandle
, WAVE_IN_DEVICE_TYPE
);
938 PopulateWdmDeviceList(KernelHandle
, MIDI_OUT_DEVICE_TYPE
);
939 PopulateWdmDeviceList(KernelHandle
, MIDI_IN_DEVICE_TYPE
);
940 PopulateWdmDeviceList(KernelHandle
, AUX_DEVICE_TYPE
);
941 PopulateWdmDeviceList(KernelHandle
, MIXER_DEVICE_TYPE
);
943 SND_TRACE(L
"Initialisation complete\n");
950 SND_TRACE(L
"DRV_FREE\n");
952 if ( KernelHandle
!= INVALID_HANDLE_VALUE
)
954 CloseHandle(KernelHandle
);
955 KernelHandle
= INVALID_HANDLE_VALUE
;
958 /* TODO: Clean up the path names! */
959 UnlistAllSoundDevices();
961 CleanupEntrypointMutexes();
963 SND_TRACE(L
"Unfreed memory blocks: %d\n",
964 GetMemoryAllocationCount());
972 SND_TRACE(L
"DRV_ENABLE / DRV_DISABLE\n");
979 SND_TRACE(L
"DRV_OPEN / DRV_CLOSE\n");
983 case DRV_QUERYCONFIGURE
:
985 SND_TRACE(L
"DRV_QUERYCONFIGURE\n");
992 SND_TRACE(L
"Unhandled message %d\n", Message
);
993 return DefDriverProc(DriverId
,
1002 BOOL WINAPI
DllMain(
1007 switch ( fdwReason
)
1009 case DLL_PROCESS_ATTACH
:
1010 SND_TRACE(L
"WDMAUD.DRV - Process attached\n");
1012 case DLL_PROCESS_DETACH
:
1013 SND_TRACE(L
"WDMAUD.DRV - Process detached\n");
1015 case DLL_THREAD_ATTACH
:
1016 SND_TRACE(L
"WDMAUD.DRV - Thread attached\n");
1018 case DLL_THREAD_DETACH
:
1019 SND_TRACE(L
"WDMAUD.DRV - Thread detached\n");