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
6 * PURPOSE: Manages instances of sound devices.
8 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
17 AllocateSoundDeviceInstance(
18 OUT PSOUND_DEVICE_INSTANCE
* SoundDeviceInstance
)
20 PSOUND_DEVICE_INSTANCE NewInstance
;
22 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance
);
24 /* Allocate memory for the new instance */
25 NewInstance
= AllocateStruct(SOUND_DEVICE_INSTANCE
);
28 return MMSYSERR_NOMEM
;
30 /* Provide the caller with the new instance pointer */
31 *SoundDeviceInstance
= NewInstance
;
33 return MMSYSERR_NOERROR
;
37 FreeSoundDeviceInstance(
38 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
)
40 /* This won't work as the device is no longer valid by this point! */
41 /*SND_ASSERT( IsValidSoundDeviceInstance(SoundDeviceInstance) );*/
42 ZeroMemory(SoundDeviceInstance
, sizeof(SOUND_DEVICE_INSTANCE
));
43 FreeMemory(SoundDeviceInstance
);
47 IsValidSoundDeviceInstance(
48 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
)
50 PSOUND_DEVICE SoundDevice
;
51 PSOUND_DEVICE_INSTANCE CurrentInstance
;
53 if ( ! SoundDeviceInstance
)
56 /* GetSoundDeviceFromInstance would send us into a recursive loop... */
57 SoundDevice
= SoundDeviceInstance
->Device
;
58 SND_ASSERT(SoundDevice
);
60 CurrentInstance
= SoundDevice
->HeadInstance
;
62 while ( CurrentInstance
)
64 if ( CurrentInstance
== SoundDeviceInstance
)
67 CurrentInstance
= CurrentInstance
->Next
;
74 ListSoundDeviceInstance(
75 IN PSOUND_DEVICE SoundDevice
,
76 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
)
78 VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice
) );
79 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance
);
81 SND_TRACE(L
"Listing sound device instance\n");
83 if ( ! SoundDevice
->HeadInstance
)
85 /* First entry - assign to head and tail */
86 SoundDevice
->HeadInstance
= SoundDeviceInstance
;
87 SoundDevice
->TailInstance
= SoundDeviceInstance
;
91 /* Attach to the end */
92 SoundDevice
->TailInstance
->Next
= SoundDeviceInstance
;
93 SoundDevice
->TailInstance
= SoundDeviceInstance
;
96 return MMSYSERR_NOERROR
;
100 UnlistSoundDeviceInstance(
101 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
)
104 PSOUND_DEVICE SoundDevice
;
105 PSOUND_DEVICE_INSTANCE CurrentInstance
, PreviousInstance
;
107 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance
) );
109 SND_TRACE(L
"Unlisting sound device instance\n");
111 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
112 SND_ASSERT( MMSUCCESS(Result
) );
114 PreviousInstance
= NULL
;
115 CurrentInstance
= SoundDevice
->HeadInstance
;
117 while ( CurrentInstance
)
119 if ( CurrentInstance
== SoundDeviceInstance
)
121 if ( ! PreviousInstance
)
123 /* This is the head node */
124 SoundDevice
->HeadInstance
= SoundDevice
->HeadInstance
->Next
;
128 /* There are nodes before this one - cut ours out */
129 PreviousInstance
->Next
= CurrentInstance
->Next
;
132 if ( ! CurrentInstance
->Next
)
134 /* This is the tail node */
135 SoundDevice
->TailInstance
= PreviousInstance
;
139 PreviousInstance
= CurrentInstance
;
140 CurrentInstance
= CurrentInstance
->Next
;
143 return MMSYSERR_NOERROR
;
147 CreateSoundDeviceInstance(
148 IN PSOUND_DEVICE SoundDevice
,
149 OUT PSOUND_DEVICE_INSTANCE
* SoundDeviceInstance
)
152 PMMFUNCTION_TABLE FunctionTable
;
154 SND_TRACE(L
"Creating a sound device instance\n");
156 VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice
) );
157 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance
!= NULL
);
159 Result
= AllocateSoundDeviceInstance(SoundDeviceInstance
);
161 if ( ! MMSUCCESS(Result
) )
162 return TranslateInternalMmResult(Result
);
164 /* Get the "open" routine from the function table, and validate it */
165 Result
= GetSoundDeviceFunctionTable(SoundDevice
, &FunctionTable
);
166 if ( ! MMSUCCESS(Result
) )
168 FreeSoundDeviceInstance(*SoundDeviceInstance
);
169 return TranslateInternalMmResult(Result
);
172 if ( FunctionTable
->Open
== NULL
)
174 FreeSoundDeviceInstance(*SoundDeviceInstance
);
175 return MMSYSERR_NOTSUPPORTED
;
178 /* Set up the members of the structure */
179 (*SoundDeviceInstance
)->Next
= NULL
;
180 (*SoundDeviceInstance
)->Device
= SoundDevice
;
181 (*SoundDeviceInstance
)->Handle
= NULL
;
182 (*SoundDeviceInstance
)->Thread
= NULL
;
184 (*SoundDeviceInstance
)->WinMM
.Handle
= INVALID_HANDLE_VALUE
;
185 (*SoundDeviceInstance
)->WinMM
.ClientCallback
= 0;
186 (*SoundDeviceInstance
)->WinMM
.ClientCallbackInstanceData
= 0;
187 (*SoundDeviceInstance
)->WinMM
.Flags
= 0;
189 /* Create the streaming thread (TODO - is this for wave only?) */
190 Result
= CreateSoundThread(&(*SoundDeviceInstance
)->Thread
);
191 if ( ! MMSUCCESS(Result
) )
193 FreeSoundDeviceInstance(*SoundDeviceInstance
);
194 return TranslateInternalMmResult(Result
);
197 /* Add the instance to the list */
198 Result
= ListSoundDeviceInstance(SoundDevice
, *SoundDeviceInstance
);
199 if ( ! MMSUCCESS(Result
) )
201 FreeSoundDeviceInstance(*SoundDeviceInstance
);
202 return TranslateInternalMmResult(Result
);
205 /* Try and open the device */
206 Result
= FunctionTable
->Open(SoundDevice
, (&(*SoundDeviceInstance
)->Handle
));
207 if ( ! MMSUCCESS(Result
) )
209 UnlistSoundDeviceInstance(*SoundDeviceInstance
);
210 FreeSoundDeviceInstance(*SoundDeviceInstance
);
211 return TranslateInternalMmResult(Result
);
214 return MMSYSERR_NOERROR
;
218 DestroySoundDeviceInstance(
219 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
)
222 PMMFUNCTION_TABLE FunctionTable
;
223 PSOUND_DEVICE SoundDevice
;
226 SND_TRACE(L
"Destroying a sound device instance\n");
228 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance
) );
230 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
231 if ( ! MMSUCCESS(Result
) )
232 return TranslateInternalMmResult(Result
);
234 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
235 if ( ! MMSUCCESS(Result
) )
236 return TranslateInternalMmResult(Result
);
238 /* Get the "close" routine from the function table, and validate it */
239 Result
= GetSoundDeviceFunctionTable(SoundDevice
, &FunctionTable
);
240 if ( ! MMSUCCESS(Result
) )
241 return TranslateInternalMmResult(Result
);
243 SND_ASSERT( FunctionTable
->Close
);
244 if ( FunctionTable
->Close
== NULL
)
246 /* This indicates bad practice, really! If you can open, why not close?! */
247 return MMSYSERR_NOTSUPPORTED
;
250 /* Try and close the device */
251 Result
= FunctionTable
->Close(SoundDeviceInstance
, Handle
);
252 if ( ! MMSUCCESS(Result
) )
253 return TranslateInternalMmResult(Result
);
255 /* Drop it from the list */
256 Result
= UnlistSoundDeviceInstance(SoundDeviceInstance
);
257 if ( ! MMSUCCESS(Result
) )
258 return TranslateInternalMmResult(Result
);
260 FreeSoundDeviceInstance(SoundDeviceInstance
);
262 return MMSYSERR_NOERROR
;
266 DestroyAllSoundDeviceInstances(
267 IN PSOUND_DEVICE SoundDevice
)
269 return MMSYSERR_NOTSUPPORTED
;
273 GetSoundDeviceFromInstance(
274 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
275 OUT PSOUND_DEVICE
* SoundDevice
)
277 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance
) );
278 VALIDATE_MMSYS_PARAMETER( SoundDevice
);
280 *SoundDevice
= SoundDeviceInstance
->Device
;
282 return MMSYSERR_NOERROR
;
286 GetSoundDeviceInstanceHandle(
287 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
290 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance
) );
291 VALIDATE_MMSYS_PARAMETER( Handle
);
293 *Handle
= SoundDeviceInstance
->Handle
;
295 return MMSYSERR_NOERROR
;
299 SetSoundDeviceInstanceMmeData(
300 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
302 IN DWORD ClientCallback
,
303 IN DWORD ClientCallbackData
,
306 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance
) );
308 SND_TRACE(L
"Setting MME data - handle %x, callback %x, instance data %x, flags %x\n",
309 MmeHandle
, ClientCallback
, ClientCallbackData
, Flags
);
311 SoundDeviceInstance
->WinMM
.Handle
= MmeHandle
;
312 SoundDeviceInstance
->WinMM
.ClientCallback
= ClientCallback
;
313 SoundDeviceInstance
->WinMM
.ClientCallbackInstanceData
= ClientCallbackData
;
314 SoundDeviceInstance
->WinMM
.Flags
= Flags
;
316 return MMSYSERR_NOERROR
;