7050ca724639cfb0fe2c5a873dfaca113ff96c4a
[reactos.git] / reactos / dll / win32 / wdmaud.drv / wdmaud.c
1 /*
2 * PROJECT: ReactOS Sound System
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/wdmaud.drv/wdmaud.c
5 *
6 * PURPOSE: WDM Audio Driver (User-mode part)
7 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
8 *
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.
12 *
13 */
14
15 #include <windows.h>
16 #include <ntddsnd.h>
17 #include <sndtypes.h>
18 #include <mmddk.h>
19 #include <mmebuddy.h>
20
21 #include <ks.h>
22 #include <ksmedia.h>
23 #include "interface.h"
24
25 #define KERNEL_DEVICE_NAME L"\\\\.\\wdmaud"
26
27 PWSTR UnknownWaveIn = L"Wave Input";
28 PWSTR UnknownWaveOut = L"Wave Output";
29 PWSTR UnknownMidiIn = L"Midi Input";
30 PWSTR UnknownMidiOut = L"Midi Output";
31
32 HANDLE KernelHandle = INVALID_HANDLE_VALUE;
33 DWORD OpenCount = 0;
34
35 MMRESULT
36 WriteFileEx_Remixer(
37 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
38 IN PVOID OffsetPtr,
39 IN DWORD Length,
40 IN PSOUND_OVERLAPPED Overlap,
41 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine);
42
43
44
45 MMRESULT
46 GetNumWdmDevs(
47 IN HANDLE Handle,
48 IN MMDEVICE_TYPE DeviceType,
49 OUT DWORD* DeviceCount)
50 {
51 MMRESULT Result;
52 WDMAUD_DEVICE_INFO DeviceInfo;
53
54 VALIDATE_MMSYS_PARAMETER( Handle != INVALID_HANDLE_VALUE );
55 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
56 VALIDATE_MMSYS_PARAMETER( DeviceCount );
57
58 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
59 DeviceInfo.DeviceType = DeviceType;
60
61 Result = SyncOverlappedDeviceIoControl(Handle,
62 IOCTL_GETNUMDEVS_TYPE,
63 (LPVOID) &DeviceInfo,
64 sizeof(WDMAUD_DEVICE_INFO),
65 (LPVOID) &DeviceInfo,
66 sizeof(WDMAUD_DEVICE_INFO),
67 NULL);
68
69 if ( ! MMSUCCESS( Result ) )
70 {
71 SND_ERR(L"Call to IOCTL_GETNUMDEVS_TYPE failed\n");
72 *DeviceCount = 0;
73 return TranslateInternalMmResult(Result);
74 }
75
76 *DeviceCount = DeviceInfo.DeviceCount;
77
78 return MMSYSERR_NOERROR;
79 }
80
81 MMRESULT
82 GetWdmDeviceCapabilities(
83 IN PSOUND_DEVICE SoundDevice,
84 IN DWORD DeviceId,
85 OUT PVOID Capabilities,
86 IN DWORD CapabilitiesSize)
87 {
88 /* NOTE - At this time, WDMAUD does not support this properly */
89
90 MMRESULT Result;
91 MMDEVICE_TYPE DeviceType;
92 WDMAUD_DEVICE_INFO DeviceInfo;
93
94 SND_ASSERT( SoundDevice );
95 SND_ASSERT( Capabilities );
96
97 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
98 SND_ASSERT( Result == MMSYSERR_NOERROR );
99
100 if ( ! MMSUCCESS(Result) )
101 return Result;
102
103 SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType, DeviceId);
104
105 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
106 DeviceInfo.DeviceType = DeviceType;
107 DeviceInfo.DeviceIndex = DeviceId;
108
109 Result = SyncOverlappedDeviceIoControl(KernelHandle,
110 IOCTL_GETCAPABILITIES,
111 (LPVOID) &DeviceInfo,
112 sizeof(WDMAUD_DEVICE_INFO),
113 (LPVOID) &DeviceInfo,
114 sizeof(WDMAUD_DEVICE_INFO),
115 NULL);
116
117 if ( ! MMSUCCESS(Result) )
118 {
119 return TranslateInternalMmResult(Result);
120 }
121
122 /* This is pretty much a big hack right now */
123 switch ( DeviceType )
124 {
125 case MIXER_DEVICE_TYPE:
126 {
127 LPMIXERCAPS MixerCaps = (LPMIXERCAPS) Capabilities;
128
129 DeviceInfo.u.MixCaps.szPname[MAXPNAMELEN-1] = L'\0';
130 CopyWideString(MixerCaps->szPname, DeviceInfo.u.MixCaps.szPname);
131
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;
137 break;
138 }
139 case WAVE_OUT_DEVICE_TYPE :
140 {
141 LPWAVEOUTCAPS WaveOutCaps = (LPWAVEOUTCAPS) Capabilities;
142
143 DeviceInfo.u.WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0';
144 WaveOutCaps->wMid = DeviceInfo.u.WaveOutCaps.wMid;
145 WaveOutCaps->wPid = DeviceInfo.u.WaveOutCaps.wPid;
146
147 WaveOutCaps->vDriverVersion = 0x0001;
148 CopyWideString(WaveOutCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname);
149
150 WaveOutCaps->dwFormats = DeviceInfo.u.WaveOutCaps.dwFormats;
151 WaveOutCaps->wChannels = DeviceInfo.u.WaveOutCaps.wChannels;
152 WaveOutCaps->dwSupport = DeviceInfo.u.WaveOutCaps.dwSupport;
153 break;
154 }
155 case WAVE_IN_DEVICE_TYPE :
156 {
157 LPWAVEINCAPSW WaveInCaps = (LPWAVEINCAPSW) Capabilities;
158
159 DeviceInfo.u.WaveInCaps.szPname[MAXPNAMELEN-1] = L'\0';
160
161 WaveInCaps->wMid = DeviceInfo.u.WaveInCaps.wMid;
162 WaveInCaps->wPid = DeviceInfo.u.WaveInCaps.wPid;
163
164 WaveInCaps->vDriverVersion = 0x0001;
165 CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveInCaps.szPname);
166
167 WaveInCaps->dwFormats = DeviceInfo.u.WaveInCaps.dwFormats;
168 WaveInCaps->wChannels = DeviceInfo.u.WaveInCaps.wChannels;
169 WaveInCaps->wReserved1 = 0;
170 break;
171 }
172 }
173
174 return MMSYSERR_NOERROR;
175 }
176
177
178 MMRESULT
179 OpenWdmSoundDevice(
180 IN struct _SOUND_DEVICE* SoundDevice, /* NOT USED */
181 OUT PVOID* Handle)
182 {
183 /* Only open this if it's not already open */
184 if ( KernelHandle == INVALID_HANDLE_VALUE )
185 {
186 SND_TRACE(L"Opening wdmaud device\n");
187 KernelHandle = CreateFileW(KERNEL_DEVICE_NAME,
188 GENERIC_READ | GENERIC_WRITE,
189 0,
190 NULL,
191 OPEN_EXISTING,
192 FILE_FLAG_OVERLAPPED,
193 NULL);
194 }
195
196 if ( KernelHandle == INVALID_HANDLE_VALUE )
197 return MMSYSERR_ERROR;
198
199 SND_ASSERT( Handle );
200
201 *Handle = KernelHandle;
202 ++ OpenCount;
203
204 return MMSYSERR_NOERROR;
205 }
206
207 MMRESULT
208 CloseWdmSoundDevice(
209 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
210 IN PVOID Handle)
211 {
212 WDMAUD_DEVICE_INFO DeviceInfo;
213 MMRESULT Result;
214 MMDEVICE_TYPE DeviceType;
215 PSOUND_DEVICE SoundDevice;
216
217 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
218
219 if ( ! MMSUCCESS(Result) )
220 {
221 return TranslateInternalMmResult(Result);
222 }
223
224 if ( OpenCount == 0 )
225 {
226 return MMSYSERR_NOERROR;
227 }
228
229 SND_ASSERT( KernelHandle != INVALID_HANDLE_VALUE );
230
231 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
232 SND_ASSERT( Result == MMSYSERR_NOERROR );
233
234 if (SoundDeviceInstance->Handle != (PVOID)KernelHandle)
235 {
236 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
237
238 DeviceInfo.DeviceType = DeviceType;
239 DeviceInfo.hDevice = SoundDeviceInstance->Handle;
240
241 /* First stop the stream */
242 if (DeviceType != MIXER_DEVICE_TYPE)
243 {
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),
251 NULL);
252 }
253
254 SyncOverlappedDeviceIoControl(KernelHandle,
255 IOCTL_CLOSE_WDMAUD,
256 (LPVOID) &DeviceInfo,
257 sizeof(WDMAUD_DEVICE_INFO),
258 (LPVOID) &DeviceInfo,
259 sizeof(WDMAUD_DEVICE_INFO),
260 NULL);
261 }
262
263 --OpenCount;
264
265 if ( OpenCount < 1 )
266 {
267 CloseHandle(KernelHandle);
268 KernelHandle = INVALID_HANDLE_VALUE;
269 }
270
271 return MMSYSERR_NOERROR;
272 }
273
274
275 MMRESULT
276 QueryWdmWaveDeviceFormatSupport(
277 IN PSOUND_DEVICE Device,
278 IN PWAVEFORMATEX WaveFormat,
279 IN DWORD WaveFormatSize)
280 {
281 /* Whatever... */
282 return MMSYSERR_NOERROR;
283 }
284
285
286 MMRESULT
287 SetWdmMixerDeviceFormat(
288 IN PSOUND_DEVICE_INSTANCE Instance,
289 IN DWORD DeviceId,
290 IN PWAVEFORMATEX WaveFormat,
291 IN DWORD WaveFormatSize)
292 {
293 MMRESULT Result;
294 WDMAUD_DEVICE_INFO DeviceInfo;
295
296 if (Instance->Handle != KernelHandle)
297 {
298 /* device is already open */
299 return MMSYSERR_NOERROR;
300 }
301
302
303 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
304 DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
305 DeviceInfo.DeviceIndex = DeviceId;
306
307 Result = SyncOverlappedDeviceIoControl(KernelHandle,
308 IOCTL_OPEN_WDMAUD,
309 (LPVOID) &DeviceInfo,
310 sizeof(WDMAUD_DEVICE_INFO),
311 (LPVOID) &DeviceInfo,
312 sizeof(WDMAUD_DEVICE_INFO),
313 NULL);
314
315 if ( ! MMSUCCESS(Result) )
316 {
317 return TranslateInternalMmResult(Result);
318 }
319
320 /* Store sound device handle instance handle */
321 Instance->Handle = (PVOID)DeviceInfo.hDevice;
322
323 return MMSYSERR_NOERROR;
324 }
325
326 MMRESULT
327 SetWdmWaveDeviceFormat(
328 IN PSOUND_DEVICE_INSTANCE Instance,
329 IN DWORD DeviceId,
330 IN PWAVEFORMATEX WaveFormat,
331 IN DWORD WaveFormatSize)
332 {
333 MMRESULT Result;
334 PSOUND_DEVICE SoundDevice;
335 PVOID Identifier;
336 WDMAUD_DEVICE_INFO DeviceInfo;
337 MMDEVICE_TYPE DeviceType;
338
339 Result = GetSoundDeviceFromInstance(Instance, &SoundDevice);
340
341 if ( ! MMSUCCESS(Result) )
342 {
343 return TranslateInternalMmResult(Result);
344 }
345
346 Result = GetSoundDeviceIdentifier(SoundDevice, &Identifier);
347
348 if ( ! MMSUCCESS(Result) )
349 {
350 return TranslateInternalMmResult(Result);
351 }
352
353 if (Instance->Handle != KernelHandle)
354 {
355 /* device is already open */
356 return MMSYSERR_NOERROR;
357 }
358
359
360 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
361 SND_ASSERT( Result == MMSYSERR_NOERROR );
362
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;
374 #else
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;
380 #endif
381
382 Result = SyncOverlappedDeviceIoControl(KernelHandle,
383 IOCTL_OPEN_WDMAUD,
384 (LPVOID) &DeviceInfo,
385 sizeof(WDMAUD_DEVICE_INFO),
386 (LPVOID) &DeviceInfo,
387 sizeof(WDMAUD_DEVICE_INFO),
388 NULL);
389
390 if ( ! MMSUCCESS(Result) )
391 {
392 return TranslateInternalMmResult(Result);
393 }
394
395 /* Store format */
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;
403
404 /* Store sound device handle instance handle */
405 Instance->Handle = (PVOID)DeviceInfo.hDevice;
406
407 /* Now determine framing requirements */
408 Result = SyncOverlappedDeviceIoControl(KernelHandle,
409 IOCTL_GETFRAMESIZE,
410 (LPVOID) &DeviceInfo,
411 sizeof(WDMAUD_DEVICE_INFO),
412 (LPVOID) &DeviceInfo,
413 sizeof(WDMAUD_DEVICE_INFO),
414 NULL);
415
416 if ( MMSUCCESS(Result) )
417 {
418 if (DeviceInfo.u.FrameSize)
419 {
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);
423 }
424 }
425 else
426 {
427 // use a default of 100 buffers
428 Instance->BufferCount = 100;
429 }
430
431
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),
440 NULL);
441
442 return MMSYSERR_NOERROR;
443 }
444
445 MMRESULT
446 WriteFileEx_Committer2(
447 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
448 IN PVOID OffsetPtr,
449 IN DWORD Length,
450 IN PSOUND_OVERLAPPED Overlap,
451 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
452 {
453 HANDLE Handle;
454 MMRESULT Result;
455 WDMAUD_DEVICE_INFO DeviceInfo;
456 PSOUND_DEVICE SoundDevice;
457 MMDEVICE_TYPE DeviceType;
458 BOOL Ret;
459
460 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
461 VALIDATE_MMSYS_PARAMETER( OffsetPtr );
462 VALIDATE_MMSYS_PARAMETER( Overlap );
463 VALIDATE_MMSYS_PARAMETER( CompletionRoutine );
464
465 GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
466
467
468 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
469
470 if ( ! MMSUCCESS(Result) )
471 {
472 return TranslateInternalMmResult(Result);
473 }
474
475 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
476 SND_ASSERT( Result == MMSYSERR_NOERROR );
477
478 SND_ASSERT(Handle);
479
480 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
481
482 DeviceInfo.Header.FrameExtent = Length;
483 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
484 {
485 DeviceInfo.Header.DataUsed = Length;
486 }
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;
493
494 Overlap->Standard.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
495
496 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
497 {
498 Ret = WriteFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine);
499 if (Ret)
500 WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
501 }
502 else if (DeviceType == WAVE_IN_DEVICE_TYPE)
503 {
504 Ret = ReadFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine);
505 if (Ret)
506 WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
507 }
508
509 return MMSYSERR_NOERROR;
510 }
511
512 MMRESULT
513 GetWdmPosition(
514 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
515 IN MMTIME* Time)
516 {
517 MMRESULT Result;
518 PSOUND_DEVICE SoundDevice;
519 WDMAUD_DEVICE_INFO DeviceInfo;
520 MMDEVICE_TYPE DeviceType;
521 HANDLE Handle;
522
523 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
524
525 if ( ! MMSUCCESS(Result) )
526 {
527 return TranslateInternalMmResult(Result);
528 }
529
530 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
531 SND_ASSERT( Result == MMSYSERR_NOERROR );
532
533 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
534 SND_ASSERT( Result == MMSYSERR_NOERROR );
535
536 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
537 DeviceInfo.hDevice = Handle;
538 DeviceInfo.DeviceType = DeviceType;
539
540 Result = SyncOverlappedDeviceIoControl(KernelHandle,
541 IOCTL_OPEN_WDMAUD,
542 (LPVOID) &DeviceInfo,
543 sizeof(WDMAUD_DEVICE_INFO),
544 (LPVOID) &DeviceInfo,
545 sizeof(WDMAUD_DEVICE_INFO),
546 NULL);
547
548 if ( ! MMSUCCESS(Result) )
549 {
550 return TranslateInternalMmResult(Result);
551 }
552
553 Time->wType = TIME_BYTES;
554 Time->u.cb = (DWORD)DeviceInfo.u.Position;
555
556 return MMSYSERR_NOERROR;
557 }
558
559 MMRESULT
560 QueryMixerInfo(
561 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
562 IN UINT uMsg,
563 IN LPVOID Parameter,
564 IN DWORD Flags)
565 {
566 MMRESULT Result;
567 WDMAUD_DEVICE_INFO DeviceInfo;
568 HANDLE Handle;
569 DWORD IoControlCode;
570 LPMIXERLINEW MixLine;
571 LPMIXERLINECONTROLSW MixControls;
572 LPMIXERCONTROLDETAILS MixDetails;
573
574 SND_TRACE(L"uMsg %x Flags %x\n", uMsg, Flags);
575
576 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
577 SND_ASSERT( Result == MMSYSERR_NOERROR );
578
579 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
580 DeviceInfo.hDevice = Handle;
581 DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
582 DeviceInfo.Flags = Flags;
583
584 MixLine = (LPMIXERLINEW)Parameter;
585 MixControls = (LPMIXERLINECONTROLSW)Parameter;
586 MixDetails = (LPMIXERCONTROLDETAILS)Parameter;
587
588 switch(uMsg)
589 {
590 case MXDM_GETLINEINFO:
591 RtlCopyMemory(&DeviceInfo.u.MixLine, MixLine, sizeof(MIXERLINEW));
592 IoControlCode = IOCTL_GETLINEINFO;
593 break;
594 case MXDM_GETLINECONTROLS:
595 RtlCopyMemory(&DeviceInfo.u.MixControls, MixControls, sizeof(MIXERLINECONTROLSW));
596 IoControlCode = IOCTL_GETLINECONTROLS;
597 break;
598 case MXDM_SETCONTROLDETAILS:
599 RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
600 IoControlCode = IOCTL_SETCONTROLDETAILS;
601 break;
602 case MXDM_GETCONTROLDETAILS:
603 RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
604 IoControlCode = IOCTL_GETCONTROLDETAILS;
605 break;
606 default:
607 SND_ASSERT(0);
608 }
609
610 Result = SyncOverlappedDeviceIoControl(KernelHandle,
611 IoControlCode,
612 (LPVOID) &DeviceInfo,
613 sizeof(WDMAUD_DEVICE_INFO),
614 (LPVOID) &DeviceInfo,
615 sizeof(WDMAUD_DEVICE_INFO),
616 NULL);
617
618 if ( ! MMSUCCESS(Result) )
619 {
620 return TranslateInternalMmResult(Result);
621 }
622
623 switch(uMsg)
624 {
625 case MXDM_GETLINEINFO:
626 {
627 RtlCopyMemory(MixLine, &DeviceInfo.u.MixLine, sizeof(MIXERLINEW));
628 break;
629 }
630 }
631
632 return Result;
633 }
634
635
636 MMRESULT
637 PopulateWdmDeviceList(
638 HANDLE Handle,
639 MMDEVICE_TYPE DeviceType)
640 {
641 MMRESULT Result;
642 DWORD DeviceCount = 0;
643 PSOUND_DEVICE SoundDevice = NULL;
644 MMFUNCTION_TABLE FuncTable;
645 DWORD i;
646
647 VALIDATE_MMSYS_PARAMETER( Handle != INVALID_HANDLE_VALUE );
648 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
649
650 Result = GetNumWdmDevs(Handle, DeviceType, &DeviceCount);
651
652 if ( ! MMSUCCESS(Result) )
653 {
654 SND_ERR(L"Error %d while obtaining number of devices\n", Result);
655 return TranslateInternalMmResult(Result);
656 }
657
658 SND_TRACE(L"%d devices of type %d found\n", DeviceCount, DeviceType);
659
660
661 for ( i = 0; i < DeviceCount; ++ i )
662 {
663 Result = ListSoundDevice(DeviceType, (PVOID) i, &SoundDevice);
664
665 if ( ! MMSUCCESS(Result) )
666 {
667 SND_ERR(L"Failed to list sound device - error %d\n", Result);
668 return TranslateInternalMmResult(Result);
669 }
670
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)
676 {
677 FuncTable.SetWaveFormat = SetWdmMixerDeviceFormat;
678 FuncTable.QueryMixerInfo = QueryMixerInfo;
679 }
680 else
681 {
682 FuncTable.SetWaveFormat = SetWdmWaveDeviceFormat;
683 }
684
685 FuncTable.Open = OpenWdmSoundDevice;
686 FuncTable.Close = CloseWdmSoundDevice;
687 #ifndef USERMODE_MIXER
688 FuncTable.CommitWaveBuffer = WriteFileEx_Committer2;
689 #else
690 FuncTable.CommitWaveBuffer = WriteFileEx_Remixer;
691 #endif
692 FuncTable.GetPos = GetWdmPosition;
693
694 SetSoundDeviceFunctionTable(SoundDevice, &FuncTable);
695 }
696
697 return MMSYSERR_NOERROR;
698 }
699
700
701
702 LONG
703 APIENTRY
704 DriverProc(
705 DWORD DriverId,
706 HANDLE DriverHandle,
707 UINT Message,
708 LONG Parameter1,
709 LONG Parameter2)
710 {
711 MMRESULT Result;
712
713 switch ( Message )
714 {
715 case DRV_LOAD :
716 {
717 HANDLE Handle;
718 SND_TRACE(L"DRV_LOAD\n");
719
720 Result = InitEntrypointMutexes();
721
722 if ( ! MMSUCCESS(Result) )
723 return 0L;
724
725 OpenWdmSoundDevice(NULL, &Handle);
726
727 if ( Handle == INVALID_HANDLE_VALUE )
728 {
729 SND_ERR(L"Failed to open %s\n", KERNEL_DEVICE_NAME);
730 CleanupEntrypointMutexes();
731
732 //UnlistAllSoundDevices();
733
734 return 0L;
735 }
736
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);
745
746 SND_TRACE(L"Initialisation complete\n");
747
748 return 1L;
749 }
750
751 case DRV_FREE :
752 {
753 SND_TRACE(L"DRV_FREE\n");
754
755 if ( KernelHandle != INVALID_HANDLE_VALUE )
756 {
757 CloseHandle(KernelHandle);
758 KernelHandle = INVALID_HANDLE_VALUE;
759 }
760
761 /* TODO: Clean up the path names! */
762 UnlistAllSoundDevices();
763
764 CleanupEntrypointMutexes();
765
766 SND_TRACE(L"Unfreed memory blocks: %d\n",
767 GetMemoryAllocationCount());
768
769 return 1L;
770 }
771
772 case DRV_ENABLE :
773 case DRV_DISABLE :
774 {
775 SND_TRACE(L"DRV_ENABLE / DRV_DISABLE\n");
776 return 1L;
777 }
778
779 case DRV_OPEN :
780 case DRV_CLOSE :
781 {
782 SND_TRACE(L"DRV_OPEN / DRV_CLOSE\n");
783 return 1L;
784 }
785
786 case DRV_QUERYCONFIGURE :
787 {
788 SND_TRACE(L"DRV_QUERYCONFIGURE\n");
789 return 0L;
790 }
791 case DRV_CONFIGURE :
792 return DRVCNF_OK;
793
794 default :
795 SND_TRACE(L"Unhandled message %d\n", Message);
796 return DefDriverProc(DriverId,
797 DriverHandle,
798 Message,
799 Parameter1,
800 Parameter2);
801 }
802 }
803
804
805 BOOL WINAPI DllMain(
806 HINSTANCE hinstDLL,
807 DWORD fdwReason,
808 LPVOID lpvReserved)
809 {
810 switch ( fdwReason )
811 {
812 case DLL_PROCESS_ATTACH :
813 SND_TRACE(L"WDMAUD.DRV - Process attached\n");
814 break;
815 case DLL_PROCESS_DETACH :
816 SND_TRACE(L"WDMAUD.DRV - Process detached\n");
817 break;
818 case DLL_THREAD_ATTACH :
819 SND_TRACE(L"WDMAUD.DRV - Thread attached\n");
820 break;
821 case DLL_THREAD_DETACH :
822 SND_TRACE(L"WDMAUD.DRV - Thread detached\n");
823 break;
824 }
825
826 return TRUE;
827 }