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 */
326 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
327 IOCTL_GET_MIXER_EVENT
,
328 (LPVOID
) &DeviceInfo
,
329 sizeof(WDMAUD_DEVICE_INFO
),
330 (LPVOID
) &DeviceInfo
,
331 sizeof(WDMAUD_DEVICE_INFO
),
334 if (Result
== MMSYSERR_NOERROR
)
336 DriverCallback(Instance
->WinMM
.ClientCallback
,
337 HIWORD(Instance
->WinMM
.Flags
),
338 Instance
->WinMM
.Handle
,
339 DeviceInfo
.u
.MixerEvent
.NotificationType
,
340 Instance
->WinMM
.ClientCallbackInstanceData
,
341 (DWORD_PTR
)DeviceInfo
.u
.MixerEvent
.Value
,
344 }while(Result
== MMSYSERR_NOERROR
);
353 SetWdmMixerDeviceFormat(
354 IN PSOUND_DEVICE_INSTANCE Instance
,
356 IN PWAVEFORMATEX WaveFormat
,
357 IN DWORD WaveFormatSize
)
360 WDMAUD_DEVICE_INFO DeviceInfo
;
363 if (Instance
->Handle
!= KernelHandle
)
365 /* device is already open */
366 return MMSYSERR_NOERROR
;
369 Instance
->hNotifyEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
370 if ( ! Instance
->hNotifyEvent
)
371 return MMSYSERR_NOMEM
;
373 Instance
->hStopEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
374 if ( ! Instance
->hStopEvent
)
375 return MMSYSERR_NOMEM
;
377 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
378 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
379 DeviceInfo
.DeviceIndex
= DeviceId
;
380 DeviceInfo
.u
.hNotifyEvent
= Instance
->hNotifyEvent
;
382 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
384 (LPVOID
) &DeviceInfo
,
385 sizeof(WDMAUD_DEVICE_INFO
),
386 (LPVOID
) &DeviceInfo
,
387 sizeof(WDMAUD_DEVICE_INFO
),
390 if ( ! MMSUCCESS(Result
) )
392 CloseHandle(Instance
->hNotifyEvent
);
393 CloseHandle(Instance
->hStopEvent
);
394 return TranslateInternalMmResult(Result
);
397 hThread
= CreateThread(NULL
, 0, MixerEventThreadRoutine
, (LPVOID
)Instance
, 0, NULL
);
400 CloseHandle(hThread
);
403 /* Store sound device handle instance handle */
404 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
406 return MMSYSERR_NOERROR
;
410 SetWdmWaveDeviceFormat(
411 IN PSOUND_DEVICE_INSTANCE Instance
,
413 IN PWAVEFORMATEX WaveFormat
,
414 IN DWORD WaveFormatSize
)
417 PSOUND_DEVICE SoundDevice
;
419 WDMAUD_DEVICE_INFO DeviceInfo
;
420 MMDEVICE_TYPE DeviceType
;
422 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
424 if ( ! MMSUCCESS(Result
) )
426 return TranslateInternalMmResult(Result
);
429 Result
= GetSoundDeviceIdentifier(SoundDevice
, &Identifier
);
431 if ( ! MMSUCCESS(Result
) )
433 return TranslateInternalMmResult(Result
);
436 if (Instance
->Handle
!= KernelHandle
)
438 /* device is already open */
439 return MMSYSERR_NOERROR
;
443 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
444 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
446 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
447 DeviceInfo
.DeviceType
= DeviceType
;
448 DeviceInfo
.DeviceIndex
= DeviceId
;
449 DeviceInfo
.u
.WaveFormatEx
.cbSize
= sizeof(WAVEFORMATEX
); //WaveFormat->cbSize;
450 DeviceInfo
.u
.WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
451 #ifdef USERMODE_MIXER
452 DeviceInfo
.u
.WaveFormatEx
.nChannels
= 2;
453 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= 44100;
454 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= 4;
455 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= 176400;
456 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= 16;
458 DeviceInfo
.u
.WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
459 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
460 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
461 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
462 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
465 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
467 (LPVOID
) &DeviceInfo
,
468 sizeof(WDMAUD_DEVICE_INFO
),
469 (LPVOID
) &DeviceInfo
,
470 sizeof(WDMAUD_DEVICE_INFO
),
473 if ( ! MMSUCCESS(Result
) )
475 return TranslateInternalMmResult(Result
);
479 Instance
->WaveFormatEx
.cbSize
= WaveFormat
->cbSize
;
480 Instance
->WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
481 Instance
->WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
482 Instance
->WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
483 Instance
->WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
484 Instance
->WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
485 Instance
->WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
487 /* Store sound device handle instance handle */
488 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
490 /* Now determine framing requirements */
491 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
493 (LPVOID
) &DeviceInfo
,
494 sizeof(WDMAUD_DEVICE_INFO
),
495 (LPVOID
) &DeviceInfo
,
496 sizeof(WDMAUD_DEVICE_INFO
),
499 if ( MMSUCCESS(Result
) )
501 if (DeviceInfo
.u
.FrameSize
)
503 Instance
->FrameSize
= DeviceInfo
.u
.FrameSize
* 2;
504 Instance
->BufferCount
= WaveFormat
->nAvgBytesPerSec
/ Instance
->FrameSize
;
505 SND_TRACE(L
"FrameSize %u BufferCount %u\n", Instance
->FrameSize
, Instance
->BufferCount
);
510 // use a default of 100 buffers
511 Instance
->BufferCount
= 100;
514 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
516 /* Now start the stream */
517 DeviceInfo
.u
.State
= KSSTATE_RUN
;
518 SyncOverlappedDeviceIoControl(KernelHandle
,
519 IOCTL_SETDEVICE_STATE
,
520 (LPVOID
) &DeviceInfo
,
521 sizeof(WDMAUD_DEVICE_INFO
),
522 (LPVOID
) &DeviceInfo
,
523 sizeof(WDMAUD_DEVICE_INFO
),
527 return MMSYSERR_NOERROR
;
531 WriteFileEx_Committer2(
532 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
535 IN PSOUND_OVERLAPPED Overlap
,
536 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
)
540 WDMAUD_DEVICE_INFO DeviceInfo
;
541 PSOUND_DEVICE SoundDevice
;
542 MMDEVICE_TYPE DeviceType
;
545 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance
);
546 VALIDATE_MMSYS_PARAMETER( OffsetPtr
);
547 VALIDATE_MMSYS_PARAMETER( Overlap
);
548 VALIDATE_MMSYS_PARAMETER( CompletionRoutine
);
550 GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
553 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
555 if ( ! MMSUCCESS(Result
) )
557 return TranslateInternalMmResult(Result
);
560 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
561 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
565 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
567 DeviceInfo
.Header
.FrameExtent
= Length
;
568 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
570 DeviceInfo
.Header
.DataUsed
= Length
;
572 DeviceInfo
.Header
.Data
= OffsetPtr
;
573 DeviceInfo
.Header
.Size
= sizeof(WDMAUD_DEVICE_INFO
);
574 DeviceInfo
.Header
.PresentationTime
.Numerator
= 1;
575 DeviceInfo
.Header
.PresentationTime
.Denominator
= 1;
576 DeviceInfo
.hDevice
= Handle
;
577 DeviceInfo
.DeviceType
= DeviceType
;
579 Overlap
->Standard
.hEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
581 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
583 Ret
= WriteFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
);
585 WaitForSingleObjectEx (KernelHandle
, INFINITE
, TRUE
);
587 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
589 Ret
= ReadFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
);
591 // WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
594 return MMSYSERR_NOERROR
;
599 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
603 PSOUND_DEVICE SoundDevice
;
604 WDMAUD_DEVICE_INFO DeviceInfo
;
605 MMDEVICE_TYPE DeviceType
;
608 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
610 if ( ! MMSUCCESS(Result
) )
612 return TranslateInternalMmResult(Result
);
615 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
616 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
618 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
619 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
621 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
622 DeviceInfo
.hDevice
= Handle
;
623 DeviceInfo
.DeviceType
= DeviceType
;
626 DeviceInfo
.u
.State
= KSSTATE_RUN
;
628 DeviceInfo
.u
.State
= KSSTATE_PAUSE
;
629 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
630 IOCTL_SETDEVICE_STATE
,
631 (LPVOID
) &DeviceInfo
,
632 sizeof(WDMAUD_DEVICE_INFO
),
633 (LPVOID
) &DeviceInfo
,
634 sizeof(WDMAUD_DEVICE_INFO
),
641 GetDeviceInterfaceString(
642 IN MMDEVICE_TYPE DeviceType
,
645 IN DWORD InterfaceLength
,
646 OUT DWORD
* InterfaceSize
)
648 WDMAUD_DEVICE_INFO DeviceInfo
;
651 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
652 DeviceInfo
.DeviceType
= DeviceType
;
653 DeviceInfo
.DeviceIndex
= DeviceId
;
656 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
657 IOCTL_QUERYDEVICEINTERFACESTRING
,
658 (LPVOID
) &DeviceInfo
,
659 sizeof(WDMAUD_DEVICE_INFO
),
660 (LPVOID
) &DeviceInfo
,
661 sizeof(WDMAUD_DEVICE_INFO
),
665 if ( ! MMSUCCESS(Result
) )
667 return TranslateInternalMmResult(Result
);
673 SND_ASSERT(InterfaceSize
);
675 *InterfaceSize
= DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
;
676 return MMSYSERR_NOERROR
;
679 if (InterfaceLength
< DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
)
681 /* buffer is too small */
682 return MMSYSERR_MOREDATA
;
685 DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
= InterfaceLength
;
686 DeviceInfo
.u
.Interface
.DeviceInterfaceString
= Interface
;
688 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
689 IOCTL_QUERYDEVICEINTERFACESTRING
,
690 (LPVOID
) &DeviceInfo
,
691 sizeof(WDMAUD_DEVICE_INFO
),
692 (LPVOID
) &DeviceInfo
,
693 sizeof(WDMAUD_DEVICE_INFO
),
696 if ( MMSUCCESS(Result
) && InterfaceLength
> 2)
698 Interface
[1] = L
'\\';
699 Interface
[InterfaceLength
-1] = L
'\0';
707 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
711 PSOUND_DEVICE SoundDevice
;
712 WDMAUD_DEVICE_INFO DeviceInfo
;
713 MMDEVICE_TYPE DeviceType
;
716 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
718 if ( ! MMSUCCESS(Result
) )
720 return TranslateInternalMmResult(Result
);
723 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
724 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
726 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
727 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
729 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
730 DeviceInfo
.hDevice
= Handle
;
731 DeviceInfo
.DeviceType
= DeviceType
;
733 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
735 (LPVOID
) &DeviceInfo
,
736 sizeof(WDMAUD_DEVICE_INFO
),
737 (LPVOID
) &DeviceInfo
,
738 sizeof(WDMAUD_DEVICE_INFO
),
741 if ( ! MMSUCCESS(Result
) )
743 return TranslateInternalMmResult(Result
);
746 Time
->wType
= TIME_BYTES
;
747 Time
->u
.cb
= (DWORD
)DeviceInfo
.u
.Position
;
749 return MMSYSERR_NOERROR
;
754 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
755 IN MMDEVICE_TYPE DeviceType
,
756 IN BOOLEAN bStartReset
)
760 WDMAUD_DEVICE_INFO DeviceInfo
;
762 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
763 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
765 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
766 DeviceInfo
.hDevice
= Handle
;
767 DeviceInfo
.DeviceType
= DeviceType
;
768 DeviceInfo
.u
.ResetStream
= (bStartReset
? KSRESET_BEGIN
: KSRESET_END
);
770 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
772 (LPVOID
) &DeviceInfo
,
773 sizeof(WDMAUD_DEVICE_INFO
),
774 (LPVOID
) &DeviceInfo
,
775 sizeof(WDMAUD_DEVICE_INFO
),
783 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
789 WDMAUD_DEVICE_INFO DeviceInfo
;
792 LPMIXERLINEW MixLine
;
793 LPMIXERLINECONTROLSW MixControls
;
794 LPMIXERCONTROLDETAILS MixDetails
;
796 SND_TRACE(L
"uMsg %x Flags %x\n", uMsg
, Flags
);
798 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
799 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
801 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
802 DeviceInfo
.hDevice
= Handle
;
803 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
804 DeviceInfo
.Flags
= Flags
;
806 MixLine
= (LPMIXERLINEW
)Parameter
;
807 MixControls
= (LPMIXERLINECONTROLSW
)Parameter
;
808 MixDetails
= (LPMIXERCONTROLDETAILS
)Parameter
;
812 case MXDM_GETLINEINFO
:
813 RtlCopyMemory(&DeviceInfo
.u
.MixLine
, MixLine
, sizeof(MIXERLINEW
));
814 IoControlCode
= IOCTL_GETLINEINFO
;
816 case MXDM_GETLINECONTROLS
:
817 RtlCopyMemory(&DeviceInfo
.u
.MixControls
, MixControls
, sizeof(MIXERLINECONTROLSW
));
818 IoControlCode
= IOCTL_GETLINECONTROLS
;
820 case MXDM_SETCONTROLDETAILS
:
821 RtlCopyMemory(&DeviceInfo
.u
.MixDetails
, MixDetails
, sizeof(MIXERCONTROLDETAILS
));
822 IoControlCode
= IOCTL_SETCONTROLDETAILS
;
824 case MXDM_GETCONTROLDETAILS
:
825 RtlCopyMemory(&DeviceInfo
.u
.MixDetails
, MixDetails
, sizeof(MIXERCONTROLDETAILS
));
826 IoControlCode
= IOCTL_GETCONTROLDETAILS
;
830 return MMSYSERR_NOTSUPPORTED
;
833 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
835 (LPVOID
) &DeviceInfo
,
836 sizeof(WDMAUD_DEVICE_INFO
),
837 (LPVOID
) &DeviceInfo
,
838 sizeof(WDMAUD_DEVICE_INFO
),
841 if ( ! MMSUCCESS(Result
) )
848 case MXDM_GETLINEINFO
:
850 RtlCopyMemory(MixLine
, &DeviceInfo
.u
.MixLine
, sizeof(MIXERLINEW
));
860 PopulateWdmDeviceList(
862 MMDEVICE_TYPE DeviceType
)
865 DWORD DeviceCount
= 0;
866 PSOUND_DEVICE SoundDevice
= NULL
;
867 MMFUNCTION_TABLE FuncTable
;
870 VALIDATE_MMSYS_PARAMETER( Handle
!= INVALID_HANDLE_VALUE
);
871 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
873 Result
= GetNumWdmDevs(Handle
, DeviceType
, &DeviceCount
);
875 if ( ! MMSUCCESS(Result
) )
877 SND_ERR(L
"Error %d while obtaining number of devices\n", Result
);
878 return TranslateInternalMmResult(Result
);
881 SND_TRACE(L
"%d devices of type %d found\n", DeviceCount
, DeviceType
);
884 for ( i
= 0; i
< DeviceCount
; ++ i
)
886 Result
= ListSoundDevice(DeviceType
, (PVOID
) i
, &SoundDevice
);
888 if ( ! MMSUCCESS(Result
) )
890 SND_ERR(L
"Failed to list sound device - error %d\n", Result
);
891 return TranslateInternalMmResult(Result
);
894 /* Set up our function table */
895 ZeroMemory(&FuncTable
, sizeof(MMFUNCTION_TABLE
));
896 FuncTable
.GetCapabilities
= GetWdmDeviceCapabilities
;
897 FuncTable
.QueryWaveFormatSupport
= QueryWdmWaveDeviceFormatSupport
;
898 if (DeviceType
== MIXER_DEVICE_TYPE
)
900 FuncTable
.SetWaveFormat
= SetWdmMixerDeviceFormat
;
901 FuncTable
.QueryMixerInfo
= QueryMixerInfo
;
905 FuncTable
.SetWaveFormat
= SetWdmWaveDeviceFormat
;
908 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
910 FuncTable
.SetState
= SetWdmWaveState
;
911 FuncTable
.ResetStream
= ResetStream
;
914 FuncTable
.Open
= OpenWdmSoundDevice
;
915 FuncTable
.Close
= CloseWdmSoundDevice
;
916 FuncTable
.GetDeviceInterfaceString
= GetDeviceInterfaceString
;
917 #ifndef USERMODE_MIXER
918 FuncTable
.CommitWaveBuffer
= WriteFileEx_Committer2
;
920 FuncTable
.CommitWaveBuffer
= WriteFileEx_Remixer
;
922 FuncTable
.GetPos
= GetWdmPosition
;
924 SetSoundDeviceFunctionTable(SoundDevice
, &FuncTable
);
927 return MMSYSERR_NOERROR
;
948 SND_TRACE(L
"DRV_LOAD\n");
950 Result
= InitEntrypointMutexes();
952 if ( ! MMSUCCESS(Result
) )
955 OpenWdmSoundDevice(NULL
, &Handle
);
957 if ( Handle
== INVALID_HANDLE_VALUE
)
959 SND_ERR(L
"Failed to open %s\n", KERNEL_DEVICE_NAME
);
960 CleanupEntrypointMutexes();
962 //UnlistAllSoundDevices();
967 /* Populate the device lists */
968 SND_TRACE(L
"Populating device lists\n");
969 PopulateWdmDeviceList(KernelHandle
, WAVE_OUT_DEVICE_TYPE
);
970 PopulateWdmDeviceList(KernelHandle
, WAVE_IN_DEVICE_TYPE
);
971 PopulateWdmDeviceList(KernelHandle
, MIDI_OUT_DEVICE_TYPE
);
972 PopulateWdmDeviceList(KernelHandle
, MIDI_IN_DEVICE_TYPE
);
973 PopulateWdmDeviceList(KernelHandle
, AUX_DEVICE_TYPE
);
974 PopulateWdmDeviceList(KernelHandle
, MIXER_DEVICE_TYPE
);
976 SND_TRACE(L
"Initialisation complete\n");
983 SND_TRACE(L
"DRV_FREE\n");
985 if ( KernelHandle
!= INVALID_HANDLE_VALUE
)
987 CloseHandle(KernelHandle
);
988 KernelHandle
= INVALID_HANDLE_VALUE
;
991 /* TODO: Clean up the path names! */
992 UnlistAllSoundDevices();
994 CleanupEntrypointMutexes();
996 SND_TRACE(L
"Unfreed memory blocks: %d\n",
997 GetMemoryAllocationCount());
1005 SND_TRACE(L
"DRV_ENABLE / DRV_DISABLE\n");
1012 SND_TRACE(L
"DRV_OPEN / DRV_CLOSE\n");
1016 case DRV_QUERYCONFIGURE
:
1018 SND_TRACE(L
"DRV_QUERYCONFIGURE\n");
1021 case DRV_CONFIGURE
:
1025 SND_TRACE(L
"Unhandled message %d\n", Message
);
1026 return DefDriverProc(DriverId
,
1035 BOOL WINAPI
DllMain(
1040 switch ( fdwReason
)
1042 case DLL_PROCESS_ATTACH
:
1043 SND_TRACE(L
"WDMAUD.DRV - Process attached\n");
1045 case DLL_PROCESS_DETACH
:
1046 SND_TRACE(L
"WDMAUD.DRV - Process detached\n");
1048 case DLL_THREAD_ATTACH
:
1049 SND_TRACE(L
"WDMAUD.DRV - Thread attached\n");
1051 case DLL_THREAD_DETACH
:
1052 SND_TRACE(L
"WDMAUD.DRV - Thread detached\n");