2 * PROJECT: ReactOS Sound System "MME Buddy" Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: include/reactos/libs/sound/mmebuddy.h
6 * PURPOSE: Header for the "MME Buddy" helper library (located in
7 * lib/drivers/sound/mmebuddy)
9 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
11 * HISTORY: 4 July 2008 - Created
12 * 31 Dec 2008 - Split off NT4-specific code into a separate library
14 * NOTES: MME Buddy was the best name I could come up with...
15 * The structures etc. here should be treated as internal to the
16 * library so should not be directly accessed elsewhere. Perhaps they
17 * can be moved to an internal header?
20 #ifndef ROS_AUDIO_MMEBUDDY_H
21 #define ROS_AUDIO_MMEBUDDY_H
29 WCHAR dbg_popup_msg[1024], dbg_popup_title[256]; \
30 wsprintf(dbg_popup_title, L"%hS(%d)", __FILE__, __LINE__); \
31 wsprintf(dbg_popup_msg, __VA_ARGS__); \
32 MessageBox(0, dbg_popup_msg, dbg_popup_title, MB_OK | MB_TASKMODAL); \
36 #define SND_ERR(...) \
38 WCHAR dbg_popup_msg[1024]; \
39 wsprintf(dbg_popup_msg, __VA_ARGS__); \
40 OutputDebugString(dbg_popup_msg); \
42 #define SND_WARN(...) \
44 WCHAR dbg_popup_msg[1024]; \
45 wsprintf(dbg_popup_msg, __VA_ARGS__); \
46 OutputDebugString(dbg_popup_msg); \
48 #define SND_TRACE(...) \
50 WCHAR dbg_popup_msg[1024]; \
51 wsprintf(dbg_popup_msg, __VA_ARGS__); \
52 OutputDebugString(dbg_popup_msg); \
55 #define SND_ASSERT(condition) \
57 if ( ! ( condition ) ) \
59 SND_ERR(L"ASSERT FAILED: %hS\n", #condition); \
60 POPUP(L"ASSERT FAILED: %hS\n", #condition); \
65 #define DUMP_WAVEHDR_QUEUE(sound_device_instance) \
67 PWAVEHDR CurrDumpHdr = sound_device_instance->HeadWaveHeader; \
68 SND_TRACE(L"-- Current wave header list --\n"); \
69 while ( CurrDumpHdr ) \
71 SND_TRACE(L"%x | %d bytes | flags: %x\n", CurrDumpHdr->lpData, \
72 CurrDumpHdr->dwBufferLength, \
73 CurrDumpHdr->dwFlags); \
74 CurrDumpHdr = CurrDumpHdr->lpNext; \
79 #define SND_ERR(...) do {} while ( 0 )
80 #define SND_WARN(...) do {} while ( 0 )
81 #define SND_TRACE(...) do {} while ( 0 )
82 #define SND_ASSERT(condition) do {} while ( 0 )
86 Some memory allocation helper macros
89 #define AllocateStruct(thing) \
90 (thing*) AllocateMemory(sizeof(thing))
92 #define StringLengthToBytes(chartype, string_length) \
93 ( ( string_length + 1 ) * sizeof(chartype) )
95 #define AllocateWideString(string_length) \
96 (PWSTR) AllocateMemory(StringLengthToBytes(WCHAR, string_length))
98 #define ZeroWideString(string) \
99 ZeroMemory(string, StringLengthToBytes(WCHAR, wcslen(string)))
101 #define CopyWideString(dest, source) \
102 CopyMemory(dest, source, StringLengthToBytes(WCHAR, wcslen(source)))
106 Helps find the minimum/maximum of two values
109 #define MinimumOf(value_a, value_b) \
110 ( value_a < value_b ? value_a : value_b )
112 #define MaximumOf(value_a, value_b) \
113 ( value_a > value_b ? value_a : value_b )
117 Convert a device type into a zero-based array index
120 #define SOUND_DEVICE_TYPE_TO_INDEX(x) \
121 ( x - MIN_SOUND_DEVICE_TYPE )
123 #define INDEX_TO_SOUND_DEVICE_TYPE(x) \
124 ( x + MIN_SOUND_DEVICE_TYPE )
131 #define IsValidSoundDeviceType IS_VALID_SOUND_DEVICE_TYPE
133 #define VALIDATE_MMSYS_PARAMETER(parameter_condition) \
135 if ( ! (parameter_condition) ) \
137 SND_ERR(L"FAILED parameter check: %hS\n", #parameter_condition); \
138 return MMSYSERR_INVALPARAM; \
142 #define MMSUCCESS(result) \
143 ( result == MMSYSERR_NOERROR )
150 typedef UCHAR MMDEVICE_TYPE
, *PMMDEVICE_TYPE
;
151 struct _SOUND_DEVICE
;
152 struct _SOUND_DEVICE_INSTANCE
;
155 #define DEFINE_GETCAPS_FUNCTYPE(func_typename, caps_type) \
156 typedef MMRESULT (*func_typename)( \
157 IN struct _SOUND_DEVICE* SoundDevice, \
158 OUT caps_type Capabilities, \
159 IN DWORD CapabilitiesSize);
161 /* This one is for those of us who don't care */
162 DEFINE_GETCAPS_FUNCTYPE(MMGETCAPS_FUNC
, PVOID
);
164 /* These are for those of us that do */
165 DEFINE_GETCAPS_FUNCTYPE(MMGETWAVEOUTCAPS_FUNC
, LPWAVEOUTCAPS
);
166 DEFINE_GETCAPS_FUNCTYPE(MMGETWAVEINCAPS_FUNC
, LPWAVEINCAPS
);
167 DEFINE_GETCAPS_FUNCTYPE(MMGETMIDIOUTCAPS_FUNC
, LPMIDIOUTCAPS
);
168 DEFINE_GETCAPS_FUNCTYPE(MMGETMIDIINCAPS_FUNC
, LPMIDIINCAPS
);
170 struct _SOUND_DEVICE
;
171 struct _SOUND_DEVICE_INSTANCE
;
175 By extending the OVERLAPPED structure, it becomes possible to provide the
176 I/O completion routines with additional information.
179 typedef struct _SOUND_OVERLAPPED
182 struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
;
184 } SOUND_OVERLAPPED
, *PSOUND_OVERLAPPED
;
186 typedef MMRESULT (*WAVE_COMMIT_FUNC
)(
187 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
190 IN PSOUND_OVERLAPPED Overlap
,
191 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
);
195 typedef MMRESULT (*MMWAVEQUERYFORMATSUPPORT_FUNC
)(
196 IN
struct _SOUND_DEVICE
* Device
,
197 IN PWAVEFORMATEX WaveFormat
,
198 IN DWORD WaveFormatSize
);
200 typedef MMRESULT (*MMWAVESETFORMAT_FUNC
)(
201 IN
struct _SOUND_DEVICE_INSTANCE
* Instance
,
202 IN PWAVEFORMATEX WaveFormat
,
203 IN DWORD WaveFormatSize
);
205 typedef MMRESULT (*MMOPEN_FUNC
)(
206 IN
struct _SOUND_DEVICE
* SoundDevice
,
209 typedef MMRESULT (*MMCLOSE_FUNC
)(
210 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
211 IN PVOID Handle
); /* not sure about this */
213 typedef MMRESULT (*MMWAVEHEADER_FUNC
)(
214 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
215 IN PWAVEHDR WaveHeader
);
217 typedef MMRESULT (*MMBUFFER_FUNC
)(
218 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
222 typedef struct _MMFUNCTION_TABLE
226 MMGETCAPS_FUNC GetCapabilities
;
227 MMGETWAVEOUTCAPS_FUNC GetWaveOutCapabilities
;
228 MMGETWAVEINCAPS_FUNC GetWaveInCapabilities
;
229 MMGETMIDIOUTCAPS_FUNC GetMidiOutCapabilities
;
230 MMGETMIDIINCAPS_FUNC GetMidiInCapabilities
;
236 MMWAVEQUERYFORMATSUPPORT_FUNC QueryWaveFormatSupport
;
237 MMWAVESETFORMAT_FUNC SetWaveFormat
;
239 WAVE_COMMIT_FUNC CommitWaveBuffer
;
242 //MMWAVEHEADER_FUNC PrepareWaveHeader;
243 //MMWAVEHEADER_FUNC UnprepareWaveHeader;
244 //MMWAVEHEADER_FUNC WriteWaveHeader;
246 //MMWAVEHEADER_FUNC SubmitWaveHeaderToDevice;
247 //MMBUFFER_FUNC CompleteBuffer;
248 } MMFUNCTION_TABLE
, *PMMFUNCTION_TABLE
;
252 typedef MMRESULT (*SOUND_THREAD_REQUEST_HANDLER
)(
253 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
256 typedef struct _SOUND_THREAD
270 SOUND_THREAD_REQUEST_HANDLER Handler
;
271 struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
;
275 } SOUND_THREAD
, *PSOUND_THREAD
;
277 typedef struct _SOUND_DEVICE
279 struct _SOUND_DEVICE
* Next
;
280 struct _SOUND_DEVICE_INSTANCE
* HeadInstance
;
281 struct _SOUND_DEVICE_INSTANCE
* TailInstance
;
283 PVOID Identifier
; /* Path for NT4 drivers */
285 MMFUNCTION_TABLE FunctionTable
;
286 } SOUND_DEVICE
, *PSOUND_DEVICE
;
288 typedef struct _SOUND_DEVICE_INSTANCE
290 struct _SOUND_DEVICE_INSTANCE
* Next
;
291 struct _SOUND_DEVICE
* Device
;
293 struct _SOUND_THREAD
* Thread
;
295 /* Stuff generously donated to us from WinMM */
300 DWORD ClientCallback
;
301 DWORD ClientCallbackInstanceData
;
304 /* DO NOT TOUCH THESE OUTSIDE OF THE SOUND THREAD */
308 PWAVEHDR HeadWaveHeader
;
313 PWAVEHDR TailWaveHeader
;
316 PWAVEHDR WaveLoopStart
;
317 PWAVEHDR CurrentWaveHeader
;
318 DWORD OutstandingBuffers
;
319 } SOUND_DEVICE_INSTANCE
, *PSOUND_DEVICE_INSTANCE
;
321 /* This lives in WAVEHDR.reserved */
322 typedef struct _WAVEHDR_EXTENSION
324 DWORD BytesCommitted
;
325 DWORD BytesCompleted
;
326 } WAVEHDR_EXTENSION
, *PWAVEHDR_EXTENSION
;
334 InitEntrypointMutexes();
337 CleanupEntrypointMutexes();
340 AcquireEntrypointMutex(
341 IN MMDEVICE_TYPE DeviceType
);
344 ReleaseEntrypointMutex(
345 IN MMDEVICE_TYPE DeviceType
);
354 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
359 MmeGetSoundDeviceCapabilities(
360 IN MMDEVICE_TYPE DeviceType
,
362 IN PVOID Capabilities
,
363 IN DWORD CapabilitiesSize
);
367 IN MMDEVICE_TYPE DeviceType
,
369 IN LPWAVEOPENDESC OpenParameters
,
371 OUT DWORD
* PrivateHandle
);
375 IN DWORD PrivateHandle
);
377 #define MmePrepareWaveHeader(private_handle, header) \
378 PrepareWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header)
380 #define MmeUnprepareWaveHeader(private_handle, header) \
381 UnprepareWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header)
383 #define MmeWriteWaveHeader(private_handle, header) \
384 WriteWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header)
392 GetSoundDeviceCapabilities(
393 IN PSOUND_DEVICE SoundDevice
,
394 OUT PVOID Capabilities
,
395 IN DWORD CapabilitiesSize
);
404 IN MMDEVICE_TYPE DeviceType
);
408 IN PSOUND_DEVICE SoundDevice
);
412 IN MMDEVICE_TYPE DeviceType
,
413 IN PVOID Identifier OPTIONAL
,
414 OUT PSOUND_DEVICE
* SoundDevice OPTIONAL
);
418 IN MMDEVICE_TYPE DeviceType
,
419 IN PSOUND_DEVICE SoundDevice
);
423 IN MMDEVICE_TYPE DeviceType
);
426 UnlistAllSoundDevices();
430 IN MMDEVICE_TYPE DeviceType
,
431 IN DWORD DeviceIndex
,
432 OUT PSOUND_DEVICE
* Device
);
435 GetSoundDeviceIdentifier(
436 IN PSOUND_DEVICE SoundDevice
,
437 OUT PVOID
* Identifier
);
441 IN PSOUND_DEVICE SoundDevice
,
442 OUT PMMDEVICE_TYPE DeviceType
);
450 SetSoundDeviceFunctionTable(
451 IN PSOUND_DEVICE SoundDevice
,
452 IN PMMFUNCTION_TABLE FunctionTable
);
455 GetSoundDeviceFunctionTable(
456 IN PSOUND_DEVICE SoundDevice
,
457 OUT PMMFUNCTION_TABLE
* FunctionTable
);
465 IsValidSoundDeviceInstance(
466 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
);
469 CreateSoundDeviceInstance(
470 IN PSOUND_DEVICE SoundDevice
,
471 OUT PSOUND_DEVICE_INSTANCE
* SoundDeviceInstance
);
474 DestroySoundDeviceInstance(
475 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
);
478 DestroyAllSoundDeviceInstances(
479 IN PSOUND_DEVICE SoundDevice
);
482 GetSoundDeviceFromInstance(
483 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
484 OUT PSOUND_DEVICE
* SoundDevice
);
487 GetSoundDeviceInstanceHandle(
488 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
492 SetSoundDeviceInstanceMmeData(
493 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
495 IN DWORD ClientCallback
,
496 IN DWORD ClientCallbackData
,
506 OUT PSOUND_THREAD
* Thread
);
510 IN PSOUND_THREAD Thread
);
514 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
515 IN SOUND_THREAD_REQUEST_HANDLER RequestHandler
,
516 IN PVOID Parameter OPTIONAL
);
532 GetMemoryAllocationCount();
539 Win32ErrorToMmResult(
543 TranslateInternalMmResult(
552 QueryWaveDeviceFormatSupport(
553 IN PSOUND_DEVICE SoundDevice
,
554 IN LPWAVEFORMATEX Format
,
555 IN DWORD FormatSize
);
559 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
560 IN LPWAVEFORMATEX Format
,
561 IN DWORD FormatSize
);
570 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
575 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
580 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
585 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
590 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
600 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
);
604 IN DWORD dwErrorCode
,
605 IN DWORD dwNumberOfBytesTransferred
,
606 IN LPOVERLAPPED lpOverlapped
);
609 CommitWaveHeaderToKernelDevice(
610 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
612 IN WAVE_COMMIT_FUNC CommitFunction
);
615 WriteFileEx_Committer(
616 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
619 IN PSOUND_OVERLAPPED Overlap
,
620 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
);
628 #define QueryDevice(h, ctl, o, o_size, xfer, ovl) \
629 Win32ErrorToMmResult( \
630 DeviceIoControl(h, ctl, NULL, 0, o, o_size, xfer, ovl) != 0 \
631 ? ERROR_SUCCESS : GetLastError() \
634 #define ControlDevice(h, ctl, i, i_size, xfer, ovl) \
635 Win32ErrorToMmResult( \
636 DeviceIoControl(h, ctl, i, i_size, NULL, 0, xfer, ovl) != 0 \
637 ? ERROR_SUCCESS : GetLastError() \
640 #define QuerySoundDevice(sd, ctl, o, o_size, xfer) \
641 SoundDeviceIoControl(sd, ctl, NULL, 0, o, o_size, xfer)
643 #define ControlSoundDevice(sd, ctl, i, i_size, xfer) \
644 SoundDeviceIoControl(sd, ctl, i, i_size, NULL, 0, xfer)
648 OpenKernelSoundDeviceByName(
654 OpenKernelSoundDevice(
655 IN PSOUND_DEVICE SoundDevice
,
660 CloseKernelSoundDevice(
664 SyncOverlappedDeviceIoControl(
665 IN HANDLE SoundDeviceInstance
,
666 IN DWORD IoControlCode
,
668 IN DWORD InBufferSize
,
669 OUT LPVOID OutBuffer
,
670 IN DWORD OutBufferSize
,
671 OUT LPDWORD BytesTransferred OPTIONAL
);
676 typedef UCHAR MMDEVICE_TYPE
, *PMMDEVICE_TYPE
;
678 struct _SOUND_DEVICE
;
679 struct _SOUND_DEVICE_INSTANCE
;
683 Rather than pass caps structures around as a PVOID, this can be
687 typedef union _UNIVERSAL_CAPS
693 } UNIVERSAL_CAPS
, *PUNIVERSAL_CAPS
;
697 /* New sound thread code */
699 typedef MMRESULT (*SOUND_THREAD_REQUEST_HANDLER
)(
700 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
701 IN OPTIONAL PVOID Parameter
);
703 typedef struct _SOUND_THREAD_REQUEST
705 /* The sound device instance this request relates to */
706 struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
;
707 /* What function to call */
708 SOUND_THREAD_REQUEST_HANDLER RequestHandler
;
709 /* Caller-defined parameter */
711 /* This will contain the return code of the request function */
712 MMRESULT ReturnValue
;
713 } SOUND_THREAD_REQUEST
, *PSOUND_THREAD_REQUEST
;
715 typedef VOID (*SOUND_THREAD_IO_COMPLETION_HANDLER
)(
716 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
717 IN PVOID Parameter OPTIONAL
,
718 IN DWORD BytesWritten
);
720 typedef struct _SOUND_THREAD_COMPLETED_IO
722 struct _SOUND_THREAD_COMPLETED_IO
* Previous
;
723 struct _SOUND_THREAD_COMPLETED_IO
* Next
;
725 struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
;
726 SOUND_THREAD_IO_COMPLETION_HANDLER CompletionHandler
;
728 DWORD BytesTransferred
;
729 } SOUND_THREAD_COMPLETED_IO
, *PSOUND_THREAD_COMPLETED_IO
;
731 typedef struct _SOUND_THREAD_OVERLAPPED
735 /* Pointer to structure to fill with completion data */
736 PSOUND_THREAD_COMPLETED_IO CompletionData
;
737 } SOUND_THREAD_OVERLAPPED
, *PSOUND_THREAD_OVERLAPPED
;
740 Audio device function table
743 typedef MMRESULT (*MMCREATEINSTANCE_FUNC
)(
744 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
);
746 typedef VOID (*MMDESTROYINSTANCE_FUNC
)(
747 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
);
749 typedef MMRESULT (*MMGETCAPS_FUNC
)(
750 IN
struct _SOUND_DEVICE
* Device
,
751 OUT PUNIVERSAL_CAPS Capabilities
);
753 typedef MMRESULT (*MMWAVEQUERYFORMAT_FUNC
)(
754 IN
struct _SOUND_DEVICE
* Device
,
755 IN PWAVEFORMATEX WaveFormat
,
756 IN DWORD WaveFormatSize
);
758 typedef MMRESULT (*MMWAVESETFORMAT_FUNC
)(
759 IN
struct _SOUND_DEVICE_INSTANCE
* Instance
,
760 IN PWAVEFORMATEX WaveFormat
,
761 IN DWORD WaveFormatSize
);
763 typedef MMRESULT (*MMWAVEQUEUEBUFFER_FUNC
)(
764 IN
struct _SOUND_DEVICE_INSTANCE
* Instance
,
765 IN PWAVEHDR WaveHeader
);
767 typedef MMRESULT (*MMGETWAVESTATE_FUNC
)(
768 IN
struct _SOUND_DEVICE_INSTANCE
* Instance
,
771 typedef MMRESULT (*MMSETWAVESTATE_FUNC
)(
772 IN
struct _SOUND_DEVICE_INSTANCE
* Instance
);
774 typedef struct _MMFUNCTION_TABLE
776 MMCREATEINSTANCE_FUNC Constructor
;
777 MMDESTROYINSTANCE_FUNC Destructor
;
778 MMGETCAPS_FUNC GetCapabilities
;
780 MMWAVEQUERYFORMAT_FUNC QueryWaveFormat
;
781 MMWAVESETFORMAT_FUNC SetWaveFormat
;
782 MMWAVEQUEUEBUFFER_FUNC QueueWaveBuffer
;
784 MMGETWAVESTATE_FUNC GetWaveDeviceState
;
785 MMSETWAVESTATE_FUNC PauseWaveDevice
;
786 MMSETWAVESTATE_FUNC RestartWaveDevice
;
787 MMSETWAVESTATE_FUNC ResetWaveDevice
;
788 MMSETWAVESTATE_FUNC BreakWaveDeviceLoop
;
789 } MMFUNCTION_TABLE
, *PMMFUNCTION_TABLE
;
793 Represents an audio device
796 #define SOUND_DEVICE_TAG "SndD"
798 typedef struct _SOUND_DEVICE
800 struct _SOUND_DEVICE
* Next
;
801 struct _SOUND_DEVICE_INSTANCE
* FirstInstance
;
804 MMFUNCTION_TABLE Functions
;
805 } SOUND_DEVICE
, *PSOUND_DEVICE
;
809 Represents an individual instance of an audio device
812 #define WAVE_STREAM_INFO_TAG "WavS"
814 typedef struct _WAVE_STREAM_INFO
816 /* Buffer queue head and tail */
817 PWAVEHDR BufferQueueHead
;
818 PWAVEHDR BufferQueueTail
;
819 /* The buffer currently being processed */
820 PWAVEHDR CurrentBuffer
;
821 /* How far into the current buffer we've gone */
823 /* How many I/O operations have been submitted */
824 DWORD BuffersOutstanding
;
827 DWORD LoopsRemaining
;
828 } WAVE_STREAM_INFO
, *PWAVE_STREAM_INFO
;
831 #define SOUND_DEVICE_INSTANCE_TAG "SndI"
833 typedef struct _SOUND_DEVICE_INSTANCE
835 struct _SOUND_DEVICE_INSTANCE
* Next
;
836 PSOUND_DEVICE Device
;
838 /* The currently opened handle to the device */
840 /* PSOUND_THREAD Thread;*/
843 /* Device-specific parameters */
846 WAVE_STREAM_INFO Wave
;
848 } SOUND_DEVICE_INSTANCE
, *PSOUND_DEVICE_INSTANCE
;