khronosfws/openmax_al/src/mmf_adaptation/positionupdatetimer.cpp
branchRCL_3
changeset 45 095bea5f582e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/khronosfws/openmax_al/src/mmf_adaptation/positionupdatetimer.cpp	Tue Aug 31 15:43:02 2010 +0300
@@ -0,0 +1,248 @@
+/*
+ * 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: Handles new position timer implementation 
+ *
+ */
+
+#include "positionupdatetimer.h"
+#include <mdaaudiosampleplayer.h>
+#include <videoplayer2.h>
+#include <e32math.h>
+
+extern "C"
+    {
+#include "xarecorditfadaptationmmf.h"
+    }
+
+#define RET_ERR_IF_ERR(s) if (s!=KErrNone) return s;
+#define RET_IF_ERR(s) if (s!=KErrNone) return;
+
+CPositionUpdateTimer::CPositionUpdateTimer(
+        CMdaAudioPlayerUtility* aAudioPlayer,
+        CVideoPlayerUtility2* aVideoPlayer) :
+    CActive(CActive::EPriorityStandard), iAudioPlayer(aAudioPlayer),
+            iVideoPlayer(aVideoPlayer)
+    {
+    CActiveScheduler::Add(this);
+    }
+
+CPositionUpdateTimer::~CPositionUpdateTimer()
+    {
+    Cancel();
+    iTimer.Close();
+    }
+
+CPositionUpdateTimer* CPositionUpdateTimer::NewL(
+        CMdaAudioPlayerUtility* aAudioPlayer,
+        CVideoPlayerUtility2* aVideoPlayer)
+    {
+    CPositionUpdateTimer* self = new (ELeave) CPositionUpdateTimer(
+            aAudioPlayer, aVideoPlayer);
+    CleanupStack::PushL(self);
+    self->CostructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+void CPositionUpdateTimer::CostructL()
+    {
+    User::LeaveIfError(iTimer.CreateLocal());
+    }
+
+void CPositionUpdateTimer::SetContext(TAny* aCtx)
+    {
+    iCtx = aCtx;
+    }
+
+void CPositionUpdateTimer::SetPositionUpdatePeriod(XAmillisecond aPos)
+    {
+    iPositionUpdatePeriod = aPos;
+    iDelay = TTimeIntervalMicroSeconds32(aPos * 1000);
+    }
+
+void CPositionUpdateTimer::SetCallbackEventMask(XAuint32 aMask)
+    {
+    iCallbackEventMask = aMask;
+    }
+
+void CPositionUpdateTimer::RegisterCallback(xaPlayCallback aCallback)
+    {
+    iCallback = aCallback;
+    }
+
+void CPositionUpdateTimer::UseAudioPlayer()
+    {
+    iPlayerToUse = static_cast<CBase*> (iAudioPlayer);
+    }
+void CPositionUpdateTimer::UseVideoPlayer()
+    {
+    iPlayerToUse = static_cast<CBase*> (iVideoPlayer);
+    }
+
+void CPositionUpdateTimer::ResetPlayer()
+    {
+    iPlayerToUse = NULL;
+    }
+
+TInt CPositionUpdateTimer::Start()
+    {
+    TInt retVal(KErrNone);
+    if (IsActive())
+        {
+        Cancel();
+        }
+    if ((iCallbackEventMask & XA_PLAYEVENT_HEADATNEWPOS) && iCallback
+            && iPlayerToUse)
+        {
+        TTimeIntervalMicroSeconds curPlayPos;
+        /* Convert milli to micro */
+        TTimeIntervalMicroSeconds posUpdatePeriod(iPositionUpdatePeriod
+                * 1000);
+        TTimeIntervalMicroSeconds32 delay;
+        /* Convert milli to micro */
+        TReal res;
+        TReal p;
+        TReal q(posUpdatePeriod.Int64());
+
+        iSyncToPlayHead = ETrue;
+
+        retVal = GetCurrentPlayPosition(iSyncToPlayHeadStartPos);
+        RET_ERR_IF_ERR(retVal);
+
+        p = iSyncToPlayHeadStartPos.Int64();
+        /* Adjust delay based on current play position
+         * user may call this in the middle of playback */
+        retVal = Math::Mod(res, p, q);
+        RET_ERR_IF_ERR(retVal);
+
+        /* Let the timer go off early and then re-adjust 
+         * the remaining time based on then current position */
+        delay = (posUpdatePeriod.Int64() - res) / 2;
+#ifdef POSITIONUPDATETIMERLOG
+        // Keep this block for debugging purposes
+        RDebug::Print(_L("CPositionUpdateTimer::RunL:SyncPlayHead[%u]Delay Reset[%u]microSec"),
+                iSyncToPlayHeadStartPos.Int64(),
+                delay.Int());
+#endif /* POSITIONUPDATETIMERLOG */
+        if (delay >= TTimeIntervalMicroSeconds32(0))
+            {
+            iStatus = KRequestPending;
+            iTimer.After(iStatus, delay);
+            SetActive();
+            }
+        }
+    return retVal;
+    }
+
+void CPositionUpdateTimer::Stop()
+    {
+    Cancel();
+    }
+
+void CPositionUpdateTimer::RunL()
+    {
+    TInt retVal(KErrNone);
+    /* Make sure some of the attributes are not unset */
+    if ((iStatus == KErrNone) && iCtx && (iCallbackEventMask
+            & XA_PLAYEVENT_HEADATNEWPOS) && iCallback && iPlayerToUse)
+        {
+        TTimeIntervalMicroSeconds curPlayPos;
+        if (iSyncToPlayHead)
+            {
+            retVal = GetCurrentPlayPosition(curPlayPos);
+            RET_IF_ERR(retVal);
+
+            /* If the play head hasn't moved, re-start all over again */
+            if (curPlayPos == iSyncToPlayHeadStartPos)
+                {
+#ifdef POSITIONUPDATETIMERLOG
+                RDebug::Print(_L("CPositionUpdateTimer::RunL:CurPlayPos[%u]SyncPlayHead[%u]microSec. Restart"),
+                        iSyncToPlayHeadStartPos.Int64(),
+                        curPlayPos.Int64());
+#endif /* POSITIONUPDATETIMERLOG */
+                Start();
+                return;
+                }
+            /* Play head has moved. calculate remaining time and set the timer */
+            /* Convert milli to micro */
+            TTimeIntervalMicroSeconds posUpdatePeriod(iPositionUpdatePeriod
+                    * 1000);
+            TReal res;
+            TReal p;
+            TReal q(posUpdatePeriod.Int64());
+
+            p = curPlayPos.Int64();
+            iSyncToPlayHead = EFalse;
+
+            retVal = Math::Mod(res, p, q);
+            RET_IF_ERR(retVal);
+
+            TTimeIntervalMicroSeconds32 delay = (posUpdatePeriod.Int64()
+                    - res);
+#ifdef POSITIONUPDATETIMERLOG
+            RDebug::Print(_L("CPositionUpdateTimer::RunL:CurPlayPos[%u]SyncPlayHead[%u]Delay Reset[%u]microSec"),
+                    iSyncToPlayHeadStartPos.Int64(),
+                    curPlayPos.Int64(),
+                    delay.Int());
+#endif /* POSITIONUPDATETIMERLOG */
+            if (delay >= TTimeIntervalMicroSeconds32(0))
+                {
+                iStatus = KRequestPending;
+                iTimer.After(iStatus, delay);
+                SetActive();
+                }
+            return;
+            } /* of if (iSyncToPlayHead) */
+
+#ifdef POSITIONUPDATETIMERLOG
+        retVal = GetCurrentPlayPosition(curPlayPos);
+        RDebug::Print(_L("CPositionUpdateTimer::RunL:CurPlayPos[%u]microSec. Posting XA_PLAYEVENT_HEADATNEWPOS."), curPlayPos.Int64());
+#endif /* POSITIONUPDATETIMERLOG */
+        XAAdaptEvent xaevent =
+            {
+            XA_PLAYITFEVENTS, XA_PLAYEVENT_HEADATNEWPOS, 0, 0
+            };
+        XAAdaptationBase_SendAdaptEvents((XAAdaptationBaseCtx*) iCtx,
+                &xaevent);
+        iStatus = KRequestPending;
+        iTimer.After(iStatus, iDelay);
+        SetActive();
+        }
+    }
+
+void CPositionUpdateTimer::DoCancel()
+    {
+    iTimer.Cancel();
+    }
+
+TInt CPositionUpdateTimer::RunError(TInt aError)
+    {
+    return aError;
+    }
+
+TInt CPositionUpdateTimer::GetCurrentPlayPosition(
+        TTimeIntervalMicroSeconds& aPos)
+    {
+    TTimeIntervalMicroSeconds pos;
+    TInt err(KErrNone);
+    if (iPlayerToUse && (iPlayerToUse == iAudioPlayer))
+        {
+        iAudioPlayer->GetPosition(aPos);
+        }
+    else if (iPlayerToUse && (iPlayerToUse == iVideoPlayer))
+        {
+        TRAP(err, aPos = iVideoPlayer->PositionL());
+        }
+    return err;
+    }