examples/ForumNokia/AudioStreamExample/src/AudioStreamEngine.cpp

00001 /*
00002  * Copyright � 2008 Nokia Corporation.
00003  */
00004 
00005 #include <mda\common\audio.h>
00006 #include <mmf\common\mmfutilities.h>
00007 #include <MdaAudioInputStream.h>    // audio input stream
00008 #include <MdaAudioOutputStream.h>   // audio output stream
00009 #include <s32file.h>                // RFileWriteStream and RFileReadStream
00010 
00011 #include "AudioStreamEngine.h"
00012 #include "audiostream.pan"
00013 
00014 // Audio data buffer size.
00015 // In both 3rd Edition and 2nd Edition the total buffer (iStreamBuffer) size is 
00016 // KFrameSizePCM * KFrameCountPCM = 40960 bytes. This will contain 2560 ms 
00017 // of 16-bit audio data. 
00018 // In 3rd Edition the KFrameSizePCM is 4096 bytes, because CMdaAudioInputStream::ReadL() 
00019 // returns audio data in 4096-byte chunks. In 2nd Edition, ReadL() returns data in 320-byte
00020 // chunks.
00021 const TInt KFrameSizePCM = 4096;
00022 const TInt KFrameCountPCM = 100;
00023 
00024 // Audio data buffer size for AMR encoding. For AMR, the buffer size is the same in
00025 // both 2nd and 3rd Edition devices (20 ms per frame, a total of 2560 ms in 128 frames).
00026 const TInt KFrameSizeAMR = 14;
00027 const TInt KFrameCountAMR = 128;
00028 // Header data for an AMR-encoded audio file
00029 const TInt KAMRHeaderLength=6;
00030 const TUint8 KAMRNBHeader[KAMRHeaderLength] = { 0x23, 0x21, 0x41, 0x4d, 0x52, 0x0a };
00031 
00032 // Files to store the sample audio clips
00033 _LIT(KAudioFilePCM, "sample.aud");
00034 _LIT(KAudioFileAMR, "sample.amr");
00035 
00036 
00037 CAudioStreamEngine* CAudioStreamEngine::NewL(CAudioStreamAppUi* aAppUi)
00038     {
00039     CAudioStreamEngine* self = CAudioStreamEngine::NewLC(aAppUi);
00040     CleanupStack::Pop(self);
00041     return self;
00042     }
00043 
00044 CAudioStreamEngine* CAudioStreamEngine::NewLC(CAudioStreamAppUi* aAppUi)
00045     {
00046     CAudioStreamEngine* self = new (ELeave) CAudioStreamEngine(aAppUi);
00047     CleanupStack::PushL(self);
00048     self->ConstructL();
00049     return self;
00050     }
00051 
00052 // Standard EPOC 2nd phase constructor
00053 void CAudioStreamEngine::ConstructL()
00054     {
00055     // Construct streams. We need to construct these here, so that at least the input stream
00056     // exists if SetEncodingL() is called before any recording has taken place 
00057     iInputStream = CMdaAudioInputStream::NewL(*this);
00058     iOutputStream = CMdaAudioOutputStream::NewL(*this);
00059 
00060     // Get a handle to the RFs session to be used (owned by CEikonEnv, NOT to be closed
00061     // when this application exits!)        
00062     iFs = CEikonEnv::Static()->FsSession();
00063 
00064     // Save the default encoding for later reference (the encoding is the same for
00065     // both input and output streams).
00066     iDefaultEncoding = iInputStream->DataType();
00067     // At first we are using the default encoding.
00068     iCurrentEncoding = iDefaultEncoding;
00069 
00070     // Stream buffer allocation (by default for PCM)
00071     iStreamBuffer = HBufC8::NewMaxL(iFrameSize * iFrameCount);
00072     iStreamStart=0;
00073     iStreamEnd=iFrameCount - 1;
00074     
00075     // The sample.aud/amr can be found in \private<UID3>\ folder
00076     User::LeaveIfError( iFs.CreatePrivatePath( EDriveC ) );
00077     User::LeaveIfError( iFs.SetSessionToPrivate( EDriveC ) );
00078     
00079     iStop = CIdle::NewL( CActive::EPriorityIdle );
00080     }
00081 
00082 // ----------------------------------------------------------------------------
00083 // CAudioStreamEngine::CAudioStreamEngine(
00084 //     CAudioStreamAppUi* aAppUi)
00085 //
00086 // onstructor
00087 // ----------------------------------------------------------------------------
00088 CAudioStreamEngine::CAudioStreamEngine(CAudioStreamAppUi* aAppUi)
00089 : iAppUi(aAppUi), iUseAMR(EFalse), iAudioFile(KAudioFilePCM), iFrameSize(KFrameSizePCM), 
00090 iFrameCount(KFrameCountPCM), iStreamBuffer(0), iFramePtr(0,0), iBufferOK(EFalse)
00091     {
00092     // By default we use PCM and initialise the instance variables accordingly above.
00093         
00094     // Initial audio stream properties for input and output, 8KHz mono. 
00095     // These settings could also be set/changed using method SetAudioPropertiesL() of
00096     // the input and output streams.
00097     iStreamSettings.iChannels=TMdaAudioDataSettings::EChannelsMono;
00098     iStreamSettings.iSampleRate=TMdaAudioDataSettings::ESampleRate8000Hz;
00099     }
00100 
00101 // ----------------------------------------------------------------------------
00102 // CAudioStreamEngine::~CAudioStreamEngine()
00103 //
00104 // destructor
00105 // ----------------------------------------------------------------------------
00106 CAudioStreamEngine::~CAudioStreamEngine()
00107     { 
00108     if (iInputStream)
00109         {
00110         if (iInputStatus!=ENotReady) 
00111             {
00112             iInputStream->Stop();
00113             }
00114         delete iInputStream;
00115         }
00116 
00117     if (iOutputStream)
00118         {
00119         if (iOutputStatus!=ENotReady) 
00120             {
00121             iOutputStream->Stop();
00122             }
00123         delete iOutputStream;
00124         }
00125 
00126     if (iStreamBuffer)
00127         {
00128         delete iStreamBuffer;
00129         }
00130     if (iStop)
00131         {
00132         iStop->Cancel();
00133         }
00134     delete iStop;
00135     }
00136 
00137 
00138 // ----------------------------------------------------------------------------
00139 // CAudioStreamEngine::Play()
00140 //
00141 // plays the audio data contained in the buffer
00142 // ----------------------------------------------------------------------------
00143 void CAudioStreamEngine::Play()
00144     {
00145     ShowMessage(_L("Play "), ETrue);
00146     // if either stream is active, return
00147     if (iInputStatus!=ENotReady || iOutputStatus!=ENotReady) 
00148         {
00149         ShowMessage(_L("Stream in use, \ncannot play audio."), ETrue);
00150         return;
00151         }
00152 
00153     if(!iBufferOK)
00154         {
00155         ShowMessage(_L("Nothing to play - \nrecord or load \na file first."), ETrue);
00156         return;
00157         }
00158         
00159     // Open output stream.
00160     // Upon completion will receive callback in 
00161     // MMdaAudioOutputStreamCallback::MaoscOpenComplete().
00162     iOutputStream->Open(&iStreamSettings);
00163     }
00164 
00165 
00166 // ----------------------------------------------------------------------------
00167 // CAudioStreamEngine::Record()
00168 //
00169 // records audio data into the buffer
00170 // ----------------------------------------------------------------------------
00171 void CAudioStreamEngine::Record()
00172     {
00173     // If either stream is active, return
00174     if (iInputStatus!=ENotReady || iOutputStatus!=ENotReady) 
00175     {
00176         ShowMessage(_L("Stream in use, \ncannot record audio."), ETrue);
00177         return;
00178     }
00179 
00180     // Open input stream.
00181     // Upon completion will receive callback in 
00182     // MMdaAudioInputStreamCallback::MaiscOpenComplete().
00183     iInputStream->Open(&iStreamSettings);
00184     }
00185 
00186 // ----------------------------------------------------------------------------
00187 // CAudioStreamEngine::Stop()
00188 //
00189 // stops playing/recording
00190 // ----------------------------------------------------------------------------
00191 void CAudioStreamEngine::Stop()
00192     {
00193     // if input or output streams are active, close them
00194     if (iInputStatus!=ENotReady) 
00195         {
00196         iInputStream->Stop();
00197         ShowMessage(_L("\nRecording stopped!"), ETrue);
00198         iBufferOK = ETrue;
00199         iInputStatus = ENotReady;
00200         }       
00201     if (iOutputStatus!=ENotReady) 
00202         {
00203         iOutputStream->Stop();
00204         iOutputStatus = ENotReady;
00205         ShowMessage(_L("\nPlayback stopped!"), ETrue);
00206         }
00207     }
00208 
00209 
00210 // ----------------------------------------------------------------------------
00211 // CAudioStreamEngine::LoadAudioFileL()
00212 //
00213 // loads the audio data from a file into the buffer
00214 // ----------------------------------------------------------------------------
00215 void CAudioStreamEngine::LoadAudioFileL()
00216     {
00217     RFileReadStream audiofile;
00218 
00219     // open file
00220     TFileName fileName;
00221     fileName.Copy(iAudioFilePath);
00222     fileName.Append(iAudioFile);
00223 
00224     TInt err = audiofile.Open(iFs, fileName, EFileRead|EFileStream);
00225     iStreamBuffer->Des().FillZ(iFrameCount * iFrameSize);  // Empty the stream buffer
00226     if (err==KErrNone) 
00227         {
00228         // file opened ok, proceed reading
00229         if (iUseAMR)
00230             {
00231             // Read the AMR header (the first 6 bytes). We don't need to save/use the header,
00232             // since while playback we already know it's an AMR-NB encoded stream.
00233             TBuf8<KAMRHeaderLength> temp;
00234             audiofile.ReadL(temp, KAMRHeaderLength);
00235             }
00236 
00237         TUint idx=0;
00238         while (idx < iFrameCount)
00239             {
00240             TRAPD(fstatus, audiofile.ReadL(GetFrame(idx), iFrameSize));
00241             if (fstatus!=KErrNone)
00242                 break;
00243             idx++;
00244             }
00245         iStreamStart=0;
00246         iStreamEnd=idx-1;
00247         ShowMessage(_L("Loading complete!"), ETrue);
00248         iBufferOK = ETrue;  
00249         }   
00250     else 
00251         {
00252         // failed to open file
00253         ShowMessage(_L("Error loading \naudio sample!"), ETrue); 
00254         iBufferOK = EFalse;
00255         }
00256     audiofile.Close();
00257     }
00258 
00259 
00260 // ----------------------------------------------------------------------------
00261 // CAudioStreamEngine::SaveAudioFileL()
00262 //
00263 // saves the audio data in the buffer into a file
00264 // ----------------------------------------------------------------------------
00265 void CAudioStreamEngine::SaveAudioFileL()
00266     {
00267     if (!iBufferOK)
00268     {
00269         // In case the encoding was changed between recording and trying to save the file
00270         ShowMessage(_L("Recorded buffer does not \nmatch current encoding."), ETrue);   
00271         ShowMessage(_L("\nPlease re-record and \ntry again."), EFalse); 
00272         return;
00273     }
00274     RFileWriteStream audiofile;
00275 
00276     // Check for free space for saving the sample
00277     TVolumeInfo volinfo;
00278     TInt err=iFs.Volume(volinfo,EDriveC);
00279     if ( volinfo.iFree<(iFrameCount*iFrameSize))
00280         {
00281         // Not enough free space on drive for saving, report and exit
00282         ShowMessage(_L("Cannot save file:\nnot enough space!"), ETrue); 
00283         return;
00284         }
00285 
00286     TFileName fileName;
00287     fileName.Copy(iAudioFilePath);
00288     fileName.Append(iAudioFile);
00289     err = audiofile.Replace(iFs, fileName, EFileWrite|EFileStream);
00290     if (err==KErrNone) 
00291         {
00292         if (iUseAMR)
00293             {
00294                 // Write the six-byte AMR header, so that the file can be used by other
00295                 // applications as well.
00296                 for (int i = 0; i < KAMRHeaderLength; i++)
00297                     audiofile.WriteUint8L(KAMRNBHeader[i]);
00298             }
00299             
00300         // File opened ok, proceed writing.
00301         // Write audio data directly from iStreamBuffer
00302         for (TUint idx=iStreamStart; idx<=iStreamEnd; idx++)//iFrameCount; idx++)
00303             {
00304             audiofile.WriteL(GetFrame(idx));
00305             }
00306         ShowMessage(_L("Saving complete!"), ETrue); 
00307         }   
00308     else 
00309         {
00310         // failed to open file
00311         ShowMessage(_L("Error saving \naudio sample!"), ETrue); 
00312         }
00313     audiofile.Close();
00314     }
00315 
00316 // ----------------------------------------------------------------------------
00317 // CAudioStreamEngine::SetEncodingL(TBool aAmr)
00318 //
00319 // If argument is ETrue, AMR-NB encoding will be used in audio input/output.
00320 // If EFalse, the default PCM is used. If the platform does not support AMR-NB,
00321 // PCM will be used no matter what the argument's value is.
00322 // ----------------------------------------------------------------------------
00323 void CAudioStreamEngine::SetEncodingL(TBool aAmr)
00324     {
00325     // Act only if the new encoding differs from the current one
00326     if (iUseAMR != aAmr)
00327         {
00328         iUseAMR = aAmr;
00329         if (iUseAMR)
00330             {
00331             // Try to set AMR-NB encoding, this will indicate whether it is supported
00332             // by the platform or not.
00333             TRAPD(err, iInputStream->SetDataTypeL(KMMFFourCCCodeAMR));
00334             if (err != KErrNone)
00335                 {
00336                 ShowMessage(_L("AMR-NB not supported,\nusing PCM."), ETrue);    
00337                 iCurrentEncoding = iDefaultEncoding;
00338                 iUseAMR = EFalse;
00339                 // We do not need to invalidate the buffer or change buffer settings, 
00340                 // since the encoding was not changed -> just return.
00341                 return;  
00342                 }
00343             else
00344                 {
00345                 iCurrentEncoding = KMMFFourCCCodeAMR;
00346                 iAudioFile.Zero();  // Empty the audio file name                
00347                 iAudioFile.Append(KAudioFileAMR);
00348                 iFrameCount = KFrameCountAMR;
00349                 iFrameSize = KFrameSizeAMR;
00350                 ShowMessage(_L("Encoding set to AMR-NB."), ETrue);  
00351                 }
00352             }
00353         else
00354             {
00355             // If we get here, the encoding has previously been changed to AMR. Switch back to
00356             // PCM.
00357             iCurrentEncoding = iDefaultEncoding;
00358             iAudioFile.Zero();  // Empty the audio file name                
00359             iAudioFile.Append(KAudioFilePCM);
00360             iFrameCount = KFrameCountPCM;
00361             iFrameSize = KFrameSizePCM;
00362             ShowMessage(_L("Encoding set to PCM."), ETrue); 
00363             }
00364 
00365         // Make sure the user re-records or reloads the audio file, so that we do not 
00366         // accidentally try to play PCM data using AMR or vice versa.
00367         iBufferOK = EFalse; 
00368         if (iStreamBuffer) delete iStreamBuffer;
00369         iStreamBuffer = NULL; // In case the following NewL leaves
00370         iStreamBuffer = HBufC8::NewMaxL(iFrameSize * iFrameCount);
00371         iStreamStart=0;
00372         iStreamEnd=iFrameCount - 1;
00373         }   
00374     }
00375 
00376 // ----------------------------------------------------------------------------
00377 // CAudioStreamEngine::ShowMessage(
00378 //     const TDesC& aMsg, TBool aReset=EFalse)
00379 //
00380 // displays text referenced by aMsg in the label, will append the aMsg in the 
00381 // existing text in label if aReset is EFalse, otherwise will reset the label 
00382 // text.
00383 // ----------------------------------------------------------------------------
00384 void CAudioStreamEngine::ShowMessage(const TDesC& aMsg, TBool aReset=EFalse)
00385     {
00386     if (aReset)     // if ETrue, clear the message on the label prior to output
00387         iMsg.Zero();
00388     iMsg.Append(aMsg);
00389     TRAPD(error, iAppUi->GetView()->ShowMessageL(iMsg));
00390     PanicIfError(error);
00391     }
00392 
00393 // ----------------------------------------------------------------------------
00394 // TPtr8& CAudioStreamEngine::GetFrame(TUint aFrameIdx)
00395 //
00396 // Returns a modifiable pointer to a single frame inside the audio buffer 
00397 // ----------------------------------------------------------------------------
00398 TPtr8& CAudioStreamEngine::GetFrame(TUint aFrameIdx)
00399     {
00400       __ASSERT_ALWAYS(aFrameIdx < iFrameCount, 
00401                                     User::Panic(_L("AudioStreamEx"), 1));
00402                                 
00403       iFramePtr.Set((TUint8*)(iStreamBuffer->Ptr() + (aFrameIdx * iFrameSize)),
00404                                  iFrameSize,
00405                                  iFrameSize);
00406       return iFramePtr;
00407     }
00408 
00409 // ----------------------------------------------------------------------------
00410 // TPtr8& CAudioStreamEngine::GetPlaybackFrames(TUint aLastFrame)
00411 //
00412 // Returns a modifiable pointer to the requested frames inside the audio buffer
00413 // (from the first frame to aLastFrame). 
00414 // ----------------------------------------------------------------------------
00415 TPtr8& CAudioStreamEngine::GetPlaybackFrames(TUint aLastFrame)
00416     {
00417     __ASSERT_ALWAYS(aLastFrame < iFrameCount, 
00418                                 User::Panic(_L("AudioStreamEx"), 2));
00419                                 
00420     iFramePtr.Set((TUint8*)(iStreamBuffer->Ptr()),
00421                                  (aLastFrame + 1) * iFrameSize,
00422                                  (aLastFrame + 1) * iFrameSize);
00423     return iFramePtr;
00424     }
00425 
00426 
00427 //
00428 // MMdaAudioInputStream callbacks (MMdaAudioInputStreamCallback)
00429 //
00430 // ----------------------------------------------------------------------------
00431 // CAudioStreamEngine::MaiscOpenComplete(
00432 //     TInt aError)
00433 //
00434 // called upon completion of CMdaAudioInputStream::Open(),
00435 // if the stream was opened succesfully (aError==KErrNone), it's ready for use.
00436 // upon succesful open, the first audio data block will be read from the input
00437 // stream.
00438 // ----------------------------------------------------------------------------
00439 void CAudioStreamEngine::MaiscOpenComplete(TInt aError)
00440     {
00441     if (aError==KErrNone) 
00442         {
00443         // Input stream opened succesfully, set status
00444         iInputStatus = EOpen;
00445         // Set the data type (encoding)
00446         TRAPD(error, iInputStream->SetDataTypeL(iCurrentEncoding));
00447         PanicIfError(error);
00448 
00449         // set stream input gain to maximum
00450         iInputStream->SetGain(iInputStream->MaxGain()); 
00451         // set stream priority to normal and time sensitive
00452         iInputStream->SetPriority(EPriorityNormal, EMdaPriorityPreferenceTime);             
00453         ShowMessage(_L("Recording..."), ETrue);
00454         
00455         // Emtpy the buffer and issue ReadL() to read the first audio data block, 
00456         // subsequent calls to ReadL() will be issued 
00457         // in MMdaAudioInputStreamCallback::MaiscBufferCopied()
00458         iStreamBuffer->Des().FillZ(iFrameCount * iFrameSize);
00459         iStreamIdx=0;
00460         TRAPD(error2, iInputStream->ReadL(GetFrame(iStreamIdx)));
00461         PanicIfError(error2);
00462         } 
00463     else 
00464         {
00465         // input stream open failed
00466         iInputStatus = ENotReady;
00467         ShowMessage(_L("Recording failed!"), ETrue);
00468         }
00469     }
00470 
00471 // ----------------------------------------------------------------------------
00472 // CAudioStreamEngine::MaiscBufferCopied(
00473 //     TInt aError, const TDesC8& aBuffer)
00474 //
00475 // called when a block of audio data has been read and is available at the 
00476 // buffer reference *aBuffer.  calls to ReadL() will be issued until all blocks
00477 // in the audio data buffer (iStreamBuffer) are filled.
00478 // ----------------------------------------------------------------------------
00479 void CAudioStreamEngine::MaiscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
00480     {
00481     if (aError!=KErrNone)
00482         {
00483         _LIT(KMessage,"Recording error: %d");
00484         HBufC16* message = HBufC16::NewLC(KMessage().Length()+10);
00485         message->Des().AppendFormat(KMessage,aError);
00486         ShowMessage(*message, ETrue);
00487         CleanupStack::PopAndDestroy(); // message
00488         message = NULL;
00489         }
00490     
00491     if (aError==KErrNone) 
00492         {
00493         // stop recording if at the end of the buffer
00494         iStreamIdx++;
00495         if (iStreamIdx == iFrameCount)
00496             {
00497             ShowMessage(_L("\nRecording complete!"), ETrue);
00498             iStreamEnd = iStreamIdx - 1;
00499             iBufferOK = ETrue;
00500 
00501             // Playback is complete:
00502             // Start the active object that will stop the stream
00503             iStop->Start( TCallBack(BackgroundStop, this) );            
00504             return;
00505             }       
00506         
00507         // issue ReadL() for next frame     
00508         TRAPD(error, iInputStream->ReadL(GetFrame(iStreamIdx)));
00509         PanicIfError(error);
00510         }
00511     else if (aError==KErrAbort) 
00512         {
00513         // Recording was aborted, due to call to CMdaAudioInputStream::Stop()
00514         // This KErrAbort will occur each time the Stop() method in this class is executed.
00515         // Also, MaiscRecordComplete() will be called after exiting this method.
00516         iStreamEnd = iStreamIdx - 1;
00517         iBufferOK = ETrue;
00518         iInputStatus = ENotReady;
00519         }
00520     else 
00521         {
00522         ShowMessage(_L("\nError reading data \nfrom input"), ETrue);
00523         iInputStatus = ENotReady;
00524         }
00525     }
00526 
00527 
00528 TInt CAudioStreamEngine::BackgroundStop( TAny *aStream )  // static member function
00529     {
00530     ((CAudioStreamEngine*)aStream)->Stop();
00531     return EFalse;
00532     }
00533 
00534 
00535 // ----------------------------------------------------------------------------
00536 // CAudioStreamEngine::MaiscRecordComplete(
00537 //     TInt aError)
00538 //
00539 // called when input stream is closed by CMdaAudioInputStream::Stop()
00540 // ----------------------------------------------------------------------------
00541 void CAudioStreamEngine::MaiscRecordComplete(TInt aError)
00542     {   
00543     iInputStatus = ENotReady;
00544     if (aError==KErrNone) 
00545         {
00546         // normal stream closure
00547         }
00548     else 
00549         {
00550         // completed with error(s)
00551         }
00552     }
00553 
00554 
00555 // MMdaAudioOutputStream callbacks (MMdaAudioOutputStreamCallback)
00556 
00557 // ----------------------------------------------------------------------------
00558 // CAudioStreamEngine::MaoscOpenComplete(
00559 //     TInt aError)
00560 //
00561 // called upon completion of CMdaAudioOutputStream::Open(),
00562 // if the stream was opened succesfully (aError==KErrNone), it's ready for use.
00563 // upon succesful open, the first audio data block will be written to the 
00564 // output stream.
00565 // ----------------------------------------------------------------------------
00566 void CAudioStreamEngine::MaoscOpenComplete(TInt aError)
00567     {
00568     if (aError==KErrNone) 
00569         {
00570         // output stream opened succesfully, set status
00571         iOutputStatus = EOpen;
00572         // Set the data type (encoding). Should not fail, since we already
00573         // have tested support for this encoding in SetEncodingL with the 
00574         // corresponding input stream!
00575         TRAPD(error, iOutputStream->SetDataTypeL(iCurrentEncoding));
00576         PanicIfError(error);
00577         
00578         // set volume to 1/4th of stream max volume
00579         iOutputStream->SetVolume(iOutputStream->MaxVolume()/2);
00580         // set stream priority to normal and time sensitive
00581         iOutputStream->SetPriority(EPriorityNormal, 
00582             EMdaPriorityPreferenceTime);                
00583         ShowMessage(_L("Playing "), ETrue);
00584 
00585         if (iUseAMR)
00586             {
00587             // In case of AMR, the whole recorded/loaded buffer is played back at once, not frame by frame. 
00588             // The buffer might not be fully recorded, so we will only play back the part
00589             // that is filled with data.
00590             iStreamIdx = iStreamEnd;
00591             TRAPD(error2, iOutputStream->WriteL(GetPlaybackFrames(iStreamEnd)));
00592             PanicIfError(error2);
00593             }
00594         else
00595             {
00596             // PCM needs to be played back frame by frame, otherwise some older devices might
00597             // run into buffer overflow situations.
00598             iStreamIdx = 0;
00599             TRAPD(error3, iOutputStream->WriteL(GetFrame(iStreamIdx)));
00600             PanicIfError(error3);
00601             }
00602         }
00603     else 
00604         {
00605         // output stream open failed
00606         iOutputStatus = ENotReady;
00607         ShowMessage(_L("Playback failed!"), ETrue);
00608         }       
00609     }
00610 
00611 // ----------------------------------------------------------------------------
00612 // CAudioStreamEngine::MaoscBufferCopied(
00613 //     TInt aError, const TDesC8& aBuffer)
00614 //
00615 // called when a block of audio data has been written to MMF. calls to WriteL() 
00616 // will be issued until all blocks in the audio data buffer (iStreamBuffer) are 
00617 // written.
00618 // ----------------------------------------------------------------------------
00619 void CAudioStreamEngine::MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
00620     {   
00621     if (aError==KErrNone) 
00622         {
00623         if (iStreamIdx==iStreamEnd)
00624             {
00625             ShowMessage(_L("\nPlayback complete!"), EFalse);
00626             // Playback is complete:
00627             // Start the active object that will stop the stream
00628             iStop->Start( TCallBack(BackgroundStop, this) );            
00629             }
00630         else 
00631             {
00632             iStreamIdx++;
00633             TRAPD(error, iOutputStream->WriteL(GetFrame(iStreamIdx)));  
00634             PanicIfError(error);
00635             }
00636         }
00637     else if (aError==KErrAbort) 
00638         {
00639         // Playing was aborted, due to call to CMdaAudioOutputStream::Stop().
00640         // MaoscRecordComplete() will be called after exiting this method.
00641         iOutputStatus = ENotReady;
00642         }
00643     else 
00644         {
00645         ShowMessage(_L("\nError writing data \nto output"), EFalse);            
00646         iOutputStatus = ENotReady;
00647         }
00648     }
00649 
00650 
00651 // ----------------------------------------------------------------------------
00652 // CAudioStreamEngine::MaoscPlayComplete(
00653 //     TInt aError)
00654 //
00655 // called when output stream is closed by CMdaAudioOutputStream::Stop() or if 
00656 // end of audio data has been reached, in this case KErrUnderflow will be 
00657 // returned.
00658 // ----------------------------------------------------------------------------
00659 void CAudioStreamEngine::MaoscPlayComplete(TInt aError)
00660     {
00661     iOutputStatus = ENotReady;
00662     if (aError==KErrNone) 
00663         {
00664         // normal stream closure
00665         }   
00666     else if (aError==KErrUnderflow) 
00667         {
00668         // end of audio data stream was reached because of stream underflow,
00669         }
00670     else 
00671         {
00672         // completed with error(s)
00673         }   
00674     }
00675 
00676 // END OF FILE
00677 

Generated by  doxygen 1.6.2