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)
15 Sets the device into running or stopped state
20 IN DWORD_PTR PrivateHandle
,
24 PMMFUNCTION_TABLE FunctionTable
;
25 PSOUND_DEVICE SoundDevice
;
26 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
29 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
30 SoundDeviceInstance
= (PSOUND_DEVICE_INSTANCE
) PrivateHandle
;
32 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance
) );
34 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
35 if ( ! MMSUCCESS(Result
) )
36 return TranslateInternalMmResult(Result
);
38 /* Get the function table, and validate it */
39 Result
= GetSoundDeviceFunctionTable(SoundDevice
, &FunctionTable
);
40 if ( ! MMSUCCESS(Result
) )
41 return TranslateInternalMmResult(Result
);
43 SND_ASSERT( FunctionTable
->SetState
);
44 if ( FunctionTable
->SetState
== NULL
)
47 return MMSYSERR_NOTSUPPORTED
;
49 /* Try change state */
50 Result
= FunctionTable
->SetState(SoundDeviceInstance
, bStart
);
52 if ( MMSUCCESS(Result
) )
54 /* Get old audio stream state */
55 OldState
= SoundDeviceInstance
->bPaused
;
57 /* Store audio stream pause state */
58 SoundDeviceInstance
->bPaused
= !bStart
;
60 if (SoundDeviceInstance
->bPaused
== FALSE
&& OldState
== TRUE
)
62 InitiateSoundStreaming(SoundDeviceInstance
);
70 Call the client application when something interesting happens (MME API
71 defines "interesting things" as device open, close, and buffer
76 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
78 IN DWORD_PTR Parameter
)
80 SND_ASSERT( SoundDeviceInstance
);
82 SND_TRACE(L
"MME client callback - message %d, parameter %d\n",
86 if ( SoundDeviceInstance
->WinMM
.ClientCallback
)
88 DriverCallback(SoundDeviceInstance
->WinMM
.ClientCallback
,
89 HIWORD(SoundDeviceInstance
->WinMM
.Flags
),
90 SoundDeviceInstance
->WinMM
.Handle
,
92 SoundDeviceInstance
->WinMM
.ClientCallbackInstanceData
,
99 This is a helper function to alleviate some of the repetition involved with
100 implementing the various MME message functions.
103 MmeGetSoundDeviceCapabilities(
104 IN MMDEVICE_TYPE DeviceType
,
106 IN PVOID Capabilities
,
107 IN DWORD CapabilitiesSize
)
109 PSOUND_DEVICE SoundDevice
;
112 SND_TRACE(L
"MME *_GETCAPS for device %d of type %d\n", DeviceId
, DeviceType
);
114 /* FIXME: Validate device ID */
115 VALIDATE_MMSYS_PARAMETER( Capabilities
);
116 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
118 /* Our parameter checks are done elsewhere */
120 Result
= GetSoundDevice(DeviceType
, DeviceId
, &SoundDevice
);
122 if ( ! MMSUCCESS(Result
) )
125 return GetSoundDeviceCapabilities(SoundDevice
,
133 IN MMDEVICE_TYPE DeviceType
,
135 IN LPWAVEOPENDESC OpenParameters
,
137 OUT DWORD_PTR
* PrivateHandle
)
141 PSOUND_DEVICE SoundDevice
;
142 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
143 LPWAVEFORMATEX Format
= NULL
;
145 SND_TRACE(L
"Opening device");
147 VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType
) || IS_MIXER_DEVICE_TYPE(DeviceType
) || IS_MIDI_DEVICE_TYPE(DeviceType
) ); /* FIXME? wave in too? */
148 VALIDATE_MMSYS_PARAMETER( OpenParameters
);
150 Result
= GetSoundDevice(DeviceType
, DeviceId
, &SoundDevice
);
151 if ( ! MMSUCCESS(Result
) )
152 return TranslateInternalMmResult(Result
);
154 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
156 Format
= OpenParameters
->lpFormat
;
158 /* Does this device support the format? */
159 Result
= QueryWaveDeviceFormatSupport(SoundDevice
, Format
, sizeof(WAVEFORMATEX
));
160 if ( ! MMSUCCESS(Result
) )
162 SND_ERR(L
"Format not supported\n");
163 return TranslateInternalMmResult(Result
);
166 /* If the caller just wanted to know if a format is supported, end here */
167 if ( Flags
& WAVE_FORMAT_QUERY
)
168 return MMSYSERR_NOERROR
;
171 /* Check that winmm gave us a private handle to fill */
172 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
174 /* Create a sound device instance and open the sound device */
175 Result
= CreateSoundDeviceInstance(SoundDevice
, &SoundDeviceInstance
);
176 if ( ! MMSUCCESS(Result
) )
177 return TranslateInternalMmResult(Result
);
179 Result
= SetWaveDeviceFormat(SoundDeviceInstance
, DeviceId
, Format
, sizeof(WAVEFORMATEX
));
180 if ( ! MMSUCCESS(Result
) )
182 /* TODO: Destroy sound instance */
183 return TranslateInternalMmResult(Result
);
186 /* Store the device instance pointer in the private handle */
187 *PrivateHandle
= (DWORD_PTR
)SoundDeviceInstance
;
189 /* Store the additional information we were given - FIXME: Need flags! */
190 SetSoundDeviceInstanceMmeData(SoundDeviceInstance
,
191 (HDRVR
)OpenParameters
->hWave
, /* works because LPMIXEROPENDESC/etc has also the handle as first member */
192 OpenParameters
->dwCallback
,
193 OpenParameters
->dwInstance
,
196 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
|| DeviceType
== WAVE_IN_DEVICE_TYPE
||
197 DeviceType
== MIDI_OUT_DEVICE_TYPE
|| DeviceType
== MIDI_IN_DEVICE_TYPE
)
199 /* Let the application know the device is open */
201 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
203 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
205 else if (DeviceType
== MIDI_IN_DEVICE_TYPE
)
210 ReleaseEntrypointMutex(DeviceType
);
212 NotifyMmeClient(SoundDeviceInstance
,
216 AcquireEntrypointMutex(DeviceType
);
219 SND_TRACE(L
"device now open\n");
221 return MMSYSERR_NOERROR
;
226 IN DWORD_PTR PrivateHandle
)
229 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
230 PSOUND_DEVICE SoundDevice
;
231 MMDEVICE_TYPE DeviceType
;
234 SND_TRACE(L
"Closing wave device (WIDM_CLOSE / WODM_CLOSE)\n");
236 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
237 SoundDeviceInstance
= (PSOUND_DEVICE_INSTANCE
) PrivateHandle
;
239 if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance
) )
240 return MMSYSERR_INVALHANDLE
;
242 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
243 if ( ! MMSUCCESS(Result
) )
244 return TranslateInternalMmResult(Result
);
246 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
247 if ( ! MMSUCCESS(Result
) )
248 return TranslateInternalMmResult(Result
);
251 /* TODO: Check device is stopped! */
254 if (DeviceType
!= MIXER_DEVICE_TYPE
)
256 ReleaseEntrypointMutex(DeviceType
);
258 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
260 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
262 else if (DeviceType
== MIDI_IN_DEVICE_TYPE
)
264 else if (DeviceType
== MIDI_OUT_DEVICE_TYPE
)
267 /* TODO: Work with MIDI devices too */
268 NotifyMmeClient(SoundDeviceInstance
,
271 AcquireEntrypointMutex(DeviceType
);
274 Result
= DestroySoundDeviceInstance(SoundDeviceInstance
);
280 MmeResetWavePlayback(
281 IN DWORD_PTR PrivateHandle
)
283 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
285 SND_TRACE(L
"Resetting wave device (WODM_RESET)\n");
287 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
288 SoundDeviceInstance
= (PSOUND_DEVICE_INSTANCE
) PrivateHandle
;
290 return StopStreaming(SoundDeviceInstance
);
294 MmeGetDeviceInterfaceString(
295 IN MMDEVICE_TYPE DeviceType
,
298 IN DWORD InterfaceLength
,
299 OUT DWORD
* InterfaceSize
)
302 PSOUND_DEVICE SoundDevice
;
303 PMMFUNCTION_TABLE FunctionTable
;
305 Result
= GetSoundDevice(DeviceType
, DeviceId
, &SoundDevice
);
306 if ( ! MMSUCCESS(Result
) )
307 return TranslateInternalMmResult(Result
);
309 Result
= GetSoundDeviceFunctionTable(SoundDevice
, &FunctionTable
);
310 if ( ! MMSUCCESS(Result
) )
311 return TranslateInternalMmResult(Result
);
313 if ( FunctionTable
->GetDeviceInterfaceString
== NULL
)
315 /* querying device interface string / size not supported */
316 return MMSYSERR_NOTSUPPORTED
;
319 /* Call the driver */
320 Result
= FunctionTable
->GetDeviceInterfaceString(DeviceType
, DeviceId
, Interface
, InterfaceLength
, InterfaceSize
);
328 IN MMDEVICE_TYPE DeviceType
,
330 IN DWORD_PTR PrivateHandle
,
335 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
336 PSOUND_DEVICE SoundDevice
;
337 PMMFUNCTION_TABLE FunctionTable
;
339 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
340 SoundDeviceInstance
= (PSOUND_DEVICE_INSTANCE
) PrivateHandle
;
342 if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance
) )
343 return MMSYSERR_INVALHANDLE
;
345 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
346 if ( ! MMSUCCESS(Result
) )
347 return TranslateInternalMmResult(Result
);
349 if ( Size
!= sizeof(MMTIME
) )
350 return MMSYSERR_INVALPARAM
;
352 Result
= GetSoundDeviceFunctionTable(SoundDevice
, &FunctionTable
);
353 if ( ! MMSUCCESS(Result
) )
354 return TranslateInternalMmResult(Result
);
356 if ( FunctionTable
->GetPos
== NULL
)
358 /* This indicates bad practice, really! If you can open, why not close?! */
359 return MMSYSERR_NOTSUPPORTED
;
362 /* Call the driver */
363 Result
= FunctionTable
->GetPos(SoundDeviceInstance
, Time
);