sl@0: // Copyright (c) 2006-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 sl@0: #include "mmfdevsoundserver.h" sl@0: #include "mmfdevsoundserverstart.h" sl@0: #include "mmfdevsoundsession.h" sl@0: #include "mmfdevsoundserverconsts.h" sl@0: sl@0: const TInt KDevSoundShutDownDelay = 0; //no delay sl@0: _LIT(KMMFDevSoundServerName, "MMFDevSoundServer-"); sl@0: sl@0: // ======== LOCAL FUNCTIONS ======== sl@0: void Panic(TInt aPanicCode) sl@0: { sl@0: _LIT(KDevSoundServerPanicCategory, "mmfdevsoundserver"); sl@0: User::Panic(KDevSoundServerPanicCategory, aPanicCode); sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer* CMMFDevSoundServer::NewL sl@0: Two-phased constructor. sl@0: */ sl@0: EXPORT_C CMMFDevSoundServer* CMMFDevSoundServer::NewL( sl@0: MGlobalProperties* aGlobalProperties, sl@0: TProcessId& aClientPID) sl@0: { sl@0: CMMFDevSoundServer* self = new(ELeave) CMMFDevSoundServer(aGlobalProperties, sl@0: aClientPID); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::CMMFDevSoundServer sl@0: C++ default constructor can NOT contain any code, that might leave. sl@0: */ sl@0: CMMFDevSoundServer::CMMFDevSoundServer( sl@0: MGlobalProperties* aGlobalProperties, sl@0: TProcessId& aClientPID) : sl@0: CMmfIpcServer(EPriorityStandard, EGlobalSharableSessions), sl@0: iClientPID(aClientPID), sl@0: iActualClientPID(aClientPID) sl@0: { sl@0: iGlobalProperties = aGlobalProperties; sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::ConstructL sl@0: Symbian 2nd phase constructor can leave. sl@0: */ sl@0: void CMMFDevSoundServer::ConstructL() sl@0: { sl@0: RProcess client; sl@0: User::LeaveIfError(client.Open(iClientPID)); sl@0: sl@0: sl@0: client.Close(); sl@0: sl@0: iDelayDevSoundShutDown = CDelayDevSoundShutDown::NewL(); sl@0: sl@0: // Call base class to Start server sl@0: StartL(KNullDesC); sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::~CMMFDevSoundServer sl@0: Destructor sl@0: */ sl@0: CMMFDevSoundServer::~CMMFDevSoundServer() sl@0: { sl@0: if (iDelayDevSoundShutDown) sl@0: { sl@0: iDelayDevSoundShutDown->Cancel(); sl@0: delete iDelayDevSoundShutDown; sl@0: } sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::NewSessionL sl@0: Creates new session sl@0: (other items were commented in a header). sl@0: */ sl@0: CMmfIpcSession* CMMFDevSoundServer::NewSessionL(const TVersion& aVersion) const sl@0: { sl@0: CMmfIpcSession* devSoundSession = NULL; sl@0: sl@0: TRAPD(error, devSoundSession = CreateNewSessionL(aVersion)); sl@0: sl@0: if (error!=KErrNone) sl@0: { sl@0: // session create failed, so flag for subsequent destruction of server sl@0: CMMFDevSoundServer* mutableThis = const_cast(this); sl@0: mutableThis->CheckForNoSessionsLeft(); sl@0: User::Leave(error); sl@0: } sl@0: return devSoundSession; sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::CreateNewSessionL sl@0: Guts of what would otherwise be in NewSessionL() itself sl@0: */ sl@0: CMmfIpcSession* CMMFDevSoundServer::CreateNewSessionL(const TVersion& aVersion) const sl@0: { sl@0: TVersion version(KMMFDevSoundServerVersion, sl@0: KMMFDevSoundServerMinorVersionNumber, sl@0: KMMFDevSoundServerBuildVersionNumber); sl@0: sl@0: if(!User::QueryVersionSupported(version, aVersion)) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: CMMFDevSoundSession* devSoundSession = sl@0: CMMFDevSoundSession::NewL(*iGlobalProperties); sl@0: return devSoundSession; sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::IncrementSessionId sl@0: Increments session count sl@0: (other items were commented in a header). sl@0: */ sl@0: void CMMFDevSoundServer::IncrementSessionId() sl@0: { sl@0: iDevSoundSessionId++; sl@0: if (iDevSoundSessionId) sl@0: { sl@0: iDelayDevSoundShutDown->Cancel(); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::DecrementSessionId sl@0: Decrements session count sl@0: (other items were commented in a header). sl@0: */ sl@0: void CMMFDevSoundServer::DecrementSessionId() sl@0: { sl@0: iDevSoundSessionId--; sl@0: CheckForNoSessionsLeft(); sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::CheckForNoSessionsLeft sl@0: If no sessions are left, we kick off timer, which closes down server after timeout sl@0: really meaning the server closes asynchronously sl@0: */ sl@0: void CMMFDevSoundServer::CheckForNoSessionsLeft() sl@0: { sl@0: if (iDevSoundSessionId == 0) sl@0: { sl@0: iDelayDevSoundShutDown->SetDelay( sl@0: TTimeIntervalMicroSeconds32(KDevSoundShutDownDelay)); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::SendEventToClient sl@0: For the session requested, send event to client sl@0: (other items were commented in a header). sl@0: */ sl@0: void CMMFDevSoundServer::SendEventToClient(TInt aSessionToAlert, sl@0: TInt /*aSessionToBeLaunched*/) sl@0: { sl@0: iSessionIter.SetToFirst(); sl@0: CMMFDevSoundSession* session = sl@0: static_cast(iSessionIter++); sl@0: sl@0: while (session != NULL) sl@0: { sl@0: if (session->DevSoundSessionId() == aSessionToAlert) sl@0: { sl@0: break; // Finished sl@0: } sl@0: session = static_cast(iSessionIter++); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::LaunchRequest sl@0: Launches the DevSound servers waiting for Audio Policy. sl@0: (other items were commented in a header). sl@0: */ sl@0: void CMMFDevSoundServer::LaunchRequest(TInt aSessionId) sl@0: { sl@0: iSessionIter.SetToFirst(); sl@0: CMMFDevSoundSession* session = sl@0: static_cast(iSessionIter++); sl@0: sl@0: while (session != NULL) sl@0: { sl@0: if (session->DevSoundSessionId() == aSessionId) sl@0: { sl@0: break; // Finished sl@0: } sl@0: session = static_cast(iSessionIter++); sl@0: } sl@0: } sl@0: sl@0: sl@0: void CMMFDevSoundServer::RenamePrioritizeServer() sl@0: { sl@0: //Rename devsound server name sl@0: RThread devsoundServerThread; sl@0: TThreadId threadId; sl@0: TName name; sl@0: name.Append(KMMFDevSoundServerName); sl@0: threadId = devsoundServerThread.Id(); sl@0: name.AppendNum(threadId.Id(),EHex); sl@0: //We are ignoring the error code returned from User::RenameThread sl@0: //as it is not important here, may be for profiling sl@0: User::RenameThread(name); sl@0: sl@0: //Set the devsound priority sl@0: TThreadPriority devsoundServerPriority = static_cast(KDevsoundServerPriority); sl@0: devsoundServerThread.SetPriority(devsoundServerPriority); sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer* CMMFDevSoundServer::NewL sl@0: Two-phased constructor. sl@0: */ sl@0: CMMFDevSoundServer::CDelayDevSoundShutDown* sl@0: CMMFDevSoundServer::CDelayDevSoundShutDown::NewL() sl@0: { sl@0: CDelayDevSoundShutDown* self = new(ELeave) CDelayDevSoundShutDown; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::CDelayDevSoundShutDown::CDelayDevSoundShutDown sl@0: C++ constructor sl@0: (other items were commented in a header). sl@0: */ sl@0: CMMFDevSoundServer::CDelayDevSoundShutDown::CDelayDevSoundShutDown() sl@0: : CActive(0) sl@0: { sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::CDelayDevSoundShutDown::ConstructL sl@0: Symbian 2nd phase constructor can leave. sl@0: */ sl@0: void CMMFDevSoundServer::CDelayDevSoundShutDown::ConstructL() sl@0: { sl@0: User::LeaveIfError(iTimer.CreateLocal()); sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::CDelayDevSoundShutDown::~CDelayDevSoundShutDown sl@0: Destructor sl@0: */ sl@0: CMMFDevSoundServer::CDelayDevSoundShutDown::~CDelayDevSoundShutDown() sl@0: { sl@0: Cancel(); sl@0: iTimer.Close(); sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::CDelayDevSoundShutDown::SetDelay sl@0: Request a timeout after aDelay sl@0: (other items were commented in a header). sl@0: */ sl@0: void CMMFDevSoundServer::CDelayDevSoundShutDown::SetDelay( sl@0: TTimeIntervalMicroSeconds32 aDelay) sl@0: { sl@0: __ASSERT_ALWAYS(!IsActive(), Panic(EMMFDevSoundServerIsActive)); sl@0: iTimer.After(iStatus, aDelay); sl@0: SetActive(); sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::CDelayDevSoundShutDown::RunL sl@0: Called by Active object framework after timer expires sl@0: (other items were commented in a header). sl@0: */ sl@0: void CMMFDevSoundServer::CDelayDevSoundShutDown::RunL() sl@0: { sl@0: CActiveScheduler::Stop(); sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::CDelayDevSoundShutDown::DoCancel sl@0: Called by Active object framework when user cancels active object. sl@0: (other items were commented in a header). sl@0: */ sl@0: void CMMFDevSoundServer::CDelayDevSoundShutDown::DoCancel() sl@0: { sl@0: iTimer.Cancel(); sl@0: } sl@0: sl@0: /** sl@0: CMMFDevSoundServer::SetClientProcessIdL sl@0: */ sl@0: void CMMFDevSoundServer::SetClientProcessIdL(TThreadId aTid) sl@0: { sl@0: sl@0: RThread clientThread; sl@0: User::LeaveIfError(clientThread.Open(aTid)); sl@0: CleanupClosePushL(clientThread); sl@0: sl@0: RProcess clientProcess; sl@0: User::LeaveIfError(clientThread.Process(clientProcess)); sl@0: CleanupClosePushL(clientProcess); sl@0: sl@0: iActualClientPID = clientProcess.Id(); sl@0: CleanupStack::PopAndDestroy(2, &clientThread); // clientProcess, clientThread sl@0: } sl@0: //GLOBAL FUNCTIONS sl@0: sl@0: /** sl@0: This function raises a panic on the client of the DevSound Server sl@0: sl@0: @param aError sl@0: one of the several panic codes that may be raised by this dll on sl@0: the client sl@0: sl@0: @panic EMMFDevSoundPlayDataWithoutInitialize is raised when playdata is sl@0: called without initialization sl@0: @panic EMMFDevSoundRecordDataWithoutInitialize is raised when recorddata sl@0: is called without initialization sl@0: */ sl@0: GLDEF_C void PanicClient(const RMmfIpcMessage& aMessage, sl@0: TMMFDevSoundClientPanicCodes aPanicCode) sl@0: { sl@0: aMessage.Panic(KMMFDevSoundClientPanicCategory, aPanicCode); sl@0: } sl@0: sl@0: // End of File