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
)
47 *DeviceCount
= WdmAudGetMixerCount();
48 return MMSYSERR_NOERROR
;
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
;
83 GetWdmDeviceCapabilities(
84 IN PSOUND_DEVICE SoundDevice
,
86 OUT PVOID Capabilities
,
87 IN DWORD CapabilitiesSize
)
89 /* NOTE - At this time, WDMAUD does not support this properly */
92 MMDEVICE_TYPE DeviceType
;
93 WDMAUD_DEVICE_INFO DeviceInfo
;
95 SND_ASSERT( SoundDevice
);
96 SND_ASSERT( Capabilities
);
98 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
99 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
101 if ( ! MMSUCCESS(Result
) )
104 SND_TRACE(L
"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType
, DeviceId
);
106 #ifdef USE_MMIXER_LIB
107 if (DeviceType
== MIXER_DEVICE_TYPE
)
109 return WdmAudGetMixerCapabilties(DeviceId
, (LPMIXERCAPSW
)Capabilities
);
114 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
115 DeviceInfo
.DeviceType
= DeviceType
;
116 DeviceInfo
.DeviceIndex
= DeviceId
;
118 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
119 IOCTL_GETCAPABILITIES
,
120 (LPVOID
) &DeviceInfo
,
121 sizeof(WDMAUD_DEVICE_INFO
),
122 (LPVOID
) &DeviceInfo
,
123 sizeof(WDMAUD_DEVICE_INFO
),
126 if ( ! MMSUCCESS(Result
) )
128 return TranslateInternalMmResult(Result
);
131 /* This is pretty much a big hack right now */
132 switch ( DeviceType
)
134 case MIXER_DEVICE_TYPE
:
136 LPMIXERCAPS MixerCaps
= (LPMIXERCAPS
) Capabilities
;
138 DeviceInfo
.u
.MixCaps
.szPname
[MAXPNAMELEN
-1] = L
'\0';
139 CopyWideString(MixerCaps
->szPname
, DeviceInfo
.u
.MixCaps
.szPname
);
141 MixerCaps
->cDestinations
= DeviceInfo
.u
.MixCaps
.cDestinations
;
142 MixerCaps
->fdwSupport
= DeviceInfo
.u
.MixCaps
.fdwSupport
;
143 MixerCaps
->vDriverVersion
= DeviceInfo
.u
.MixCaps
.vDriverVersion
;
144 MixerCaps
->wMid
= DeviceInfo
.u
.MixCaps
.wMid
;
145 MixerCaps
->wPid
= DeviceInfo
.u
.MixCaps
.wPid
;
148 case WAVE_OUT_DEVICE_TYPE
:
150 LPWAVEOUTCAPS WaveOutCaps
= (LPWAVEOUTCAPS
) Capabilities
;
152 DeviceInfo
.u
.WaveOutCaps
.szPname
[MAXPNAMELEN
-1] = L
'\0';
153 WaveOutCaps
->wMid
= DeviceInfo
.u
.WaveOutCaps
.wMid
;
154 WaveOutCaps
->wPid
= DeviceInfo
.u
.WaveOutCaps
.wPid
;
156 WaveOutCaps
->vDriverVersion
= 0x0001;
157 CopyWideString(WaveOutCaps
->szPname
, DeviceInfo
.u
.WaveOutCaps
.szPname
);
159 WaveOutCaps
->dwFormats
= DeviceInfo
.u
.WaveOutCaps
.dwFormats
;
160 WaveOutCaps
->wChannels
= DeviceInfo
.u
.WaveOutCaps
.wChannels
;
161 WaveOutCaps
->dwSupport
= DeviceInfo
.u
.WaveOutCaps
.dwSupport
;
164 case WAVE_IN_DEVICE_TYPE
:
166 LPWAVEINCAPSW WaveInCaps
= (LPWAVEINCAPSW
) Capabilities
;
168 DeviceInfo
.u
.WaveInCaps
.szPname
[MAXPNAMELEN
-1] = L
'\0';
170 WaveInCaps
->wMid
= DeviceInfo
.u
.WaveInCaps
.wMid
;
171 WaveInCaps
->wPid
= DeviceInfo
.u
.WaveInCaps
.wPid
;
173 WaveInCaps
->vDriverVersion
= 0x0001;
174 CopyWideString(WaveInCaps
->szPname
, DeviceInfo
.u
.WaveInCaps
.szPname
);
176 WaveInCaps
->dwFormats
= DeviceInfo
.u
.WaveInCaps
.dwFormats
;
177 WaveInCaps
->wChannels
= DeviceInfo
.u
.WaveInCaps
.wChannels
;
178 WaveInCaps
->wReserved1
= 0;
183 return MMSYSERR_NOERROR
;
189 IN
struct _SOUND_DEVICE
* SoundDevice
, /* NOT USED */
192 /* Only open this if it's not already open */
193 if ( KernelHandle
== INVALID_HANDLE_VALUE
)
195 SND_TRACE(L
"Opening wdmaud device\n");
196 KernelHandle
= CreateFileW(KERNEL_DEVICE_NAME
,
197 GENERIC_READ
| GENERIC_WRITE
,
201 FILE_FLAG_OVERLAPPED
,
205 if ( KernelHandle
== INVALID_HANDLE_VALUE
)
206 return MMSYSERR_ERROR
;
208 SND_ASSERT( Handle
);
210 *Handle
= KernelHandle
;
213 return MMSYSERR_NOERROR
;
218 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
221 WDMAUD_DEVICE_INFO DeviceInfo
;
223 MMDEVICE_TYPE DeviceType
;
224 PSOUND_DEVICE SoundDevice
;
226 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
228 if ( ! MMSUCCESS(Result
) )
230 return TranslateInternalMmResult(Result
);
233 if ( OpenCount
== 0 )
235 return MMSYSERR_NOERROR
;
238 SND_ASSERT( KernelHandle
!= INVALID_HANDLE_VALUE
);
240 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
241 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
243 if (SoundDeviceInstance
->Handle
!= (PVOID
)KernelHandle
)
245 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
247 DeviceInfo
.DeviceType
= DeviceType
;
248 DeviceInfo
.hDevice
= SoundDeviceInstance
->Handle
;
250 /* First stop the stream */
251 if (DeviceType
!= MIXER_DEVICE_TYPE
)
253 DeviceInfo
.u
.State
= KSSTATE_STOP
;
254 SyncOverlappedDeviceIoControl(KernelHandle
,
255 IOCTL_SETDEVICE_STATE
,
256 (LPVOID
) &DeviceInfo
,
257 sizeof(WDMAUD_DEVICE_INFO
),
258 (LPVOID
) &DeviceInfo
,
259 sizeof(WDMAUD_DEVICE_INFO
),
262 #ifdef USE_MMIXER_LIB
263 if (DeviceType
== MIXER_DEVICE_TYPE
)
265 return WdmAudCloseMixer(SoundDeviceInstance
->Handle
, SoundDeviceInstance
->hNotifyEvent
);
269 SyncOverlappedDeviceIoControl(KernelHandle
,
271 (LPVOID
) &DeviceInfo
,
272 sizeof(WDMAUD_DEVICE_INFO
),
273 (LPVOID
) &DeviceInfo
,
274 sizeof(WDMAUD_DEVICE_INFO
),
278 if (DeviceType
== MIXER_DEVICE_TYPE
)
280 SetEvent(SoundDeviceInstance
->hStopEvent
);
281 CloseHandle(SoundDeviceInstance
->hStopEvent
);
282 CloseHandle(SoundDeviceInstance
->hNotifyEvent
);
289 CloseHandle(KernelHandle
);
290 KernelHandle
= INVALID_HANDLE_VALUE
;
293 return MMSYSERR_NOERROR
;
298 QueryWdmWaveDeviceFormatSupport(
299 IN PSOUND_DEVICE Device
,
300 IN PWAVEFORMATEX WaveFormat
,
301 IN DWORD WaveFormatSize
)
304 return MMSYSERR_NOERROR
;
310 MixerEventThreadRoutine(
313 HANDLE WaitObjects
[2];
316 WDMAUD_DEVICE_INFO DeviceInfo
;
317 PSOUND_DEVICE_INSTANCE Instance
= (PSOUND_DEVICE_INSTANCE
)Parameter
;
319 /* setup wait objects */
320 WaitObjects
[0] = Instance
->hNotifyEvent
;
321 WaitObjects
[1] = Instance
->hStopEvent
;
323 /* zero device info */
324 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
326 DeviceInfo
.hDevice
= Instance
->Handle
;
327 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
331 dwResult
= WaitForMultipleObjects(2, WaitObjects
, FALSE
, INFINITE
);
333 if (dwResult
== WAIT_OBJECT_0
+ 1)
335 /* stop event was signalled */
341 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
342 IOCTL_GET_MIXER_EVENT
,
343 (LPVOID
) &DeviceInfo
,
344 sizeof(WDMAUD_DEVICE_INFO
),
345 (LPVOID
) &DeviceInfo
,
346 sizeof(WDMAUD_DEVICE_INFO
),
349 if (Result
== MMSYSERR_NOERROR
)
351 DriverCallback(Instance
->WinMM
.ClientCallback
,
352 HIWORD(Instance
->WinMM
.Flags
),
353 Instance
->WinMM
.Handle
,
354 DeviceInfo
.u
.MixerEvent
.NotificationType
,
355 Instance
->WinMM
.ClientCallbackInstanceData
,
356 (DWORD_PTR
)DeviceInfo
.u
.MixerEvent
.Value
,
359 }while(Result
== MMSYSERR_NOERROR
);
368 SetWdmMixerDeviceFormat(
369 IN PSOUND_DEVICE_INSTANCE Instance
,
371 IN PWAVEFORMATEX WaveFormat
,
372 IN DWORD WaveFormatSize
)
375 WDMAUD_DEVICE_INFO DeviceInfo
;
379 Instance
->hNotifyEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
380 if ( ! Instance
->hNotifyEvent
)
381 return MMSYSERR_NOMEM
;
383 #ifdef USE_MMIXER_LIB
384 return WdmAudOpenMixer(&Instance
->Handle
, DeviceId
, Instance
->hNotifyEvent
);
387 if (Instance
->Handle
!= KernelHandle
)
389 /* device is already open */
390 return MMSYSERR_NOERROR
;
393 Instance
->hStopEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
394 if ( ! Instance
->hStopEvent
)
395 return MMSYSERR_NOMEM
;
397 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
398 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
399 DeviceInfo
.DeviceIndex
= DeviceId
;
400 DeviceInfo
.u
.hNotifyEvent
= Instance
->hNotifyEvent
;
402 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
404 (LPVOID
) &DeviceInfo
,
405 sizeof(WDMAUD_DEVICE_INFO
),
406 (LPVOID
) &DeviceInfo
,
407 sizeof(WDMAUD_DEVICE_INFO
),
410 if ( ! MMSUCCESS(Result
) )
412 CloseHandle(Instance
->hNotifyEvent
);
413 CloseHandle(Instance
->hStopEvent
);
414 return TranslateInternalMmResult(Result
);
417 hThread
= CreateThread(NULL
, 0, MixerEventThreadRoutine
, (LPVOID
)Instance
, 0, NULL
);
420 CloseHandle(hThread
);
423 /* Store sound device handle instance handle */
424 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
426 return MMSYSERR_NOERROR
;
430 SetWdmWaveDeviceFormat(
431 IN PSOUND_DEVICE_INSTANCE Instance
,
433 IN PWAVEFORMATEX WaveFormat
,
434 IN DWORD WaveFormatSize
)
437 PSOUND_DEVICE SoundDevice
;
439 WDMAUD_DEVICE_INFO DeviceInfo
;
440 MMDEVICE_TYPE DeviceType
;
442 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
444 if ( ! MMSUCCESS(Result
) )
446 return TranslateInternalMmResult(Result
);
449 Result
= GetSoundDeviceIdentifier(SoundDevice
, &Identifier
);
451 if ( ! MMSUCCESS(Result
) )
453 return TranslateInternalMmResult(Result
);
456 if (Instance
->Handle
!= KernelHandle
)
458 /* device is already open */
459 return MMSYSERR_NOERROR
;
463 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
464 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
466 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
467 DeviceInfo
.DeviceType
= DeviceType
;
468 DeviceInfo
.DeviceIndex
= DeviceId
;
469 DeviceInfo
.u
.WaveFormatEx
.cbSize
= sizeof(WAVEFORMATEX
); //WaveFormat->cbSize;
470 DeviceInfo
.u
.WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
471 #ifdef USERMODE_MIXER
472 DeviceInfo
.u
.WaveFormatEx
.nChannels
= 2;
473 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= 44100;
474 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= 4;
475 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= 176400;
476 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= 16;
478 DeviceInfo
.u
.WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
479 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
480 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
481 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
482 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
485 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
487 (LPVOID
) &DeviceInfo
,
488 sizeof(WDMAUD_DEVICE_INFO
),
489 (LPVOID
) &DeviceInfo
,
490 sizeof(WDMAUD_DEVICE_INFO
),
493 if ( ! MMSUCCESS(Result
) )
495 return TranslateInternalMmResult(Result
);
499 Instance
->WaveFormatEx
.cbSize
= WaveFormat
->cbSize
;
500 Instance
->WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
501 Instance
->WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
502 Instance
->WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
503 Instance
->WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
504 Instance
->WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
505 Instance
->WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
507 /* Store sound device handle instance handle */
508 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
510 /* Now determine framing requirements */
511 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
513 (LPVOID
) &DeviceInfo
,
514 sizeof(WDMAUD_DEVICE_INFO
),
515 (LPVOID
) &DeviceInfo
,
516 sizeof(WDMAUD_DEVICE_INFO
),
519 if ( MMSUCCESS(Result
) )
521 if (DeviceInfo
.u
.FrameSize
)
523 Instance
->FrameSize
= DeviceInfo
.u
.FrameSize
* 2;
524 Instance
->BufferCount
= WaveFormat
->nAvgBytesPerSec
/ Instance
->FrameSize
;
525 SND_TRACE(L
"FrameSize %u BufferCount %u\n", Instance
->FrameSize
, Instance
->BufferCount
);
530 // use a default of 100 buffers
531 Instance
->BufferCount
= 100;
534 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
536 /* Now start the stream */
537 DeviceInfo
.u
.State
= KSSTATE_RUN
;
538 SyncOverlappedDeviceIoControl(KernelHandle
,
539 IOCTL_SETDEVICE_STATE
,
540 (LPVOID
) &DeviceInfo
,
541 sizeof(WDMAUD_DEVICE_INFO
),
542 (LPVOID
) &DeviceInfo
,
543 sizeof(WDMAUD_DEVICE_INFO
),
547 return MMSYSERR_NOERROR
;
551 WriteFileEx_Committer2(
552 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
555 IN PSOUND_OVERLAPPED Overlap
,
556 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
)
560 WDMAUD_DEVICE_INFO DeviceInfo
;
561 PSOUND_DEVICE SoundDevice
;
562 MMDEVICE_TYPE DeviceType
;
565 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance
);
566 VALIDATE_MMSYS_PARAMETER( OffsetPtr
);
567 VALIDATE_MMSYS_PARAMETER( Overlap
);
568 VALIDATE_MMSYS_PARAMETER( CompletionRoutine
);
570 GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
573 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
575 if ( ! MMSUCCESS(Result
) )
577 return TranslateInternalMmResult(Result
);
580 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
581 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
585 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
587 DeviceInfo
.Header
.FrameExtent
= Length
;
588 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
590 DeviceInfo
.Header
.DataUsed
= Length
;
592 DeviceInfo
.Header
.Data
= OffsetPtr
;
593 DeviceInfo
.Header
.Size
= sizeof(WDMAUD_DEVICE_INFO
);
594 DeviceInfo
.Header
.PresentationTime
.Numerator
= 1;
595 DeviceInfo
.Header
.PresentationTime
.Denominator
= 1;
596 DeviceInfo
.hDevice
= Handle
;
597 DeviceInfo
.DeviceType
= DeviceType
;
599 Overlap
->Standard
.hEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
601 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
603 Ret
= WriteFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
);
605 WaitForSingleObjectEx (KernelHandle
, INFINITE
, TRUE
);
607 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
609 Ret
= ReadFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
);
611 // WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
614 return MMSYSERR_NOERROR
;
619 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
623 PSOUND_DEVICE SoundDevice
;
624 WDMAUD_DEVICE_INFO DeviceInfo
;
625 MMDEVICE_TYPE DeviceType
;
628 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
630 if ( ! MMSUCCESS(Result
) )
632 return TranslateInternalMmResult(Result
);
635 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
636 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
638 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
639 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
641 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
642 DeviceInfo
.hDevice
= Handle
;
643 DeviceInfo
.DeviceType
= DeviceType
;
646 DeviceInfo
.u
.State
= KSSTATE_RUN
;
648 DeviceInfo
.u
.State
= KSSTATE_PAUSE
;
649 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
650 IOCTL_SETDEVICE_STATE
,
651 (LPVOID
) &DeviceInfo
,
652 sizeof(WDMAUD_DEVICE_INFO
),
653 (LPVOID
) &DeviceInfo
,
654 sizeof(WDMAUD_DEVICE_INFO
),
661 GetDeviceInterfaceString(
662 IN MMDEVICE_TYPE DeviceType
,
665 IN DWORD InterfaceLength
,
666 OUT DWORD
* InterfaceSize
)
668 WDMAUD_DEVICE_INFO DeviceInfo
;
671 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
672 DeviceInfo
.DeviceType
= DeviceType
;
673 DeviceInfo
.DeviceIndex
= DeviceId
;
676 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
677 IOCTL_QUERYDEVICEINTERFACESTRING
,
678 (LPVOID
) &DeviceInfo
,
679 sizeof(WDMAUD_DEVICE_INFO
),
680 (LPVOID
) &DeviceInfo
,
681 sizeof(WDMAUD_DEVICE_INFO
),
685 if ( ! MMSUCCESS(Result
) )
687 return TranslateInternalMmResult(Result
);
693 SND_ASSERT(InterfaceSize
);
695 *InterfaceSize
= DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
;
696 return MMSYSERR_NOERROR
;
699 if (InterfaceLength
< DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
)
701 /* buffer is too small */
702 return MMSYSERR_MOREDATA
;
705 DeviceInfo
.u
.Interface
.DeviceInterfaceStringSize
= InterfaceLength
;
706 DeviceInfo
.u
.Interface
.DeviceInterfaceString
= Interface
;
708 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
709 IOCTL_QUERYDEVICEINTERFACESTRING
,
710 (LPVOID
) &DeviceInfo
,
711 sizeof(WDMAUD_DEVICE_INFO
),
712 (LPVOID
) &DeviceInfo
,
713 sizeof(WDMAUD_DEVICE_INFO
),
716 if ( MMSUCCESS(Result
) && InterfaceLength
> 2)
718 Interface
[1] = L
'\\';
719 Interface
[InterfaceLength
-1] = L
'\0';
727 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
731 PSOUND_DEVICE SoundDevice
;
732 WDMAUD_DEVICE_INFO DeviceInfo
;
733 MMDEVICE_TYPE DeviceType
;
736 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
738 if ( ! MMSUCCESS(Result
) )
740 return TranslateInternalMmResult(Result
);
743 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
744 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
746 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
747 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
749 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
750 DeviceInfo
.hDevice
= Handle
;
751 DeviceInfo
.DeviceType
= DeviceType
;
753 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
755 (LPVOID
) &DeviceInfo
,
756 sizeof(WDMAUD_DEVICE_INFO
),
757 (LPVOID
) &DeviceInfo
,
758 sizeof(WDMAUD_DEVICE_INFO
),
761 if ( ! MMSUCCESS(Result
) )
763 return TranslateInternalMmResult(Result
);
766 Time
->wType
= TIME_BYTES
;
767 Time
->u
.cb
= (DWORD
)DeviceInfo
.u
.Position
;
769 return MMSYSERR_NOERROR
;
774 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
775 IN MMDEVICE_TYPE DeviceType
,
776 IN BOOLEAN bStartReset
)
780 WDMAUD_DEVICE_INFO DeviceInfo
;
782 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
783 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
785 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
786 DeviceInfo
.hDevice
= Handle
;
787 DeviceInfo
.DeviceType
= DeviceType
;
788 DeviceInfo
.u
.ResetStream
= (bStartReset
? KSRESET_BEGIN
: KSRESET_END
);
790 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
792 (LPVOID
) &DeviceInfo
,
793 sizeof(WDMAUD_DEVICE_INFO
),
794 (LPVOID
) &DeviceInfo
,
795 sizeof(WDMAUD_DEVICE_INFO
),
803 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
809 WDMAUD_DEVICE_INFO DeviceInfo
;
812 LPMIXERLINEW MixLine
;
813 LPMIXERLINECONTROLSW MixControls
;
814 LPMIXERCONTROLDETAILS MixDetails
;
816 SND_TRACE(L
"uMsg %x Flags %x\n", uMsg
, Flags
);
818 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
819 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
821 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
822 DeviceInfo
.hDevice
= Handle
;
823 DeviceInfo
.DeviceType
= MIXER_DEVICE_TYPE
;
824 DeviceInfo
.Flags
= Flags
;
826 MixLine
= (LPMIXERLINEW
)Parameter
;
827 MixControls
= (LPMIXERLINECONTROLSW
)Parameter
;
828 MixDetails
= (LPMIXERCONTROLDETAILS
)Parameter
;
830 #ifdef USE_MMIXER_LIB
833 case MXDM_GETLINEINFO
:
834 return WdmAudGetLineInfo(SoundDeviceInstance
->Handle
, MixLine
, Flags
);
835 case MXDM_GETLINECONTROLS
:
836 return WdmAudGetLineControls(SoundDeviceInstance
->Handle
, MixControls
, Flags
);
837 case MXDM_SETCONTROLDETAILS
:
838 return WdmAudSetControlDetails(SoundDeviceInstance
->Handle
, MixDetails
, Flags
);
840 case MXDM_GETCONTROLDETAILS
:
841 return WdmAudGetControlDetails(SoundDeviceInstance
->Handle
, MixDetails
, Flags
);
845 return MMSYSERR_NOTSUPPORTED
;
852 case MXDM_GETLINEINFO
:
853 RtlCopyMemory(&DeviceInfo
.u
.MixLine
, MixLine
, sizeof(MIXERLINEW
));
854 IoControlCode
= IOCTL_GETLINEINFO
;
856 case MXDM_GETLINECONTROLS
:
857 RtlCopyMemory(&DeviceInfo
.u
.MixControls
, MixControls
, sizeof(MIXERLINECONTROLSW
));
858 IoControlCode
= IOCTL_GETLINECONTROLS
;
860 case MXDM_SETCONTROLDETAILS
:
861 RtlCopyMemory(&DeviceInfo
.u
.MixDetails
, MixDetails
, sizeof(MIXERCONTROLDETAILS
));
862 IoControlCode
= IOCTL_SETCONTROLDETAILS
;
864 case MXDM_GETCONTROLDETAILS
:
865 RtlCopyMemory(&DeviceInfo
.u
.MixDetails
, MixDetails
, sizeof(MIXERCONTROLDETAILS
));
866 IoControlCode
= IOCTL_GETCONTROLDETAILS
;
870 return MMSYSERR_NOTSUPPORTED
;
873 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
875 (LPVOID
) &DeviceInfo
,
876 sizeof(WDMAUD_DEVICE_INFO
),
877 (LPVOID
) &DeviceInfo
,
878 sizeof(WDMAUD_DEVICE_INFO
),
881 if ( ! MMSUCCESS(Result
) )
888 case MXDM_GETLINEINFO
:
890 RtlCopyMemory(MixLine
, &DeviceInfo
.u
.MixLine
, sizeof(MIXERLINEW
));
900 PopulateWdmDeviceList(
902 MMDEVICE_TYPE DeviceType
)
905 DWORD DeviceCount
= 0;
906 PSOUND_DEVICE SoundDevice
= NULL
;
907 MMFUNCTION_TABLE FuncTable
;
910 VALIDATE_MMSYS_PARAMETER( Handle
!= INVALID_HANDLE_VALUE
);
911 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
913 Result
= GetNumWdmDevs(Handle
, DeviceType
, &DeviceCount
);
915 if ( ! MMSUCCESS(Result
) )
917 SND_ERR(L
"Error %d while obtaining number of devices\n", Result
);
918 return TranslateInternalMmResult(Result
);
921 SND_TRACE(L
"%d devices of type %d found\n", DeviceCount
, DeviceType
);
924 for ( i
= 0; i
< DeviceCount
; ++ i
)
926 Result
= ListSoundDevice(DeviceType
, (PVOID
) i
, &SoundDevice
);
928 if ( ! MMSUCCESS(Result
) )
930 SND_ERR(L
"Failed to list sound device - error %d\n", Result
);
931 return TranslateInternalMmResult(Result
);
934 /* Set up our function table */
935 ZeroMemory(&FuncTable
, sizeof(MMFUNCTION_TABLE
));
936 FuncTable
.GetCapabilities
= GetWdmDeviceCapabilities
;
937 FuncTable
.QueryWaveFormatSupport
= QueryWdmWaveDeviceFormatSupport
;
938 if (DeviceType
== MIXER_DEVICE_TYPE
)
940 FuncTable
.SetWaveFormat
= SetWdmMixerDeviceFormat
;
941 FuncTable
.QueryMixerInfo
= QueryMixerInfo
;
945 FuncTable
.SetWaveFormat
= SetWdmWaveDeviceFormat
;
948 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
950 FuncTable
.SetState
= SetWdmWaveState
;
951 FuncTable
.ResetStream
= ResetStream
;
954 FuncTable
.Open
= OpenWdmSoundDevice
;
955 FuncTable
.Close
= CloseWdmSoundDevice
;
956 FuncTable
.GetDeviceInterfaceString
= GetDeviceInterfaceString
;
957 #ifndef USERMODE_MIXER
958 FuncTable
.CommitWaveBuffer
= WriteFileEx_Committer2
;
960 FuncTable
.CommitWaveBuffer
= WriteFileEx_Remixer
;
962 FuncTable
.GetPos
= GetWdmPosition
;
964 SetSoundDeviceFunctionTable(SoundDevice
, &FuncTable
);
967 return MMSYSERR_NOERROR
;
988 SND_TRACE(L
"DRV_LOAD\n");
990 Result
= InitEntrypointMutexes();
992 if ( ! MMSUCCESS(Result
) )
995 OpenWdmSoundDevice(NULL
, &Handle
);
997 if ( Handle
== INVALID_HANDLE_VALUE
)
999 SND_ERR(L
"Failed to open %s\n", KERNEL_DEVICE_NAME
);
1000 CleanupEntrypointMutexes();
1002 //UnlistAllSoundDevices();
1007 /* Populate the device lists */
1008 SND_TRACE(L
"Populating device lists\n");
1009 PopulateWdmDeviceList(KernelHandle
, WAVE_OUT_DEVICE_TYPE
);
1010 PopulateWdmDeviceList(KernelHandle
, WAVE_IN_DEVICE_TYPE
);
1011 PopulateWdmDeviceList(KernelHandle
, MIDI_OUT_DEVICE_TYPE
);
1012 PopulateWdmDeviceList(KernelHandle
, MIDI_IN_DEVICE_TYPE
);
1013 PopulateWdmDeviceList(KernelHandle
, AUX_DEVICE_TYPE
);
1014 PopulateWdmDeviceList(KernelHandle
, MIXER_DEVICE_TYPE
);
1016 SND_TRACE(L
"Initialisation complete\n");
1023 SND_TRACE(L
"DRV_FREE\n");
1025 if ( KernelHandle
!= INVALID_HANDLE_VALUE
)
1027 CloseHandle(KernelHandle
);
1028 KernelHandle
= INVALID_HANDLE_VALUE
;
1031 /* TODO: Clean up the path names! */
1032 UnlistAllSoundDevices();
1034 CleanupEntrypointMutexes();
1036 SND_TRACE(L
"Unfreed memory blocks: %d\n",
1037 GetMemoryAllocationCount());
1045 SND_TRACE(L
"DRV_ENABLE / DRV_DISABLE\n");
1052 SND_TRACE(L
"DRV_OPEN / DRV_CLOSE\n");
1056 case DRV_QUERYCONFIGURE
:
1058 SND_TRACE(L
"DRV_QUERYCONFIGURE\n");
1061 case DRV_CONFIGURE
:
1065 SND_TRACE(L
"Unhandled message %d\n", Message
);
1066 return DefDriverProc(DriverId
,
1075 BOOL WINAPI
DllMain(
1080 switch ( fdwReason
)
1082 case DLL_PROCESS_ATTACH
:
1083 #ifdef USE_MMIXER_LIB
1084 WdmAudInitUserModeMixer();
1086 SND_TRACE(L
"WDMAUD.DRV - Process attached\n");
1088 case DLL_PROCESS_DETACH
:
1089 SND_TRACE(L
"WDMAUD.DRV - Process detached\n");
1091 case DLL_THREAD_ATTACH
:
1092 SND_TRACE(L
"WDMAUD.DRV - Thread attached\n");
1094 case DLL_THREAD_DETACH
:
1095 SND_TRACE(L
"WDMAUD.DRV - Thread detached\n");