312d325148a548536ba34da3be22f18b58c35f3e
[reactos.git] / reactos / dll / win32 / wdmaud.drv / mmixer.c
1 /*
2 * PROJECT: ReactOS Sound System
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/wdmaud.drv/mmixer.c
5 *
6 * PURPOSE: WDM Audio Mixer API (User-mode part)
7 * PROGRAMMERS: Johannes Anderwald
8 */
9
10 #include "wdmaud.h"
11
12
13 PVOID Alloc(ULONG NumBytes);
14 MIXER_STATUS Close(HANDLE hDevice);
15 VOID Free(PVOID Block);
16 VOID Copy(PVOID Src, PVOID Dst, ULONG NumBytes);
17 MIXER_STATUS Open(IN LPWSTR DevicePath, OUT PHANDLE hDevice);
18 MIXER_STATUS Control(IN HANDLE hMixer, IN ULONG dwIoControlCode, IN PVOID lpInBuffer, IN ULONG nInBufferSize, OUT PVOID lpOutBuffer, ULONG nOutBufferSize, PULONG lpBytesReturned);
19 MIXER_STATUS Enum(IN PVOID EnumContext, IN ULONG DeviceIndex, OUT LPWSTR * DeviceName, OUT PHANDLE OutHandle, OUT PHANDLE OutKey);
20 MIXER_STATUS OpenKey(IN HANDLE hKey, IN LPWSTR SubKey, IN ULONG DesiredAccess, OUT PHANDLE OutKey);
21 MIXER_STATUS CloseKey(IN HANDLE hKey);
22 MIXER_STATUS QueryKeyValue(IN HANDLE hKey, IN LPWSTR KeyName, OUT PVOID * ResultBuffer, OUT PULONG ResultLength, OUT PULONG KeyType);
23 PVOID AllocEventData(IN ULONG ExtraSize);
24 VOID FreeEventData(IN PVOID EventData);
25
26 MIXER_CONTEXT MixerContext =
27 {
28 sizeof(MIXER_CONTEXT),
29 NULL,
30 Alloc,
31 Control,
32 Free,
33 Open,
34 Close,
35 Copy,
36 OpenKey,
37 QueryKeyValue,
38 CloseKey,
39 AllocEventData,
40 FreeEventData
41 };
42
43 GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO};
44
45 MIXER_STATUS
46 QueryKeyValue(
47 IN HANDLE hKey,
48 IN LPWSTR KeyName,
49 OUT PVOID * ResultBuffer,
50 OUT PULONG ResultLength,
51 OUT PULONG KeyType)
52 {
53 if (RegQueryValueExW((HKEY)hKey, KeyName, NULL, KeyType, NULL, ResultLength) == ERROR_FILE_NOT_FOUND)
54 return MM_STATUS_UNSUCCESSFUL;
55
56 *ResultBuffer = HeapAlloc(GetProcessHeap(), 0, *ResultLength);
57 if (*ResultBuffer == NULL)
58 return MM_STATUS_NO_MEMORY;
59
60 if (RegQueryValueExW((HKEY)hKey, KeyName, NULL, KeyType, *ResultBuffer, ResultLength) != ERROR_SUCCESS)
61 {
62 HeapFree(GetProcessHeap(), 0, *ResultBuffer);
63 return MM_STATUS_UNSUCCESSFUL;
64 }
65 return MM_STATUS_SUCCESS;
66 }
67
68 MIXER_STATUS
69 OpenKey(
70 IN HANDLE hKey,
71 IN LPWSTR SubKey,
72 IN ULONG DesiredAccess,
73 OUT PHANDLE OutKey)
74 {
75 if (RegOpenKeyExW((HKEY)hKey, SubKey, 0, DesiredAccess, (PHKEY)OutKey) == ERROR_SUCCESS)
76 return MM_STATUS_SUCCESS;
77
78 return MM_STATUS_UNSUCCESSFUL;
79 }
80
81 MIXER_STATUS
82 CloseKey(
83 IN HANDLE hKey)
84 {
85 RegCloseKey((HKEY)hKey);
86 return MM_STATUS_SUCCESS;
87 }
88
89
90 PVOID Alloc(ULONG NumBytes)
91 {
92 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, NumBytes);
93 }
94
95 MIXER_STATUS
96 Close(HANDLE hDevice)
97 {
98 if (CloseHandle(hDevice))
99 return MM_STATUS_SUCCESS;
100 else
101 return MM_STATUS_UNSUCCESSFUL;
102 }
103
104 VOID
105 Free(PVOID Block)
106 {
107 HeapFree(GetProcessHeap(), 0, Block);
108 }
109
110 VOID
111 Copy(PVOID Src, PVOID Dst, ULONG NumBytes)
112 {
113 CopyMemory(Src, Dst, NumBytes);
114 }
115
116 MIXER_STATUS
117 Open(
118 IN LPWSTR DevicePath,
119 OUT PHANDLE hDevice)
120 {
121 DevicePath[1] = L'\\';
122 *hDevice = CreateFileW(DevicePath,
123 GENERIC_READ | GENERIC_WRITE,
124 0,
125 NULL,
126 OPEN_EXISTING,
127 FILE_FLAG_OVERLAPPED,
128 NULL);
129 if (*hDevice == INVALID_HANDLE_VALUE)
130 {
131 return MM_STATUS_UNSUCCESSFUL;
132 }
133
134 return MM_STATUS_SUCCESS;
135 }
136
137 MIXER_STATUS
138 Control(
139 IN HANDLE hMixer,
140 IN ULONG dwIoControlCode,
141 IN PVOID lpInBuffer,
142 IN ULONG nInBufferSize,
143 OUT PVOID lpOutBuffer,
144 ULONG nOutBufferSize,
145 PULONG lpBytesReturned)
146 {
147 OVERLAPPED Overlapped;
148 BOOLEAN IoResult;
149 DWORD Transferred = 0;
150
151 /* Overlapped I/O is done here - this is used for waiting for completion */
152 ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
153 Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
154
155 if ( ! Overlapped.hEvent )
156 return MM_STATUS_NO_MEMORY;
157
158 /* Talk to the device */
159 IoResult = DeviceIoControl(hMixer,
160 dwIoControlCode,
161 lpInBuffer,
162 nInBufferSize,
163 lpOutBuffer,
164 nOutBufferSize,
165 &Transferred,
166 &Overlapped);
167
168 /* If failure occurs, make sure it's not just due to the overlapped I/O */
169 if ( ! IoResult )
170 {
171 if ( GetLastError() != ERROR_IO_PENDING )
172 {
173 CloseHandle(Overlapped.hEvent);
174
175 if (GetLastError() == ERROR_MORE_DATA || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
176 {
177 if ( lpBytesReturned )
178 *lpBytesReturned = Transferred;
179 return MM_STATUS_MORE_ENTRIES;
180 }
181
182 return MM_STATUS_UNSUCCESSFUL;
183 }
184 }
185
186 /* Wait for the I/O to complete */
187 IoResult = GetOverlappedResult(hMixer,
188 &Overlapped,
189 &Transferred,
190 TRUE);
191
192 /* Don't need this any more */
193 CloseHandle(Overlapped.hEvent);
194
195 if ( ! IoResult )
196 return MM_STATUS_UNSUCCESSFUL;
197
198 if ( lpBytesReturned )
199 *lpBytesReturned = Transferred;
200
201 return MM_STATUS_SUCCESS;
202 }
203
204 MIXER_STATUS
205 Enum(
206 IN PVOID EnumContext,
207 IN ULONG DeviceIndex,
208 OUT LPWSTR * DeviceName,
209 OUT PHANDLE OutHandle,
210 OUT PHANDLE OutKey)
211 {
212 SP_DEVICE_INTERFACE_DATA InterfaceData;
213 SP_DEVINFO_DATA DeviceData;
214 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData;
215 BOOL Result;
216 DWORD Length;
217 MIXER_STATUS Status;
218
219 //printf("Enum EnumContext %p DeviceIndex %lu OutHandle %p\n", EnumContext, DeviceIndex, OutHandle);
220
221 InterfaceData.cbSize = sizeof(InterfaceData);
222 InterfaceData.Reserved = 0;
223
224 Result = SetupDiEnumDeviceInterfaces(EnumContext,
225 NULL,
226 &CategoryGuid,
227 DeviceIndex,
228 &InterfaceData);
229
230 if (!Result)
231 {
232 if (GetLastError() == ERROR_NO_MORE_ITEMS)
233 {
234 return MM_STATUS_NO_MORE_DEVICES;
235 }
236 return MM_STATUS_UNSUCCESSFUL;
237 }
238
239 Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR);
240 DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(),
241 0,
242 Length);
243 DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
244 DeviceData.cbSize = sizeof(DeviceData);
245 DeviceData.Reserved = 0;
246
247 Result = SetupDiGetDeviceInterfaceDetailW(EnumContext,
248 &InterfaceData,
249 DetailData,
250 Length,
251 NULL,
252 &DeviceData);
253
254 if (!Result)
255 {
256 DPRINT("SetupDiGetDeviceInterfaceDetailW failed with %lu\n", GetLastError());
257 return MM_STATUS_UNSUCCESSFUL;
258 }
259
260
261 *OutKey = SetupDiOpenDeviceInterfaceRegKey(EnumContext, &InterfaceData, 0, KEY_READ);
262 if ((HKEY)*OutKey == INVALID_HANDLE_VALUE)
263 {
264 HeapFree(GetProcessHeap(), 0, DetailData);
265 return MM_STATUS_UNSUCCESSFUL;
266 }
267
268 Status = Open(DetailData->DevicePath, OutHandle);
269
270 if (Status != MM_STATUS_SUCCESS)
271 {
272 RegCloseKey((HKEY)*OutKey);
273 HeapFree(GetProcessHeap(), 0, DetailData);
274 return Status;
275 }
276
277 *DeviceName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(DetailData->DevicePath)+1) * sizeof(WCHAR));
278 if (*DeviceName == NULL)
279 {
280 CloseHandle(*OutHandle);
281 RegCloseKey((HKEY)*OutKey);
282 HeapFree(GetProcessHeap(), 0, DetailData);
283 return MM_STATUS_NO_MEMORY;
284 }
285
286 wcscpy(*DeviceName, DetailData->DevicePath);
287 HeapFree(GetProcessHeap(), 0, DetailData);
288
289 return Status;
290 }
291
292 PVOID
293 AllocEventData(
294 IN ULONG ExtraSize)
295 {
296 PKSEVENTDATA Data = (PKSEVENTDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KSEVENTDATA) + ExtraSize);
297 if (!Data)
298 return NULL;
299
300 Data->EventHandle.Event = CreateEventW(NULL, FALSE, FALSE, NULL);
301 if (!Data->EventHandle.Event)
302 {
303 HeapFree(GetProcessHeap(), 0, Data);
304 return NULL;
305 }
306
307 Data->NotificationType = KSEVENTF_EVENT_HANDLE;
308 return Data;
309 }
310
311 VOID
312 FreeEventData(IN PVOID EventData)
313 {
314 PKSEVENTDATA Data = (PKSEVENTDATA)EventData;
315
316 CloseHandle(Data->EventHandle.Event);
317 HeapFree(GetProcessHeap(), 0, Data);
318 }
319
320
321 BOOL
322 WdmAudInitUserModeMixer()
323 {
324 HDEVINFO DeviceHandle;
325 MIXER_STATUS Status;
326
327 /* create a device list */
328 DeviceHandle = SetupDiGetClassDevs(&CategoryGuid,
329 NULL,
330 NULL,
331 DIGCF_DEVICEINTERFACE/* FIXME |DIGCF_PRESENT*/);
332
333 if (DeviceHandle == INVALID_HANDLE_VALUE)
334 {
335 /* failed to create a device list */
336 return FALSE;
337 }
338
339
340 /* initialize the mixer library */
341 Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceHandle);
342
343 /* free device list */
344 SetupDiDestroyDeviceInfoList(DeviceHandle);
345
346 if (Status != MM_STATUS_SUCCESS)
347 {
348 /* failed to initialize mixer library */
349 DPRINT1("Failed to initialize mixer library with %x\n", Status);
350 return FALSE;
351 }
352
353 /* completed successfully */
354 return TRUE;
355 }
356
357 MMRESULT
358 WdmAudCleanupByMMixer()
359 {
360 /* TODO */
361 return MMSYSERR_NOERROR;
362 }
363
364 MMRESULT
365 WdmAudGetMixerCapabilties(
366 IN ULONG DeviceId,
367 LPMIXERCAPSW Capabilities)
368 {
369 if (MMixerGetCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS)
370 return MMSYSERR_NOERROR;
371
372 return MMSYSERR_BADDEVICEID;
373 }
374
375 MMRESULT
376 WdmAudGetLineInfo(
377 IN HANDLE hMixer,
378 IN LPMIXERLINEW MixLine,
379 IN ULONG Flags)
380 {
381 if (MMixerGetLineInfo(&MixerContext, hMixer, Flags, MixLine) == MM_STATUS_SUCCESS)
382 return MMSYSERR_NOERROR;
383
384 return MMSYSERR_ERROR;
385 }
386
387 MMRESULT
388 WdmAudGetLineControls(
389 IN HANDLE hMixer,
390 IN LPMIXERLINECONTROLSW MixControls,
391 IN ULONG Flags)
392 {
393 if (MMixerGetLineControls(&MixerContext, hMixer, Flags, MixControls) == MM_STATUS_SUCCESS)
394 return MMSYSERR_NOERROR;
395
396 return MMSYSERR_ERROR;
397 }
398
399 MMRESULT
400 WdmAudSetControlDetails(
401 IN HANDLE hMixer,
402 IN LPMIXERCONTROLDETAILS MixDetails,
403 IN ULONG Flags)
404 {
405 if (MMixerSetControlDetails(&MixerContext, hMixer, Flags, MixDetails) == MM_STATUS_SUCCESS)
406 return MMSYSERR_NOERROR;
407
408 return MMSYSERR_ERROR;
409
410 }
411
412 MMRESULT
413 WdmAudGetControlDetails(
414 IN HANDLE hMixer,
415 IN LPMIXERCONTROLDETAILS MixDetails,
416 IN ULONG Flags)
417 {
418 if (MMixerGetControlDetails(&MixerContext, hMixer, Flags, MixDetails) == MM_STATUS_SUCCESS)
419 return MMSYSERR_NOERROR;
420
421 return MMSYSERR_ERROR;
422 }
423
424 MMRESULT
425 WdmAudGetWaveOutCapabilities(
426 IN ULONG DeviceId,
427 LPWAVEOUTCAPSW Capabilities)
428 {
429 if (MMixerWaveOutCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS)
430 return MMSYSERR_NOERROR;
431
432 return MMSYSERR_ERROR;
433
434 }
435
436 MMRESULT
437 WdmAudGetWaveInCapabilities(
438 IN ULONG DeviceId,
439 LPWAVEINCAPSW Capabilities)
440 {
441 if (MMixerWaveInCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS)
442 return MMSYSERR_NOERROR;
443
444 return MMSYSERR_ERROR;
445 }
446
447 MMRESULT
448 WdmAudSetWaveDeviceFormatByMMixer(
449 IN PSOUND_DEVICE_INSTANCE Instance,
450 IN DWORD DeviceId,
451 IN PWAVEFORMATEX WaveFormat,
452 IN DWORD WaveFormatSize)
453 {
454 MMDEVICE_TYPE DeviceType;
455 PSOUND_DEVICE SoundDevice;
456 MMRESULT Result;
457 BOOL bWaveIn;
458
459 Result = GetSoundDeviceFromInstance(Instance, &SoundDevice);
460
461 if ( ! MMSUCCESS(Result) )
462 {
463 return TranslateInternalMmResult(Result);
464 }
465
466 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
467 SND_ASSERT( Result == MMSYSERR_NOERROR );
468
469 bWaveIn = (DeviceType == WAVE_IN_DEVICE_TYPE ? TRUE : FALSE);
470
471 if (MMixerOpenWave(&MixerContext, DeviceId, bWaveIn, WaveFormat, NULL, NULL, &Instance->Handle) == MM_STATUS_SUCCESS)
472 {
473 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
474 {
475 MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_ACQUIRE);
476 MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_PAUSE);
477 MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_RUN);
478 }
479 return MMSYSERR_NOERROR;
480 }
481 return MMSYSERR_ERROR;
482 }
483
484
485 MMRESULT
486 WdmAudGetCapabilitiesByMMixer(
487 IN PSOUND_DEVICE SoundDevice,
488 IN DWORD DeviceId,
489 OUT PVOID Capabilities,
490 IN DWORD CapabilitiesSize)
491 {
492 MMDEVICE_TYPE DeviceType;
493 MMRESULT Result;
494
495 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
496 SND_ASSERT( Result == MMSYSERR_NOERROR );
497
498 if (DeviceType == MIXER_DEVICE_TYPE)
499 {
500 return WdmAudGetMixerCapabilties(DeviceId, (LPMIXERCAPSW)Capabilities);
501 }
502 else if (DeviceType == WAVE_OUT_DEVICE_TYPE)
503 {
504 return WdmAudGetWaveOutCapabilities(DeviceId, (LPWAVEOUTCAPSW)Capabilities);
505 }
506 else if (DeviceType == WAVE_IN_DEVICE_TYPE)
507 {
508 return WdmAudGetWaveInCapabilities(DeviceId, (LPWAVEINCAPSW)Capabilities);
509 }
510 else
511 {
512 // not supported
513 return MMSYSERR_ERROR;
514 }
515 }
516
517 MMRESULT
518 WdmAudOpenSoundDeviceByMMixer(
519 IN struct _SOUND_DEVICE* SoundDevice,
520 OUT PVOID* Handle)
521 {
522 return WdmAudInitUserModeMixer();
523 }
524
525 MMRESULT
526 WdmAudCloseSoundDeviceByMMixer(
527 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
528 IN PVOID Handle)
529 {
530 MMDEVICE_TYPE DeviceType;
531 PSOUND_DEVICE SoundDevice;
532 MMRESULT Result;
533
534 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
535
536 if ( ! MMSUCCESS(Result) )
537 {
538 return TranslateInternalMmResult(Result);
539 }
540
541 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
542 SND_ASSERT( Result == MMSYSERR_NOERROR );
543
544 if (DeviceType == MIXER_DEVICE_TYPE)
545 {
546 /* no op */
547 return MMSYSERR_NOERROR;
548 }
549 else if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
550 {
551 /* make sure the pin is stopped */
552 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE);
553 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE);
554 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP);
555
556 CloseHandle(Handle);
557 return MMSYSERR_NOERROR;
558 }
559
560 /* midi is not supported */
561 return MMSYSERR_ERROR;
562 }
563
564 MMRESULT
565 WdmAudGetNumWdmDevsByMMixer(
566 IN MMDEVICE_TYPE DeviceType,
567 OUT DWORD* DeviceCount)
568 {
569 switch(DeviceType)
570 {
571 case MIXER_DEVICE_TYPE:
572 *DeviceCount = MMixerGetCount(&MixerContext);
573 break;
574 case WAVE_OUT_DEVICE_TYPE:
575 *DeviceCount = MMixerGetWaveOutCount(&MixerContext);
576 break;
577 case WAVE_IN_DEVICE_TYPE:
578 *DeviceCount = MMixerGetWaveInCount(&MixerContext);
579 break;
580 default:
581 *DeviceCount = 0;
582 }
583 return MMSYSERR_NOERROR;
584 }
585
586 MMRESULT
587 WdmAudQueryMixerInfoByMMixer(
588 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
589 IN UINT uMsg,
590 IN LPVOID Parameter,
591 IN DWORD Flags)
592 {
593 LPMIXERLINEW MixLine;
594 LPMIXERLINECONTROLSW MixControls;
595 LPMIXERCONTROLDETAILS MixDetails;
596
597 MixLine = (LPMIXERLINEW)Parameter;
598 MixControls = (LPMIXERLINECONTROLSW)Parameter;
599 MixDetails = (LPMIXERCONTROLDETAILS)Parameter;
600
601 /* FIXME param checks */
602
603 switch(uMsg)
604 {
605 case MXDM_GETLINEINFO:
606 return WdmAudGetLineInfo(SoundDeviceInstance->Handle, MixLine, Flags);
607 case MXDM_GETLINECONTROLS:
608 return WdmAudGetLineControls(SoundDeviceInstance->Handle, MixControls, Flags);
609 case MXDM_SETCONTROLDETAILS:
610 return WdmAudSetControlDetails(SoundDeviceInstance->Handle, MixDetails, Flags);
611 break;
612 case MXDM_GETCONTROLDETAILS:
613 return WdmAudGetControlDetails(SoundDeviceInstance->Handle, MixDetails, Flags);
614 break;
615 default:
616 SND_ASSERT(0);
617 return MMSYSERR_NOTSUPPORTED;
618 }
619 }
620
621 MMRESULT
622 WdmAudGetDeviceInterfaceStringByMMixer(
623 IN MMDEVICE_TYPE DeviceType,
624 IN DWORD DeviceId,
625 IN LPWSTR Interface,
626 IN DWORD InterfaceLength,
627 OUT DWORD * InterfaceSize)
628 {
629 /* FIXME */
630 return MMSYSERR_NOTSUPPORTED;
631 }
632
633 MMRESULT
634 WdmAudSetMixerDeviceFormatByMMixer(
635 IN PSOUND_DEVICE_INSTANCE Instance,
636 IN DWORD DeviceId,
637 IN PWAVEFORMATEX WaveFormat,
638 IN DWORD WaveFormatSize)
639 {
640 Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
641 if ( ! Instance->hNotifyEvent )
642 return MMSYSERR_NOMEM;
643
644 if (MMixerOpen(&MixerContext, DeviceId, Instance->hNotifyEvent, NULL /* FIXME */, &Instance->Handle) == MM_STATUS_SUCCESS)
645 return MMSYSERR_NOERROR;
646
647 return MMSYSERR_BADDEVICEID;
648 }
649
650 MMRESULT
651 WdmAudSetWaveStateByMMixer(
652 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
653 IN BOOL bStart)
654 {
655 if (bStart)
656 {
657 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE);
658 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE);
659 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_RUN);
660 }
661 else
662 {
663 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE);
664 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE);
665 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP);
666 }
667
668 return MMSYSERR_NOERROR;
669 }
670
671 MMRESULT
672 WdmAudResetStreamByMMixer(
673 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
674 IN MMDEVICE_TYPE DeviceType,
675 IN BOOLEAN bStartReset)
676 {
677 /* FIXME */
678 return MMSYSERR_NOTSUPPORTED;
679 }
680
681 MMRESULT
682 WdmAudGetWavePositionByMMixer(
683 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
684 IN MMTIME* Time)
685 {
686 /* FIXME */
687 return MMSYSERR_NOTSUPPORTED;
688 }
689
690 MMRESULT
691 WdmAudCommitWaveBufferByMMixer(
692 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
693 IN PVOID OffsetPtr,
694 IN DWORD Length,
695 IN PSOUND_OVERLAPPED Overlap,
696 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
697 {
698 KSSTREAM_HEADER Packet;
699 PSOUND_DEVICE SoundDevice;
700 MMDEVICE_TYPE DeviceType;
701 MMRESULT Result;
702
703 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
704
705 if ( ! MMSUCCESS(Result) )
706 {
707 return TranslateInternalMmResult(Result);
708 }
709
710 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
711 SND_ASSERT( Result == MMSYSERR_NOERROR );
712
713 /* setup stream packet */
714 ZeroMemory(&Packet, sizeof(KSSTREAM_HEADER));
715 Packet.Size = sizeof(KSSTREAM_HEADER);
716 Packet.PresentationTime.Numerator = 1;
717 Packet.PresentationTime.Denominator = 1;
718 Packet.Data = OffsetPtr;
719 Packet.FrameExtent = Length;
720
721 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
722 {
723 Packet.DataUsed = Length;
724 }
725
726 Result = SyncOverlappedDeviceIoControl(SoundDeviceInstance->Handle,
727 IOCTL_KS_WRITE_STREAM,
728 NULL,
729 0,
730 &Packet,
731 sizeof(KSSTREAM_HEADER),
732 &Length);
733
734 /* HACK:
735 * don't call completion routine directly
736 */
737 CompletionRoutine(ERROR_SUCCESS, Length, (LPOVERLAPPED)Overlap);
738
739 return MMSYSERR_NOERROR;
740 }