ReactOS  0.4.14-dev-384-g5b37caa
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 */
35  NewInstance->FrameSize = SOUND_KERNEL_BUFFER_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 
45 VOID
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 
59 BOOLEAN
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 
112 MMRESULT
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 
161 MMRESULT
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);
190  return MMSYSERR_NOTSUPPORTED;
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 
240 MMRESULT
242  IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
243 {
246  PSOUND_DEVICE SoundDevice;
247  PVOID Handle;
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?! */
270  return MMSYSERR_NOTSUPPORTED;
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 
304 MMRESULT
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 
324 MMRESULT
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 
337 MMRESULT
339  IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
340  OUT PVOID* Handle)
341 {
344 
345  *Handle = SoundDeviceInstance->Handle;
346 
347  return MMSYSERR_NOERROR;
348 }
349 
350 MMRESULT
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 }
#define IN
Definition: typedefs.h:38
static VOID FreeMemory(PCREATE_DATA Data)
Definition: create.c:134
#define TRUE
Definition: types.h:120
struct _SOUND_DEVICE_INSTANCE * TailInstance
Definition: mmebuddy.h:260
#define MMSUCCESS(result)
Definition: mmebuddy.h:80
MMRESULT TranslateInternalMmResult(IN MMRESULT Result)
Definition: utility.c:132
#define INVALID_HANDLE_VALUE
Definition: compat.h:399
#define ZeroMemory
Definition: winbase.h:1642
UINT MMRESULT
Definition: mmsystem.h:962
MMRESULT DestroySoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
MMRESULT CreateSoundThread(OUT PSOUND_THREAD *Thread)
Definition: thread.c:209
MMRESULT GetSoundDeviceFromInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, OUT PSOUND_DEVICE *SoundDevice)
#define VALIDATE_MMSYS_PARAMETER(parameter_condition)
Definition: mmebuddy.h:71
MMRESULT DestroySoundThread(IN PSOUND_THREAD Thread)
Definition: thread.c:272
MMRESULT GetSoundDeviceFunctionTable(IN PSOUND_DEVICE SoundDevice, OUT PMMFUNCTION_TABLE *FunctionTable)
Definition: functiontable.c:47
MMRESULT DestroyAllSoundDeviceInstances(IN PSOUND_DEVICE SoundDevice)
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define SND_ASSERT(condition)
_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:426
#define SOUND_KERNEL_BUFFER_SIZE
MMRESULT AllocateSoundDeviceInstance(OUT PSOUND_DEVICE_INSTANCE *SoundDeviceInstance)
struct _SOUND_DEVICE_INSTANCE * HeadInstance
Definition: mmebuddy.h:259
_In_ HANDLE Handle
Definition: extypes.h:390
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
MMRESULT SetSoundDeviceInstanceMmeData(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN HDRVR MmeHandle, IN DWORD_PTR ClientCallback, IN DWORD_PTR ClientCallbackData, IN DWORD Flags)
#define AllocateStruct(thing)
Definition: mmebuddy.h:27
unsigned long DWORD
Definition: ntddk_ex.h:95
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
#define SOUND_KERNEL_BUFFER_COUNT
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
static const WCHAR L[]
Definition: oid.c:1250
MMRESULT UnlistSoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
uint32_t DWORD_PTR
Definition: typedefs.h:63
MMRESULT ListSoundDeviceInstance(IN PSOUND_DEVICE SoundDevice, IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
BOOLEAN IsValidSoundDevice(IN PSOUND_DEVICE SoundDevice)
Definition: devicelist.c:87
MMRESULT GetSoundDeviceInstanceHandle(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, OUT PVOID *Handle)
struct _SOUND_DEVICE_INSTANCE * Next
Definition: mmebuddy.h:269
#define OUT
Definition: typedefs.h:39
static WLX_DISPATCH_VERSION_1_4 FunctionTable
Definition: wlx.c:736
VOID FreeSoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
MMRESULT CreateSoundDeviceInstance(IN PSOUND_DEVICE SoundDevice, OUT PSOUND_DEVICE_INSTANCE *SoundDeviceInstance)
BOOLEAN IsValidSoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
#define SND_TRACE(...)