khronosfws/openmax_al/src/mmf_adaptation/positionupdatetimer.cpp
changeset 16 43d09473c595
child 25 6f7ceef7b1d1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/khronosfws/openmax_al/src/mmf_adaptation/positionupdatetimer.cpp	Fri May 14 16:22:35 2010 +0300
@@ -0,0 +1,243 @@
+/*
+* 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 KErrNone;
+    }
+
+TInt CPositionUpdateTimer::GetCurrentPlayPosition(TTimeIntervalMicroSeconds& aPos)
+    {
+    TTimeIntervalMicroSeconds pos;
+    TInt err(KErrNone);
+    if (iPlayerToUse == iAudioPlayer)
+        {
+        iAudioPlayer->GetPosition(aPos);
+        }
+    else if (iPlayerToUse == iVideoPlayer)
+        {
+        TRAP(err, aPos = iVideoPlayer->PositionL());
+        }
+    return err;
+    }