Closing of wave output devices is functional and terminates the sound thread
[reactos.git] / reactos / include / reactos / libs / sound / mmebuddy.h
1 /*
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
5 *
6 * PURPOSE: Header for the "MME Buddy" helper library (located in
7 * lib/drivers/sound/mmebuddy)
8 *
9 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
10 *
11 * HISTORY: 4 July 2008 - Created
12 * 31 Dec 2008 - Split off NT4-specific code into a separate library
13 *
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?
18 */
19
20 #ifndef ROS_AUDIO_MMEBUDDY_H
21 #define ROS_AUDIO_MMEBUDDY_H
22
23 /*
24 Hacky debug macro
25 */
26
27 #define POPUP(...) \
28 { \
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); \
33 }
34
35 #ifndef NDEBUG
36 #define SND_ERR(...) \
37 { \
38 WCHAR dbg_popup_msg[1024]; \
39 wsprintf(dbg_popup_msg, __VA_ARGS__); \
40 OutputDebugString(dbg_popup_msg); \
41 }
42 #define SND_WARN(...) \
43 { \
44 WCHAR dbg_popup_msg[1024]; \
45 wsprintf(dbg_popup_msg, __VA_ARGS__); \
46 OutputDebugString(dbg_popup_msg); \
47 }
48 #define SND_TRACE(...) \
49 { \
50 WCHAR dbg_popup_msg[1024]; \
51 wsprintf(dbg_popup_msg, __VA_ARGS__); \
52 OutputDebugString(dbg_popup_msg); \
53 }
54
55 #define SND_ASSERT(condition) \
56 { \
57 if ( ! ( condition ) ) \
58 { \
59 SND_ERR(L"ASSERT FAILED: %hS\n", #condition); \
60 POPUP(L"ASSERT FAILED: %hS\n", #condition); \
61 ExitProcess(1); \
62 } \
63 }
64
65 #define DUMP_WAVEHDR_QUEUE(sound_device_instance) \
66 { \
67 PWAVEHDR CurrDumpHdr = sound_device_instance->HeadWaveHeader; \
68 SND_TRACE(L"-- Current wave header list --\n"); \
69 while ( CurrDumpHdr ) \
70 { \
71 SND_TRACE(L"%x | %d bytes | flags: %x\n", CurrDumpHdr->lpData, \
72 CurrDumpHdr->dwBufferLength, \
73 CurrDumpHdr->dwFlags); \
74 CurrDumpHdr = CurrDumpHdr->lpNext; \
75 } \
76 }
77
78 #else
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 )
83 #endif
84
85 /*
86 Some memory allocation helper macros
87 */
88
89 #define AllocateStruct(thing) \
90 (thing*) AllocateMemory(sizeof(thing))
91
92 #define StringLengthToBytes(chartype, string_length) \
93 ( ( string_length + 1 ) * sizeof(chartype) )
94
95 #define AllocateWideString(string_length) \
96 (PWSTR) AllocateMemory(StringLengthToBytes(WCHAR, string_length))
97
98 #define ZeroWideString(string) \
99 ZeroMemory(string, StringLengthToBytes(WCHAR, wcslen(string)))
100
101 #define CopyWideString(dest, source) \
102 CopyMemory(dest, source, StringLengthToBytes(WCHAR, wcslen(source)))
103
104
105 /*
106 Helps find the minimum/maximum of two values
107 */
108
109 #define MinimumOf(value_a, value_b) \
110 ( value_a < value_b ? value_a : value_b )
111
112 #define MaximumOf(value_a, value_b) \
113 ( value_a > value_b ? value_a : value_b )
114
115
116 /*
117 Convert a device type into a zero-based array index
118 */
119
120 #define SOUND_DEVICE_TYPE_TO_INDEX(x) \
121 ( x - MIN_SOUND_DEVICE_TYPE )
122
123 #define INDEX_TO_SOUND_DEVICE_TYPE(x) \
124 ( x + MIN_SOUND_DEVICE_TYPE )
125
126
127 /*
128 Validation
129 */
130
131 #define IsValidSoundDeviceType IS_VALID_SOUND_DEVICE_TYPE
132
133 #define VALIDATE_MMSYS_PARAMETER(parameter_condition) \
134 { \
135 if ( ! (parameter_condition) ) \
136 { \
137 SND_ERR(L"FAILED parameter check: %hS\n", #parameter_condition); \
138 return MMSYSERR_INVALPARAM; \
139 } \
140 }
141
142 #define MMSUCCESS(result) \
143 ( result == MMSYSERR_NOERROR )
144
145
146 /*
147 Types and Structures
148 */
149
150 typedef UCHAR MMDEVICE_TYPE, *PMMDEVICE_TYPE;
151 struct _SOUND_DEVICE;
152 struct _SOUND_DEVICE_INSTANCE;
153
154
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);
160
161 /* This one is for those of us who don't care */
162 DEFINE_GETCAPS_FUNCTYPE(MMGETCAPS_FUNC, PVOID);
163
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 );
169
170 struct _SOUND_DEVICE;
171 struct _SOUND_DEVICE_INSTANCE;
172
173
174 /*
175 By extending the OVERLAPPED structure, it becomes possible to provide the
176 I/O completion routines with additional information.
177 */
178
179 typedef struct _SOUND_OVERLAPPED
180 {
181 OVERLAPPED Standard;
182 struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance;
183 PWAVEHDR Header;
184 BOOL PerformCompletion;
185 } SOUND_OVERLAPPED, *PSOUND_OVERLAPPED;
186
187 typedef MMRESULT (*WAVE_COMMIT_FUNC)(
188 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
189 IN PVOID OffsetPtr,
190 IN DWORD Bytes,
191 IN PSOUND_OVERLAPPED Overlap,
192 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine);
193
194
195
196 typedef MMRESULT (*MMWAVEQUERYFORMATSUPPORT_FUNC)(
197 IN struct _SOUND_DEVICE* Device,
198 IN PWAVEFORMATEX WaveFormat,
199 IN DWORD WaveFormatSize);
200
201 typedef MMRESULT (*MMWAVESETFORMAT_FUNC)(
202 IN struct _SOUND_DEVICE_INSTANCE* Instance,
203 IN PWAVEFORMATEX WaveFormat,
204 IN DWORD WaveFormatSize);
205
206 typedef MMRESULT (*MMOPEN_FUNC)(
207 IN struct _SOUND_DEVICE* SoundDevice,
208 OUT PVOID* Handle);
209
210 typedef MMRESULT (*MMCLOSE_FUNC)(
211 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
212 IN PVOID Handle); /* not sure about this */
213
214 typedef MMRESULT (*MMWAVEHEADER_FUNC)(
215 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
216 IN PWAVEHDR WaveHeader);
217
218 typedef MMRESULT (*MMBUFFER_FUNC)(
219 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
220 IN PVOID Buffer,
221 IN DWORD Length);
222
223 typedef struct _MMFUNCTION_TABLE
224 {
225 union
226 {
227 MMGETCAPS_FUNC GetCapabilities;
228 MMGETWAVEOUTCAPS_FUNC GetWaveOutCapabilities;
229 MMGETWAVEINCAPS_FUNC GetWaveInCapabilities;
230 MMGETMIDIOUTCAPS_FUNC GetMidiOutCapabilities;
231 MMGETMIDIINCAPS_FUNC GetMidiInCapabilities;
232 };
233
234 MMOPEN_FUNC Open;
235 MMCLOSE_FUNC Close;
236
237 MMWAVEQUERYFORMATSUPPORT_FUNC QueryWaveFormatSupport;
238 MMWAVESETFORMAT_FUNC SetWaveFormat;
239
240 WAVE_COMMIT_FUNC CommitWaveBuffer;
241
242 // Redundant
243 //MMWAVEHEADER_FUNC PrepareWaveHeader;
244 //MMWAVEHEADER_FUNC UnprepareWaveHeader;
245 //MMWAVEHEADER_FUNC WriteWaveHeader;
246
247 //MMWAVEHEADER_FUNC SubmitWaveHeaderToDevice;
248 //MMBUFFER_FUNC CompleteBuffer;
249 } MMFUNCTION_TABLE, *PMMFUNCTION_TABLE;
250
251
252
253 typedef MMRESULT (*SOUND_THREAD_REQUEST_HANDLER)(
254 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
255 IN PVOID Parameter);
256
257 typedef struct _SOUND_THREAD
258 {
259 HANDLE Handle;
260 BOOL Running;
261
262 struct
263 {
264 HANDLE Ready;
265 HANDLE Request;
266 HANDLE Done;
267 } Events;
268
269 struct
270 {
271 SOUND_THREAD_REQUEST_HANDLER Handler;
272 struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance;
273 PVOID Parameter;
274 MMRESULT Result;
275 } Request;
276 } SOUND_THREAD, *PSOUND_THREAD;
277
278 typedef struct _SOUND_DEVICE
279 {
280 struct _SOUND_DEVICE* Next;
281 struct _SOUND_DEVICE_INSTANCE* HeadInstance;
282 struct _SOUND_DEVICE_INSTANCE* TailInstance;
283 MMDEVICE_TYPE Type;
284 PVOID Identifier; /* Path for NT4 drivers */
285 /*PWSTR Path;*/
286 MMFUNCTION_TABLE FunctionTable;
287 } SOUND_DEVICE, *PSOUND_DEVICE;
288
289 typedef struct _SOUND_DEVICE_INSTANCE
290 {
291 struct _SOUND_DEVICE_INSTANCE* Next;
292 struct _SOUND_DEVICE* Device;
293 PVOID Handle;
294 struct _SOUND_THREAD* Thread;
295
296 /* Stuff generously donated to us from WinMM */
297 struct
298 {
299 HDRVR Handle;
300 DWORD Flags;
301 DWORD ClientCallback;
302 DWORD ClientCallbackInstanceData;
303 } WinMM;
304
305 /* DO NOT TOUCH THESE OUTSIDE OF THE SOUND THREAD */
306
307 union
308 {
309 PWAVEHDR HeadWaveHeader;
310 };
311
312 union
313 {
314 PWAVEHDR TailWaveHeader;
315 };
316
317 PWAVEHDR WaveLoopStart;
318 //PWAVEHDR CurrentWaveHeader;
319 DWORD OutstandingBuffers;
320 DWORD LoopsRemaining;
321 } SOUND_DEVICE_INSTANCE, *PSOUND_DEVICE_INSTANCE;
322
323 /* This lives in WAVEHDR.reserved */
324 typedef struct _WAVEHDR_EXTENSION
325 {
326 DWORD BytesCommitted;
327 DWORD BytesCompleted;
328 } WAVEHDR_EXTENSION, *PWAVEHDR_EXTENSION;
329
330
331 /*
332 reentrancy.c
333 */
334
335 MMRESULT
336 InitEntrypointMutexes();
337
338 VOID
339 CleanupEntrypointMutexes();
340
341 VOID
342 AcquireEntrypointMutex(
343 IN MMDEVICE_TYPE DeviceType);
344
345 VOID
346 ReleaseEntrypointMutex(
347 IN MMDEVICE_TYPE DeviceType);
348
349
350 /*
351 mme.c
352 */
353
354 VOID
355 NotifyMmeClient(
356 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
357 IN DWORD Message,
358 IN DWORD Parameter);
359
360 MMRESULT
361 MmeGetSoundDeviceCapabilities(
362 IN MMDEVICE_TYPE DeviceType,
363 IN DWORD DeviceId,
364 IN PVOID Capabilities,
365 IN DWORD CapabilitiesSize);
366
367 MMRESULT
368 MmeOpenWaveDevice(
369 IN MMDEVICE_TYPE DeviceType,
370 IN DWORD DeviceId,
371 IN LPWAVEOPENDESC OpenParameters,
372 IN DWORD Flags,
373 OUT DWORD* PrivateHandle);
374
375 MMRESULT
376 MmeCloseDevice(
377 IN DWORD PrivateHandle);
378
379 #define MmePrepareWaveHeader(private_handle, header) \
380 PrepareWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header)
381
382 #define MmeUnprepareWaveHeader(private_handle, header) \
383 UnprepareWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header)
384
385 #define MmeWriteWaveHeader(private_handle, header) \
386 WriteWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header)
387
388 MMRESULT
389 MmeResetWavePlayback(
390 IN DWORD PrivateHandle);
391
392
393 /*
394 capabilities.c
395 */
396
397 MMRESULT
398 GetSoundDeviceCapabilities(
399 IN PSOUND_DEVICE SoundDevice,
400 OUT PVOID Capabilities,
401 IN DWORD CapabilitiesSize);
402
403
404 /*
405 devicelist.c
406 */
407
408 ULONG
409 GetSoundDeviceCount(
410 IN MMDEVICE_TYPE DeviceType);
411
412 BOOLEAN
413 IsValidSoundDevice(
414 IN PSOUND_DEVICE SoundDevice);
415
416 MMRESULT
417 ListSoundDevice(
418 IN MMDEVICE_TYPE DeviceType,
419 IN PVOID Identifier OPTIONAL,
420 OUT PSOUND_DEVICE* SoundDevice OPTIONAL);
421
422 MMRESULT
423 UnlistSoundDevice(
424 IN MMDEVICE_TYPE DeviceType,
425 IN PSOUND_DEVICE SoundDevice);
426
427 MMRESULT
428 UnlistSoundDevices(
429 IN MMDEVICE_TYPE DeviceType);
430
431 VOID
432 UnlistAllSoundDevices();
433
434 MMRESULT
435 GetSoundDevice(
436 IN MMDEVICE_TYPE DeviceType,
437 IN DWORD DeviceIndex,
438 OUT PSOUND_DEVICE* Device);
439
440 MMRESULT
441 GetSoundDeviceIdentifier(
442 IN PSOUND_DEVICE SoundDevice,
443 OUT PVOID* Identifier);
444
445 MMRESULT
446 GetSoundDeviceType(
447 IN PSOUND_DEVICE SoundDevice,
448 OUT PMMDEVICE_TYPE DeviceType);
449
450
451 /*
452 functiontable.c
453 */
454
455 MMRESULT
456 SetSoundDeviceFunctionTable(
457 IN PSOUND_DEVICE SoundDevice,
458 IN PMMFUNCTION_TABLE FunctionTable);
459
460 MMRESULT
461 GetSoundDeviceFunctionTable(
462 IN PSOUND_DEVICE SoundDevice,
463 OUT PMMFUNCTION_TABLE* FunctionTable);
464
465
466 /*
467 deviceinstance.c
468 */
469
470 BOOLEAN
471 IsValidSoundDeviceInstance(
472 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance);
473
474 MMRESULT
475 CreateSoundDeviceInstance(
476 IN PSOUND_DEVICE SoundDevice,
477 OUT PSOUND_DEVICE_INSTANCE* SoundDeviceInstance);
478
479 MMRESULT
480 DestroySoundDeviceInstance(
481 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance);
482
483 MMRESULT
484 DestroyAllSoundDeviceInstances(
485 IN PSOUND_DEVICE SoundDevice);
486
487 MMRESULT
488 GetSoundDeviceFromInstance(
489 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
490 OUT PSOUND_DEVICE* SoundDevice);
491
492 MMRESULT
493 GetSoundDeviceInstanceHandle(
494 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
495 OUT PVOID* Handle);
496
497 MMRESULT
498 SetSoundDeviceInstanceMmeData(
499 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
500 IN HDRVR MmeHandle,
501 IN DWORD ClientCallback,
502 IN DWORD ClientCallbackData,
503 IN DWORD Flags);
504
505
506 /*
507 thread.c
508 */
509
510 MMRESULT
511 CreateSoundThread(
512 OUT PSOUND_THREAD* Thread);
513
514 MMRESULT
515 DestroySoundThread(
516 IN PSOUND_THREAD Thread);
517
518 MMRESULT
519 CallSoundThread(
520 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
521 IN SOUND_THREAD_REQUEST_HANDLER RequestHandler,
522 IN PVOID Parameter OPTIONAL);
523
524
525 /*
526 utility.c
527 */
528
529 PVOID
530 AllocateMemory(
531 IN UINT Size);
532
533 VOID
534 FreeMemory(
535 IN PVOID Pointer);
536
537 UINT
538 GetMemoryAllocationCount();
539
540 UINT
541 GetDigitCount(
542 IN UINT Number);
543
544 MMRESULT
545 Win32ErrorToMmResult(
546 IN UINT ErrorCode);
547
548 MMRESULT
549 TranslateInternalMmResult(
550 IN MMRESULT Result);
551
552
553 /*
554 wave/format.c
555 */
556
557 MMRESULT
558 QueryWaveDeviceFormatSupport(
559 IN PSOUND_DEVICE SoundDevice,
560 IN LPWAVEFORMATEX Format,
561 IN DWORD FormatSize);
562
563 MMRESULT
564 SetWaveDeviceFormat(
565 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
566 IN LPWAVEFORMATEX Format,
567 IN DWORD FormatSize);
568
569
570 /*
571 wave/header.c
572 */
573
574 MMRESULT
575 EnqueueWaveHeader(
576 PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
577 IN PVOID Parameter);
578
579 VOID
580 CompleteWaveHeader(
581 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
582 IN PWAVEHDR Header);
583
584 MMRESULT
585 PrepareWaveHeader(
586 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
587 IN PWAVEHDR Header);
588
589 MMRESULT
590 UnprepareWaveHeader(
591 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
592 IN PWAVEHDR Header);
593
594 MMRESULT
595 WriteWaveHeader(
596 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
597 IN PWAVEHDR Header);
598
599
600 /*
601 wave/streaming.c
602 */
603
604 VOID
605 DoWaveStreaming(
606 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance);
607
608 VOID CALLBACK
609 CompleteIO(
610 IN DWORD dwErrorCode,
611 IN DWORD dwNumberOfBytesTransferred,
612 IN LPOVERLAPPED lpOverlapped);
613
614 MMRESULT
615 CommitWaveHeaderToKernelDevice(
616 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
617 IN PWAVEHDR Header,
618 IN WAVE_COMMIT_FUNC CommitFunction);
619
620 MMRESULT
621 WriteFileEx_Committer(
622 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
623 IN PVOID OffsetPtr,
624 IN DWORD Length,
625 IN PSOUND_OVERLAPPED Overlap,
626 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine);
627
628 MMRESULT
629 StopStreaming(
630 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance);
631
632
633 /*
634 kernel.c
635 */
636
637 MMRESULT
638 OpenKernelSoundDeviceByName(
639 IN PWSTR DevicePath,
640 IN BOOLEAN ReadOnly,
641 OUT PHANDLE Handle);
642
643 MMRESULT
644 OpenKernelSoundDevice(
645 IN PSOUND_DEVICE SoundDevice,
646 IN BOOLEAN ReadOnly,
647 OUT PHANDLE Handle);
648
649 MMRESULT
650 CloseKernelSoundDevice(
651 IN HANDLE Handle);
652
653 MMRESULT
654 SyncOverlappedDeviceIoControl(
655 IN HANDLE SoundDeviceInstance,
656 IN DWORD IoControlCode,
657 IN LPVOID InBuffer,
658 IN DWORD InBufferSize,
659 OUT LPVOID OutBuffer,
660 IN DWORD OutBufferSize,
661 OUT LPDWORD BytesTransferred OPTIONAL);
662
663
664 #endif