Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendeviceinstance.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Sound System "MME Buddy" Library 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: lib/drivers/sound/mmebuddy/deviceinstance.c 00005 * 00006 * PURPOSE: Manages instances of sound devices. 00007 * 00008 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) 00009 */ 00010 00011 #include "precomp.h" 00012 00013 /* 00014 Restrain ourselves from flooding the kernel device! 00015 */ 00016 00017 #define SOUND_KERNEL_BUFFER_COUNT 10 00018 #define SOUND_KERNEL_BUFFER_SIZE 16384 00019 00020 MMRESULT 00021 AllocateSoundDeviceInstance( 00022 OUT PSOUND_DEVICE_INSTANCE* SoundDeviceInstance) 00023 { 00024 PSOUND_DEVICE_INSTANCE NewInstance; 00025 00026 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance ); 00027 00028 /* Allocate memory for the new instance */ 00029 NewInstance = AllocateStruct(SOUND_DEVICE_INSTANCE); 00030 00031 if ( ! NewInstance ) 00032 return MMSYSERR_NOMEM; 00033 00034 /* Use default frame size */ 00035 NewInstance->FrameSize = SOUND_KERNEL_BUFFER_SIZE; 00036 /* Use default buffer count */ 00037 NewInstance->BufferCount = SOUND_KERNEL_BUFFER_COUNT; 00038 00039 /* Provide the caller with the new instance pointer */ 00040 *SoundDeviceInstance = NewInstance; 00041 00042 return MMSYSERR_NOERROR; 00043 } 00044 00045 VOID 00046 FreeSoundDeviceInstance( 00047 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance) 00048 { 00049 /* 00050 Device is marked as invalid by now, but we can still do some sanity 00051 checking. 00052 */ 00053 SND_ASSERT( SoundDeviceInstance->Thread == NULL ); 00054 00055 ZeroMemory(SoundDeviceInstance, sizeof(SOUND_DEVICE_INSTANCE)); 00056 FreeMemory(SoundDeviceInstance); 00057 } 00058 00059 BOOLEAN 00060 IsValidSoundDeviceInstance( 00061 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance) 00062 { 00063 PSOUND_DEVICE SoundDevice; 00064 PSOUND_DEVICE_INSTANCE CurrentInstance; 00065 00066 if ( ! SoundDeviceInstance ) 00067 return FALSE; 00068 00069 /* GetSoundDeviceFromInstance would send us into a recursive loop... */ 00070 SoundDevice = SoundDeviceInstance->Device; 00071 SND_ASSERT(SoundDevice); 00072 00073 CurrentInstance = SoundDevice->HeadInstance; 00074 00075 while ( CurrentInstance ) 00076 { 00077 if ( CurrentInstance == SoundDeviceInstance ) 00078 return TRUE; 00079 00080 CurrentInstance = CurrentInstance->Next; 00081 } 00082 00083 return FALSE; 00084 } 00085 00086 MMRESULT 00087 ListSoundDeviceInstance( 00088 IN PSOUND_DEVICE SoundDevice, 00089 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance) 00090 { 00091 VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) ); 00092 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance ); 00093 00094 SND_TRACE(L"Listing sound device instance\n"); 00095 00096 if ( ! SoundDevice->HeadInstance ) 00097 { 00098 /* First entry - assign to head and tail */ 00099 SoundDevice->HeadInstance = SoundDeviceInstance; 00100 SoundDevice->TailInstance = SoundDeviceInstance; 00101 } 00102 else 00103 { 00104 /* Attach to the end */ 00105 SoundDevice->TailInstance->Next = SoundDeviceInstance; 00106 SoundDevice->TailInstance = SoundDeviceInstance; 00107 } 00108 00109 return MMSYSERR_NOERROR; 00110 } 00111 00112 MMRESULT 00113 UnlistSoundDeviceInstance( 00114 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance) 00115 { 00116 MMRESULT Result; 00117 PSOUND_DEVICE SoundDevice; 00118 PSOUND_DEVICE_INSTANCE CurrentInstance, PreviousInstance; 00119 00120 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) ); 00121 00122 SND_TRACE(L"Unlisting sound device instance\n"); 00123 00124 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); 00125 SND_ASSERT( MMSUCCESS(Result) ); 00126 if ( ! MMSUCCESS(Result) ) 00127 return TranslateInternalMmResult(Result); 00128 00129 PreviousInstance = NULL; 00130 CurrentInstance = SoundDevice->HeadInstance; 00131 00132 while ( CurrentInstance ) 00133 { 00134 if ( CurrentInstance == SoundDeviceInstance ) 00135 { 00136 if ( ! PreviousInstance ) 00137 { 00138 /* This is the head node */ 00139 SoundDevice->HeadInstance = SoundDevice->HeadInstance->Next; 00140 } 00141 else 00142 { 00143 /* There are nodes before this one - cut ours out */ 00144 PreviousInstance->Next = CurrentInstance->Next; 00145 } 00146 00147 if ( ! CurrentInstance->Next ) 00148 { 00149 /* This is the tail node */ 00150 SoundDevice->TailInstance = PreviousInstance; 00151 } 00152 } 00153 00154 PreviousInstance = CurrentInstance; 00155 CurrentInstance = CurrentInstance->Next; 00156 } 00157 00158 return MMSYSERR_NOERROR; 00159 } 00160 00161 MMRESULT 00162 CreateSoundDeviceInstance( 00163 IN PSOUND_DEVICE SoundDevice, 00164 OUT PSOUND_DEVICE_INSTANCE* SoundDeviceInstance) 00165 { 00166 MMRESULT Result; 00167 PMMFUNCTION_TABLE FunctionTable; 00168 00169 SND_TRACE(L"Creating a sound device instance\n"); 00170 00171 VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) ); 00172 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance != NULL ); 00173 00174 Result = AllocateSoundDeviceInstance(SoundDeviceInstance); 00175 00176 if ( ! MMSUCCESS(Result) ) 00177 return TranslateInternalMmResult(Result); 00178 00179 /* Get the "open" routine from the function table, and validate it */ 00180 Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); 00181 if ( ! MMSUCCESS(Result) ) 00182 { 00183 FreeSoundDeviceInstance(*SoundDeviceInstance); 00184 return TranslateInternalMmResult(Result); 00185 } 00186 00187 if ( FunctionTable->Open == NULL ) 00188 { 00189 FreeSoundDeviceInstance(*SoundDeviceInstance); 00190 return MMSYSERR_NOTSUPPORTED; 00191 } 00192 00193 /* Set up the members of the structure */ 00194 (*SoundDeviceInstance)->Next = NULL; 00195 (*SoundDeviceInstance)->Device = SoundDevice; 00196 (*SoundDeviceInstance)->Handle = NULL; 00197 (*SoundDeviceInstance)->Thread = NULL; 00198 00199 (*SoundDeviceInstance)->WinMM.Handle = INVALID_HANDLE_VALUE; 00200 (*SoundDeviceInstance)->WinMM.ClientCallback = 0; 00201 (*SoundDeviceInstance)->WinMM.ClientCallbackInstanceData = 0; 00202 (*SoundDeviceInstance)->WinMM.Flags = 0; 00203 00204 /* Initialise the members of the struct used by the sound thread */ 00205 (*SoundDeviceInstance)->HeadWaveHeader = NULL; 00206 (*SoundDeviceInstance)->TailWaveHeader = NULL; 00207 00208 (*SoundDeviceInstance)->OutstandingBuffers = 0; 00209 00210 (*SoundDeviceInstance)->LoopsRemaining = 0; 00211 00212 /* Create the streaming thread (TODO - is this for wave only?) */ 00213 Result = CreateSoundThread(&(*SoundDeviceInstance)->Thread); 00214 if ( ! MMSUCCESS(Result) ) 00215 { 00216 FreeSoundDeviceInstance(*SoundDeviceInstance); 00217 return TranslateInternalMmResult(Result); 00218 } 00219 00220 /* Add the instance to the list */ 00221 Result = ListSoundDeviceInstance(SoundDevice, *SoundDeviceInstance); 00222 if ( ! MMSUCCESS(Result) ) 00223 { 00224 FreeSoundDeviceInstance(*SoundDeviceInstance); 00225 return TranslateInternalMmResult(Result); 00226 } 00227 00228 /* Try and open the device */ 00229 Result = FunctionTable->Open(SoundDevice, (&(*SoundDeviceInstance)->Handle)); 00230 if ( ! MMSUCCESS(Result) ) 00231 { 00232 UnlistSoundDeviceInstance(*SoundDeviceInstance); 00233 FreeSoundDeviceInstance(*SoundDeviceInstance); 00234 return TranslateInternalMmResult(Result); 00235 } 00236 00237 return MMSYSERR_NOERROR; 00238 } 00239 00240 MMRESULT 00241 DestroySoundDeviceInstance( 00242 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance) 00243 { 00244 MMRESULT Result; 00245 PMMFUNCTION_TABLE FunctionTable; 00246 PSOUND_DEVICE SoundDevice; 00247 PVOID Handle; 00248 00249 SND_TRACE(L"Destroying a sound device instance\n"); 00250 00251 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) ); 00252 00253 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); 00254 if ( ! MMSUCCESS(Result) ) 00255 return TranslateInternalMmResult(Result); 00256 00257 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); 00258 if ( ! MMSUCCESS(Result) ) 00259 return TranslateInternalMmResult(Result); 00260 00261 /* Get the "close" routine from the function table, and validate it */ 00262 Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); 00263 if ( ! MMSUCCESS(Result) ) 00264 return TranslateInternalMmResult(Result); 00265 00266 SND_ASSERT( FunctionTable->Close ); 00267 if ( FunctionTable->Close == NULL ) 00268 { 00269 /* This indicates bad practice, really! If you can open, why not close?! */ 00270 return MMSYSERR_NOTSUPPORTED; 00271 } 00272 00273 /* Stop the streaming thread */ 00274 if ( SoundDeviceInstance->Thread ) 00275 { 00276 Result = DestroySoundThread(SoundDeviceInstance->Thread); 00277 SND_ASSERT( MMSUCCESS(Result) ); /* It should succeed! */ 00278 if ( ! MMSUCCESS(Result ) ) 00279 { 00280 return TranslateInternalMmResult(Result); 00281 } 00282 } 00283 00284 /* Blank this out here */ 00285 SoundDeviceInstance->Thread = NULL; 00286 00287 /* Try and close the device */ 00288 Result = FunctionTable->Close(SoundDeviceInstance, Handle); 00289 SND_ASSERT( MMSUCCESS(Result) ); /* It should succeed! */ 00290 if ( ! MMSUCCESS(Result) ) 00291 return TranslateInternalMmResult(Result); 00292 00293 /* Drop it from the list */ 00294 Result = UnlistSoundDeviceInstance(SoundDeviceInstance); 00295 SND_ASSERT( MMSUCCESS(Result) ); /* It should succeed! */ 00296 if ( ! MMSUCCESS(Result) ) 00297 return TranslateInternalMmResult(Result); 00298 00299 FreeSoundDeviceInstance(SoundDeviceInstance); 00300 00301 return MMSYSERR_NOERROR; 00302 } 00303 00304 MMRESULT 00305 DestroyAllSoundDeviceInstances( 00306 IN PSOUND_DEVICE SoundDevice) 00307 { 00308 MMRESULT Result; 00309 PSOUND_DEVICE_INSTANCE SoundDeviceInstance; 00310 00311 SoundDeviceInstance = SoundDevice->HeadInstance; 00312 00313 while ( SoundDeviceInstance ) 00314 { 00315 Result = DestroySoundDeviceInstance(SoundDeviceInstance); 00316 SND_ASSERT( MMSUCCESS(Result) ); 00317 SoundDeviceInstance = SoundDeviceInstance->Next; 00318 } 00319 00320 return MMSYSERR_NOERROR; 00321 } 00322 00323 MMRESULT 00324 GetSoundDeviceFromInstance( 00325 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 00326 OUT PSOUND_DEVICE* SoundDevice) 00327 { 00328 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) ); 00329 VALIDATE_MMSYS_PARAMETER( SoundDevice ); 00330 00331 *SoundDevice = SoundDeviceInstance->Device; 00332 00333 return MMSYSERR_NOERROR; 00334 } 00335 00336 MMRESULT 00337 GetSoundDeviceInstanceHandle( 00338 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 00339 OUT PVOID* Handle) 00340 { 00341 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) ); 00342 VALIDATE_MMSYS_PARAMETER( Handle ); 00343 00344 *Handle = SoundDeviceInstance->Handle; 00345 00346 return MMSYSERR_NOERROR; 00347 } 00348 00349 MMRESULT 00350 SetSoundDeviceInstanceMmeData( 00351 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 00352 IN HDRVR MmeHandle, 00353 IN DWORD_PTR ClientCallback, 00354 IN DWORD_PTR ClientCallbackData, 00355 IN DWORD Flags) 00356 { 00357 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) ); 00358 00359 SND_TRACE(L"Setting MME data - handle %x, callback %x, instance data %x, flags %x\n", 00360 MmeHandle, ClientCallback, ClientCallbackData, Flags); 00361 00362 SoundDeviceInstance->WinMM.Handle = MmeHandle; 00363 SoundDeviceInstance->WinMM.ClientCallback = ClientCallback; 00364 SoundDeviceInstance->WinMM.ClientCallbackInstanceData = ClientCallbackData; 00365 SoundDeviceInstance->WinMM.Flags = Flags; 00366 00367 return MMSYSERR_NOERROR; 00368 } Generated on Fri May 25 2012 04:34:39 for ReactOS by
1.7.6.1
|