sl@0: // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: //
sl@0: 
sl@0: 
sl@0: #include <mmf/server/mmfcodec.h>
sl@0: #include "MmfUtilities.h"
sl@0: #include <mmf/common/mmfcontrollerpluginresolver.h>
sl@0: #include <ecom/ecom.h>
sl@0: #include <mm/mmpluginutils.h>
sl@0: 
sl@0: _LIT8( KEmptyFourCCString, "    ,    " ) ;
sl@0: _LIT( KNullString, "" ) ;
sl@0: 
sl@0: static const TUid KUidMmfPluginInterfaceCodec = {KMmfUidPluginInterfaceCodec};
sl@0: 
sl@0: /**
sl@0: Creates a CMMFCodec object with match parameter in addition to the source and
sl@0: destination fourCC codes (for instance a manufacturer's name).
sl@0: 
sl@0: Will attempt match without extra match string if no match.
sl@0: 
sl@0: Will Leave if no match on 4CC codes (KErrNotFound).
sl@0: 
sl@0: Used where there may be multiple codecs that perform the same conversion to ensure the controller
sl@0: uses the codec specified by aPreferredSupplier.
sl@0: 
sl@0: @param  aSrcDataType
sl@0:         The source data type.
sl@0: @param  aDstDataType
sl@0:         The destination data type.
sl@0: @param  aPreferredSupplier
sl@0:         Additional resolution criteria when searching for plug in codec. If this is provided, the 
sl@0:         list of matching plugins will be further searched for the latest version of a plugin 
sl@0:         supplied by supplier named. Note that the display name field is parsed for a match.
sl@0: 
sl@0: @return An instantiated CMMFCodec derived obeject from an ECOM plugin DLL.
sl@0: */
sl@0: EXPORT_C CMMFCodec* CMMFCodec::NewL(const TFourCC& aSrcDataType, const TFourCC& aDstDataType,  const TDesC& aPreferredSupplier)
sl@0: 	{
sl@0: 
sl@0: 	// Create a match string using the two FourCC codes.
sl@0: 	TBufC8<9> fourCCString( KEmptyFourCCString ) ;
sl@0: 	TPtr8 fourCCPtr = fourCCString.Des() ;
sl@0: 	TPtr8 fourCCPtr1( &fourCCPtr[0], 4 ) ;
sl@0: 	TPtr8 fourCCPtr2( &fourCCPtr[5], 4 ) ;
sl@0: 	aSrcDataType.FourCC( &fourCCPtr1 ) ;
sl@0: 	aDstDataType.FourCC( &fourCCPtr2 ) ;
sl@0: 
sl@0: 	// Do a list implementations here.
sl@0: 
sl@0: 	RImplInfoPtrArray plugInArray; // Array to return matching decoders in
sl@0: 	CleanupResetAndDestroyPushL(plugInArray);
sl@0: 
sl@0: 	MmPluginUtils::FindImplementationsL(KUidMmfPluginInterfaceCodec, plugInArray, fourCCPtr);
sl@0: 
sl@0: 	if (plugInArray.Count() == 0)
sl@0: 		{
sl@0: 		User::Leave(KErrNotSupported);
sl@0: 		}
sl@0: 
sl@0: 	TUid chosenUid = {0};
sl@0: 
sl@0: 	if ( plugInArray.Count() == 1 )
sl@0: 		{
sl@0: 		chosenUid = plugInArray[0]->ImplementationUid() ;
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		// Use the preferred supplier to select a codec.
sl@0: 		SelectByPreference( plugInArray, aPreferredSupplier ) ;
sl@0: 		for ( TInt ii = 0 ; ii < plugInArray.Count() ; ii++ )
sl@0: 			{
sl@0: 			if ( !(plugInArray[ii]->Disabled()) )
sl@0: 				{
sl@0: 				// we've found our plugin...
sl@0: 				chosenUid = plugInArray[ii]->ImplementationUid() ;
sl@0: 				break ;
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	//Instantiate the chosen one
sl@0: 	CMMFCodec* theChosenOne = REINTERPRET_CAST( CMMFCodec*,
sl@0: 						REComSession::CreateImplementationL( chosenUid, _FOFF( CMMFCodec, iDtor_ID_Key ) ) ) ;
sl@0: 
sl@0: 	CleanupStack::PopAndDestroy() ;  // pluginArray
sl@0: 
sl@0: 	return theChosenOne ;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Creates a CMMFCodec object with known fourCC codes for source and destination.
sl@0: The first matching plug-in will be used.
sl@0: 
sl@0: The FourCC codes are the same codes as those specified in the resource file and are used to identify
sl@0: the datatype. ECom scans the registry to find a codec that is registered in its resource file as
sl@0: being able to convert between the source data type and the destination data type as specified by
sl@0: their FourCC codes. If a match is found then an instantiation of the appropriate CMMFCodec is made.
sl@0: If a match is not found this function leaves with KErrNotFound. If more than one codec is present
sl@0: with the same fourCC match codes then the one that is instantiated is indeterminate. If there is
sl@0: likely to be any ambiguity due to more than one codec that performs the same conversion being
sl@0: present, then a preferred supplier should be specified.
sl@0: 
sl@0: @param  aSrcDataType
sl@0:         The source data type.
sl@0: @param  aDstDataType
sl@0:         The destination data type.
sl@0: 
sl@0: @return An instantiated CMMFCodec derived obeject from an ECOM plugin DLL.
sl@0: */
sl@0: EXPORT_C CMMFCodec* CMMFCodec::NewL(const TFourCC& aSrcDataType, const TFourCC& aDstDataType )
sl@0: 	{
sl@0: 	// Create a match string using the two FourCC codes.
sl@0: 	return NewL( aSrcDataType, aDstDataType, KNullString ) ;
sl@0: 
sl@0: 	}
sl@0: 
sl@0: 
sl@0: // local function to disable items which do not match the preferred supplier.
sl@0: // Note that at least one enabled item is returned (if there was an enabled item to begin with) which
sl@0: // may not match the preferred supplier.
sl@0: /**
sl@0: Selects a codec according to the specified preference.
sl@0: 
sl@0: @param  aPlugInArray
sl@0:         On return, array of plugins.
sl@0: @param  aPreferredSupplier
sl@0:         Search criteria, a supplier's name for example.
sl@0: */
sl@0: void CMMFCodec::SelectByPreference( RImplInfoPtrArray& aPlugInArray, const TDesC& aPreferredSupplier )
sl@0: 	{	
sl@0: 	// Use the Disabled flag to eliminated all currently enabled matches that
sl@0: 	// do not match the preferred supplier.
sl@0: 	TInt firstEnabled = -1 ; // to ensure that we return something valid
sl@0: 	TInt matchCount = 0 ;
sl@0: 	for ( TInt ii = 0 ; ii < aPlugInArray.Count() ; ii++ )
sl@0: 		{
sl@0: 		if ( !( aPlugInArray[ii]->Disabled() ) )
sl@0: 			{
sl@0: 			if ( firstEnabled == -1 )
sl@0: 				firstEnabled = ii ;
sl@0: 			if ( aPlugInArray[ii]->DisplayName().FindF( aPreferredSupplier ) == KErrNotFound )
sl@0: 				aPlugInArray[ii]->SetDisabled( ETrue ) ;
sl@0: 			else
sl@0: 				matchCount++ ;
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	// If there are no matches then re-enable the first enabled
sl@0: 	if ( matchCount == 0 )
sl@0: 		aPlugInArray[firstEnabled]->SetDisabled( EFalse ) ;
sl@0: 	else if ( matchCount > 1 )
sl@0: 		{
sl@0: 		// find the latest version from more than one match
sl@0: 		TInt highestVersionIndex = -1 ;
sl@0: 		for ( TInt ii = 0 ; ii < aPlugInArray.Count() ; ii++ )
sl@0: 			{
sl@0: 			if ( !( aPlugInArray[ii]->Disabled() ) )  // only interested in enabled elements
sl@0: 				{
sl@0: 				if ( highestVersionIndex == -1 )
sl@0: 					{ // first match.  Store this.  Keep it enabled
sl@0: 					highestVersionIndex = ii ;
sl@0: 					}
sl@0: 				else if ( aPlugInArray[ii]->Version() > aPlugInArray[highestVersionIndex]->Version() )
sl@0: 					{ // a new leader.  Disable the previous leader.  Keep this one.
sl@0: 					aPlugInArray[highestVersionIndex]->SetDisabled( ETrue ) ;
sl@0: 					highestVersionIndex = ii ;
sl@0: 					}
sl@0: 				else  // we already have a higher version.
sl@0: 					aPlugInArray[ii]->SetDisabled( ETrue ) ;
sl@0: 				}
sl@0: 			}
sl@0: 		}	
sl@0: 	}
sl@0: 
sl@0: 
sl@0: /**
sl@0: Creates a CMMFCodec object with a known UID.
sl@0: 
sl@0: Will Leave if the plug in is not found (KErrNotFound).
sl@0: 
sl@0: @param aUid
sl@0:        The UID of a plugin implementation.
sl@0: 
sl@0: @return An instantiated CMMFCodec derived obeject from an ECOM plugin DLL.
sl@0: */
sl@0: EXPORT_C CMMFCodec* CMMFCodec::NewL(TUid aUid)
sl@0: 	{
sl@0: 	return REINTERPRET_CAST(CMMFCodec*, REComSession::CreateImplementationL(aUid,
sl@0: 												_FOFF(CMMFCodec,iDtor_ID_Key)));
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @internalComponent
sl@0: 
sl@0: Gets a pointer to the extension specified by an identifier. The extension can be either an
sl@0: interface or function. If the extension is not supported NULL value is given and returns
sl@0: KErrExtensionNotSupported.
sl@0: 
sl@0: @param	aExtensionId
sl@0: 		Extension identifier.
sl@0: @param	aExtPtr
sl@0: 		Pointer to get the extension.
sl@0: @return	If successful returns KErrNone otherwise KErrExtensionNotSupported.		
sl@0: */
sl@0: TInt CMMFCodec::ExtensionInterface(TUint aExtensionId, TAny*& aExtPtr)
sl@0: 	{
sl@0: 	return Extension_(aExtensionId, aExtPtr, NULL);	
sl@0: 	}
sl@0: