mmlibs/mmfw/src/server/BaseClasses/mmfdatapathproxy.cpp
changeset 0 b8ed18f6c07b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmlibs/mmfw/src/server/BaseClasses/mmfdatapathproxy.cpp	Thu Oct 07 22:34:12 2010 +0100
@@ -0,0 +1,676 @@
+// Copyright (c) 2002-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:
+//
+
+#include <e32math.h>
+#include <mmf/server/mmfdatapathproxy.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <mmf/server/mmfdatapathproxyserver.h>
+#endif
+
+/**
+Constructs a datapath event monitor object.
+
+@param  aObserver
+        A reference to the observer of the active object. The observer will be notified when an
+        event occurs.
+@param  aMMFDataPathProxy
+        A reference to the client datapath proxy class.
+
+@return A pointer to the new event monitor.
+
+@since 7.0s
+*/
+EXPORT_C CMMFDataPathEventMonitor* CMMFDataPathEventMonitor::NewL(MMMFDataPathEventMonitorObserver& aObserver,
+															 RMMFDataPathProxy& aMMFDataPathProxy)
+	{
+	return (new(ELeave) CMMFDataPathEventMonitor(aObserver, aMMFDataPathProxy));
+	}
+
+CMMFDataPathEventMonitor::CMMFDataPathEventMonitor(MMMFDataPathEventMonitorObserver& aObserver, 
+													   RMMFDataPathProxy& aMMFDataPathProxy) :
+	CActive(EPriorityStandard),
+	iObserver(aObserver), 
+	iMMFDataPathProxy(aMMFDataPathProxy)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+/**
+Destructor.
+
+Calls Cancel().
+*/
+EXPORT_C CMMFDataPathEventMonitor::~CMMFDataPathEventMonitor()
+	{
+	Cancel();
+	}
+
+/**
+Tells the datapath event monitor to start listening for events.
+
+The datapath proxy must have been opened before this method is called.
+
+@since  7.0s
+*/
+EXPORT_C void CMMFDataPathEventMonitor::Start()
+	{
+	iMMFDataPathProxy.ReceiveEvents(iEventPckg, iStatus);
+	SetActive();
+	}
+
+/**
+Internal active object function.
+
+Starts the data path event monitor and handles an event if there is no error status.
+
+Calls HandleEvent on iObserver.
+
+@since  7.0s
+*/
+EXPORT_C void CMMFDataPathEventMonitor::RunL()
+	{
+	if (iStatus.Int() == KErrNone)
+		{
+		iObserver.HandleEvent(iEventPckg());
+		Start();
+		}
+	else
+		{
+		//something's gone wrong with trying to receive events (e.g. server died etc)
+		TMMFEvent event(KMMFErrorCategoryDataPathGeneralError, iStatus.Int());
+		iObserver.HandleEvent(event);
+		//we don't want to receive events again here...
+		}
+	}
+
+/**
+Cancels the outstanding request on iMMFDataPathProxy.
+
+@since  7.0s
+*/
+void CMMFDataPathEventMonitor::DoCancel()
+	{
+	iMMFDataPathProxy.CancelReceiveEvents();
+	}
+
+/**
+Creates a subthread that will contain the datapath.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since 7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::CreateSubThread()
+	{
+	//start the subthread with a unique name
+	TName subThreadName(_L("MMFDataPathThread"));
+	subThreadName.AppendNum(Math::Random(),EHex);
+	
+	TInt error = DoCreateSubThread(subThreadName, &CMMFDataPathProxyServer::StartThread);
+	if (error)
+		return error;
+
+	//now create a session with the subthread
+	error = CreateSession(subThreadName, KMMFDataPathProxyVersion);
+
+	return error;
+	}
+
+// Note: in the following, we can pass straight addresses for writing since both client and server
+// are in the same process.
+/**
+Load the datapath in the new thread. Use this method if the codec UID is not known
+and there is no datapath ambiguity, ie. only one datapath is possible.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since 7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::LoadDataPath()
+	{
+	return SendReceive(EMMFDataPathProxyLoadDataPathBy);
+	}
+
+/**
+Load the datapath in the new thread. 
+
+Use this method if the codec UID is not known but the TMediaId can be used to select which codec 
+to use.
+
+@param  aMediaId
+	    The type of media to be handled by this datapath.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since  7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::LoadDataPath(TMediaId aMediaId)
+	{
+	return SendReceive (EMMFDataPathProxyLoadDataPathByMediaId, TInt(&aMediaId));
+	}
+
+/**
+Load the datapath in the new thread. 
+
+Use this method if the codec UID is known and there is no datapath ambiguity, ie. only one datapath
+is possible.
+
+@param  aCodecUid
+        The UID of the codec plugin to be used by the datapath.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since  7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::LoadDataPath(TUid aCodecUid) 
+	{
+	return SendReceive(EMMFDataPathProxyLoadDataPathByCodecUid, TInt(&aCodecUid));
+	}
+
+/**
+Loads the datapath in the new thread. 
+
+Use this method if the codec UID is known and there is datapath ambiguity. The TMediaId will be
+used to choose the correct path.
+
+@param  aCodecUid
+        The UID of the codec plugin to be used by the datapath.
+@param  aMediaId
+        The type of media to be handled by this datapath.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since  7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::LoadDataPath(TUid aCodecUid, TMediaId aMediaId)
+	{
+	return SendReceive(EMMFDataPathProxyLoadDataPathByMediaIdCodecUid, TInt(&aCodecUid), TInt(&aMediaId));
+	}
+	
+/**
+Specify the data source for this datapath.
+
+If the sink already exists, this function tries to establish a connection between the source and 
+sink. Note that only one data source can be added to the datapath.
+
+@param  aSource
+        A pointer to the data source.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since 7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::AddDataSource(MDataSource* aSource)
+	{
+	return SendReceive(EMMFDataPathProxyAddDataSource, TInt(aSource));
+	}
+	
+/**
+Specify the data sink for this datapath.  
+
+If the source already exists, this function tries to establish a connection between the source and 
+the sink. Note that only one data sink can be added to the datapath.
+
+@param  aSink
+        A pointer to the data sink.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since  7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::AddDataSink(MDataSink* aSink)
+	{
+	return SendReceive(EMMFDataPathProxyAddDataSink, TInt(aSink));
+	}
+	
+/**
+Transfer the datapath from the stopped into the primed state.
+
+This function allocates buffers in preparation to play and must be called before calling PlayL().
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since  7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::Prime()
+	{
+	return SendReceive(EMMFDataPathProxyPrime);
+	}
+
+/**
+Transfer the datapath from the primed into the playing state.
+
+This function starts an active scheduler play loop and can only play from the primed state.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since 7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::Play()
+	{
+	return SendReceive(EMMFDataPathProxyPlay);
+	}
+
+/**
+Pauses playing.
+
+This function transfers the datapath from the playing into the primed state and sends 
+KMMFErrorCategoryDataPathGeneralError to the client if an error occurs.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since  7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::Pause()
+	{
+	return SendReceive(EMMFDataPathProxyPause);
+	}
+	
+/**
+Stops playing.
+
+This function transfers the datapath from the primed into the stopped state and resets the data 
+path position, but does not clean up buffers. It also sends KMMFErrorCategoryDataPathGeneralError 
+to the client if an error occurs.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since  7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::Stop()
+	{
+	return SendReceive(EMMFDataPathProxyStop);
+	}
+	
+/**
+Gets the current position of the datapath in units of time.
+
+@param  aPosition
+        The current position in micro seconds will be copied into this variable.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since  7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::GetPosition(TTimeIntervalMicroSeconds& aPosition) const
+	{
+	return SendReceive(EMMFDataPathProxyGetPosition, TInt(&aPosition));
+	}
+
+/**
+Sets the current position of the datapath in units of time.
+
+@param  aPosition
+        The required position in micro seconds.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since 7.0s
+**/
+EXPORT_C TInt RMMFDataPathProxy::SetPosition(const TTimeIntervalMicroSeconds& aPosition)
+	{
+	return SendReceive(EMMFDataPathProxySetPosition, TInt(&aPosition));
+	}
+	
+/**
+Sets the play window relative to the start of the entire clip.
+
+@param  aStart
+        The start position in micro seconds relative to the start of the clip.
+@param  aEnd
+        The end position in micro seconds relative to the start of the clip.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since  7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::SetPlayWindow( const TTimeIntervalMicroSeconds& aStart, const TTimeIntervalMicroSeconds& aEnd )
+	{
+	return SendReceive( EMMFDataPathProxySetPlayWindow, TInt(&aStart), TInt(&aEnd)) ;
+	}
+	
+/**
+Removes a previously defined play window.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since  7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::ClearPlayWindow()
+	{
+	return SendReceive( EMMFDataPathProxyClearPlayWindow) ;
+	}
+	
+/**
+Gets the current datapath state.
+
+@param  aState
+        The current state of the datapath will be copied into this variable.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@since  7.0s
+*/
+EXPORT_C TInt RMMFDataPathProxy::State( TInt& aState )
+	{
+	return SendReceive( EMMFDataPathProxyState, TInt(&aState) ) ; // pass address, not value
+	}
+
+/**
+Deletes the datapath and shuts down the datapath proxy thread.
+
+Calls RMMFSubThreadBase::Shutdown(). This function will not return until the subthread has 
+exited, or a timeout has occurred.
+
+@since  7.0s
+*/
+EXPORT_C void RMMFDataPathProxy::Close()
+	{
+	Shutdown();
+	}
+
+
+
+
+
+
+CMMFDataPathProxyServer* CMMFDataPathProxyServer::NewL()
+	{
+	CMMFDataPathProxyServer* s = new(ELeave) CMMFDataPathProxyServer();
+	CleanupStack::PushL(s);
+	s->ConstructL();
+	CleanupStack::Pop();
+	return s;
+	}
+
+CMMFDataPathProxyServer::CMMFDataPathProxyServer() :
+	CMMFSubThreadServer(EPriorityStandard)
+	{
+	}
+
+void CMMFDataPathProxyServer::ConstructL()
+	{
+	//just need to call baseclass's constructL here
+	CMMFSubThreadServer::ConstructL();
+	}
+
+CMMFDataPathProxyServer::~CMMFDataPathProxyServer()
+	{
+	}
+
+CMmfIpcSession* CMMFDataPathProxyServer::NewSessionL(const TVersion& aVersion) const
+	{
+	if (!User::QueryVersionSupported(KMMFDataPathProxyVersion, aVersion))
+		User::Leave(KErrNotSupported);
+
+	return CMMFDataPathProxySession::NewL();
+	}
+
+TInt CMMFDataPathProxyServer::StartThread(TAny*)
+	{
+	TInt err = KErrNone;
+	//create cleanupstack
+	CTrapCleanup* cleanup=CTrapCleanup::New(); // get clean-up stack
+	if (!cleanup)
+		err = KErrNoMemory;
+	if (!err)
+		{
+		TRAP(err, DoStartThreadL());
+		}
+	delete cleanup;
+	return err;
+	}
+
+void CMMFDataPathProxyServer::DoStartThreadL()
+	{
+	// create and install the active scheduler we need
+	CActiveScheduler* s=new(ELeave) CActiveScheduler;
+	CleanupStack::PushL(s);
+	CActiveScheduler::Install(s);
+	// create the server (leave it on the cleanup stack)
+	CleanupStack::PushL(CMMFDataPathProxyServer::NewL());
+	// Initialisation complete, now signal the client
+	RThread::Rendezvous(KErrNone);
+	// Ready to run
+	CActiveScheduler::Start();
+	// Cleanup the server and scheduler
+	CleanupStack::PopAndDestroy(2);
+	REComSession::FinalClose(); // fix 047933
+	}
+
+
+
+
+
+CMMFDataPathProxySession* CMMFDataPathProxySession::NewL()
+	{
+	return new(ELeave) CMMFDataPathProxySession();
+	}
+
+CMMFDataPathProxySession::CMMFDataPathProxySession()
+	{
+	}
+
+
+CMMFDataPathProxySession::~CMMFDataPathProxySession()
+	{
+	delete iDataPath;
+	}
+
+void CMMFDataPathProxySession::ServiceL(const RMmfIpcMessage& aMessage)
+	{
+	TBool complete = EFalse;
+	switch(aMessage.Function())
+		{
+	case EMMFDataPathProxyLoadDataPathBy:
+		complete = LoadDataPathByL(aMessage);
+		break;
+	case EMMFDataPathProxyLoadDataPathByMediaId:
+		complete = LoadDataPathByMediaIdL(aMessage);
+		break;
+	case EMMFDataPathProxyLoadDataPathByCodecUid:
+		complete = LoadDataPathByCodecUidL(aMessage);
+		break;
+	case EMMFDataPathProxyLoadDataPathByMediaIdCodecUid:
+		complete = LoadDataPathByMediaIdCodecUidL(aMessage);
+		break;
+	case EMMFDataPathProxyAddDataSource:
+		complete = AddDataSourceL(aMessage);
+		break;
+	case EMMFDataPathProxyAddDataSink:
+		complete = AddDataSinkL(aMessage);
+		break;
+	case EMMFDataPathProxyPrime:
+		complete = PrimeL(aMessage);
+		break;
+	case EMMFDataPathProxyPlay:
+		complete = PlayL(aMessage);
+		break;
+	case EMMFDataPathProxyPause:
+		complete = PauseL(aMessage);
+		break;
+	case EMMFDataPathProxyStop:
+		complete = StopL(aMessage);
+		break;
+	case EMMFDataPathProxyGetPosition:
+		complete = GetPositionL(aMessage);
+		break;
+	case EMMFDataPathProxySetPosition:
+		complete = SetPositionL(aMessage);
+		break;
+	case EMMFDataPathProxySetPlayWindow :
+		complete = SetPlayWindowL(aMessage) ;
+		break;
+	case EMMFDataPathProxyClearPlayWindow:
+		complete = ClearPlayWindowL(aMessage);
+		break;
+	case EMMFDataPathProxyState:
+		complete = StateL(aMessage);
+		break;
+	case EMMFSubThreadReceiveEvents:
+		complete = ReceiveEventsL(aMessage);//provided by baseclass
+		break;
+	case EMMFSubThreadCancelReceiveEvents:
+		complete = CancelReceiveEvents();//provided by baseclass
+		break;
+	case EMMFSubThreadShutdown:
+		complete = ShutDown();//provided by baseclass
+		break;
+	default:
+		User::Leave(KErrNotSupported);
+		break;
+		}
+
+	if (complete)
+		aMessage.Complete(KErrNone);
+	}
+
+
+TBool CMMFDataPathProxySession::LoadDataPathByL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	if (iDataPath)
+		User::Leave(KErrAlreadyExists);
+	iDataPath = CMMFDataPath::NewL(*this);
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::LoadDataPathByMediaIdL(const RMmfIpcMessage& aMessage)
+	{
+	if (iDataPath)
+		User::Leave(KErrAlreadyExists);
+	TMediaId* mediaId = REINTERPRET_CAST(TMediaId*, aMessage.Int0());
+	iDataPath = CMMFDataPath::NewL(*mediaId, *this);
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::LoadDataPathByCodecUidL(const RMmfIpcMessage& aMessage)
+	{
+	if (iDataPath)
+		User::Leave(KErrAlreadyExists);
+	TUid* uid = REINTERPRET_CAST(TUid*, aMessage.Int0());
+	iDataPath = CMMFDataPath::NewL(*uid, *this);
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::LoadDataPathByMediaIdCodecUidL(const RMmfIpcMessage& aMessage)
+	{
+	if (iDataPath)
+		User::Leave(KErrAlreadyExists);
+	TUid* uid = REINTERPRET_CAST(TUid*, aMessage.Int0());
+	TMediaId* mediaId = REINTERPRET_CAST(TMediaId*, aMessage.Int1());
+	iDataPath = CMMFDataPath::NewL(*uid, *mediaId, *this);
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::AddDataSourceL(const RMmfIpcMessage& aMessage)
+	{
+	CheckDataPathExistsL();
+	MDataSource* source = REINTERPRET_CAST(MDataSource*, aMessage.Int0());
+	iDataPath->AddDataSourceL(source);
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::AddDataSinkL(const RMmfIpcMessage& aMessage)
+	{
+	CheckDataPathExistsL();
+	MDataSink* sink = REINTERPRET_CAST(MDataSink*, aMessage.Int0());
+	iDataPath->AddDataSinkL(sink);
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::PrimeL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	CheckDataPathExistsL();
+	iDataPath->PrimeL();
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::PlayL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	CheckDataPathExistsL();
+	iDataPath->PlayL();
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::PauseL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	CheckDataPathExistsL();
+	iDataPath->Pause();
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::StopL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	CheckDataPathExistsL();
+	iDataPath->Stop();
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::GetPositionL(const RMmfIpcMessage& aMessage) const
+	{
+	CheckDataPathExistsL();
+	TTimeIntervalMicroSeconds* t = REINTERPRET_CAST(TTimeIntervalMicroSeconds*, aMessage.Int0());
+	*t = iDataPath->Position();
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::SetPositionL(const RMmfIpcMessage& aMessage)
+	{
+	CheckDataPathExistsL();
+	TTimeIntervalMicroSeconds* t = REINTERPRET_CAST(TTimeIntervalMicroSeconds*, aMessage.Int0());
+	iDataPath->SetPositionL(*t);
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::SetPlayWindowL(const RMmfIpcMessage& aMessage) 
+	{
+	CheckDataPathExistsL() ;
+	TTimeIntervalMicroSeconds* start = REINTERPRET_CAST( TTimeIntervalMicroSeconds*, aMessage.Int0() ) ;
+	TTimeIntervalMicroSeconds* end = REINTERPRET_CAST( TTimeIntervalMicroSeconds*, aMessage.Int1() ) ;
+	iDataPath->SetPlayWindowL( *start, *end ) ;
+	return ETrue;
+	}
+
+TBool CMMFDataPathProxySession::ClearPlayWindowL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	CheckDataPathExistsL() ;
+	iDataPath->ClearPlayWindowL() ;
+	return ETrue ;
+	}
+
+TBool CMMFDataPathProxySession::StateL(const RMmfIpcMessage& aMessage)
+	{
+	CheckDataPathExistsL() ;
+	TInt* state = REINTERPRET_CAST( TInt*, aMessage.Int0() ) ;
+	*state = iDataPath->State();
+	return ETrue ;
+	}
+