diff -r 000000000000 -r 40261b775718 devsound/devsoundrefplugin/src/sounddevice/DevSoundUtility.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/devsound/devsoundrefplugin/src/sounddevice/DevSoundUtility.cpp Tue Feb 02 01:56:55 2010 +0200 @@ -0,0 +1,532 @@ +// Copyright (c) 2001-2009 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: +// MMF\SoundDev\src\SoundDevice\DevSoundUtility.cpp +// File: DevSoundUtility.cpp +// Author: Vasudevan Ramachandraiah +// Date: July 16, 2002 +// Class that provides API to list ECOM plugin implementation IDs +// (c) Nokia Inc. +// Revisions: +// Date: Author Description +// +// + +#include +#include +#include +#include +#include +#include +#include "DevSoundUtility.h" +#include //needed for CleanupResetAndDestroyPushL() +#include +#ifdef SYMBIAN_MULTIMEDIA_CODEC_API +#include +#include +#include +#include +#endif // SYMBIAN_MULTIMEDIA_CODEC_API + +_LIT(KFixedSequenceResourceFile, "Z:\\Resource\\DevSound\\FixedSequence.rsc"); +const TInt KFourCCStringLength = 9; + +inline TMMFRawPackage::TMMFRawPackage(TInt aDerivedSize) +#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list +: iThis((TUint8*)this,aDerivedSize,aDerivedSize) +#pragma warning( default : 4355 ) + { + } + +inline TPtr8& TMMFRawPackage::Package() + { + ((TMMFRawPackage*)this)->iThis.Set((TUint8*)this,iThis.Length(),iThis.MaxLength()); + return iThis; + } + +inline const TPtr8& TMMFRawPackage::Package() const + { + ((TMMFRawPackage*)this)->iThis.Set((TUint8*)this,iThis.Length(),iThis.MaxLength()); + return iThis; + } + +inline void TMMFRawPackage::SetSize(TInt aDerivedSize) + { + iThis.Set((TUint8*)this,aDerivedSize,aDerivedSize); + } + +inline TMMFToneFixedSequenceNames::TMMFToneFixedSequenceNames() : +TMMFRawPackage(sizeof(TMMFToneFixedSequenceNames)) {} + +#ifdef _UNICODE +class TNameBuf : public TBufCBase16 +#else +class TNameBuf : public TBufCBase8 +#endif + { + friend class HMMFToneFixedSequenceNames; + }; + +HMMFToneFixedSequenceNames::HMMFToneFixedSequenceNames() + { + iCount = 0; + } + +HMMFToneFixedSequenceNames* HMMFToneFixedSequenceNames::AddNameL(const TDesC& aName) +// Append a copy of the supplied descriptor to the end of the +// current heap cell. This will involve a realloc that will normally +// result in the object moving + { + TInt size = Package().Length(); + TInt desSize = aName.Size() + sizeof(TInt); + if (desSize&3) + desSize = ((desSize+4)&(~3)); // Must round up to word boundary to keep aligned + HMMFToneFixedSequenceNames* self = REINTERPRET_CAST(HMMFToneFixedSequenceNames*,User::ReAllocL(STATIC_CAST(TAny*,this),size + desSize)); + TUint8* newDesPtr = REINTERPRET_CAST(TUint8*,self) + size; + Mem::FillZ(newDesPtr,desSize); + TNameBuf* newDes = REINTERPRET_CAST(TNameBuf*,newDesPtr); + newDes->Copy(aName,aName.Length()); + self->SetSize(size+desSize); + self->iCount++; + return self; + } + + +/****************************************************************** + * CMMFDevSoundUtility + ******************************************************************/ +CMMFDevSoundUtility::CMMFDevSoundUtility() + { + // No default implementation + } + + +CMMFDevSoundUtility::~CMMFDevSoundUtility() + { + delete iInfo; + delete iFixedSequenceNames; + } + +CMMFDevSoundUtility* CMMFDevSoundUtility::NewL() + { + CMMFDevSoundUtility* self = NewLC(); + CleanupStack::Pop(); + return self; + } + +CMMFDevSoundUtility* CMMFDevSoundUtility::NewLC() + { + CMMFDevSoundUtility* self = new(ELeave) CMMFDevSoundUtility(); + CleanupStack::PushL(self); + self->ConstructL(); + // Leave it on Cleanupstack + return self; + } + +void CMMFDevSoundUtility::ConstructL() + { + iFixedSequenceNames = new (ELeave) HMMFToneFixedSequenceNames; + } + +void CMMFDevSoundUtility::SeekUsingFourCCL(TUid aInterfaceUid, RImplInfoPtrArray& aPlugInArray, const TFourCC& aSrcDataType, const TFourCC& aDstDataType, const TDesC& aPreferredSupplier) + { + + // Create a match string using the two FourCC codes. + _LIT8(KEmptyFourCCString, " , "); + TBufC8 fourCCString(KEmptyFourCCString); + TPtr8 fourCCPtr = fourCCString.Des(); + TPtr8 fourCCPtr1(&fourCCPtr[0], 4); + TPtr8 fourCCPtr2(&fourCCPtr[5], 4 ); + aSrcDataType.FourCC(&fourCCPtr1); + aDstDataType.FourCC(&fourCCPtr2); + + MmPluginUtils::FindImplementationsL(aInterfaceUid, aPlugInArray, fourCCPtr); + + // If more than one match. Narrow the search by preferred supplier + if((aPlugInArray.Count() > 1) && aPreferredSupplier.Length()) + { + SelectByPreference( aPlugInArray, aPreferredSupplier ); + } + + // If there are no plugins, return failure + if(aPlugInArray.Count() == 0) + { + User::Leave( KErrNotFound ); + } + } + + +#ifdef SYMBIAN_MULTIMEDIA_CODEC_API +void CMMFDevSoundUtility::FindHwDeviceAdapterL(TUid aInterfaceUid, RImplInfoPtrArray& aPlugInArray) + { + // Create a match string using the two FourCC codes. + _LIT8(KAdapterMatch, "*"); + + MmPluginUtils::FindImplementationsL(aInterfaceUid, aPlugInArray, KAdapterMatch); + + // If there are no plugins, return failure + + if(aPlugInArray.Count() == 0) + { + User::Leave( KErrNotFound ); + } + } + +void CMMFDevSoundUtility::SeekCodecPluginsL(RArray& aSupportedDataTypes, TMMFState aState, TBool aAppend) + { + _LIT8(KPCM16FourCCString, " P16"); + //check argument precondition for aState + if ((aState != EMMFStatePlaying) && (aState != EMMFStateRecording)) + { + User::Leave(KErrArgument); + } + + if (!aAppend) + { + aSupportedDataTypes.Reset(); //clear any existing data in aSupportedDataTypes array if not appending + } + + CCodecApiResolverData* customMatchData = CCodecApiResolverData::NewLC(); + if (aState == EMMFStatePlaying) + { + customMatchData->SetMatchType(EMatchOutputDataFormat); + customMatchData->SetOutputDataL(KPCM16FourCCString); + } + else + { + customMatchData->SetMatchType(EMatchInputDataFormat); + customMatchData->SetInputDataL(KPCM16FourCCString); + } + + customMatchData->SetImplementationType(TUid::Uid(KUidAudioCodec)); + + HBufC8* package = customMatchData->NewPackLC(); + + RImplInfoPtrArray ecomArray; + CleanupResetAndDestroyPushL(ecomArray); + + TInt err = KErrNone; + MmPluginUtils::FindImplementationsL(TUid::Uid(KUidMdfProcessingUnit), ecomArray, *package, TUid::Uid(KUidCodecApiResolverImplementation)); + + for (TInt i=0 ; i < ecomArray.Count() ; i++) + { + CCodecApiOpaqueData* data = NULL; + TRAP(err, data = CCodecApiOpaqueData::NewL(ecomArray[i]->OpaqueData())); + // simply ignore plugins that we can't parse the opaque data. They should not cause other plugins + // to fall over + if (err == KErrNone) + { + const TDesC8* dataType; + if (aState == EMMFStatePlaying) + { + dataType = &data->InputDataType(); + } + else + { + dataType = &data->OutputDataType(); + } + TFourCC fourCC(*dataType); + delete data; + aSupportedDataTypes.AppendL(fourCC); + } + } + CleanupStack::PopAndDestroy(3, customMatchData); + } +#endif // SYMBIAN_MULTIMEDIA_CODEC_API + +/* + * local function to disable items which do not match the preferred supplier. + * Note that at least one enabled item is returned (if there was an enabled item to begin with) which + * may not match the preferred supplier. + * + */ +void CMMFDevSoundUtility::SelectByPreference( RImplInfoPtrArray& aPlugInArray, const TDesC& aPreferredSupplier ) + { + + // Use the Disabled flag to eliminated all currently enabled matches that + // do not match the preferred supplier. + TInt firstEnabled = -1 ; // to ensure that we return something valid + TInt matchCount = 0 ; + for ( TInt ii = 0 ; ii < aPlugInArray.Count() ; ii++ ) + { + if ( !( aPlugInArray[ii]->Disabled() ) ) + { + if ( firstEnabled == -1 ) + firstEnabled = ii ; + if ( aPlugInArray[ii]->DisplayName().FindF( aPreferredSupplier ) == KErrNotFound ) + aPlugInArray[ii]->SetDisabled( ETrue ) ; + else + matchCount++ ; + } + } + + // If there are no matches then re-enable the first enabled + if ( matchCount == 0 ) + aPlugInArray[firstEnabled]->SetDisabled( EFalse ) ; + else if ( matchCount > 1 ) + { + // find the latest version from more than one match + TInt highestVersionIndex = -1 ; + for ( TInt ii = 0 ; ii < aPlugInArray.Count() ; ii++ ) + { + if ( !( aPlugInArray[ii]->Disabled() ) ) // only interested in enabled elements + { + if ( highestVersionIndex == -1 ) + { // first match. Store this. Keep it enabled + highestVersionIndex = ii ; + } + else if ( aPlugInArray[ii]->Version() > aPlugInArray[highestVersionIndex]->Version() ) + { // a new leader. Disable the previous leader. Keep this one. + aPlugInArray[highestVersionIndex]->SetDisabled( ETrue ) ; + highestVersionIndex = ii ; + } + else // we already have a higher version. + aPlugInArray[ii]->SetDisabled( ETrue ) ; + } + } + } + } + + +/* + * SeekHwDevicePluginsL + * This method looks for hwDevicePlugins that support the state given in aState which + * must be either EMMFStatePlaying or EMMFStateRecording + * For each HwDevice plugin found the datatype as indicated by its fourCC code + * from the default_data field in the resource file is added to the array of aSupportedDataTypes + * + * @internalComponent + * + * @param "RArray& aSupportedDataTypes" + * an array of fourCC codes that has a fourCC code added to for each hardware device found + * + * @param "TMMFState aState" + * must be set to EMMFStatePlaying if seeking HwDevice plugins that support play and + * EMMFStateRecording if seeking HwDevice plugins that support record + * + * @leave KErrArgument if aState is not EMMFStatePlaying or EMMFStateRecording else leaves + * with standard symbian OS error code + */ +void CMMFDevSoundUtility::SeekHwDevicePluginsL(RArray& aSupportedDataTypes, TMMFState aState) + { + //check argument precondition for aState + if ((aState != EMMFStatePlaying) && (aState != EMMFStateRecording)) + { + User::Leave(KErrArgument); + } + + aSupportedDataTypes.Reset(); //clear any existing data in aSupportedDataTypes array + + RImplInfoPtrArray plugInArray ; // Array to return hw device plugin resource info + CleanupResetAndDestroyPushL(plugInArray); + + TUid KUidMmfHWPluginInterfaceCodec = {KMmfUidPluginInterfaceHwDevice}; + + MmPluginUtils::FindImplementationsL(KUidMmfHWPluginInterfaceCodec, plugInArray); + + TUint numberOfHwDevicePlugins = plugInArray.Count(); + + //if have hwdevice plugin resource entries then scan entries + //matching on a datatype of pcm16 as the destination datatype for play and the + //source datatype for record + //if a match is found and isn't already in list of supported data types + //then add it to the list + if (numberOfHwDevicePlugins) + { + CImplementationInformation* hwDeviceResourceEntry = NULL; + _LIT8(KPCM16FourCCString, " P16"); + TBufC8 fourCCStringPCM16(KPCM16FourCCString); + TPtr8 fourCCPtrPCM16 = fourCCStringPCM16.Des(); + TUint entryNumber = 0; + + //check each resource entry for dst 4CC = P16 for play and src 4CC = P16 for record + for (TUint hwDeviceEntry = 0; hwDeviceEntry < numberOfHwDevicePlugins; hwDeviceEntry++) + { + hwDeviceResourceEntry = plugInArray[hwDeviceEntry]; + if (IsDataTypeMatch(hwDeviceResourceEntry, fourCCPtrPCM16, aState)) + {//resource entry data field has dest/src datatype ' P16' ie pcm16 for play/record + TPtrC8 fourCCPtr(0,0); + if (aState == EMMFStatePlaying)//then datatype supported 4CC is left 4 chars + { + fourCCPtr.Set(hwDeviceResourceEntry->DataType().Left(KFourCCLength)); + } + else if (aState == EMMFStateRecording) //then datatype supported 4CC is right 4 chars + { + fourCCPtr.Set(hwDeviceResourceEntry->DataType().Right(KFourCCLength)); + } + TFourCC fourCCEntry(fourCCPtr); + //need to check if entry already exists to prevent duplicate entries + entryNumber = aSupportedDataTypes.Count(); + TBool alreadyExists = EFalse; + for (TUint fourCCEntryNumber = 0; fourCCEntryNumber < entryNumber; fourCCEntryNumber++) + { + if (aSupportedDataTypes[fourCCEntryNumber]==fourCCEntry) + { + alreadyExists = ETrue;//we already have this 4CC in the supported data types + break; + } + } + if (!alreadyExists) + { + TInt err = aSupportedDataTypes.Append(fourCCEntry); + if (err) + {//note we don't destroy array because we don't own it + //but we do reset it as it is incomplete + aSupportedDataTypes.Reset(); + User::Leave(err); + } + } + }//if (IsDataTypeMatch(hwDeviceResourceEntry, fourCCPtrPCM16, aState)) + }//for (TUint hwDeviceEntry = 0; hwDeviceEntry < numberOfHwDevicePlugins; hwDeviceEntry++) + }//if (numberOfHwDevicePlugins) + + CleanupStack::PopAndDestroy(&plugInArray); + } + + +/* + * IsDataTypeMatch + * This method takes a given resource entry from a hardware device and determines + * whether the hwdevice plugin is a data type match for playing or recording + * depending on the setting of aState + * The method matchs the default_data field from the hw device resource entry matching + * it with the aHwMatchFourCC code. + * + * @internalComponent + * + * @param "CImplementationInformation aHwDeviceResourceEntry" + * the hw device resource entry that is to be checked + * whether it can be used to play or record + * + * @param "TDesC8& aHwMatchFourCC + * the data type fourCC code to match to that the hardware device that must convert to for + * playing and convert from for recording - for the reference DevSound this is always ' P16' ie pcm16 + * + * @param "TMMFState aState" + * this determines whether the match is for playing or recording and should take + * either the values EMMFStatePlaying or EMMFStateRecording + * + * @return ETrue if a match for play or record else EFalse + */ +TBool CMMFDevSoundUtility::IsDataTypeMatch(CImplementationInformation* aHwDeviceResourceEntry,const TDesC8& aHwMatchFourCC, TMMFState aState) + { + TBool match = EFalse; + // extra length safety check to remove adapter plugins and incorrect ones + if (aHwDeviceResourceEntry->DataType().Length()>=KFourCCStringLength) + { + if (aState == EMMFStatePlaying) + {//play need to match with the right four characters + match = (!(aHwMatchFourCC.Match(aHwDeviceResourceEntry->DataType().Right(KFourCCLength))==KErrNotFound)); + } + else if (aState == EMMFStateRecording) + {//record need to match with the left four characters + match = (!(aHwMatchFourCC.Match(aHwDeviceResourceEntry->DataType().Left(KFourCCLength))==KErrNotFound)); + } + } + return match; + } + + +/** + * Populate fixed sequences + * + */ +void CMMFDevSoundUtility::InitializeFixedSequenceL(CPtrC8Array** aFixedSequences) + { + + RFs fsSession; + User::LeaveIfError(fsSession.Connect()); + CleanupClosePushL(fsSession); + + // Open the resource file + RResourceFile resourceFile; + resourceFile.OpenL(fsSession, KFixedSequenceResourceFile); + CleanupClosePushL(resourceFile); + + // Allocate buffer to hold resource data in binary format + iInfo = resourceFile.AllocReadL(FIXED_TONE_SEQUENCE); + + TResourceReader reader; + reader.SetBuffer(iInfo); + + // Create array to hold fixed sequences data + CPtrC8Array* tempSequences = new(ELeave) CPtrC8Array(8); // granularity + CleanupStack::PushL(tempSequences); + + // First word gives number of entries + TInt numberOfEntries = reader.ReadUint16(); + ASSERT(!(numberOfEntries&1)); // Should have atleast one entry + + // There must be an even number entries as each sequence structure + // is made of a name string and a data string (SEQUENCE_NAME and SEQUENCE_DATA) + + HMMFToneFixedSequenceNames* names = new (ELeave) HMMFToneFixedSequenceNames; + CleanupStack::PushL(names); + for (TInt i=0;iAddNameL(reader.ReadTPtrC()); + if (names != newNames) + { // May have moved so fixup cleanupstack reference + CleanupStack::Pop(); + names = newNames; + CleanupStack::PushL(names); + } + TInt len = reader.ReadUint16(); + TPtrC8 tempTPtrC8(REINTERPRET_CAST(const TUint8*,reader.Ptr()),len<<1); + tempSequences->AppendL(tempTPtrC8); + reader.Advance(len<<1); + } + CleanupStack::Pop(); // names + + // Delete the old fixed sequence names + delete iFixedSequenceNames; + iFixedSequenceNames = NULL; + iFixedSequenceNames = names; + + *aFixedSequences = tempSequences; + CleanupStack::Pop(tempSequences); + CleanupStack::PopAndDestroy(2); // resourceFile, fsSession + } + +TBool CMMFDevSoundUtility::RecognizeSequence(const TDesC8& aData) + { + // Reference plug-in only supports its own sequence format + _LIT8(KSequenceSignature,"SQNC"); + if (aData.Length() > 4) + { + if (aData.Left(4) == KSequenceSignature) + return ETrue; + } + // Didn't recognise + return EFalse; + } + +const TDesC& CMMFDevSoundUtility::FixedSequenceName(TInt aSequenceNumber) + { + ASSERT(iFixedSequenceNames); // Defect if this not true when previous was true + ASSERT((aSequenceNumber>=0)&&(aSequenceNumberiCount)); + + // Ptr to first descriptor + TUint8* ptr = REINTERPRET_CAST(TUint8*,&(iFixedSequenceNames->iCount))+sizeof(TInt); + TDesC* desPtr = REINTERPRET_CAST(TDesC*,ptr); // First des + while (aSequenceNumber--) + { + TInt size = desPtr->Size(); + if (size&3) + size = ((size+4)&(~3)); + ptr += sizeof(TInt) + size; + desPtr = REINTERPRET_CAST(TDesC*,ptr); // Next des + } + return *desPtr; + }