Bug 3673 - Seeking via grabbing the Music Player progress bar does not work.
// 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 <e32svr.h>
#include "TestFrameworkServer.h"
#include "TestFrameworkServer.inl"
#include <testframeworkipc.h>
/**
*
* Initiate server exit when the timer expires
*
* @xxxx
*
*/
void CTestFrameworkServerShutdown::RunL()
{
CActiveScheduler::Stop();
}
/**
*
* Test Framework server static constructor
* NOTE : only one instance of the server process should run
* during any Test Framework run; all client sessions
* will use this one instance.
*
* @xxxx
*
*/
CMmfIpcServer* CTestFrameworkServer::NewL()
{
CTestFrameworkServer* s = new(ELeave) CTestFrameworkServer;
CleanupStack::PushL(s);
s->ConstructL();
CleanupStack::Pop();
return s;
}
/**
*
* Test Framework server first-phase constructor
*
* @xxxx
*
*/
CTestFrameworkServer::CTestFrameworkServer()
:CMmfIpcServer(0, ESharableSessions)
{
}
// set up so that iConsole is NULL. A call to OpenLogL will initialise the console
// and file (if any)
/**
*
* Test Framework server second-phase constructor
* Starts the server; does not initialise the log
* (this must be done independently with a call to OpenLogL)
*
* @xxxx
*
*/
void CTestFrameworkServer::ConstructL()
{
StartL(KTestFrameworkServerName);
//Ensure that the server will exit even if the first client fails to connect
iShutdown.ConstructL();
iShutdown.Start();
iLogMode = 0; // initial value : not running any log
iConsole = NULL;
iFileLogger = NULL;
}
/**
*
* Test Framework server destructor
*
* @xxxx
*
*/
CTestFrameworkServer::~CTestFrameworkServer()
{
CloseLog();
}
/**
*
* Create new server session.
*
* @param "const TVersion &aVersion"
* Server version (required)
*
* @return "CSharableSession*"
* The created server session.
*
* @xxxx
*
*/
CMmfIpcSession* CTestFrameworkServer::NewSessionL(const TVersion &aVersion) const
{
TVersion ver(KTestFrameworkServerMajorVersionNumber,
KTestFrameworkServerMinorVersionNumber,
KTestFrameworkServerBuildVersionNumber);
if (!User::QueryVersionSupported(ver, aVersion))
User::Leave(KErrNotSupported);
// make new session
return new(ELeave) CTestFrameworkServerSession();
}
/**
*
* Add a server session.
*
* @xxxx
*
*/
void CTestFrameworkServer::AddSession()
{
++iSessionCount;
iShutdown.Cancel();
}
/**
*
* Drop a server session.
*
* @xxxx
*
*/
void CTestFrameworkServer::DropSession()
{
if (--iSessionCount <= 0)
iShutdown.Start();
}
/**
*
* Add an input window (at request from client).
*
* @param "CTestFrameworkServerSession* aOwner"
* Window owning server session
*
* @xxxx
*
*/
void CTestFrameworkServer::AddInputWindowL(CTestFrameworkServerSession* aOwner)
{
if (iInputWindow.HasOwner())
User::Leave(KErrAlreadyExists);
// else
iInputWindow.SetOwner(aOwner);
TRect rect;
rect.iTl = TPoint(0,0);
rect.iBr = TPoint(KConsFullScreen, KConsFullScreen);
iInputWindow.SetWinRectAndNotifyOwner(rect);
}
/**
*
* Remove an input window (at request from client).
*
* @param "CTestFrameworkServerSession* aOwner"
* Window owning server session
*
* @xxxx
*
*/
void CTestFrameworkServer::RemoveWindow(CTestFrameworkServerSession* aOwner)
{
if (aOwner == iInputWindow.Owner())
{
iInputWindow.SetOwner(NULL);
}
}
/**
*
* Open a log.
*
* @param "const TDesC& aLogName"
* The log name
*
* @param "TInt aLogMode"
* The log mode (as bitmask of TTestFrameworkLogMode)
*
* @xxxx
*
*/
void CTestFrameworkServer::OpenLogL(const TDesC& aLogName, TInt aLogMode)
{
// NB we need to check if a console is already open - if so, we do NOT
// create another one. Ditto with file / port.
if(aLogMode & ELogToConsole)
{
if(!iConsole)
{
iConsole = CServerConsole::NewL(aLogName);
CConsoleBase* theConsole = iConsole->Console();
theConsole->Printf(_L("%S : Server log starting\n"), &aLogName);
iLogMode |= ELogToConsole;
if (aLogMode & ELogConsoleFull)
iLogMode |= ELogConsoleFull;
iConsole->Read(*this);
}
}
// NB relative paths will not work with TParse (there is no file server open).
// Exception is a bare filename (with no path) : this will be found in root of C:
// NOTE! We have no mechanism to notify this error. The console will display
// and then exit. The log file cannot be opened.
// TO BE ENHANCED - if console is made active, then we can pause
if(aLogMode & ELogToFile)
{
if(!iFileLogger)
{
TRAPD(err, iFileLogger = CFileLogger::NewL());
if(err != KErrNone)
{
// if we can't create a logger, we panic
User::Panic(_L("TestFrameworkServer"), 1);
}
_LIT(KLogPath, "C:\\Logs\\TestResults");
_LIT(KDefault, "C:\\.htm");
TParse parseLogName;
parseLogName.Set(aLogName, NULL, NULL);
TFileName logFilePath;
logFilePath = KLogPath;
if(parseLogName.PathPresent())
logFilePath.Append(parseLogName.Path());
else
logFilePath.Append(_L("\\"));
// overwrite extension if supplied with .htm
TParse logFileFullName;
TInt returnCode = logFileFullName.Set(KDefault, &logFilePath, &aLogName);
if (returnCode == KErrNone)
{
TInt ret = iFileLogger->Connect();
if (ret == KErrNone)
{
iFileLogger->CreateLog(logFilePath, logFileFullName.NameAndExt());
iLogMode |= ELogToFile;
}
}
}
}
if(aLogMode & ELogToPort)
{
// RDebug::Print will deal with the serial port, we don't do anything special here
iLogMode |= ELogToPort;
}
}
/**
*
* Write to the log.
*
* @param "const TDesC& aMsg"
* The message string to write
*
* @param "TInt aLogMode"
* The log mode (as bitmask of TTestFrameworkLogMode)
*
* @xxxx
*
*/
void CTestFrameworkServer::WriteLog(const TDesC& aMsg, TInt aLogMode)
{
if(aLogMode & ELogToConsole)
{
if(iConsole)
{
CConsoleBase* theConsole = iConsole->Console();
theConsole->Printf(aMsg);
theConsole->Printf(_L("\n")); // add newline
}
}
if(aLogMode & ELogToFile)
{
if(iFileLogger)
{
iFileLogger->WriteLog(aMsg);
}
}
if(aLogMode & ELogToPort)
{
RDebug::Print(aMsg);
}
}
/**
*
* Close the log.
*
* @xxxx
*
*/
void CTestFrameworkServer::CloseLog()
{
if (iFileLogger != NULL)
iFileLogger->CloseLog();
delete(iFileLogger);
iFileLogger = NULL;
delete(iConsole);
iConsole = NULL;
iLogMode = 0;
}
/**
*
* Get the log status.
*
* @return "TInt"
* The log status (as bitmask of TTestFrameworkLogMode)
*
* @xxxx
*
*/
TInt CTestFrameworkServer::LogStatus() const
{
return iLogMode;
}
/**
*
* process key input from console.
*
* @param "TKeyCode aKeystroke"
* The keystroke
*
* @xxxx
*
*/
void CTestFrameworkServer::InputReceived(TKeyCode aKeystroke)
{
// store it
iInputKey = STATIC_CAST(TInt, aKeystroke);
// key not processed as yet - pending implementation of async request from client
//read from console again
iConsole->Read(*this);
}
/**
*
* Display general error.
*
* @param "TInt aError"
* The error code
*
* @xxxx
*
*/
void CTestFrameworkServer::Error(TInt)
{
// stubbed; undefined input keys can be safely discarded
}
/**
*
* Default window constructor (no owner)
*
* @xxxx
*
*/
TWindow::TWindow()
{
iOwner = NULL;
}
/**
*
* Default window constructor
*
* @param "CTestFrameworkServerSession* aOwner"
* The window owner
* @xxxx
*
*/
TWindow::TWindow(CTestFrameworkServerSession* aOwner)
{
iOwner = aOwner;
}
/**
*
* Set the window owner
*
* @param "CTestFrameworkServerSession* aOwner"
* The window owner
* @xxxx
*
*/
void TWindow::SetOwner(CTestFrameworkServerSession* aOwner)
{
iOwner = aOwner;
}
/**
*
* Set the window rectangle, and notify owner
*
* @param "const TRect& aWinRect"
* The window rectangle
* @xxxx
*
*/
void TWindow::SetWinRectAndNotifyOwner(const TRect& aWinRect)
{
if (HasOwner())
iOwner->NotifyWindowChanged(aWinRect);
}
/**
*
* Does this window have an owner?
*
* @return "TBool"
* ETrue if window has an owner
* @xxxx
*
*/
TBool TWindow::HasOwner()
{
if (iOwner)
return ETrue;
return EFalse;
}
/**
*
* Server session first-phase constructor
*
* @xxxx
*
*/
CTestFrameworkServerSession::CTestFrameworkServerSession()
{
}
/**
*
* Create a server session.
*
* @param "aServer"
* The server to add this session to
*
* @xxxx
*
*/
void CTestFrameworkServerSession::CreateL(const CMmfIpcServer& aServer)
{
CMmfIpcSession::CreateL(aServer); // does not leave
//Add session to server first. If anything leaves, it will be removed by the destructor
iServer = STATIC_CAST(CTestFrameworkServer*, (CONST_CAST(CMmfIpcServer*, &aServer)));
iServer->AddSession();
ConstructL();
}
/**
*
* Server session second-phase constructor
*
* @xxxx
*
*/
void CTestFrameworkServerSession::ConstructL()
{
}
/**
*
* Server session destructor
*
* @xxxx
*
*/
CTestFrameworkServerSession::~CTestFrameworkServerSession()
{
iServer->RemoveWindow(this);
iServer->DropSession();
}
/**
*
* Server session service function
*
* @param "aMessage"
* The message to be serviced.
*
* @xxxx
*
*/
void CTestFrameworkServerSession::ServiceL(const RMmfIpcMessage& aMessage)
{
switch (aMessage.Function())
{
case ECreateInputWindow:
SetOwnCopyOfWindowMessageL(aMessage);
iServer->AddInputWindowL(this);
break;
case ENotifyIfWindowChange:
SetOwnCopyOfWindowMessageL(aMessage);
break;
case ECancelNotifyIfWindowChange:
CompleteOwnCopyOfWindowMessage(KErrCancel);
aMessage.Complete(KErrNone);
break;
// logging messages
case EOpenLog:
{
TBuf<KMaxLogFilenameLength> msgBuf;
TInt r = MmfMessageUtilX::Read(aMessage, 0, msgBuf);
if (r != KErrNone)
RunError(aMessage, r);
else
{
iServer->OpenLogL(msgBuf, aMessage.Int1());
aMessage.Complete(KErrNone);
}
}
break;
case EWriteLog:
{
TBuf<KMaxLogLineLength> msgBuf;
TInt r = MmfMessageUtilX::Read(aMessage, 0, msgBuf);
if (r != KErrNone)
RunError(aMessage, r);
else
{
iServer->WriteLog(msgBuf, aMessage.Int1());
aMessage.Complete(KErrNone);
}
}
break;
case ECloseLog:
iServer->CloseLog();
aMessage.Complete(KErrNone);
break;
case ELogStatus:
{
TPckgBuf<TInt> countPckg(iServer->LogStatus());
TInt r = MmfMessageUtilX::Write(aMessage, 0, countPckg);
if (r != KErrNone)
RunError(aMessage, r);
else
aMessage.Complete(KErrNone);
}
break;
default:
// ? should panic here
break;
}
}
/**
*
* Error handler for server session.
* Completes the pending message using the error code
*
* @param "TInt aError"
* The error code
*
* @return "TInt"
* The error code (always KErrNone)
*
* @xxxx
*
*/
TInt CTestFrameworkServerSession::RunError(const RMmfIpcMessage& aMessage, TInt aError)
{
aMessage.Complete(aError);
return KErrNone;
}
/**
*
* Set own copy of message.
* Helper function to enable window change notification.
*
* @param "aMessage"
* The message to be serviced.
*
* @xxxx
*
*/
void CTestFrameworkServerSession::SetOwnCopyOfWindowMessageL(const RMmfIpcMessage& aMessage)
{
if (iCanCompleteWindowMessage)
User::Leave(KErrAlreadyExists);
//else
iWindowMessage = aMessage;
iCanCompleteWindowMessage = ETrue;
if (iNeedToNotifyClientOfWindowSizeChange)
{
TInt err = MmfMessageUtil::Write(iWindowMessage, 0, iWinRectBuf);
CompleteOwnCopyOfWindowMessage(err);
iNeedToNotifyClientOfWindowSizeChange = EFalse;
}
}
/**
*
* Complete own copy of message.
* Helper function to enable window change notification.
*
* @param "TInt aReason"
* The message return code.
*
* @xxxx
*
*/
void CTestFrameworkServerSession::CompleteOwnCopyOfWindowMessage(TInt aReason)
{
if (iCanCompleteWindowMessage)
iWindowMessage.Complete(aReason);
iCanCompleteWindowMessage = EFalse;
}
/**
*
* Window change notification.
*
* @param "const TRect& aWinRect"
* The window rectangle.
*
* @xxxx
*
*/
void CTestFrameworkServerSession::NotifyWindowChanged(const TRect& aWinRect)
{
iWinRectBuf() = aWinRect;
if (iCanCompleteWindowMessage)
{
TInt err = MmfMessageUtilX::Write(iWindowMessage, 0, iWinRectBuf);
CompleteOwnCopyOfWindowMessage(err);
}
else
{
iNeedToNotifyClientOfWindowSizeChange = ETrue;
}
}
// EXE/DLL initialisation
// NOTE! None of this should be built when compiling for Unit Testing
#if !defined (__TSU_TESTFRAMEWORK__)
/**
*
* Perform all server initialisation, in particular creation of the
* scheduler and server; then run the scheduler
*
*
* @xxxx
*
*/
static void RunServerL()
{
// 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(CTestFrameworkServer::NewL());
//
// Initialisation complete, now signal the client
RProcess::Rendezvous(KErrNone);
//
// Ready to run
CActiveScheduler::Start();
//
// Cleanup the server and scheduler
CleanupStack::PopAndDestroy(2);
}
/**
*
* Main entry point for the server thread
*
* @param "TTestFrameworkServerStart& aStart"
* The server starter.
*
* @xxxx
*
*/
static TInt RunServer()
{
__UHEAP_MARK;
CTrapCleanup* cleanup = CTrapCleanup::New();
TInt r = KErrNoMemory;
if (cleanup)
{
TRAP(r, RunServerL());
delete cleanup;
}
//
__UHEAP_MARKEND;
return r;
}
GLDEF_C TInt E32Main()
// Server process entry-point
// Recover the startup parameters and run the server
{
TInt r = RunServer();
return r;
}
#endif // __TSU_TESTFRAMEWORK__