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