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
9 * Jan 14, 2007: Created
15 Translates errors to MMRESULT codes.
19 ErrorToMmResult(UINT error_code
)
24 case ERROR_IO_PENDING
:
25 return MMSYSERR_NOERROR
;
28 return MMSYSERR_ALLOCATED
;
30 case ERROR_NOT_SUPPORTED
:
31 case ERROR_INVALID_FUNCTION
:
32 return MMSYSERR_NOTSUPPORTED
;
34 case ERROR_NOT_ENOUGH_MEMORY
:
35 return MMSYSERR_NOMEM
;
37 case ERROR_ACCESS_DENIED
:
38 return MMSYSERR_BADDEVICEID
;
40 case ERROR_INSUFFICIENT_BUFFER
:
41 return MMSYSERR_INVALPARAM
;
44 /* If all else fails, it's just a plain old error */
46 return MMSYSERR_ERROR
;
51 Obtains a device count for a specific kind of device.
55 GetDeviceCount(DeviceType device_type
)
60 /* Cycle through devices until an error occurs */
62 while ( OpenKernelDevice(device_type
, index
, GENERIC_READ
, &handle
) == MMSYSERR_NOERROR
)
68 DPRINT("Found %d devices of type %d\n", index
, device_type
);
75 Obtains device capabilities. This could either be done as individual
76 functions for wave, MIDI and aux, or like this. I chose this method as
77 it centralizes everything.
81 GetDeviceCapabilities(
82 DeviceType device_type
,
84 DWORD_PTR capabilities
,
85 DWORD capabilities_size
)
91 BOOL device_io_result
;
95 /* Choose the right IOCTL for the job */
97 if ( IsWaveDevice(device_type
) )
98 ioctl
= IOCTL_WAVE_GET_CAPABILITIES
;
99 else if ( IsMidiDevice(device_type
) )
100 ioctl
= IOCTL_MIDI_GET_CAPABILITIES
;
101 else if ( IsAuxDevice(device_type
) )
102 return MMSYSERR_NOTSUPPORTED
; /* TODO */
104 return MMSYSERR_NOTSUPPORTED
;
106 result
= OpenKernelDevice(device_type
,
111 if ( result
!= MMSYSERR_NOERROR
)
113 DPRINT("Failed to open kernel device\n");
117 device_io_result
= DeviceIoControl(handle
,
121 (LPVOID
) capabilities
,
126 /* Translate result */
128 if ( device_io_result
)
129 result
= MMSYSERR_NOERROR
;
131 result
= ErrorToMmResult(GetLastError());
133 /* Clean up and return */
135 CloseKernelDevice(handle
);
142 A wrapper around OpenKernelDevice that creates a session,
143 opens the kernel device, initializes session data and notifies
144 the client (application) that the device has been opened. Again,
145 this supports any device type and the only real difference is
151 DeviceType device_type
,
153 PVOID open_descriptor
,
155 DWORD_PTR private_handle
)
157 SessionInfo
* session_info
;
161 /* This will automatically check for duplicate sessions */
162 result
= CreateSession(device_type
, device_id
, &session_info
);
164 if ( result
!= MMSYSERR_NOERROR
)
166 DPRINT("Couldn't allocate session info\n");
170 result
= OpenKernelDevice(device_type
,
173 &session_info
->kernel_device_handle
);
175 if ( result
!= MMSYSERR_NOERROR
)
177 DPRINT("Failed to open kernel device\n");
178 DestroySession(session_info
);
182 /* Set common session data */
184 session_info
->flags
= flags
;
186 /* Set wave/MIDI specific data */
188 if ( IsWaveDevice(device_type
) )
190 LPWAVEOPENDESC wave_open_desc
= (LPWAVEOPENDESC
) open_descriptor
;
191 session_info
->callback
= wave_open_desc
->dwCallback
;
192 session_info
->mme_wave_handle
= wave_open_desc
->hWave
;
193 session_info
->app_user_data
= wave_open_desc
->dwInstance
;
197 DPRINT("Only wave devices are supported at present!\n");
198 DestroySession(session_info
);
199 return MMSYSERR_NOTSUPPORTED
;
202 /* Start the processing thread */
204 result
= StartSessionThread(session_info
);
206 if ( result
!= MMSYSERR_NOERROR
)
208 DestroySession(session_info
);
212 /* Store the session info */
214 *((SessionInfo
**)private_handle
) = session_info
;
216 /* Send the right message */
218 message
= (device_type
== WaveOutDevice
) ? WOM_OPEN
:
219 (device_type
== WaveInDevice
) ? WIM_OPEN
:
220 (device_type
== MidiOutDevice
) ? MOM_OPEN
:
221 (device_type
== MidiInDevice
) ? MIM_OPEN
: 0xFFFFFFFF;
223 NotifyClient(session_info
, message
, 0, 0);
225 return MMSYSERR_NOERROR
;
230 Attempts to close a device. This can fail if playback/recording has
231 not been stopped. We need to make sure it's safe to destroy the
232 session as well (mainly by killing the session thread.)
237 DWORD_PTR private_handle
)
240 SessionInfo
* session_info
= (SessionInfo
*) private_handle
;
241 /* TODO: Maybe this is best off inside the playback thread? */
243 ASSERT(session_info
);
245 result
= CallSessionThread(session_info
, WODM_CLOSE
, 0);
247 if ( result
== MMSYSERR_NOERROR
)
249 /* TODO: Wait for it to be safe to terminate */
251 CloseKernelDevice(session_info
->kernel_device_handle
);
253 DestroySession(session_info
);