dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpFromFile.cpp
branchRCL_3
changeset 48 13a33d82ad98
parent 0 822a42b6c3f1
equal deleted inserted replaced
47:826cea16efd9 48:13a33d82ad98
       
     1 /*
       
     2 * Copyright (c) 2007 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 the License "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 the DVB-H Recording Manager RTP read class.*
       
    15 */
       
    16 
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "CRtpToFile.h"
       
    22 #include "CRtpFromFile.h"
       
    23 #include <ipvideo/CRtpMetaHeader.h>
       
    24 #include <ipvideo/CRtpClipManager.h>
       
    25 #include "CRtpTimer.h"
       
    26 #include <bsp.h>
       
    27 #include "videoserviceutilsLogger.h"
       
    28 
       
    29 // CONSTANTS
       
    30 const TInt KReadTimerInterval( 1000 );
       
    31 
       
    32 // ============================ MEMBER FUNCTIONS ===============================
       
    33 
       
    34 // -----------------------------------------------------------------------------
       
    35 // CRtpFromFile::NewL
       
    36 // Static two-phased constructor. Leaves object to cleanup stack.
       
    37 // -----------------------------------------------------------------------------
       
    38 //
       
    39 CRtpFromFile* CRtpFromFile::NewL( 
       
    40     MRtpFileReadObserver& aReadObs,
       
    41     CRtpToFile* aToFile )
       
    42     {
       
    43     CRtpFromFile* self = new( ELeave ) CRtpFromFile( aReadObs, aToFile );
       
    44     CleanupStack::PushL( self );
       
    45     self->ConstructL();
       
    46     CleanupStack::Pop( self );
       
    47     return self;
       
    48     }
       
    49 
       
    50 // -----------------------------------------------------------------------------
       
    51 // CRtpFromFile::CRtpFromFile
       
    52 // C++ default constructor can NOT contain any code, that might leave.
       
    53 // -----------------------------------------------------------------------------
       
    54 //
       
    55 CRtpFromFile::CRtpFromFile( MRtpFileReadObserver& aReadObs, CRtpToFile* aToFile )
       
    56   : CRtpFileBase(),
       
    57     iReadObs( aReadObs ),
       
    58     iToFile( aToFile ),
       
    59     iSkippedRead( EFalse ),
       
    60     iDuration( 0 )
       
    61     {
       
    62     // None
       
    63     }
       
    64 
       
    65 // -----------------------------------------------------------------------------
       
    66 // CRtpFromFile::ConstructL
       
    67 // Symbian 2nd phase constructor can leave.
       
    68 // -----------------------------------------------------------------------------
       
    69 //
       
    70 void CRtpFromFile::ConstructL()
       
    71     {
       
    72     LOG( "CRtpFromFile::ConstructL()" );
       
    73 
       
    74     CRtpFileBase::ConstructL();
       
    75     }
       
    76 
       
    77 // -----------------------------------------------------------------------------
       
    78 // Destructor
       
    79 //
       
    80 CRtpFromFile::~CRtpFromFile()
       
    81 // -----------------------------------------------------------------------------
       
    82     {
       
    83     LOG( "CRtpFromFile::~CRtpFromFile()" );
       
    84 
       
    85     Cancel();
       
    86     delete iTimer; iTimer = NULL;
       
    87     delete iFileData; iFileData = NULL;
       
    88     }
       
    89 
       
    90 // -----------------------------------------------------------------------------
       
    91 // CRtpFromFile::InitRtpReadL
       
    92 // Sets path of RTP file.
       
    93 // -----------------------------------------------------------------------------
       
    94 //
       
    95 void CRtpFromFile::InitRtpReadL(
       
    96     const TDesC& aClipPath,
       
    97     TInt8& aVersion,
       
    98     const TBool aTimeShift )
       
    99     {
       
   100     LOG1( "CRtpFromFile::InitRtpReadL(), aClipPath: %S", &aClipPath );
       
   101     
       
   102     // File server
       
   103     if ( !iFs.Handle() )
       
   104         {
       
   105         User::LeaveIfError( iFs.Connect() );
       
   106         }
       
   107 
       
   108     // Open clip
       
   109     aVersion = SwapClipL( aClipPath );
       
   110     
       
   111     // Mode
       
   112     iMode = ( aTimeShift )? EModeTimeShift: EModeNormal;
       
   113 
       
   114 #ifdef CR_ALL_LOGS
       
   115     LogVariables( _L( "InitRtpReadL()" ) );
       
   116 #endif // CR_ALL_LOGS
       
   117     }
       
   118 
       
   119 // -----------------------------------------------------------------------------
       
   120 // CRtpFromFile::InitRtpReadL
       
   121 // Sets path of RTP file.
       
   122 // -----------------------------------------------------------------------------
       
   123 //
       
   124 void CRtpFromFile::InitRtpReadL(
       
   125     const RFile& aFileHandle,
       
   126     TInt8& aVersion )
       
   127     {
       
   128     LOG( "CRtpFromFile::InitRtpReadL(), with handle" );
       
   129     
       
   130     // File handle
       
   131     if ( !iFs.Handle() )
       
   132         {
       
   133         User::LeaveIfError( iFs.Connect() );
       
   134         }
       
   135     
       
   136     // Duplicate handle
       
   137     iFile.Close();
       
   138     iFile.Duplicate( aFileHandle );
       
   139     
       
   140     // File header
       
   141     ReadClipHeaderL( aVersion );
       
   142     delete iCurrentPath; iCurrentPath = NULL;
       
   143     TFileName name( KNullDesC );
       
   144     iFile.FullName( name );
       
   145     iCurrentPath = name.AllocL();
       
   146 
       
   147     // Mode
       
   148     iMode = EModeNormal;
       
   149 
       
   150 #ifdef CR_ALL_LOGS
       
   151     LogVariables( _L( "InitRtpReadL()" ) );
       
   152 #endif // CR_ALL_LOGS
       
   153     }
       
   154 
       
   155 // -----------------------------------------------------------------------------
       
   156 // CRtpFromFile::SwapClipL
       
   157 // Sets new path of RTP file.
       
   158 // -----------------------------------------------------------------------------
       
   159 //
       
   160 TInt8 CRtpFromFile::SwapClipL( const TDesC& aClipPath )
       
   161     {
       
   162     LOG1( "CRtpFromFile::SwapClipL(), aClipPath: %S", &aClipPath );
       
   163 
       
   164     iFile.Close();
       
   165     if ( !iFs.Handle() )
       
   166         {
       
   167         User::Leave( KErrBadHandle );
       
   168         }
       
   169         
       
   170     // Delete used clip
       
   171     if ( iMode == EModeTimeShift )
       
   172         {
       
   173         iFs.Delete( *iCurrentPath );
       
   174         }
       
   175     
       
   176     // Open new
       
   177     User::LeaveIfError( iFile.Open( iFs, aClipPath,
       
   178                         EFileShareAny | EFileStream | EFileRead ) );
       
   179     // File header
       
   180     TInt8 version( 0 );
       
   181     ReadClipHeaderL( version );
       
   182     delete iCurrentPath; iCurrentPath = NULL;
       
   183     iCurrentPath = aClipPath.AllocL();
       
   184 
       
   185     return version;
       
   186     }
       
   187 
       
   188 // -----------------------------------------------------------------------------
       
   189 // CRtpFromFile::ReadNextGroupL
       
   190 // Reads next RTP packets group from a specified file.
       
   191 // -----------------------------------------------------------------------------
       
   192 //
       
   193 TInt CRtpFromFile::ReadNextGroupL( const TInt aGroupPoint )
       
   194     {
       
   195     User::LeaveIfError( iMode );
       
   196     TBool delayedRead( EFalse );
       
   197 
       
   198     // Allready active??
       
   199     if ( iFileData )
       
   200         {
       
   201         if ( iTimer || IsActive() )
       
   202             {
       
   203             return KErrInUse; // Read already started, indication, not error
       
   204             }
       
   205         else
       
   206             {
       
   207             // Packet read may happen during iReadObs.RtpGroupReaded() call
       
   208             LOG( "CRtpFromFile::ReadNextGroupL(), Delayed read !" );
       
   209             delayedRead = ETrue;
       
   210             }
       
   211         }
       
   212     
       
   213     // Is watch during recording too close to live?
       
   214     if ( iToFile && iNextGroupPoint >= LastSeekAddr() )
       
   215         {
       
   216         iSkippedRead = ETrue;
       
   217         LOG( "CRtpFromFile::ReadNextGroupL(), Too close to live !" );
       
   218         return KErrEof; // No read actions now, indication, not error
       
   219         }
       
   220 
       
   221     // Group
       
   222     iThisGroup = ( aGroupPoint > KErrNotFound )? aGroupPoint: iNextGroupPoint;
       
   223 
       
   224     // Ok to read more?
       
   225     if ( iThisGroup > iLastSeekAddr || iGroupTime >= iDuration )
       
   226         {
       
   227         LOG( "CRtpFromFile::ReadNextGroupL(), All packets readed !" );
       
   228         User::Leave( KErrEof );
       
   229         }
       
   230 
       
   231     // Read group
       
   232     if ( delayedRead )
       
   233         {
       
   234         delete iTimer; iTimer = NULL;
       
   235         iTimer = CRtpTimer::NewL( *this );
       
   236         iTimer->After( KReadTimerInterval );
       
   237         }
       
   238     else
       
   239         {
       
   240         ReadGroupHeaderL();
       
   241         ReadNextGroupFromFileL();
       
   242         }
       
   243     
       
   244     return KErrNone;
       
   245     }
       
   246 
       
   247 // -----------------------------------------------------------------------------
       
   248 // CRtpFromFile::GetClipSdpL
       
   249 // Reads SDP from a current clip. SDP is stored to meta header during recording.
       
   250 // -----------------------------------------------------------------------------
       
   251 //
       
   252 HBufC8* CRtpFromFile::GetClipSdpL()
       
   253     {
       
   254     User::LeaveIfError( iMode );
       
   255     CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC(
       
   256                                  iFile, CRtpMetaHeader::EMetaRead );
       
   257     HBufC8* sdp = metaheader->ReadSdpDataL();
       
   258     CleanupStack::PopAndDestroy( metaheader );
       
   259     return sdp;
       
   260     }
       
   261     
       
   262 // -----------------------------------------------------------------------------
       
   263 // CRtpFromFile::ReadSkippedGroup
       
   264 // Reads one RTP packet from a specified file if previous read was skipped.
       
   265 // -----------------------------------------------------------------------------
       
   266 //
       
   267 void CRtpFromFile::ReadSkippedGroup()
       
   268     {
       
   269     if ( iSkippedRead && iNextGroupPoint < LastSeekAddr() &&
       
   270          iMode != EModeNone && iFileData != NULL )
       
   271         {
       
   272         iSkippedRead = EFalse;
       
   273         iThisGroup = iNextGroupPoint;
       
   274         TRAP_IGNORE( ReadGroupHeaderL();
       
   275                      ReadNextGroupFromFileL() );
       
   276         }
       
   277     }
       
   278 
       
   279 // -----------------------------------------------------------------------------
       
   280 // CRtpFromFile::UpdateLastSeekAddr
       
   281 // Updates final last seek addres from clip write when recording stopped.
       
   282 // -----------------------------------------------------------------------------
       
   283 //
       
   284 void CRtpFromFile::UpdateLastSeekAddr()
       
   285     {
       
   286     if ( iToFile )
       
   287         {
       
   288         iDuration = iToFile->GetCurrentLength();
       
   289         iLastSeekAddr = iToFile->LastSeekAddr();
       
   290     
       
   291         LOG2( "CRtpFromFile::UpdateLastSeekAddr(), iLastSeekAddr: %d, iDuration: %d",
       
   292                                                    iLastSeekAddr, iDuration ); 
       
   293         // Recording is stopped
       
   294         iToFile = NULL;
       
   295         }
       
   296     }
       
   297 
       
   298 // -----------------------------------------------------------------------------
       
   299 // CRtpFromFile::SetSeekPointL
       
   300 // Sets the seek point of the clip.
       
   301 // -----------------------------------------------------------------------------
       
   302 //
       
   303 void CRtpFromFile::SetSeekPointL( const TUint aTime )
       
   304     {
       
   305     Cancel();
       
   306     delete iTimer; iTimer = NULL;
       
   307     delete iFileData; iFileData = NULL;
       
   308     User::LeaveIfError( iMode );
       
   309     
       
   310     // Group from the seek array, accuracy 30s
       
   311     iThisGroup = FindSeekGroup( aTime, ( iToFile )? iToFile->SeekArray(): iSeekArray );
       
   312     LOG2( "CRtpFromFile::SetSeekPointL(), aTime: %d, group from seek array: %d", 
       
   313                                           aTime, iThisGroup );
       
   314     if ( iThisGroup == KErrNotFound )
       
   315         {
       
   316         iThisGroup = iFirstSeekAddr;
       
   317         }
       
   318     ReadGroupHeaderL();
       
   319     
       
   320     // Find group basing on the seek time, accuracy 0 - 3 s
       
   321     if ( aTime > 0 )
       
   322         {
       
   323         while ( aTime > iGroupTime && iNextGroupPoint < iLastSeekAddr )
       
   324             {
       
   325             // Next group
       
   326             iThisGroup = iNextGroupPoint;
       
   327             ReadGroupHeaderL();
       
   328 #ifdef CR_ALL_LOGS
       
   329             LOG2( "CRtpFromFile::SetSeekPointL(), iThisGroup: %u, iGroupTime: %u", 
       
   330                                                   iThisGroup, iGroupTime );
       
   331 #endif // CR_ALL_LOGS
       
   332             }
       
   333         }
       
   334     
       
   335     // Prepare for next read, one extra group back looks better
       
   336     iNextGroupPoint = ( iPrevGroupPoint > iFirstSeekAddr ) ?
       
   337         iPrevGroupPoint : iThisGroup;
       
   338     delete iFileData; iFileData = NULL;
       
   339         
       
   340     LOG1( "CRtpFromFile::SetSeekPointL(), iNextGroupPoint: %d",
       
   341                                           iNextGroupPoint );
       
   342     }
       
   343 
       
   344 // -----------------------------------------------------------------------------
       
   345 // CRtpFromFile::StopRtpRead
       
   346 // Stops file reading.
       
   347 // -----------------------------------------------------------------------------
       
   348 //
       
   349 void CRtpFromFile::StopRtpRead( const TInt aStatus, const TUint aPlayerBuf )
       
   350     {
       
   351     LOG2( "CRtpFromFile::StopRtpRead(), aStatus: %d, aPlayerBuf: %u",
       
   352                                         aStatus, aPlayerBuf );
       
   353     LOG2( "CRtpFromFile::StopRtpRead(), iMode: %d, iGroupTime: %d",
       
   354                                         iMode, iGroupTime );
       
   355     Cancel();
       
   356     if ( iMode != EModeNone )
       
   357         {
       
   358         iFile.ReadCancel();
       
   359 
       
   360 #ifdef CR_ALL_LOGS
       
   361         LogVariables( _L( "StopRtpRead()" ) );
       
   362 #endif // CR_ALL_LOGS
       
   363         }
       
   364     
       
   365     delete iTimer; iTimer = NULL;
       
   366     delete iFileData; iFileData = NULL;
       
   367     if ( iMode == EModeNormal || iMode == EModeHandle )
       
   368         {
       
   369         // Try to seek back to what user sees for continue play spot
       
   370         if ( !aStatus & iThisGroup > 0 && iThisGroup < iLastSeekAddr )
       
   371             {
       
   372             const TInt thisGroup( iThisGroup );
       
   373             TRAPD( err, SetSeekPointL( iGroupTime - aPlayerBuf ) );
       
   374             if ( err )
       
   375                 {
       
   376                 LOG1( "CRtpFromFile::StopRtpRead(), SetSeekPointL Leaved: %d", err ); 
       
   377                 iThisGroup = thisGroup;
       
   378                 }
       
   379             }
       
   380         
       
   381         // Update meta header if no error
       
   382         if ( !aStatus )
       
   383             {
       
   384             TInt err ( KErrNone );
       
   385             if ( iToFile )
       
   386                 {
       
   387                 TRAP( err, iToFile->UpdatePlayAttL( iThisGroup ) );
       
   388                 }
       
   389             else
       
   390                 {
       
   391                 TRAP( err, UpdatePlayAttL() );
       
   392                 }
       
   393 
       
   394             // Possible error ignored
       
   395             if ( err )
       
   396                 {
       
   397                 LOG1( "CRtpFromFile::StopRtpRead(), UpdatePlayAttL Leaved: %d", err ); 
       
   398                 }
       
   399             }
       
   400         }
       
   401 
       
   402     iMode = EModeNone;
       
   403     iFile.Close();
       
   404     }
       
   405 
       
   406 // -----------------------------------------------------------------------------
       
   407 // CRtpFromFile::RunL
       
   408 // -----------------------------------------------------------------------------
       
   409 //
       
   410 void CRtpFromFile::RunL()
       
   411     {
       
   412     User::LeaveIfError( iStatus.Int() );
       
   413 
       
   414     // All groups readed?
       
   415     if ( iThisGroup >= iLastSeekAddr ||
       
   416        ( iNextGroupPoint >= iLastSeekAddr &&
       
   417          iToFile && iToFile->Action() == MRtpFileWriteObserver::ESavePause ) )
       
   418         {
       
   419         LOG2( "CRtpFromFile::RunL(), All groups readed ! total: %d, iDuration: %d",
       
   420                                                          iThisGroup, iDuration ); 
       
   421         iGroupTime = iDuration;
       
   422         }
       
   423     
       
   424     iReadObs.GroupReadedL( iDataPtr, iGroupTime, ( iGroupTime >= iDuration ) );
       
   425     delete iFileData; iFileData = NULL;
       
   426     }
       
   427     
       
   428 // -----------------------------------------------------------------------------
       
   429 // CRtpFromFile::RunError
       
   430 // -----------------------------------------------------------------------------
       
   431 //
       
   432 TInt CRtpFromFile::RunError( TInt aError )
       
   433     {
       
   434     LOG1( "CRtpFromFile::RunError(), RunL Leaved: %d", aError );
       
   435 
       
   436     iReadObs.ReadStatus( aError );
       
   437     StopRtpRead( aError, 0 );
       
   438     return KErrNone;
       
   439     }
       
   440  
       
   441 // -----------------------------------------------------------------------------
       
   442 // CRtpFromFile::DoCancel
       
   443 // -----------------------------------------------------------------------------
       
   444 //
       
   445 void CRtpFromFile::DoCancel()
       
   446     {
       
   447     LOG( "CRtpFromFile::DoCancel()" );
       
   448     }
       
   449 
       
   450 // -----------------------------------------------------------------------------
       
   451 // CRtpFromFile::TimerEventL
       
   452 // Internal timer call this when triggered.
       
   453 // -----------------------------------------------------------------------------
       
   454 //
       
   455 void CRtpFromFile::TimerEventL()
       
   456     {
       
   457     LOG( "CRtpFromFile::TimerEventL() in" );
       
   458 
       
   459     ReadGroupHeaderL();
       
   460     ReadNextGroupFromFileL();
       
   461     delete iTimer; iTimer = NULL;
       
   462 
       
   463     LOG( "CRtpFromFile::TimerEventL() out" );
       
   464     }
       
   465 
       
   466 // -----------------------------------------------------------------------------
       
   467 // CRtpFromFile::TimerError
       
   468 // Internal timer call this when TimerEventL() leaves.
       
   469 // -----------------------------------------------------------------------------
       
   470 //
       
   471 void CRtpFromFile::TimerError( const TInt aError )
       
   472     {
       
   473     LOG1( "CRtpFromFile::TimerError(), TimerEventL Leaved: %d", aError );
       
   474 
       
   475     StopRtpRead( aError, 0 );
       
   476     delete iTimer; iTimer = NULL;
       
   477     }
       
   478 
       
   479 // -----------------------------------------------------------------------------
       
   480 // CRtpFromFile::ReadClipHeaderL
       
   481 // Reads meta data and seek header from the beginning of the file.
       
   482 // -----------------------------------------------------------------------------
       
   483 //
       
   484 void CRtpFromFile::ReadClipHeaderL( TInt8& aVersion )
       
   485     {
       
   486     LOG1( "CRtpFromFile::ReadClipHeaderL(), iToFile: %d", iToFile );
       
   487 
       
   488     if ( !iToFile )
       
   489         {
       
   490         TInt seekArrayPoint( KErrNotFound );
       
   491         aVersion = ReadMetaHeaderL( iSeekHeaderPoint, seekArrayPoint );
       
   492         ReadSeekHeaderL();
       
   493         
       
   494         // Read seek array if exist
       
   495         if ( seekArrayPoint > iLastSeekAddr )
       
   496             {
       
   497             ReadSeekArrayL( seekArrayPoint );
       
   498             }
       
   499         }
       
   500     else // Recording ongoing with the same clip
       
   501         {
       
   502         aVersion = KCurrentClipVersion;
       
   503         iSeekHeaderPoint = iToFile->SeekHeaderPoint();
       
   504         iGroupsTotalCount = iToFile->GroupsTotalCount();
       
   505         iFirstSeekAddr = iToFile->FirstSeekAddr();
       
   506         iLastSeekAddr = iToFile->LastSeekAddr();
       
   507         }
       
   508 
       
   509     iNextGroupPoint = iFirstSeekAddr;
       
   510     }
       
   511     
       
   512 // -----------------------------------------------------------------------------
       
   513 // CRtpFromFile::ReadMetaHeaderL
       
   514 // Reads meta data header from the beginning of the file.
       
   515 // -----------------------------------------------------------------------------
       
   516 //
       
   517 TInt8 CRtpFromFile::ReadMetaHeaderL(
       
   518     TInt& aSeekHeaderPoint,
       
   519     TInt& aSeekArrayPoint )
       
   520     {
       
   521     CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC(
       
   522                                  iFile, CRtpMetaHeader::EMetaRead );
       
   523     aSeekHeaderPoint = metaheader->SeekHeaderPoint();
       
   524     metaheader->ReadSeekArrayPointL( aSeekArrayPoint );
       
   525     LOG2( "CRtpFromFile::ReadMetaHeaderL(), aSeekHeaderPoint: %d, aSeekArrayPoint: %d",
       
   526                                             aSeekHeaderPoint, aSeekArrayPoint );
       
   527     // Clip version
       
   528     CRtpMetaHeader::SAttributes att;
       
   529     metaheader->ReadAttributesL( att );
       
   530     metaheader->ReadDurationL( iDuration );
       
   531     
       
   532     // Verify post rule
       
   533     CRtpClipManager* clipManager = CRtpClipManager::NewLC();
       
   534     clipManager->VerifyPostRuleL( att.iPostRule, metaheader );
       
   535     CleanupStack::PopAndDestroy( clipManager );
       
   536     CleanupStack::PopAndDestroy( metaheader );
       
   537     
       
   538     LOG2( "CRtpFromFile::ReadMetaHeaderL(), Version: %d, Duration: %d",
       
   539                                             att.iVersion, iDuration );
       
   540     return att.iVersion;
       
   541     }
       
   542     
       
   543 // -----------------------------------------------------------------------------
       
   544 // CRtpFromFile::ReadNextGroupFromFileL
       
   545 // Reads RTP payload from a file.
       
   546 // Payload is allways after data header, so read position set is not needed.
       
   547 // -----------------------------------------------------------------------------
       
   548 //
       
   549 void CRtpFromFile::ReadNextGroupFromFileL()
       
   550     {
       
   551     LOG2( "CRtpFromFile::ReadNextGroupFromFileL(), iThisGroup: %d, iGroupTime: %u", 
       
   552                                                    iThisGroup, iGroupTime  );
       
   553 #ifdef CR_ALL_LOGS
       
   554     LogVariables( _L( "ReadNextGroupFromFileL()" ) );
       
   555 #endif // CR_ALL_LOGS
       
   556 
       
   557     const TInt len( iGroupTotalLen - KGroupHeaderBytes );
       
   558     if ( len <= 0 || iThisGroup < iFirstSeekAddr || iThisGroup > iLastSeekAddr )
       
   559         {
       
   560 #ifdef CR_ALL_LOGS
       
   561         LogVariables( _L( "ReadNextGroupFromFileL()" ) );
       
   562 #endif // CR_ALL_LOGS
       
   563 
       
   564         LOG( "CRtpFromFile::ReadNextGroupFromFileL(), No More Groups" );
       
   565         User::Leave( KErrEof );
       
   566         }
       
   567 
       
   568     // Reading should never be active at this point
       
   569     if ( iFileData != NULL )
       
   570         {
       
   571         LOG( "CRtpFromFile::ReadNextGroupFromFileL(), Invalid usage of class !" );
       
   572         User::Leave( KErrGeneral );
       
   573         }
       
   574 
       
   575     // Start reading group
       
   576     iFileData = HBufC8::NewL( len );
       
   577     iDataPtr.Set( iFileData->Des() );
       
   578     iFile.Read( iThisGroup + KGroupHeaderBytes, iDataPtr, len, iStatus );
       
   579     SetActive();
       
   580     }
       
   581     
       
   582 // -----------------------------------------------------------------------------
       
   583 // CRtpFromFile::FindSeekGroup
       
   584 // Finds closes point with seek array, accuracy about 0 - 30 s.
       
   585 // -----------------------------------------------------------------------------
       
   586 //
       
   587 TInt CRtpFromFile::FindSeekGroup( const TUint aTime, CArrayFix<SSeek>* aArray )
       
   588     {
       
   589     if ( aArray->Count() && aTime >= aArray->At( 0 ).iTime )
       
   590         {
       
   591         for ( TInt i( aArray->Count() - 1 ); i > 0 ; i-- )
       
   592             {
       
   593 #ifdef CR_ALL_LOGS
       
   594             LOG3( "CRtpFromFile::FindSeekGroup(), ind: %d, aTime: %u, array time: %u", 
       
   595                                                   i, aTime, aArray->At( i ).iTime );
       
   596 #endif //CR_ALL_LOGS
       
   597 
       
   598             if ( aTime > aArray->At( i ).iTime )
       
   599                 {
       
   600                 return aArray->At( i ).iPoint;
       
   601                 }
       
   602             }
       
   603         
       
   604         return aArray->At( 0 ).iPoint;
       
   605         }
       
   606     
       
   607     return KErrNotFound;
       
   608     }
       
   609 
       
   610 // -----------------------------------------------------------------------------
       
   611 // CRtpFromFile::UpdatePlayAttL
       
   612 // Updates clip's playback count and spot attributes after watching.
       
   613 // -----------------------------------------------------------------------------
       
   614 //
       
   615 void CRtpFromFile::UpdatePlayAttL()
       
   616     {
       
   617     // Update attributes
       
   618     if ( iMode == EModeNormal )
       
   619         {
       
   620         iFile.Close();
       
   621         User::LeaveIfError( iFile.Open( iFs, *iCurrentPath,
       
   622                             EFileShareAny | EFileStream | EFileWrite ) );
       
   623         }
       
   624 
       
   625     CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC(
       
   626                                  iFile, CRtpMetaHeader::EMetaUpdate );
       
   627     TTime startTime( 0 );
       
   628     metaheader->ReadStartTimeL( startTime );
       
   629 
       
   630     CRtpMetaHeader::SAttributes att;
       
   631     metaheader->ReadAttributesL( att );
       
   632     
       
   633     // Step playback counter by one
       
   634     att.iPlayCount++;
       
   635     // Update play spot
       
   636     att.iPlaySpot = ( iThisGroup > 0 && iThisGroup < iLastSeekAddr )? iThisGroup:
       
   637                                                                       KErrNone;
       
   638     metaheader->WriteAttributesL( att );
       
   639     CleanupStack::PopAndDestroy( metaheader );
       
   640     LOG2( "CRtpFromFile::UpdatePlayAttL(), New play count: %d, spot: %d", 
       
   641                                            att.iPlayCount, att.iPlaySpot );
       
   642     // Set start time to file date
       
   643     iFile.SetModified( startTime );
       
   644     }
       
   645     
       
   646 // -----------------------------------------------------------------------------
       
   647 // CRtpFromFile::LastSeekAddr
       
   648 // Gets last seek addres.
       
   649 // It is either from opened clip or from file writer when recording is ongoing.
       
   650 // -----------------------------------------------------------------------------
       
   651 //
       
   652 TInt CRtpFromFile::LastSeekAddr()
       
   653     {
       
   654     if ( iToFile )
       
   655         {
       
   656         iLastSeekAddr = iToFile->LastSeekAddr();
       
   657         }
       
   658     
       
   659     return iLastSeekAddr;
       
   660     }
       
   661 
       
   662 // End of File
       
   663