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

header.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/header.c
00005  *
00006  * PURPOSE:     Wave header preparation and submission routines
00007  *
00008  * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
00009 */
00010 
00011 #include "precomp.h"
00012 
00013 
00014 /*
00015     This structure gets used locally within functions as a way to shuttle data
00016     to the sound thread. It's safe to use locally since CallSoundThread will
00017     not return until the operation has been carried out.
00018 */
00019 
00020 typedef struct
00021 {
00022     MMWAVEHEADER_FUNC Function;
00023     PWAVEHDR Header;
00024 } THREADED_WAVEHEADER_PARAMETERS;
00025 
00026 
00027 /*
00028     Helper routines to simplify the call to the sound thread for the header
00029     functions.
00030 */
00031 
00032 MMRESULT
00033 WaveHeaderOperationInSoundThread(
00034     PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
00035     IN  PVOID Parameter)
00036 {
00037     THREADED_WAVEHEADER_PARAMETERS* Parameters = (THREADED_WAVEHEADER_PARAMETERS*) Parameter;
00038     return Parameters->Function(SoundDeviceInstance, Parameters->Header);
00039 }
00040 
00041 MMRESULT
00042 WaveHeaderOperation(
00043     MMWAVEHEADER_FUNC Function,
00044     PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
00045     PWAVEHDR Header)
00046 {
00047     THREADED_WAVEHEADER_PARAMETERS Parameters;
00048 
00049     Parameters.Function = Function;
00050     Parameters.Header = Header;
00051 
00052     return CallSoundThread(SoundDeviceInstance,
00053                            WaveHeaderOperationInSoundThread,
00054                            &Parameters);
00055 }
00056 
00057 
00058 /*
00059     SanitizeWaveHeader
00060         Clean up a header / reinitialize
00061 */
00062 
00063 VOID
00064 SanitizeWaveHeader(
00065     PWAVEHDR Header)
00066 {
00067     PWAVEHDR_EXTENSION Extension = (PWAVEHDR_EXTENSION) Header->reserved;
00068     SND_ASSERT( Extension );
00069 
00070     Header->dwBytesRecorded = 0;
00071 
00072     Extension->BytesCommitted = 0;
00073     Extension->BytesCompleted = 0;
00074 }
00075 
00076 
00077 /*
00078     The following routines are basically handlers for:
00079     - WODM_PREPARE
00080     - WODM_UNPREPARE
00081     - WODM_WRITE
00082 
00083     All of these calls are ultimately dealt with in the context of the
00084     appropriate sound thread, so the implementation should expect itself to
00085     be running in this other thread when any of these operations take place.
00086 */
00087 
00088 MMRESULT
00089 PrepareWaveHeader(
00090     IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
00091     IN  PWAVEHDR Header)
00092 {
00093     MMRESULT Result;
00094     PSOUND_DEVICE SoundDevice;
00095     PMMFUNCTION_TABLE FunctionTable;
00096     PWAVEHDR_EXTENSION Extension;
00097 
00098     VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
00099     VALIDATE_MMSYS_PARAMETER( Header );
00100 
00101     SND_TRACE(L"Preparing wave header\n");
00102 
00103     Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
00104     if ( ! MMSUCCESS(Result) )
00105         return TranslateInternalMmResult(Result);
00106 
00107     Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
00108     if ( ! MMSUCCESS(Result) )
00109         return TranslateInternalMmResult(Result);
00110 
00111     Extension = AllocateStruct(WAVEHDR_EXTENSION);
00112     if ( ! Extension )
00113         return MMSYSERR_NOMEM;
00114 
00115     Header->reserved = (DWORD_PTR) Extension;
00116     Extension->BytesCommitted = 0;
00117     Extension->BytesCompleted = 0;
00118 
00119     /* Configure the flags */
00120     Header->dwFlags |= WHDR_PREPARED;
00121 
00122     return MMSYSERR_NOERROR;
00123 }
00124 
00125 MMRESULT
00126 UnprepareWaveHeader(
00127     IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
00128     IN  PWAVEHDR Header)
00129 {
00130     MMRESULT Result;
00131     PSOUND_DEVICE SoundDevice;
00132     PMMFUNCTION_TABLE FunctionTable;
00133     PWAVEHDR_EXTENSION Extension;
00134 
00135     VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
00136     VALIDATE_MMSYS_PARAMETER( Header );
00137 
00138     SND_TRACE(L"Un-preparing wave header\n");
00139 
00140     Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
00141     if ( ! MMSUCCESS(Result) )
00142         return TranslateInternalMmResult(Result);
00143 
00144     Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
00145     if ( ! MMSUCCESS(Result) )
00146         return TranslateInternalMmResult(Result);
00147 
00148     SND_ASSERT( Header->reserved );
00149     Extension = (PWAVEHDR_EXTENSION) Header->reserved;
00150     FreeMemory(Extension);
00151 
00152     /* Configure the flags */
00153     Header->dwFlags &= ~WHDR_PREPARED;
00154 
00155     return MMSYSERR_NOERROR;
00156 }
00157 
00158 MMRESULT
00159 WriteWaveHeader(
00160     IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
00161     IN  PWAVEHDR Header)
00162 {
00163     MMRESULT Result;
00164     PSOUND_DEVICE SoundDevice;
00165     PMMFUNCTION_TABLE FunctionTable;
00166 
00167     VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
00168     VALIDATE_MMSYS_PARAMETER( Header );
00169 
00170     SND_TRACE(L"Submitting wave header\n");
00171 
00172     Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
00173     if ( ! MMSUCCESS(Result) )
00174         return TranslateInternalMmResult(Result);
00175 
00176     Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
00177     if ( ! MMSUCCESS(Result) )
00178         return TranslateInternalMmResult(Result);
00179 
00180     if ( ! FunctionTable->CommitWaveBuffer )
00181         return MMSYSERR_NOTSUPPORTED;
00182 
00183     /*
00184         A few minor sanity checks - any custom checks should've been carried
00185         out during wave header preparation etc.
00186     */
00187     VALIDATE_MMSYS_PARAMETER( Header->lpData != NULL );
00188     VALIDATE_MMSYS_PARAMETER( Header->dwBufferLength > 0 );
00189     VALIDATE_MMSYS_PARAMETER( Header->dwFlags & WHDR_PREPARED );
00190     VALIDATE_MMSYS_PARAMETER( ! (Header->dwFlags & WHDR_INQUEUE) );
00191 
00192     SanitizeWaveHeader(Header);
00193 
00194     /* Clear the "done" flag for the buffer */
00195     Header->dwFlags &= ~WHDR_DONE;
00196 
00197     Result = CallSoundThread(SoundDeviceInstance,
00198                              EnqueueWaveHeader,
00199                              Header);
00200 
00201     return Result;
00202 }
00203 
00204 
00205 /*
00206     EnqueueWaveHeader
00207         Put the header in the record/playback queue. This is performed within
00208         the context of the sound thread, it must NEVER be called from another
00209         thread.
00210 
00211     CompleteWaveHeader
00212         Set the header information to indicate that it has finished playing,
00213         and return it to the client application. This again must be called
00214         within the context of the sound thread.
00215 */
00216 
00217 MMRESULT
00218 EnqueueWaveHeader(
00219     PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
00220     IN  PVOID Parameter)
00221 {
00222     PWAVEHDR WaveHeader = (PWAVEHDR) Parameter;
00223 
00224     VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
00225     VALIDATE_MMSYS_PARAMETER( Parameter );
00226 
00227     /* Initialise */
00228     WaveHeader->lpNext = NULL;
00229 
00230     /* Set the "in queue" flag */
00231     WaveHeader->dwFlags |= WHDR_INQUEUE;
00232 
00233     if ( ! SoundDeviceInstance->HeadWaveHeader )
00234     {
00235         /* This is the first header in the queue */
00236         SND_TRACE(L"Enqueued first wave header\n");
00237         SoundDeviceInstance->HeadWaveHeader = WaveHeader;
00238         SoundDeviceInstance->TailWaveHeader = WaveHeader;
00239 
00240         /* Only do wave streaming when the stream has not been paused */
00241         if (SoundDeviceInstance->bPaused == FALSE)
00242         {
00243             DoWaveStreaming(SoundDeviceInstance);
00244         }
00245     }
00246     else
00247     {
00248         /* There are already queued headers - make this one the tail */
00249         SND_TRACE(L"Enqueued next wave header\n");
00250 
00251         /* FIXME - Make sure that the buffer has not already been added to the list */
00252         if ( SoundDeviceInstance->TailWaveHeader != WaveHeader )
00253         {
00254             SND_ASSERT(SoundDeviceInstance->TailWaveHeader != WaveHeader);
00255 
00256             SoundDeviceInstance->TailWaveHeader->lpNext = WaveHeader;
00257             SoundDeviceInstance->TailWaveHeader = WaveHeader;
00258             DUMP_WAVEHDR_QUEUE(SoundDeviceInstance);
00259 
00260             /* Only do wave streaming when the stream has not been paused */
00261             if ( SoundDeviceInstance->bPaused == FALSE )
00262             {
00263                 DoWaveStreaming(SoundDeviceInstance);
00264             }
00265         }
00266     }
00267 
00268     DUMP_WAVEHDR_QUEUE(SoundDeviceInstance);
00269 
00270     return MMSYSERR_NOERROR;
00271 }
00272 
00273 VOID
00274 CompleteWaveHeader(
00275     IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
00276     IN  PWAVEHDR Header)
00277 {
00278     PWAVEHDR PrevHdr = NULL, CurrHdr = NULL;
00279     PWAVEHDR_EXTENSION Extension;
00280     PSOUND_DEVICE SoundDevice;
00281     MMDEVICE_TYPE DeviceType;
00282     MMRESULT Result;
00283 
00284     SND_TRACE(L"BUFFER COMPLETE :)\n");
00285 
00286     // TODO: Set header flags?
00287     // TODO: Call client
00288     // TODO: Streaming
00289 
00290     //DoWaveStreaming(SoundDeviceInstance);
00291 
00292     Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
00293     SND_ASSERT( MMSUCCESS(Result) );
00294     Result = GetSoundDeviceType(SoundDevice, &DeviceType);
00295     SND_ASSERT( MMSUCCESS(Result) );
00296 
00297     Extension = (PWAVEHDR_EXTENSION)Header->reserved;
00298     SND_ASSERT( Extension );
00299 
00300     /* Remove the header from the queue, like so */
00301     if ( SoundDeviceInstance->HeadWaveHeader == Header )
00302     {
00303         SoundDeviceInstance->HeadWaveHeader = Header->lpNext;
00304 
00305         SND_TRACE(L"Dropping head node\n");
00306 
00307         /* If nothing after the head, then there is no tail */
00308         if ( Header->lpNext == NULL )
00309         {
00310             SND_TRACE(L"Dropping tail node\n");
00311             SoundDeviceInstance->TailWaveHeader = NULL;
00312         }
00313     }
00314     else
00315     {
00316         PrevHdr = NULL;
00317         CurrHdr = SoundDeviceInstance->HeadWaveHeader;
00318 
00319         SND_TRACE(L"Relinking nodes\n");
00320 
00321         while ( CurrHdr != Header )
00322         {
00323             PrevHdr = CurrHdr;
00324             CurrHdr = CurrHdr->lpNext;
00325             SND_ASSERT( CurrHdr );
00326         }
00327 
00328         SND_ASSERT( PrevHdr );
00329 
00330         PrevHdr->lpNext = CurrHdr->lpNext;
00331 
00332         /* If this is the tail node, update the tail */
00333         if ( Header->lpNext == NULL )
00334         {
00335             SND_TRACE(L"Updating tail node\n");
00336             SoundDeviceInstance->TailWaveHeader = PrevHdr;
00337         }
00338     }
00339 
00340     /* Make sure we're not using this as the current buffer any more, either! */
00341 /*
00342     if ( SoundDeviceInstance->CurrentWaveHeader == Header )
00343     {
00344         SoundDeviceInstance->CurrentWaveHeader = Header->lpNext;
00345     }
00346 */
00347 
00348     DUMP_WAVEHDR_QUEUE(SoundDeviceInstance);
00349 
00350     SND_TRACE(L"Returning buffer to client...\n");
00351 
00352     /* Update the header */
00353     Header->dwFlags &= ~WHDR_INQUEUE;
00354     Header->dwFlags |= WHDR_DONE;
00355 
00356     if ( DeviceType == WAVE_IN_DEVICE_TYPE )
00357     {
00358         // FIXME: We won't be called on incomplete buffer!
00359         Header->dwBytesRecorded = Extension->BytesCompleted;
00360     }
00361 
00362     /* Safe to do this without thread protection, as we're done with the header */
00363     NotifyMmeClient(SoundDeviceInstance,
00364                     DeviceType == WAVE_OUT_DEVICE_TYPE ? WOM_DONE : WIM_DATA,
00365                     (DWORD_PTR)Header);
00366 }

Generated on Sun May 27 2012 04:22:59 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.