Sync with trunk head
[reactos.git] / 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 VOID
358 WdmAudCleanupMMixer()
359 {
360 /* TODO */
361 }
362
363 MMRESULT
364 WdmAudGetMixerCapabilties(
365 IN ULONG DeviceId,
366 LPMIXERCAPSW Capabilities)
367 {
368 if (MMixerGetCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS)
369 return MMSYSERR_NOERROR;
370
371 return MMSYSERR_BADDEVICEID;
372 }
373
374 MMRESULT
375 WdmAudGetLineInfo(
376 IN HANDLE hMixer,
377 IN LPMIXERLINEW MixLine,
378 IN ULONG Flags)
379 {
380 if (MMixerGetLineInfo(&MixerContext, hMixer, Flags, MixLine) == MM_STATUS_SUCCESS)
381 return MMSYSERR_NOERROR;
382
383 return MMSYSERR_ERROR;
384 }
385
386 MMRESULT
387 WdmAudGetLineControls(
388 IN HANDLE hMixer,
389 IN LPMIXERLINECONTROLSW MixControls,
390 IN ULONG Flags)
391 {
392 if (MMixerGetLineControls(&MixerContext, hMixer, Flags, MixControls) == MM_STATUS_SUCCESS)
393 return MMSYSERR_NOERROR;
394
395 return MMSYSERR_ERROR;
396 }
397
398 MMRESULT
399 WdmAudSetControlDetails(
400 IN HANDLE hMixer,
401 IN LPMIXERCONTROLDETAILS MixDetails,
402 IN ULONG Flags)
403 {
404 if (MMixerSetControlDetails(&MixerContext, hMixer, Flags, MixDetails) == MM_STATUS_SUCCESS)
405 return MMSYSERR_NOERROR;
406
407 return MMSYSERR_ERROR;
408
409 }
410
411 MMRESULT
412 WdmAudGetControlDetails(
413 IN HANDLE hMixer,
414 IN LPMIXERCONTROLDETAILS MixDetails,
415 IN ULONG Flags)
416 {
417 if (MMixerGetControlDetails(&MixerContext, hMixer, Flags, MixDetails) == MM_STATUS_SUCCESS)
418 return MMSYSERR_NOERROR;
419
420 return MMSYSERR_ERROR;
421 }
422
423 MMRESULT
424 WdmAudGetWaveOutCapabilities(
425 IN ULONG DeviceId,
426 LPWAVEOUTCAPSW Capabilities)
427 {
428 if (MMixerWaveOutCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS)
429 return MMSYSERR_NOERROR;
430
431 return MMSYSERR_ERROR;
432
433 }
434
435 MMRESULT
436 WdmAudGetWaveInCapabilities(
437 IN ULONG DeviceId,
438 LPWAVEINCAPSW Capabilities)
439 {
440 if (MMixerWaveInCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS)
441 return MMSYSERR_NOERROR;
442
443 return MMSYSERR_ERROR;
444 }
445
446 MMRESULT
447 WdmAudSetWdmWaveDeviceFormatByMMixer(
448 IN PSOUND_DEVICE_INSTANCE Instance,
449 IN DWORD DeviceId,
450 IN PWAVEFORMATEX WaveFormat,
451 IN DWORD WaveFormatSize)
452 {
453 MMDEVICE_TYPE DeviceType;
454 PSOUND_DEVICE SoundDevice;
455 MMRESULT Result;
456 BOOL bWaveIn;
457
458 Result = GetSoundDeviceFromInstance(Instance, &SoundDevice);
459
460 if ( ! MMSUCCESS(Result) )
461 {
462 return TranslateInternalMmResult(Result);
463 }
464
465 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
466 SND_ASSERT( Result == MMSYSERR_NOERROR );
467
468 bWaveIn = (DeviceType == WAVE_IN_DEVICE_TYPE ? TRUE : FALSE);
469
470 if (MMixerOpenWave(&MixerContext, DeviceId, bWaveIn, WaveFormat, NULL, NULL, &Instance->Handle) == MM_STATUS_SUCCESS)
471 {
472 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
473 {
474 MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_ACQUIRE);
475 MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_PAUSE);
476 MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_RUN);
477 }
478 return MMSYSERR_NOERROR;
479 }
480 return MMSYSERR_ERROR;
481 }
482
483
484 MMRESULT
485 WdmAudGetCapabilitiesByMMixer(
486 IN PSOUND_DEVICE SoundDevice,
487 IN DWORD DeviceId,
488 OUT PVOID Capabilities,
489 IN DWORD CapabilitiesSize)
490 {
491 MMDEVICE_TYPE DeviceType;
492 MMRESULT Result;
493
494 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
495 SND_ASSERT( Result == MMSYSERR_NOERROR );
496
497 if (DeviceType == MIXER_DEVICE_TYPE)
498 {
499 return WdmAudGetMixerCapabilties(DeviceId, (LPMIXERCAPSW)Capabilities);
500 }
501 else if (DeviceType == WAVE_OUT_DEVICE_TYPE)
502 {
503 return WdmAudGetWaveOutCapabilities(DeviceId, (LPWAVEOUTCAPSW)Capabilities);
504 }
505 else if (DeviceType == WAVE_IN_DEVICE_TYPE)
506 {
507 return WdmAudGetWaveInCapabilities(DeviceId, (LPWAVEINCAPSW)Capabilities);
508 }
509 else
510 {
511 // not supported
512 return MMSYSERR_ERROR;
513 }
514 }
515
516 MMRESULT
517 WdmAudOpenSoundDeviceByMMixer(
518 IN struct _SOUND_DEVICE* SoundDevice,
519 OUT PVOID* Handle)
520 {
521 return WdmAudInitUserModeMixer();
522 }
523
524 MMRESULT
525 WdmAudCloseSoundDeviceByMMixer(
526 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
527 IN PVOID Handle)
528 {
529 MMDEVICE_TYPE DeviceType;
530 PSOUND_DEVICE SoundDevice;
531 MMRESULT Result;
532
533 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
534
535 if ( ! MMSUCCESS(Result) )
536 {
537 return TranslateInternalMmResult(Result);
538 }
539
540 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
541 SND_ASSERT( Result == MMSYSERR_NOERROR );
542
543 if (DeviceType == MIXER_DEVICE_TYPE)
544 {
545 /* no op */
546 return MMSYSERR_NOERROR;
547 }
548 else if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
549 {
550 /* make sure the pin is stopped */
551 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE);
552 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE);
553 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP);
554
555 CloseHandle(Handle);
556 return MMSYSERR_NOERROR;
557 }
558
559 /* midi is not supported */
560 return MMSYSERR_ERROR;
561 }
562
563 MMRESULT
564 WdmAudGetNumDevsByMMixer(
565 IN MMDEVICE_TYPE DeviceType,
566 OUT DWORD* DeviceCount)
567 {
568 switch(DeviceType)
569 {
570 case MIXER_DEVICE_TYPE:
571 *DeviceCount = MMixerGetCount(&MixerContext);
572 break;
573 case WAVE_OUT_DEVICE_TYPE:
574 *DeviceCount = MMixerGetWaveOutCount(&MixerContext);
575 break;
576 case WAVE_IN_DEVICE_TYPE:
577 *DeviceCount = MMixerGetWaveInCount(&MixerContext);
578 break;
579 default:
580 *DeviceCount = 0;
581 }
582 return MMSYSERR_NOERROR;
583 }
584
585 MMRESULT
586 WdmAudQueryMixerInfoByMMixer(
587 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
588 IN UINT uMsg,
589 IN LPVOID Parameter,
590 IN DWORD Flags)
591 {
592 LPMIXERLINEW MixLine;
593 LPMIXERLINECONTROLSW MixControls;
594 LPMIXERCONTROLDETAILS MixDetails;
595
596 MixLine = (LPMIXERLINEW)Parameter;
597 MixControls = (LPMIXERLINECONTROLSW)Parameter;
598 MixDetails = (LPMIXERCONTROLDETAILS)Parameter;
599
600 /* FIXME param checks */
601
602 switch(uMsg)
603 {
604 case MXDM_GETLINEINFO:
605 return WdmAudGetLineInfo(SoundDeviceInstance->Handle, MixLine, Flags);
606 case MXDM_GETLINECONTROLS:
607 return WdmAudGetLineControls(SoundDeviceInstance->Handle, MixControls, Flags);
608 case MXDM_SETCONTROLDETAILS:
609 return WdmAudSetControlDetails(SoundDeviceInstance->Handle, MixDetails, Flags);
610 break;
611 case MXDM_GETCONTROLDETAILS:
612 return WdmAudGetControlDetails(SoundDeviceInstance->Handle, MixDetails, Flags);
613 break;
614 default:
615 SND_ASSERT(0);
616 return MMSYSERR_NOTSUPPORTED;
617 }
618 }
619
620 MMRESULT
621 WdmAudGetDeviceInterfaceStringByMMixer(
622 IN MMDEVICE_TYPE DeviceType,
623 IN DWORD DeviceId,
624 IN LPWSTR Interface,
625 IN DWORD InterfaceLength,
626 OUT DWORD * InterfaceSize)
627 {
628 /* FIXME */
629 return MMSYSERR_NOTSUPPORTED;
630 }
631
632 MMRESULT
633 WdmAudSetMixerDeviceFormatByMMixer(
634 IN PSOUND_DEVICE_INSTANCE Instance,
635 IN DWORD DeviceId,
636 IN PWAVEFORMATEX WaveFormat,
637 IN DWORD WaveFormatSize)
638 {
639 Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
640 if ( ! Instance->hNotifyEvent )
641 return MMSYSERR_NOMEM;
642
643 if (MMixerOpen(&MixerContext, DeviceId, Instance->hNotifyEvent, NULL /* FIXME */, &Instance->Handle) == MM_STATUS_SUCCESS)
644 return MMSYSERR_NOERROR;
645
646 return MMSYSERR_BADDEVICEID;
647 }
648
649 MMRESULT
650 WdmAudSetWdmWaveStateByMMixer(
651 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
652 IN BOOL bStart)
653 {
654 if (bStart)
655 {
656 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE);
657 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE);
658 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_RUN);
659 }
660 else
661 {
662 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE);
663 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE);
664 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP);
665 }
666
667 return MMSYSERR_NOERROR;
668 }
669
670 MMRESULT
671 WdmAudResetStreamByMMixer(
672 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
673 IN MMDEVICE_TYPE DeviceType,
674 IN BOOLEAN bStartReset)
675 {
676 /* FIXME */
677 return MMSYSERR_NOTSUPPORTED;
678 }
679
680 MMRESULT
681 WdmAudGetWdmPositionByMMixer(
682 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
683 IN MMTIME* Time)
684 {
685 /* FIXME */
686 return MMSYSERR_NOTSUPPORTED;
687 }
688
689 MMRESULT
690 WdmAudCommitWaveBufferByMMixer(
691 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
692 IN PVOID OffsetPtr,
693 IN DWORD Length,
694 IN PSOUND_OVERLAPPED Overlap,
695 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
696 {
697 KSSTREAM_HEADER Packet;
698 PSOUND_DEVICE SoundDevice;
699 MMDEVICE_TYPE DeviceType;
700 MMRESULT Result;
701
702 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
703
704 if ( ! MMSUCCESS(Result) )
705 {
706 return TranslateInternalMmResult(Result);
707 }
708
709 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
710 SND_ASSERT( Result == MMSYSERR_NOERROR );
711
712 /* setup stream packet */
713 ZeroMemory(&Packet, sizeof(KSSTREAM_HEADER));
714 Packet.Size = sizeof(KSSTREAM_HEADER);
715 Packet.PresentationTime.Numerator = 1;
716 Packet.PresentationTime.Denominator = 1;
717 Packet.Data = OffsetPtr;
718 Packet.FrameExtent = Length;
719
720 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
721 {
722 Packet.DataUsed = Length;
723 }
724
725 Result = SyncOverlappedDeviceIoControl(SoundDeviceInstance->Handle,
726 IOCTL_KS_WRITE_STREAM,
727 NULL,
728 0,
729 &Packet,
730 sizeof(KSSTREAM_HEADER),
731 &Length);
732
733 /* HACK:
734 * don't call completion routine directly
735 */
736 CompletionRoutine(ERROR_SUCCESS, Length, (LPOVERLAPPED)Overlap);
737
738 return MMSYSERR_NOERROR;
739 }