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 DPRINT1("DeviceName %S\n", DetailData
->DevicePath
);
297 wcscpy(*DeviceName
, DetailData
->DevicePath
);
298 HeapFree(GetProcessHeap(), 0, DetailData
);
307 PKSEVENTDATA Data
= (PKSEVENTDATA
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(KSEVENTDATA
) + ExtraSize
);
311 Data
->EventHandle
.Event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
312 if (!Data
->EventHandle
.Event
)
314 HeapFree(GetProcessHeap(), 0, Data
);
318 Data
->NotificationType
= KSEVENTF_EVENT_HANDLE
;
323 FreeEventData(IN PVOID EventData
)
325 PKSEVENTDATA Data
= (PKSEVENTDATA
)EventData
;
327 CloseHandle(Data
->EventHandle
.Event
);
328 HeapFree(GetProcessHeap(), 0, Data
);
333 WdmAudInitUserModeMixer()
335 HDEVINFO DeviceHandle
;
338 if (MMixerLibraryInitialized
)
340 /* library is already initialized */
345 /* create a device list */
346 DeviceHandle
= SetupDiGetClassDevs(&CategoryGuid
,
349 DIGCF_DEVICEINTERFACE
/* FIXME |DIGCF_PRESENT*/);
351 if (DeviceHandle
== INVALID_HANDLE_VALUE
)
353 /* failed to create a device list */
358 /* initialize the mixer library */
359 Status
= MMixerInitialize(&MixerContext
, Enum
, (PVOID
)DeviceHandle
);
361 /* free device list */
362 SetupDiDestroyDeviceInfoList(DeviceHandle
);
364 if (Status
!= MM_STATUS_SUCCESS
)
366 /* failed to initialize mixer library */
367 DPRINT1("Failed to initialize mixer library with %x\n", Status
);
371 /* library is now initialized */
372 MMixerLibraryInitialized
= TRUE
;
374 /* completed successfully */
379 WdmAudCleanupByMMixer()
382 return MMSYSERR_NOERROR
;
386 WdmAudGetMixerCapabilties(
388 LPMIXERCAPSW Capabilities
)
390 if (MMixerGetCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
391 return MMSYSERR_NOERROR
;
393 return MMSYSERR_BADDEVICEID
;
400 IN LPMIXERLINEW MixLine
,
403 if (MMixerGetLineInfo(&MixerContext
, hMixer
, MixerId
, Flags
, MixLine
) == MM_STATUS_SUCCESS
)
404 return MMSYSERR_NOERROR
;
406 return MMSYSERR_ERROR
;
410 WdmAudGetLineControls(
413 IN LPMIXERLINECONTROLSW MixControls
,
416 if (MMixerGetLineControls(&MixerContext
, hMixer
, MixerId
, Flags
, MixControls
) == MM_STATUS_SUCCESS
)
417 return MMSYSERR_NOERROR
;
419 return MMSYSERR_ERROR
;
423 WdmAudSetControlDetails(
426 IN LPMIXERCONTROLDETAILS MixDetails
,
429 if (MMixerSetControlDetails(&MixerContext
, hMixer
, MixerId
, Flags
, MixDetails
) == MM_STATUS_SUCCESS
)
430 return MMSYSERR_NOERROR
;
432 return MMSYSERR_ERROR
;
437 WdmAudGetControlDetails(
440 IN LPMIXERCONTROLDETAILS MixDetails
,
443 if (MMixerGetControlDetails(&MixerContext
, hMixer
, MixerId
, Flags
, MixDetails
) == MM_STATUS_SUCCESS
)
444 return MMSYSERR_NOERROR
;
446 return MMSYSERR_ERROR
;
450 WdmAudGetWaveOutCapabilities(
452 LPWAVEOUTCAPSW Capabilities
)
454 if (MMixerWaveOutCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
455 return MMSYSERR_NOERROR
;
457 return MMSYSERR_ERROR
;
462 WdmAudGetWaveInCapabilities(
464 LPWAVEINCAPSW Capabilities
)
466 if (MMixerWaveInCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
467 return MMSYSERR_NOERROR
;
469 return MMSYSERR_ERROR
;
473 WdmAudSetWaveDeviceFormatByMMixer(
474 IN PSOUND_DEVICE_INSTANCE Instance
,
476 IN PWAVEFORMATEX WaveFormat
,
477 IN DWORD WaveFormatSize
)
479 MMDEVICE_TYPE DeviceType
;
480 PSOUND_DEVICE SoundDevice
;
484 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
486 if ( ! MMSUCCESS(Result
) )
488 return TranslateInternalMmResult(Result
);
491 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
492 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
494 bWaveIn
= (DeviceType
== WAVE_IN_DEVICE_TYPE
? TRUE
: FALSE
);
496 if (MMixerOpenWave(&MixerContext
, DeviceId
, bWaveIn
, WaveFormat
, NULL
, NULL
, &Instance
->Handle
) == MM_STATUS_SUCCESS
)
498 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
500 MMixerSetWaveStatus(&MixerContext
, Instance
->Handle
, KSSTATE_ACQUIRE
);
501 MMixerSetWaveStatus(&MixerContext
, Instance
->Handle
, KSSTATE_PAUSE
);
502 MMixerSetWaveStatus(&MixerContext
, Instance
->Handle
, KSSTATE_RUN
);
504 return MMSYSERR_NOERROR
;
506 return MMSYSERR_ERROR
;
511 WdmAudGetCapabilitiesByMMixer(
512 IN PSOUND_DEVICE SoundDevice
,
514 OUT PVOID Capabilities
,
515 IN DWORD CapabilitiesSize
)
517 MMDEVICE_TYPE DeviceType
;
520 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
521 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
523 if (DeviceType
== MIXER_DEVICE_TYPE
)
525 return WdmAudGetMixerCapabilties(DeviceId
, (LPMIXERCAPSW
)Capabilities
);
527 else if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
529 return WdmAudGetWaveOutCapabilities(DeviceId
, (LPWAVEOUTCAPSW
)Capabilities
);
531 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
533 return WdmAudGetWaveInCapabilities(DeviceId
, (LPWAVEINCAPSW
)Capabilities
);
538 return MMSYSERR_ERROR
;
543 WdmAudOpenSoundDeviceByMMixer(
544 IN
struct _SOUND_DEVICE
* SoundDevice
,
547 if (WdmAudInitUserModeMixer())
548 return MMSYSERR_NOERROR
;
550 return MMSYSERR_ERROR
;
554 WdmAudCloseSoundDeviceByMMixer(
555 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
558 MMDEVICE_TYPE DeviceType
;
559 PSOUND_DEVICE SoundDevice
;
562 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
564 if ( ! MMSUCCESS(Result
) )
566 return TranslateInternalMmResult(Result
);
569 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
570 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
572 if (DeviceType
== MIXER_DEVICE_TYPE
)
575 return MMSYSERR_NOERROR
;
577 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
579 /* make sure the pin is stopped */
580 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
581 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
582 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_STOP
);
585 return MMSYSERR_NOERROR
;
588 /* midi is not supported */
589 return MMSYSERR_ERROR
;
593 WdmAudGetNumWdmDevsByMMixer(
594 IN MMDEVICE_TYPE DeviceType
,
595 OUT DWORD
* DeviceCount
)
599 case MIXER_DEVICE_TYPE
:
600 *DeviceCount
= MMixerGetCount(&MixerContext
);
602 case WAVE_OUT_DEVICE_TYPE
:
603 *DeviceCount
= MMixerGetWaveOutCount(&MixerContext
);
605 case WAVE_IN_DEVICE_TYPE
:
606 *DeviceCount
= MMixerGetWaveInCount(&MixerContext
);
611 return MMSYSERR_NOERROR
;
615 WdmAudQueryMixerInfoByMMixer(
616 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
622 LPMIXERLINEW MixLine
;
623 LPMIXERLINECONTROLSW MixControls
;
624 LPMIXERCONTROLDETAILS MixDetails
;
625 HANDLE hMixer
= NULL
;
627 MixLine
= (LPMIXERLINEW
)Parameter
;
628 MixControls
= (LPMIXERLINECONTROLSW
)Parameter
;
629 MixDetails
= (LPMIXERCONTROLDETAILS
)Parameter
;
631 /* FIXME param checks */
633 if (SoundDeviceInstance
)
635 hMixer
= SoundDeviceInstance
->Handle
;
640 case MXDM_GETLINEINFO
:
641 return WdmAudGetLineInfo(hMixer
, MixerId
, MixLine
, Flags
);
642 case MXDM_GETLINECONTROLS
:
643 return WdmAudGetLineControls(hMixer
, MixerId
, MixControls
, Flags
);
644 case MXDM_SETCONTROLDETAILS
:
645 return WdmAudSetControlDetails(hMixer
, MixerId
, MixDetails
, Flags
);
646 case MXDM_GETCONTROLDETAILS
:
647 return WdmAudGetControlDetails(hMixer
, MixerId
, MixDetails
, Flags
);
649 DPRINT1("MixerId %lu, uMsg %lu, Parameter %p, Flags %lu\n", MixerId
, uMsg
, Parameter
, Flags
);
651 return MMSYSERR_NOTSUPPORTED
;
656 WdmAudGetDeviceInterfaceStringByMMixer(
657 IN MMDEVICE_TYPE DeviceType
,
660 IN DWORD InterfaceLength
,
661 OUT DWORD
* InterfaceSize
)
664 return MMSYSERR_NOTSUPPORTED
;
668 WdmAudSetMixerDeviceFormatByMMixer(
669 IN PSOUND_DEVICE_INSTANCE Instance
,
671 IN PWAVEFORMATEX WaveFormat
,
672 IN DWORD WaveFormatSize
)
674 Instance
->hNotifyEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
675 if ( ! Instance
->hNotifyEvent
)
676 return MMSYSERR_NOMEM
;
678 if (MMixerOpen(&MixerContext
, DeviceId
, Instance
->hNotifyEvent
, NULL
/* FIXME */, &Instance
->Handle
) == MM_STATUS_SUCCESS
)
679 return MMSYSERR_NOERROR
;
681 return MMSYSERR_BADDEVICEID
;
685 WdmAudSetWaveStateByMMixer(
686 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
689 MMDEVICE_TYPE DeviceType
;
690 PSOUND_DEVICE SoundDevice
;
693 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
694 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
697 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
698 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
700 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
704 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
705 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
706 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_RUN
);
710 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
711 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
712 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_STOP
);
715 else if (DeviceType
== MIDI_IN_DEVICE_TYPE
|| DeviceType
== MIDI_OUT_DEVICE_TYPE
)
719 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
720 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
721 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_RUN
);
725 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
726 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
727 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_STOP
);
731 return MMSYSERR_NOERROR
;
735 WdmAudResetStreamByMMixer(
736 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
737 IN MMDEVICE_TYPE DeviceType
,
738 IN BOOLEAN bStartReset
)
741 return MMSYSERR_NOTSUPPORTED
;
745 WdmAudGetWavePositionByMMixer(
746 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
750 return MMSYSERR_NOTSUPPORTED
;
760 LPIO_PACKET Packet
= (LPIO_PACKET
)lpParameter
;
762 Result
= SyncOverlappedDeviceIoControl(Packet
->hDevice
,
763 IOCTL_KS_WRITE_STREAM
, //FIXME IOCTL_KS_READ_STREAM
767 sizeof(KSSTREAM_HEADER
),
771 * don't call completion routine directly
774 Packet
->CompletionRoutine(ERROR_SUCCESS
, Packet
->Header
.DataUsed
, (LPOVERLAPPED
)Packet
->Overlap
);
776 HeapFree(GetProcessHeap(), 0, Packet
);
787 WdmAudCommitWaveBufferByMMixer(
788 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
791 IN PSOUND_OVERLAPPED Overlap
,
792 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
)
794 PSOUND_DEVICE SoundDevice
;
795 MMDEVICE_TYPE DeviceType
;
800 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
802 if ( ! MMSUCCESS(Result
) )
804 return TranslateInternalMmResult(Result
);
807 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
808 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
810 Packet
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IO_PACKET
));
814 return MMSYSERR_NOMEM
;
817 /* setup stream packet */
818 Packet
->Header
.Size
= sizeof(KSSTREAM_HEADER
);
819 Packet
->Header
.PresentationTime
.Numerator
= 1;
820 Packet
->Header
.PresentationTime
.Denominator
= 1;
821 Packet
->Header
.Data
= OffsetPtr
;
822 Packet
->Header
.FrameExtent
= Length
;
823 Packet
->hDevice
= SoundDeviceInstance
->Handle
;
824 Packet
->Overlap
= Overlap
;
825 Packet
->CompletionRoutine
= CompletionRoutine
;
827 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
829 Packet
->Header
.DataUsed
= Length
;
832 hThread
= CreateThread(NULL
, 0, IoStreamingThread
, (LPVOID
)Packet
, 0, NULL
);
836 return MMSYSERR_ERROR
;
839 CloseHandle(hThread
);
841 return MMSYSERR_NOERROR
;