--- /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 <logger.h>
+#include <mmf/server/mmffile.h>
+#include <mmf/server/mmfdes.h>
+#include <mmfformatimplementationuids.hrh>
+#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<TMMFFileHandleParams> 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