diff -r f9bb0fca356a -r 0fd27995241b javauis/mmapi_qt/baseline/src/cmmaaudiorecorder.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/mmapi_qt/baseline/src/cmmaaudiorecorder.cpp Tue May 11 16:07:20 2010 +0300 @@ -0,0 +1,391 @@ +/* +* Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: This class is used for recording Audio +* +*/ + + +#include +#include +#include +#include +#include "cmmaaudiorecorder.h" +#include "cmmaoutputstream.h" + +const TInt KDefaultSize = KMaxTInt32; // Default record size limit + +CMMAAudioRecorder* CMMAAudioRecorder::NewLC( + CMMAMMFResolver* aResolver, + CMMAAudioSettings* aAudioSettings, + TInt aMIDletSuiteID) +{ + // Not using ELeave to avoid leave before owneship change of settings + CMMAAudioRecorder* self = new CMMAAudioRecorder(aResolver, aMIDletSuiteID); + if (!self) + { + delete aAudioSettings; + User::Leave(KErrNoMemory); + } + // Take the ownership of setting before any possible leaves + self->iSettings = aAudioSettings; + CleanupStack::PushL(self); + self->iWait = new(ELeave) CActiveSchedulerWait(); + self->ConstructL(); + return self; +} + + +CMMAAudioRecorder::~CMMAAudioRecorder() +{ + iFile.Close(); + delete iSettings; + delete iWait; +} + + +CMMAAudioRecorder::CMMAAudioRecorder( + CMMAMMFResolver* aResolver, + TInt /*aMIDletSuiteID*/): + CMMAMMFPlayerBase(aResolver), + iAudioRecordControllerCustomCommands(iController), + iAudioControllerRecCustomCommands(iController), + iRecordSizeLimit(KDefaultSize), + iPauseError(KErrNone), + iEOFReached(EFalse) +{ +} + +/** + * start the play + */ +void CMMAAudioRecorder::StartL() +{ + TInt64 time; + GetMediaTime(&time); + + PostLongEvent(CMMAPlayerEvent::EStarted, time); + ChangeState(EStarted); + PostActionCompletedStart(); +} + + +void CMMAAudioRecorder::StopL(TBool aPostEvent) +{ + if (iState == EStarted) + { + ChangeState(EPrefetched); + } + + if (aPostEvent) + { + TInt64 time; + GetMediaTime(&time); + PostLongEvent(CMMAPlayerEvent::EStopped, time); + } +} + +void CMMAAudioRecorder::DoOpenL() +{ + // Make sure any existing controller is closed. + iEventMonitor->Cancel(); + iController.Close(); + + // player priority settings + TMMFPrioritySettings prioritySettings; + prioritySettings.iPriority = EMdaPriorityMax; + prioritySettings.iPref = EMdaPriorityPreferenceTimeAndQuality; + prioritySettings.iState = EMMFStateRecording; + + // Try opening and configuring each controller in turn + TInt error = KErrNotSupported; + TInt index = 0; + + // Try controllers until found a good controller or out of list + while ((error != KErrNone) && + (index < iControllerInfos->Count())) + { + // Open the controller + error = iController.Open((*iControllerInfos)[ index ]->Uid(), + prioritySettings); + + // If the controller was opened without error, start receiving events from it. + if (!error) + { + iEventMonitor->Start(); + + // Add the data source to the controller. + error = iController.AddDataSource(KUidMmfAudioInput, KNullDesC8); + } + + // Add the data sink + if (!error) + { + TMMFFileHandleParams params(&iFile); + TPckg paramPckg = params; + error = iController.AddDataSink(KUidMmfFileSink, paramPckg, iSinkInfo); + } + + // If an error occurred in any of the above, close the controller. + if (error) + { + iEventMonitor->Cancel(); + iController.Close(); + } + + index++; + } + User::LeaveIfError(error); + + HBufC8* contentType8 = HBufC8::NewLC(iContentType->Length()); + contentType8->Des().Copy(*iContentType); + + TInt cInfoCount = iControllerInfos->Count(); + for (TInt i = 0; i < cInfoCount; i++) + { + CMMFControllerImplementationInformation* contrInfo = (*iControllerInfos)[ i ]; + const RMMFFormatImplInfoArray& recordFormats = contrInfo->RecordFormats(); + + for (TInt formatIndex = 0; formatIndex < recordFormats.Count(); formatIndex++) + { + CMMFFormatImplementationInformation* formatInfo = recordFormats[ formatIndex ]; + + if (formatInfo->SupportsMimeType(*contentType8)) + { + iSupplier.Set(formatInfo->Supplier()); + // Some of the controllers those support only one format can return KErrNotSupported + // error when setting the format, but still they can record that only supported format + // Ignoring this error + TInt err = iAudioControllerRecCustomCommands.SetSinkFormat(formatInfo->Uid()); + if ((err != KErrNotSupported)) + { + User::LeaveIfError(err); + } + break; + } + } + } + CleanupStack::PopAndDestroy(contentType8); + + // Do not set codec if it is default + if (iSettings->iDataType != TFourCC(KFourCCNULL)) + { + User::LeaveIfError( + iAudioControllerRecCustomCommands.SetCodec(KFourCCNULL, iSettings->iDataType)); + } + + // set the audio data settings ie sample rate & channels, if not defaults + if (iSettings->iRate != KDefaultRate) + { + User::LeaveIfError( + iAudioControllerRecCustomCommands.SetSinkSampleRate(iSettings->iRate)); + } + + if (iSettings->iChannels != KDefaultChannels) + { + User::LeaveIfError( + iAudioControllerRecCustomCommands.SetSinkNumChannels(iSettings->iChannels)); + } +} + +void CMMAAudioRecorder::PrefetchL() +{ + if (iResetController) + { + DoOpenL(); + } + User::LeaveIfError(iController.Prime()); + //PostActionCompleted(KErrNone); + PostActionCompletedFile(); + ChangeState(EPrefetched); +} + +void CMMAAudioRecorder::InitializeL(RFile* aFile, + MMMFControllerEventMonitorObserver* aObserver) +{ + iFile.Duplicate(*aFile); + iObserver = aObserver; + DoOpenL(); +} + +void CMMAAudioRecorder::Deinitialize() +{ + LOG( EJavaMMAPI, EInfo, "CMMAAudioRecorder::Deinitialize++"); + if (iEventMonitor) + { + iEventMonitor->Cancel(); + } + iController.Close(); + iFile.Close(); + LOG( EJavaMMAPI, EInfo, "CMMAAudioRecorder::Deinitialize--"); +} + +const TDesC& CMMAAudioRecorder::Type() +{ + return KMMAAudioRecorder; +} + +void CMMAAudioRecorder::StartRecordL() +{ + if (iResetController) + { + iResetController = EFalse; + LOG( EJavaMMAPI, EInfo, "CMMAAudioRecorder::StartRecordL reopen controller"); + DoOpenL(); + LOG( EJavaMMAPI, EInfo, "CMMAAudioRecorder::StartRecordL reopen done"); + } + + + User::LeaveIfError( + iAudioRecordControllerCustomCommands.SetMaxFileSize(iRecordSizeLimit)); + + LOG1( EJavaMMAPI, EInfo, "CMMAAudioRecorder::StartRecordL Max File size set %d", iRecordSizeLimit); + + User::LeaveIfError(iController.Prime()); + User::LeaveIfError(iController.Play()); +} + + +void CMMAAudioRecorder::StopRecordL() +{ + // ! here is the workaround for pause + // Pause() doesn't work with all formats. + LOG( EJavaMMAPI, EInfo, "CMMAAudioRecorder::StopRecordL Stopping"); + + TInt pauseError = iController.Pause(); + // if EOF is already reached return without + // doing any operation because controller is + // already in Stopped state + if (iEOFReached && (KErrNotReady == pauseError)) + { + LOG( EJavaMMAPI, EInfo, "CMMAAudioRecorder::StopRecordL, EOF reached already"); + iEOFReached = EFalse; + return; + } + if (pauseError == KErrNotSupported) + { + LOG( EJavaMMAPI, EInfo, "CMMAAudioRecorder::StopRecordL Stopped instead pause"); + User::LeaveIfError(iController.Stop()); + } + else + { + User::LeaveIfError(pauseError); +// wait only in HW +#ifndef __WINS__ + LOG( EJavaMMAPI, EInfo, "CMMAAudioRecorder::StopRecordL Stopped waiting"); + // wait for playback complete event + if (!iWait->IsStarted()) + { + iWait->Start(); + } + User::LeaveIfError(iError); +#endif + } + + + // prime controller and set position back to end (autorewind in controller) + User::LeaveIfError(iController.Prime()); + + TTimeIntervalMicroSeconds position(0); + User::LeaveIfError(iController.GetDuration(position)); + User::LeaveIfError(iController.SetPosition(position)); +} + +void CMMAAudioRecorder::GetDuration(TInt64* aDuration) +{ + // Return -1 in realized state in order to pass END_OF_MEDIA + // tests in TCK. MMFPlayerbase would return 0. + if (iState == ERealized) + { + *aDuration = KTimeUnknown; + } + else + { + CMMAMMFPlayerBase::GetDuration(aDuration); + } +} + +void CMMAAudioRecorder::DeallocateL() +{ + // set control to be reopened since + // deallocate closes it + if (iState == EPrefetched) + { + iResetController = ETrue; + } + CMMAMMFPlayerBase::DeallocateL(); +} + +void CMMAAudioRecorder::ResetL() +{ + iResetController = ETrue; +} + +const TInt KMMASymbianControllerLimit = 4096 + 44; // buffer size + header +_LIT(KSymbian, "Symbian"); + +TInt CMMAAudioRecorder::SetRecordSizeLimitL(TInt aSize) +{ + iRecordSizeLimit = aSize; + + // Wav and AU controller (supplied from symbian) is recording in 4kb buffers + // this controller does not record at all if size is smaller than 4kb and + // goes even in wierd state. + LOG1( EJavaMMAPI, EInfo, "CMMAAudioRecorder::SetRecordSizeLimitL Supplier = %S", iSupplier.Ptr()); + if ((iSupplier == KSymbian) && + (aSize < KMMASymbianControllerLimit)) + { + iRecordSizeLimit = KMMASymbianControllerLimit; + } + + // normal case is that recordsize is set just before starting + if (iState == EStarted) + { + LOG1( EJavaMMAPI, EInfo, "CMMAAudioRecorder::SetRecordSizeLimitL Setting while playing limit: %d", iRecordSizeLimit); + // trying to set max file size while recording + User::LeaveIfError( + iAudioRecordControllerCustomCommands.SetMaxFileSize(iRecordSizeLimit)); + } + return iRecordSizeLimit; +} + +void CMMAAudioRecorder::HandleEvent(const TMMFEvent& aEvent) +{ + ELOG1( EJavaMMAPI, "CMMAAudioRecorder::HandleEvent event error: %d", aEvent.iErrorCode); + + if (KErrEof == aEvent.iErrorCode) + { + iEOFReached = ETrue; + } + // if we are waiting event + if (iWait->IsStarted()) + { + iError = aEvent.iErrorCode; + iWait->AsyncStop(); + return; + } + TMMFEvent event = aEvent; + if ((event.iEventType == KMMFEventCategoryPlaybackComplete) && + ((event.iErrorCode == KErrNone) || + (event.iErrorCode == KErrEof))) + { + // Prime controller after playback complete, in order to get position/duration + event.iErrorCode = iController.Prime(); + } + if (iObserver) + { + iObserver->HandleEvent(event); + } +} + +// END OF FILE