Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencommon.c
Go to the documentation of this file.
00001 /* 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS Multimedia 00005 * FILE: dll/win32/mmdrv/common.c 00006 * PURPOSE: Multimedia User Mode Driver (Common functions) 00007 * PROGRAMMER: Andrew Greenwood 00008 * UPDATE HISTORY: 00009 * Jan 14, 2007: Created 00010 */ 00011 00012 #include <mmdrv.h> 00013 00014 /* 00015 Translates errors to MMRESULT codes. 00016 */ 00017 00018 MMRESULT 00019 ErrorToMmResult(UINT error_code) 00020 { 00021 switch ( error_code ) 00022 { 00023 case NO_ERROR : 00024 case ERROR_IO_PENDING : 00025 return MMSYSERR_NOERROR; 00026 00027 case ERROR_BUSY : 00028 return MMSYSERR_ALLOCATED; 00029 00030 case ERROR_NOT_SUPPORTED : 00031 case ERROR_INVALID_FUNCTION : 00032 return MMSYSERR_NOTSUPPORTED; 00033 00034 case ERROR_NOT_ENOUGH_MEMORY : 00035 return MMSYSERR_NOMEM; 00036 00037 case ERROR_ACCESS_DENIED : 00038 return MMSYSERR_BADDEVICEID; 00039 00040 case ERROR_INSUFFICIENT_BUFFER : 00041 return MMSYSERR_INVALPARAM; 00042 }; 00043 00044 /* If all else fails, it's just a plain old error */ 00045 00046 return MMSYSERR_ERROR; 00047 } 00048 00049 00050 /* 00051 Obtains a device count for a specific kind of device. 00052 */ 00053 00054 DWORD 00055 GetDeviceCount(DeviceType device_type) 00056 { 00057 UINT index = 0; 00058 HANDLE handle; 00059 00060 /* Cycle through devices until an error occurs */ 00061 00062 while ( OpenKernelDevice(device_type, index, GENERIC_READ, &handle) == MMSYSERR_NOERROR ) 00063 { 00064 CloseHandle(handle); 00065 index ++; 00066 } 00067 00068 DPRINT("Found %d devices of type %d\n", index, device_type); 00069 00070 return index; 00071 } 00072 00073 00074 /* 00075 Obtains device capabilities. This could either be done as individual 00076 functions for wave, MIDI and aux, or like this. I chose this method as 00077 it centralizes everything. 00078 */ 00079 00080 DWORD 00081 GetDeviceCapabilities( 00082 DeviceType device_type, 00083 UINT device_id, 00084 DWORD_PTR capabilities, 00085 DWORD capabilities_size) 00086 { 00087 MMRESULT result; 00088 DWORD ioctl; 00089 HANDLE handle; 00090 DWORD bytes_returned; 00091 BOOL device_io_result; 00092 00093 ASSERT(capabilities); 00094 00095 /* Choose the right IOCTL for the job */ 00096 00097 if ( IsWaveDevice(device_type) ) 00098 ioctl = IOCTL_WAVE_GET_CAPABILITIES; 00099 else if ( IsMidiDevice(device_type) ) 00100 ioctl = IOCTL_MIDI_GET_CAPABILITIES; 00101 else if ( IsAuxDevice(device_type) ) 00102 return MMSYSERR_NOTSUPPORTED; /* TODO */ 00103 else 00104 return MMSYSERR_NOTSUPPORTED; 00105 00106 result = OpenKernelDevice(device_type, 00107 device_id, 00108 GENERIC_READ, 00109 &handle); 00110 00111 if ( result != MMSYSERR_NOERROR ) 00112 { 00113 DPRINT("Failed to open kernel device\n"); 00114 return result; 00115 } 00116 00117 device_io_result = DeviceIoControl(handle, 00118 ioctl, 00119 NULL, 00120 0, 00121 (LPVOID) capabilities, 00122 capabilities_size, 00123 &bytes_returned, 00124 NULL); 00125 00126 /* Translate result */ 00127 00128 if ( device_io_result ) 00129 result = MMSYSERR_NOERROR; 00130 else 00131 result = ErrorToMmResult(GetLastError()); 00132 00133 /* Clean up and return */ 00134 00135 CloseKernelDevice(handle); 00136 00137 return result; 00138 } 00139 00140 00141 /* 00142 A wrapper around OpenKernelDevice that creates a session, 00143 opens the kernel device, initializes session data and notifies 00144 the client (application) that the device has been opened. Again, 00145 this supports any device type and the only real difference is 00146 the open descriptor. 00147 */ 00148 00149 DWORD 00150 OpenDevice( 00151 DeviceType device_type, 00152 UINT device_id, 00153 PVOID open_descriptor, 00154 DWORD flags, 00155 DWORD_PTR private_handle) 00156 { 00157 SessionInfo* session_info; 00158 MMRESULT result; 00159 DWORD message; 00160 00161 /* This will automatically check for duplicate sessions */ 00162 result = CreateSession(device_type, device_id, &session_info); 00163 00164 if ( result != MMSYSERR_NOERROR ) 00165 { 00166 DPRINT("Couldn't allocate session info\n"); 00167 return result; 00168 } 00169 00170 result = OpenKernelDevice(device_type, 00171 device_id, 00172 GENERIC_READ, 00173 &session_info->kernel_device_handle); 00174 00175 if ( result != MMSYSERR_NOERROR ) 00176 { 00177 DPRINT("Failed to open kernel device\n"); 00178 DestroySession(session_info); 00179 return result; 00180 } 00181 00182 /* Set common session data */ 00183 00184 session_info->flags = flags; 00185 00186 /* Set wave/MIDI specific data */ 00187 00188 if ( IsWaveDevice(device_type) ) 00189 { 00190 LPWAVEOPENDESC wave_open_desc = (LPWAVEOPENDESC) open_descriptor; 00191 session_info->callback = wave_open_desc->dwCallback; 00192 session_info->mme_wave_handle = wave_open_desc->hWave; 00193 session_info->app_user_data = wave_open_desc->dwInstance; 00194 } 00195 else 00196 { 00197 DPRINT("Only wave devices are supported at present!\n"); 00198 DestroySession(session_info); 00199 return MMSYSERR_NOTSUPPORTED; 00200 } 00201 00202 /* Start the processing thread */ 00203 00204 result = StartSessionThread(session_info); 00205 00206 if ( result != MMSYSERR_NOERROR ) 00207 { 00208 DestroySession(session_info); 00209 return result; 00210 } 00211 00212 /* Store the session info */ 00213 00214 *((SessionInfo**)private_handle) = session_info; 00215 00216 /* Send the right message */ 00217 00218 message = (device_type == WaveOutDevice) ? WOM_OPEN : 00219 (device_type == WaveInDevice) ? WIM_OPEN : 00220 (device_type == MidiOutDevice) ? MOM_OPEN : 00221 (device_type == MidiInDevice) ? MIM_OPEN : 0xFFFFFFFF; 00222 00223 NotifyClient(session_info, message, 0, 0); 00224 00225 return MMSYSERR_NOERROR; 00226 } 00227 00228 00229 /* 00230 Attempts to close a device. This can fail if playback/recording has 00231 not been stopped. We need to make sure it's safe to destroy the 00232 session as well (mainly by killing the session thread.) 00233 */ 00234 00235 DWORD 00236 CloseDevice( 00237 DWORD_PTR private_handle) 00238 { 00239 MMRESULT result; 00240 SessionInfo* session_info = (SessionInfo*) private_handle; 00241 /* TODO: Maybe this is best off inside the playback thread? */ 00242 00243 ASSERT(session_info); 00244 00245 result = CallSessionThread(session_info, WODM_CLOSE, 0); 00246 00247 if ( result == MMSYSERR_NOERROR ) 00248 { 00249 /* TODO: Wait for it to be safe to terminate */ 00250 00251 CloseKernelDevice(session_info->kernel_device_handle); 00252 00253 DestroySession(session_info); 00254 } 00255 00256 return result; 00257 } 00258 Generated on Sun May 27 2012 04:24:41 for ReactOS by
1.7.6.1
|