sl@0: // Copyright (c) 2004-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 "MmfBtAudioServer.h" sl@0: #include "MmfBtAudioServerStart.h" sl@0: #include "MmfBtDevSoundSession.h" sl@0: #include "MmfBtAudioServerSession.h" sl@0: #include "MmfBtDevSoundServer.h" sl@0: #include "MmfBtDevSoundServerStart.h" sl@0: #include "../../../../inc/common/mmfBtBase.hrh" sl@0: sl@0: sl@0: static const TUid KUidDevSoundServer = {KUidMmfBtDevSoundServerDllUnicodeDefine}; sl@0: sl@0: const TInt KAudioServerShutDownDelay = 50000000; //50 sec sl@0: sl@0: sl@0: CMMFAudioServer* CMMFAudioServer::NewL() sl@0: { sl@0: CMMFAudioServer* s = new(ELeave) CMMFAudioServer(); sl@0: CleanupStack::PushL(s); sl@0: s->ConstructL(); sl@0: CleanupStack::Pop(); sl@0: return s; sl@0: } sl@0: sl@0: CMMFAudioServer::CMMFAudioServer() : sl@0: CMmfIpcServer(EPriorityStandard) sl@0: { sl@0: } sl@0: sl@0: void CMMFAudioServer::ConstructL() sl@0: { sl@0: iDelayAudioServerShutDown = CDelayAudioServerShutDown::NewL(); sl@0: // Call base class to Start server sl@0: StartL(KAudioServerName); sl@0: } sl@0: sl@0: CMMFAudioServer::~CMMFAudioServer() sl@0: { sl@0: if (iDelayAudioServerShutDown) sl@0: { sl@0: iDelayAudioServerShutDown->Cancel(); sl@0: delete iDelayAudioServerShutDown; sl@0: } sl@0: iDevSoundServList.Close(); sl@0: iPolicyServerHandle.Close(); sl@0: } sl@0: sl@0: CMmfIpcSession* CMMFAudioServer::NewSessionL(const TVersion& aVersion) const sl@0: { sl@0: TVersion v(KMMFAudioServerVersion,KMMFAudioServerMinorVersionNumber,KMMFAudioServerBuildVersionNumber); sl@0: if(!User::QueryVersionSupported(v, aVersion)) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: for(TInt i=0; iIsActive()) sl@0: { sl@0: iDevSoundServList.Remove(i); sl@0: delete devSoundMonitorThread; sl@0: } sl@0: iDevSoundServList.Compress(); sl@0: } sl@0: sl@0: TName devSoundServerName; sl@0: User::LeaveIfError(StartDevSoundServerL(devSoundServerName)); sl@0: CMMFAudioServerSession* audioServerSession = CMMFAudioServerSession::NewL(devSoundServerName); sl@0: return audioServerSession; sl@0: } sl@0: sl@0: void CMMFAudioServer::IncrementSessionId() sl@0: { sl@0: iAudioServerSessionId++; sl@0: } sl@0: sl@0: void CMMFAudioServer::DecrementSessionId() sl@0: { sl@0: iAudioServerSessionId--; sl@0: } sl@0: sl@0: void CMMFAudioServer::IncrementDevSoundCount() sl@0: { sl@0: iDevSoundCount++; sl@0: if(iDevSoundCount) sl@0: iDelayAudioServerShutDown->Cancel(); //in the case we started the shutdown due to no more DevSound sl@0: } sl@0: sl@0: void CMMFAudioServer::DecrementDevSoundCount() sl@0: { sl@0: iDevSoundCount--; sl@0: if ( iDevSoundCount == 0 ) sl@0: { sl@0: iDelayAudioServerShutDown->SetDelay(TTimeIntervalMicroSeconds32(KAudioServerShutDownDelay)); sl@0: } sl@0: } sl@0: sl@0: void CMMFAudioServer::SendEventToClient(TInt aSessionToAlert, TInt /*aSessionToBeLaunched*/) sl@0: { sl@0: // For the session requested, send event to client sl@0: iSessionIter.SetToFirst(); sl@0: CMMFAudioServerSession* session = static_cast(iSessionIter++); sl@0: while (session != NULL) sl@0: { sl@0: if (session->AudioServerSessionId() == aSessionToAlert) sl@0: { sl@0: break; // Finished sl@0: } sl@0: session = static_cast(iSessionIter++); sl@0: } sl@0: } sl@0: sl@0: void CMMFAudioServer::LaunchRequest(TInt aSessionId) sl@0: { sl@0: iSessionIter.SetToFirst(); sl@0: CMMFAudioServerSession* session = static_cast(iSessionIter++); sl@0: while (session != NULL) sl@0: { sl@0: if (session->AudioServerSessionId() == aSessionId) sl@0: { sl@0: break; // Finished sl@0: } sl@0: session = static_cast(iSessionIter++); sl@0: } sl@0: } sl@0: sl@0: TInt CMMFAudioServer::StartDevSoundServerL(TName& aDevSoundName) const sl@0: { sl@0: RMessage2 message(Message()); sl@0: CStartAndMonitorDevSoundThread* monitorDevSound = NULL; sl@0: sl@0: TRAPD(err, monitorDevSound = CStartAndMonitorDevSoundThread::NewL(const_cast(this))); sl@0: if(err != KErrNone) sl@0: { sl@0: delete monitorDevSound; sl@0: return err; sl@0: } sl@0: sl@0: iDevSoundServList.Append(monitorDevSound); sl@0: sl@0: CMMFAudioServer* mutableThis = const_cast(this); sl@0: mutableThis->iGlobalNum+=1; sl@0: sl@0: return monitorDevSound->StartDevSoundServerL(message, aDevSoundName, iGlobalNum); sl@0: sl@0: } sl@0: sl@0: sl@0: CMMFAudioServer::CDelayAudioServerShutDown* CMMFAudioServer::CDelayAudioServerShutDown::NewL() sl@0: { sl@0: CDelayAudioServerShutDown* self = new(ELeave) CDelayAudioServerShutDown; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: CMMFAudioServer::CDelayAudioServerShutDown::CDelayAudioServerShutDown() : CActive(0) sl@0: { sl@0: } sl@0: sl@0: void CMMFAudioServer::CDelayAudioServerShutDown::ConstructL() sl@0: { sl@0: User::LeaveIfError(iShutDownTimer.CreateLocal()); sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: CMMFAudioServer::CDelayAudioServerShutDown::~CDelayAudioServerShutDown() sl@0: { sl@0: Cancel(); sl@0: iShutDownTimer.Close(); sl@0: } sl@0: sl@0: sl@0: void CMMFAudioServer::CDelayAudioServerShutDown::SetDelay(TTimeIntervalMicroSeconds32 aDelay) sl@0: { sl@0: __ASSERT_ALWAYS(!IsActive(), User::Panic(_L("CDelayedShutDown"), 1)); sl@0: iShutDownTimer.After(iStatus, aDelay); sl@0: SetActive(); sl@0: } sl@0: sl@0: void CMMFAudioServer::CDelayAudioServerShutDown::RunL() sl@0: { sl@0: CActiveScheduler::Stop(); sl@0: } sl@0: sl@0: sl@0: void CMMFAudioServer::CDelayAudioServerShutDown::DoCancel() sl@0: { sl@0: iShutDownTimer.Cancel(); sl@0: } sl@0: sl@0: sl@0: CStartAndMonitorDevSoundThread* CStartAndMonitorDevSoundThread::NewL(CMMFAudioServer* aAudioServer) sl@0: { sl@0: CStartAndMonitorDevSoundThread* self = new(ELeave) CStartAndMonitorDevSoundThread(aAudioServer); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: void CStartAndMonitorDevSoundThread::ConstructL() sl@0: { sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: TInt CStartAndMonitorDevSoundThread::StartDevSoundServerL(RMessage2& aMessage, TName& aDevSoundName, TInt aUniqueNum) sl@0: { sl@0: RThread clientThread; sl@0: aMessage.ClientL(clientThread); sl@0: RProcess clientProcess; sl@0: User::LeaveIfError(clientThread.Process(clientProcess)); sl@0: TProcessId clientProcessId(clientProcess.Id()); sl@0: sl@0: clientThread.Close(); sl@0: clientProcess.Close(); sl@0: sl@0: TDevSoundServerStart start(iAudioServer, clientProcessId);//Pass to DevSoundServer the clien't process ID sl@0: sl@0: const TUidType serverUid(KNullUid,KNullUid,KUidDevSoundServer); sl@0: sl@0: TThreadFunction serverFunc=CMMFDevSoundServer::StartThread; sl@0: // sl@0: // To deal with the unique thread (+semaphore!) naming in EPOC, and that we may sl@0: // be trying to restart a server that has just exited we attempt to create a sl@0: // unique thread name for the server. sl@0: // sl@0: sl@0: TInt err = KErrNone; sl@0: TName name(KDevSoundServerName); sl@0: name.AppendNum(TInt(this),EHex); sl@0: name.Append(TChar('.')); sl@0: name.AppendNum(aUniqueNum,EHex); sl@0: err = iServer.Create(name, serverFunc, KDevSoundServerStackSize, sl@0: KDevSoundServerInitHeapSize, KDevSoundServerMaxHeapSize, sl@0: &start, EOwnerProcess); sl@0: sl@0: sl@0: if(err != KErrNone) sl@0: return err; sl@0: // Synchronise with the server sl@0: TRequestStatus reqStatus; sl@0: iServer.Rendezvous(reqStatus); sl@0: sl@0: if (reqStatus!=KRequestPending) sl@0: { sl@0: iServer.Kill(0); sl@0: } sl@0: else sl@0: { sl@0: // Start the test harness sl@0: iServer.Resume(); sl@0: // Server will call the reciprocal static synchronise call sl@0: } sl@0: sl@0: User::WaitForRequest(reqStatus); // wait for start or death sl@0: if(reqStatus.Int() != KErrNone) sl@0: { sl@0: iServer.Close(); sl@0: return reqStatus.Int(); sl@0: } sl@0: sl@0: aDevSoundName = iServer.Name(); sl@0: sl@0: iServer.Logon(iStatus); sl@0: SetActive(); sl@0: sl@0: iAudioServer->IncrementDevSoundCount(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: CStartAndMonitorDevSoundThread::CStartAndMonitorDevSoundThread(CMMFAudioServer* aAudioServer): CActive(0) sl@0: { sl@0: iAudioServer = aAudioServer; sl@0: } sl@0: sl@0: CStartAndMonitorDevSoundThread::~CStartAndMonitorDevSoundThread() sl@0: { sl@0: Cancel(); sl@0: } sl@0: sl@0: void CStartAndMonitorDevSoundThread::RunL() sl@0: { sl@0: iServer.Close(); sl@0: iAudioServer->DecrementDevSoundCount(); sl@0: } sl@0: sl@0: void CStartAndMonitorDevSoundThread::DoCancel() sl@0: { sl@0: iServer.LogonCancel(iStatus); sl@0: } sl@0: sl@0: sl@0: