ReactOS 0.4.15-dev-7961-gdcf9eb0
deviceinstance.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Sound System "MME Buddy" Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/sound/mmebuddy/deviceinstance.c
5 *
6 * PURPOSE: Manages instances of sound devices.
7 *
8 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
9*/
10
11#include "precomp.h"
12
13/*
14 Restrain ourselves from flooding the kernel device!
15*/
16
17#define SOUND_KERNEL_BUFFER_COUNT 10
18#define SOUND_KERNEL_BUFFER_SIZE 16384
19
22 OUT PSOUND_DEVICE_INSTANCE* SoundDeviceInstance)
23{
24 PSOUND_DEVICE_INSTANCE NewInstance;
25
26 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
27
28 /* Allocate memory for the new instance */
30
31 if ( ! NewInstance )
32 return MMSYSERR_NOMEM;
33
34 /* Use default frame size */
36 /* Use default buffer count */
38
39 /* Provide the caller with the new instance pointer */
40 *SoundDeviceInstance = NewInstance;
41
42 return MMSYSERR_NOERROR;
43}
44
45VOID
47 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
48{
49 /*
50 Device is marked as invalid by now, but we can still do some sanity
51 checking.
52 */
53 SND_ASSERT( SoundDeviceInstance->Thread == NULL );
54
55 ZeroMemory(SoundDeviceInstance, sizeof(SOUND_DEVICE_INSTANCE));
56 FreeMemory(SoundDeviceInstance);
57}
58
61 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
62{
63 PSOUND_DEVICE SoundDevice;
64 PSOUND_DEVICE_INSTANCE CurrentInstance;
65
66 if ( ! SoundDeviceInstance )
67 return FALSE;
68
69 /* GetSoundDeviceFromInstance would send us into a recursive loop... */
70 SoundDevice = SoundDeviceInstance->Device;
71 SND_ASSERT(SoundDevice);
72
73 CurrentInstance = SoundDevice->HeadInstance;
74
75 while ( CurrentInstance )
76 {
77 if ( CurrentInstance == SoundDeviceInstance )
78 return TRUE;
79
80 CurrentInstance = CurrentInstance->Next;
81 }
82
83 return FALSE;
84}
85
88 IN PSOUND_DEVICE SoundDevice,
89 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
90{
92 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
93
94 SND_TRACE(L"Listing sound device instance\n");
95
96 if ( ! SoundDevice->HeadInstance )
97 {
98 /* First entry - assign to head and tail */
99 SoundDevice->HeadInstance = SoundDeviceInstance;
100 SoundDevice->TailInstance = SoundDeviceInstance;
101 }
102 else
103 {
104 /* Attach to the end */
105 SoundDevice->TailInstance->Next = SoundDeviceInstance;
106 SoundDevice->TailInstance = SoundDeviceInstance;
107 }
108
109 return MMSYSERR_NOERROR;
110}
111
114 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
115{
117 PSOUND_DEVICE SoundDevice;
118 PSOUND_DEVICE_INSTANCE CurrentInstance, PreviousInstance;
119
121
122 SND_TRACE(L"Unlisting sound device instance\n");
123
124 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
126 if ( ! MMSUCCESS(Result) )
128
129 PreviousInstance = NULL;
130 CurrentInstance = SoundDevice->HeadInstance;
131
132 while ( CurrentInstance )
133 {
134 if ( CurrentInstance == SoundDeviceInstance )
135 {
136 if ( ! PreviousInstance )
137 {
138 /* This is the head node */
139 SoundDevice->HeadInstance = SoundDevice->HeadInstance->Next;
140 }
141 else
142 {
143 /* There are nodes before this one - cut ours out */
144 PreviousInstance->Next = CurrentInstance->Next;
145 }
146
147 if ( ! CurrentInstance->Next )
148 {
149 /* This is the tail node */
150 SoundDevice->TailInstance = PreviousInstance;
151 }
152 }
153
154 PreviousInstance = CurrentInstance;
155 CurrentInstance = CurrentInstance->Next;
156 }
157
158 return MMSYSERR_NOERROR;
159}
160
163 IN PSOUND_DEVICE SoundDevice,
164 OUT PSOUND_DEVICE_INSTANCE* SoundDeviceInstance)
165{
168
169 SND_TRACE(L"Creating a sound device instance\n");
170
172 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance != NULL );
173
174 Result = AllocateSoundDeviceInstance(SoundDeviceInstance);
175
176 if ( ! MMSUCCESS(Result) )
178
179 /* Get the "open" routine from the function table, and validate it */
181 if ( ! MMSUCCESS(Result) )
182 {
183 FreeSoundDeviceInstance(*SoundDeviceInstance);
185 }
186
187 if ( FunctionTable->Open == NULL )
188 {
189 FreeSoundDeviceInstance(*SoundDeviceInstance);
191 }
192
193 /* Set up the members of the structure */
194 (*SoundDeviceInstance)->Next = NULL;
195 (*SoundDeviceInstance)->Device = SoundDevice;
196 (*SoundDeviceInstance)->Handle = NULL;
197 (*SoundDeviceInstance)->Thread = NULL;
198
199 (*SoundDeviceInstance)->WinMM.Handle = INVALID_HANDLE_VALUE;
200 (*SoundDeviceInstance)->WinMM.ClientCallback = 0;
201 (*SoundDeviceInstance)->WinMM.ClientCallbackInstanceData = 0;
202 (*SoundDeviceInstance)->WinMM.Flags = 0;
203
204 /* Initialise the members of the struct used by the sound thread */
205 (*SoundDeviceInstance)->HeadWaveHeader = NULL;
206 (*SoundDeviceInstance)->TailWaveHeader = NULL;
207
208 (*SoundDeviceInstance)->OutstandingBuffers = 0;
209
210 (*SoundDeviceInstance)->LoopsRemaining = 0;
211
212 /* Create the streaming thread (TODO - is this for wave only?) */
213 Result = CreateSoundThread(&(*SoundDeviceInstance)->Thread);
214 if ( ! MMSUCCESS(Result) )
215 {
216 FreeSoundDeviceInstance(*SoundDeviceInstance);
218 }
219
220 /* Add the instance to the list */
221 Result = ListSoundDeviceInstance(SoundDevice, *SoundDeviceInstance);
222 if ( ! MMSUCCESS(Result) )
223 {
224 FreeSoundDeviceInstance(*SoundDeviceInstance);
226 }
227
228 /* Try and open the device */
229 Result = FunctionTable->Open(SoundDevice, (&(*SoundDeviceInstance)->Handle));
230 if ( ! MMSUCCESS(Result) )
231 {
232 UnlistSoundDeviceInstance(*SoundDeviceInstance);
233 FreeSoundDeviceInstance(*SoundDeviceInstance);
235 }
236
237 return MMSYSERR_NOERROR;
238}
239
242 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
243{
246 PSOUND_DEVICE SoundDevice;
248
249 SND_TRACE(L"Destroying a sound device instance\n");
250
252
253 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
254 if ( ! MMSUCCESS(Result) )
256
257 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
258 if ( ! MMSUCCESS(Result) )
260
261 /* Get the "close" routine from the function table, and validate it */
263 if ( ! MMSUCCESS(Result) )
265
266 SND_ASSERT( FunctionTable->Close );
267 if ( FunctionTable->Close == NULL )
268 {
269 /* This indicates bad practice, really! If you can open, why not close?! */
271 }
272
273 /* Stop the streaming thread */
274 if ( SoundDeviceInstance->Thread )
275 {
276 Result = DestroySoundThread(SoundDeviceInstance->Thread);
277 SND_ASSERT( MMSUCCESS(Result) ); /* It should succeed! */
278 if ( ! MMSUCCESS(Result ) )
279 {
281 }
282 }
283
284 /* Blank this out here */
285 SoundDeviceInstance->Thread = NULL;
286
287 /* Try and close the device */
288 Result = FunctionTable->Close(SoundDeviceInstance, Handle);
289 SND_ASSERT( MMSUCCESS(Result) ); /* It should succeed! */
290 if ( ! MMSUCCESS(Result) )
292
293 /* Drop it from the list */
294 Result = UnlistSoundDeviceInstance(SoundDeviceInstance);
295 SND_ASSERT( MMSUCCESS(Result) ); /* It should succeed! */
296 if ( ! MMSUCCESS(Result) )
298
299 FreeSoundDeviceInstance(SoundDeviceInstance);
300
301 return MMSYSERR_NOERROR;
302}
303
306 IN PSOUND_DEVICE SoundDevice)
307{
309 PSOUND_DEVICE_INSTANCE SoundDeviceInstance, NextDeviceInstance;
310
311 SoundDeviceInstance = SoundDevice->HeadInstance;
312
313 while ( SoundDeviceInstance )
314 {
315 NextDeviceInstance = SoundDeviceInstance->Next;
316 Result = DestroySoundDeviceInstance(SoundDeviceInstance);
318 SoundDeviceInstance = NextDeviceInstance;
319 }
320
321 return MMSYSERR_NOERROR;
322}
323
326 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
327 OUT PSOUND_DEVICE* SoundDevice)
328{
330 VALIDATE_MMSYS_PARAMETER( SoundDevice );
331
332 *SoundDevice = SoundDeviceInstance->Device;
333
334 return MMSYSERR_NOERROR;
335}
336
339 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
341{
344
345 *Handle = SoundDeviceInstance->Handle;
346
347 return MMSYSERR_NOERROR;
348}
349
352 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
353 IN HDRVR MmeHandle,
354 IN DWORD_PTR ClientCallback,
355 IN DWORD_PTR ClientCallbackData,
356 IN DWORD Flags)
357{
359
360 SND_TRACE(L"Setting MME data - handle %x, callback %x, instance data %x, flags %x\n",
361 MmeHandle, ClientCallback, ClientCallbackData, Flags);
362
363 SoundDeviceInstance->WinMM.Handle = MmeHandle;
364 SoundDeviceInstance->WinMM.ClientCallback = ClientCallback;
365 SoundDeviceInstance->WinMM.ClientCallbackInstanceData = ClientCallbackData;
366 SoundDeviceInstance->WinMM.Flags = Flags;
367
368 return MMSYSERR_NOERROR;
369}
unsigned char BOOLEAN
static VOID FreeMemory(PCREATE_DATA Data)
Definition: create.c:134
MMRESULT DestroyAllSoundDeviceInstances(IN PSOUND_DEVICE SoundDevice)
#define SOUND_KERNEL_BUFFER_COUNT
VOID FreeSoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
MMRESULT SetSoundDeviceInstanceMmeData(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN HDRVR MmeHandle, IN DWORD_PTR ClientCallback, IN DWORD_PTR ClientCallbackData, IN DWORD Flags)
MMRESULT AllocateSoundDeviceInstance(OUT PSOUND_DEVICE_INSTANCE *SoundDeviceInstance)
#define SOUND_KERNEL_BUFFER_SIZE
MMRESULT GetSoundDeviceFromInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, OUT PSOUND_DEVICE *SoundDevice)
MMRESULT UnlistSoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
MMRESULT ListSoundDeviceInstance(IN PSOUND_DEVICE SoundDevice, IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
MMRESULT GetSoundDeviceInstanceHandle(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, OUT PVOID *Handle)
MMRESULT DestroySoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
BOOLEAN IsValidSoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
MMRESULT CreateSoundDeviceInstance(IN PSOUND_DEVICE SoundDevice, OUT PSOUND_DEVICE_INSTANCE *SoundDeviceInstance)
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
unsigned long DWORD
Definition: ntddk_ex.h:95
ULONG Handle
Definition: gdb_input.c:15
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
BOOLEAN IsValidSoundDevice(IN PSOUND_DEVICE SoundDevice)
Definition: devicelist.c:87
MMRESULT CreateSoundThread(OUT PSOUND_THREAD *Thread)
Definition: thread.c:209
#define VALIDATE_MMSYS_PARAMETER(parameter_condition)
Definition: mmebuddy.h:71
#define AllocateStruct(thing)
Definition: mmebuddy.h:27
MMRESULT GetSoundDeviceFunctionTable(IN PSOUND_DEVICE SoundDevice, OUT PMMFUNCTION_TABLE *FunctionTable)
Definition: functiontable.c:47
MMRESULT DestroySoundThread(IN PSOUND_THREAD Thread)
Definition: thread.c:272
MMRESULT TranslateInternalMmResult(IN MMRESULT Result)
Definition: utility.c:132
#define MMSUCCESS(result)
Definition: mmebuddy.h:80
#define SND_TRACE(...)
#define SND_ASSERT(condition)
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
UINT MMRESULT
Definition: mmsystem.h:962
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define L(x)
Definition: ntvdm.h:50
struct _SOUND_DEVICE_INSTANCE * Next
Definition: mmebuddy.h:268
struct _SOUND_DEVICE_INSTANCE * HeadInstance
Definition: mmebuddy.h:258
struct _SOUND_DEVICE_INSTANCE * TailInstance
Definition: mmebuddy.h:259
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
#define ZeroMemory
Definition: winbase.h:1712
static WLX_DISPATCH_VERSION_1_4 FunctionTable
Definition: wlx.c:722
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170