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