khronosfws/openmax_al/src/mmf_adaptation/positionupdatetimer.cpp
changeset 16 43d09473c595
child 25 6f7ceef7b1d1
equal deleted inserted replaced
14:80975da52420 16:43d09473c595
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Handles new position timer implementation 
       
    15 *
       
    16 */
       
    17 
       
    18 #include "positionupdatetimer.h"
       
    19 #include <mdaaudiosampleplayer.h>
       
    20 #include <videoplayer2.h>
       
    21 #include <e32math.h>
       
    22 
       
    23 extern "C" {
       
    24 #include "xarecorditfadaptationmmf.h"
       
    25 }
       
    26 
       
    27 #define RET_ERR_IF_ERR(s) if (s!=KErrNone) return s;
       
    28 #define RET_IF_ERR(s) if (s!=KErrNone) return;
       
    29 
       
    30 CPositionUpdateTimer::CPositionUpdateTimer(
       
    31         CMdaAudioPlayerUtility* aAudioPlayer,
       
    32         CVideoPlayerUtility2* aVideoPlayer)
       
    33 :CActive(CActive::EPriorityStandard),
       
    34  iAudioPlayer(aAudioPlayer),
       
    35  iVideoPlayer(aVideoPlayer)
       
    36     {
       
    37     CActiveScheduler::Add(this);
       
    38     }
       
    39 
       
    40 CPositionUpdateTimer::~CPositionUpdateTimer()
       
    41     {
       
    42     Cancel();
       
    43     iTimer.Close();
       
    44     }
       
    45 
       
    46 CPositionUpdateTimer* CPositionUpdateTimer::NewL(
       
    47         CMdaAudioPlayerUtility* aAudioPlayer,
       
    48         CVideoPlayerUtility2* aVideoPlayer)
       
    49     {
       
    50     CPositionUpdateTimer* self = new (ELeave)CPositionUpdateTimer(aAudioPlayer, aVideoPlayer);
       
    51     CleanupStack::PushL(self);
       
    52     self->CostructL();
       
    53     CleanupStack::Pop(self);
       
    54     return self;
       
    55     }
       
    56 
       
    57 void CPositionUpdateTimer::CostructL()
       
    58     {
       
    59     User::LeaveIfError(iTimer.CreateLocal());    
       
    60     }
       
    61 
       
    62 void CPositionUpdateTimer::SetContext(TAny* aCtx)
       
    63     {
       
    64     iCtx = aCtx;    
       
    65     }
       
    66 
       
    67 void CPositionUpdateTimer::SetPositionUpdatePeriod(XAmillisecond aPos)
       
    68     {
       
    69     iPositionUpdatePeriod = aPos;
       
    70     iDelay = TTimeIntervalMicroSeconds32(aPos*1000);
       
    71     }
       
    72 
       
    73 void CPositionUpdateTimer::SetCallbackEventMask(XAuint32 aMask)
       
    74     {
       
    75     iCallbackEventMask = aMask;
       
    76     }
       
    77 
       
    78 void CPositionUpdateTimer::RegisterCallback(xaPlayCallback aCallback)
       
    79     {
       
    80     iCallback = aCallback;
       
    81     }
       
    82 
       
    83 void CPositionUpdateTimer::UseAudioPlayer()
       
    84     {
       
    85     iPlayerToUse = static_cast<CBase*>(iAudioPlayer);
       
    86     }
       
    87 void CPositionUpdateTimer::UseVideoPlayer()
       
    88     {
       
    89     iPlayerToUse = static_cast<CBase*>(iVideoPlayer);
       
    90     }
       
    91 
       
    92 void CPositionUpdateTimer::ResetPlayer()
       
    93     {
       
    94     iPlayerToUse = NULL;
       
    95     }
       
    96 
       
    97 TInt CPositionUpdateTimer::Start()
       
    98     {
       
    99     TInt retVal(KErrNone);
       
   100     if (IsActive())
       
   101         {
       
   102         Cancel();
       
   103         }
       
   104     if ((iCallbackEventMask & XA_PLAYEVENT_HEADATNEWPOS) &&
       
   105         iCallback &&
       
   106         iPlayerToUse)
       
   107         {
       
   108         TTimeIntervalMicroSeconds curPlayPos;
       
   109         /* Convert milli to micro */
       
   110         TTimeIntervalMicroSeconds posUpdatePeriod(iPositionUpdatePeriod * 1000);
       
   111         TTimeIntervalMicroSeconds32 delay;
       
   112         /* Convert milli to micro */
       
   113         TReal res;
       
   114         TReal p;
       
   115         TReal q(posUpdatePeriod.Int64());
       
   116 
       
   117         iSyncToPlayHead = ETrue;
       
   118 
       
   119         retVal = GetCurrentPlayPosition(iSyncToPlayHeadStartPos);
       
   120         RET_ERR_IF_ERR(retVal);
       
   121 
       
   122         p = iSyncToPlayHeadStartPos.Int64();
       
   123         /* Adjust delay based on current play position
       
   124          * user may call this in the middle of playback */
       
   125         retVal = Math::Mod(res, p, q);
       
   126         RET_ERR_IF_ERR(retVal);
       
   127 
       
   128         /* Let the timer go off early and then re-adjust 
       
   129          * the remaining time based on then current position */
       
   130         delay = (posUpdatePeriod.Int64() - res) / 2;
       
   131 #ifdef POSITIONUPDATETIMERLOG
       
   132         // Keep this block for debugging purposes
       
   133         RDebug::Print(_L("CPositionUpdateTimer::RunL:SyncPlayHead[%u]Delay Reset[%u]microSec"),
       
   134                 iSyncToPlayHeadStartPos.Int64(),
       
   135                 delay.Int());
       
   136 #endif /* POSITIONUPDATETIMERLOG */
       
   137         if ( delay >= TTimeIntervalMicroSeconds32(0))
       
   138             {
       
   139             iStatus = KRequestPending;
       
   140             iTimer.After(iStatus, delay);
       
   141             SetActive();
       
   142             }
       
   143         }
       
   144     return retVal;
       
   145     }
       
   146 
       
   147 void CPositionUpdateTimer::Stop()
       
   148     {
       
   149     Cancel();
       
   150     }
       
   151 
       
   152 void CPositionUpdateTimer::RunL()
       
   153     {
       
   154     TInt retVal(KErrNone);
       
   155     /* Make sure some of the attributes are not unset */
       
   156     if ((iStatus == KErrNone) &&
       
   157             iCtx &&
       
   158             (iCallbackEventMask & XA_PLAYEVENT_HEADATNEWPOS) &&
       
   159             iCallback &&
       
   160             iPlayerToUse)
       
   161         {
       
   162         TTimeIntervalMicroSeconds curPlayPos;
       
   163         if (iSyncToPlayHead)
       
   164             {
       
   165             retVal = GetCurrentPlayPosition(curPlayPos);
       
   166             RET_IF_ERR(retVal);
       
   167 
       
   168             /* If the play head hasn't moved, re-start all over again */
       
   169             if (curPlayPos == iSyncToPlayHeadStartPos)
       
   170                 {
       
   171 #ifdef POSITIONUPDATETIMERLOG
       
   172             RDebug::Print(_L("CPositionUpdateTimer::RunL:CurPlayPos[%u]SyncPlayHead[%u]microSec. Restart"),
       
   173                     iSyncToPlayHeadStartPos.Int64(),
       
   174                     curPlayPos.Int64());
       
   175 #endif /* POSITIONUPDATETIMERLOG */
       
   176                 Start();
       
   177                 return;
       
   178                 }
       
   179             /* Play head has moved. calculate remaining time and set the timer */
       
   180             /* Convert milli to micro */
       
   181             TTimeIntervalMicroSeconds posUpdatePeriod(iPositionUpdatePeriod * 1000);
       
   182             TReal res;
       
   183             TReal p;
       
   184             TReal q(posUpdatePeriod.Int64());
       
   185 
       
   186             p = curPlayPos.Int64();
       
   187             iSyncToPlayHead = EFalse;
       
   188 
       
   189             retVal = Math::Mod(res, p, q);
       
   190             RET_IF_ERR(retVal);
       
   191 
       
   192             TTimeIntervalMicroSeconds32 delay = (posUpdatePeriod.Int64() - res);
       
   193 #ifdef POSITIONUPDATETIMERLOG
       
   194             RDebug::Print(_L("CPositionUpdateTimer::RunL:CurPlayPos[%u]SyncPlayHead[%u]Delay Reset[%u]microSec"),
       
   195                     iSyncToPlayHeadStartPos.Int64(),
       
   196                     curPlayPos.Int64(),
       
   197                     delay.Int());
       
   198 #endif /* POSITIONUPDATETIMERLOG */
       
   199             if ( delay >= TTimeIntervalMicroSeconds32(0))
       
   200                 {
       
   201                 iStatus = KRequestPending;
       
   202                 iTimer.After(iStatus, delay);
       
   203                 SetActive();
       
   204                 }
       
   205             return;
       
   206             } /* of if (iSyncToPlayHead) */
       
   207 
       
   208 #ifdef POSITIONUPDATETIMERLOG
       
   209         retVal = GetCurrentPlayPosition(curPlayPos);
       
   210         RDebug::Print(_L("CPositionUpdateTimer::RunL:CurPlayPos[%u]microSec. Posting XA_PLAYEVENT_HEADATNEWPOS."), curPlayPos.Int64());
       
   211 #endif /* POSITIONUPDATETIMERLOG */
       
   212         XAAdaptEvent xaevent = {XA_PLAYITFEVENTS, XA_PLAYEVENT_HEADATNEWPOS, 0, 0 };
       
   213         XAAdaptationBase_SendAdaptEvents((XAAdaptationBaseCtx*)iCtx, &xaevent );
       
   214         iStatus = KRequestPending;
       
   215         iTimer.After(iStatus, iDelay);
       
   216         SetActive();
       
   217         }
       
   218     }
       
   219 
       
   220 void CPositionUpdateTimer::DoCancel()
       
   221     {
       
   222     iTimer.Cancel();
       
   223     }
       
   224 
       
   225 TInt CPositionUpdateTimer::RunError(TInt /*aError*/)
       
   226     {
       
   227     return KErrNone;
       
   228     }
       
   229 
       
   230 TInt CPositionUpdateTimer::GetCurrentPlayPosition(TTimeIntervalMicroSeconds& aPos)
       
   231     {
       
   232     TTimeIntervalMicroSeconds pos;
       
   233     TInt err(KErrNone);
       
   234     if (iPlayerToUse == iAudioPlayer)
       
   235         {
       
   236         iAudioPlayer->GetPosition(aPos);
       
   237         }
       
   238     else if (iPlayerToUse == iVideoPlayer)
       
   239         {
       
   240         TRAP(err, aPos = iVideoPlayer->PositionL());
       
   241         }
       
   242     return err;
       
   243     }