ReactOS  0.4.14-dev-41-g31d7680
mmewrap.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/mmewrap.c
5  *
6  * PURPOSE: Interface between MME functions and MME Buddy's own.
7  *
8  * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
9 */
10 
11 #include "precomp.h"
12 
13 
14 /*
15  Sets the device into running or stopped state
16 */
17 
20  IN DWORD_PTR PrivateHandle,
21  IN BOOL bStart)
22 {
25  PSOUND_DEVICE SoundDevice;
26  PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
27  BOOL OldState;
28 
29  VALIDATE_MMSYS_PARAMETER( PrivateHandle );
30  SoundDeviceInstance = (PSOUND_DEVICE_INSTANCE) PrivateHandle;
31 
33 
34  Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
35  if ( ! MMSUCCESS(Result) )
37 
38  /* Get the function table, and validate it */
40  if ( ! MMSUCCESS(Result) )
42 
43  SND_ASSERT( FunctionTable->SetState );
44  if ( FunctionTable->SetState == NULL )
45  {
46  /* FIXME */
47  return MMSYSERR_NOTSUPPORTED;
48  }
49  /* Try change state */
50  Result = FunctionTable->SetState(SoundDeviceInstance, bStart);
51 
52  if ( MMSUCCESS(Result) )
53  {
54  /* Get old audio stream state */
55  OldState = SoundDeviceInstance->bPaused;
56 
57  /* Store audio stream pause state */
58  SoundDeviceInstance->bPaused = !bStart;
59 
60  if (SoundDeviceInstance->bPaused == FALSE && OldState)
61  {
62  InitiateSoundStreaming(SoundDeviceInstance);
63  }
64  }
65 
66  return Result;
67 }
68 
69 /*
70  Call the client application when something interesting happens (MME API
71  defines "interesting things" as device open, close, and buffer
72  completion.)
73 */
74 VOID
76  IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
77  IN UINT Message,
79 {
80  SND_ASSERT( SoundDeviceInstance );
81 
82  SND_TRACE(L"MME client callback - message %d, parameter %d\n",
83  (int) Message,
84  (int) Parameter);
85 
86  if ( SoundDeviceInstance->WinMM.ClientCallback )
87  {
88  DriverCallback(SoundDeviceInstance->WinMM.ClientCallback,
89  HIWORD(SoundDeviceInstance->WinMM.Flags),
90  SoundDeviceInstance->WinMM.Handle,
91  Message,
92  SoundDeviceInstance->WinMM.ClientCallbackInstanceData,
93  Parameter,
94  0);
95  }
96 }
97 
98 /*
99  This is a helper function to alleviate some of the repetition involved with
100  implementing the various MME message functions.
101 */
102 MMRESULT
105  IN DWORD DeviceId,
107  IN DWORD CapabilitiesSize)
108 {
109  PSOUND_DEVICE SoundDevice;
111 
112  SND_TRACE(L"MME *_GETCAPS for device %d of type %d\n", DeviceId, DeviceType);
113 
114  /* FIXME: Validate device ID */
117 
118  /* Our parameter checks are done elsewhere */
119 
120  Result = GetSoundDevice(DeviceType, DeviceId, &SoundDevice);
121 
122  if ( ! MMSUCCESS(Result) )
123  return Result;
124 
125  return GetSoundDeviceCapabilities(SoundDevice,
126  DeviceId,
127  Capabilities,
128  CapabilitiesSize);
129 }
130 
131 MMRESULT
134  IN UINT DeviceId,
135  IN LPWAVEOPENDESC OpenParameters,
136  IN DWORD Flags,
137  OUT DWORD_PTR* PrivateHandle)
138 {
140  UINT Message;
141  PSOUND_DEVICE SoundDevice;
142  PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
144 
145  SND_TRACE(L"Opening device");
146 
148  VALIDATE_MMSYS_PARAMETER( OpenParameters );
149 
150  Result = GetSoundDevice(DeviceType, DeviceId, &SoundDevice);
151  if ( ! MMSUCCESS(Result) )
153 
155  {
156  Format = OpenParameters->lpFormat;
157 
158  /* Does this device support the format? */
159  Result = QueryWaveDeviceFormatSupport(SoundDevice, Format, sizeof(WAVEFORMATEX));
160  if ( ! MMSUCCESS(Result) )
161  {
162  SND_ERR(L"Format not supported\n");
164  }
165 
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;
169  }
170 
171  /* Check that winmm gave us a private handle to fill */
172  VALIDATE_MMSYS_PARAMETER( PrivateHandle );
173 
174  /* Create a sound device instance and open the sound device */
175  Result = CreateSoundDeviceInstance(SoundDevice, &SoundDeviceInstance);
176  if ( ! MMSUCCESS(Result) )
178 
179  Result = SetWaveDeviceFormat(SoundDeviceInstance, DeviceId, Format, sizeof(WAVEFORMATEX));
180  if ( ! MMSUCCESS(Result) )
181  {
182  /* TODO: Destroy sound instance */
184  }
185 
186  /* Store the device instance pointer in the private handle */
187  *PrivateHandle = (DWORD_PTR)SoundDeviceInstance;
188 
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,
194  Flags);
195 
198  {
199  /* Let the application know the device is open */
200 
202  Message = WOM_OPEN;
203  else if (DeviceType == WAVE_IN_DEVICE_TYPE)
204  Message = WIM_OPEN;
205  else if (DeviceType == MIDI_IN_DEVICE_TYPE)
206  Message = MIM_OPEN;
207  else
208  Message = MOM_OPEN;
209 
211 
212  NotifyMmeClient(SoundDeviceInstance,
213  Message,
214  0);
215 
217  }
218 
219  SND_TRACE(L"device now open\n");
220 
221  return MMSYSERR_NOERROR;
222 }
223 
224 MMRESULT
226  IN DWORD_PTR PrivateHandle)
227 {
229  PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
230  PSOUND_DEVICE SoundDevice;
232  UINT Message = 0;
233 
234  SND_TRACE(L"Closing wave device (WIDM_CLOSE / WODM_CLOSE)\n");
235 
236  VALIDATE_MMSYS_PARAMETER( PrivateHandle );
237  SoundDeviceInstance = (PSOUND_DEVICE_INSTANCE) PrivateHandle;
238 
239  if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance) )
240  return MMSYSERR_INVALHANDLE;
241 
242  Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
243  if ( ! MMSUCCESS(Result) )
245 
246  Result = GetSoundDeviceType(SoundDevice, &DeviceType);
247  if ( ! MMSUCCESS(Result) )
249 
250 
251  /* TODO: Check device is stopped! */
252 
253 
255  {
257 
259  Message = WOM_CLOSE;
260  else if (DeviceType == WAVE_IN_DEVICE_TYPE)
261  Message = WIM_CLOSE;
262  else if (DeviceType == MIDI_IN_DEVICE_TYPE)
263  Message = MIM_CLOSE;
264  else if (DeviceType == MIDI_OUT_DEVICE_TYPE)
265  Message = MOM_CLOSE;
266 
267  /* TODO: Work with MIDI devices too */
268  NotifyMmeClient(SoundDeviceInstance,
269  Message,
270  0);
272  }
273 
274  Result = DestroySoundDeviceInstance(SoundDeviceInstance);
275 
276  return Result;
277 }
278 
279 MMRESULT
281  IN DWORD_PTR PrivateHandle)
282 {
283  PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
284 
285  SND_TRACE(L"Resetting wave device (WODM_RESET)\n");
286 
287  VALIDATE_MMSYS_PARAMETER( PrivateHandle );
288  SoundDeviceInstance = (PSOUND_DEVICE_INSTANCE) PrivateHandle;
289 
290  return StopStreaming(SoundDeviceInstance);
291 }
292 
293 MMRESULT
296  IN DWORD DeviceId,
298  IN DWORD InterfaceLength,
299  OUT DWORD * InterfaceSize)
300 {
302  PSOUND_DEVICE SoundDevice;
304 
305  Result = GetSoundDevice(DeviceType, DeviceId, &SoundDevice);
306  if ( ! MMSUCCESS(Result) )
308 
310  if ( ! MMSUCCESS(Result) )
312 
313  if ( FunctionTable->GetDeviceInterfaceString == NULL )
314  {
315  /* querying device interface string / size not supported */
316  return MMSYSERR_NOTSUPPORTED;
317  }
318 
319  /* Call the driver */
320  Result = FunctionTable->GetDeviceInterfaceString(DeviceType, DeviceId, Interface, InterfaceLength, InterfaceSize);
321 
322  return Result;
323 }
324 
325 
326 MMRESULT
329  IN DWORD DeviceId,
330  IN DWORD_PTR PrivateHandle,
331  IN MMTIME* Time,
332  IN DWORD Size)
333 {
335  PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
336  PSOUND_DEVICE SoundDevice;
338 
339  VALIDATE_MMSYS_PARAMETER( PrivateHandle );
340  SoundDeviceInstance = (PSOUND_DEVICE_INSTANCE) PrivateHandle;
341 
342  if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance) )
343  return MMSYSERR_INVALHANDLE;
344 
345  Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
346  if ( ! MMSUCCESS(Result) )
348 
349  if ( Size != sizeof(MMTIME) )
350  return MMSYSERR_INVALPARAM;
351 
353  if ( ! MMSUCCESS(Result) )
355 
356  if ( FunctionTable->GetPos == NULL )
357  {
358  /* This indicates bad practice, really! If you can open, why not close?! */
359  return MMSYSERR_NOTSUPPORTED;
360  }
361 
362  /* Call the driver */
363  Result = FunctionTable->GetPos(SoundDeviceInstance, Time);
364 
365  return Result;
366 }
367 
#define IN
Definition: typedefs.h:38
#define WAVE_FORMAT_QUERY
Definition: mmsystem.h:188
VOID InitiateSoundStreaming(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
Definition: streaming.c:383
#define DWORD_PTR
Definition: treelist.c:76
#define MMSUCCESS(result)
Definition: mmebuddy.h:80
MMRESULT MmeOpenDevice(IN MMDEVICE_TYPE DeviceType, IN UINT DeviceId, IN LPWAVEOPENDESC OpenParameters, IN DWORD Flags, OUT DWORD_PTR *PrivateHandle)
Definition: mmewrap.c:132
DeviceType
Definition: mmdrv.h:41
MMRESULT SetWaveDeviceFormat(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN DWORD DeviceId, IN LPWAVEFORMATEX Format, IN DWORD FormatSize)
Definition: format.c:49
MMRESULT StopStreaming(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
Definition: streaming.c:334
#define MIM_CLOSE
Definition: mmsystem.h:242
MMRESULT TranslateInternalMmResult(IN MMRESULT Result)
Definition: utility.c:132
UINT MMRESULT
Definition: mmsystem.h:962
MaybeUInt64 bStart[BZ_MAX_HANDLED_BLOCKS]
Definition: bzip2recover.c:296
#define IS_MIDI_DEVICE_TYPE(x)
Definition: sndtypes.h:49
#define MMSYSERR_INVALHANDLE
Definition: mmsystem.h:101
_In_ PVOID Parameter
Definition: ldrtypes.h:240
MMRESULT QueryWaveDeviceFormatSupport(IN PSOUND_DEVICE SoundDevice, IN LPWAVEFORMATEX Format, IN DWORD FormatSize)
Definition: format.c:14
MMRESULT GetSoundDevice(IN MMDEVICE_TYPE DeviceType, IN DWORD DeviceIndex, OUT PSOUND_DEVICE *Device)
Definition: devicelist.c:289
#define WOM_OPEN
Definition: mmsystem.h:181
MMRESULT SetSoundDeviceInstanceMmeData(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN HDRVR MmeHandle, IN DWORD_PTR ClientCallback, IN DWORD_PTR ClientCallbackData, IN DWORD Flags)
MMRESULT MmeResetWavePlayback(IN DWORD_PTR PrivateHandle)
Definition: mmewrap.c:280
#define VALIDATE_MMSYS_PARAMETER(parameter_condition)
Definition: mmebuddy.h:71
struct _SOUND_DEVICE_INSTANCE * PSOUND_DEVICE_INSTANCE
UCHAR MMDEVICE_TYPE
Definition: mmebuddy.h:88
MMRESULT GetSoundDeviceFunctionTable(IN PSOUND_DEVICE SoundDevice, OUT PMMFUNCTION_TABLE *FunctionTable)
Definition: functiontable.c:47
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define WOM_CLOSE
Definition: mmsystem.h:182
#define WIM_CLOSE
Definition: mmsystem.h:185
_Must_inspect_result_ typedef _Out_ PHIDP_CAPS Capabilities
Definition: hidclass.h:103
unsigned int BOOL
Definition: ntddk_ex.h:94
VOID AcquireEntrypointMutex(IN MMDEVICE_TYPE DeviceType)
Definition: reentrancy.c:75
#define WIM_OPEN
Definition: mmsystem.h:184
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
MMRESULT CreateSoundDeviceInstance(IN PSOUND_DEVICE SoundDevice, OUT PSOUND_DEVICE_INSTANCE *SoundDeviceInstance)
#define IS_WAVE_DEVICE_TYPE(x)
Definition: sndtypes.h:46
BOOLEAN IsValidSoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
MMRESULT MmeGetSoundDeviceCapabilities(IN MMDEVICE_TYPE DeviceType, IN DWORD DeviceId, IN PVOID Capabilities, IN DWORD CapabilitiesSize)
Definition: mmewrap.c:103
IN PVOID IN PVOID IN USHORT IN USHORT IN PINTERFACE Interface
Definition: pci.h:359
#define MIM_OPEN
Definition: mmsystem.h:241
#define MOM_OPEN
Definition: mmsystem.h:247
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define SND_ERR(...)
unsigned long DWORD
Definition: ntddk_ex.h:95
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
MMRESULT MmeGetDeviceInterfaceString(IN MMDEVICE_TYPE DeviceType, IN DWORD DeviceId, IN LPWSTR Interface, IN DWORD InterfaceLength, OUT DWORD *InterfaceSize)
Definition: mmewrap.c:294
CHAR Message[80]
Definition: alive.c:5
#define MOM_CLOSE
Definition: mmsystem.h:248
MMRESULT DestroySoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
static const WCHAR L[]
Definition: oid.c:1250
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
uint32_t DWORD_PTR
Definition: typedefs.h:63
MMRESULT MmeGetPosition(IN MMDEVICE_TYPE DeviceType, IN DWORD DeviceId, IN DWORD_PTR PrivateHandle, IN MMTIME *Time, IN DWORD Size)
Definition: mmewrap.c:327
MMRESULT MmeSetState(IN DWORD_PTR PrivateHandle, IN BOOL bStart)
Definition: mmewrap.c:19
MMRESULT MmeCloseDevice(IN DWORD_PTR PrivateHandle)
Definition: mmewrap.c:225
#define IS_MIXER_DEVICE_TYPE(x)
Definition: sndtypes.h:55
MMRESULT GetSoundDeviceType(IN PSOUND_DEVICE SoundDevice, OUT PMMDEVICE_TYPE DeviceType)
Definition: devicelist.c:346
#define MMSYSERR_INVALPARAM
Definition: mmsystem.h:107
unsigned int UINT
Definition: ndis.h:50
#define IS_VALID_SOUND_DEVICE_TYPE(x)
Definition: sndtypes.h:43
#define OUT
Definition: typedefs.h:39
VOID ReleaseEntrypointMutex(IN MMDEVICE_TYPE DeviceType)
Definition: reentrancy.c:92
#define HIWORD(l)
Definition: typedefs.h:246
static WLX_DISPATCH_VERSION_1_4 FunctionTable
Definition: wlx.c:736
VOID NotifyMmeClient(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN UINT Message, IN DWORD_PTR Parameter)
Definition: mmewrap.c:75
MMRESULT GetSoundDeviceFromInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, OUT PSOUND_DEVICE *SoundDevice)
BOOL WINAPI DriverCallback(DWORD dwCallBack, UINT uFlags, HDRVR hDev, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
WCHAR * LPWSTR
Definition: xmlstorage.h:184
static PLARGE_INTEGER Time
Definition: time.c:105
#define SND_TRACE(...)
MMRESULT GetSoundDeviceCapabilities(IN PSOUND_DEVICE SoundDevice, IN DWORD DeviceId, OUT PVOID Capabilities, IN DWORD CapabilitiesSize)
Definition: capabilities.c:24