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
18 Translates errors to MMRESULT codes.
22 ErrorToMmResult(UINT error_code
)
27 case ERROR_IO_PENDING
:
28 return MMSYSERR_NOERROR
;
31 return MMSYSERR_ALLOCATED
;
33 case ERROR_NOT_SUPPORTED
:
34 case ERROR_INVALID_FUNCTION
:
35 return MMSYSERR_NOTSUPPORTED
;
37 case ERROR_NOT_ENOUGH_MEMORY
:
38 return MMSYSERR_NOMEM
;
40 case ERROR_ACCESS_DENIED
:
41 return MMSYSERR_BADDEVICEID
;
43 case ERROR_INSUFFICIENT_BUFFER
:
44 return MMSYSERR_INVALPARAM
;
47 /* If all else fails, it's just a plain old error */
49 return MMSYSERR_ERROR
;
54 Obtains a device count for a specific kind of device.
58 GetDeviceCount(DeviceType device_type
)
63 /* Cycle through devices until an error occurs */
65 while ( OpenKernelDevice(device_type
, index
, GENERIC_READ
, &handle
) == MMSYSERR_NOERROR
)
71 DPRINT("Found %d devices of type %d\n", index
, device_type
);
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.
84 GetDeviceCapabilities(
85 DeviceType device_type
,
87 DWORD_PTR capabilities
,
88 DWORD capabilities_size
)
94 BOOL device_io_result
;
98 /* Choose the right IOCTL for the job */
100 if ( IsWaveDevice(device_type
) )
101 ioctl
= IOCTL_WAVE_GET_CAPABILITIES
;
102 else if ( IsMidiDevice(device_type
) )
103 ioctl
= IOCTL_MIDI_GET_CAPABILITIES
;
104 else if ( IsAuxDevice(device_type
) )
105 return MMSYSERR_NOTSUPPORTED
; /* TODO */
107 return MMSYSERR_NOTSUPPORTED
;
109 result
= OpenKernelDevice(device_type
,
114 if ( result
!= MMSYSERR_NOERROR
)
116 DPRINT("Failed to open kernel device\n");
120 device_io_result
= DeviceIoControl(handle
,
124 (LPVOID
) capabilities
,
129 /* Translate result */
131 if ( device_io_result
)
132 result
= MMSYSERR_NOERROR
;
134 result
= ErrorToMmResult(GetLastError());
136 /* Clean up and return */
138 CloseKernelDevice(handle
);
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
154 DeviceType device_type
,
156 PVOID open_descriptor
,
158 DWORD_PTR private_handle
)
160 SessionInfo
* session_info
;
164 /* This will automatically check for duplicate sessions */
165 result
= CreateSession(device_type
, device_id
, &session_info
);
167 if ( result
!= MMSYSERR_NOERROR
)
169 DPRINT("Couldn't allocate session info\n");
173 result
= OpenKernelDevice(device_type
,
176 &session_info
->kernel_device_handle
);
178 if ( result
!= MMSYSERR_NOERROR
)
180 DPRINT("Failed to open kernel device\n");
181 DestroySession(session_info
);
185 /* Set common session data */
187 session_info
->flags
= flags
;
189 /* Set wave/MIDI specific data */
191 if ( IsWaveDevice(device_type
) )
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
;
200 DPRINT("Only wave devices are supported at present!\n");
201 DestroySession(session_info
);
202 return MMSYSERR_NOTSUPPORTED
;
205 /* Start the processing thread */
207 result
= StartSessionThread(session_info
);
209 if ( result
!= MMSYSERR_NOERROR
)
211 DestroySession(session_info
);
215 /* Store the session info */
217 *((SessionInfo
**)private_handle
) = session_info
;
219 /* Send the right message */
221 message
= (device_type
== WaveOutDevice
) ? WOM_OPEN
:
222 (device_type
== WaveInDevice
) ? WIM_OPEN
:
223 (device_type
== MidiOutDevice
) ? MOM_OPEN
:
224 (device_type
== MidiInDevice
) ? MIM_OPEN
: 0xFFFFFFFF;
226 NotifyClient(session_info
, message
, 0, 0);
228 return MMSYSERR_NOERROR
;
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.)
240 DWORD_PTR private_handle
)
243 SessionInfo
* session_info
= (SessionInfo
*) private_handle
;
244 /* TODO: Maybe this is best off inside the playback thread? */
246 ASSERT(session_info
);
248 result
= CallSessionThread(session_info
, WODM_CLOSE
, 0);
250 if ( result
== MMSYSERR_NOERROR
)
252 /* TODO: Wait for it to be safe to terminate */
254 CloseKernelDevice(session_info
->kernel_device_handle
);
256 DestroySession(session_info
);