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
),
267 CloseHandle(KernelHandle
);
268 KernelHandle
= INVALID_HANDLE_VALUE
;
271 return MMSYSERR_NOERROR
;
276 QueryWdmWaveDeviceFormatSupport(
277 IN PSOUND_DEVICE Device
,
278 IN PWAVEFORMATEX WaveFormat
,
279 IN DWORD WaveFormatSize
)
282 return MMSYSERR_NOERROR
;
287 SetWdmMixerDeviceFormat(
288 IN PSOUND_DEVICE_INSTANCE Instance
,
290 IN PWAVEFORMATEX WaveFormat
,
291 IN DWORD WaveFormatSize
)
294 WDMAUD_DEVICE_INFO DeviceInfo
;
296 if (Instance
->Handle
!= KernelHandle
)
298 /* device is already open */
299 return MMSYSERR_NOERROR
;
303 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
304 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
305 DeviceInfo
.DeviceIndex
= DeviceId
;
307 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
309 (LPVOID
) &DeviceInfo
,
310 sizeof(WDMAUD_DEVICE_INFO
),
311 (LPVOID
) &DeviceInfo
,
312 sizeof(WDMAUD_DEVICE_INFO
),
315 if ( ! MMSUCCESS(Result
) )
317 return TranslateInternalMmResult(Result
);
320 /* Store sound device handle instance handle */
321 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
323 return MMSYSERR_NOERROR
;
327 SetWdmWaveDeviceFormat(
328 IN PSOUND_DEVICE_INSTANCE Instance
,
330 IN PWAVEFORMATEX WaveFormat
,
331 IN DWORD WaveFormatSize
)
334 PSOUND_DEVICE SoundDevice
;
336 WDMAUD_DEVICE_INFO DeviceInfo
;
337 MMDEVICE_TYPE DeviceType
;
339 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
341 if ( ! MMSUCCESS(Result
) )
343 return TranslateInternalMmResult(Result
);
346 Result
= GetSoundDeviceIdentifier(SoundDevice
, &Identifier
);
348 if ( ! MMSUCCESS(Result
) )
350 return TranslateInternalMmResult(Result
);
353 if (Instance
->Handle
!= KernelHandle
)
355 /* device is already open */
356 return MMSYSERR_NOERROR
;
360 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
361 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
363 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
364 DeviceInfo
.DeviceType
= DeviceType
;
365 DeviceInfo
.DeviceIndex
= DeviceId
;
366 DeviceInfo
.u
.WaveFormatEx
.cbSize
= WaveFormat
->cbSize
;
367 DeviceInfo
.u
.WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
368 #ifdef USERMODE_MIXER
369 DeviceInfo
.u
.WaveFormatEx
.nChannels
= 2;
370 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= 44100;
371 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= 4;
372 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= 176400;
373 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= 16;
375 DeviceInfo
.u
.WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
376 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
377 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
378 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
379 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
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 return TranslateInternalMmResult(Result
);
396 Instance
->WaveFormatEx
.cbSize
= WaveFormat
->cbSize
;
397 Instance
->WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
398 Instance
->WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
399 Instance
->WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
400 Instance
->WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
401 Instance
->WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
402 Instance
->WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
404 /* Store sound device handle instance handle */
405 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
407 /* Now determine framing requirements */
408 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
410 (LPVOID
) &DeviceInfo
,
411 sizeof(WDMAUD_DEVICE_INFO
),
412 (LPVOID
) &DeviceInfo
,
413 sizeof(WDMAUD_DEVICE_INFO
),
416 if ( MMSUCCESS(Result
) )
418 if (DeviceInfo
.u
.FrameSize
)
420 Instance
->FrameSize
= DeviceInfo
.u
.FrameSize
* 2;
421 Instance
->BufferCount
= WaveFormat
->nAvgBytesPerSec
/ Instance
->FrameSize
;
422 SND_TRACE(L
"FrameSize %u BufferCount %u\n", Instance
->FrameSize
, Instance
->BufferCount
);
427 // use a default of 100 buffers
428 Instance
->BufferCount
= 100;
432 /* Now start the stream */
433 DeviceInfo
.u
.State
= KSSTATE_RUN
;
434 SyncOverlappedDeviceIoControl(KernelHandle
,
435 IOCTL_SETDEVICE_STATE
,
436 (LPVOID
) &DeviceInfo
,
437 sizeof(WDMAUD_DEVICE_INFO
),
438 (LPVOID
) &DeviceInfo
,
439 sizeof(WDMAUD_DEVICE_INFO
),
442 return MMSYSERR_NOERROR
;
446 WriteFileEx_Committer2(
447 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
450 IN PSOUND_OVERLAPPED Overlap
,
451 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
)
455 WDMAUD_DEVICE_INFO DeviceInfo
;
456 PSOUND_DEVICE SoundDevice
;
457 MMDEVICE_TYPE DeviceType
;
460 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance
);
461 VALIDATE_MMSYS_PARAMETER( OffsetPtr
);
462 VALIDATE_MMSYS_PARAMETER( Overlap
);
463 VALIDATE_MMSYS_PARAMETER( CompletionRoutine
);
465 GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
468 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
470 if ( ! MMSUCCESS(Result
) )
472 return TranslateInternalMmResult(Result
);
475 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
476 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
480 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
482 DeviceInfo
.Header
.FrameExtent
= Length
;
483 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
485 DeviceInfo
.Header
.DataUsed
= Length
;
487 DeviceInfo
.Header
.Data
= OffsetPtr
;
488 DeviceInfo
.Header
.Size
= sizeof(WDMAUD_DEVICE_INFO
);
489 DeviceInfo
.Header
.PresentationTime
.Numerator
= 1;
490 DeviceInfo
.Header
.PresentationTime
.Denominator
= 1;
491 DeviceInfo
.hDevice
= Handle
;
492 DeviceInfo
.DeviceType
= DeviceType
;
494 Overlap
->Standard
.hEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
496 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
498 Ret
= WriteFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
);
500 WaitForSingleObjectEx (KernelHandle
, INFINITE
, TRUE
);
502 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
504 Ret
= ReadFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
);
506 WaitForSingleObjectEx (KernelHandle
, INFINITE
, TRUE
);
509 return MMSYSERR_NOERROR
;
514 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
518 PSOUND_DEVICE SoundDevice
;
519 WDMAUD_DEVICE_INFO DeviceInfo
;
520 MMDEVICE_TYPE DeviceType
;
523 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
525 if ( ! MMSUCCESS(Result
) )
527 return TranslateInternalMmResult(Result
);
530 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
531 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
533 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
534 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
536 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
537 DeviceInfo
.hDevice
= Handle
;
538 DeviceInfo
.DeviceType
= DeviceType
;
540 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
542 (LPVOID
) &DeviceInfo
,
543 sizeof(WDMAUD_DEVICE_INFO
),
544 (LPVOID
) &DeviceInfo
,
545 sizeof(WDMAUD_DEVICE_INFO
),
548 if ( ! MMSUCCESS(Result
) )
550 return TranslateInternalMmResult(Result
);
553 Time
->wType
= TIME_BYTES
;
554 Time
->u
.cb
= (DWORD
)DeviceInfo
.u
.Position
;
556 return MMSYSERR_NOERROR
;
561 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
567 WDMAUD_DEVICE_INFO DeviceInfo
;
570 LPMIXERLINEW MixLine
;
571 LPMIXERLINECONTROLSW MixControls
;
572 LPMIXERCONTROLDETAILS MixDetails
;
574 SND_TRACE(L
"uMsg %x Flags %x\n", uMsg
, Flags
);
576 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
577 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
579 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
580 DeviceInfo
.hDevice
= Handle
;
581 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
582 DeviceInfo
.Flags
= Flags
;
584 MixLine
= (LPMIXERLINEW
)Parameter
;
585 MixControls
= (LPMIXERLINECONTROLSW
)Parameter
;
586 MixDetails
= (LPMIXERCONTROLDETAILS
)Parameter
;
590 case MXDM_GETLINEINFO
:
591 RtlCopyMemory(&DeviceInfo
.u
.MixLine
, MixLine
, sizeof(MIXERLINEW
));
592 IoControlCode
= IOCTL_GETLINEINFO
;
594 case MXDM_GETLINECONTROLS
:
595 RtlCopyMemory(&DeviceInfo
.u
.MixControls
, MixControls
, sizeof(MIXERLINECONTROLSW
));
596 IoControlCode
= IOCTL_GETLINECONTROLS
;
598 case MXDM_SETCONTROLDETAILS
:
599 RtlCopyMemory(&DeviceInfo
.u
.MixDetails
, MixDetails
, sizeof(MIXERCONTROLDETAILS
));
600 IoControlCode
= IOCTL_SETCONTROLDETAILS
;
602 case MXDM_GETCONTROLDETAILS
:
603 RtlCopyMemory(&DeviceInfo
.u
.MixDetails
, MixDetails
, sizeof(MIXERCONTROLDETAILS
));
604 IoControlCode
= IOCTL_GETCONTROLDETAILS
;
610 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
612 (LPVOID
) &DeviceInfo
,
613 sizeof(WDMAUD_DEVICE_INFO
),
614 (LPVOID
) &DeviceInfo
,
615 sizeof(WDMAUD_DEVICE_INFO
),
618 if ( ! MMSUCCESS(Result
) )
620 return TranslateInternalMmResult(Result
);
625 case MXDM_GETLINEINFO
:
627 RtlCopyMemory(MixLine
, &DeviceInfo
.u
.MixLine
, sizeof(MIXERLINEW
));
637 PopulateWdmDeviceList(
639 MMDEVICE_TYPE DeviceType
)
642 DWORD DeviceCount
= 0;
643 PSOUND_DEVICE SoundDevice
= NULL
;
644 MMFUNCTION_TABLE FuncTable
;
647 VALIDATE_MMSYS_PARAMETER( Handle
!= INVALID_HANDLE_VALUE
);
648 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
650 Result
= GetNumWdmDevs(Handle
, DeviceType
, &DeviceCount
);
652 if ( ! MMSUCCESS(Result
) )
654 SND_ERR(L
"Error %d while obtaining number of devices\n", Result
);
655 return TranslateInternalMmResult(Result
);
658 SND_TRACE(L
"%d devices of type %d found\n", DeviceCount
, DeviceType
);
661 for ( i
= 0; i
< DeviceCount
; ++ i
)
663 Result
= ListSoundDevice(DeviceType
, (PVOID
) i
, &SoundDevice
);
665 if ( ! MMSUCCESS(Result
) )
667 SND_ERR(L
"Failed to list sound device - error %d\n", Result
);
668 return TranslateInternalMmResult(Result
);
671 /* Set up our function table */
672 ZeroMemory(&FuncTable
, sizeof(MMFUNCTION_TABLE
));
673 FuncTable
.GetCapabilities
= GetWdmDeviceCapabilities
;
674 FuncTable
.QueryWaveFormatSupport
= QueryWdmWaveDeviceFormatSupport
;
675 if (DeviceType
== MIXER_DEVICE_TYPE
)
677 FuncTable
.SetWaveFormat
= SetWdmMixerDeviceFormat
;
678 FuncTable
.QueryMixerInfo
= QueryMixerInfo
;
682 FuncTable
.SetWaveFormat
= SetWdmWaveDeviceFormat
;
685 FuncTable
.Open
= OpenWdmSoundDevice
;
686 FuncTable
.Close
= CloseWdmSoundDevice
;
687 #ifndef USERMODE_MIXER
688 FuncTable
.CommitWaveBuffer
= WriteFileEx_Committer2
;
690 FuncTable
.CommitWaveBuffer
= WriteFileEx_Remixer
;
692 FuncTable
.GetPos
= GetWdmPosition
;
694 SetSoundDeviceFunctionTable(SoundDevice
, &FuncTable
);
697 return MMSYSERR_NOERROR
;
718 SND_TRACE(L
"DRV_LOAD\n");
720 Result
= InitEntrypointMutexes();
722 if ( ! MMSUCCESS(Result
) )
725 OpenWdmSoundDevice(NULL
, &Handle
);
727 if ( Handle
== INVALID_HANDLE_VALUE
)
729 SND_ERR(L
"Failed to open %s\n", KERNEL_DEVICE_NAME
);
730 CleanupEntrypointMutexes();
732 //UnlistAllSoundDevices();
737 /* Populate the device lists */
738 SND_TRACE(L
"Populating device lists\n");
739 PopulateWdmDeviceList(KernelHandle
, WAVE_OUT_DEVICE_TYPE
);
740 PopulateWdmDeviceList(KernelHandle
, WAVE_IN_DEVICE_TYPE
);
741 PopulateWdmDeviceList(KernelHandle
, MIDI_OUT_DEVICE_TYPE
);
742 PopulateWdmDeviceList(KernelHandle
, MIDI_IN_DEVICE_TYPE
);
743 PopulateWdmDeviceList(KernelHandle
, AUX_DEVICE_TYPE
);
744 PopulateWdmDeviceList(KernelHandle
, MIXER_DEVICE_TYPE
);
746 SND_TRACE(L
"Initialisation complete\n");
753 SND_TRACE(L
"DRV_FREE\n");
755 if ( KernelHandle
!= INVALID_HANDLE_VALUE
)
757 CloseHandle(KernelHandle
);
758 KernelHandle
= INVALID_HANDLE_VALUE
;
761 /* TODO: Clean up the path names! */
762 UnlistAllSoundDevices();
764 CleanupEntrypointMutexes();
766 SND_TRACE(L
"Unfreed memory blocks: %d\n",
767 GetMemoryAllocationCount());
775 SND_TRACE(L
"DRV_ENABLE / DRV_DISABLE\n");
782 SND_TRACE(L
"DRV_OPEN / DRV_CLOSE\n");
786 case DRV_QUERYCONFIGURE
:
788 SND_TRACE(L
"DRV_QUERYCONFIGURE\n");
795 SND_TRACE(L
"Unhandled message %d\n", Message
);
796 return DefDriverProc(DriverId
,
812 case DLL_PROCESS_ATTACH
:
813 SND_TRACE(L
"WDMAUD.DRV - Process attached\n");
815 case DLL_PROCESS_DETACH
:
816 SND_TRACE(L
"WDMAUD.DRV - Process detached\n");
818 case DLL_THREAD_ATTACH
:
819 SND_TRACE(L
"WDMAUD.DRV - Thread attached\n");
821 case DLL_THREAD_DETACH
:
822 SND_TRACE(L
"WDMAUD.DRV - Thread detached\n");