--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmfenh/advancedaudiocontroller/audiocontrollerpluginsvariant/3gpaudiorecordcontroller/Src/3GPAudioRecordControllerPlugin.cpp Tue Feb 02 01:08:46 2010 +0200
@@ -0,0 +1,1043 @@
+/*
+* Copyright (c) 2005 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: Implementation file for 3GPAudioRecordControllerPlugin
+*
+*/
+
+
+#include "3GPAudioRecordControllerPluginUIDs.hrh"
+#include "3GPAudioRecordControllerPlugin.h"
+#include "3GPAudioRecordControllerEncoderBuilder.h"
+#include "3GPAudioRecordControllerResource.h"
+#include "DevSoundAudioInput.h"
+#include <mmffile.h>
+#include "DebugMacros.h"
+
+// CONSTANTS
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::C3GPAudioRecordControllerPlugin
+// C++ default constructor can NOT contain any code, that might leave.
+// -----------------------------------------------------------------------------
+//
+C3GPAudioRecordControllerPlugin::C3GPAudioRecordControllerPlugin()
+ : iMP4Handle(NULL),
+ iEncoderBuilder(NULL),
+ iBuffer(NULL)
+ {
+ iEnableDelayWrite = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::ConstructL()
+ {
+ CAdvancedAudioRecordController::ConstructL();
+ DP0(_L("C3GPAudioRecordControllerPlugin::ConstructL(1)"));
+ iEncoderBuilder = C3GPAudioRecordControllerEncoderBuilder::NewL();
+ DP0(_L("C3GPAudioRecordControllerPlugin::ConstructL(2)"));
+ iAudioResource = C3GPAudioRecordControllerResource::NewL(K3GPResourceAAC);
+
+ TAapProperties aapProperties = iAudioResource->PropertiesL();
+ DP0(_L("C3GPAudioRecordControllerPlugin::ConstructL(3)"));
+ iSharedBufferMaxNum = aapProperties.iSharedBufferMaxNum; // default size
+ iSharedBufferMaxSize = aapProperties.iSharedBufferMaxSize; // default size
+
+ iMetaData = C3GPAudioRecordControllerMetaData::NewL();
+
+ iMetaData->AddMetaDataWriteParserL(this);
+ RArray<TInt>& codecConfigData = CONST_CAST(RArray<TInt>&, iAudioResource->CodecConfigParametersL());
+
+ iSampleRate = codecConfigData[1]; // default sample rate for devsound
+ iChannels = codecConfigData[3]; // default channels for devsound
+
+ DP0(_L("C3GPAudioRecordControllerPlugin::ConstructL(4)"));
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+C3GPAudioRecordControllerPlugin* C3GPAudioRecordControllerPlugin::NewL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::NewL"));
+ C3GPAudioRecordControllerPlugin* self = new(ELeave) C3GPAudioRecordControllerPlugin;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::~C3GPAudioRecordControllerPlugin
+// Destructor
+// -----------------------------------------------------------------------------
+//
+C3GPAudioRecordControllerPlugin::~C3GPAudioRecordControllerPlugin()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::~C3GPAudioRecordControllerPlugin"));
+
+ TRAP_IGNORE(CloseMP4ComposerL());
+ delete iMetaData;
+ delete iEncoderBuilder;
+ delete iAudioResource;
+ delete iAudioInput;
+ delete iBuffer;
+
+ iSupportedChannels.Close();
+ iSharedBuffers.ResetAndDestroy();
+ iSharedBuffers.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::DoAddDataSourceL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::DoAddDataSourceL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::DoAddDataSourceL"));
+
+ iAudioInput = CDevSoundAudioInput::NewL(iPrioritySettings, *this, *iMMFDevSound);
+
+ iEncoderType = K3GPEncoder;
+ iDataType = TFourCC(' ','A','A','C');
+
+ if ( iDataSink )
+ {
+ CAdvancedAudioEncoder* encoder = iEncoderBuilder->BuildEncoderL(iEncoderType, iDataType);
+ // AudioInput takes ownership of Encoder object
+ iAudioInput->SetEncoder(encoder);
+ iAudioInput->PrimeL();
+ DetermineSupportedNumChannelsL();
+ iAudioInput->StopL();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::DoAddDataSinkL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::DoAddDataSinkL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::DoAddDataSinkL"));
+ CMMFClip* clip = STATIC_CAST(CMMFClip*, iDataSink);
+
+ if ( iDataSink->DataSinkType() == KUidMmfFileSink )
+ {
+ iSinkType = KUidMmfFileSink;
+ clip->SinkPrimeL();
+ clip->SinkThreadLogon(*this);
+ iDriveNumber = GetDriveNumber(STATIC_CAST(CMMFFile*, iDataSink)->FileDrive());
+
+ TInt size = clip->Size();
+ if (size == 0) // check for size = 0, to verify whether header has been written
+ {
+ WriteHeaderL();
+ }
+
+ clip->SinkStopL();
+ TRAP_IGNORE(UpdateMP4DurationL()); // get duration if file contains valid recorded data
+ }
+ else // KUidMmfDescriptorSink
+ {
+ iSinkType = KUidMmfDescriptorSink;
+ }
+
+ if ( iDataSource )
+ {
+ CAdvancedAudioEncoder* encoder = iEncoderBuilder->BuildEncoderL(iEncoderType, iDataType);
+ // AudioInput takes ownership of Encoder object
+ iAudioInput->SetEncoder(encoder);
+ iAudioInput->PrimeL();
+ DetermineSupportedNumChannelsL();
+ iAudioInput->StopL();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::DoStopL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::DoStopL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::DoStopL"));
+
+ iAudioInput->StopL();
+
+ if (!iEnableDelayWrite)
+ DoCommitMetaDataL();
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::EmptyBufferL
+// -----------------------------------------------------------------------------
+//
+TInt C3GPAudioRecordControllerPlugin::EmptyBufferL(
+ CMMFBuffer* aBuffer )
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::EmptyBufferL"));
+
+ TUint buffersize = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data().Length();
+ CMMFDataBuffer* buf = STATIC_CAST(CMMFDataBuffer*, aBuffer);
+ TUint8* buffer = CONST_CAST(TUint8*, buf->Data().Ptr());
+
+ MP4Err err = MP4ComposeWriteAudioFrames(iMP4Handle, buffer, buffersize, 0, 1024);
+
+ aBuffer->SetStatus(EAvailable);
+ iDuration = PositionL().Int64(); // update duration during recording state, base on position
+
+ return TranslateMP4Err(err);
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::PauseL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::PauseL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::PauseL"));
+
+ User::Leave(KErrNotSupported);
+
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::PrimeL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::PrimeL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::PrimeL"));
+
+ if ( iState == ERecording )
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ // Since Append is not supported on Recording, this function should leave if Duration is not equal to 0
+ if (iDuration == 0)
+ {
+ PrepareMP4ComposerL();
+
+ // Read the default codec configuration parameters from resource file
+ RArray<TInt>& codecConfigData = CONST_CAST(RArray<TInt>&, iAudioResource->CodecConfigParametersL());
+
+ codecConfigData[1] = iSampleRate; // configure the decoder with any user modified values.
+ codecConfigData[3] = iChannels;
+ iAudioInput->ConfigureL(iSampleRate, iChannels, iDataType, codecConfigData);
+ iAudioInput->PrimeL();
+ }
+ else
+ User::Leave(KErrNotSupported);
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::Play
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::PlayL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::PlayL"));
+
+ MP4Err err = MP4ComposeAddAudioDescription(iMP4Handle, (mp4_u32)iSampleRate, 1, 0);
+
+ DP1(_L("MP4ComposeAddAudioDescription err = %d"), err);
+ User::LeaveIfError(TranslateMP4Err(err));
+
+ ResetSharedBuffersL(iSharedBufferMaxNum, iSharedBufferMaxSize);
+ iAudioInput->RecordL(&iSharedBuffers);
+ iState = ERecording;
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::StopL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::StopL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::StopL"));
+ switch ( iState )
+ {
+ case ERecording:
+ DoStopL();
+ iState = EStopped;
+ break;
+
+ case EStopped:
+ break;
+
+ default:
+ Panic(EBadState);
+ break;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::SetPositionL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::SetPositionL(
+ const TTimeIntervalMicroSeconds& aPosition )
+ {
+ DP1(_L("C3GPAudioRecordControllerPlugin::SetPositionL pos = %d"), aPosition.Int64());
+
+ if ( aPosition > 0 ) // 3gp library doesn't support set position.
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::SendEvent
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::SendEvent(
+ const TMMFEvent& aEvent )
+ {
+ DP1(_L("C3GPAudioRecordControllerPlugin::SendEvent(%d)"), aEvent.iErrorCode);
+
+ iTimePositionInMicroSecs = 0;
+ iState = EStopped;
+ TRAP_IGNORE(CloseMP4ComposerL());
+ SendEventToClient(aEvent);
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::MarcCropL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::MarcCropL(
+ TBool /*aToEnd*/ )
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::MarcCropL"));
+ User::Leave(KErrNotSupported);
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::MarcAddMetaDataEntryL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::MarcAddMetaDataEntryL(const CMMFMetaDataEntry& aNewEntry)
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::MarcAddMetaDataEntryL"));
+ iMetaData->AddMetaDataEntryL(aNewEntry);
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::PrepareMP4ComposerL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::PrepareMP4ComposerL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::PrepareMP4ComposerL"));
+ MP4Err err = 0;
+
+ if ( iSinkType == KUidMmfFileSink )
+ {
+ CMMFFile* file = STATIC_CAST(CMMFFile*, iDataSink);
+ RFile fileHandle;
+ TRAP_IGNORE(fileHandle = file->FileL());
+
+ if (file->FilePath().Length() && (fileHandle.SubSessionHandle() == 0)) // File Path exists, not file handle
+ {
+ TFileName fileName = file->FullName();
+ err = MP4ComposeOpen(&iMP4Handle, (MP4FileName) fileName.Ptr(), MP4_TYPE_MPEG4_AUDIO);
+ DP1(_L("MP4ComposeOpen err = %d - Using File Name"), err);
+ }
+ else
+ {
+ err = MP4ComposeOpenFileHandle(&iMP4Handle, &fileHandle, (TDriveNumber)EDriveC, MP4_TYPE_MPEG4_AUDIO);
+ DP1(_L("MP4ComposeOpen err = %d - Using File Handle"), err);
+ }
+ User::LeaveIfError(TranslateMP4Err(err));
+
+ mp4_u32 flags = (MP4_FLAG_METADATALAST | MP4_FLAG_GENERATE_MP4 | MP4_FLAG_LONGCLIP );
+
+ err = MP4ComposeSetFlags(iMP4Handle, flags);
+ User::LeaveIfError(TranslateMP4Err(err));
+
+ }
+ else // KUidMmfDescriptorSink
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::UpdateMP4DurationL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::UpdateMP4DurationL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::UpdateMP4DurationL"));
+ MP4Err err = 0;
+
+ mp4_u32 audioLength, audioType, timeScale, averateBitRate;
+ mp4_u8 framesPerSample;
+
+ if ( iSinkType == KUidMmfFileSink )
+ {
+ CMMFFile* file = STATIC_CAST(CMMFFile*, iDataSink);
+ if (file->FilePath().Length()) // File Path exists, not file handle
+ {
+ TFileName fileName = file->FullName();
+ err = MP4ParseOpen(&iMP4Handle, (MP4FileName) fileName.Ptr());
+ DP1(_L("MP4ParseOpen err = %d - Using File Name"), err);
+ }
+ else
+ {
+ err = MP4ParseOpenFileHandle(&iMP4Handle, &(file->FileL()));
+ DP1(_L("MP4ParseOpen err = %d - Using File Handle"), err);
+ }
+ User::LeaveIfError(TranslateMP4Err(err));
+ }
+
+ err = MP4ParseRequestAudioDescription(iMP4Handle, &audioLength, &audioType,
+ &framesPerSample, &timeScale, &averateBitRate);
+
+ MP4ParseClose(iMP4Handle);
+ iMP4Handle = NULL;
+ User::LeaveIfError(TranslateMP4Err(err));
+ iDuration = (TInt64)audioLength*1000; // convert to microseconds
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::TranslateMP4Err
+// -----------------------------------------------------------------------------
+//
+TInt C3GPAudioRecordControllerPlugin::TranslateMP4Err(
+ MP4Err aError )
+ {
+ TInt err;
+ switch ( aError )
+ {
+ case MP4_OK:
+ err = KErrNone;
+ break;
+ case MP4_OUT_OF_MEMORY:
+ err = KErrNoMemory;
+ break;
+ case MP4_NOT_AVAILABLE:
+ err = KErrNotReady;
+ break;
+ case MP4_FILE_ERROR:
+ err = KErrBadHandle;
+ break;
+ case MP4_INVALID_TYPE:
+ err = KErrNotSupported;
+ break;
+ case MP4_TIMESCALE_NOT_SET:
+ err = KErrNotReady;
+ break;
+ case MP4_NOT_STREAMABLE:
+ case MP4_NO_REQUESTED_FRAME:
+ case MP4_CANT_SEEK:
+ case MP4_INVALID_INPUT_STREAM:
+ case MP4_NO_FRAME:
+ err = KErrArgument;
+ break;
+ case MP4_ERROR:
+ case MP4_FILE_MODE:
+ case MP4_BUFFER_TOO_SMALL:
+ case MP4_END_OF_VIDEO:
+ case MP4_NO_VIDEO:
+ case MP4_NO_AUDIO:
+ err = KErrGeneral;
+ break;
+ case MP4_METADATA_ERROR:
+ err = KErrWrite;
+ break;
+ default:
+ err = KErrGeneral;
+ break;
+ }
+ return err;
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::WriteDecoderSpecificInfoL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::WriteAudioDecoderSpecificInfoL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::WriteDecoderSpecificInfoL"));
+
+ HBufC8* decSpecInfo = NULL;
+ TUint8* buf = NULL;
+
+ decSpecInfo = HBufC8::NewLC(2);
+ buf = CONST_CAST(TUint8*, decSpecInfo->Ptr());
+
+ // constructing decoder specific information
+
+ TInt profile = 2; // Object type 2 AAC-LC
+
+ buf[0] = profile << 3;
+ TInt sampleFreqIndex = 0;
+
+ switch ( iSampleRate ) // maping sampling rate to sampling frequency index
+ {
+ case 96000:
+ sampleFreqIndex = 0x0;
+ break;
+ case 88200:
+ sampleFreqIndex = 0x1;
+ break;
+ case 64000:
+ sampleFreqIndex = 0x2;
+ break;
+ case 48000:
+ sampleFreqIndex = 0x3;
+ break;
+ case 44100:
+ sampleFreqIndex = 0x4;
+ break;
+ case 32000:
+ sampleFreqIndex = 0x5;
+ break;
+ case 24000:
+ sampleFreqIndex = 0x6;
+ break;
+ case 22050:
+ sampleFreqIndex = 0x7;
+ break;
+ case 16000:
+ sampleFreqIndex = 0x8;
+ break;
+ case 12000:
+ sampleFreqIndex = 0x9;
+ break;
+ case 11025:
+ sampleFreqIndex = 0xa;
+ break;
+ case 8000:
+ sampleFreqIndex = 0xb;
+ break;
+ default:
+ User::Leave(KErrNotSupported);
+ }
+
+ buf[0] = buf[0] | (sampleFreqIndex >> 1);
+ buf[1] = 0;
+ buf[1] = sampleFreqIndex << 7;
+
+ buf[1] = buf[1] | iChannels << 3;
+
+ //buf[1] = 0; // Frame Length Flag ( Don't know what this is ? )
+ //buf[1] = 0; // Depends on Core Coder flag ( no )
+ //buf[1] = 0; // Extension flag ( no extension )
+
+ MP4Err err = MP4ComposeWriteAudioDecoderSpecificInfo(iMP4Handle, buf, 2);
+ User::LeaveIfError(TranslateMP4Err(err));
+
+ CleanupStack::PopAndDestroy(decSpecInfo); // decSpecInfo
+
+
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::WriteHeaderL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::WriteHeaderL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::WriteHeaderL"));
+
+ CMMFDataBuffer* buffer = CMMFDataBuffer::NewL(32);
+ buffer->Data().FillZ(32);
+ buffer->Data().SetLength(0);
+ TDes8& bufDes = buffer->Data();
+
+ bufDes.Append(0x00);
+ bufDes.Append(0x00);
+ bufDes.Append(0x00);
+ bufDes.Append(0x1c);
+ bufDes.Append(_L("ftypmp4"));
+
+ CleanupStack::PushL(buffer);
+ WriteIfEnoughSpaceL(buffer, 0);
+ CleanupStack::PopAndDestroy(buffer);
+
+
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::GetDriveNumber
+// -----------------------------------------------------------------------------
+//
+TDriveNumber C3GPAudioRecordControllerPlugin::GetDriveNumber(
+ const TDesC& aDriveName )
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::GetDriveNumber"));
+ TDriveNumber driveNumber = EDriveC;
+
+ if ( !aDriveName.Length() )
+ {
+ return driveNumber;
+ }
+ else
+ {
+ switch ( aDriveName[0] )
+ {
+ case 'a':
+ case 'A':
+ driveNumber = EDriveA;
+ break;
+ case 'b':
+ case 'B':
+ driveNumber = EDriveB;
+ break;
+ case 'c':
+ case 'C':
+ driveNumber = EDriveC;
+ break;
+ case 'd':
+ case 'D':
+ driveNumber = EDriveD;
+ break;
+ case 'e':
+ case 'E':
+ driveNumber = EDriveE;
+ break;
+ case 'f':
+ case 'F':
+ driveNumber = EDriveF;
+ break;
+ case 'g':
+ case 'G':
+ driveNumber = EDriveG;
+ break;
+ case 'h':
+ case 'H':
+ driveNumber = EDriveH;
+ break;
+ case 'i':
+ case 'I':
+ driveNumber = EDriveI;
+ break;
+ case 'j':
+ case 'J':
+ driveNumber = EDriveJ;
+ break;
+ case 'k':
+ case 'K':
+ driveNumber = EDriveK;
+ break;
+ case 'l':
+ case 'L':
+ driveNumber = EDriveL;
+ break;
+ case 'm':
+ case 'M':
+ driveNumber = EDriveM;
+ break;
+ case 'n':
+ case 'N':
+ driveNumber = EDriveN;
+ break;
+ case 'o':
+ case 'O':
+ driveNumber = EDriveO;
+ break;
+ case 'p':
+ case 'P':
+ driveNumber = EDriveP;
+ break;
+ case 'q':
+ case 'Q':
+ driveNumber = EDriveQ;
+ break;
+ case 'r':
+ case 'R':
+ driveNumber = EDriveR;
+ break;
+ case 's':
+ case 'S':
+ driveNumber = EDriveS;
+ break;
+ case 't':
+ case 'T':
+ driveNumber = EDriveT;
+ break;
+ case 'u':
+ case 'U':
+ driveNumber = EDriveU;
+ break;
+ case 'v':
+ case 'V':
+ driveNumber = EDriveV;
+ break;
+ case 'x':
+ case 'X':
+ driveNumber = EDriveX;
+ break;
+ case 'y':
+ case 'Y':
+ driveNumber = EDriveY;
+ break;
+ case 'z':
+ case 'Z':
+ driveNumber = EDriveZ;
+ break;
+ default:
+ break;
+ }
+ }
+ return driveNumber;
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::MacGetSupportedSinkBitRatesL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::MacGetSupportedSinkBitRatesL(
+ RArray<TUint>& aSupportedRates )
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::MacGetSupportedSinkBitRatesL"));
+ if ( !iDataSink )
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ aSupportedRates.Reset();
+ const RArray<TUint>& supportedBitRates = STATIC_CAST(C3GPAudioRecordControllerResource*, iAudioResource)->SupportedBitRatesL();
+ TInt count = supportedBitRates.Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ User::LeaveIfError( aSupportedRates.Append(supportedBitRates[i]) );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::MacSetSinkBitRateL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::MacSetSinkBitRateL(
+ TUint aRate )
+ {
+ DP1(_L("C3GPAudioRecordControllerPlugin::MacSetSinkBitRateL [%d]"), aRate);
+ if ( !iDataSink || !iDataSource )
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ const RArray<TUint>& supportedBitRates = STATIC_CAST(C3GPAudioRecordControllerResource*, iAudioResource)->SupportedBitRatesL();
+ TInt count = supportedBitRates.Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ if ( supportedBitRates[i] == aRate )
+ {
+ iBitRate = aRate;
+ // Read the default codec configuration parameters from resource file
+ RArray<TInt>& codecConfigData = CONST_CAST(RArray<TInt>&, iAudioResource->CodecConfigParametersL());
+ iAudioInput->SetBitRateL(aRate, codecConfigData);
+ return;
+ }
+ }
+
+ // aRate is not one of the supportedBitRates!
+ User::Leave(KErrNotSupported);
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::MacGetSupportedSinkSampleRatesL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::MacGetSupportedSinkSampleRatesL(
+ RArray<TUint>& aSupportedRates )
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::MacGetSupportedSinkSampleRatesL"));
+ if ( !iDataSink )
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ aSupportedRates.Reset();
+
+ const RArray<TUint>& sinkSupportedSampleRates = STATIC_CAST(C3GPAudioRecordControllerResource*, iAudioResource)->SupportedSampleRatesL();
+
+ RArray<TUint> sourceSupportedSampleRates;
+ CleanupClosePushL(sourceSupportedSampleRates);
+ iAudioInput->CapabilitiesRatesL( sourceSupportedSampleRates );
+
+ // Check if the source supported sampling rate are the same as sink sampling rate.
+ for ( TInt i = 0; i < sourceSupportedSampleRates.Count(); i++ )
+ {
+ for ( TInt j = 0; j < sinkSupportedSampleRates.Count(); j++ )
+ {
+ if ( sinkSupportedSampleRates[j] == sourceSupportedSampleRates[i] )
+ {
+ User::LeaveIfError(aSupportedRates.Append(sourceSupportedSampleRates[i]));
+ break;
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(&sourceSupportedSampleRates); // sourceSupportedSampleRates
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::MacSetSinkSampleRateL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::MacSetSinkSampleRateL(
+ TUint aSampleRate )
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::MacSetSinkSampleRateL"));
+
+ if ( !iDataSink )
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ const RArray<TUint>& sinkSupportedSampleRates = STATIC_CAST(C3GPAudioRecordControllerResource*, iAudioResource)->SupportedSampleRatesL();
+
+ RArray<TUint> sourceSupportedSampleRates;
+ CleanupClosePushL(sourceSupportedSampleRates);
+ iAudioInput->CapabilitiesRatesL( sourceSupportedSampleRates );
+
+ // first check if the source supports the sampling rate
+ for ( TInt i = 0; i < sourceSupportedSampleRates.Count(); i++ )
+ {
+ if ( sourceSupportedSampleRates[i] == aSampleRate )
+ {
+ // then check if the sink also supports the sampling rate
+ for ( TInt j = 0; j < sinkSupportedSampleRates.Count(); j++ )
+ {
+ if ( sinkSupportedSampleRates[j] == aSampleRate )
+ {
+ iSampleRate = aSampleRate;
+ CleanupStack::PopAndDestroy(&sourceSupportedSampleRates); // sourceSupportedSampleRates
+ return;
+ }
+ }
+ User::Leave(KErrNotSupported);
+ }
+ }
+ User::Leave(KErrNotSupported);
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::MacGetSupportedSinkNumChannelsL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::MacGetSupportedSinkNumChannelsL(
+ RArray<TUint>& aSupportedChannels )
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::MacGetSupportedSinkNumChannelsL"));
+ if ( !iDataSink )
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ aSupportedChannels.Reset();
+
+ for (TInt i = 0; i < iSupportedChannels.Count(); i++)
+ {
+ User::LeaveIfError(aSupportedChannels.Append(iSupportedChannels[i]));
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::MacSetSinkNumChannelsL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::MacSetSinkNumChannelsL(
+ TUint aNumChannels )
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::MacSetSinkNumChannelsL"));
+ if ( !iDataSink )
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ if ( iSupportedChannels.Find(aNumChannels) >= 0 )
+ {
+ iChannels = aNumChannels;
+ }
+ else
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::DetermineSupportedNumChannelsL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::DetermineSupportedNumChannelsL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::DetermineSupportedNumChannelsL"));
+ if (iSupportedChannels.Count() == 0)
+ {
+ iAudioInput->CapabilitiesChannelsL(iSupportedChannels);
+ iSupportedChannels.Sort();
+
+ TAapProperties aapProperties = iAudioResource->PropertiesL();
+ TInt channels = 1;
+ if (aapProperties.iStereoSupport)
+ {
+ channels = 2;
+ }
+
+ // number of sink number of channels supported is limited/tied to source can support
+ while (channels < iSupportedChannels[iSupportedChannels.Count()-1])
+ {
+ iSupportedChannels.Remove(iSupportedChannels.Count()-1);
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::AddMetaDataWriteParserL
+// Add a MetaDataWrite Parser.
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::AddMetaDataWriteParserL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::AddMetaDataWriteParserL"));
+ CMetaDataWriteCustomCommandParser* metaDataWriteParser = CMetaDataWriteCustomCommandParser::NewL(*this);
+ CleanupStack::PushL(metaDataWriteParser);
+ AddCustomCommandParserL(*metaDataWriteParser);
+ CleanupStack::Pop(metaDataWriteParser);
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::MmdwcEnableMetaDataWrite
+// -----------------------------------------------------------------------------
+//
+TInt C3GPAudioRecordControllerPlugin::MmdwcEnableDelayWrite()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::MmdwcEnableDelayWrite"));
+ iEnableDelayWrite = ETrue;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::MmdwcCommitMetaData
+// -----------------------------------------------------------------------------
+//
+TInt C3GPAudioRecordControllerPlugin::MmdwcCommitMetaData()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::MmdwcCommitMetaData"));
+ if (iEnableDelayWrite && (iState == EStopped))
+ {
+ TRAPD(err, DoCommitMetaDataL());
+
+ return err;
+ }
+ else
+ return KErrNotReady;
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::DoCommitMetaDataL()
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::DoCommitMetaDataL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::DoCommitMetaDataL"));
+ if (iMP4Handle)
+ {
+ TRAPD(err, WriteUdtaL());
+ CloseMP4ComposerL();
+
+ if (err != KErrNone)
+ User::Leave(KErrWrite);
+ }
+ else
+ User::Leave(KErrNotReady);
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::WriteUdtaL
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::WriteUdtaL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::WriteUdtaL"));
+ HBufC8* buffer = iMetaData->GetUdtaAtomL();
+
+ if (buffer)
+ {
+ mp4_u8 udtalocation = MP4_UDTA_MOOV;
+ mp4_u32 udtalength = buffer->Length();
+
+ MP4Err err = MP4ComposeSetUserDataAtom(iMP4Handle, udtalocation, (mp4_u8*)(buffer->Ptr()), udtalength);
+
+ delete buffer;
+ User::LeaveIfError(TranslateMP4Err(err));
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPAudioRecordControllerPlugin::CloseMP4ComposerL()
+// -----------------------------------------------------------------------------
+//
+void C3GPAudioRecordControllerPlugin::CloseMP4ComposerL()
+ {
+ DP0(_L("C3GPAudioRecordControllerPlugin::CloseMP4ComposerL"));
+ if (iMP4Handle)
+ {
+ CMMFClip* clip = STATIC_CAST(CMMFClip*, iDataSink);
+
+ TRAPD(err0, WriteAudioDecoderSpecificInfoL()); // trap leave to ensure handle is closed properly in error situation
+
+ TInt err1 = TranslateMP4Err(MP4ComposeClose(iMP4Handle));
+
+ iMP4Handle = NULL;
+ clip->SinkStopL();
+ User::LeaveIfError(err0);
+ User::LeaveIfError(err1);
+ UpdateMP4DurationL();
+ }
+ }
+
+// __________________________________________________________________________
+// Exported proxy for instantiation method resolution
+// Define the interface UIDs
+
+/**
+*
+* ImplementationTable
+*
+*/
+const TImplementationProxy ImplementationTable[] =
+ {
+ // defined in 3GPAudioRecordControllerPluginUIDs.hrh
+ IMPLEMENTATION_PROXY_ENTRY(KUID3GPRecordControllerPluginImplementation, C3GPAudioRecordControllerPlugin::NewL)
+ };
+
+/**
+* ImplementationGroupProxy
+* @param aTableCount
+* @returns "TImplementationProxy*"
+*/
+
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
+ {
+ aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
+ return ImplementationTable;
+ }
+
+// End of file