--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmserv/tms/tmsproxy/src/tmsproxy.cpp Tue Feb 02 01:08:46 2010 +0200
@@ -0,0 +1,666 @@
+/*
+ * Copyright (c) 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: Telephony Multimedia Service
+ *
+ */
+
+#include <s32mem.h>
+#include <AudioPreference.h>
+#include <tmseffectobsrvr.h>
+#include <tmsglobalroutingobsrvr.h>
+#include "tmsutility.h"
+#include "tmsclientserver.h"
+#include "tmsproxy.h"
+
+using namespace TMS;
+
+// CONSTANTS
+const TUint KServerConnectRetries = 2;
+const TUint KSessionMessageSlots = 10;
+
+// -----------------------------------------------------------------------------
+// StartServer
+// Static function to start the server process thread.
+// Start the server process/thread which lives in an EPOCEXE object.
+// Returns: gint: TMS_RESULT_SUCCESS (0) if no error
+// -----------------------------------------------------------------------------
+//
+static gint StartServer()
+ {
+ const TUidType serverUid(KNullUid, KNullUid, KTMSServerUid3);
+
+ // Only one instance of the server is allowed. Attempt of launching
+ // second instance of the server will fail with KErrAlreadyExists.
+ RProcess server;
+ gint r = server.Create(KTMSServerName, KNullDesC, serverUid);
+
+ if (r != TMS_RESULT_SUCCESS)
+ {
+ return r;
+ }
+
+ TRequestStatus stat;
+ server.Rendezvous(stat);
+
+ if (stat != KRequestPending)
+ {
+ server.Kill(0); // abort startup
+ }
+ else
+ {
+ server.Resume(); // logon OK - start the server
+ }
+
+ User::WaitForRequest(stat); // wait for start or death
+
+ // Panic reason cannot be '0' as it would conflict with TMS_RESULT_SUCCESS
+ r = (server.ExitType() == EExitPanic) ? KErrGeneral : stat.Int();
+ server.Close();
+ return r;
+ }
+
+// -----------------------------------------------------------------------------
+// TMSProxy::TMSProxy
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TMSProxy::TMSProxy()
+ {
+ iEffectsObsrvrList.Reset();
+ iEffectsParentList.Reset();
+ iRoutingObsrvrList.Reset();
+ iRoutingParentList.Reset();
+ iMsgQHandler = NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// TMSProxy::~TMSProxy
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TMSProxy::~TMSProxy()
+ {
+ iEffectsObsrvrList.Reset();
+ iEffectsParentList.Reset();
+ iRoutingObsrvrList.Reset();
+ iRoutingParentList.Reset();
+
+ if (iMsgQHandler)
+ {
+ iMsgQHandler->Cancel();
+ }
+ delete iMsgQHandler;
+ if (iMsgQueue.Handle() > 0)
+ {
+ iMsgQueue.Close();
+ }
+ if (Handle() > 0)
+ {
+ Close();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// TMSProxy::Connect
+// Create a client-side session. Start the server if not started already.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C gint TMSProxy::Connect()
+ {
+ TRACE_PRN_FN_ENT;
+
+ gint retry = KServerConnectRetries;
+ gint err(TMS_RESULT_GENERAL_ERROR);
+ gint numMessageSlots = KSessionMessageSlots;
+
+ for (;;)
+ {
+ // Try to create a new session with the server
+ err = CreateSession(KTMSServerName, Version(), numMessageSlots);
+
+ if ((err != KErrNotFound) && (err != KErrServerTerminated))
+ {
+ TRACE_PRN_N1(_L("[TMS session created; err==%d]"), err);
+ break; // Connected to existing server - ok
+ }
+
+ if (--retry == 0)
+ {
+ break; // Failed.
+ }
+
+ // Server not running, try to start it.
+ err = StartServer();
+ TRACE_PRN_N1(_L("[TMS server started; err==%d]"), err);
+
+ if ((err != TMS_RESULT_SUCCESS) && (err != KErrAlreadyExists))
+ {
+ break; // Server not launched - propagate error
+ }
+ }
+
+ TRACE_PRN_IF_ERR(err);
+
+ if (err == KErrNone)
+ {
+ err = CreateQueue(KTMSMsgQSlots);
+ }
+
+ TRACE_PRN_FN_EXT;
+ return TMSRESULT(err);
+ }
+
+// -----------------------------------------------------------------------------
+// TMSProxy::Version
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TVersion TMSProxy::Version() const
+ {
+ return (TVersion(KTMSServMajorVersionNumber,
+ KTMSServMinorVersionNumber, KTMSServBuildVersionNumber));
+ }
+
+// -----------------------------------------------------------------------------
+// TMSProxy::Close
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void TMSProxy::Close()
+ {
+ TRACE_PRN_FN_ENT;
+ RSessionBase::Close();
+ TRACE_PRN_FN_EXT;
+ }
+
+EXPORT_C gint TMSProxy::GetTMSCallSessionHandle()
+ {
+ gint err(TMS_RESULT_SUCCESS);
+ err = SendReceive(ETMSCallSessionHandle);
+ return TMSRESULT(err);
+ }
+
+EXPORT_C gint TMSProxy::GetSupportedDecoders(RArray<TUint32>& aDecoders,
+ gint& aFrameSize)
+ {
+ TRACE_PRN_FN_ENT;
+ gint err(TMS_RESULT_SUCCESS);
+
+ TmsMsgBufPckg pckg1;
+ TIpcArgs args1(&pckg1);
+ err = SendReceive(ETMSGetSupportedDecodersCount, args1);
+ gint count = 0;
+ aFrameSize = 0;
+
+ if (err == TMS_RESULT_SUCCESS)
+ {
+ count = pckg1().iInt;
+ aFrameSize = pckg1().iUint; //for g711 10/20ms frame detection
+ err = pckg1().iStatus;
+ }
+
+ if (count > 0 && err == TMS_RESULT_SUCCESS)
+ {
+ TRAP(err, PopulateArrayL(ETMSGetSupportedDecoders, aDecoders, count));
+ }
+
+ TRACE_PRN_FN_EXT;
+ return TMSRESULT(err);
+ }
+
+EXPORT_C gint TMSProxy::GetSupportedEncoders(RArray<TUint32>& aEncoders,
+ gint& aFrameSize)
+ {
+ TRACE_PRN_FN_ENT;
+ gint err(TMS_RESULT_SUCCESS);
+
+ TmsMsgBufPckg pckg1;
+ TIpcArgs args1(&pckg1);
+ err = SendReceive(ETMSGetSupportedEncodersCount, args1);
+ gint count = 0;
+ aFrameSize = 0;
+
+ if (err == TMS_RESULT_SUCCESS)
+ {
+ count = pckg1().iInt;
+ aFrameSize = pckg1().iUint; //for g711 10/20ms frame detection
+ err = pckg1().iStatus;
+ }
+
+ if (count > 0 && err == TMS_RESULT_SUCCESS)
+ {
+ TRAP(err, PopulateArrayL(ETMSGetSupportedEncoders, aEncoders, count));
+ }
+
+ TRACE_PRN_FN_EXT;
+ return TMSRESULT(err);
+ }
+
+EXPORT_C gint TMSProxy::SetOutput(TMSAudioOutput output)
+ {
+ TRACE_PRN_FN_ENT;
+ gint status = TMS_RESULT_SUCCESS;
+ if (output == TMS_AUDIO_OUTPUT_NONE)
+ {
+ status = TMS_RESULT_INVALID_ARGUMENT;
+ }
+ else
+ {
+ status = RSessionBase::SendReceive(ETMSSetOutput, TIpcArgs(output));
+ }
+ TRACE_PRN_FN_EXT;
+ return TMSRESULT(status);
+ }
+
+EXPORT_C gint TMSProxy::GetOutput(TMSAudioOutput& output)
+ {
+ TRACE_PRN_FN_ENT;
+ TPckgBuf<guint> pckg;
+ TIpcArgs args(&pckg);
+ gint status = RSessionBase::SendReceive(ETMSGetOutput, args);
+ if (status == TMS_RESULT_SUCCESS)
+ {
+ output = pckg();
+ }
+ TRACE_PRN_FN_EXT;
+ return TMSRESULT(status);
+ }
+
+EXPORT_C gint TMSProxy::GetPreviousOutput(TMSAudioOutput& output)
+ {
+ TRACE_PRN_FN_ENT;
+ TPckgBuf<guint> pckg;
+ TIpcArgs args(&pckg);
+ gint status = RSessionBase::SendReceive(ETMSGetPreviousOutput, args);
+ if (status == TMS_RESULT_SUCCESS)
+ {
+ output = pckg();
+ }
+ TRACE_PRN_FN_EXT;
+ return TMSRESULT(status);
+ }
+
+EXPORT_C gint TMSProxy::GetAvailableOutputs(OutputVector& outputs)
+ {
+ gint status(TMS_RESULT_DOES_NOT_EXIST);
+ TRAP(status, GetAvailableOutputsL(outputs));
+ return TMSRESULT(status);
+ }
+
+void TMSProxy::GetAvailableOutputsL(OutputVector& outputs)
+ {
+ HBufC8* buf = HBufC8::NewLC(10 * sizeof(TUint32));
+ TPtr8 ptr = buf->Des();
+ TPckgBuf<gint> countpkg;
+ TIpcArgs args;
+ args.Set(0, &countpkg);
+ args.Set(1, &ptr);
+ gint status = SendReceive(ETMSGetAvailableOutputs, args);
+ outputs.clear();
+ if (status != TMS_RESULT_SUCCESS)
+ {
+ User::Leave(status);
+ }
+ else
+ {
+ RDesReadStream stream(ptr);
+ CleanupClosePushL(stream);
+
+ for (gint i = 0; i < countpkg(); i++)
+ {
+ TMSAudioOutput output = stream.ReadUint32L();
+ if (output != TMS_AUDIO_OUTPUT_NONE)
+ {
+ outputs.push_back(output);
+ }
+ //TRACE_PRN_N1(_L("TMS->TMSProxy: outputs: [%d]"), stream.ReadUint32L());
+ }
+
+ CleanupStack::PopAndDestroy(&stream);
+ }
+ CleanupStack::PopAndDestroy(buf);
+ }
+
+EXPORT_C gint TMSProxy::GetLevel(guint& level)
+ {
+ TRACE_PRN_FN_ENT;
+ TPckgBuf<guint> pckg;
+ TIpcArgs args(&pckg);
+ gint status = RSessionBase::SendReceive(ETMSGetGlobalVol, args);
+ if (status == TMS_RESULT_SUCCESS)
+ {
+ level = pckg();
+ }
+ TRACE_PRN_FN_EXT;
+ return TMSRESULT(status);
+ }
+
+EXPORT_C gint TMSProxy::GetMaxLevel(guint& level)
+ {
+ TRACE_PRN_FN_ENT;
+ TPckgBuf<guint> pckg;
+ TIpcArgs args(&pckg);
+ gint status = RSessionBase::SendReceive(ETMSGetMaxGlobalVol, args);
+ if (status == TMS_RESULT_SUCCESS)
+ {
+ level = pckg();
+ }
+ TRACE_PRN_FN_EXT;
+ return TMSRESULT(status);
+ }
+
+EXPORT_C gint TMSProxy::SetLevel(guint level)
+ {
+ TRACE_PRN_FN_ENT;
+ gint status = RSessionBase::SendReceive(ETMSSetGlobalVol, TIpcArgs(level));
+ TRACE_PRN_FN_EXT;
+ return TMSRESULT(status);
+ }
+
+EXPORT_C gint TMSProxy::GetGain(guint& level)
+ {
+ TRACE_PRN_FN_ENT;
+ TPckgBuf<guint> pckg;
+ TIpcArgs args(&pckg);
+ gint status = RSessionBase::SendReceive(ETMSGetGlobalGain, args);
+ if (status == TMS_RESULT_SUCCESS)
+ {
+ level = pckg();
+ }
+ TRACE_PRN_FN_EXT;
+ return TMSRESULT(status);
+ }
+
+EXPORT_C gint TMSProxy::GetMaxGain(guint& level)
+ {
+ TRACE_PRN_FN_ENT;
+ TPckgBuf<guint> pckg;
+ TIpcArgs args(&pckg);
+ gint status = RSessionBase::SendReceive(ETMSGetMaxGlobalGain, args);
+ if (status == TMS_RESULT_SUCCESS)
+ {
+ level = pckg();
+ }
+ TRACE_PRN_FN_EXT;
+ return TMSRESULT(status);
+ }
+
+EXPORT_C gint TMSProxy::SetGain(guint level)
+ {
+ TRACE_PRN_FN_ENT;
+ gint status = RSessionBase::SendReceive(ETMSSetGlobalGain,
+ TIpcArgs(level));
+ TRACE_PRN_FN_EXT;
+ return TMSRESULT(status);
+ }
+
+EXPORT_C gint TMSProxy::StartGlobalEffectNotifier()
+ {
+ gint status(TMS_RESULT_SUCCESS);
+ RSessionBase::SendReceive(ETMSStartGlobalEffectNotifier); //CenRepHandler
+ return TMSRESULT(status);
+ }
+
+EXPORT_C gint TMSProxy::CancelGlobalEffectNotifier()
+ {
+ gint status(TMS_RESULT_SUCCESS);
+ status = RSessionBase::SendReceive(ETMSCancelGlobalEffectNotifier);
+ return TMSRESULT(status);
+ }
+
+EXPORT_C gint TMSProxy::StartRoutingNotifier()
+ {
+ gint status(TMS_RESULT_SUCCESS);
+ status = RSessionBase::SendReceive(ETMSStartRoutingNotifier); //TAR
+ return TMSRESULT(status);
+ }
+
+EXPORT_C gint TMSProxy::CancelRoutingNotifier()
+ {
+ gint status(TMS_RESULT_SUCCESS);
+ status = RSessionBase::SendReceive(ETMSCancelRoutingNotifier);
+ return TMSRESULT(status);
+ }
+
+// ---------------------------------------------------------------------------
+// TMSProxy::SetMsgQueueNotifier
+// ---------------------------------------------------------------------------
+//
+EXPORT_C gint TMSProxy::SetMsgQueueNotifier(TMSMsgQueueNotifierType type,
+ gpointer obsrv, gpointer parent, gint clientid)
+ {
+ gint status(TMS_RESULT_SUCCESS);
+ switch (type)
+ {
+ case EMsgQueueGlobalVolumeType:
+ case EMsgQueueGlobalGainType:
+ status = AddGlobalEffectObserver((*(TMSEffectObserver*) obsrv),
+ (*(TMSEffect*)parent), clientid);
+ break;
+ case EMsgQueueGlobalRoutingType:
+ status = AddRoutingObserver((*(TMSGlobalRoutingObserver*) obsrv),
+ (*(TMSGlobalRouting*)parent), clientid);
+ break;
+ default:
+ status = TMS_RESULT_INVALID_ARGUMENT;
+ break;
+ }
+ return TMSRESULT(status);
+ }
+
+// ---------------------------------------------------------------------------
+// TMSProxy::RemoveMsgQueueNotifier
+// ---------------------------------------------------------------------------
+//
+EXPORT_C gint TMSProxy::RemoveMsgQueueNotifier(TMSMsgQueueNotifierType type,
+ gpointer obsrv)
+ {
+ gint status(TMS_RESULT_SUCCESS);
+
+ switch (type)
+ {
+ case EMsgQueueGlobalVolumeType:
+ case EMsgQueueGlobalGainType:
+ status = RemoveGlobalEffectObserver((*(TMSEffectObserver*) obsrv));
+ break;
+ case EMsgQueueGlobalRoutingType:
+ status = RemoveRoutingObserver((*(TMSGlobalRoutingObserver*) obsrv));
+ break;
+ default:
+ status = TMS_RESULT_INVALID_ARGUMENT;
+ break;
+ }
+ return TMSRESULT(status);
+ }
+
+void TMSProxy::PopulateArrayL(TMSClientServerRequest aRequest,
+ RArray<TUint32>& aDecoders, gint aCount)
+ {
+ HBufC8* buf = HBufC8::NewLC(aCount * sizeof(TUint32));
+ TPtr8 ptr = buf->Des();
+ TIpcArgs args;
+ args.Set(0, &ptr);
+ gint err = SendReceive(aRequest, args);
+
+ if (err == TMS_RESULT_SUCCESS)
+ {
+ RDesReadStream stream(ptr);
+ CleanupClosePushL(stream);
+ aDecoders.Reset();
+
+ for (gint i = 0; i < aCount; i++)
+ {
+ aDecoders.Append(stream.ReadUint32L());
+ }
+ CleanupStack::PopAndDestroy(&stream);
+ }
+ CleanupStack::PopAndDestroy(buf);
+ }
+
+gint TMSProxy::AddGlobalEffectObserver(TMSEffectObserver& obsrv,
+ TMSEffect& parent, gint /*clientid*/)
+ {
+ gint status = iEffectsObsrvrList.Find(&obsrv);
+ if (status == KErrNotFound)
+ {
+ status = iEffectsObsrvrList.Append(&obsrv);
+ status = iEffectsParentList.Append(&parent);
+ //status = iClientList.Append(clientid);
+ }
+ else
+ {
+ status = TMS_RESULT_ALREADY_EXIST;
+ }
+ return TMSRESULT(status);
+ }
+
+gint TMSProxy::RemoveGlobalEffectObserver(TMSEffectObserver& obsrv)
+ {
+ gint status(TMS_RESULT_SUCCESS);
+ gint index = iEffectsObsrvrList.Find(&obsrv);
+ if (index >= 0)
+ {
+ iEffectsObsrvrList.Remove(index);
+ iEffectsParentList.Remove(index);
+ //iClientList.Remove(index);
+ }
+ else
+ {
+ status = TMS_RESULT_DOES_NOT_EXIST;
+ }
+ return TMSRESULT(status);
+ }
+
+gint TMSProxy::AddRoutingObserver(TMSGlobalRoutingObserver& obsrv,
+ TMSGlobalRouting& parent, gint /*clientid*/)
+ {
+ gint status = iRoutingObsrvrList.Find(&obsrv);
+ if (status == KErrNotFound)
+ {
+ status = iRoutingObsrvrList.Append(&obsrv);
+ status = iRoutingParentList.Append(&parent);
+ //status = iClientList.Append(clientid);
+ }
+ else
+ {
+ status = TMS_RESULT_ALREADY_EXIST;
+ }
+ return TMSRESULT(status);
+ }
+
+gint TMSProxy::RemoveRoutingObserver(TMSGlobalRoutingObserver& obsrv)
+ {
+ gint status(TMS_RESULT_SUCCESS);
+ gint index = iRoutingObsrvrList.Find(&obsrv);
+ if (index >= 0)
+ {
+ iRoutingObsrvrList.Remove(index);
+ iRoutingParentList.Remove(index);
+ //iClientList.Remove(index);
+ }
+ else
+ {
+ status = TMS_RESULT_DOES_NOT_EXIST;
+ }
+ return TMSRESULT(status);
+ }
+
+// ---------------------------------------------------------------------------
+// TMSProxy::CreateQueue
+// ---------------------------------------------------------------------------
+//
+gint TMSProxy::CreateQueue(const gint aNumSlots)
+ {
+ gint status(TMS_RESULT_INVALID_ARGUMENT);
+
+ if (iMsgQueue.Handle() <= 0)
+ {
+ status = iMsgQueue.CreateGlobal(KNullDesC, aNumSlots);
+ if (status == TMS_RESULT_SUCCESS)
+ {
+ TRAP(status, ReceiveMsgQHandlerEventsL());
+ if (status == TMS_RESULT_SUCCESS)
+ {
+ TIpcArgs args;
+ args.Set(0, iMsgQueue);
+ status = RSessionBase::SendReceive(ETMSSetMsgQueueHandle,
+ args);
+ }
+ }
+ }
+ return TMSRESULT(status);
+ }
+
+// ---------------------------------------------------------------------------
+// TMSProxy::ReceiveMsgQHandlerEventsL
+// Starts message queue handler (A/O) to monitor communication and transfer
+// buffer events between client and the server.
+// ---------------------------------------------------------------------------
+//
+void TMSProxy::ReceiveMsgQHandlerEventsL()
+ {
+ if (iMsgQHandler)
+ {
+ iMsgQHandler->Cancel();
+ }
+ else
+ {
+ iMsgQHandler = CQueueHandler::NewL(&iMsgQueue, NULL);
+ iMsgQHandler->AddObserver(*this, -1);
+ }
+ iMsgQHandler->Start();
+ }
+
+// ---------------------------------------------------------------------------
+// TMSProxy::QueueEvent
+// Call from QueueHandler as a result of TMS Server callback.
+// ---------------------------------------------------------------------------
+//
+void TMSProxy::QueueEvent(gint aEventType, gint aError, void* user_data)
+ {
+ TMSSignalEvent event;
+ event.type = aEventType;
+ event.reason = aError;
+ event.user_data = user_data;
+
+ switch (aEventType)
+ {
+ case TMS_EVENT_EFFECT_VOL_CHANGED:
+ case TMS_EVENT_EFFECT_GAIN_CHANGED:
+ {
+ for (gint i = 0; i < iEffectsObsrvrList.Count(); i++)
+ {
+ iEffectsObsrvrList[i]->EffectsEvent(iEffectsParentList[i],
+ event);
+ }
+ break;
+ }
+ case TMS_EVENT_ROUTING_AVAIL_OUTPUTS_CHANGED:
+ case TMS_EVENT_ROUTING_OUTPUT_CHANGED:
+ case TMS_EVENT_ROUTING_SET_OUTPUT_COMPLETE:
+ {
+ guint output(0);
+ if (user_data != NULL)
+ {
+ output = *((guint*) user_data);
+ }
+ for (gint i = 0; i < iRoutingObsrvrList.Count(); i++)
+ {
+ iRoutingObsrvrList[i]->GlobalRoutingEvent(iRoutingParentList[i],
+ event, output);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+// End of file