ReactOS  0.4.14-dev-376-gaedba84
common.c
Go to the documentation of this file.
1 /*
2  *
3  * COPYRIGHT: See COPYING in the top level directory
4  * PROJECT: ReactOS Multimedia
5  * FILE: dll/win32/mmdrv/common.c
6  * PURPOSE: Multimedia User Mode Driver (Common functions)
7  * PROGRAMMER: Andrew Greenwood
8  * UPDATE HISTORY:
9  * Jan 14, 2007: Created
10  */
11 
12 #include "mmdrv.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /*
18  Translates errors to MMRESULT codes.
19 */
20 
23 {
24  switch ( error_code )
25  {
26  case NO_ERROR :
27  case ERROR_IO_PENDING :
28  return MMSYSERR_NOERROR;
29 
30  case ERROR_BUSY :
31  return MMSYSERR_ALLOCATED;
32 
33  case ERROR_NOT_SUPPORTED :
35  return MMSYSERR_NOTSUPPORTED;
36 
38  return MMSYSERR_NOMEM;
39 
40  case ERROR_ACCESS_DENIED :
41  return MMSYSERR_BADDEVICEID;
42 
44  return MMSYSERR_INVALPARAM;
45  };
46 
47  /* If all else fails, it's just a plain old error */
48 
49  return MMSYSERR_ERROR;
50 }
51 
52 
53 /*
54  Obtains a device count for a specific kind of device.
55 */
56 
57 DWORD
59 {
60  UINT index = 0;
61  HANDLE handle;
62 
63  /* Cycle through devices until an error occurs */
64 
66  {
68  index ++;
69  }
70 
71  DPRINT("Found %d devices of type %d\n", index, device_type);
72 
73  return index;
74 }
75 
76 
77 /*
78  Obtains device capabilities. This could either be done as individual
79  functions for wave, MIDI and aux, or like this. I chose this method as
80  it centralizes everything.
81 */
82 
83 DWORD
86  UINT device_id,
87  DWORD_PTR capabilities,
88  DWORD capabilities_size)
89 {
91  DWORD ioctl;
92  HANDLE handle;
93  DWORD bytes_returned;
94  BOOL device_io_result;
95 
96  ASSERT(capabilities);
97 
98  /* Choose the right IOCTL for the job */
99 
100  if ( IsWaveDevice(device_type) )
102  else if ( IsMidiDevice(device_type) )
104  else if ( IsAuxDevice(device_type) )
105  return MMSYSERR_NOTSUPPORTED; /* TODO */
106  else
107  return MMSYSERR_NOTSUPPORTED;
108 
110  device_id,
111  GENERIC_READ,
112  &handle);
113 
114  if ( result != MMSYSERR_NOERROR )
115  {
116  DPRINT("Failed to open kernel device\n");
117  return result;
118  }
119 
120  device_io_result = DeviceIoControl(handle,
121  ioctl,
122  NULL,
123  0,
124  (LPVOID) capabilities,
125  capabilities_size,
126  &bytes_returned,
127  NULL);
128 
129  /* Translate result */
130 
131  if ( device_io_result )
133  else
135 
136  /* Clean up and return */
137 
139 
140  return result;
141 }
142 
143 
144 /*
145  A wrapper around OpenKernelDevice that creates a session,
146  opens the kernel device, initializes session data and notifies
147  the client (application) that the device has been opened. Again,
148  this supports any device type and the only real difference is
149  the open descriptor.
150 */
151 
152 DWORD
155  UINT device_id,
156  PVOID open_descriptor,
157  DWORD flags,
158  DWORD_PTR private_handle)
159 {
160  SessionInfo* session_info;
162  DWORD message;
163 
164  /* This will automatically check for duplicate sessions */
165  result = CreateSession(device_type, device_id, &session_info);
166 
167  if ( result != MMSYSERR_NOERROR )
168  {
169  DPRINT("Couldn't allocate session info\n");
170  return result;
171  }
172 
174  device_id,
175  GENERIC_READ,
176  &session_info->kernel_device_handle);
177 
178  if ( result != MMSYSERR_NOERROR )
179  {
180  DPRINT("Failed to open kernel device\n");
181  DestroySession(session_info);
182  return result;
183  }
184 
185  /* Set common session data */
186 
187  session_info->flags = flags;
188 
189  /* Set wave/MIDI specific data */
190 
191  if ( IsWaveDevice(device_type) )
192  {
193  LPWAVEOPENDESC wave_open_desc = (LPWAVEOPENDESC) open_descriptor;
194  session_info->callback = wave_open_desc->dwCallback;
195  session_info->mme_wave_handle = wave_open_desc->hWave;
196  session_info->app_user_data = wave_open_desc->dwInstance;
197  }
198  else
199  {
200  DPRINT("Only wave devices are supported at present!\n");
201  DestroySession(session_info);
202  return MMSYSERR_NOTSUPPORTED;
203  }
204 
205  /* Start the processing thread */
206 
207  result = StartSessionThread(session_info);
208 
209  if ( result != MMSYSERR_NOERROR )
210  {
211  DestroySession(session_info);
212  return result;
213  }
214 
215  /* Store the session info */
216 
217  *((SessionInfo**)private_handle) = session_info;
218 
219  /* Send the right message */
220 
224  (device_type == MidiInDevice) ? MIM_OPEN : 0xFFFFFFFF;
225 
226  NotifyClient(session_info, message, 0, 0);
227 
228  return MMSYSERR_NOERROR;
229 }
230 
231 
232 /*
233  Attempts to close a device. This can fail if playback/recording has
234  not been stopped. We need to make sure it's safe to destroy the
235  session as well (mainly by killing the session thread.)
236 */
237 
238 DWORD
240  DWORD_PTR private_handle)
241 {
243  SessionInfo* session_info = (SessionInfo*) private_handle;
244  /* TODO: Maybe this is best off inside the playback thread? */
245 
246  ASSERT(session_info);
247 
248  result = CallSessionThread(session_info, WODM_CLOSE, 0);
249 
250  if ( result == MMSYSERR_NOERROR )
251  {
252  /* TODO: Wait for it to be safe to terminate */
253 
255 
256  DestroySession(session_info);
257  }
258 
259  return result;
260 }
261 
#define IsMidiDevice(devicetype)
Definition: mmdrv.h:53
Definition: tftpd.h:59
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define CloseHandle
Definition: compat.h:406
DWORD CloseDevice(DWORD_PTR private_handle)
Definition: common.c:239
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
DeviceType
Definition: mmdrv.h:41
DWORD dwCallback
Definition: mmddk.h:400
device_type
GLenum GLuint GLenum GLsizei const GLchar * message
Definition: glext.h:5579
VOID DestroySession(SessionInfo *session)
Definition: session.c:113
DWORD flags
Definition: mmdrv.h:153
void CloseKernelDevice(HANDLE device_handle)
Definition: kernel.c:132
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
UINT MMRESULT
Definition: mmsystem.h:962
#define ERROR_IO_PENDING
Definition: dderror.h:15
#define NO_ERROR
Definition: dderror.h:5
#define WOM_OPEN
Definition: mmsystem.h:181
DWORD_PTR app_user_data
Definition: mmdrv.h:150
#define ERROR_BUSY
Definition: dderror.h:12
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
BOOL NotifyClient(SessionInfo *session_info, DWORD message, DWORD_PTR parameter1, DWORD_PTR parameter2)
Definition: mme.c:25
#define IOCTL_MIDI_GET_CAPABILITIES
Definition: mmdef.h:69
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ioctl
Definition: wintirpc.h:60
static int error_code[8]
Definition: odbccp32.c:61
#define WIM_OPEN
Definition: mmsystem.h:184
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
GLuint index
Definition: glext.h:6031
#define IsAuxDevice(devicetype)
Definition: mmdrv.h:56
HWAVE hWave
Definition: mmddk.h:398
MMRESULT CreateSession(DeviceType device_type, UINT device_id, SessionInfo **session_info)
Definition: session.c:63
#define MIM_OPEN
Definition: mmsystem.h:241
#define MOM_OPEN
Definition: mmsystem.h:247
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define MMSYSERR_ERROR
Definition: mmsystem.h:97
#define MMSYSERR_ALLOCATED
Definition: mmsystem.h:100
MMRESULT OpenKernelDevice(DeviceType device_type, UINT device_id, DWORD access, HANDLE *handle)
Definition: kernel.c:84
unsigned long DWORD
Definition: ntddk_ex.h:95
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
GLbitfield flags
Definition: glext.h:7161
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
DWORD GetDeviceCapabilities(DeviceType device_type, UINT device_id, DWORD_PTR capabilities, DWORD capabilities_size)
Definition: common.c:84
MMRESULT ErrorToMmResult(UINT error_code)
Definition: common.c:22
#define index(s, c)
Definition: various.h:29
DWORD dwInstance
Definition: mmddk.h:401
#define MMSYSERR_BADDEVICEID
Definition: mmsystem.h:98
HANDLE kernel_device_handle
Definition: mmdrv.h:136
struct WAVEOPENDESC * LPWAVEOPENDESC
#define GENERIC_READ
Definition: compat.h:124
DWORD_PTR callback
Definition: mmdrv.h:151
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define WODM_CLOSE
Definition: mmddk.h:111
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
#define MMSYSERR_INVALPARAM
Definition: mmsystem.h:107
unsigned int UINT
Definition: ndis.h:50
HWAVE mme_wave_handle
Definition: mmdrv.h:142
DWORD GetDeviceCount(DeviceType device_type)
Definition: common.c:58
#define ERROR_NOT_SUPPORTED
Definition: compat.h:90
MMRESULT CallSessionThread(SessionInfo *session_info, ThreadFunction function, PVOID thread_parameter)
Definition: session.c:219
#define IOCTL_WAVE_GET_CAPABILITIES
Definition: mmdef.h:52
#define IsWaveDevice(devicetype)
Definition: mmdrv.h:50
DWORD OpenDevice(DeviceType device_type, UINT device_id, PVOID open_descriptor, DWORD flags, DWORD_PTR private_handle)
Definition: common.c:153
GLuint64EXT * result
Definition: glext.h:11304
MMRESULT StartSessionThread(SessionInfo *session_info)
Definition: session.c:154
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10