2 * PROJECT: ReactOS Sound System "MME Buddy" Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/sound/mmebuddy/mmewrap.c
6 * PURPOSE: Interface between MME functions and MME Buddy's own.
8 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
20 Sets the device into running or stopped state
25 IN DWORD_PTR PrivateHandle
,
29 PMMFUNCTION_TABLE FunctionTable
;
30 PSOUND_DEVICE SoundDevice
;
31 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
33 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
34 SoundDeviceInstance
= (PSOUND_DEVICE_INSTANCE
) PrivateHandle
;
36 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance
) );
38 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
39 if ( ! MMSUCCESS(Result
) )
40 return TranslateInternalMmResult(Result
);
42 /* Get the function table, and validate it */
43 Result
= GetSoundDeviceFunctionTable(SoundDevice
, &FunctionTable
);
44 if ( ! MMSUCCESS(Result
) )
45 return TranslateInternalMmResult(Result
);
47 SND_ASSERT( FunctionTable
->SetState
);
48 if ( FunctionTable
->SetState
== NULL
)
51 return MMSYSERR_NOTSUPPORTED
;
53 /* Try change state */
54 Result
= FunctionTable
->SetState(SoundDeviceInstance
, bStart
);
60 Call the client application when something interesting happens (MME API
61 defines "interesting things" as device open, close, and buffer
66 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
68 IN DWORD_PTR Parameter
)
70 SND_ASSERT( SoundDeviceInstance
);
72 SND_TRACE(L
"MME client callback - message %d, parameter %d\n",
76 if ( SoundDeviceInstance
->WinMM
.ClientCallback
)
78 DriverCallback(SoundDeviceInstance
->WinMM
.ClientCallback
,
79 HIWORD(SoundDeviceInstance
->WinMM
.Flags
),
80 SoundDeviceInstance
->WinMM
.Handle
,
82 SoundDeviceInstance
->WinMM
.ClientCallbackInstanceData
,
89 This is a helper function to alleviate some of the repetition involved with
90 implementing the various MME message functions.
93 MmeGetSoundDeviceCapabilities(
94 IN MMDEVICE_TYPE DeviceType
,
96 IN PVOID Capabilities
,
97 IN DWORD CapabilitiesSize
)
99 PSOUND_DEVICE SoundDevice
;
102 SND_TRACE(L
"MME *_GETCAPS for device %d of type %d\n", DeviceId
, DeviceType
);
104 /* FIXME: Validate device ID */
105 VALIDATE_MMSYS_PARAMETER( Capabilities
);
106 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
108 /* Our parameter checks are done elsewhere */
110 Result
= GetSoundDevice(DeviceType
, DeviceId
, &SoundDevice
);
112 if ( ! MMSUCCESS(Result
) )
115 return GetSoundDeviceCapabilities(SoundDevice
,
123 IN MMDEVICE_TYPE DeviceType
,
125 IN LPWAVEOPENDESC OpenParameters
,
127 OUT DWORD_PTR
* PrivateHandle
)
131 PSOUND_DEVICE SoundDevice
;
132 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
133 LPWAVEFORMATEX Format
;
135 SND_TRACE(L
"Opening device");
137 VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType
) ); /* FIXME? wave in too? */
138 VALIDATE_MMSYS_PARAMETER( OpenParameters
);
140 Result
= GetSoundDevice(DeviceType
, DeviceId
, &SoundDevice
);
141 if ( ! MMSUCCESS(Result
) )
142 return TranslateInternalMmResult(Result
);
144 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
146 Format
= OpenParameters
->lpFormat
;
148 /* Does this device support the format? */
149 Result
= QueryWaveDeviceFormatSupport(SoundDevice
, Format
, sizeof(WAVEFORMATEX
));
150 if ( ! MMSUCCESS(Result
) )
152 SND_ERR(L
"Format not supported\n");
153 return TranslateInternalMmResult(Result
);
156 /* If the caller just wanted to know if a format is supported, end here */
157 if ( Flags
& WAVE_FORMAT_QUERY
)
158 return MMSYSERR_NOERROR
;
161 /* Check that winmm gave us a private handle to fill */
162 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
164 /* Create a sound device instance and open the sound device */
165 Result
= CreateSoundDeviceInstance(SoundDevice
, &SoundDeviceInstance
);
166 if ( ! MMSUCCESS(Result
) )
167 return TranslateInternalMmResult(Result
);
169 Result
= SetWaveDeviceFormat(SoundDeviceInstance
, DeviceId
, Format
, sizeof(WAVEFORMATEX
));
170 if ( ! MMSUCCESS(Result
) )
172 /* TODO: Destroy sound instance */
173 return TranslateInternalMmResult(Result
);
176 /* Store the device instance pointer in the private handle */
177 *PrivateHandle
= (DWORD_PTR
)SoundDeviceInstance
;
179 /* Store the additional information we were given - FIXME: Need flags! */
180 SetSoundDeviceInstanceMmeData(SoundDeviceInstance
,
181 (HDRVR
)OpenParameters
->hWave
, /* works because LPMIXEROPENDESC/etc has also the handle as first member */
182 OpenParameters
->dwCallback
,
183 OpenParameters
->dwInstance
,
186 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
|| DeviceType
== WAVE_IN_DEVICE_TYPE
||
187 DeviceType
== MIDI_OUT_DEVICE_TYPE
|| DeviceType
== MIDI_IN_DEVICE_TYPE
)
189 /* Let the application know the device is open */
191 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
193 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
195 else if (DeviceType
== MIDI_IN_DEVICE_TYPE
)
200 ReleaseEntrypointMutex(DeviceType
);
202 NotifyMmeClient(SoundDeviceInstance
,
206 AcquireEntrypointMutex(DeviceType
);
209 SND_TRACE(L
"device now open\n");
211 return MMSYSERR_NOERROR
;
216 IN DWORD_PTR PrivateHandle
)
219 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
220 PSOUND_DEVICE SoundDevice
;
221 MMDEVICE_TYPE DeviceType
;
224 SND_TRACE(L
"Closing wave device (WIDM_CLOSE / WODM_CLOSE)\n");
226 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
227 SoundDeviceInstance
= (PSOUND_DEVICE_INSTANCE
) PrivateHandle
;
229 if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance
) )
230 return MMSYSERR_INVALHANDLE
;
232 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
233 if ( ! MMSUCCESS(Result
) )
234 return TranslateInternalMmResult(Result
);
236 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
237 if ( ! MMSUCCESS(Result
) )
238 return TranslateInternalMmResult(Result
);
241 /* TODO: Check device is stopped! */
244 if (DeviceType
!= MIXER_DEVICE_TYPE
)
246 ReleaseEntrypointMutex(DeviceType
);
248 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
250 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
252 else if (DeviceType
== MIDI_IN_DEVICE_TYPE
)
254 else if (DeviceType
== MIDI_OUT_DEVICE_TYPE
)
257 /* TODO: Work with MIDI devices too */
258 NotifyMmeClient(SoundDeviceInstance
,
261 AcquireEntrypointMutex(DeviceType
);
264 Result
= DestroySoundDeviceInstance(SoundDeviceInstance
);
270 MmeResetWavePlayback(
271 IN DWORD_PTR PrivateHandle
)
273 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
275 SND_TRACE(L
"Resetting wave device (WODM_RESET)\n");
277 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
278 SoundDeviceInstance
= (PSOUND_DEVICE_INSTANCE
) PrivateHandle
;
280 return StopStreaming(SoundDeviceInstance
);
284 MmeGetDeviceInterfaceString(
285 IN MMDEVICE_TYPE DeviceType
,
288 IN DWORD InterfaceLength
,
289 OUT DWORD
* InterfaceSize
)
292 PSOUND_DEVICE SoundDevice
;
293 PMMFUNCTION_TABLE FunctionTable
;
295 Result
= GetSoundDevice(DeviceType
, DeviceId
, &SoundDevice
);
296 if ( ! MMSUCCESS(Result
) )
297 return TranslateInternalMmResult(Result
);
299 Result
= GetSoundDeviceFunctionTable(SoundDevice
, &FunctionTable
);
300 if ( ! MMSUCCESS(Result
) )
301 return TranslateInternalMmResult(Result
);
303 if ( FunctionTable
->GetDeviceInterfaceString
== NULL
)
305 /* querying device interface string / size not supported */
306 return MMSYSERR_NOTSUPPORTED
;
309 /* Call the driver */
310 Result
= FunctionTable
->GetDeviceInterfaceString(DeviceType
, DeviceId
, Interface
, InterfaceLength
, InterfaceSize
);
318 IN MMDEVICE_TYPE DeviceType
,
320 IN DWORD_PTR PrivateHandle
,
325 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
326 PSOUND_DEVICE SoundDevice
;
327 PMMFUNCTION_TABLE FunctionTable
;
329 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
330 SoundDeviceInstance
= (PSOUND_DEVICE_INSTANCE
) PrivateHandle
;
332 if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance
) )
333 return MMSYSERR_INVALHANDLE
;
335 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
336 if ( ! MMSUCCESS(Result
) )
337 return TranslateInternalMmResult(Result
);
339 if ( Size
!= sizeof(MMTIME
) )
340 return MMSYSERR_INVALPARAM
;
342 Result
= GetSoundDeviceFunctionTable(SoundDevice
, &FunctionTable
);
343 if ( ! MMSUCCESS(Result
) )
344 return TranslateInternalMmResult(Result
);
346 if ( FunctionTable
->GetPos
== NULL
)
348 /* This indicates bad practice, really! If you can open, why not close?! */
349 return MMSYSERR_NOTSUPPORTED
;
352 /* Call the driver */
353 Result
= FunctionTable
->GetPos(SoundDeviceInstance
, Time
);