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 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
,
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
* PrivateHandle
)
131 PSOUND_DEVICE SoundDevice
;
132 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
133 LPWAVEFORMATEX Format
;
135 SND_TRACE(L
"Opening wave device (WIDM_OPEN / WODM_OPEN)");
137 VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType
) ); /* FIXME? wave in too? */
138 VALIDATE_MMSYS_PARAMETER( OpenParameters
);
140 Format
= OpenParameters
->lpFormat
;
142 Result
= GetSoundDevice(DeviceType
, DeviceId
, &SoundDevice
);
143 if ( ! MMSUCCESS(Result
) )
144 return TranslateInternalMmResult(Result
);
146 /* Does this device support the format? */
147 Result
= QueryWaveDeviceFormatSupport(SoundDevice
, Format
, sizeof(WAVEFORMATEX
));
148 if ( ! MMSUCCESS(Result
) )
150 SND_ERR(L
"Format not supported\n");
151 return TranslateInternalMmResult(Result
);
154 /* If the caller just wanted to know if a format is supported, end here */
155 if ( Flags
& WAVE_FORMAT_QUERY
)
156 return MMSYSERR_NOERROR
;
158 /* Check that winmm gave us a private handle to fill */
159 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
161 /* Create a sound device instance and open the sound device */
162 Result
= CreateSoundDeviceInstance(SoundDevice
, &SoundDeviceInstance
);
163 if ( ! MMSUCCESS(Result
) )
164 return TranslateInternalMmResult(Result
);
166 Result
= SetWaveDeviceFormat(SoundDeviceInstance
, DeviceId
, Format
, sizeof(WAVEFORMATEX
));
167 if ( ! MMSUCCESS(Result
) )
169 /* TODO: Destroy sound instance */
170 return TranslateInternalMmResult(Result
);
173 /* Store the device instance pointer in the private handle - is DWORD safe here? */
174 *PrivateHandle
= (DWORD
) SoundDeviceInstance
;
176 /* Store the additional information we were given - FIXME: Need flags! */
177 SetSoundDeviceInstanceMmeData(SoundDeviceInstance
,
178 (HDRVR
)OpenParameters
->hWave
,
179 OpenParameters
->dwCallback
,
180 OpenParameters
->dwInstance
,
183 /* Let the application know the device is open */
184 ReleaseEntrypointMutex(DeviceType
);
185 NotifyMmeClient(SoundDeviceInstance
,
186 DeviceType
== WAVE_OUT_DEVICE_TYPE
? WOM_OPEN
: WIM_OPEN
,
189 AcquireEntrypointMutex(DeviceType
);
191 SND_TRACE(L
"Wave device now open\n");
193 return MMSYSERR_NOERROR
;
198 IN DWORD PrivateHandle
)
201 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
202 PSOUND_DEVICE SoundDevice
;
203 MMDEVICE_TYPE DeviceType
;
205 SND_TRACE(L
"Closing wave device (WIDM_CLOSE / WODM_CLOSE)\n");
207 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
208 SoundDeviceInstance
= (PSOUND_DEVICE_INSTANCE
) PrivateHandle
;
210 if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance
) )
211 return MMSYSERR_INVALHANDLE
;
213 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
214 if ( ! MMSUCCESS(Result
) )
215 return TranslateInternalMmResult(Result
);
217 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
218 if ( ! MMSUCCESS(Result
) )
219 return TranslateInternalMmResult(Result
);
222 /* TODO: Check device is stopped! */
224 ReleaseEntrypointMutex(DeviceType
);
225 /* TODO: Work with MIDI devices too */
226 NotifyMmeClient(SoundDeviceInstance
,
227 DeviceType
== WAVE_OUT_DEVICE_TYPE
? WOM_CLOSE
: WIM_CLOSE
,
229 AcquireEntrypointMutex(DeviceType
);
231 Result
= DestroySoundDeviceInstance(SoundDeviceInstance
);
237 MmeResetWavePlayback(
238 IN DWORD PrivateHandle
)
240 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
242 SND_TRACE(L
"Resetting wave device (WODM_RESET)\n");
244 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
245 SoundDeviceInstance
= (PSOUND_DEVICE_INSTANCE
) PrivateHandle
;
247 return StopStreaming(SoundDeviceInstance
);
251 MmeGetDeviceInterfaceString(
252 IN MMDEVICE_TYPE DeviceType
,
255 IN DWORD InterfaceLength
,
256 OUT DWORD
* InterfaceSize
)
259 PSOUND_DEVICE SoundDevice
;
260 PMMFUNCTION_TABLE FunctionTable
;
262 Result
= GetSoundDevice(DeviceType
, DeviceId
, &SoundDevice
);
263 if ( ! MMSUCCESS(Result
) )
264 return TranslateInternalMmResult(Result
);
266 Result
= GetSoundDeviceFunctionTable(SoundDevice
, &FunctionTable
);
267 if ( ! MMSUCCESS(Result
) )
268 return TranslateInternalMmResult(Result
);
270 if ( FunctionTable
->GetDeviceInterfaceString
== NULL
)
272 /* querying device interface string / size not supported */
273 return MMSYSERR_NOTSUPPORTED
;
276 /* Call the driver */
277 Result
= FunctionTable
->GetDeviceInterfaceString(DeviceType
, DeviceId
, Interface
, InterfaceLength
, InterfaceSize
);
285 IN MMDEVICE_TYPE DeviceType
,
287 IN DWORD PrivateHandle
,
292 PSOUND_DEVICE_INSTANCE SoundDeviceInstance
;
293 PSOUND_DEVICE SoundDevice
;
294 PMMFUNCTION_TABLE FunctionTable
;
296 VALIDATE_MMSYS_PARAMETER( PrivateHandle
);
297 SoundDeviceInstance
= (PSOUND_DEVICE_INSTANCE
) PrivateHandle
;
299 if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance
) )
300 return MMSYSERR_INVALHANDLE
;
302 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
303 if ( ! MMSUCCESS(Result
) )
304 return TranslateInternalMmResult(Result
);
306 if ( Size
!= sizeof(MMTIME
) )
307 return MMSYSERR_INVALPARAM
;
309 Result
= GetSoundDeviceFunctionTable(SoundDevice
, &FunctionTable
);
310 if ( ! MMSUCCESS(Result
) )
311 return TranslateInternalMmResult(Result
);
313 if ( FunctionTable
->GetPos
== NULL
)
315 /* This indicates bad practice, really! If you can open, why not close?! */
316 return MMSYSERR_NOTSUPPORTED
;
319 /* Call the driver */
320 Result
= FunctionTable
->GetPos(SoundDeviceInstance
, Time
);