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
;
334 SetWdmMixerDeviceFormat(
335 IN PSOUND_DEVICE_INSTANCE Instance
,
337 IN PWAVEFORMATEX WaveFormat
,
338 IN DWORD WaveFormatSize
)
341 WDMAUD_DEVICE_INFO DeviceInfo
;
345 Instance
->hNotifyEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
346 if ( ! Instance
->hNotifyEvent
)
347 return MMSYSERR_NOMEM
;
349 #ifdef USE_MMIXER_LIB
350 return WdmAudOpenMixer(&Instance
->Handle
, DeviceId
, Instance
->hNotifyEvent
);
353 if (Instance
->Handle
!= KernelHandle
)
355 /* device is already open */
356 return MMSYSERR_NOERROR
;
359 Instance
->hStopEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
360 if ( ! Instance
->hStopEvent
)
361 return MMSYSERR_NOMEM
;
363 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
364 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
365 DeviceInfo
.DeviceIndex
= DeviceId
;
366 DeviceInfo
.u
.hNotifyEvent
= Instance
->hNotifyEvent
;
368 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
370 (LPVOID
) &DeviceInfo
,
371 sizeof(WDMAUD_DEVICE_INFO
),
372 (LPVOID
) &DeviceInfo
,
373 sizeof(WDMAUD_DEVICE_INFO
),
376 if ( ! MMSUCCESS(Result
) )
378 CloseHandle(Instance
->hNotifyEvent
);
379 CloseHandle(Instance
->hStopEvent
);
380 return TranslateInternalMmResult(Result
);
383 hThread
= CreateThread(NULL
, 0, MixerEventThreadRoutine
, (LPVOID
)Instance
, 0, NULL
);
386 CloseHandle(hThread
);
389 /* Store sound device handle instance handle */
390 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
392 return MMSYSERR_NOERROR
;
396 SetWdmWaveDeviceFormat(
397 IN PSOUND_DEVICE_INSTANCE Instance
,
399 IN PWAVEFORMATEX WaveFormat
,
400 IN DWORD WaveFormatSize
)
403 PSOUND_DEVICE SoundDevice
;
405 WDMAUD_DEVICE_INFO DeviceInfo
;
406 MMDEVICE_TYPE DeviceType
;
408 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
410 if ( ! MMSUCCESS(Result
) )
412 return TranslateInternalMmResult(Result
);
415 Result
= GetSoundDeviceIdentifier(SoundDevice
, &Identifier
);
417 if ( ! MMSUCCESS(Result
) )
419 return TranslateInternalMmResult(Result
);
422 if (Instance
->Handle
!= KernelHandle
)
424 /* device is already open */
425 return MMSYSERR_NOERROR
;
428 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
430 #ifdef USE_MMIXER_LIB
431 return WdmAudOpenWavePin(Instance
, DeviceId
, WaveFormat
, DeviceType
);
435 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
437 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
438 DeviceInfo
.DeviceType
= DeviceType
;
439 DeviceInfo
.DeviceIndex
= DeviceId
;
440 DeviceInfo
.u
.WaveFormatEx
.cbSize
= sizeof(WAVEFORMATEX
); //WaveFormat->cbSize;
441 DeviceInfo
.u
.WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
442 #ifdef USERMODE_MIXER
443 DeviceInfo
.u
.WaveFormatEx
.nChannels
= 2;
444 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= 44100;
445 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= 4;
446 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= 176400;
447 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= 16;
449 DeviceInfo
.u
.WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
450 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
451 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
452 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
453 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
456 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
458 (LPVOID
) &DeviceInfo
,
459 sizeof(WDMAUD_DEVICE_INFO
),
460 (LPVOID
) &DeviceInfo
,
461 sizeof(WDMAUD_DEVICE_INFO
),
464 if ( ! MMSUCCESS(Result
) )
466 return TranslateInternalMmResult(Result
);
470 Instance
->WaveFormatEx
.cbSize
= WaveFormat
->cbSize
;
471 Instance
->WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
472 Instance
->WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
473 Instance
->WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
474 Instance
->WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
475 Instance
->WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
476 Instance
->WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
478 /* Store sound device handle instance handle */
479 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
481 /* Now determine framing requirements */
482 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
484 (LPVOID
) &DeviceInfo
,
485 sizeof(WDMAUD_DEVICE_INFO
),
486 (LPVOID
) &DeviceInfo
,
487 sizeof(WDMAUD_DEVICE_INFO
),
490 if ( MMSUCCESS(Result
) )
492 if (DeviceInfo
.u
.FrameSize
)
494 Instance
->FrameSize
= DeviceInfo
.u
.FrameSize
* 2;
495 Instance
->BufferCount
= WaveFormat
->nAvgBytesPerSec
/ Instance
->FrameSize
;
496 SND_TRACE(L
"FrameSize %u BufferCount %u\n", Instance
->FrameSize
, Instance
->BufferCount
);
501 // use a default of 100 buffers
502 Instance
->BufferCount
= 100;
505 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
507 /* Now start the stream */
508 DeviceInfo
.u
.State
= KSSTATE_RUN
;
509 SyncOverlappedDeviceIoControl(KernelHandle
,
510 IOCTL_SETDEVICE_STATE
,
511 (LPVOID
) &DeviceInfo
,
512 sizeof(WDMAUD_DEVICE_INFO
),
513 (LPVOID
) &DeviceInfo
,
514 sizeof(WDMAUD_DEVICE_INFO
),
518 return MMSYSERR_NOERROR
;
524 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
528 PSOUND_DEVICE SoundDevice
;
529 WDMAUD_DEVICE_INFO DeviceInfo
;
530 MMDEVICE_TYPE DeviceType
;
533 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
535 if ( ! MMSUCCESS(Result
) )
537 return TranslateInternalMmResult(Result
);
540 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
541 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
543 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
544 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
546 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
547 DeviceInfo
.hDevice
= Handle
;
548 DeviceInfo
.DeviceType
= DeviceType
;
551 DeviceInfo
.u
.State
= KSSTATE_RUN
;
553 DeviceInfo
.u
.State
= KSSTATE_PAUSE
;
554 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
555 IOCTL_SETDEVICE_STATE
,
556 (LPVOID
) &DeviceInfo
,
557 sizeof(WDMAUD_DEVICE_INFO
),
558 (LPVOID
) &DeviceInfo
,
559 sizeof(WDMAUD_DEVICE_INFO
),
566 GetDeviceInterfaceString(
567 IN MMDEVICE_TYPE DeviceType
,
570 IN DWORD InterfaceLength
,
571 OUT DWORD
* InterfaceSize
)
573 WDMAUD_DEVICE_INFO DeviceInfo
;
576 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
577 DeviceInfo
.DeviceType
= DeviceType
;
578 DeviceInfo
.DeviceIndex
= DeviceId
;
581 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
582 IOCTL_QUERYDEVICEINTERFACESTRING
,
583 (LPVOID
) &DeviceInfo
,
584 sizeof(WDMAUD_DEVICE_INFO
),
585 (LPVOID
) &DeviceInfo
,
586 sizeof(WDMAUD_DEVICE_INFO
),
590 if ( ! MMSUCCESS(Result
) )
592 return TranslateInternalMmResult(Result
);
598 SND_ASSERT(InterfaceSize
);
600 *InterfaceSize
= DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
;
601 return MMSYSERR_NOERROR
;
604 if (InterfaceLength
< DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
)
606 /* buffer is too small */
607 return MMSYSERR_MOREDATA
;
610 DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
= InterfaceLength
;
611 DeviceInfo
.u
.Interface
.DeviceInterfaceString
= Interface
;
613 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
614 IOCTL_QUERYDEVICEINTERFACESTRING
,
615 (LPVOID
) &DeviceInfo
,
616 sizeof(WDMAUD_DEVICE_INFO
),
617 (LPVOID
) &DeviceInfo
,
618 sizeof(WDMAUD_DEVICE_INFO
),
621 if ( MMSUCCESS(Result
) && InterfaceLength
> 2)
623 Interface
[1] = L
'\\';
624 Interface
[InterfaceLength
-1] = L
'\0';
632 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
636 PSOUND_DEVICE SoundDevice
;
637 WDMAUD_DEVICE_INFO DeviceInfo
;
638 MMDEVICE_TYPE DeviceType
;
641 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
643 if ( ! MMSUCCESS(Result
) )
645 return TranslateInternalMmResult(Result
);
648 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
649 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
651 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
652 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
654 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
655 DeviceInfo
.hDevice
= Handle
;
656 DeviceInfo
.DeviceType
= DeviceType
;
658 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
660 (LPVOID
) &DeviceInfo
,
661 sizeof(WDMAUD_DEVICE_INFO
),
662 (LPVOID
) &DeviceInfo
,
663 sizeof(WDMAUD_DEVICE_INFO
),
666 if ( ! MMSUCCESS(Result
) )
668 return TranslateInternalMmResult(Result
);
671 Time
->wType
= TIME_BYTES
;
672 Time
->u
.cb
= (DWORD
)DeviceInfo
.u
.Position
;
674 return MMSYSERR_NOERROR
;
679 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
680 IN MMDEVICE_TYPE DeviceType
,
681 IN BOOLEAN bStartReset
)
685 WDMAUD_DEVICE_INFO DeviceInfo
;
687 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
688 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
690 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
691 DeviceInfo
.hDevice
= Handle
;
692 DeviceInfo
.DeviceType
= DeviceType
;
693 DeviceInfo
.u
.ResetStream
= (bStartReset
? KSRESET_BEGIN
: KSRESET_END
);
695 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
697 (LPVOID
) &DeviceInfo
,
698 sizeof(WDMAUD_DEVICE_INFO
),
699 (LPVOID
) &DeviceInfo
,
700 sizeof(WDMAUD_DEVICE_INFO
),
708 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
714 WDMAUD_DEVICE_INFO DeviceInfo
;
717 LPMIXERLINEW MixLine
;
718 LPMIXERLINECONTROLSW MixControls
;
719 LPMIXERCONTROLDETAILS MixDetails
;
721 SND_TRACE(L
"uMsg %x Flags %x\n", uMsg
, Flags
);
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
= MIXER_DEVICE_TYPE
;
729 DeviceInfo
.Flags
= Flags
;
731 MixLine
= (LPMIXERLINEW
)Parameter
;
732 MixControls
= (LPMIXERLINECONTROLSW
)Parameter
;
733 MixDetails
= (LPMIXERCONTROLDETAILS
)Parameter
;
735 #ifdef USE_MMIXER_LIB
738 case MXDM_GETLINEINFO
:
739 return WdmAudGetLineInfo(SoundDeviceInstance
->Handle
, MixLine
, Flags
);
740 case MXDM_GETLINECONTROLS
:
741 return WdmAudGetLineControls(SoundDeviceInstance
->Handle
, MixControls
, Flags
);
742 case MXDM_SETCONTROLDETAILS
:
743 return WdmAudSetControlDetails(SoundDeviceInstance
->Handle
, MixDetails
, Flags
);
745 case MXDM_GETCONTROLDETAILS
:
746 return WdmAudGetControlDetails(SoundDeviceInstance
->Handle
, MixDetails
, Flags
);
750 return MMSYSERR_NOTSUPPORTED
;
757 case MXDM_GETLINEINFO
:
758 RtlCopyMemory(&DeviceInfo
.u
.MixLine
, MixLine
, sizeof(MIXERLINEW
));
759 IoControlCode
= IOCTL_GETLINEINFO
;
761 case MXDM_GETLINECONTROLS
:
762 RtlCopyMemory(&DeviceInfo
.u
.MixControls
, MixControls
, sizeof(MIXERLINECONTROLSW
));
763 IoControlCode
= IOCTL_GETLINECONTROLS
;
765 case MXDM_SETCONTROLDETAILS
:
766 RtlCopyMemory(&DeviceInfo
.u
.MixDetails
, MixDetails
, sizeof(MIXERCONTROLDETAILS
));
767 IoControlCode
= IOCTL_SETCONTROLDETAILS
;
769 case MXDM_GETCONTROLDETAILS
:
770 RtlCopyMemory(&DeviceInfo
.u
.MixDetails
, MixDetails
, sizeof(MIXERCONTROLDETAILS
));
771 IoControlCode
= IOCTL_GETCONTROLDETAILS
;
775 return MMSYSERR_NOTSUPPORTED
;
778 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
780 (LPVOID
) &DeviceInfo
,
781 sizeof(WDMAUD_DEVICE_INFO
),
782 (LPVOID
) &DeviceInfo
,
783 sizeof(WDMAUD_DEVICE_INFO
),
786 if ( ! MMSUCCESS(Result
) )
793 case MXDM_GETLINEINFO
:
795 RtlCopyMemory(MixLine
, &DeviceInfo
.u
.MixLine
, sizeof(MIXERLINEW
));
805 PopulateWdmDeviceList(
807 MMDEVICE_TYPE DeviceType
)
810 DWORD DeviceCount
= 0;
811 PSOUND_DEVICE SoundDevice
= NULL
;
812 MMFUNCTION_TABLE FuncTable
;
815 VALIDATE_MMSYS_PARAMETER( Handle
!= INVALID_HANDLE_VALUE
);
816 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
818 Result
= GetNumWdmDevs(Handle
, DeviceType
, &DeviceCount
);
820 if ( ! MMSUCCESS(Result
) )
822 SND_ERR(L
"Error %d while obtaining number of devices\n", Result
);
823 return TranslateInternalMmResult(Result
);
826 SND_TRACE(L
"%d devices of type %d found\n", DeviceCount
, DeviceType
);
829 for ( i
= 0; i
< DeviceCount
; ++ i
)
831 Result
= ListSoundDevice(DeviceType
, UlongToPtr(i
), &SoundDevice
);
833 if ( ! MMSUCCESS(Result
) )
835 SND_ERR(L
"Failed to list sound device - error %d\n", Result
);
836 return TranslateInternalMmResult(Result
);
839 /* Set up our function table */
840 ZeroMemory(&FuncTable
, sizeof(MMFUNCTION_TABLE
));
841 FuncTable
.GetCapabilities
= GetWdmDeviceCapabilities
;
842 FuncTable
.QueryWaveFormatSupport
= QueryWdmWaveDeviceFormatSupport
;
843 if (DeviceType
== MIXER_DEVICE_TYPE
)
845 FuncTable
.SetWaveFormat
= SetWdmMixerDeviceFormat
;
846 FuncTable
.QueryMixerInfo
= QueryMixerInfo
;
850 FuncTable
.SetWaveFormat
= SetWdmWaveDeviceFormat
;
853 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
855 FuncTable
.SetState
= SetWdmWaveState
;
856 FuncTable
.ResetStream
= ResetStream
;
859 FuncTable
.Open
= OpenWdmSoundDevice
;
860 FuncTable
.Close
= CloseWdmSoundDevice
;
861 FuncTable
.GetDeviceInterfaceString
= GetDeviceInterfaceString
;
862 #ifndef USERMODE_MIXER
863 FuncTable
.CommitWaveBuffer
= WriteFileEx_Committer2
;
865 FuncTable
.CommitWaveBuffer
= WriteFileEx_Remixer
;
867 FuncTable
.GetPos
= GetWdmPosition
;
869 SetSoundDeviceFunctionTable(SoundDevice
, &FuncTable
);
872 return MMSYSERR_NOERROR
;
893 SND_TRACE(L
"DRV_LOAD\n");
895 Result
= InitEntrypointMutexes();
897 if ( ! MMSUCCESS(Result
) )
900 OpenWdmSoundDevice(NULL
, &Handle
);
902 if ( Handle
== INVALID_HANDLE_VALUE
)
904 SND_ERR(L
"Failed to open \\\\.\\wdmaud\n");
905 CleanupEntrypointMutexes();
907 //UnlistAllSoundDevices();
912 /* Populate the device lists */
913 SND_TRACE(L
"Populating device lists\n");
914 PopulateWdmDeviceList(KernelHandle
, WAVE_OUT_DEVICE_TYPE
);
915 PopulateWdmDeviceList(KernelHandle
, WAVE_IN_DEVICE_TYPE
);
916 PopulateWdmDeviceList(KernelHandle
, MIDI_OUT_DEVICE_TYPE
);
917 PopulateWdmDeviceList(KernelHandle
, MIDI_IN_DEVICE_TYPE
);
918 PopulateWdmDeviceList(KernelHandle
, AUX_DEVICE_TYPE
);
919 PopulateWdmDeviceList(KernelHandle
, MIXER_DEVICE_TYPE
);
921 SND_TRACE(L
"Initialisation complete\n");
928 SND_TRACE(L
"DRV_FREE\n");
930 if ( KernelHandle
!= INVALID_HANDLE_VALUE
)
932 CloseHandle(KernelHandle
);
933 KernelHandle
= INVALID_HANDLE_VALUE
;
936 /* TODO: Clean up the path names! */
937 UnlistAllSoundDevices();
939 CleanupEntrypointMutexes();
941 SND_TRACE(L
"Unfreed memory blocks: %d\n",
942 GetMemoryAllocationCount());
950 SND_TRACE(L
"DRV_ENABLE / DRV_DISABLE\n");
957 SND_TRACE(L
"DRV_OPEN / DRV_CLOSE\n");
961 case DRV_QUERYCONFIGURE
:
963 SND_TRACE(L
"DRV_QUERYCONFIGURE\n");
970 SND_TRACE(L
"Unhandled message %d\n", Message
);
971 return DefDriverProc(DriverId
,
987 case DLL_PROCESS_ATTACH
:
988 #ifdef USE_MMIXER_LIB
989 WdmAudInitUserModeMixer();
991 SND_TRACE(L
"WDMAUD.DRV - Process attached\n");
993 case DLL_PROCESS_DETACH
:
994 SND_TRACE(L
"WDMAUD.DRV - Process detached\n");
996 case DLL_THREAD_ATTACH
:
997 SND_TRACE(L
"WDMAUD.DRV - Thread attached\n");
999 case DLL_THREAD_DETACH
:
1000 SND_TRACE(L
"WDMAUD.DRV - Thread detached\n");