Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenstreaming.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/wave/streaming.c 00005 * 00006 * PURPOSE: Wave streaming 00007 * 00008 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) 00009 */ 00010 00011 #include "precomp.h" 00012 00013 00014 /* 00015 DoWaveStreaming 00016 Check if there is streaming to be done, and if so, do it. 00017 */ 00018 00019 VOID 00020 DoWaveStreaming( 00021 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance) 00022 { 00023 MMRESULT Result; 00024 MMDEVICE_TYPE DeviceType; 00025 PSOUND_DEVICE SoundDevice; 00026 PMMFUNCTION_TABLE FunctionTable; 00027 PWAVEHDR Header; 00028 PWAVEHDR_EXTENSION HeaderExtension; 00029 00030 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); 00031 SND_ASSERT( MMSUCCESS(Result) ); 00032 00033 Result = GetSoundDeviceType(SoundDevice, &DeviceType); 00034 SND_ASSERT( MMSUCCESS(Result) ); 00035 00036 Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); 00037 SND_ASSERT( MMSUCCESS(Result) ); 00038 SND_ASSERT( FunctionTable ); 00039 SND_ASSERT( FunctionTable->CommitWaveBuffer ); 00040 00041 /* No point in doing anything if no resources available to use */ 00042 if ( SoundDeviceInstance->OutstandingBuffers >= SoundDeviceInstance->BufferCount ) 00043 { 00044 SND_TRACE(L"DoWaveStreaming: No available buffers to stream with - doing nothing\n"); 00045 return; 00046 } 00047 00048 /* Is there any work to do? */ 00049 Header = SoundDeviceInstance->HeadWaveHeader; 00050 00051 if ( ! Header ) 00052 { 00053 SND_TRACE(L"DoWaveStreaming: No work to do - doing nothing\n"); 00054 return; 00055 } 00056 00057 while ( ( SoundDeviceInstance->OutstandingBuffers < SoundDeviceInstance->BufferCount ) && 00058 ( Header ) && SoundDeviceInstance->ResetInProgress == FALSE) 00059 { 00060 HeaderExtension = (PWAVEHDR_EXTENSION) Header->reserved; 00061 SND_ASSERT( HeaderExtension ); 00062 00063 /* Saniy checks */ 00064 SND_ASSERT(Header->dwFlags & WHDR_PREPARED); 00065 SND_ASSERT(Header->dwFlags & WHDR_INQUEUE); 00066 00067 /* Can never be *above* the length */ 00068 SND_ASSERT( HeaderExtension->BytesCommitted <= Header->dwBufferLength ); 00069 00070 /* Is this header entirely committed? */ 00071 if ( HeaderExtension->BytesCommitted == Header->dwBufferLength ) 00072 { 00073 { 00074 /* Move on to the next header */ 00075 SND_ASSERT(Header != Header->lpNext); 00076 Header = Header->lpNext; 00077 } 00078 } 00079 else 00080 { 00081 PSOUND_OVERLAPPED Overlap; 00082 LPVOID OffsetPtr; 00083 DWORD BytesRemaining, BytesToCommit; 00084 BOOL OK; 00085 00086 /* Where within the header buffer to stream from */ 00087 OffsetPtr = Header->lpData + HeaderExtension->BytesCommitted; 00088 00089 /* How much of this header has not been committed */ 00090 BytesRemaining = Header->dwBufferLength - HeaderExtension->BytesCommitted; 00091 00092 /* We can commit anything up to the buffer size limit */ 00093 BytesToCommit = BytesRemaining > SoundDeviceInstance->FrameSize ? 00094 SoundDeviceInstance->FrameSize : 00095 BytesRemaining; 00096 00097 /* Should always have something to commit by this point */ 00098 SND_ASSERT( BytesToCommit > 0 ); 00099 00100 /* We need a new overlapped info structure for each buffer */ 00101 Overlap = AllocateStruct(SOUND_OVERLAPPED); 00102 00103 if ( Overlap ) 00104 { 00105 ZeroMemory(Overlap, sizeof(SOUND_OVERLAPPED)); 00106 Overlap->SoundDeviceInstance = SoundDeviceInstance; 00107 Overlap->Header = Header; 00108 00109 /* Don't complete this header if it's part of a loop */ 00110 Overlap->PerformCompletion = TRUE; 00111 // ( SoundDeviceInstance->LoopsRemaining > 0 ); 00112 00113 /* Adjust the commit-related counters */ 00114 HeaderExtension->BytesCommitted += BytesToCommit; 00115 ++ SoundDeviceInstance->OutstandingBuffers; 00116 00117 OK = MMSUCCESS(FunctionTable->CommitWaveBuffer(SoundDeviceInstance, 00118 OffsetPtr, 00119 BytesToCommit, 00120 Overlap, 00121 CompleteIO)); 00122 00123 if ( ! OK ) 00124 { 00125 /* Clean-up and try again on the next iteration (is this OK?) */ 00126 SND_WARN(L"FAILED\n"); 00127 00128 FreeMemory(Overlap); 00129 HeaderExtension->BytesCommitted -= BytesToCommit; 00130 -- SoundDeviceInstance->OutstandingBuffers; 00131 } 00132 } 00133 } 00134 } 00135 } 00136 00137 00138 /* 00139 CompleteIO 00140 An APC called as a result of a call to CommitWaveHeaderToKernelDevice. 00141 This will count up the number of bytes which have been dealt with, 00142 and when the entire wave header has been dealt with, will call 00143 CompleteWaveHeader to have the wave header returned to the client. 00144 00145 CommitWaveHeaderToKernelDevice 00146 Sends portions of the buffer described by the wave header to a kernel 00147 device. This must only be called from within the context of the sound 00148 thread. The caller supplies either their own commit routine, or uses 00149 WriteFileEx_Committer. The committer is called with portions of the 00150 buffer specified in the wave header. 00151 00152 WriteFileEx_Committer 00153 Commit buffers using the WriteFileEx API. 00154 */ 00155 00156 VOID CALLBACK 00157 CompleteIO( 00158 IN DWORD dwErrorCode, 00159 IN DWORD dwNumberOfBytesTransferred, 00160 IN LPOVERLAPPED lpOverlapped) 00161 { 00162 MMDEVICE_TYPE DeviceType; 00163 PSOUND_DEVICE SoundDevice; 00164 PSOUND_DEVICE_INSTANCE SoundDeviceInstance; 00165 PSOUND_OVERLAPPED SoundOverlapped = (PSOUND_OVERLAPPED) lpOverlapped; 00166 PWAVEHDR WaveHdr; 00167 PWAVEHDR_EXTENSION HdrExtension; 00168 MMRESULT Result; 00169 DWORD Bytes; 00170 00171 WaveHdr = (PWAVEHDR) SoundOverlapped->Header; 00172 SND_ASSERT( WaveHdr ); 00173 00174 HdrExtension = (PWAVEHDR_EXTENSION) WaveHdr->reserved; 00175 SND_ASSERT( HdrExtension ); 00176 00177 SoundDeviceInstance = SoundOverlapped->SoundDeviceInstance; 00178 00179 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); 00180 SND_ASSERT( MMSUCCESS(Result) ); 00181 00182 Result = GetSoundDeviceType(SoundDevice, &DeviceType); 00183 SND_ASSERT( MMSUCCESS(Result) ); 00184 00185 do 00186 { 00187 00188 /* We have an available buffer now */ 00189 -- SoundDeviceInstance->OutstandingBuffers; 00190 00191 /* Did we finish a WAVEHDR and aren't looping? */ 00192 if ( HdrExtension->BytesCompleted + dwNumberOfBytesTransferred >= WaveHdr->dwBufferLength && 00193 SoundOverlapped->PerformCompletion ) 00194 { 00195 /* Wave buffer fully completed */ 00196 Bytes = WaveHdr->dwBufferLength - HdrExtension->BytesCompleted; 00197 00198 HdrExtension->BytesCompleted += Bytes; 00199 dwNumberOfBytesTransferred -= Bytes; 00200 00201 CompleteWaveHeader(SoundDeviceInstance, WaveHdr); 00202 SND_TRACE(L"%d/%d bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength); 00203 } 00204 else 00205 { 00206 /* Partially completed */ 00207 HdrExtension->BytesCompleted += dwNumberOfBytesTransferred; 00208 SND_TRACE(L"%d/%d bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength); 00209 break; 00210 } 00211 00212 /* Move to next wave header */ 00213 WaveHdr = WaveHdr->lpNext; 00214 00215 if (!WaveHdr) 00216 { 00217 /* No following WaveHdr */ 00218 SND_ASSERT(dwNumberOfBytesTransferred == 0); 00219 break; 00220 } 00221 00222 HdrExtension = (PWAVEHDR_EXTENSION) WaveHdr->reserved; 00223 SND_ASSERT( HdrExtension ); 00224 00225 00226 }while(dwNumberOfBytesTransferred); 00227 00228 // AUDIO-BRANCH DIFF 00229 // completion callback is performed in a thread 00230 DoWaveStreaming(SoundDeviceInstance); 00231 00232 //CompleteWavePortion(SoundDeviceInstance, dwNumberOfBytesTransferred); 00233 00234 FreeMemory(lpOverlapped); 00235 } 00236 00237 MMRESULT 00238 WriteFileEx_Committer( 00239 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 00240 IN PVOID OffsetPtr, 00241 IN DWORD Length, 00242 IN PSOUND_OVERLAPPED Overlap, 00243 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine) 00244 { 00245 HANDLE Handle; 00246 00247 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance ); 00248 VALIDATE_MMSYS_PARAMETER( OffsetPtr ); 00249 VALIDATE_MMSYS_PARAMETER( Overlap ); 00250 VALIDATE_MMSYS_PARAMETER( CompletionRoutine ); 00251 00252 GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); 00253 00254 if ( ! WriteFileEx(Handle, OffsetPtr, Length, (LPOVERLAPPED)Overlap, CompletionRoutine) ) 00255 { 00256 // TODO 00257 } 00258 00259 return MMSYSERR_NOERROR; 00260 } 00261 00262 00263 /* 00264 Stream control functions 00265 (External/internal thread pairs) 00266 00267 TODO - Move elsewhere as these shouldn't be wave specific! 00268 */ 00269 00270 MMRESULT 00271 StopStreamingInSoundThread( 00272 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 00273 IN PVOID Parameter) 00274 { 00275 MMDEVICE_TYPE DeviceType; 00276 PMMFUNCTION_TABLE FunctionTable; 00277 MMRESULT Result; 00278 PSOUND_DEVICE SoundDevice; 00279 00280 /* set state reset in progress */ 00281 SoundDeviceInstance->ResetInProgress = TRUE; 00282 00283 /* Get sound device */ 00284 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); 00285 SND_ASSERT( Result == MMSYSERR_NOERROR ); 00286 00287 /* Obtain the function table */ 00288 Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); 00289 SND_ASSERT( Result == MMSYSERR_NOERROR ); 00290 00291 /* Obtain device instance type */ 00292 Result = GetSoundDeviceType(SoundDevice, &DeviceType); 00293 SND_ASSERT( Result == MMSYSERR_NOERROR ); 00294 00295 /* Check if reset function is supported */ 00296 if (FunctionTable->ResetStream) 00297 { 00298 /* cancel all current audio buffers */ 00299 FunctionTable->ResetStream(SoundDeviceInstance, DeviceType, TRUE); 00300 } 00301 while(SoundDeviceInstance->OutstandingBuffers) 00302 { 00303 SND_TRACE(L"StopStreamingInSoundThread OutStandingBufferCount %lu\n", SoundDeviceInstance->OutstandingBuffers); 00304 /* wait until pending i/o has completed */ 00305 SleepEx(10, TRUE); 00306 } 00307 00308 /* complete all current headers */ 00309 while( SoundDeviceInstance->HeadWaveHeader ) 00310 { 00311 SND_TRACE(L"StopStreamingInSoundThread: Completing Header %p\n", SoundDeviceInstance->HeadWaveHeader); 00312 CompleteWaveHeader( SoundDeviceInstance, SoundDeviceInstance->HeadWaveHeader ); 00313 } 00314 00315 /* there should be no oustanding buffers now */ 00316 SND_ASSERT(SoundDeviceInstance->OutstandingBuffers == 0); 00317 00318 00319 /* Check if reset function is supported */ 00320 if (FunctionTable->ResetStream) 00321 { 00322 /* finish the reset */ 00323 FunctionTable->ResetStream(SoundDeviceInstance, DeviceType, FALSE); 00324 } 00325 00326 /* clear state reset in progress */ 00327 SoundDeviceInstance->ResetInProgress = FALSE; 00328 00329 00330 return MMSYSERR_NOERROR; 00331 } 00332 00333 MMRESULT 00334 StopStreaming( 00335 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance) 00336 { 00337 MMRESULT Result; 00338 PSOUND_DEVICE SoundDevice; 00339 MMDEVICE_TYPE DeviceType; 00340 00341 if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance) ) 00342 return MMSYSERR_INVALHANDLE; 00343 00344 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); 00345 if ( ! MMSUCCESS(Result) ) 00346 return TranslateInternalMmResult(Result); 00347 00348 Result = GetSoundDeviceType(SoundDevice, &DeviceType); 00349 if ( ! MMSUCCESS(Result) ) 00350 return TranslateInternalMmResult(Result); 00351 00352 if ( DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceType != WAVE_IN_DEVICE_TYPE ) 00353 return MMSYSERR_NOTSUPPORTED; 00354 00355 return CallSoundThread(SoundDeviceInstance, 00356 StopStreamingInSoundThread, 00357 NULL); 00358 } 00359 00360 MMRESULT 00361 PerformWaveStreaming( 00362 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 00363 IN PVOID Parameter) 00364 { 00365 DoWaveStreaming(SoundDeviceInstance); 00366 00367 return MMSYSERR_NOERROR; 00368 } 00369 00370 DWORD 00371 WINAPI 00372 WaveActivateSoundStreaming( 00373 IN PVOID lpParameter) 00374 { 00375 CallSoundThread((PSOUND_DEVICE_INSTANCE)lpParameter, 00376 PerformWaveStreaming, 00377 NULL); 00378 00379 ExitThread(0); 00380 } 00381 00382 VOID 00383 InitiateSoundStreaming( 00384 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance) 00385 { 00386 HANDLE hThread; 00387 00388 hThread = CreateThread(NULL, 0, WaveActivateSoundStreaming, (PVOID)SoundDeviceInstance, 0, NULL); 00389 00390 if (hThread != NULL) 00391 CloseHandle(hThread); 00392 } Generated on Tue May 22 2012 04:40:25 for ReactOS by
1.7.6.1
|