javauis/mmapi_akn/baseline/src/cmmaaudiorecorder.cpp
branchRCL_3
changeset 66 2455ef1f5bbc
child 83 26b2b12093af
equal deleted inserted replaced
65:ae942d28ec0e 66:2455ef1f5bbc
       
     1 /*
       
     2 * Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  This class is used for recording Audio
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <jdebug.h>
       
    20 #include <mmf/server/mmffile.h>
       
    21 #include <mmf/server/mmfdes.h>
       
    22 #include <mmf/plugin/mmfformatimplementationuids.hrh>
       
    23 #include "cmmaaudiorecorder.h"
       
    24 #include "cmmaoutputstream.h"
       
    25 
       
    26 const TInt KDefaultSize = KMaxTInt32;   // Default record size limit
       
    27 
       
    28 CMMAAudioRecorder* CMMAAudioRecorder::NewLC(
       
    29     CMMAMMFResolver* aResolver,
       
    30     CMMAAudioSettings* aAudioSettings,
       
    31     TInt aMIDletSuiteID)
       
    32 {
       
    33     // Not using ELeave to avoid leave before owneship change of settings
       
    34     CMMAAudioRecorder* self = new CMMAAudioRecorder(aResolver, aMIDletSuiteID);
       
    35     if (!self)
       
    36     {
       
    37         delete aAudioSettings;
       
    38         User::Leave(KErrNoMemory);
       
    39     }
       
    40     // Take the ownership of setting before any possible leaves
       
    41     self->iSettings = aAudioSettings;
       
    42     CleanupStack::PushL(self);
       
    43     self->iWait = new(ELeave) CActiveSchedulerWait();
       
    44     self->ConstructL();
       
    45     return self;
       
    46 }
       
    47 
       
    48 
       
    49 CMMAAudioRecorder::~CMMAAudioRecorder()
       
    50 {
       
    51     iFile.Close();
       
    52     delete iSettings;
       
    53     delete iWait;
       
    54 }
       
    55 
       
    56 
       
    57 CMMAAudioRecorder::CMMAAudioRecorder(
       
    58     CMMAMMFResolver* aResolver,
       
    59     TInt /*aMIDletSuiteID*/):
       
    60         CMMAMMFPlayerBase(aResolver),
       
    61         iAudioRecordControllerCustomCommands(iController),
       
    62         iAudioControllerRecCustomCommands(iController),
       
    63         iRecordSizeLimit(KDefaultSize),
       
    64         iPauseError(KErrNone)
       
    65 {
       
    66 }
       
    67 
       
    68 /**
       
    69  * start the play
       
    70  */
       
    71 void CMMAAudioRecorder::StartL(TBool aPostEvent)
       
    72 {
       
    73     if (aPostEvent)
       
    74     {
       
    75         TInt64 time;
       
    76         GetMediaTime(&time);
       
    77         PostLongEvent(CMMAPlayerEvent::EStarted, time);
       
    78     }
       
    79 
       
    80     ChangeState(EStarted);
       
    81     PostActionCompleted(KErrNone);   // java start return
       
    82 }
       
    83 
       
    84 
       
    85 void CMMAAudioRecorder::StopL(TBool aPostEvent)
       
    86 {
       
    87     if (iState == EStarted)
       
    88     {
       
    89         ChangeState(EPrefetched);
       
    90     }
       
    91 
       
    92     if (aPostEvent)
       
    93     {
       
    94         TInt64 time;
       
    95         GetMediaTime(&time);
       
    96         PostLongEvent(CMMAPlayerEvent::EStopped, time);
       
    97     }
       
    98 }
       
    99 
       
   100 void CMMAAudioRecorder::DoOpenL()
       
   101 {
       
   102     // Make sure any existing controller is closed.
       
   103     iEventMonitor->Cancel();
       
   104     iController.Close();
       
   105 
       
   106     // player priority settings
       
   107     TMMFPrioritySettings prioritySettings;
       
   108     prioritySettings.iPriority = EMdaPriorityMax;
       
   109     prioritySettings.iPref = EMdaPriorityPreferenceTimeAndQuality;
       
   110     prioritySettings.iState = EMMFStateRecording;
       
   111 
       
   112     // Try opening and configuring each controller in turn
       
   113     TInt error = KErrNotSupported;
       
   114     TInt index = 0;
       
   115 
       
   116     // Try controllers until found a good controller or out of list
       
   117     while ((error != KErrNone) &&
       
   118             (index < iControllerInfos->Count()))
       
   119     {
       
   120         // Open the controller
       
   121         error = iController.Open((*iControllerInfos)[ index ]->Uid(),
       
   122                                  prioritySettings);
       
   123 
       
   124         // If the controller was opened without error, start receiving events from it.
       
   125         if (!error)
       
   126         {
       
   127             iEventMonitor->Start();
       
   128 
       
   129             // Add the data source to the controller.
       
   130             error = iController.AddDataSource(KUidMmfAudioInput, KNullDesC8);
       
   131         }
       
   132 
       
   133         // Add the data sink
       
   134         if (!error)
       
   135         {
       
   136             TMMFFileHandleParams params(&iFile);
       
   137             TPckg<TMMFFileHandleParams> paramPckg = params;
       
   138             error = iController.AddDataSink(KUidMmfFileSink, paramPckg, iSinkInfo);
       
   139         }
       
   140 
       
   141         // If an error occurred in any of the above, close the controller.
       
   142         if (error)
       
   143         {
       
   144             iEventMonitor->Cancel();
       
   145             iController.Close();
       
   146         }
       
   147 
       
   148         index++;
       
   149     }
       
   150     User::LeaveIfError(error);
       
   151 
       
   152     HBufC8* contentType8 = HBufC8::NewLC(iContentType->Length());
       
   153     contentType8->Des().Copy(*iContentType);
       
   154 
       
   155     TInt cInfoCount = iControllerInfos->Count();
       
   156     for (TInt i = 0; i < cInfoCount; i++)
       
   157     {
       
   158         CMMFControllerImplementationInformation* contrInfo = (*iControllerInfos)[ i ];
       
   159         const RMMFFormatImplInfoArray& recordFormats = contrInfo->RecordFormats();
       
   160 
       
   161         for (TInt formatIndex = 0; formatIndex < recordFormats.Count(); formatIndex++)
       
   162         {
       
   163             CMMFFormatImplementationInformation* formatInfo = recordFormats[ formatIndex ];
       
   164 
       
   165             if (formatInfo->SupportsMimeType(*contentType8))
       
   166             {
       
   167                 iSupplier.Set(formatInfo->Supplier());
       
   168                 // Some of the controllers those support only one format can return KErrNotSupported
       
   169                 // error when setting the format, but still they can record that only supported format
       
   170                 // Ignoring this error
       
   171                 TInt err = iAudioControllerRecCustomCommands.SetSinkFormat(formatInfo->Uid());
       
   172                 if ((err != KErrNotSupported))
       
   173                 {
       
   174                     User::LeaveIfError(err);
       
   175                 }
       
   176                 break;
       
   177             }
       
   178         }
       
   179     }
       
   180     CleanupStack::PopAndDestroy(contentType8);
       
   181 
       
   182     // Do not set codec if it is default
       
   183     if (iSettings->iDataType != TFourCC(KFourCCNULL))
       
   184     {
       
   185         User::LeaveIfError(
       
   186             iAudioControllerRecCustomCommands.SetCodec(KFourCCNULL, iSettings->iDataType));
       
   187     }
       
   188 
       
   189     // set the audio data settings ie sample rate & channels, if not defaults
       
   190     if (iSettings->iRate != KDefaultRate)
       
   191     {
       
   192         User::LeaveIfError(
       
   193             iAudioControllerRecCustomCommands.SetSinkSampleRate(iSettings->iRate));
       
   194     }
       
   195 
       
   196     if (iSettings->iChannels != KDefaultChannels)
       
   197     {
       
   198         User::LeaveIfError(
       
   199             iAudioControllerRecCustomCommands.SetSinkNumChannels(iSettings->iChannels));
       
   200     }
       
   201 }
       
   202 
       
   203 void CMMAAudioRecorder::PrefetchL()
       
   204 {
       
   205     if (iResetController)
       
   206     {
       
   207         DoOpenL();
       
   208     }
       
   209     User::LeaveIfError(iController.Prime());
       
   210     ChangeState(EPrefetched);
       
   211     PostActionCompleted(KErrNone);
       
   212 }
       
   213 
       
   214 void CMMAAudioRecorder::InitializeL(RFile* aFile,
       
   215                                     MMMFControllerEventMonitorObserver* aObserver)
       
   216 {
       
   217     iFile.Duplicate(*aFile);
       
   218     iObserver = aObserver;
       
   219     DoOpenL();
       
   220 }
       
   221 
       
   222 void CMMAAudioRecorder::Deinitialize()
       
   223 {
       
   224     DEBUG("CMMAAudioRecorder::Deinitialize++");
       
   225     if (iEventMonitor)
       
   226     {
       
   227         iEventMonitor->Cancel();
       
   228     }
       
   229     iController.Close();
       
   230     iFile.Close();
       
   231     DEBUG("CMMAAudioRecorder::Deinitialize--");
       
   232 }
       
   233 
       
   234 const TDesC& CMMAAudioRecorder::Type()
       
   235 {
       
   236     return KMMAAudioRecorder;
       
   237 }
       
   238 
       
   239 void CMMAAudioRecorder::StartRecordL()
       
   240 {
       
   241     if (iResetController)
       
   242     {
       
   243         iResetController = EFalse;
       
   244         DEBUG("CMMAAudioRecorder::StartRecordL reopen controller");
       
   245         DoOpenL();
       
   246         DEBUG("CMMAAudioRecorder::StartRecordL reopen done");
       
   247     }
       
   248 
       
   249     User::LeaveIfError(
       
   250         iAudioRecordControllerCustomCommands.SetMaxFileSize(iRecordSizeLimit));
       
   251 
       
   252     DEBUG_INT("CMMAAudioRecorder::StartRecordL Max File size set %d", iRecordSizeLimit);
       
   253 
       
   254     User::LeaveIfError(iController.Prime());
       
   255     User::LeaveIfError(iController.Play());
       
   256 }
       
   257 
       
   258 
       
   259 void CMMAAudioRecorder::StopRecordL()
       
   260 {
       
   261     // ! here is the workaround for pause
       
   262     // Pause() doesn't work with all formats.
       
   263     DEBUG("CMMAAudioRecorder::StopRecordL Stopping");
       
   264 
       
   265     TInt pauseError = iController.Pause();
       
   266     // if EOF is already reached return without
       
   267     // doing any operation because controller is
       
   268     // already in Stopped state
       
   269     if (pauseError == KErrNotSupported)
       
   270     {
       
   271         DEBUG("CMMAAudioRecorder::StopRecordL Stopped instead pause");
       
   272         User::LeaveIfError(iController.Stop());
       
   273     }
       
   274     else
       
   275     {
       
   276         User::LeaveIfError(pauseError);
       
   277 // wait only in HW
       
   278 #ifndef __WINS__
       
   279         DEBUG("CMMAAudioRecorder::StopRecordL Stopped waiting");
       
   280         // wait for playback complete event
       
   281         if (!iWait->IsStarted())
       
   282         {
       
   283             iWait->Start();
       
   284         }
       
   285         User::LeaveIfError(iError);
       
   286 #endif
       
   287     }
       
   288 
       
   289 
       
   290     // prime controller and set position back to end (autorewind in controller)
       
   291     User::LeaveIfError(iController.Prime());
       
   292 
       
   293     TTimeIntervalMicroSeconds position(0);
       
   294     User::LeaveIfError(iController.GetDuration(position));
       
   295     User::LeaveIfError(iController.SetPosition(position));
       
   296 }
       
   297 
       
   298 void CMMAAudioRecorder::GetDuration(TInt64* aDuration)
       
   299 {
       
   300     // Return -1 in realized state in order to pass END_OF_MEDIA
       
   301     // tests in TCK. MMFPlayerbase would return 0.
       
   302     if (iState == ERealized)
       
   303     {
       
   304         *aDuration = KTimeUnknown;
       
   305     }
       
   306     else
       
   307     {
       
   308         CMMAMMFPlayerBase::GetDuration(aDuration);
       
   309     }
       
   310 }
       
   311 
       
   312 void CMMAAudioRecorder::DeallocateL()
       
   313 {
       
   314     // set control to be reopened since
       
   315     // deallocate closes it
       
   316     if (iState == EPrefetched)
       
   317     {
       
   318         iResetController = ETrue;
       
   319     }
       
   320     CMMAMMFPlayerBase::DeallocateL();
       
   321 }
       
   322 
       
   323 void CMMAAudioRecorder::ResetL()
       
   324 {
       
   325     iResetController = ETrue;
       
   326 }
       
   327 
       
   328 const TInt KMMASymbianControllerLimit = 4096 + 44; // buffer size + header
       
   329 _LIT(KSymbian, "Symbian");
       
   330 
       
   331 TInt CMMAAudioRecorder::SetRecordSizeLimitL(TInt aSize)
       
   332 {
       
   333     iRecordSizeLimit = aSize;
       
   334 
       
   335     // Wav and AU controller (supplied from symbian) is recording in 4kb buffers
       
   336     // this controller does not record at all if size is smaller than 4kb and
       
   337     // goes even in wierd state.
       
   338     DEBUG_STR("CMMAAudioRecorder::SetRecordSizeLimitL Supplier = %S", iSupplier);
       
   339     if ((iSupplier == KSymbian) &&
       
   340             (aSize < KMMASymbianControllerLimit))
       
   341     {
       
   342         iRecordSizeLimit = KMMASymbianControllerLimit;
       
   343     }
       
   344 
       
   345     // normal case is that recordsize is set just before starting
       
   346     if (iState == EStarted)
       
   347     {
       
   348         DEBUG_INT("CMMAAudioRecorder::SetRecordSizeLimitL Setting while playing limit: %d", iRecordSizeLimit);
       
   349         // trying to set max file size while recording
       
   350         User::LeaveIfError(
       
   351             iAudioRecordControllerCustomCommands.SetMaxFileSize(iRecordSizeLimit));
       
   352     }
       
   353     return iRecordSizeLimit;
       
   354 }
       
   355 
       
   356 void CMMAAudioRecorder::HandleEvent(const TMMFEvent& aEvent)
       
   357 {
       
   358     DEBUG_INT("CMMAAudioRecorder::HandleEvent event error: %d", aEvent.iErrorCode);
       
   359 
       
   360     if (iWait->IsStarted())
       
   361     {
       
   362         iError = aEvent.iErrorCode;
       
   363         iWait->AsyncStop();
       
   364         return;
       
   365     }
       
   366     TMMFEvent event = aEvent;
       
   367     if ((event.iEventType == KMMFEventCategoryPlaybackComplete) &&
       
   368             ((event.iErrorCode == KErrNone) ||
       
   369              (event.iErrorCode == KErrEof)))
       
   370     {
       
   371         // Prime controller after playback complete, in order to get position/duration
       
   372         event.iErrorCode = iController.Prime();
       
   373     }
       
   374     if (iObserver)
       
   375     {
       
   376         iObserver->HandleEvent(event);
       
   377     }
       
   378 }
       
   379 
       
   380 //  END OF FILE