upnpavcontroller/upnprenderingstatemachine/src/upnprenderingstatemachine.cpp
branchIOP_Improvements
changeset 40 08b5eae9f9ff
equal deleted inserted replaced
39:6369bfd1b60d 40:08b5eae9f9ff
       
     1 /*
       
     2 * Copyright (c) 2007,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:  Implementation of generic upnp remote rendering state machine
       
    15 *
       
    16 */
       
    17 
       
    18 // INCLUDES
       
    19 // dlnasrv / mediaserver api
       
    20 #include <upnpitem.h>
       
    21 
       
    22 // dlnasrv / avcontroller api
       
    23 #include "upnpavrenderingsession.h"
       
    24 #include "upnpavdevice.h"
       
    25 #include "upnpitemutility.h"
       
    26 #include "upnpconstantdefs.h"
       
    27 #include "upnprenderingstatemachineconstants.h"
       
    28 #include "upnprenderingstatemachineobserver.h"
       
    29 
       
    30 // dlnasrv / component internal
       
    31 #include "upnprenderingoperation.h"
       
    32 #include "upnprenderingplaytimecalculator.h"
       
    33 #include "upnpretraces.h"
       
    34 #include "upnprenderingstatemachine.h"
       
    35 #include "upnpavcontrollerglobals.h"
       
    36 
       
    37 _LIT( KComponentLogfile, "upnprenderingstatemachine.txt");
       
    38 #include "upnplog.h"
       
    39 
       
    40 // CONSTANTS
       
    41 const TInt64 KMicrosecondsInMillisecond = 1000;
       
    42 const TInt KSeekThresholdTime = 2000; //ms
       
    43 
       
    44 // ======== MEMBER FUNCTIONS ========
       
    45 
       
    46 // --------------------------------------------------------------------------
       
    47 // CUpnpRenderingStateMachine::NewL
       
    48 // Static constructor.
       
    49 // --------------------------------------------------------------------------
       
    50 //
       
    51 EXPORT_C CUpnpRenderingStateMachine* CUpnpRenderingStateMachine::NewL( 
       
    52     MUPnPAVRenderingSession& aSession )
       
    53     {
       
    54     CUpnpRenderingStateMachine* self =
       
    55         new (ELeave) CUpnpRenderingStateMachine( aSession );
       
    56     CleanupStack::PushL( self );
       
    57     self->ConstructL();
       
    58     CleanupStack::Pop( self );
       
    59     return self;
       
    60     }
       
    61 
       
    62 // --------------------------------------------------------------------------
       
    63 // CUpnpRenderingStateMachine::CUpnpRenderingStateMachine
       
    64 // default constructor
       
    65 // --------------------------------------------------------------------------
       
    66 //
       
    67 CUpnpRenderingStateMachine::CUpnpRenderingStateMachine( 
       
    68     MUPnPAVRenderingSession& aSession )
       
    69     : iSession( aSession )
       
    70     {
       
    71     iState = Upnp::EOffSync;
       
    72     iObserver = NULL;
       
    73     iOptions = 0;
       
    74     iSelector = 0;
       
    75     }
       
    76 
       
    77 // --------------------------------------------------------------------------
       
    78 // CUpnpRenderingStateMachine::ConstructL
       
    79 // 2nd phase constructor
       
    80 // --------------------------------------------------------------------------
       
    81 //
       
    82 void CUpnpRenderingStateMachine::ConstructL()
       
    83     {
       
    84     __LOG( "RenderingStateMachine::ConstructL" );
       
    85     iPlaytimeCalculator = new(ELeave) CUpnpRenderingPlaytimeCalculator();
       
    86     }
       
    87 
       
    88 // --------------------------------------------------------------------------
       
    89 // CUpnpRenderingStateMachine::~CUpnpRenderingStateMachine
       
    90 // destructor
       
    91 // --------------------------------------------------------------------------
       
    92 //
       
    93 EXPORT_C CUpnpRenderingStateMachine::~CUpnpRenderingStateMachine()
       
    94     {
       
    95     __LOG( "RenderingStateMachine: ~CUpnpRenderingStateMachine" );
       
    96     delete iPlaytimeCalculator;
       
    97     iQueue.Close();
       
    98     iObserver = NULL;
       
    99     __LOG( "RenderingStateMachine: ~CUpnpRenderingStateMachine end" );
       
   100     }
       
   101 
       
   102 
       
   103 
       
   104 // --------------------------------------------------------------------------
       
   105 // CUpnpRenderingStateMachine::SetOptions
       
   106 // sets the option flags for this state machine
       
   107 // --------------------------------------------------------------------------
       
   108 //
       
   109 EXPORT_C void CUpnpRenderingStateMachine::SetOptions( TInt aOptions )
       
   110     {
       
   111     iOptions = aOptions;
       
   112     }
       
   113 
       
   114 // --------------------------------------------------------------------------
       
   115 // CUpnpRenderingStateMachine::Options
       
   116 // --------------------------------------------------------------------------
       
   117 //
       
   118 EXPORT_C TInt CUpnpRenderingStateMachine::Options() const
       
   119     {
       
   120     return iOptions;
       
   121     }
       
   122 
       
   123 // --------------------------------------------------------------------------
       
   124 // CUpnpRenderingStateMachine::SetObserver
       
   125 // --------------------------------------------------------------------------
       
   126 //
       
   127 EXPORT_C void CUpnpRenderingStateMachine::SetObserver(
       
   128     MUpnpRenderingStateMachineObserver& aObserver )
       
   129     {
       
   130     iObserver = &aObserver;
       
   131     }
       
   132 
       
   133 // --------------------------------------------------------------------------
       
   134 // CUpnpRenderingStateMachine::RemoveObserver
       
   135 // --------------------------------------------------------------------------
       
   136 //
       
   137 EXPORT_C void CUpnpRenderingStateMachine::RemoveObserver()
       
   138     {
       
   139     iObserver = NULL;
       
   140     }
       
   141 
       
   142 // --------------------------------------------------------------------------
       
   143 // CUpnpRenderingStateMachine::SetResourceSelector
       
   144 // custom selection for resource inside item
       
   145 // selects which resource is used in SetAvTransportUri
       
   146 // --------------------------------------------------------------------------
       
   147 //
       
   148 EXPORT_C void CUpnpRenderingStateMachine::SetResourceSelector(
       
   149     MUPnPResourceSelector& aSelector )
       
   150     {
       
   151     __LOG( "RenderingStateMachine: SetResourceSelector" );
       
   152     iSelector = &aSelector;
       
   153     }
       
   154 
       
   155 // --------------------------------------------------------------------------
       
   156 // CUpnpRenderingStateMachine::SyncL
       
   157 // synchronises the state machine with renderer
       
   158 // --------------------------------------------------------------------------
       
   159 //
       
   160 EXPORT_C void CUpnpRenderingStateMachine::SyncL()
       
   161     {
       
   162     __LOG( "CUpnpRenderingStateMachine::SyncL" );
       
   163     __ASSERT( !IsInSync(), __FILE__, __LINE__ );
       
   164     __ASSERT( !IsBusy(), __FILE__, __LINE__ );
       
   165     if ( IsInSync() )
       
   166         {
       
   167         User::Leave( KErrGeneral );
       
   168         }
       
   169     if ( IsBusy() )
       
   170         {
       
   171         User::Leave( KErrServerBusy );
       
   172         }
       
   173     TUpnpRenderingOperation sync(
       
   174         Upnp::ESync );
       
   175     PushAndExecuteL( sync );
       
   176     }
       
   177 
       
   178 // --------------------------------------------------------------------------
       
   179 // CUpnpRenderingStateMachine::SetOffSync
       
   180 // sets this state machine off sync
       
   181 // --------------------------------------------------------------------------
       
   182 //
       
   183 EXPORT_C void CUpnpRenderingStateMachine::SetOffSync()
       
   184     {
       
   185     __LOG( "CUpnpRenderingStateMachine::SetOffSync" );
       
   186     __ASSERT( !IsBusy(), __FILE__, __LINE__ );
       
   187     iState = Upnp::EOffSync;
       
   188     }
       
   189 
       
   190 // --------------------------------------------------------------------------
       
   191 // CUpnpRenderingStateMachine::IsInSync
       
   192 // --------------------------------------------------------------------------
       
   193 //
       
   194 EXPORT_C TBool CUpnpRenderingStateMachine::IsInSync() const
       
   195     {
       
   196     return (iState & Upnp::EStateMaskInSync) != 0;
       
   197     }
       
   198 
       
   199 // --------------------------------------------------------------------------
       
   200 // CUpnpRenderingStateMachine::Command
       
   201 // Issues a command to the renderer through the state machine
       
   202 // --------------------------------------------------------------------------
       
   203 //
       
   204 EXPORT_C void CUpnpRenderingStateMachine::CommandL(
       
   205     Upnp::TCommand aCommand,
       
   206     TInt aCommandParameter,
       
   207     const CUpnpItem* aMedia )
       
   208     {
       
   209     __LOG1( "CUpnpRenderingStateMachine::CommandL cmd = %d",aCommand );
       
   210     TUpnpRenderingOperation cmd(
       
   211         aCommand, aCommandParameter, aMedia );
       
   212     PushAndExecuteL( cmd );
       
   213     }
       
   214 
       
   215 // --------------------------------------------------------------------------
       
   216 // CUpnpRenderingStateMachine::IsBusy
       
   217 // --------------------------------------------------------------------------
       
   218 //
       
   219 EXPORT_C TBool CUpnpRenderingStateMachine::IsBusy() const
       
   220     {
       
   221     return !IsFree();
       
   222     }
       
   223 
       
   224 // --------------------------------------------------------------------------
       
   225 // CUpnpRenderingStateMachine::State
       
   226 // --------------------------------------------------------------------------
       
   227 //
       
   228 EXPORT_C Upnp::TState CUpnpRenderingStateMachine::State() const
       
   229     {
       
   230     return iState;
       
   231     }
       
   232 
       
   233 // --------------------------------------------------------------------------
       
   234 // CUpnpRenderingStateMachine::Duration
       
   235 // --------------------------------------------------------------------------
       
   236 //
       
   237 EXPORT_C TInt CUpnpRenderingStateMachine::Duration() const
       
   238     {
       
   239     __LOG( "CUpnpRenderingStateMachine::Duration" );
       
   240     __ASSERT( iState & Upnp::EStateMaskActive,
       
   241         __FILE__, __LINE__ );
       
   242     __ASSERT( iPlaytimeCalculator, __FILE__, __LINE__ );
       
   243     return iPlaytimeCalculator->Duration();
       
   244     }
       
   245 
       
   246 // --------------------------------------------------------------------------
       
   247 // CUpnpRenderingStateMachine::Position
       
   248 // --------------------------------------------------------------------------
       
   249 //
       
   250 EXPORT_C TInt CUpnpRenderingStateMachine::Position() const
       
   251     {
       
   252     __LOG( "CUpnpRenderingStateMachine::Position" );
       
   253     __ASSERT( iState & Upnp::EStateMaskActive,
       
   254         __FILE__, __LINE__ );
       
   255     __ASSERT( iPlaytimeCalculator, __FILE__, __LINE__ );
       
   256     return iPlaytimeCalculator->Position();
       
   257     }
       
   258 
       
   259 // --------------------------------------------------------------------------
       
   260 // CUpnpRenderingStateMachine::HasPauseCapability
       
   261 // --------------------------------------------------------------------------
       
   262 //
       
   263 EXPORT_C TBool CUpnpRenderingStateMachine::HasPauseCapability() const
       
   264     {
       
   265     return iSession.Device().PauseCapability();
       
   266     }
       
   267 
       
   268 // --------------------------------------------------------------------------
       
   269 // CUpnpRenderingStateMachine::InteractOperationComplete
       
   270 // --------------------------------------------------------------------------
       
   271 //
       
   272 EXPORT_C void CUpnpRenderingStateMachine::InteractOperationComplete(
       
   273     TInt aError, TUPnPAVInteractOperation aOperation )
       
   274     {
       
   275     __LOG( "CUpnpRenderingStateMachine::InteractOperationComplete" );
       
   276     Process(
       
   277         CUpnpRenderingStateMachine::EInteractOperationComplete,
       
   278         aError, &aOperation );
       
   279     }
       
   280 
       
   281 // --------------------------------------------------------------------------
       
   282 // CUpnpRenderingStateMachine::PositionInfoResult
       
   283 // --------------------------------------------------------------------------
       
   284 //
       
   285 EXPORT_C void CUpnpRenderingStateMachine::PositionInfoResult( 
       
   286     TInt aError, const TDesC8& aPosition, const TDesC8& aLength )
       
   287     {
       
   288     __LOG( "CUpnpRenderingStateMachine::PositionInfoResult" );
       
   289     Process(
       
   290         CUpnpRenderingStateMachine::EPositionInfo,
       
   291         aError, (TAny*)&aPosition, (TAny*)&aLength );
       
   292     }
       
   293 
       
   294 // --------------------------------------------------------------------------
       
   295 // CUpnpRenderingStateMachine::SetURIResult
       
   296 // --------------------------------------------------------------------------
       
   297 //
       
   298 EXPORT_C void CUpnpRenderingStateMachine::SetURIResult( TInt aError )
       
   299     {
       
   300     __LOG( "CUpnpRenderingStateMachine::SetURIResult" );
       
   301     Process(
       
   302         CUpnpRenderingStateMachine::ESetUriResult,
       
   303         aError );
       
   304     }
       
   305 
       
   306 // --------------------------------------------------------------------------
       
   307 // CUpnpRenderingStateMachine::SetNextURIResult
       
   308 // --------------------------------------------------------------------------
       
   309 //
       
   310 EXPORT_C void CUpnpRenderingStateMachine::SetNextURIResult( TInt /*aError*/ )
       
   311     {
       
   312     __LOG( "CUpnpRenderingStateMachine::SetNextURIResult" );
       
   313     __PANIC( __FILE__, __LINE__ );
       
   314     }
       
   315 
       
   316 // --------------------------------------------------------------------------
       
   317 // CUpnpRenderingStateMachine::ReportSyncReady
       
   318 // --------------------------------------------------------------------------
       
   319 //
       
   320 void CUpnpRenderingStateMachine::ReportSyncReady(
       
   321     TInt aError, Upnp::TState aNewState )
       
   322     {
       
   323     __LOG3( "RenderingStateMachine: SyncReady err=%i %s->%s",
       
   324         aError, StateName( iState ), StateName( aNewState ) );
       
   325     iState = aNewState;
       
   326     if ( iObserver )
       
   327         {
       
   328         iObserver->RendererSyncReady( aError, iState );
       
   329         }
       
   330     }
       
   331 
       
   332 // --------------------------------------------------------------------------
       
   333 // CUpnpRenderingStateMachine::ReportStateChanged
       
   334 // --------------------------------------------------------------------------
       
   335 //
       
   336 void CUpnpRenderingStateMachine::ReportStateChanged(
       
   337     TInt aError, Upnp::TState aNewState,
       
   338     TBool aActionResponse, TInt aStateParam )
       
   339     {
       
   340     __LOG3( "RenderingStateMachine: StateChanged err=%i %s->%s",
       
   341         aError, StateName( iState ), StateName( aNewState ) );
       
   342     iState = aNewState;
       
   343     if ( iObserver )
       
   344         {
       
   345         iObserver->RenderingStateChanged(
       
   346             aError, iState, aActionResponse, aStateParam );
       
   347         }
       
   348     }
       
   349 
       
   350 // --------------------------------------------------------------------------
       
   351 // CUpnpRenderingStateMachine::ReportPositionSync
       
   352 // --------------------------------------------------------------------------
       
   353 //
       
   354 void CUpnpRenderingStateMachine::ReportPositionSync( TInt aError,
       
   355     Upnp::TPositionMode aMode,
       
   356     TInt aDuration, TInt aPosition )
       
   357     {
       
   358     __LOG1( "RenderingStateMachine: PositionSync %i", aError );
       
   359     if ( iObserver )
       
   360         {
       
   361         iObserver->PositionSync( aError, aMode, aDuration, aPosition );
       
   362         }
       
   363     }
       
   364 
       
   365 
       
   366 
       
   367 /*****************************************
       
   368  ** State machine states implementation ** 
       
   369  *****************************************/
       
   370 
       
   371 // --------------------------------------------------------------------------
       
   372 // CUpnpRenderingStateMachine::ExecuteOperationL
       
   373 // --------------------------------------------------------------------------
       
   374 //
       
   375 MUpnpRenderingOperationExecutor::TResult 
       
   376 CUpnpRenderingStateMachine::ExecuteOperationL(
       
   377     const TUpnpRenderingOperation& aOperation,
       
   378     const TUpnpRenderingOperation& aCurrent )
       
   379     {
       
   380     __LOG1( "RenderingStateMachine: ExecuteOperationL (operation=%d)",
       
   381         aOperation.Command() );
       
   382     MUpnpRenderingOperationExecutor::TResult ret(ECompleted);
       
   383     switch( aOperation.Command() )
       
   384         {
       
   385         case Upnp::ESync:
       
   386             {
       
   387             ret = ExecuteOperationSyncL( aOperation, aCurrent );
       
   388             break;
       
   389             }
       
   390         case Upnp::EPlay:
       
   391             {
       
   392             ret = ExecuteOperationPlayL( aOperation, aCurrent );
       
   393             break;
       
   394             }
       
   395         case Upnp::EStop:
       
   396             {
       
   397             ret = ExecuteOperationStopL( aOperation, aCurrent );
       
   398             break;
       
   399             }
       
   400         case Upnp::EPause:
       
   401             {
       
   402             ret = ExecuteOperationPauseL( aOperation, aCurrent );
       
   403             break;
       
   404             }
       
   405         case Upnp::EResume:
       
   406             {
       
   407             ret = ExecuteOperationResumeL( aOperation, aCurrent );
       
   408             break;
       
   409             }
       
   410         case Upnp::ERestart:
       
   411             {
       
   412             ret = ExecuteOperationRestartL( aOperation, aCurrent );
       
   413             break;
       
   414             }
       
   415         case Upnp::ESeek:
       
   416             {
       
   417             ret = ExecuteOperationSeekL( aOperation, aCurrent );
       
   418             break;
       
   419             }
       
   420         case Upnp::ECalibrate:
       
   421             {
       
   422             ret = ExecuteOperationCalibrateL( aOperation, aCurrent );
       
   423             break;
       
   424             }
       
   425         case Upnp::ESetUri:
       
   426             {
       
   427             ret = ExecuteOperationSetUriL( aOperation, aCurrent );
       
   428             break;
       
   429             }
       
   430         default:
       
   431             __PANIC( __FILE__, __LINE__ );
       
   432         }
       
   433     return ret;
       
   434     }
       
   435 
       
   436 // --------------------------------------------------------------------------
       
   437 // CUpnpRenderingStateMachine::ProcessOperationL
       
   438 // --------------------------------------------------------------------------
       
   439 //
       
   440 MUpnpRenderingOperationExecutor::TResult 
       
   441 CUpnpRenderingStateMachine::ProcessOperationL(
       
   442     const TUpnpRenderingOperation& aOperation, TInt aEvent,
       
   443     TInt aError, const TAny* aParam1, const TAny* aParam2 )
       
   444     {
       
   445     __LOG2( "RenderingStateMachine: ProcessOperationL (event=%d) (aError=%d)",
       
   446             aEvent, aError );
       
   447     
       
   448     MUpnpRenderingOperationExecutor::TResult ret(ECompleted);
       
   449     switch( aEvent )
       
   450         {
       
   451         case EInteractOperationComplete:
       
   452             {
       
   453             TUPnPAVInteractOperation op =
       
   454                 *(TUPnPAVInteractOperation*)aParam1;
       
   455             if ( op == EUPnPAVPlay 
       
   456               || op == EUPnPAVPlayUser 
       
   457               || op == EUPnPAVStop 
       
   458               || op == EUPnPAVStopUser 
       
   459               || op == EUPnPAVPause 
       
   460               || op == EUPnPAVPauseUser
       
   461               || op == EUPnPAVSeek )
       
   462                 {
       
   463                 ret = ProcessAVEvents( aOperation, op, aError );
       
   464                 }
       
   465             else if ( op == EUPnPAVTransition )
       
   466                 {
       
   467                 ret = EContinue;
       
   468                 __LOG1( "RenderingStateMachine: Transition %d", aError );
       
   469                 }
       
   470             else
       
   471                 {
       
   472                 __PANIC( __FILE__, __LINE__ );
       
   473                 }
       
   474             break;
       
   475             }
       
   476         case EPositionInfo: 
       
   477             {
       
   478             const TDesC8& pos = *(const TDesC8*)aParam1;
       
   479             const TDesC8& len = *(const TDesC8*)aParam2;
       
   480             ret = ProcessPositionInfo( aOperation, aError, pos, len );
       
   481             break;
       
   482             }
       
   483         case ESetUriResult:
       
   484             {
       
   485             ret = ProcessSetURIResultL( aOperation, aError );
       
   486             break;
       
   487             }
       
   488         default:
       
   489             {
       
   490             __PANIC( __FILE__, __LINE__ );
       
   491             }
       
   492         }
       
   493     return ret;
       
   494     }
       
   495 
       
   496 // --------------------------------------------------------------------------
       
   497 // CUpnpRenderingStateMachine::HandleAsyncError
       
   498 // cancels the ongoing operation
       
   499 // --------------------------------------------------------------------------
       
   500 //
       
   501 void CUpnpRenderingStateMachine::HandleAsyncError(
       
   502     const TUpnpRenderingOperation& aOperation, TInt aError )
       
   503     {
       
   504     __LOG( "RenderingStateMachine: HandleAsyncError" );
       
   505     switch ( aOperation.Command() )
       
   506         {
       
   507         case Upnp::ESync:
       
   508             {
       
   509             ReportSyncReady( aError, State() );
       
   510             break;
       
   511             }
       
   512         case Upnp::EPlay:
       
   513             {
       
   514             if ( aOperation.IsUserOriented() )
       
   515                 {
       
   516                 ReportStateChanged( aError, 
       
   517                     Upnp::EStopped, ETrue );
       
   518                 }
       
   519             break;
       
   520             }
       
   521         case Upnp::EStop:
       
   522             {
       
   523             if ( aOperation.IsUserOriented() )
       
   524                 {
       
   525                 ReportStateChanged( aError, State(), ETrue );
       
   526                 }
       
   527             break;
       
   528             }
       
   529         case Upnp::EPause:
       
   530             {
       
   531             if ( aOperation.IsUserOriented() )
       
   532                 {
       
   533                 ReportStateChanged( aError, State(), ETrue );
       
   534                 }
       
   535             break;
       
   536             }
       
   537         case Upnp::ECalibrate:
       
   538             {
       
   539             // do nothing
       
   540             break;
       
   541             }
       
   542         case Upnp::ESeek:
       
   543             {
       
   544             TInt seekCode = Upnp::EPositionChanged;
       
   545             ReportStateChanged( aError,
       
   546                     State(), ETrue, seekCode );
       
   547             break;
       
   548             }
       
   549         default:
       
   550            // __PANICD( __FILE__, __LINE__ );
       
   551             break;
       
   552         }
       
   553     }
       
   554 
       
   555 // --------------------------------------------------------------------------
       
   556 // CUpnpRenderingStateMachine::ExecuteOperationSyncL
       
   557 // --------------------------------------------------------------------------
       
   558 //
       
   559 MUpnpRenderingOperationExecutor::TResult 
       
   560 CUpnpRenderingStateMachine::ExecuteOperationSyncL(
       
   561     const TUpnpRenderingOperation& /*aOperation*/,
       
   562     const TUpnpRenderingOperation& /*aCurrent*/ )
       
   563     {
       
   564     __LOG( "RenderingStateMachine: ExecuteOperationSyncL" );
       
   565     // GetRendererState() method to be implemented in AVController
       
   566     // 1. if renderer has already sent its first state event, it will be
       
   567     // returned immediately. 
       
   568     // 2. if not (SUBSCRIBE just sent) there will be a small wait loop to
       
   569     // wait for the initial event
       
   570     // 3. if the initial even does not arrive
       
   571     //    3.1 Request the state from the renderer (optional)
       
   572     //    3.2 Assume it is in stopped state. (maybe enough)
       
   573     
       
   574     TUPnPAVInteractOperation op = iSession.GetRendererStateL();
       
   575     __LOG1( "RenderingStateMachine: ExecuteOperationSyncL \
       
   576 current op = %d" ,op );
       
   577     Upnp::TState state = Upnp::EPlaying;
       
   578     if( op == EUPnPAVStopUser )
       
   579         {
       
   580         state = Upnp::EStopped;
       
   581         }
       
   582     ReportSyncReady( KErrNone , state );
       
   583     return ECompleted;
       
   584     }
       
   585 
       
   586 // --------------------------------------------------------------------------
       
   587 // CUpnpRenderingStateMachine::ExecuteOperationPlayL
       
   588 // --------------------------------------------------------------------------
       
   589 //
       
   590 MUpnpRenderingOperationExecutor::TResult 
       
   591 CUpnpRenderingStateMachine::ExecuteOperationPlayL(
       
   592     const TUpnpRenderingOperation& aOperation,
       
   593     const TUpnpRenderingOperation& aCurrent )
       
   594     {
       
   595     __LOG( "RenderingStateMachine: ExecuteOperationPlayL" );
       
   596     MUpnpRenderingOperationExecutor::TResult ret(ECompleted);
       
   597     if ( aCurrent == Upnp::EPlay )
       
   598         {
       
   599         __LOG( "RenderingStateMachine: ExecuteOperationPlayL \
       
   600 aCurrent == Upnp::EPlay " );
       
   601         // Play request repeats. Compare content.
       
   602         const CUpnpItem* item = static_cast<const CUpnpItem*>(
       
   603             aOperation.Data() );
       
   604         if ( ResourceFromL( *item ).Value() != iCurrentUri )
       
   605             {
       
   606             ret = EQueue;
       
   607             }
       
   608         }
       
   609     else if ( aCurrent != Upnp::ENone )
       
   610         {
       
   611         __LOG( "RenderingStateMachine: ExecuteOperationPlayL \
       
   612 aCurrent == Upnp::ENone " );
       
   613         ret = EQueue;
       
   614         }
       
   615     else
       
   616         {
       
   617         switch( State() )
       
   618             {
       
   619             case Upnp::EPaused:
       
   620                 {
       
   621                 __LOG( "RenderingStateMachine: ExecuteOperationPlayL \
       
   622 aCurrent == Upnp::EPaused " );
       
   623                 
       
   624                 const CUpnpItem* item =
       
   625                     static_cast<const CUpnpItem*>( aOperation.Data() );
       
   626                 if ( item && ResourceFromL( *item ).Value() != iCurrentUri )
       
   627                     {
       
   628                     // track changed during pause -> stop paused and start 
       
   629                     // playing the new
       
   630                     TUpnpRenderingOperation stop( Upnp::EStop );
       
   631                     stop.SetUserOriented( EFalse );
       
   632                     PushL( stop );
       
   633                     TUpnpRenderingOperation play( aOperation );
       
   634                     PushL( play );
       
   635                     }
       
   636                 else
       
   637                     {
       
   638                     iSession.PlayL();
       
   639                     ret = EContinue;
       
   640                     }
       
   641                 break;
       
   642                 }
       
   643             case Upnp::EPlaying:
       
   644             case Upnp::EStopped:
       
   645                 {
       
   646                 __LOG( "RenderingStateMachine: ExecuteOperationPlayL aCurrent == Upnp::EStopped " );
       
   647 
       
   648                 // start play sequence
       
   649                 const CUpnpItem* item = static_cast<const CUpnpItem*>(
       
   650                     aOperation.Data() );
       
   651                 
       
   652                 __LOG1( "RenderingStateMachine: ExecuteOperationPlayL item 0x%x ", item );
       
   653                 
       
   654                 if ( item )
       
   655                     {
       
   656                     // improvements !!!
       
   657                     // check if user requests playing the same track that was
       
   658                     // previously playing. In that case we just call Play().
       
   659                     // Much faster.
       
   660                     const TDesC8& httpuri = ResourceFromL( *item ).Value();
       
   661                     
       
   662                     __LOG( "RenderingStateMachine: ExecuteOperationPlayL current:" );
       
   663                     __LOG8( iCurrentUri );
       
   664                     __LOG( "RenderingStateMachine: ExecuteOperationPlayL new:" );
       
   665                     __LOG8( httpuri );
       
   666                     if( iCurrentUri == httpuri )
       
   667                         {
       
   668                         iSession.PlayL();
       
   669                         }
       
   670                     else
       
   671                         {
       
   672                         SetUriL( aOperation );
       
   673                         }
       
   674                     }
       
   675                 else
       
   676                     {
       
   677                     // uri not available
       
   678                     User::Leave( KErrArgument );
       
   679                     }
       
   680                 ret = EContinue;
       
   681                 break;
       
   682                 }
       
   683             case Upnp::EOffSync:  
       
   684             case Upnp::EBusy: 
       
   685             case Upnp::EDead:
       
   686             case Upnp::EBuffering:
       
   687             case Upnp::EStateMaskInSync:
       
   688             case Upnp::EStateMaskActive:
       
   689             case Upnp::EStateMaskRendering: 
       
   690             default:
       
   691                 {
       
   692                 User::Leave( KErrNotReady );
       
   693                 }
       
   694             }
       
   695         }
       
   696     return ret;
       
   697     }
       
   698 
       
   699 // --------------------------------------------------------------------------
       
   700 // CUpnpRenderingStateMachine::ExecuteOperationSetUriL
       
   701 // --------------------------------------------------------------------------
       
   702 //
       
   703 MUpnpRenderingOperationExecutor::TResult 
       
   704 CUpnpRenderingStateMachine::ExecuteOperationSetUriL(
       
   705     const TUpnpRenderingOperation& aOperation,
       
   706     const TUpnpRenderingOperation& /*aCurrent*/ )
       
   707     {
       
   708     __LOG( "RenderingStateMachine: ExecuteOperationSetUriL" );
       
   709 
       
   710     iStateBeforeSetUri = State(); 
       
   711     SetUriL( aOperation );
       
   712 
       
   713     return EContinue;
       
   714     }
       
   715     
       
   716 // --------------------------------------------------------------------------
       
   717 // CUpnpRenderingStateMachine::SetUriL
       
   718 // --------------------------------------------------------------------------
       
   719 //
       
   720 void CUpnpRenderingStateMachine::SetUriL( 
       
   721     const TUpnpRenderingOperation& aOperation )
       
   722     {
       
   723     __LOG( "RenderingStateMachine: ExecuteOperationSetUriL" );
       
   724     
       
   725     const CUpnpItem* item = static_cast<const CUpnpItem*>(
       
   726         aOperation.Data() );
       
   727     
       
   728     __LOG1( "RenderingStateMachine: SetUriL item 0x%x ", item );
       
   729     
       
   730     if ( item )
       
   731         {
       
   732         const TDesC8& httpuri = ResourceFromL( *item ).Value();
       
   733         
       
   734         __LOG( "RenderingStateMachine: SetUriL current:" );
       
   735         __LOG8( iCurrentUri );
       
   736         __LOG( "RenderingStateMachine: SetUriL new:" );
       
   737         __LOG8( httpuri );
       
   738 
       
   739         __LOG( "RenderingStateMachine: SetUriL iSession.SetURIL" );
       
   740             
       
   741         iSession.SetURIL( httpuri, *item );
       
   742         iCurrentUri.Copy( httpuri );
       
   743         ReportStateChanged( KErrNone, Upnp::EBuffering );
       
   744         }
       
   745     }
       
   746 
       
   747 // --------------------------------------------------------------------------
       
   748 // CUpnpRenderingStateMachine::ExecuteOperationStopL
       
   749 // --------------------------------------------------------------------------
       
   750 //
       
   751 MUpnpRenderingOperationExecutor::TResult 
       
   752 CUpnpRenderingStateMachine::ExecuteOperationStopL(
       
   753     const TUpnpRenderingOperation& /*aOperation*/,
       
   754     const TUpnpRenderingOperation& aCurrent )
       
   755     {
       
   756     __LOG( "RenderingStateMachine: ExecuteOperationStopL" );
       
   757     MUpnpRenderingOperationExecutor::TResult ret(ECompleted);
       
   758     if ( aCurrent == Upnp::EStop )
       
   759         {
       
   760         // already stopping, no need to stop twice
       
   761         }
       
   762     else if ( aCurrent != Upnp::ENone )
       
   763         {
       
   764         ret = EQueue;
       
   765         }
       
   766     else
       
   767         {
       
   768         switch( State() )
       
   769             {
       
   770             case Upnp::EPlaying:
       
   771             case Upnp::EPaused:
       
   772                 {
       
   773                 iSession.StopL();
       
   774                 ret = EContinue;
       
   775                 break;
       
   776                 }
       
   777             case Upnp::EStopped:
       
   778                 {
       
   779                 ReportStateChanged( KErrNone, State() );
       
   780                 break;
       
   781                 }
       
   782             case Upnp::EOffSync:  
       
   783             case Upnp::EBusy: 
       
   784             case Upnp::EDead:
       
   785             case Upnp::EBuffering:
       
   786             case Upnp::EStateMaskInSync:
       
   787             case Upnp::EStateMaskActive:
       
   788             case Upnp::EStateMaskRendering: 
       
   789             default:
       
   790                 {
       
   791                 User::Leave( KErrNotReady );
       
   792                 }
       
   793             }
       
   794         }
       
   795     return ret;
       
   796     }
       
   797 
       
   798 // --------------------------------------------------------------------------
       
   799 // CUpnpRenderingStateMachine::ExecuteOperationPauseL
       
   800 // --------------------------------------------------------------------------
       
   801 //
       
   802 MUpnpRenderingOperationExecutor::TResult 
       
   803 CUpnpRenderingStateMachine::ExecuteOperationPauseL(
       
   804     const TUpnpRenderingOperation& /*aOperation*/,
       
   805     const TUpnpRenderingOperation& aCurrent )
       
   806     {
       
   807     __LOG( "RenderingStateMachine: ExecuteOperationPauseL" );
       
   808     MUpnpRenderingOperationExecutor::TResult ret(ECompleted);
       
   809     if ( aCurrent == Upnp::EPause )
       
   810         {
       
   811         // pause during pause request
       
   812         }
       
   813     else if ( aCurrent != Upnp::ENone )
       
   814         {
       
   815         ret = EQueue;
       
   816         }
       
   817     else
       
   818          {
       
   819          switch( State() )
       
   820              {
       
   821              case Upnp::EPlaying:
       
   822                  {
       
   823                  iSession.PauseL();
       
   824                  ret = EContinue;
       
   825                  break;
       
   826                  }
       
   827              case Upnp::EPaused:
       
   828                  {
       
   829                  ReportStateChanged( KErrNone, State() );
       
   830                  ret = ECompleted;
       
   831                  break;
       
   832                  }
       
   833              case Upnp::EOffSync:  
       
   834              case Upnp::EBusy: 
       
   835              case Upnp::EDead:
       
   836              case Upnp::EStopped:
       
   837              case Upnp::EBuffering:
       
   838              case Upnp::EStateMaskInSync:
       
   839              case Upnp::EStateMaskActive:
       
   840              case Upnp::EStateMaskRendering: 
       
   841              default:
       
   842                  {
       
   843                  User::Leave( KErrNotReady );
       
   844                  }
       
   845              }
       
   846          }
       
   847     return ret;
       
   848     }
       
   849 
       
   850 // --------------------------------------------------------------------------
       
   851 // CUpnpRenderingStateMachine::ExecuteOperationResumeL
       
   852 // --------------------------------------------------------------------------
       
   853 //
       
   854 MUpnpRenderingOperationExecutor::TResult 
       
   855 CUpnpRenderingStateMachine::ExecuteOperationResumeL(
       
   856     const TUpnpRenderingOperation& /*aOperation*/,
       
   857     const TUpnpRenderingOperation& aCurrent )
       
   858     {
       
   859     __LOG( "RenderingStateMachine: ExecuteOperationResumeL" );
       
   860     MUpnpRenderingOperationExecutor::TResult ret(ECompleted);
       
   861     if ( aCurrent == Upnp::EPlay )
       
   862         {
       
   863         // resume during play
       
   864         }
       
   865     else if ( aCurrent != Upnp::ENone )
       
   866         {
       
   867         ret = EQueue;
       
   868         }
       
   869     else
       
   870         {
       
   871         switch( State() )
       
   872             {
       
   873             case Upnp::EPlaying:
       
   874                 {
       
   875                 ReportStateChanged( KErrNone, State() );
       
   876                 break;
       
   877                 }
       
   878             case Upnp::EPaused:
       
   879                 {
       
   880                 iSession.PlayL();
       
   881                 ret = EContinue;
       
   882                 break;
       
   883                 }
       
   884             case Upnp::EOffSync:  
       
   885             case Upnp::EBusy: 
       
   886             case Upnp::EDead:
       
   887             case Upnp::EStopped:
       
   888             case Upnp::EBuffering:
       
   889             case Upnp::EStateMaskInSync:
       
   890             case Upnp::EStateMaskActive:
       
   891             case Upnp::EStateMaskRendering: 
       
   892             default:
       
   893                 {
       
   894                 User::Leave( KErrNotReady );
       
   895                 }
       
   896             }
       
   897 
       
   898         }
       
   899     return ret;
       
   900     }
       
   901 
       
   902 // --------------------------------------------------------------------------
       
   903 // CUpnpRenderingStateMachine::ExecuteOperationRestartL
       
   904 // --------------------------------------------------------------------------
       
   905 //
       
   906 MUpnpRenderingOperationExecutor::TResult 
       
   907 CUpnpRenderingStateMachine::ExecuteOperationRestartL(
       
   908     const TUpnpRenderingOperation& /*aOperation*/,
       
   909     const TUpnpRenderingOperation& aCurrent )
       
   910     {
       
   911     __LOG( "RenderingStateMachine: ExecuteOperationRestartL" );
       
   912     // handle parallel
       
   913     MUpnpRenderingOperationExecutor::TResult ret(ECompleted);
       
   914     if ( aCurrent != Upnp::ENone )
       
   915         {
       
   916         ret = EQueue;
       
   917         }
       
   918     else
       
   919         {
       
   920         switch( State() )
       
   921             {
       
   922             case Upnp::EPlaying:
       
   923                 {
       
   924                 TUpnpRenderingOperation stop(
       
   925                     Upnp::EStop );
       
   926                 stop.SetUserOriented( EFalse );
       
   927                 PushL( stop );
       
   928                 TUpnpRenderingOperation play(
       
   929                     Upnp::EPlay );
       
   930                 PushL( play );
       
   931                 break;
       
   932                 }
       
   933             case Upnp::EPaused:
       
   934                 {
       
   935                 TUpnpRenderingOperation stop(
       
   936                      Upnp::EStop );
       
   937                  PushL( stop );
       
   938                 break;
       
   939                 }
       
   940             case Upnp::EOffSync:  
       
   941             case Upnp::EBusy: 
       
   942             case Upnp::EDead:
       
   943             case Upnp::EStopped:
       
   944             case Upnp::EBuffering:
       
   945             case Upnp::EStateMaskInSync:
       
   946             case Upnp::EStateMaskActive:
       
   947             case Upnp::EStateMaskRendering: 
       
   948             default:
       
   949                 {
       
   950                 User::Leave( KErrNotReady );
       
   951                 }
       
   952             }
       
   953 
       
   954         }
       
   955     return ret;
       
   956     }
       
   957 
       
   958 // --------------------------------------------------------------------------
       
   959 // CUpnpRenderingStateMachine::ExecuteOperationSeekL
       
   960 // --------------------------------------------------------------------------
       
   961 //
       
   962 MUpnpRenderingOperationExecutor::TResult 
       
   963 CUpnpRenderingStateMachine::ExecuteOperationSeekL(
       
   964     const TUpnpRenderingOperation& aOperation,
       
   965     const TUpnpRenderingOperation& aCurrent )
       
   966     {
       
   967     __LOG( "RenderingStateMachine: ExecuteOperationSeekL" );
       
   968     MUpnpRenderingOperationExecutor::TResult ret(ECompleted);
       
   969     
       
   970     TInt currentPosition = iPlaytimeCalculator->Position();
       
   971     TInt seekPosition = aOperation.Param();
       
   972     __LOG3( "RenderingStateMachine: state 0x%x, currentPosition %d, seekPosition %d",
       
   973             State(), currentPosition, seekPosition );
       
   974     if( seekPosition < currentPosition + KSeekThresholdTime &&
       
   975         seekPosition > currentPosition - KSeekThresholdTime )
       
   976         {
       
   977         // ignore seek
       
   978         }
       
   979     else if ( aCurrent != Upnp::ENone )
       
   980         {
       
   981         ret = EQueue;
       
   982         }
       
   983     else if ( State() == Upnp::EStopped ||
       
   984               State() == Upnp::EPlaying )
       
   985         {
       
   986         iSeekPostion = seekPosition;
       
   987         TTime seekTime = (TInt64)iSeekPostion * KMicrosecondsInMillisecond;
       
   988         iSession.SeekRelTimeL( seekTime );
       
   989         ret = EContinue;
       
   990         }
       
   991     else if( State() == Upnp::EPaused )
       
   992         {
       
   993         TInt lastIndex( iQueue.Count() - 1 );   
       
   994         TBool found(EFalse);
       
   995         for( TInt i(lastIndex); i > 0; i-- )
       
   996             {
       
   997             if( iQueue[i].Command() == Upnp::EPause )
       
   998                 {
       
   999                 break;
       
  1000                 }
       
  1001             else if( iQueue[i].Command() == Upnp::EPlay || 
       
  1002                      iQueue[i].Command() == Upnp::EResume )
       
  1003                 {
       
  1004                 __LOG( "RenderingStateMachine: ExecuteOperationSeekL \
       
  1005                 play or resume found adding seek to queue" );
       
  1006                 TUpnpRenderingOperation seek( aOperation );
       
  1007                 PushL( seek );
       
  1008                 found = ETrue;
       
  1009                 break;
       
  1010                 }
       
  1011             }
       
  1012         /**
       
  1013          * if play or resume was not found it is 
       
  1014          * illigal to execute seek in renderer 
       
  1015          */
       
  1016         if ( !found )
       
  1017             {
       
  1018             User::Leave( KErrNotReady );
       
  1019             }
       
  1020         }
       
  1021     else
       
  1022         {
       
  1023         User::Leave( KErrNotReady );
       
  1024         }    
       
  1025     return ret;
       
  1026     }
       
  1027 
       
  1028 // --------------------------------------------------------------------------
       
  1029 // CUpnpRenderingStateMachine::ExecuteOperationCalibrateL
       
  1030 // --------------------------------------------------------------------------
       
  1031 //
       
  1032 MUpnpRenderingOperationExecutor::TResult 
       
  1033 CUpnpRenderingStateMachine::ExecuteOperationCalibrateL(
       
  1034     const TUpnpRenderingOperation& /*aOperation*/,
       
  1035     const TUpnpRenderingOperation& aCurrent )
       
  1036     {
       
  1037     __LOG( "RenderingStateMachine: ExecuteOperationCalibrateL" );
       
  1038     MUpnpRenderingOperationExecutor::TResult ret(ECompleted);
       
  1039     if ( aCurrent != Upnp::ENone )
       
  1040         {
       
  1041         ret = EQueue;
       
  1042         }
       
  1043     else if ( State() == Upnp::EPlaying ||
       
  1044         State() == Upnp::EPaused )
       
  1045         {
       
  1046         iGetPositionStartMark.UniversalTime();
       
  1047         iSession.GetPositionInfoL();
       
  1048         ret = EContinue;
       
  1049         }
       
  1050     else
       
  1051         {
       
  1052         User::Leave( KErrNotReady );
       
  1053         }
       
  1054     return ret;
       
  1055     }
       
  1056 
       
  1057 // --------------------------------------------------------------------------
       
  1058 // CUpnpRenderingStateMachine::ProcessEvents
       
  1059 // --------------------------------------------------------------------------
       
  1060 //
       
  1061 MUpnpRenderingOperationExecutor::TResult
       
  1062 CUpnpRenderingStateMachine::ProcessAVEvents( 
       
  1063                                    const TUpnpRenderingOperation& aOperation, 
       
  1064                                     const TUPnPAVInteractOperation aIntOp,
       
  1065                                     TInt aError )
       
  1066     {
       
  1067     MUpnpRenderingOperationExecutor::TResult ret(ECompleted);
       
  1068     if( !aError )
       
  1069         {
       
  1070         switch( aIntOp )
       
  1071             {
       
  1072             case EUPnPAVPlay:
       
  1073                 {
       
  1074                 if ( State() == Upnp::EPaused )
       
  1075                     {
       
  1076                     iPlaytimeCalculator->Resume();
       
  1077                     }                
       
  1078                 else if ( !iPlaytimeCalculator->IsPlaying() )
       
  1079                     {
       
  1080                     iPlaytimeCalculator->Start();
       
  1081                     }
       
  1082                 ReportStateChanged( aError,
       
  1083                     Upnp::EPlaying );
       
  1084                 break;
       
  1085                 }
       
  1086             case EUPnPAVPlayUser:
       
  1087                 {
       
  1088                 // spontaneous state change to playing
       
  1089                 if ( State() == Upnp::EStopped )
       
  1090                     {
       
  1091                     iPlaytimeCalculator->Start();
       
  1092                     }
       
  1093                 else if ( State() == Upnp::EPaused )
       
  1094                     {
       
  1095                     iPlaytimeCalculator->Resume();
       
  1096                     }
       
  1097                 ReportStateChanged( aError,
       
  1098                     Upnp::EPlaying, EFalse );
       
  1099                 ret = EContinue;
       
  1100                 break;
       
  1101                 }
       
  1102             case EUPnPAVStop:
       
  1103                 {
       
  1104                 iPlaytimeCalculator->Stop();
       
  1105                 ReportStateChanged( aError,
       
  1106                     Upnp::EStopped , ETrue );
       
  1107                 break;
       
  1108                 }
       
  1109             case EUPnPAVStopUser:
       
  1110                 {
       
  1111                 // spontaneous state change to stopped
       
  1112                 iPlaytimeCalculator->Stop();
       
  1113                 TInt stopcode = Upnp::ENoMedia;
       
  1114                 if( iPlaytimeCalculator->Duration() != KErrNotFound )
       
  1115                     {
       
  1116                     stopcode = ( iPlaytimeCalculator->IsTrackComplete() ?
       
  1117                         Upnp::ETrackCompleted : 
       
  1118                         Upnp::EStopRequested );
       
  1119                     }
       
  1120                 ReportStateChanged( aError,
       
  1121                     Upnp::EStopped, EFalse, stopcode );
       
  1122                 ret = EContinue;
       
  1123                 break;
       
  1124                 }
       
  1125             case EUPnPAVPause:
       
  1126                 {
       
  1127                 iPlaytimeCalculator->Pause();
       
  1128                 ReportStateChanged( aError,
       
  1129                     Upnp::EPaused );
       
  1130                 break;
       
  1131                 }
       
  1132             case EUPnPAVPauseUser:
       
  1133                 {
       
  1134                 // spontaneous state change to paused
       
  1135                 iPlaytimeCalculator->Pause();
       
  1136                 ReportStateChanged( aError,
       
  1137                     Upnp::EPaused, EFalse );
       
  1138                 ret = EContinue;
       
  1139                 break;
       
  1140                 }
       
  1141             case EUPnPAVSeek:
       
  1142                 {
       
  1143                 iPlaytimeCalculator->RestartAt( iSeekPostion );
       
  1144                 TInt seekCode = Upnp::EPositionChanged;
       
  1145                 ReportStateChanged( aError,
       
  1146                     State(), ETrue, seekCode );
       
  1147                 break;
       
  1148                 }
       
  1149             default:
       
  1150                 {
       
  1151                 __LOG2( "RenderingStateMachine: aIntOp = %d event during %s",
       
  1152                         aIntOp , CommandName(aOperation.Command()) );
       
  1153                 break;
       
  1154                 }
       
  1155             }
       
  1156         }
       
  1157     else
       
  1158         {
       
  1159         ReportStateChanged( aError,
       
  1160                             State() );
       
  1161         }
       
  1162     return ret;
       
  1163     }
       
  1164 
       
  1165 // --------------------------------------------------------------------------
       
  1166 // CUpnpRenderingStateMachine::ProcessPositionInfo
       
  1167 // --------------------------------------------------------------------------
       
  1168 //
       
  1169 MUpnpRenderingOperationExecutor::TResult
       
  1170 CUpnpRenderingStateMachine::ProcessPositionInfo( 
       
  1171     const TUpnpRenderingOperation& aOperation,
       
  1172     TInt aError, const TDesC8& aPosition, const TDesC8& aLength )
       
  1173     {
       
  1174     __LOG( "RenderingStateMachine: ProcessPositionInfo" );
       
  1175     __ASSERT( aOperation == Upnp::ECalibrate,
       
  1176         __FILE__, __LINE__ );
       
  1177 
       
  1178     TInt duration = 0;
       
  1179     TInt position = 0;
       
  1180     if ( aError == KErrNone )
       
  1181         {
       
  1182         aError = UPnPItemUtility::UPnPDurationAsMilliseconds(
       
  1183             aLength, duration );
       
  1184         }
       
  1185     if ( aError == KErrNone )
       
  1186         {
       
  1187         aError = UPnPItemUtility::UPnPDurationAsMilliseconds(
       
  1188             aPosition, position );
       
  1189         }
       
  1190      if ( aError == KErrNone )
       
  1191         {
       
  1192         //Incorporate the delay in receiving the response.
       
  1193         TTime posStopMark; posStopMark.UniversalTime();
       
  1194         TTimeIntervalMicroSeconds delay = 
       
  1195                  posStopMark.MicroSecondsFrom( iGetPositionStartMark );
       
  1196         TInt delayInMSec = ( delay.Int64() / KMicrosecondsInMillisecond );
       
  1197         position += (delayInMSec/2); 
       
  1198         if ( position > duration )
       
  1199             {
       
  1200             position = duration;
       
  1201             }
       
  1202         __LOG2( "RenderingStateMachine: ProcessPositionInfo added delay(%d) \
       
  1203 position(%d)", delayInMSec/2, position);
       
  1204         iPlaytimeCalculator->AcknowledgePositionInfo(
       
  1205             duration, position );
       
  1206         }
       
  1207     // response
       
  1208     // trick states
       
  1209     ReportPositionSync( aError,
       
  1210         Upnp::EPlayingNormally,
       
  1211         iPlaytimeCalculator->Duration(),
       
  1212         iPlaytimeCalculator->Position() );
       
  1213     return ECompleted;
       
  1214     }
       
  1215 
       
  1216 // --------------------------------------------------------------------------
       
  1217 // CUpnpRenderingStateMachine::ProcessSetURIResultL
       
  1218 // --------------------------------------------------------------------------
       
  1219 //
       
  1220 MUpnpRenderingOperationExecutor::TResult
       
  1221 CUpnpRenderingStateMachine::ProcessSetURIResultL(
       
  1222     const TUpnpRenderingOperation& aOperation,
       
  1223     TInt aError )
       
  1224     {
       
  1225     __LOG( "RenderingStateMachine: ProcessSetURIResultL" );
       
  1226     TBool validOp( aOperation == Upnp::EPlay || aOperation == Upnp::ESetUri );
       
  1227     __ASSERT( validOp, __FILE__, __LINE__ );
       
  1228     MUpnpRenderingOperationExecutor::TResult ret(ECompleted);
       
  1229     if ( aError == KErrNone )
       
  1230         {
       
  1231         // get duration from item and write to playtime calculator
       
  1232         const CUpnpItem* item = static_cast<const CUpnpItem*>(
       
  1233             aOperation.Data() );
       
  1234         const CUpnpAttribute* attr =
       
  1235             UPnPItemUtility::FindAttributeByName(
       
  1236                 ResourceFromL( *item ), KAttributeDuration );
       
  1237         if ( attr )
       
  1238             {
       
  1239             TInt ms = 0;
       
  1240             if ( UPnPItemUtility::UPnPDurationAsMilliseconds(
       
  1241                 attr->Value(), ms ) == KErrNone )
       
  1242                 {
       
  1243                 iPlaytimeCalculator->SetDuration( ms );
       
  1244                 }
       
  1245             }
       
  1246         if( aOperation.Command() == Upnp::EPlay )
       
  1247             {
       
  1248             iSession.PlayL();
       
  1249             ret = EContinue;
       
  1250             }
       
  1251         else
       
  1252             {
       
  1253             ReportStateChanged( KErrNone, Upnp::EBuffering, EFalse, ETrue );
       
  1254             iState = iStateBeforeSetUri;
       
  1255             ret = ECompleted;
       
  1256             }
       
  1257         }
       
  1258     //if seturi failed send first stop in that case!
       
  1259     else if( aError == KErrAccessDenied || aError == KErrLocked )
       
  1260         {
       
  1261         iCurrentUri.Zero();
       
  1262         iQueue.Remove( 0 ); // removes play from queue
       
  1263         TUpnpRenderingOperation stop( Upnp::EStop );
       
  1264         stop.SetUserOriented( EFalse );
       
  1265         PushL( stop ); // add stop
       
  1266         iSession.StopL();
       
  1267         ret = EContinue; // continue = waits for operation to complete
       
  1268         TUpnpRenderingOperation play( aOperation );
       
  1269         PushL( play );
       
  1270         }
       
  1271     else
       
  1272         {
       
  1273         HandleAsyncError( aOperation, aError );
       
  1274         }
       
  1275     return ret;
       
  1276     }
       
  1277 
       
  1278 // --------------------------------------------------------------------------
       
  1279 // CUpnpRenderingStateMachine::ResourceFrom
       
  1280 // --------------------------------------------------------------------------
       
  1281 //
       
  1282 const CUpnpElement& CUpnpRenderingStateMachine::ResourceFromL(
       
  1283     const CUpnpItem& aItem )
       
  1284     {
       
  1285     const CUpnpElement* element( NULL );
       
  1286     if ( iSelector )
       
  1287         {
       
  1288         element = &iSelector->SelectResourceL( aItem );
       
  1289         }
       
  1290     else
       
  1291         {
       
  1292         element = &iDefaultSelector.SelectResourceL( aItem );
       
  1293         }
       
  1294     return *element;
       
  1295     }
       
  1296 
       
  1297 
       
  1298 /**************************
       
  1299  ** Queue implementation ** 
       
  1300  **************************/
       
  1301 
       
  1302 // --------------------------------------------------------------------------
       
  1303 // CUpnpRenderingStateMachine::Size
       
  1304 // --------------------------------------------------------------------------
       
  1305 // 
       
  1306 TInt CUpnpRenderingStateMachine::Size() const
       
  1307     {
       
  1308     __LOG1( "CUpnpRenderingStateMachine::Size(%d)", iQueue.Count() );
       
  1309     return iQueue.Count();
       
  1310     }
       
  1311 
       
  1312 // --------------------------------------------------------------------------
       
  1313 // CUpnpRenderingStateMachine::IsFree
       
  1314 // Checks if the queue is free for new operations
       
  1315 // --------------------------------------------------------------------------
       
  1316 // 
       
  1317 TBool CUpnpRenderingStateMachine::IsFree() const
       
  1318     {
       
  1319     return Size() == 0;
       
  1320     }
       
  1321 
       
  1322 // --------------------------------------------------------------------------
       
  1323 // CUpnpRenderingStateMachine::PushL
       
  1324 // push operation to queue. Don't try to execute it yet.
       
  1325 // --------------------------------------------------------------------------
       
  1326 // 
       
  1327 void CUpnpRenderingStateMachine::PushL(
       
  1328     const TUpnpRenderingOperation& aOperation )
       
  1329     {
       
  1330     __LOG( "CUpnpRenderingStateMachine::PushL" );
       
  1331     iQueue.AppendL( aOperation );
       
  1332     CompressQueueL();
       
  1333     }
       
  1334 
       
  1335 // --------------------------------------------------------------------------
       
  1336 // CUpnpRenderingStateMachine::PushAndExecuteL
       
  1337 // push operation to queue and execute it immediately
       
  1338 // --------------------------------------------------------------------------
       
  1339 // 
       
  1340 void CUpnpRenderingStateMachine::PushAndExecuteL(
       
  1341     const TUpnpRenderingOperation& aOperation )
       
  1342     {
       
  1343     __LOG( "CUpnpRenderingStateMachine::PushAndExecuteL" );
       
  1344     if ( IsFree() )
       
  1345         {
       
  1346         PushL( aOperation );
       
  1347         ExecuteRecursivelyL();
       
  1348         }
       
  1349     else
       
  1350         {
       
  1351         ExecuteParallelL( aOperation );
       
  1352         }
       
  1353     }
       
  1354 
       
  1355 // --------------------------------------------------------------------------
       
  1356 // CUpnpRenderingAlgorithms::Execute
       
  1357 // Runs an operation in queue
       
  1358 // --------------------------------------------------------------------------
       
  1359 //
       
  1360 void CUpnpRenderingStateMachine::Execute()
       
  1361     {
       
  1362     __LOG( "CUpnpRenderingStateMachine::Execute" );
       
  1363     TUpnpRenderingOperation op = Current();
       
  1364     if ( op.IsValid() )
       
  1365         {
       
  1366         __LOG1( "OperationQueue: Executing %s",
       
  1367             CommandName(op.Command()) );
       
  1368         MUpnpRenderingOperationExecutor::TResult result = ECompleted;
       
  1369         TRAPD( leave, result = ExecuteOperationL( op,
       
  1370             Upnp::ENone ) );
       
  1371         __LOG1( "OperationQueue: leave code(%d) ", leave );
       
  1372 
       
  1373         if ( leave != KErrNone )
       
  1374             {
       
  1375             __LOG1( "OperationQueue: %s failed while executing",
       
  1376                 CommandName(op.Command()) );
       
  1377             iQueue.Reset();
       
  1378             HandleAsyncError( op, leave );
       
  1379             }
       
  1380         else if ( result == ECompleted )
       
  1381             {
       
  1382             __LOG1( "OperationQueue: %s completed while executing",
       
  1383                 CommandName(op.Command()) );
       
  1384             if( iQueue.Count() > 0 )
       
  1385                 {
       
  1386                 iQueue.Remove( 0 );
       
  1387                 Execute(); // recur
       
  1388                 }
       
  1389             }
       
  1390         else if ( result == EContinue )
       
  1391             {
       
  1392             // operation continues
       
  1393             }
       
  1394         else
       
  1395             {
       
  1396             // illegal answer
       
  1397             __PANIC( __FILE__, __LINE__ );
       
  1398             }
       
  1399         }
       
  1400     }
       
  1401 
       
  1402 // --------------------------------------------------------------------------
       
  1403 // CUpnpRenderingStateMachine::Process
       
  1404 // Abstract process of an operation
       
  1405 // --------------------------------------------------------------------------
       
  1406 //
       
  1407 void CUpnpRenderingStateMachine::Process(
       
  1408     TInt aEvent,
       
  1409     TInt aError, const TAny* aParam1, const TAny* aParam2 )
       
  1410     {
       
  1411     __LOG( "CUpnpRenderingStateMachine::Process" );
       
  1412     TUpnpRenderingOperation op = Current();
       
  1413     MUpnpRenderingOperationExecutor::TResult result = ECompleted;
       
  1414     __LOG2( "OperationQueue: Processing %s with event %d",
       
  1415         CommandName(op.Command()), aEvent );
       
  1416     __LOG( "CUpnpRenderingStateMachine::Process - call ProcessOperationL" );
       
  1417     TRAPD( leave,
       
  1418         result = ProcessOperationL( op, aEvent,
       
  1419             aError, aParam1, aParam2 ) );
       
  1420     if ( leave != KErrNone )
       
  1421         {
       
  1422         __LOG1( "OperationQueue: %s failed while processing",
       
  1423             CommandName(op.Command()) );
       
  1424         iQueue.Reset();
       
  1425         HandleAsyncError( op, leave );
       
  1426         }
       
  1427     else if ( result == ECompleted )
       
  1428         {
       
  1429         __LOG2( 
       
  1430         "OperationQueue: %s completed while processing iQueue count = %d"
       
  1431          ,CommandName(op.Command()) , iQueue.Count() );
       
  1432         if( iQueue.Count() > 0 )
       
  1433             {
       
  1434             iQueue.Remove( 0 );
       
  1435             Execute(); // pop new
       
  1436             }
       
  1437         }
       
  1438     else if ( result == EContinue )
       
  1439         {
       
  1440         // operation continues
       
  1441         }
       
  1442     else
       
  1443         {
       
  1444         // illegal answer
       
  1445         __PANIC( __FILE__, __LINE__ );
       
  1446         }
       
  1447     }
       
  1448 
       
  1449 void CUpnpRenderingStateMachine::CompressQueueL()
       
  1450     {
       
  1451     TInt queueCount( iQueue.Count() );  
       
  1452     
       
  1453     if( queueCount > 1 )
       
  1454         {
       
  1455         TInt lastIndex( queueCount - 1 );     
       
  1456         
       
  1457         switch( iQueue[lastIndex].Command() )
       
  1458             {
       
  1459             case Upnp::EStop:
       
  1460                 {
       
  1461                 /*
       
  1462                 
       
  1463                 TODO : check how to do later!! 
       
  1464                  
       
  1465                 TInt removeStartIndex( 0 );
       
  1466                 
       
  1467                 if( iQueue[0] == Upnp::EStop )
       
  1468                     {
       
  1469                     // remove all except current ongoing stop command
       
  1470                     removeStartIndex = lastIndex ;
       
  1471                     }  
       
  1472                 else
       
  1473                     {
       
  1474                     // remove all except current ongoing command and last stop 
       
  1475                     // command
       
  1476                     removeStartIndex = lastIndex - 1;
       
  1477                     }
       
  1478                     
       
  1479                 for( TInt i = removeStartIndex; i > 0; i-- )
       
  1480                     {
       
  1481                     __LOG2( "OperationQueue: Removing %s from queue index %d",
       
  1482                         CommandName( iQueue[i].Command() ), i );
       
  1483                     iQueue.Remove( i );
       
  1484                     } */
       
  1485                     
       
  1486                 break;
       
  1487                 }        
       
  1488             case Upnp::EPlay:
       
  1489                 {
       
  1490                /* 
       
  1491                 
       
  1492                 TODO : check how to do later!! 
       
  1493                 
       
  1494                 TInt removeStartIndex( 0 );
       
  1495                 
       
  1496                 const CUpnpItem* item = static_cast<const CUpnpItem*>(
       
  1497                     iQueue[lastIndex].Data() );
       
  1498                 
       
  1499                 if( iQueue[0] == Upnp::EPlay && 
       
  1500                     item                     &&
       
  1501                     ResourceFromL( *item ).Value() == iCurrentUri )
       
  1502                     {
       
  1503                     // remove all except current ongoing play command
       
  1504                     removeStartIndex = lastIndex;
       
  1505                     }
       
  1506                 else
       
  1507                     {
       
  1508                     // remove all except current ongoing command and 
       
  1509                     // (last stop and) play command
       
  1510                     if( queueCount > 2 &&
       
  1511                         iQueue[lastIndex - 1] == Upnp::EStop )
       
  1512                         {
       
  1513                         // stop found before last play command
       
  1514                         removeStartIndex = lastIndex - 2;
       
  1515                         }
       
  1516                     else
       
  1517                         {
       
  1518                         removeStartIndex = lastIndex - 1;
       
  1519                         }
       
  1520                     }
       
  1521                     
       
  1522                 for( TInt i = removeStartIndex; i > 0; i-- )
       
  1523                     {
       
  1524                     __LOG2( "OperationQueue: Removing %s from queue index %d",
       
  1525                         CommandName( iQueue[i].Command() ), i );
       
  1526                     iQueue.Remove( i );
       
  1527                     } 
       
  1528                     */
       
  1529                 break;
       
  1530                 }
       
  1531             case Upnp::ECalibrate:
       
  1532                 {
       
  1533                 RemoveAllDublicateCommands( iQueue[lastIndex].Command() );
       
  1534                 break;
       
  1535                 }
       
  1536             case Upnp::ERestart:     
       
  1537             case Upnp::EPause:
       
  1538             case Upnp::ESeek:
       
  1539             case Upnp::EResume: 
       
  1540             case Upnp::ENone:                
       
  1541             case Upnp::ESync:
       
  1542             case Upnp::EClose:
       
  1543             case Upnp::ENext:
       
  1544             case Upnp::EPrev:
       
  1545             case Upnp::EBack:
       
  1546             case Upnp::EJump:
       
  1547             default:
       
  1548                 {     
       
  1549                 //not implemented -> do nothing      
       
  1550                 break;
       
  1551                 }
       
  1552             }
       
  1553         }
       
  1554     }
       
  1555 
       
  1556 // --------------------------------------------------------------------------
       
  1557 // CUpnpRenderingStateMachine::RemoveAllDublicateCommands
       
  1558 // --------------------------------------------------------------------------
       
  1559 // 
       
  1560 void CUpnpRenderingStateMachine::RemoveAllDublicateCommands( 
       
  1561 Upnp::TCommand aCommand )
       
  1562     {
       
  1563     __LOG1( "CUpnpRenderingStateMachine::RemoveAllDublicateCommands \
       
  1564             command = %d" , aCommand );
       
  1565     TInt lastIndex( iQueue.Count() - 1 );    
       
  1566 
       
  1567     for( TInt i(lastIndex-1); i > 0; i-- )
       
  1568        {
       
  1569        if( iQueue[i].Command() == aCommand )
       
  1570            {
       
  1571            __LOG1( "CUpnpRenderingStateMachine::RemoveAllDublicateCommands \
       
  1572                   found dublicate command index = %d",i);
       
  1573            // remove dublicate command
       
  1574            iQueue.Remove( i );
       
  1575            }
       
  1576        } 
       
  1577     }
       
  1578 
       
  1579 // --------------------------------------------------------------------------
       
  1580 // CUpnpRenderingStateMachine::Current
       
  1581 // --------------------------------------------------------------------------
       
  1582 // 
       
  1583 TUpnpRenderingOperation CUpnpRenderingStateMachine::Current() const
       
  1584     {
       
  1585     __LOG( "CUpnpRenderingStateMachine::Current" );
       
  1586     return ( iQueue.Count() > 0 ) ? iQueue[0] : Upnp::ENone;
       
  1587     }
       
  1588 
       
  1589 // --------------------------------------------------------------------------
       
  1590 // ResetArray
       
  1591 // --------------------------------------------------------------------------
       
  1592 // 
       
  1593 void ResetArray( TAny* iParam )
       
  1594     {
       
  1595     __LOG( "CUpnpRenderingStateMachine::ResetArray" );
       
  1596     RArray<TUpnpRenderingOperation>* array =
       
  1597         static_cast< RArray<TUpnpRenderingOperation>* >( iParam );
       
  1598     array->Reset();
       
  1599     }
       
  1600 
       
  1601 // --------------------------------------------------------------------------
       
  1602 // CUpnpRenderingStateMachine::ExecuteRecursivelyL
       
  1603 // Runs an operation first in the queue. If during the operation there
       
  1604 // were more operations added to queue, continues running recursively.
       
  1605 // --------------------------------------------------------------------------
       
  1606 //
       
  1607 void CUpnpRenderingStateMachine::ExecuteRecursivelyL()
       
  1608     {
       
  1609     __LOG( "CUpnpRenderingStateMachine::ExecuteRecursivelyL" );
       
  1610     TUpnpRenderingOperation op = Current();
       
  1611     if ( op.IsValid() )
       
  1612         {
       
  1613         __LOG1( "OperationQueue: Executing %s",
       
  1614             CommandName(op.Command()) );
       
  1615         // if the operation fails, OperationArrayClose method will 
       
  1616         // clean up the entire operations queue !
       
  1617         CleanupStack::PushL( TCleanupItem(
       
  1618             ResetArray, &iQueue ) );
       
  1619         MUpnpRenderingOperationExecutor::TResult result = 
       
  1620             ExecuteOperationL( op,
       
  1621                     Upnp::ENone );
       
  1622         CleanupStack::Pop();
       
  1623         switch( result )
       
  1624             {
       
  1625             case ECompleted:
       
  1626                 {
       
  1627                 __LOG1( "OperationQueue: %s completed while executing",
       
  1628                     CommandName(op.Command()) );
       
  1629                 if( iQueue.Count() > 0 )
       
  1630                     {
       
  1631                     iQueue.Remove( 0 );
       
  1632                     ExecuteRecursivelyL(); // recur
       
  1633                     }
       
  1634                 break;
       
  1635                 }
       
  1636             case EContinue:
       
  1637                 {
       
  1638                 // operation continues
       
  1639                 break;
       
  1640                 }
       
  1641             case EQueue:
       
  1642             default:
       
  1643                 {
       
  1644                 // illegal answer
       
  1645                 __PANIC( __FILE__, __LINE__ );
       
  1646                 }
       
  1647             }
       
  1648         }
       
  1649     }
       
  1650 
       
  1651 // --------------------------------------------------------------------------
       
  1652 // CUpnpRenderingStateMachine::ExecuteParallelL
       
  1653 // Runs an operation that was requested to put to queue. Checks if it
       
  1654 // completes right away or if it should wait for its turn to run.
       
  1655 // --------------------------------------------------------------------------
       
  1656 //
       
  1657 void CUpnpRenderingStateMachine::ExecuteParallelL(
       
  1658     const TUpnpRenderingOperation& aOperation )
       
  1659     {
       
  1660     __LOG( "CUpnpRenderingStateMachine::ExecuteParallelL" );
       
  1661     TUpnpRenderingOperation current = Current();
       
  1662     __LOG1( "OperationQueue: Executing %s",
       
  1663         CommandName(aOperation.Command()) );
       
  1664     MUpnpRenderingOperationExecutor::TResult result = 
       
  1665                     ExecuteOperationL( aOperation, current );
       
  1666     switch( result )
       
  1667         {
       
  1668         case ECompleted:
       
  1669             {
       
  1670             __LOG1( "OperationQueue: %s completed while executing",
       
  1671                 CommandName(aOperation.Command()) );
       
  1672             break;
       
  1673             }
       
  1674         case EQueue:
       
  1675             {
       
  1676             PushL( aOperation );
       
  1677             __LOG1( "OperationQueue: %s added to queue",
       
  1678                 CommandName(aOperation.Command()) );
       
  1679             break;
       
  1680             }
       
  1681         case EContinue:
       
  1682         default:
       
  1683             {
       
  1684             // illegal answer
       
  1685             __PANIC( __FILE__, __LINE__ );
       
  1686             }
       
  1687         }
       
  1688     }
       
  1689     
       
  1690 // end of file