2 * PROJECT: ReactOS Sound System
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/wdmaud.drv/mmixer.c
6 * PURPOSE: WDM Audio Mixer API (User-mode part)
7 * PROGRAMMERS: Johannes Anderwald
14 KSSTREAM_HEADER Header
;
16 PSOUND_OVERLAPPED Overlap
;
17 LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
;
18 }IO_PACKET
, *LPIO_PACKET
;
20 BOOL MMixerLibraryInitialized
= FALSE
;
24 PVOID
Alloc(ULONG NumBytes
);
25 MIXER_STATUS
Close(HANDLE hDevice
);
26 VOID
Free(PVOID Block
);
27 VOID
Copy(PVOID Src
, PVOID Dst
, ULONG NumBytes
);
28 MIXER_STATUS
Open(IN LPWSTR DevicePath
, OUT PHANDLE hDevice
);
29 MIXER_STATUS
Control(IN HANDLE hMixer
, IN ULONG dwIoControlCode
, IN PVOID lpInBuffer
, IN ULONG nInBufferSize
, OUT PVOID lpOutBuffer
, ULONG nOutBufferSize
, PULONG lpBytesReturned
);
30 MIXER_STATUS
Enum(IN PVOID EnumContext
, IN ULONG DeviceIndex
, OUT LPWSTR
* DeviceName
, OUT PHANDLE OutHandle
, OUT PHANDLE OutKey
);
31 MIXER_STATUS
OpenKey(IN HANDLE hKey
, IN LPWSTR SubKey
, IN ULONG DesiredAccess
, OUT PHANDLE OutKey
);
32 MIXER_STATUS
CloseKey(IN HANDLE hKey
);
33 MIXER_STATUS
QueryKeyValue(IN HANDLE hKey
, IN LPWSTR KeyName
, OUT PVOID
* ResultBuffer
, OUT PULONG ResultLength
, OUT PULONG KeyType
);
34 PVOID
AllocEventData(IN ULONG ExtraSize
);
35 VOID
FreeEventData(IN PVOID EventData
);
37 MIXER_CONTEXT MixerContext
=
39 sizeof(MIXER_CONTEXT
),
54 GUID CategoryGuid
= {STATIC_KSCATEGORY_AUDIO
};
60 OUT PVOID
* ResultBuffer
,
61 OUT PULONG ResultLength
,
64 if (RegQueryValueExW((HKEY
)hKey
, KeyName
, NULL
, KeyType
, NULL
, ResultLength
) == ERROR_FILE_NOT_FOUND
)
65 return MM_STATUS_UNSUCCESSFUL
;
67 *ResultBuffer
= HeapAlloc(GetProcessHeap(), 0, *ResultLength
);
68 if (*ResultBuffer
== NULL
)
69 return MM_STATUS_NO_MEMORY
;
71 if (RegQueryValueExW((HKEY
)hKey
, KeyName
, NULL
, KeyType
, *ResultBuffer
, ResultLength
) != ERROR_SUCCESS
)
73 HeapFree(GetProcessHeap(), 0, *ResultBuffer
);
74 return MM_STATUS_UNSUCCESSFUL
;
76 return MM_STATUS_SUCCESS
;
83 IN ULONG DesiredAccess
,
86 if (RegOpenKeyExW((HKEY
)hKey
, SubKey
, 0, DesiredAccess
, (PHKEY
)OutKey
) == ERROR_SUCCESS
)
87 return MM_STATUS_SUCCESS
;
89 return MM_STATUS_UNSUCCESSFUL
;
96 RegCloseKey((HKEY
)hKey
);
97 return MM_STATUS_SUCCESS
;
101 PVOID
Alloc(ULONG NumBytes
)
103 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, NumBytes
);
107 Close(HANDLE hDevice
)
109 if (CloseHandle(hDevice
))
110 return MM_STATUS_SUCCESS
;
112 return MM_STATUS_UNSUCCESSFUL
;
118 HeapFree(GetProcessHeap(), 0, Block
);
122 Copy(PVOID Src
, PVOID Dst
, ULONG NumBytes
)
124 RtlMoveMemory(Src
, Dst
, NumBytes
);
129 IN LPWSTR DevicePath
,
132 DevicePath
[1] = L
'\\';
133 *hDevice
= CreateFileW(DevicePath
,
134 GENERIC_READ
| GENERIC_WRITE
,
138 FILE_FLAG_OVERLAPPED
,
140 if (*hDevice
== INVALID_HANDLE_VALUE
)
142 return MM_STATUS_UNSUCCESSFUL
;
145 return MM_STATUS_SUCCESS
;
151 IN ULONG dwIoControlCode
,
153 IN ULONG nInBufferSize
,
154 OUT PVOID lpOutBuffer
,
155 ULONG nOutBufferSize
,
156 PULONG lpBytesReturned
)
158 OVERLAPPED Overlapped
;
160 DWORD Transferred
= 0;
162 /* Overlapped I/O is done here - this is used for waiting for completion */
163 ZeroMemory(&Overlapped
, sizeof(OVERLAPPED
));
164 Overlapped
.hEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
166 if ( ! Overlapped
.hEvent
)
167 return MM_STATUS_NO_MEMORY
;
169 /* Talk to the device */
170 IoResult
= DeviceIoControl(hMixer
,
179 /* If failure occurs, make sure it's not just due to the overlapped I/O */
182 if ( GetLastError() != ERROR_IO_PENDING
)
184 CloseHandle(Overlapped
.hEvent
);
186 if (GetLastError() == ERROR_MORE_DATA
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
188 if ( lpBytesReturned
)
189 *lpBytesReturned
= Transferred
;
190 return MM_STATUS_MORE_ENTRIES
;
193 return MM_STATUS_UNSUCCESSFUL
;
197 /* Wait for the I/O to complete */
198 IoResult
= GetOverlappedResult(hMixer
,
203 /* Don't need this any more */
204 CloseHandle(Overlapped
.hEvent
);
207 return MM_STATUS_UNSUCCESSFUL
;
209 if ( lpBytesReturned
)
210 *lpBytesReturned
= Transferred
;
212 return MM_STATUS_SUCCESS
;
217 IN PVOID EnumContext
,
218 IN ULONG DeviceIndex
,
219 OUT LPWSTR
* DeviceName
,
220 OUT PHANDLE OutHandle
,
223 SP_DEVICE_INTERFACE_DATA InterfaceData
;
224 SP_DEVINFO_DATA DeviceData
;
225 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData
;
230 //printf("Enum EnumContext %p DeviceIndex %lu OutHandle %p\n", EnumContext, DeviceIndex, OutHandle);
232 InterfaceData
.cbSize
= sizeof(InterfaceData
);
233 InterfaceData
.Reserved
= 0;
235 Result
= SetupDiEnumDeviceInterfaces(EnumContext
,
243 if (GetLastError() == ERROR_NO_MORE_ITEMS
)
245 return MM_STATUS_NO_MORE_DEVICES
;
247 return MM_STATUS_UNSUCCESSFUL
;
250 Length
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) + MAX_PATH
* sizeof(WCHAR
);
251 DetailData
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(),
254 DetailData
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
255 DeviceData
.cbSize
= sizeof(DeviceData
);
256 DeviceData
.Reserved
= 0;
258 Result
= SetupDiGetDeviceInterfaceDetailW(EnumContext
,
267 DPRINT("SetupDiGetDeviceInterfaceDetailW failed with %lu\n", GetLastError());
268 return MM_STATUS_UNSUCCESSFUL
;
272 *OutKey
= SetupDiOpenDeviceInterfaceRegKey(EnumContext
, &InterfaceData
, 0, KEY_READ
);
273 if ((HKEY
)*OutKey
== INVALID_HANDLE_VALUE
)
275 HeapFree(GetProcessHeap(), 0, DetailData
);
276 return MM_STATUS_UNSUCCESSFUL
;
279 Status
= Open(DetailData
->DevicePath
, OutHandle
);
281 if (Status
!= MM_STATUS_SUCCESS
)
283 RegCloseKey((HKEY
)*OutKey
);
284 HeapFree(GetProcessHeap(), 0, DetailData
);
288 *DeviceName
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, (wcslen(DetailData
->DevicePath
)+1) * sizeof(WCHAR
));
289 if (*DeviceName
== NULL
)
291 CloseHandle(*OutHandle
);
292 RegCloseKey((HKEY
)*OutKey
);
293 HeapFree(GetProcessHeap(), 0, DetailData
);
294 return MM_STATUS_NO_MEMORY
;
296 wcscpy(*DeviceName
, DetailData
->DevicePath
);
297 HeapFree(GetProcessHeap(), 0, DetailData
);
306 PKSEVENTDATA Data
= (PKSEVENTDATA
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(KSEVENTDATA
) + ExtraSize
);
310 Data
->EventHandle
.Event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
311 if (!Data
->EventHandle
.Event
)
313 HeapFree(GetProcessHeap(), 0, Data
);
317 Data
->NotificationType
= KSEVENTF_EVENT_HANDLE
;
322 FreeEventData(IN PVOID EventData
)
324 PKSEVENTDATA Data
= (PKSEVENTDATA
)EventData
;
326 CloseHandle(Data
->EventHandle
.Event
);
327 HeapFree(GetProcessHeap(), 0, Data
);
332 WdmAudInitUserModeMixer()
334 HDEVINFO DeviceHandle
;
337 if (MMixerLibraryInitialized
)
339 /* library is already initialized */
344 /* create a device list */
345 DeviceHandle
= SetupDiGetClassDevs(&CategoryGuid
,
348 DIGCF_DEVICEINTERFACE
/* FIXME |DIGCF_PRESENT*/);
350 if (DeviceHandle
== INVALID_HANDLE_VALUE
)
352 /* failed to create a device list */
357 /* initialize the mixer library */
358 Status
= MMixerInitialize(&MixerContext
, Enum
, (PVOID
)DeviceHandle
);
360 /* free device list */
361 SetupDiDestroyDeviceInfoList(DeviceHandle
);
363 if (Status
!= MM_STATUS_SUCCESS
)
365 /* failed to initialize mixer library */
366 DPRINT1("Failed to initialize mixer library with %x\n", Status
);
370 /* library is now initialized */
371 MMixerLibraryInitialized
= TRUE
;
373 /* completed successfully */
378 WdmAudCleanupByMMixer()
381 return MMSYSERR_NOERROR
;
385 WdmAudGetMixerCapabilties(
387 LPMIXERCAPSW Capabilities
)
389 if (MMixerGetCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
390 return MMSYSERR_NOERROR
;
392 return MMSYSERR_BADDEVICEID
;
399 IN LPMIXERLINEW MixLine
,
402 if (MMixerGetLineInfo(&MixerContext
, hMixer
, MixerId
, Flags
, MixLine
) == MM_STATUS_SUCCESS
)
403 return MMSYSERR_NOERROR
;
405 return MMSYSERR_ERROR
;
409 WdmAudGetLineControls(
412 IN LPMIXERLINECONTROLSW MixControls
,
415 if (MMixerGetLineControls(&MixerContext
, hMixer
, MixerId
, Flags
, MixControls
) == MM_STATUS_SUCCESS
)
416 return MMSYSERR_NOERROR
;
418 return MMSYSERR_ERROR
;
422 WdmAudSetControlDetails(
425 IN LPMIXERCONTROLDETAILS MixDetails
,
428 if (MMixerSetControlDetails(&MixerContext
, hMixer
, MixerId
, Flags
, MixDetails
) == MM_STATUS_SUCCESS
)
429 return MMSYSERR_NOERROR
;
431 return MMSYSERR_ERROR
;
436 WdmAudGetControlDetails(
439 IN LPMIXERCONTROLDETAILS MixDetails
,
442 if (MMixerGetControlDetails(&MixerContext
, hMixer
, MixerId
, Flags
, MixDetails
) == MM_STATUS_SUCCESS
)
443 return MMSYSERR_NOERROR
;
445 return MMSYSERR_ERROR
;
449 WdmAudGetWaveOutCapabilities(
451 LPWAVEOUTCAPSW Capabilities
)
453 if (MMixerWaveOutCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
454 return MMSYSERR_NOERROR
;
456 return MMSYSERR_ERROR
;
461 WdmAudGetWaveInCapabilities(
463 LPWAVEINCAPSW Capabilities
)
465 if (MMixerWaveInCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
466 return MMSYSERR_NOERROR
;
468 return MMSYSERR_ERROR
;
472 WdmAudSetWaveDeviceFormatByMMixer(
473 IN PSOUND_DEVICE_INSTANCE Instance
,
475 IN PWAVEFORMATEX WaveFormat
,
476 IN DWORD WaveFormatSize
)
478 MMDEVICE_TYPE DeviceType
;
479 PSOUND_DEVICE SoundDevice
;
483 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
485 if ( ! MMSUCCESS(Result
) )
487 return TranslateInternalMmResult(Result
);
490 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
491 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
493 bWaveIn
= (DeviceType
== WAVE_IN_DEVICE_TYPE
? TRUE
: FALSE
);
495 if (MMixerOpenWave(&MixerContext
, DeviceId
, bWaveIn
, WaveFormat
, NULL
, NULL
, &Instance
->Handle
) == MM_STATUS_SUCCESS
)
497 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
499 MMixerSetWaveStatus(&MixerContext
, Instance
->Handle
, KSSTATE_ACQUIRE
);
500 MMixerSetWaveStatus(&MixerContext
, Instance
->Handle
, KSSTATE_PAUSE
);
501 MMixerSetWaveStatus(&MixerContext
, Instance
->Handle
, KSSTATE_RUN
);
503 return MMSYSERR_NOERROR
;
505 return MMSYSERR_ERROR
;
510 WdmAudGetCapabilitiesByMMixer(
511 IN PSOUND_DEVICE SoundDevice
,
513 OUT PVOID Capabilities
,
514 IN DWORD CapabilitiesSize
)
516 MMDEVICE_TYPE DeviceType
;
519 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
520 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
522 if (DeviceType
== MIXER_DEVICE_TYPE
)
524 return WdmAudGetMixerCapabilties(DeviceId
, (LPMIXERCAPSW
)Capabilities
);
526 else if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
528 return WdmAudGetWaveOutCapabilities(DeviceId
, (LPWAVEOUTCAPSW
)Capabilities
);
530 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
532 return WdmAudGetWaveInCapabilities(DeviceId
, (LPWAVEINCAPSW
)Capabilities
);
537 return MMSYSERR_ERROR
;
542 WdmAudOpenSoundDeviceByMMixer(
543 IN
struct _SOUND_DEVICE
* SoundDevice
,
546 if (WdmAudInitUserModeMixer())
547 return MMSYSERR_NOERROR
;
549 return MMSYSERR_ERROR
;
553 WdmAudCloseSoundDeviceByMMixer(
554 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
557 MMDEVICE_TYPE DeviceType
;
558 PSOUND_DEVICE SoundDevice
;
561 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
563 if ( ! MMSUCCESS(Result
) )
565 return TranslateInternalMmResult(Result
);
568 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
569 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
571 if (DeviceType
== MIXER_DEVICE_TYPE
)
574 return MMSYSERR_NOERROR
;
576 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
578 /* make sure the pin is stopped */
579 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
580 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
581 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_STOP
);
584 return MMSYSERR_NOERROR
;
587 /* midi is not supported */
588 return MMSYSERR_ERROR
;
592 WdmAudGetNumWdmDevsByMMixer(
593 IN MMDEVICE_TYPE DeviceType
,
594 OUT DWORD
* DeviceCount
)
598 case MIXER_DEVICE_TYPE
:
599 *DeviceCount
= MMixerGetCount(&MixerContext
);
601 case WAVE_OUT_DEVICE_TYPE
:
602 *DeviceCount
= MMixerGetWaveOutCount(&MixerContext
);
604 case WAVE_IN_DEVICE_TYPE
:
605 *DeviceCount
= MMixerGetWaveInCount(&MixerContext
);
610 return MMSYSERR_NOERROR
;
614 WdmAudQueryMixerInfoByMMixer(
615 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
621 LPMIXERLINEW MixLine
;
622 LPMIXERLINECONTROLSW MixControls
;
623 LPMIXERCONTROLDETAILS MixDetails
;
624 HANDLE hMixer
= NULL
;
626 MixLine
= (LPMIXERLINEW
)Parameter
;
627 MixControls
= (LPMIXERLINECONTROLSW
)Parameter
;
628 MixDetails
= (LPMIXERCONTROLDETAILS
)Parameter
;
630 /* FIXME param checks */
632 if (SoundDeviceInstance
)
634 hMixer
= SoundDeviceInstance
->Handle
;
639 case MXDM_GETLINEINFO
:
640 return WdmAudGetLineInfo(hMixer
, MixerId
, MixLine
, Flags
);
641 case MXDM_GETLINECONTROLS
:
642 return WdmAudGetLineControls(hMixer
, MixerId
, MixControls
, Flags
);
643 case MXDM_SETCONTROLDETAILS
:
644 return WdmAudSetControlDetails(hMixer
, MixerId
, MixDetails
, Flags
);
645 case MXDM_GETCONTROLDETAILS
:
646 return WdmAudGetControlDetails(hMixer
, MixerId
, MixDetails
, Flags
);
648 DPRINT1("MixerId %lu, uMsg %lu, Parameter %p, Flags %lu\n", MixerId
, uMsg
, Parameter
, Flags
);
650 return MMSYSERR_NOTSUPPORTED
;
655 WdmAudGetDeviceInterfaceStringByMMixer(
656 IN MMDEVICE_TYPE DeviceType
,
659 IN DWORD InterfaceLength
,
660 OUT DWORD
* InterfaceSize
)
663 return MMSYSERR_NOTSUPPORTED
;
669 IN PVOID MixerEventContext
,
671 IN ULONG NotificationType
,
674 PSOUND_DEVICE_INSTANCE Instance
= (PSOUND_DEVICE_INSTANCE
)MixerEventContext
;
676 DriverCallback(Instance
->WinMM
.ClientCallback
,
677 HIWORD(Instance
->WinMM
.Flags
),
678 Instance
->WinMM
.Handle
,
680 Instance
->WinMM
.ClientCallbackInstanceData
,
686 WdmAudSetMixerDeviceFormatByMMixer(
687 IN PSOUND_DEVICE_INSTANCE Instance
,
689 IN PWAVEFORMATEX WaveFormat
,
690 IN DWORD WaveFormatSize
)
692 if (MMixerOpen(&MixerContext
, DeviceId
, (PVOID
)Instance
, MixerEventCallback
, &Instance
->Handle
) == MM_STATUS_SUCCESS
)
693 return MMSYSERR_NOERROR
;
695 return MMSYSERR_BADDEVICEID
;
699 WdmAudSetWaveStateByMMixer(
700 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
703 MMDEVICE_TYPE DeviceType
;
704 PSOUND_DEVICE SoundDevice
;
707 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
708 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
711 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
712 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
714 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
718 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
719 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
720 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_RUN
);
724 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
725 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
726 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_STOP
);
729 else if (DeviceType
== MIDI_IN_DEVICE_TYPE
|| DeviceType
== MIDI_OUT_DEVICE_TYPE
)
733 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
734 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
735 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_RUN
);
739 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
740 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
741 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_STOP
);
745 return MMSYSERR_NOERROR
;
749 WdmAudResetStreamByMMixer(
750 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
751 IN MMDEVICE_TYPE DeviceType
,
752 IN BOOLEAN bStartReset
)
756 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
758 Status
= MMixerSetWaveResetState(&MixerContext
, SoundDeviceInstance
->Handle
, bStartReset
);
759 if (Status
== MM_STATUS_SUCCESS
)
761 /* completed successfully */
762 return MMSYSERR_NOERROR
;
767 return MMSYSERR_NOTSUPPORTED
;
771 WdmAudGetWavePositionByMMixer(
772 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
776 return MMSYSERR_NOTSUPPORTED
;
786 LPIO_PACKET Packet
= (LPIO_PACKET
)lpParameter
;
788 Result
= SyncOverlappedDeviceIoControl(Packet
->hDevice
,
789 IOCTL_KS_WRITE_STREAM
, //FIXME IOCTL_KS_READ_STREAM
793 sizeof(KSSTREAM_HEADER
),
797 * don't call completion routine directly
800 Packet
->CompletionRoutine(ERROR_SUCCESS
, Packet
->Header
.DataUsed
, (LPOVERLAPPED
)Packet
->Overlap
);
802 HeapFree(GetProcessHeap(), 0, Packet
);
813 WdmAudCommitWaveBufferByMMixer(
814 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
817 IN PSOUND_OVERLAPPED Overlap
,
818 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
)
820 PSOUND_DEVICE SoundDevice
;
821 MMDEVICE_TYPE DeviceType
;
826 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
828 if ( ! MMSUCCESS(Result
) )
830 return TranslateInternalMmResult(Result
);
833 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
834 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
836 Packet
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IO_PACKET
));
840 return MMSYSERR_NOMEM
;
843 /* setup stream packet */
844 Packet
->Header
.Size
= sizeof(KSSTREAM_HEADER
);
845 Packet
->Header
.PresentationTime
.Numerator
= 1;
846 Packet
->Header
.PresentationTime
.Denominator
= 1;
847 Packet
->Header
.Data
= OffsetPtr
;
848 Packet
->Header
.FrameExtent
= Length
;
849 Packet
->hDevice
= SoundDeviceInstance
->Handle
;
850 Packet
->Overlap
= Overlap
;
851 Packet
->CompletionRoutine
= CompletionRoutine
;
853 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
855 Packet
->Header
.DataUsed
= Length
;
858 hThread
= CreateThread(NULL
, 0, IoStreamingThread
, (LPVOID
)Packet
, 0, NULL
);
862 return MMSYSERR_ERROR
;
865 CloseHandle(hThread
);
867 return MMSYSERR_NOERROR
;