upnpmpxplugins/upnpplaybackplugins/src/upnpplaybackstatemachine.cpp
branchIOP_Improvements
changeset 40 08b5eae9f9ff
parent 39 6369bfd1b60d
child 41 b4d83ea1d6e2
equal deleted inserted replaced
39:6369bfd1b60d 40:08b5eae9f9ff
     1 /*
       
     2 * Copyright (c) 2008 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:      Class for retrieving and selecting media renderers
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 // INCLUDES
       
    24 #include <mpxplaybackplugin.h>
       
    25 #include <mpxplaybackpluginobserver.h>
       
    26 #include "upnpavrenderingsession.h"
       
    27 #include "upnpavrenderingsessionobserver.h"
       
    28 #include "upnpavdevice.h"
       
    29 
       
    30 #include "upnpmusicplayer.h" // for parent.Observer()
       
    31 #include "upnptrack.h" // for TrackDuration
       
    32 #include "upnpvaluestatemachine.h" //
       
    33 #include "upnpplaybackstatemachine.h" // myself
       
    34 #include "upnppluginserrortranslation.h"
       
    35 
       
    36 _LIT( KComponentLogfile, "musicplugins.txt");
       
    37 #include "upnplog.h"
       
    38 
       
    39 // CONSTANTS
       
    40 _LIT( KStateStoppedText, "Stopped" );
       
    41 _LIT( KStatePlayingText, "Playing" );
       
    42 _LIT( KStatePausedText, "Paused" );
       
    43 _LIT( KStateUnknownText, "Unknown" );
       
    44 
       
    45 const TInt KDurationErrorMargin = 500; // 0.5 seconds
       
    46 const TInt KPlaybackInfoTimeOut = 1000000; // 1s wait until device is ready
       
    47 const TInt KPlaybackInfoTimeOutEnd = 2000000; // 2s wait check whether
       
    48     //the playing is ended
       
    49 
       
    50 // ======== MEMBER FUNCTIONS ========
       
    51 
       
    52 // --------------------------------------------------------------------------
       
    53 // CUPnPPlaybackStateMachine::NewL
       
    54 // 1st phase constructor.
       
    55 // --------------------------------------------------------------------------
       
    56 //
       
    57 CUPnPPlaybackStateMachine* CUPnPPlaybackStateMachine::NewL( 
       
    58     CUPnPMusicPlayer& aParent,
       
    59     MUPnPAVRenderingSession& aRenderingSession )
       
    60     {
       
    61     __LOG( "PlaybackStateMachine::NewL" );
       
    62     CUPnPPlaybackStateMachine* self =
       
    63         new(ELeave) CUPnPPlaybackStateMachine(
       
    64             aParent, aRenderingSession );
       
    65     CleanupStack::PushL( self );
       
    66     self->ConstructL();
       
    67     CleanupStack::Pop( self );
       
    68     return self;
       
    69     }
       
    70 
       
    71 // --------------------------------------------------------------------------
       
    72 // CUPnPPlaybackStateMachine::CUPnPPlaybackStateMachine
       
    73 // Default constructor.
       
    74 // --------------------------------------------------------------------------
       
    75 // 
       
    76 CUPnPPlaybackStateMachine::CUPnPPlaybackStateMachine( 
       
    77     CUPnPMusicPlayer& aParent,
       
    78     MUPnPAVRenderingSession& aRenderingSession )
       
    79     :iParent( aParent )
       
    80     ,iRendererSession( aRenderingSession )
       
    81     ,iState( EStateStopped )
       
    82     ,iCurrentOperation( EOperationNone )
       
    83     {
       
    84     }
       
    85 
       
    86 // --------------------------------------------------------------------------
       
    87 // CUPnPPlaybackStateMachine::ConstructL
       
    88 // --------------------------------------------------------------------------
       
    89 //
       
    90 void CUPnPPlaybackStateMachine::ConstructL()
       
    91     {
       
    92     __LOG( "CUPnPPlaybackStateMachine::ConstructL" );
       
    93 
       
    94     // Create timer for observing duration query time out.
       
    95     TInt64 iTime = 0;
       
    96     iPlayMark = TTime( iTime );
       
    97     iPauseMark = TTime( iTime );
       
    98     iPeriodizer = CUPnPMusicPeriodizer::NewL( *this, KPlaybackInfoTimeOut );
       
    99     iPeriodizerEnd = CUPnPMusicPeriodizer::NewL( *this, 
       
   100         KPlaybackInfoTimeOutEnd );
       
   101     }
       
   102 
       
   103 // --------------------------------------------------------------------------
       
   104 // CUPnPPlaybackStateMachine::~CUPnPPlaybackStateMachine
       
   105 // Destructor.
       
   106 // --------------------------------------------------------------------------
       
   107 //
       
   108 CUPnPPlaybackStateMachine::~CUPnPPlaybackStateMachine()
       
   109     {
       
   110     __LOG( "PlaybackStateMachine destructor" );
       
   111     iOperationQueue.Close();
       
   112     delete iPeriodizer;
       
   113     delete iPeriodizerEnd;
       
   114     }
       
   115 
       
   116 // --------------------------------------------------------------------------
       
   117 // CUPnPPlaybackStateMachine::CommandL
       
   118 // Executes a command on the selected song.
       
   119 // --------------------------------------------------------------------------
       
   120 // 
       
   121 void CUPnPPlaybackStateMachine::CommandL( TMPXPlaybackCommand aCmd )
       
   122     {
       
   123     if ( aCmd == EPbCmdClose )
       
   124         {
       
   125         // close can be handled parallel to other commands
       
   126         HandleCloseL();
       
   127         return;
       
   128         }
       
   129 
       
   130     if ( !iCurrentOperation.None() )
       
   131         {
       
   132         __LOG( "PlaybackStateMachine::CommandL - Append to queue" );
       
   133         iOperationQueue.AppendL( aCmd );
       
   134         return;
       
   135         }
       
   136 
       
   137     switch( aCmd )
       
   138         {
       
   139         case EPbCmdPlay:
       
   140             {            
       
   141             if( iState == EStatePlaying )
       
   142                 {
       
   143                 // already playing - ignore
       
   144                 CheckOperationInQueueL();
       
   145                 }
       
   146             else
       
   147                 {
       
   148                 __LOG( "PlaybackStateMachine: command play" );
       
   149                 iCurrentOperation = aCmd;
       
   150                 iRendererSession.PlayL();
       
   151                 } 
       
   152             }
       
   153             break;
       
   154         case EPbCmdPause:
       
   155             {
       
   156             // Check if pause is supported by device
       
   157             if( iParent.UsedRendererDevice().PauseCapability() )
       
   158                 {
       
   159                 if( iState == EStatePaused )
       
   160                     {
       
   161                     // already paused - ignore
       
   162                     CheckOperationInQueueL();
       
   163                     }
       
   164                 else
       
   165                     {
       
   166                     __LOG( "PlaybackStateMachine: command pause" );
       
   167                     iCurrentOperation = aCmd;
       
   168                     iRendererSession.PauseL();
       
   169                     }
       
   170                 }
       
   171             else
       
   172                 {
       
   173                 __LOG( "PlaybackStateMachine: Pause is not supported by \
       
   174                 device!" );
       
   175                 iParent.Observer().HandlePluginEvent( 
       
   176                     MMPXPlaybackPluginObserver::EPPaused, 0,
       
   177                     KErrNotSupported );
       
   178                 }
       
   179             }
       
   180             break;
       
   181         case EPbCmdStop:
       
   182             {
       
   183             if( iState == EStateStopped )
       
   184                 {
       
   185                 // already stopped - ignore
       
   186                 CheckOperationInQueueL();
       
   187                 }
       
   188             else
       
   189                 {
       
   190                 __LOG( "PlaybackStateMachine: command stop" );
       
   191                 iCurrentOperation = aCmd;
       
   192                 iRendererSession.StopL();
       
   193                 }
       
   194             }
       
   195             break;
       
   196         case EPbCmdReplay:
       
   197             {
       
   198             iCurrentOperation = aCmd;
       
   199                 __LOG( "PlaybackStateMachine: command replay" );
       
   200             if( iState == EStatePlaying || iState == EStatePaused )
       
   201                 {
       
   202                 // playing -must stop first
       
   203                 iRendererSession.StopL();
       
   204                 }
       
   205             else
       
   206                 {
       
   207                 // just play
       
   208                 iRendererSession.PlayL();
       
   209                 }
       
   210             }
       
   211             break;
       
   212         default: // Given command is not supported
       
   213             {
       
   214             __LOG( "PlaybackStateMachine: command default?" );
       
   215             CheckOperationInQueueL();
       
   216             User::Leave( KErrNotSupported );
       
   217             break;
       
   218             } 
       
   219         } 
       
   220     }
       
   221 
       
   222 // --------------------------------------------------------------------------
       
   223 // CUPnPPlaybackStateMachine::PositionL
       
   224 // Changes the position within the currently playing track
       
   225 // --------------------------------------------------------------------------
       
   226 //
       
   227 void CUPnPPlaybackStateMachine::PositionL( TInt aPosition )
       
   228     {
       
   229     
       
   230     // Ignore if already called.
       
   231     if( iCurrentOperation == EOperationPositionToZero )
       
   232         {
       
   233         __LOG( "PlaybackStateMachine::PositionL - \
       
   234         EOperationPositionToZero called twice -> ignored" );
       
   235         return;
       
   236         }
       
   237     
       
   238     if ( !iCurrentOperation.None() )
       
   239         {
       
   240         __LOG( "PlaybackStateMachine::PositionL - Append to queue" );
       
   241         iOperationQueue.AppendL( EOperationPositionToZero );
       
   242         return;
       
   243         }
       
   244     if ( aPosition != 0 )
       
   245         {
       
   246         CheckOperationInQueueL();
       
   247         User::Leave( KErrNotSupported );
       
   248         }
       
   249 
       
   250     // handle Position(0)
       
   251     if ( iState == EStatePlaying )
       
   252         {
       
   253         __LOG( "PlaybackStateMachine: position(0) while playing" );
       
   254         iCurrentOperation = EOperationPositionToZero;
       
   255         iRendererSession.StopL();
       
   256         }
       
   257     else if ( iState == EStatePaused )
       
   258         {
       
   259         __LOG( "PlaybackStateMachine: PositionL(0) while paused" );
       
   260         iCurrentOperation = EOperationPositionToZeroDuringPause;
       
   261         iRendererSession.StopL();
       
   262         }
       
   263     else if ( iState == EStateStopped )
       
   264         {
       
   265         __LOG( "PlaybackStateMachine: PositionL(0) while stopped" );
       
   266         CheckOperationInQueueL();
       
   267         
       
   268         // immediate response !        
       
   269         iParent.Observer().HandlePluginEvent( 
       
   270             MMPXPlaybackPluginObserver::EPSetComplete,
       
   271             EPbPropertyPosition, KErrNone );
       
   272         
       
   273         }
       
   274     }
       
   275 
       
   276 // --------------------------------------------------------------------------
       
   277 // CUPnPPlaybackStateMachine::SilentStopL
       
   278 // Stops playback, does not provide any ACK event
       
   279 // --------------------------------------------------------------------------
       
   280 //
       
   281 void CUPnPPlaybackStateMachine::SilentStopL()
       
   282     {
       
   283     if ( !iCurrentOperation.None() )
       
   284         {
       
   285         __LOG( "PlaybackStateMachine::SilentStopL - Append to queue" );
       
   286         iOperationQueue.AppendL( EOperationSilentStop );
       
   287         return;
       
   288         }
       
   289 
       
   290     // handle stop
       
   291     __LOG( "PlaybackStateMachine: SilentStopL" );
       
   292     if( iState == EStateStopped )
       
   293         {
       
   294         // already stopped - ignore
       
   295         CheckOperationInQueueL();
       
   296         }
       
   297     else
       
   298         {
       
   299         iCurrentOperation = EOperationSilentStop;
       
   300         iRendererSession.StopL();
       
   301         }
       
   302     }
       
   303 
       
   304 // --------------------------------------------------------------------------
       
   305 // CUPnPPlaybackStateMachine::Cancel
       
   306 // --------------------------------------------------------------------------
       
   307 //
       
   308 void CUPnPPlaybackStateMachine::Cancel()
       
   309     {
       
   310     // reset current operation and empty the queue -> no callbacks.
       
   311     iCurrentOperation.Reset();
       
   312     iOperationQueue.Reset();
       
   313     }
       
   314 
       
   315 // --------------------------------------------------------------------------
       
   316 // CUPnPPlaybackStateMachine::HandleCloseL
       
   317 // Handles the close command
       
   318 // --------------------------------------------------------------------------
       
   319 //
       
   320 void CUPnPPlaybackStateMachine::HandleCloseL()
       
   321     {
       
   322     if ( iCurrentOperation == EPbCmdStop )
       
   323         {
       
   324         // Stop pending - it can't be completed -> fake callback.
       
   325         iParent.Observer().HandlePluginEvent( 
       
   326             MMPXPlaybackPluginObserver::EPStopped,
       
   327             KErrNone, KErrNone );
       
   328         }
       
   329 
       
   330     iParent.Observer().HandlePluginEvent(
       
   331         MMPXPlaybackPluginObserver::EPClosed,
       
   332         KErrNone, KErrNone );
       
   333     }
       
   334 
       
   335 
       
   336 // --------------------------------------------------------------------------
       
   337 // CUPnPPlaybackStateMachine::InteractOperationComplete
       
   338 // Response for interaction operation (play, stop, etc.).
       
   339 // --------------------------------------------------------------------------
       
   340 //
       
   341 void CUPnPPlaybackStateMachine::InteractOperationComplete( TInt aErrorCode, 
       
   342     TUPnPAVInteractOperation aOperation )
       
   343     {
       
   344     __LOG1( "CUPnPPlaybackStateMachine::InteractOperationComplete: err:[%d]",
       
   345         aErrorCode );
       
   346     aErrorCode = TUpnpPluginsErrorTranslation::ErrorTranslate( aErrorCode );
       
   347     switch( aOperation )
       
   348         {
       
   349         case EUPnPAVPlayUser:
       
   350             {                
       
   351             __LOG1( "PlaybackStateMachine: event play user, state[%d]",iState );
       
   352 
       
   353             if ( aErrorCode == KErrNone )
       
   354                 {
       
   355                 if ( iState == EStatePaused )
       
   356                     {
       
   357                     TimeContinue();
       
   358                     ChangeState( EStatePlaying );
       
   359                     iParent.Observer().HandlePluginEvent( 
       
   360                         MMPXPlaybackPluginObserver::EPPlaying, KErrNone,
       
   361                         aErrorCode );
       
   362                     if( iCurrentOperation == EPbCmdPlay )
       
   363                         {
       
   364                         iCurrentOperation.Reset();
       
   365                         TRAP_IGNORE( CheckOperationInQueueL() );
       
   366                         }
       
   367                     }
       
   368                 else if ( iState == EStatePlaying )
       
   369                     {
       
   370                     iPeriodizer->Stop();
       
   371                     iParent.HandlePlayStarted();
       
   372                     }
       
   373                 else if ( iState == EStateStopped )
       
   374                     {
       
   375                     if ( iCurrentOperation == EPbCmdPlay ||
       
   376                         iCurrentOperation == EPbCmdReplay )
       
   377                         {
       
   378                         TimePlay();
       
   379                         iParent.HandlePlayStarted();
       
   380                         ChangeState( EStatePlaying );
       
   381                         iCurrentOperation.Reset();
       
   382                         TRAP_IGNORE( CheckOperationInQueueL() );
       
   383                         iParent.Observer().HandlePluginEvent( 
       
   384                             MMPXPlaybackPluginObserver::EPPlaying, KErrNone,
       
   385                             aErrorCode );
       
   386                         }
       
   387                     else
       
   388                         {
       
   389                         // spontaneous change to PLAYING state -> ignore
       
   390                         }
       
   391                     }
       
   392                     
       
   393                 }
       
   394             else
       
   395                 {
       
   396                 ChangeState( EStateUnknown );
       
   397                 }
       
   398             break;
       
   399             }
       
   400         case EUPnPAVPlay: 
       
   401             {
       
   402             if ( iState == EStatePlaying )
       
   403                 {
       
   404                 __LOG( "PlaybackStateMachine: event play ignored" );
       
   405                 break;
       
   406                 }
       
   407 
       
   408             __LOG( "PlaybackStateMachine: event play" );
       
   409 
       
   410             if ( aErrorCode == KErrNone )
       
   411                 {
       
   412                 if ( iState == EStateStopped )
       
   413                     {
       
   414                     TimePlay();
       
   415                     iPeriodizer->Start();
       
   416                     iPeriodizerEnd->Start();           
       
   417                     }
       
   418                 else if ( iState == EStatePaused )
       
   419                     {
       
   420                     TimeContinue();
       
   421                     iPeriodizer->Stop();       
       
   422                     iPeriodizer->Start();    
       
   423                     iPeriodizerEnd->Stop();
       
   424                     iPeriodizerEnd->Start();
       
   425                     }
       
   426                 ChangeState( EStatePlaying );
       
   427                 }
       
   428             else
       
   429                 {
       
   430                 ChangeState( EStateUnknown );
       
   431                 }
       
   432 
       
   433                 iCurrentOperation.Reset();
       
   434                 TRAP_IGNORE( CheckOperationInQueueL() );
       
   435             break;
       
   436             }
       
   437         case EUPnPAVPauseUser:
       
   438             {            
       
   439             if ( !iCurrentOperation.None() ||
       
   440                 iState == EStatePaused )
       
   441                 {
       
   442                 __LOG( "PlaybackStateMachine: event pause user ignored" );
       
   443                 break;
       
   444                 }
       
   445             __LOG( "PlaybackStateMachine: event pause user" );
       
   446             
       
   447             if( aErrorCode == KErrNone )
       
   448                 {
       
   449                 TimePause();
       
   450                 ChangeState( EStatePaused );
       
   451                 iPeriodizerEnd->Stop();
       
   452                 }
       
   453             else
       
   454                 {
       
   455                 ChangeState( EStateUnknown );
       
   456                 }
       
   457 
       
   458             // Call callback
       
   459             iParent.Observer().HandlePluginEvent( 
       
   460                 MMPXPlaybackPluginObserver::EPPaused, KErrNone,
       
   461                 aErrorCode );
       
   462             break;
       
   463             }
       
   464 
       
   465         case EUPnPAVPause:
       
   466             {            
       
   467             __LOG( "PlaybackStateMachine: event pause" );
       
   468 
       
   469             TInt err = aErrorCode;
       
   470             if( aErrorCode == KErrNone )
       
   471                 {
       
   472                 TimePause();
       
   473                 ChangeState( EStatePaused );
       
   474                 iPeriodizerEnd->Stop();
       
   475                 }
       
   476             else if( aErrorCode == KErrNotSupported )
       
   477                 {
       
   478                 // Pause is supported (pause capability checked in CommandL )
       
   479                 // but device is not ready.
       
   480                 err = KErrNotReady;
       
   481                 }
       
   482             else
       
   483                 {
       
   484                 ChangeState( EStateUnknown );
       
   485                 }
       
   486 
       
   487             if ( iCurrentOperation == EPbCmdPause )
       
   488                 {
       
   489                 iCurrentOperation.Reset();
       
   490                 TRAP_IGNORE( CheckOperationInQueueL() );
       
   491                 iParent.Observer().HandlePluginEvent( 
       
   492                     MMPXPlaybackPluginObserver::EPPaused, KErrNone,
       
   493                     err );
       
   494                 }
       
   495             else
       
   496                 {
       
   497                 iCurrentOperation.Reset();
       
   498                 TRAP_IGNORE( CheckOperationInQueueL() );
       
   499                 }
       
   500             break;
       
   501             }
       
   502         case EUPnPAVStopUser:
       
   503             {
       
   504             iPeriodizerEnd->Stop();
       
   505             if ( !iCurrentOperation.None() ||
       
   506                 iState == EStateStopped )
       
   507                 {
       
   508                 __LOG( "PlaybackStateMachine: event stop user ignored" );
       
   509                 break;
       
   510                 }
       
   511             __LOG( "PlaybackStateMachine: event stop user" );
       
   512 
       
   513             TBool trackComplete = TimeStop();
       
   514             if ( aErrorCode == KErrNone )
       
   515                 {
       
   516                 ChangeState( EStateStopped );
       
   517                 iParent.HandlePlayComplete();
       
   518                 }
       
   519             else
       
   520                 {
       
   521                 ChangeState( EStateUnknown );
       
   522                 }
       
   523 
       
   524             // Call callback
       
   525             if ( trackComplete )
       
   526                 {
       
   527                 __LOG( "PlaybackStateMachine: play complete event to user" );
       
   528                 iParent.Observer().HandlePluginEvent( 
       
   529                     MMPXPlaybackPluginObserver::EPPlayComplete, KErrNone,
       
   530                     aErrorCode );
       
   531                 }
       
   532             else
       
   533                 {
       
   534                 __LOG( "PlaybackStateMachine: play stopped event to user" );
       
   535                 iParent.Observer().HandlePluginEvent( 
       
   536                     MMPXPlaybackPluginObserver::EPStopped, KErrNone,
       
   537                     aErrorCode );
       
   538                 }
       
   539             break;
       
   540             }       
       
   541         case EUPnPAVStop:
       
   542             {
       
   543             iPeriodizerEnd->Stop();
       
   544             if ( iState == EStateStopped )
       
   545                 {
       
   546                 // already in this state - ignore
       
   547                 break;
       
   548                 }
       
   549             __LOG( "PlaybackStateMachine: event stop" );
       
   550 
       
   551             if ( aErrorCode == KErrNone )
       
   552                 {                 
       
   553                 ChangeState( EStateStopped );
       
   554                 }
       
   555             else
       
   556                 {
       
   557                 ChangeState( EStateUnknown );
       
   558                 }
       
   559 
       
   560             if ( iCurrentOperation == EPbCmdStop )
       
   561                 {
       
   562                 iCurrentOperation.Reset();
       
   563                 TRAP_IGNORE( CheckOperationInQueueL() );
       
   564                  // Call callback
       
   565                 iParent.Observer().HandlePluginEvent( 
       
   566                     MMPXPlaybackPluginObserver::EPStopped, KErrNone,
       
   567                     aErrorCode );
       
   568                 }
       
   569             else if ( iCurrentOperation == EPbCmdReplay ||
       
   570                 iCurrentOperation == EOperationPositionToZero )
       
   571                 {
       
   572                 // continue with play
       
   573                 TRAP_IGNORE( iRendererSession.PlayL() );
       
   574                 }
       
   575             else if ( iCurrentOperation ==
       
   576                 EOperationPositionToZeroDuringPause )
       
   577                 {
       
   578                 // position zero complete
       
   579                 iCurrentOperation.Reset();
       
   580                 TRAP_IGNORE( CheckOperationInQueueL() );
       
   581                
       
   582                 iParent.Observer().HandlePluginEvent( 
       
   583                     MMPXPlaybackPluginObserver::EPSetComplete,
       
   584                     EPbPropertyPosition, aErrorCode );
       
   585                 }
       
   586             else
       
   587                 {
       
   588                 // Note: covers also EOperationSilentStop
       
   589                 iCurrentOperation.Reset();
       
   590                 TRAP_IGNORE( CheckOperationInQueueL() );
       
   591                 }
       
   592             break;
       
   593             }
       
   594         default:
       
   595             {
       
   596             __LOG( "PlaybackStateMachine: event default?" );
       
   597             __PANICD( __FILE__, __LINE__ );
       
   598             break;
       
   599             }    
       
   600         }
       
   601     }
       
   602     
       
   603 // --------------------------------------------------------------------------
       
   604 // CUPnPPlaybackStateMachine::CheckOperationInQueueL
       
   605 // Checks if operations are in the queue, and executes
       
   606 // --------------------------------------------------------------------------
       
   607 //   
       
   608 void CUPnPPlaybackStateMachine::CheckOperationInQueueL()
       
   609     {
       
   610     if ( !iCurrentOperation.None() )
       
   611         {
       
   612         // check operation though a current operation exists!
       
   613         __PANICD( __FILE__, __LINE__ );
       
   614         return;
       
   615         }
       
   616 
       
   617     if ( iOperationQueue.Count() > 0 )
       
   618         {
       
   619         TOperation op = iOperationQueue[0];
       
   620         iOperationQueue.Remove(0);
       
   621         if ( op == EOperationCommand )
       
   622             {
       
   623             CommandL( op.iCmd );
       
   624             }
       
   625         else if ( op == EOperationPositionToZero )
       
   626             {
       
   627             PositionL( 0 );
       
   628             }
       
   629         else
       
   630             {
       
   631             __PANICD( __FILE__, __LINE__ );
       
   632             }
       
   633         }
       
   634     }
       
   635 
       
   636 // --------------------------------------------------------------------------
       
   637 // CUPnPPlaybackStateMachine::TimePlay
       
   638 // --------------------------------------------------------------------------
       
   639 //
       
   640 void CUPnPPlaybackStateMachine::TimePlay()
       
   641     {
       
   642     iPlayMark.UniversalTime();
       
   643     iPausetime = 0;
       
   644     }
       
   645 
       
   646 // --------------------------------------------------------------------------
       
   647 // CUPnPPlaybackStateMachine::TimePause
       
   648 // --------------------------------------------------------------------------
       
   649 //
       
   650 void CUPnPPlaybackStateMachine::TimePause()
       
   651     {
       
   652     iPauseMark.UniversalTime();
       
   653     }
       
   654 
       
   655 // --------------------------------------------------------------------------
       
   656 // CUPnPPlaybackStateMachine::TimeContinue
       
   657 // --------------------------------------------------------------------------
       
   658 //
       
   659 void CUPnPPlaybackStateMachine::TimeContinue()
       
   660     {
       
   661     TTime continueMark;
       
   662     continueMark.UniversalTime();
       
   663     TTimeIntervalMicroSeconds paused =
       
   664         continueMark.MicroSecondsFrom( iPauseMark );
       
   665     iPausetime += ( paused.Int64() / 1000 );
       
   666     }
       
   667 
       
   668 
       
   669 // --------------------------------------------------------------------------
       
   670 // CUPnPPlaybackStateMachine::TimeStop
       
   671 // --------------------------------------------------------------------------
       
   672 //
       
   673 TBool CUPnPPlaybackStateMachine::TimeStop()
       
   674     {
       
   675     TBool isCompleted = ETrue;
       
   676     if ( !iPlayMark.Int64() )
       
   677         {
       
   678         isCompleted = EFalse; 
       
   679         return isCompleted;  
       
   680         }
       
   681     TTime stopMark;
       
   682     stopMark.UniversalTime();
       
   683     TTimeIntervalMicroSeconds played =
       
   684         stopMark.MicroSecondsFrom( iPlayMark );
       
   685 
       
   686     TInt duration = iParent.Track().TrackDuration();
       
   687     TInt playtime = ( played.Int64() / 1000 ) - iPausetime;
       
   688     __LOG3("PlaybackStateMachine: playtime=%d duration=%d (pausetime=%d)",
       
   689         playtime/1000, duration/1000, iPausetime/1000 );
       
   690 
       
   691     if ( playtime >= 0 &&
       
   692         playtime < duration - KDurationErrorMargin )
       
   693         {
       
   694         // [0 - duration-margin]
       
   695         isCompleted= EFalse;
       
   696         }
       
   697     else if ( playtime >= duration - KDurationErrorMargin &&
       
   698         playtime <= duration + KDurationErrorMargin )
       
   699         {
       
   700         // [duration-margin - duration+margin]
       
   701         isCompleted= ETrue;
       
   702         }
       
   703     else
       
   704         {
       
   705         // position either negative or greater than duration ??
       
   706         __LOG2("Time ERROR: play=%d duration=%d ?", playtime, duration );
       
   707         isCompleted= ETrue;
       
   708         }
       
   709 
       
   710     return isCompleted;
       
   711     }
       
   712 
       
   713 
       
   714 // --------------------------------------------------------------------------
       
   715 // CUPnPPlaybackStateMachine::ChangeState
       
   716 // Changes the class state
       
   717 // --------------------------------------------------------------------------
       
   718 //
       
   719 void CUPnPPlaybackStateMachine::ChangeState( TState aNewState )
       
   720     {
       
   721     __LOG2( "PlaybackStateMachine: STATE %S -> %S",
       
   722         State( iState ), State( aNewState ) );
       
   723     iState = aNewState;
       
   724     }
       
   725 
       
   726 // --------------------------------------------------------------------------
       
   727 // CUPnPPlaybackStateMachine::State
       
   728 // --------------------------------------------------------------------------
       
   729 //
       
   730 const TDesC* CUPnPPlaybackStateMachine::State( TState aState )
       
   731     {
       
   732     switch( aState )
       
   733         {
       
   734         case EStateStopped:
       
   735             return &KStateStoppedText;
       
   736         case EStatePlaying:
       
   737             return &KStatePlayingText;
       
   738         case EStatePaused:
       
   739             return &KStatePausedText;
       
   740         default:
       
   741             return &KStateUnknownText;
       
   742         }
       
   743     }
       
   744 
       
   745 // --------------------------------------------------------------------------
       
   746 // CUPnPPlaybackStateMachine::HandlePeriod
       
   747 // Action when timer has expired.
       
   748 // --------------------------------------------------------------------------
       
   749 // 
       
   750 void CUPnPPlaybackStateMachine::HandlePeriod()
       
   751     {
       
   752     __LOG( "CUPnPPlaybackStateMachine::HandlePeriod" );
       
   753 
       
   754     // Remote device is ready for give playback information.
       
   755     iPeriodizer->Stop();
       
   756     iParent.HandlePlayStarted();
       
   757     }
       
   758     
       
   759 // --------------------------------------------------------------------------
       
   760 // CUPnPPlaybackStateMachine::HandlePeriodForEnd
       
   761 // Action when timer has expired.
       
   762 // --------------------------------------------------------------------------
       
   763 // 
       
   764 void CUPnPPlaybackStateMachine::HandlePeriodForEnd()
       
   765     {
       
   766     TBool trackComplete = TimeStop();
       
   767     if ( trackComplete )
       
   768         {
       
   769         iPeriodizerEnd->Stop();
       
   770         PlayOvertimeEnd();    
       
   771         }
       
   772     else
       
   773         {      
       
   774         iPeriodizerEnd->Start(); 
       
   775         }           
       
   776     }
       
   777     
       
   778 // --------------------------------------------------------------------------
       
   779 // CUPnPPlaybackStateMachine::PlayOvertimeEnd
       
   780 // Stoping the playing song.
       
   781 // --------------------------------------------------------------------------
       
   782 // 
       
   783  void CUPnPPlaybackStateMachine::PlayOvertimeEnd()
       
   784      {
       
   785      if ( !iCurrentOperation.None() ||
       
   786          iState == EStateStopped || iState == EStateUnknown)
       
   787         {
       
   788         return;
       
   789         }
       
   790      ChangeState( EStateStopped );  
       
   791      iParent.HandlePlayComplete();       
       
   792      iParent.Observer().HandlePluginEvent( 
       
   793           MMPXPlaybackPluginObserver::EPPlayComplete, KErrNone,
       
   794           KErrNone ); 
       
   795      }
       
   796