sl@0: // Copyright (c) 2005-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: #include "MmfDevSoundCIMuxUtility.h"
sl@0: #include <mmf/plugin/mmfdevsoundcustominterface.hrh>
sl@0: #include <mmf/server/mmfdevsoundcustominterface.h>
sl@0: #include <ecom/ecom.h>
sl@0: #include <mm/mmpluginutils.h>
sl@0: 
sl@0: const TInt KMuxTempBufferSize = 20;
sl@0: 
sl@0: 
sl@0: CMMFDevSoundCIMuxUtility* CMMFDevSoundCIMuxUtility::NewL(MMMFDevSoundCustomInterfaceChannel* aCustomChannel)
sl@0: 	{
sl@0: 	CMMFDevSoundCIMuxUtility* self = new (ELeave) CMMFDevSoundCIMuxUtility(aCustomChannel);
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL();
sl@0: 	CleanupStack::Pop(self);
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: void CMMFDevSoundCIMuxUtility::ConstructL()
sl@0: 	{
sl@0: 	// nothing needed in this implementation
sl@0: 	}
sl@0: 
sl@0: CMMFDevSoundCIMuxUtility::~CMMFDevSoundCIMuxUtility()
sl@0: 	{
sl@0: 	iAsyncCustomCommandCleanup.ResetAndDestroy();
sl@0: 	iAsyncCustomCommandCleanup.Close();	
sl@0: 	}
sl@0: 
sl@0: // create a custom interface Mux implementation
sl@0: MMMFDevSoundCustomInterfaceMuxPlugin* CMMFDevSoundCIMuxUtility::CreateCustomInterfaceMuxL(TUid aInterfaceId)
sl@0: 	{
sl@0: 	// The Uid of the plugin will be used as string for matching the best suitable plug in.
sl@0: 	TInt uidAsInteger = aInterfaceId.iUid;
sl@0: 	TBuf8<KMuxTempBufferSize> tempBuffer;
sl@0: 	tempBuffer.Num(uidAsInteger, EHex);
sl@0: 	TUid interfaceUid = {KUidDevSoundCustomInterfaceMux};
sl@0: 	
sl@0: 	TUid destructorKey;
sl@0: 	MMMFDevSoundCustomInterfaceMuxPlugin* self = 
sl@0: 		static_cast<MMMFDevSoundCustomInterfaceMuxPlugin*>
sl@0: 		(MmPluginUtils::CreateImplementationL(interfaceUid, destructorKey, tempBuffer, KRomOnlyResolverUid));
sl@0: 
sl@0: 	// pass the destructor key so class can destroy itself
sl@0: 	self->PassDestructorKey(destructorKey);
sl@0: 	CleanupReleasePushL(*self);
sl@0: 
sl@0: 	// attempt to construct the plugin
sl@0: 	self->CompleteConstructL(this);
sl@0: 	CleanupStack::Pop(); // self
sl@0: 		
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: 	
sl@0: // from MMMFDevSoundCustomInterfaceMux interface
sl@0: TInt CMMFDevSoundCIMuxUtility::OpenSlave(TUid aInterface, const TDesC8& aPackageBuf)
sl@0: 	{
sl@0: 	// 1. send openslave custom command to remote side
sl@0: 	// 2. devsoundsession intercepts this custom command
sl@0: 	//    and creates / opens interface
sl@0: 	TA3FCustomInterfaceCommand command;
sl@0: 	command.iType = EMMFDevSoundCustomCommandCIOpenSlave;
sl@0: 	command.iCommand = 0; // No custom command passed on an OpenSlave
sl@0: 	command.iHandle = aInterface.iUid;
sl@0: 	TPckgBuf<TA3FCustomInterfaceCommand> commandBuffer(command);
sl@0: 	return iCustomChannel->SyncCustomCommand(KUidInterfaceMMFDevSound, commandBuffer, aPackageBuf, NULL);
sl@0: 	}
sl@0: 	
sl@0: void CMMFDevSoundCIMuxUtility::CloseSlave(TInt aHandle)
sl@0: 	{
sl@0: 	// 1. send closeslave custom command to remote side
sl@0: 	// 2. demuxplugin removes its handle for this interface
sl@0: 	TA3FCustomInterfaceCommand command;
sl@0: 	command.iType = EMMFDevSoundCustomCommandCICloseSlave;
sl@0: 	command.iCommand = 0; // No custom command passed on a CloseSlave
sl@0: 	command.iHandle = aHandle;
sl@0: 	TPckgBuf<TA3FCustomInterfaceCommand> commandBuffer(command);
sl@0: 	iCustomChannel->SyncCustomCommand(KUidInterfaceMMFDevSound, commandBuffer, KNullDesC8, NULL);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: TInt CMMFDevSoundCIMuxUtility::SendSlaveSyncCommand(TInt aHandle, TInt aCommand, const TDesC8& aPackageBuf)
sl@0: 	{
sl@0: 	TA3FCustomInterfaceCommand command;
sl@0: 	command.iType = EMMFDevSoundCustomCommandCISendSlaveSyncCommand;
sl@0: 	command.iCommand = aCommand;
sl@0: 	command.iHandle = aHandle;
sl@0: 	TPckgBuf<TA3FCustomInterfaceCommand> commandBuffer(command);
sl@0: 	
sl@0: 	return iCustomChannel->SyncCustomCommand(KUidInterfaceMMFDevSound, commandBuffer, aPackageBuf, NULL);
sl@0: 	}
sl@0: 
sl@0: TInt CMMFDevSoundCIMuxUtility::SendSlaveSyncCommandResult(TInt aHandle, TInt aCommand, const TDesC8& aPackageBuf, TDes8& aResultBuf)
sl@0: 	{
sl@0: 	TA3FCustomInterfaceCommand command;
sl@0: 	command.iType = EMMFDevSoundCustomCommandCISendSlaveSyncCommandResult;
sl@0: 	command.iCommand = aCommand;
sl@0: 	command.iHandle = aHandle;
sl@0: 	TPckgBuf<TA3FCustomInterfaceCommand> commandBuffer(command);
sl@0: 
sl@0: 	return iCustomChannel->SyncCustomCommand(KUidInterfaceMMFDevSound, commandBuffer, aPackageBuf, &aResultBuf);
sl@0: 	}
sl@0: 
sl@0: void CMMFDevSoundCIMuxUtility::SendSlaveAsyncCommand(TMMFDevSoundCustomInterfaceCommandPackage& aComPackage, TRequestStatus& aStatus, const TDesC8& aPackageBuf)
sl@0: 	{
sl@0: 	CAsyncCommandCleanup *ciMuxAsyncCommandCleanup=NULL;
sl@0: 	TRAPD(err,ciMuxAsyncCommandCleanup = CAsyncCommandCleanup::NewL(this,iCustomChannel));
sl@0: 	TRequestStatus* status= &aStatus;
sl@0: 	if(err == KErrNone)
sl@0: 		{
sl@0: 		err=iAsyncCustomCommandCleanup.Append(ciMuxAsyncCommandCleanup);
sl@0: 		if(err == KErrNone)
sl@0: 			{
sl@0: 			ciMuxAsyncCommandCleanup->AsyncCustomCommand(EMMFDevSoundCustomCommandCISendSlaveAsyncCommand,aComPackage,aStatus,aPackageBuf,NULL);		
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			User::RequestComplete(status,err);
sl@0: 			delete ciMuxAsyncCommandCleanup;
sl@0: 			return;			
sl@0: 			}	
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		User::RequestComplete(status,err);
sl@0: 		return;	
sl@0: 		}
sl@0: 	
sl@0: 	}
sl@0: 	
sl@0: void CMMFDevSoundCIMuxUtility::SendSlaveAsyncCommandResult(TMMFDevSoundCustomInterfaceCommandPackage& aComPackage, TRequestStatus& aStatus, const TDesC8& aPackageBuf, TDes8& aResultBuf)
sl@0: 	{
sl@0: 	CAsyncCommandCleanup* ciMuxAsyncCommandCleanup=NULL;
sl@0: 	TRAPD(err,ciMuxAsyncCommandCleanup = CAsyncCommandCleanup::NewL(this,iCustomChannel));
sl@0: 	TRequestStatus* status= &aStatus;
sl@0: 	if(err == KErrNone)
sl@0: 		{
sl@0: 		err=iAsyncCustomCommandCleanup.Append(ciMuxAsyncCommandCleanup);
sl@0: 		if(err == KErrNone)
sl@0: 			{
sl@0: 			ciMuxAsyncCommandCleanup->AsyncCustomCommand(EMMFDevSoundCustomCommandCISendSlaveAsyncCommandResult,aComPackage,aStatus,aPackageBuf,&aResultBuf);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			User::RequestComplete(status,err);
sl@0: 			delete ciMuxAsyncCommandCleanup;
sl@0: 			return;			
sl@0: 			}	
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		User::RequestComplete(status,err);
sl@0: 		return;
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: CMMFDevSoundCIMuxUtility::CMMFDevSoundCIMuxUtility(MMMFDevSoundCustomInterfaceChannel* aCustomChannel)
sl@0: : iCustomChannel(aCustomChannel)
sl@0: 	{
sl@0: 	}
sl@0: 	
sl@0: void CMMFDevSoundCIMuxUtility::RemoveAsyncCommand(CAsyncCommandCleanup* aAsyncCustomCommandCleanup)
sl@0: 	{
sl@0: 	TInt index = iAsyncCustomCommandCleanup.Find(aAsyncCustomCommandCleanup);
sl@0: 	__ASSERT_DEBUG( index != KErrNotFound,User::Invariant());
sl@0: 	if(index > KErrNotFound)
sl@0: 		{
sl@0: 		iAsyncCustomCommandCleanup.Remove(index);
sl@0: 		iAsyncCustomCommandCleanup.Compress();
sl@0: 		}
sl@0: 	return;
sl@0: 	}
sl@0: 	
sl@0: CMMFDevSoundCIMuxUtility::CAsyncCommandCleanup* CMMFDevSoundCIMuxUtility::CAsyncCommandCleanup::NewL(CMMFDevSoundCIMuxUtility* aMuxUtility,MMMFDevSoundCustomInterfaceChannel* aCustomChannel)
sl@0: 	{
sl@0: 	CAsyncCommandCleanup *self= new (ELeave) CAsyncCommandCleanup(aMuxUtility,aCustomChannel);
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL();
sl@0: 	CleanupStack::Pop(self);
sl@0: 	return self;
sl@0: 	}
sl@0: 	
sl@0: void CMMFDevSoundCIMuxUtility::CAsyncCommandCleanup::ConstructL()
sl@0: 	{
sl@0: 	iCommandBuffer = new (ELeave) TPckgBuf<TA3FCustomInterfaceCommand>;
sl@0: 	}
sl@0: 	
sl@0: CMMFDevSoundCIMuxUtility::CAsyncCommandCleanup::CAsyncCommandCleanup(CMMFDevSoundCIMuxUtility* aMuxUtility,MMMFDevSoundCustomInterfaceChannel* aCustomChannel)
sl@0: :CActive(CActive::EPriorityStandard),iMuxUtility(aMuxUtility),iCustomChannel(aCustomChannel)
sl@0: 	{
sl@0: 	CActiveScheduler::Add(this);
sl@0: 	}
sl@0: 	
sl@0: CMMFDevSoundCIMuxUtility::CAsyncCommandCleanup::~CAsyncCommandCleanup()
sl@0: 	{
sl@0: 	delete iCommandBuffer;
sl@0: 	Cancel();
sl@0: 	}
sl@0: 	
sl@0: void CMMFDevSoundCIMuxUtility::CAsyncCommandCleanup::AsyncCustomCommand(CMMFDevSoundCIMuxUtility::TMMFDevSoundCustomCommand aType,TMMFDevSoundCustomInterfaceCommandPackage& aComPackage, TRequestStatus& aStatus, const TDesC8& aPackageBuf, TDes8* aResultBuf)
sl@0: 	{
sl@0: 	iClientRequestStatus = &aStatus;
sl@0: 	
sl@0: 	(*iCommandBuffer)().iType = aType;
sl@0: 	(*iCommandBuffer)().iCommand = aComPackage().iCommand;
sl@0: 	(*iCommandBuffer)().iHandle = aComPackage().iHandle;
sl@0: 	*iClientRequestStatus = KRequestPending;
sl@0: 	iCustomChannel->AsyncCustomCommand(KUidInterfaceMMFDevSound,iStatus, *iCommandBuffer, aPackageBuf, aResultBuf);
sl@0: 	SetActive();
sl@0: 	}
sl@0: 	
sl@0: void CMMFDevSoundCIMuxUtility::CAsyncCommandCleanup::RunL()
sl@0: 	{
sl@0: 	if(iClientRequestStatus)
sl@0: 		{
sl@0: 		User::RequestComplete(iClientRequestStatus,iStatus.Int());		
sl@0: 		}
sl@0: 	iClientRequestStatus = NULL;
sl@0: 	iMuxUtility->RemoveAsyncCommand(this);
sl@0: 	delete this;
sl@0: 	}
sl@0: 	
sl@0: void CMMFDevSoundCIMuxUtility::CAsyncCommandCleanup::DoCancel()
sl@0: 	{
sl@0: 
sl@0: 	}