ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

common.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.