Sync with trunk (r48008)
[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 DPRINT1("DeviceName %S\n", DetailData->DevicePath);
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 if (WdmAudInitUserModeMixer())
523 return MMSYSERR_NOERROR;
524 else
525 return MMSYSERR_ERROR;
526 }
527
528 MMRESULT
529 WdmAudCloseSoundDeviceByMMixer(
530 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
531 IN PVOID Handle)
532 {
533 MMDEVICE_TYPE DeviceType;
534 PSOUND_DEVICE SoundDevice;
535 MMRESULT Result;
536
537 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
538
539 if ( ! MMSUCCESS(Result) )
540 {
541 return TranslateInternalMmResult(Result);
542 }
543
544 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
545 SND_ASSERT( Result == MMSYSERR_NOERROR );
546
547 if (DeviceType == MIXER_DEVICE_TYPE)
548 {
549 /* no op */
550 return MMSYSERR_NOERROR;
551 }
552 else if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
553 {
554 /* make sure the pin is stopped */
555 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE);
556 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE);
557 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP);
558
559 CloseHandle(Handle);
560 return MMSYSERR_NOERROR;
561 }
562
563 /* midi is not supported */
564 return MMSYSERR_ERROR;
565 }
566
567 MMRESULT
568 WdmAudGetNumWdmDevsByMMixer(
569 IN MMDEVICE_TYPE DeviceType,
570 OUT DWORD* DeviceCount)
571 {
572 switch(DeviceType)
573 {
574 case MIXER_DEVICE_TYPE:
575 *DeviceCount = MMixerGetCount(&MixerContext);
576 break;
577 case WAVE_OUT_DEVICE_TYPE:
578 *DeviceCount = MMixerGetWaveOutCount(&MixerContext);
579 break;
580 case WAVE_IN_DEVICE_TYPE:
581 *DeviceCount = MMixerGetWaveInCount(&MixerContext);
582 break;
583 default:
584 *DeviceCount = 0;
585 }
586 return MMSYSERR_NOERROR;
587 }
588
589 MMRESULT
590 WdmAudQueryMixerInfoByMMixer(
591 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
592 IN UINT uMsg,
593 IN LPVOID Parameter,
594 IN DWORD Flags)
595 {
596 LPMIXERLINEW MixLine;
597 LPMIXERLINECONTROLSW MixControls;
598 LPMIXERCONTROLDETAILS MixDetails;
599
600 MixLine = (LPMIXERLINEW)Parameter;
601 MixControls = (LPMIXERLINECONTROLSW)Parameter;
602 MixDetails = (LPMIXERCONTROLDETAILS)Parameter;
603
604 /* FIXME param checks */
605
606 switch(uMsg)
607 {
608 case MXDM_GETLINEINFO:
609 return WdmAudGetLineInfo(SoundDeviceInstance->Handle, MixLine, Flags);
610 case MXDM_GETLINECONTROLS:
611 return WdmAudGetLineControls(SoundDeviceInstance->Handle, MixControls, Flags);
612 case MXDM_SETCONTROLDETAILS:
613 return WdmAudSetControlDetails(SoundDeviceInstance->Handle, MixDetails, Flags);
614 break;
615 case MXDM_GETCONTROLDETAILS:
616 return WdmAudGetControlDetails(SoundDeviceInstance->Handle, MixDetails, Flags);
617 break;
618 default:
619 SND_ASSERT(0);
620 return MMSYSERR_NOTSUPPORTED;
621 }
622 }
623
624 MMRESULT
625 WdmAudGetDeviceInterfaceStringByMMixer(
626 IN MMDEVICE_TYPE DeviceType,
627 IN DWORD DeviceId,
628 IN LPWSTR Interface,
629 IN DWORD InterfaceLength,
630 OUT DWORD * InterfaceSize)
631 {
632 /* FIXME */
633 return MMSYSERR_NOTSUPPORTED;
634 }
635
636 MMRESULT
637 WdmAudSetMixerDeviceFormatByMMixer(
638 IN PSOUND_DEVICE_INSTANCE Instance,
639 IN DWORD DeviceId,
640 IN PWAVEFORMATEX WaveFormat,
641 IN DWORD WaveFormatSize)
642 {
643 Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
644 if ( ! Instance->hNotifyEvent )
645 return MMSYSERR_NOMEM;
646
647 if (MMixerOpen(&MixerContext, DeviceId, Instance->hNotifyEvent, NULL /* FIXME */, &Instance->Handle) == MM_STATUS_SUCCESS)
648 return MMSYSERR_NOERROR;
649
650 return MMSYSERR_BADDEVICEID;
651 }
652
653 MMRESULT
654 WdmAudSetWaveStateByMMixer(
655 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
656 IN BOOL bStart)
657 {
658 if (bStart)
659 {
660 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE);
661 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE);
662 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_RUN);
663 }
664 else
665 {
666 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE);
667 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE);
668 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP);
669 }
670
671 return MMSYSERR_NOERROR;
672 }
673
674 MMRESULT
675 WdmAudResetStreamByMMixer(
676 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
677 IN MMDEVICE_TYPE DeviceType,
678 IN BOOLEAN bStartReset)
679 {
680 /* FIXME */
681 return MMSYSERR_NOTSUPPORTED;
682 }
683
684 MMRESULT
685 WdmAudGetWavePositionByMMixer(
686 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
687 IN MMTIME* Time)
688 {
689 /* FIXME */
690 return MMSYSERR_NOTSUPPORTED;
691 }
692
693 MMRESULT
694 WdmAudCommitWaveBufferByMMixer(
695 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
696 IN PVOID OffsetPtr,
697 IN DWORD Length,
698 IN PSOUND_OVERLAPPED Overlap,
699 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
700 {
701 KSSTREAM_HEADER Packet;
702 PSOUND_DEVICE SoundDevice;
703 MMDEVICE_TYPE DeviceType;
704 MMRESULT Result;
705
706 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
707
708 if ( ! MMSUCCESS(Result) )
709 {
710 return TranslateInternalMmResult(Result);
711 }
712
713 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
714 SND_ASSERT( Result == MMSYSERR_NOERROR );
715
716 /* setup stream packet */
717 ZeroMemory(&Packet, sizeof(KSSTREAM_HEADER));
718 Packet.Size = sizeof(KSSTREAM_HEADER);
719 Packet.PresentationTime.Numerator = 1;
720 Packet.PresentationTime.Denominator = 1;
721 Packet.Data = OffsetPtr;
722 Packet.FrameExtent = Length;
723
724 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
725 {
726 Packet.DataUsed = Length;
727 }
728
729 Result = SyncOverlappedDeviceIoControl(SoundDeviceInstance->Handle,
730 IOCTL_KS_WRITE_STREAM,
731 NULL,
732 0,
733 &Packet,
734 sizeof(KSSTREAM_HEADER),
735 &Length);
736
737 /* HACK:
738 * don't call completion routine directly
739 */
740 CompletionRoutine(ERROR_SUCCESS, Length, (LPOVERLAPPED)Overlap);
741
742 return MMSYSERR_NOERROR;
743 }