--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmserv/tms/tmsimpl/src/tmsstreambodyimpl.cpp Tue Feb 02 01:08:46 2010 +0200
@@ -0,0 +1,746 @@
+/*
+ * 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 <stdio.h>
+#include <tms.h>
+#include <tmsstreamobsrvr.h>
+#include <tmsbuffer.h>
+#include <tmseffect.h>
+#include <tmsformat.h>
+#include "tmsutility.h"
+#include "tmscallproxy.h"
+#include "tmsclientserver.h"
+#include "tmsshared.h"
+#include "tmsstreambodyimpl.h"
+#include "tmsmembuffer.h"
+#include "tmsclientsourceimpl.h"
+#include "tmsclientsinkimpl.h"
+#include "tmsvolumeeffectimpl.h"
+#include "tmsgaineffectimpl.h"
+#include "tmsg711formatimpl.h"
+#include "tmsg729formatimpl.h"
+#include "tmsilbcformatimpl.h"
+#include "tmspcmformatimpl.h"
+#include "tmsamrformatimpl.h"
+
+using namespace TMS;
+
+TMSStreamBodyImpl::TMSStreamBodyImpl() :
+ iProxy(NULL),
+ iParent(NULL),
+ iSource(NULL),
+ iSink(NULL),
+ iMsgQHandler(NULL),
+ iObserver(NULL),
+ iFormat(NULL),
+ iStreamState(TMS_STREAM_UNINITIALIZED)
+ {
+ //TMSStream::Construct(this);
+ }
+
+TMSStreamBodyImpl::~TMSStreamBodyImpl()
+ {
+ if (iMsgQHandler)
+ {
+ iMsgQHandler->Cancel();
+ }
+ delete iMsgQHandler;
+ if (iMsgQueue.Handle() > 0)
+ {
+ iMsgQueue.Close();
+ }
+
+ iEffectsList.Reset();
+
+ if (iContext.CallProxy && (iContext.StreamId != -1))
+ {
+ iContext.CallProxy->DeleteStream(iContext.CallType,
+ iContext.StreamType, iContext.StreamId);
+ }
+ }
+
+gint TMSStreamBodyImpl::Create(TMSCallType callType, TMSStreamType stype,
+ TMSCallProxy* proxy, TMSStream& parent, TMSStreamBody*& bodyimpl)
+ {
+ gint ret(TMS_RESULT_INSUFFICIENT_MEMORY);
+ TMSStreamBodyImpl* self = new TMSStreamBodyImpl;
+ if (self)
+ {
+ ret = self->PostConstruct(callType, stype, proxy, parent);
+ if (ret != TMS_RESULT_SUCCESS)
+ {
+ delete self;
+ self = NULL;
+ }
+ }
+ bodyimpl = self;
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::PostConstruct(TMSCallType callType,
+ TMSStreamType stype, TMSCallProxy* proxy, TMSStream& parent)
+ {
+ gint status(TMS_RESULT_SUCCESS);
+ iContext.CallProxy = proxy;
+ iParent = &parent;
+ iContext.CallType = callType;
+ iContext.StreamType = stype;
+
+ status = CreateQueue(KTMSMsgQSlots);
+
+ if (status == TMS_RESULT_SUCCESS)
+ {
+ if (iContext.CallProxy)
+ {
+ status = (iContext.CallProxy)->CreateStream(iContext.CallType,
+ iContext.StreamType, iContext.StreamId);
+ }
+ else
+ {
+ status = TMS_RESULT_UNINITIALIZED_OBJECT;
+ }
+ }
+ return status;
+ }
+
+gint TMSStreamBodyImpl::AddObserver(TMSStreamObserver& obsrvr,
+ gpointer user_data)
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+ // TODO allow support for multiple observers
+ if (!iObserver)
+ {
+ iObserver = &obsrvr;
+ iUserData = user_data;
+ }
+ else
+ {
+ ret = TMS_RESULT_ALREADY_EXIST;
+ }
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::RemoveObserver(TMSStreamObserver& obsrvr)
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+ if (&obsrvr == iObserver)
+ {
+ iObserver = NULL;
+ }
+ else
+ {
+ ret = TMS_RESULT_DOES_NOT_EXIST;
+ }
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::AddSource(TMSSource* source)
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+
+ if (iStreamState == TMS_STREAM_UNINITIALIZED)
+ {
+ if (!iSource)
+ {
+ ret = ValidateSource(source);
+ }
+ else
+ {
+ ret = TMS_RESULT_ALREADY_EXIST;
+ }
+ }
+ else
+ {
+ ret = TMS_RESULT_INVALID_STATE;
+ }
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::RemoveSource(TMSSource* source)
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+ if (iStreamState == TMS_STREAM_UNINITIALIZED)
+ {
+ if (source == iSource)
+ {
+ iSource = NULL;
+ }
+ else
+ {
+ ret = TMS_RESULT_DOES_NOT_EXIST;
+ }
+ }
+ else
+ {
+ ret = TMS_RESULT_INVALID_STATE;
+ }
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::AddSink(TMSSink* sink)
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+
+ if (iStreamState == TMS_STREAM_UNINITIALIZED)
+ {
+ if (!iSink)
+ {
+ ret = ValidateSink(sink);
+ }
+ else
+ {
+ ret = TMS_RESULT_ALREADY_EXIST;
+ }
+ }
+ else
+ {
+ ret = TMS_RESULT_INVALID_STATE;
+ }
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::RemoveSink(TMSSink* sink)
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+
+ if (iStreamState == TMS_STREAM_UNINITIALIZED)
+ {
+ if (sink == iSink)
+ {
+ iSink = NULL;
+ }
+ else
+ {
+ ret = TMS_RESULT_DOES_NOT_EXIST;
+ }
+ }
+ else
+ {
+ ret = TMS_RESULT_INVALID_STATE;
+ }
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::SetFormat(TMSFormat* format)
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+ if (iStreamState == TMS_STREAM_UNINITIALIZED)
+ {
+ ret = ValidateFormat(format);
+ }
+ else
+ {
+ ret = TMS_RESULT_INVALID_STATE;
+ }
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::ResetFormat(TMSFormat* format)
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+ if (iStreamState == TMS_STREAM_UNINITIALIZED)
+ {
+ if (format == iFormat)
+ {
+ iFormat = NULL;
+ }
+ else
+ {
+ ret = TMS_RESULT_DOES_NOT_EXIST;
+ }
+ }
+ else
+ {
+ ret = TMS_RESULT_INVALID_STATE;
+ }
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::AddEffect(TMSEffect* effect)
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+
+ if (iStreamState == TMS_STREAM_UNINITIALIZED)
+ {
+ // Add to list if effect is not already added
+ ret = iEffectsList.Find(effect);
+ if (ret == KErrNotFound)
+ {
+ ret = iEffectsList.Append(effect);
+ }
+ else
+ {
+ ret = TMS_RESULT_ALREADY_EXIST;
+ }
+ }
+ else
+ {
+ ret = TMS_RESULT_INVALID_STATE;
+ }
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::RemoveEffect(TMSEffect* effect)
+ {
+ TInt status(TMS_RESULT_SUCCESS);
+
+ if (iStreamState == TMS_STREAM_UNINITIALIZED)
+ {
+ TInt index = iEffectsList.Find(effect);
+ // If found status has index to the effect in the array
+ // else it would contain KErrNotFound
+ if (index >= 0)
+ {
+ iEffectsList.Remove(index);
+ }
+ else
+ {
+ status = TMS_RESULT_DOES_NOT_EXIST;
+ }
+ }
+ else
+ {
+ status = TMS_RESULT_INVALID_STATE;
+ }
+ return status;
+ }
+
+TMSStreamState TMSStreamBodyImpl::GetState()
+ {
+ return iStreamState;
+ }
+
+TMSStreamType TMSStreamBodyImpl::GetStreamType()
+ {
+ return iContext.StreamType;
+ }
+
+gint TMSStreamBodyImpl::GetStreamId()
+ {
+ return iContext.StreamId;
+ }
+
+gint TMSStreamBodyImpl::Init()
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+
+ ret = ValidateStream();
+
+ RET_REASON_IF_ERR(ret);
+
+ TMSFormatType fmttype;
+ if (!iFormat && iContext.CallType == TMS_CALL_IP)
+ {
+ return TMS_RESULT_FORMAT_TYPE_UNSPECIFIED;
+ }
+ else if (iContext.CallType == TMS_CALL_IP)
+ {
+ iFormat->GetType(fmttype);
+ }
+
+ if (iContext.CallProxy)
+ {
+ ret = (iContext.CallProxy)->InitStream(iContext.CallType,
+ iContext.StreamType, iContext.StreamId, fmttype, &iMsgQueue);
+ }
+ else
+ {
+ ret = TMS_RESULT_UNINITIALIZED_OBJECT;
+ }
+
+ RET_REASON_IF_ERR(ret);
+
+ if (iEffectsList.Count())
+ {
+ for (TInt i = 0; i < iEffectsList.Count(); i++)
+ {
+ TMSEffectType effecttype;
+ iEffectsList[i]->GetType(effecttype);
+ switch (effecttype)
+ {
+ case TMS_EFFECT_GAIN:
+ ((TMSGainEffectImpl*) iEffectsList[i])->SetProxy(
+ iContext.CallProxy, iMsgQHandler);
+ break;
+ case TMS_EFFECT_VOLUME:
+ ((TMSVolumeEffectImpl*) iEffectsList[i])->SetProxy(
+ iContext.CallProxy, iMsgQHandler);
+ break;
+ default:
+ ret = TMS_RESULT_INVALID_ARGUMENT;
+ break;
+ }
+ }
+ }
+
+ if (iFormat)
+ {
+ TMSFormatType fmttype;
+ iFormat->GetType(fmttype);
+ switch (fmttype)
+ {
+ case TMS_FORMAT_PCM:
+ ((TMSPCMFormatImpl*) iFormat)->SetProxy(&iContext,
+ iMsgQHandler);
+ break;
+ case TMS_FORMAT_AMR:
+ ((TMSAMRFormatImpl*) iFormat)->SetProxy(&iContext,
+ iMsgQHandler);
+ break;
+ case TMS_FORMAT_G711:
+ ((TMSG711FormatImpl*) iFormat)->SetProxy(&iContext,
+ iMsgQHandler);
+ break;
+ case TMS_FORMAT_G729:
+ ((TMSG729FormatImpl*) iFormat)->SetProxy(&iContext,
+ iMsgQHandler);
+ break;
+ case TMS_FORMAT_ILBC:
+ ((TMSILBCFormatImpl*) iFormat)->SetProxy(&iContext,
+ iMsgQHandler);
+ break;
+ default:
+ ret = TMS_RESULT_INVALID_ARGUMENT;
+ break;
+ }
+ }
+
+ if (iContext.StreamType == TMS_STREAM_UPLINK)
+ {
+ if (iSink)
+ {
+ TMSSinkType sinkType;
+ iSink->GetType(sinkType);
+ switch (sinkType)
+ {
+ case TMS_SINK_CLIENT:
+ ((TMSClientSinkImpl*) iSink)->SetProxy(
+ iContext.CallProxy, iMsgQHandler);
+ break;
+ case TMS_SINK_MODEM:
+ case TMS_SINK_SPEAKER:
+ break;
+ default:
+ ret = TMS_RESULT_INVALID_ARGUMENT;
+ break;
+ }
+ }
+ else
+ {
+ ret = TMS_RESULT_UNINITIALIZED_OBJECT;
+ }
+ }
+ else if (iContext.StreamType == TMS_STREAM_DOWNLINK)
+ {
+ if (iSource)
+ {
+ TMSSourceType sourceType;
+ iSource->GetType(sourceType);
+ switch (sourceType)
+ {
+ case TMS_SOURCE_CLIENT:
+ ((TMSClientSourceImpl*) iSource)->SetProxy(
+ iContext.CallProxy, iContext.StreamId,
+ iMsgQHandler);
+ break;
+ case TMS_SOURCE_MODEM:
+ case TMS_SOURCE_MIC:
+ break;
+ default:
+ ret = TMS_RESULT_INVALID_ARGUMENT;
+ break;
+ }
+ }
+ else
+ {
+ ret = TMS_RESULT_UNINITIALIZED_OBJECT;
+ }
+ }
+
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::Pause()
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+ if (iContext.CallProxy)
+ {
+ ret = (iContext.CallProxy)->PauseStream(iContext.CallType,
+ iContext.StreamType, iContext.StreamId);
+ }
+ else
+ {
+ ret = TMS_RESULT_UNINITIALIZED_OBJECT;
+ }
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::Start()
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+ if (iContext.CallProxy)
+ {
+ ret = (iContext.CallProxy)->StartStream(iContext.CallType,
+ iContext.StreamType, iContext.StreamId);
+ }
+ else
+ {
+ ret = TMS_RESULT_UNINITIALIZED_OBJECT;
+ }
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::Stop()
+ {
+ gint ret(TMS_RESULT_SUCCESS);
+ if (iContext.CallProxy)
+ {
+ ret = (iContext.CallProxy)->StopStream(iContext.CallType,
+ iContext.StreamType, iContext.StreamId);
+ }
+ else
+ {
+ ret = TMS_RESULT_UNINITIALIZED_OBJECT;
+ }
+ return ret;
+ }
+
+void TMSStreamBodyImpl::Deinit()
+ {
+ if (iContext.CallProxy)
+ {
+ (iContext.CallProxy)->DeinitStream(iContext.CallType,
+ iContext.StreamType, iContext.StreamId);
+ }
+ }
+
+gint TMSStreamBodyImpl::ValidateSource(TMSSource* source)
+ {
+ gint ret(TMS_RESULT_NULL_ARGUMENT);
+ TMSSourceType sourcetype;
+
+ if (source)
+ {
+ source->GetType(sourcetype);
+
+ switch (sourcetype)
+ {
+ case TMS_SOURCE_CLIENT:
+ {
+ if (iContext.CallType == TMS_CALL_IP &&
+ iContext.StreamType == TMS_STREAM_DOWNLINK)
+ {
+ iSource = source;
+ ret = TMS_RESULT_SUCCESS;
+ }
+ }
+ break;
+ case TMS_SOURCE_MIC:
+ {
+ if (iContext.StreamType == TMS_STREAM_UPLINK)
+ {
+ iSource = source;
+ ret = TMS_RESULT_SUCCESS;
+ }
+ }
+ break;
+ case TMS_SOURCE_MODEM:
+ {
+ if (iContext.CallType == TMS_CALL_CS &&
+ iContext.StreamType == TMS_STREAM_DOWNLINK)
+ {
+ iSource = source;
+ ret = TMS_RESULT_SUCCESS;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::ValidateSink(TMSSink* sink)
+ {
+ gint ret(TMS_RESULT_NULL_ARGUMENT);
+ TMSSinkType sinktype;
+
+ if (sink)
+ {
+ sink->GetType(sinktype);
+
+ switch (sinktype)
+ {
+ case TMS_SINK_CLIENT:
+ {
+ if (iContext.CallType == TMS_CALL_IP &&
+ iContext.StreamType == TMS_STREAM_UPLINK)
+ {
+ iSink = sink;
+ ret = TMS_RESULT_SUCCESS;
+ }
+ }
+ break;
+ case TMS_SINK_SPEAKER:
+ {
+ if (iContext.StreamType == TMS_STREAM_DOWNLINK)
+ {
+ iSink = sink;
+ ret = TMS_RESULT_SUCCESS;
+ }
+ }
+ break;
+ case TMS_SINK_MODEM:
+ {
+ if (iContext.CallType == TMS_CALL_CS &&
+ iContext.StreamType == TMS_STREAM_UPLINK)
+ {
+ iSink = sink;
+ ret = TMS_RESULT_SUCCESS;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::ValidateFormat(TMSFormat* format)
+ {
+ gint ret(TMS_RESULT_NULL_ARGUMENT);
+
+ if (format)
+ {
+ if (iContext.CallType == TMS_CALL_IP)
+ {
+ iFormat = format;
+ ret = TMS_RESULT_SUCCESS;
+ }
+ else
+ {
+ ret = TMS_RESULT_INVALID_STATE;
+ }
+ }
+ return ret;
+ }
+
+gint TMSStreamBodyImpl::ValidateStream()
+ {
+ gint ret(TMS_RESULT_INVALID_STATE);
+
+ if (iContext.StreamType == TMS_STREAM_UPLINK ||
+ iContext.StreamType == TMS_STREAM_DOWNLINK)
+ {
+ if (iContext.CallType == TMS_CALL_IP)
+ {
+ if (ValidateSource(iSource) == TMS_RESULT_SUCCESS &&
+ ValidateSink(iSink) == TMS_RESULT_SUCCESS &&
+ ValidateFormat(iFormat) == TMS_RESULT_SUCCESS)
+ {
+ ret = TMS_RESULT_SUCCESS;
+ }
+ }
+ else if (iContext.CallType == TMS_CALL_CS)
+ {
+ if (ValidateSource(iSource) == TMS_RESULT_SUCCESS &&
+ ValidateSink(iSink) == TMS_RESULT_SUCCESS)
+ {
+ ret = TMS_RESULT_SUCCESS;
+ }
+ }
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// TMSStreamBodyImpl::CreateQueue
+// ---------------------------------------------------------------------------
+//
+gint TMSStreamBodyImpl::CreateQueue(const gint aNumSlots)
+ {
+ gint err = TMS_RESULT_INVALID_ARGUMENT;
+
+ if (iMsgQueue.Handle() <= 0)
+ {
+ err = iMsgQueue.CreateGlobal(KNullDesC, aNumSlots);
+ if (err == KErrNone)
+ {
+ TRAP(err, ReceiveMsgQHandlerEventsL());
+ }
+ }
+
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// TMSStreamBodyImpl::ReceiveMsgQHandlerEventsL
+// Starts message queue handler (A/O) to monitor communication and transfer
+// buffer events between client and the server.
+// ---------------------------------------------------------------------------
+//
+void TMSStreamBodyImpl::ReceiveMsgQHandlerEventsL()
+ {
+ if (iMsgQHandler)
+ {
+ iMsgQHandler->Cancel();
+ }
+ else
+ {
+ iMsgQHandler = CQueueHandler::NewL(&iMsgQueue, &iContext);
+ iMsgQHandler->AddObserver(*this, iContext.StreamType);
+ }
+
+ iMsgQHandler->Start();
+ }
+
+// ======== CALLBACK FUNCTIONS ========
+
+void TMSStreamBodyImpl::QueueEvent(TInt aEventType, TInt aError,
+ void* user_data)
+ {
+ TMSSignalEvent event;
+ event.reason = aError;
+ event.user_data = user_data;
+ iStreamState = aEventType;
+
+ switch (aEventType)
+ {
+ case TMS_STREAM_INITIALIZED:
+ case TMS_STREAM_UNINITIALIZED:
+ case TMS_STREAM_PAUSED:
+ case TMS_STREAM_STARTED:
+ {
+ event.curr_state = aEventType;
+ event.prev_state = iPrevState;
+ if (iObserver)
+ {
+ event.type = TMS_EVENT_STREAM_STATE_CHANGED;
+ iObserver->TMSStreamEvent(iParent, event);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ iPrevState = aEventType;
+ }
+