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