dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpClipManager.cpp
changeset 0 822a42b6c3f1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpClipManager.cpp	Thu Dec 17 09:14:38 2009 +0200
@@ -0,0 +1,513 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:    Help methods for propriatary RTP format.*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <pathinfo.h>
+#include <ipvideo/CRtpClipManager.h>
+#include "CRtpClipRepairer.h"
+#include <BaUtils.h>
+#include "videoserviceutilsLogger.h"
+
+// CONSTANTS
+const TInt EContentRightsRecordingAllowed( 0 );
+const TInt EContentRightsLockToDevice( 2 );
+const TInt KMaxProgramChars( 8 );
+const TInt KFirstFileIndex( 1 );
+const TInt KMaxFileIndex( 99 );
+_LIT( KDvrClipExtension, ".rtp" );
+_LIT( KIndexFormat, "(%02d)" );
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CRtpClipManager::NewL
+// Static two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CRtpClipManager* CRtpClipManager::NewL()
+    {
+    CRtpClipManager* self = CRtpClipManager::NewLC();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CRtpClipManager::NewLC
+// Static two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CRtpClipManager* CRtpClipManager::NewLC()
+    {
+    CRtpClipManager* self = new( ELeave ) CRtpClipManager();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CRtpClipManager::CRtpClipManager
+//
+// -----------------------------------------------------------------------------
+//
+CRtpClipManager::CRtpClipManager()
+    {
+    // None
+    }
+
+// -----------------------------------------------------------------------------
+// CRtpClipManager::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CRtpClipManager::ConstructL()
+    {
+    LOG( "CRtpClipManager::ConstructL() in" );
+    
+    // IMEI
+    TName buf( KNullDesC );
+    CRtpUtil::GetImeiL( buf );
+    iImei = buf.AllocL();
+    LOG1( "CRtpClipManager::ConstructL(), IMEI: %S", &*iImei );
+
+    // File server
+    User::LeaveIfError( iFs.Connect() );
+
+    LOG( "CRtpClipManager::ConstructL() out" );
+    }
+
+// -----------------------------------------------------------------------------
+// CRtpClipManager::~CRtpClipManager
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CRtpClipManager::~CRtpClipManager()
+    {
+    LOG( "CRtpClipManager::~CRtpClipManager()" );
+
+    delete iImei;
+    iRepairQueue.ResetAndDestroy();
+    delete iClipRepairer;
+    iFile.Close();
+    iFs.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CRtpClipManager::GetClipDetailsL
+// Getter for clip details.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CRtpClipManager::GetClipDetailsL(
+    const TDesC& aClipPath,
+    SRtpClipDetails& aDetails )
+    {
+    iFile.Close();
+    TBool clipOpen( EFalse );
+    iFs.IsFileOpen( aClipPath, clipOpen );
+    User::LeaveIfError( iFile.Open( iFs, aClipPath,
+                        EFileShareAny | EFileStream | EFileRead ) );
+    CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC( 
+                                 iFile, CRtpMetaHeader::EMetaRead );
+    // Attributes
+    CRtpMetaHeader::SAttributes att;
+    metaheader->ReadAttributesL( att );
+
+    // Under version 2 clips not work any longer
+    // Recording ongoing without file open indicates interrupted recording
+    if ( att.iVersion < 2 || ( att.iOngoing && !clipOpen ) )
+        {
+        LOG3( "CRtpClipManager::GetClipDetailsL(), iVersion: %d, iOngoing: %d, clipOpen: %d",
+                                                   att.iVersion, att.iOngoing, clipOpen );
+        iFile.Close();
+        User::Leave( KErrGeneral ); 
+        }
+    
+    // Details
+    GetDetailsL( att, aDetails, metaheader );
+    CleanupStack::PopAndDestroy( metaheader );
+    iFile.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CRtpClipManager::GetClipDetailsL
+// Getter for clip details.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CRtpClipManager::GetClipDetailsL(
+    RFile& aFile,
+    SRtpClipDetails& aDetails )
+    {
+    CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC( 
+                                 aFile, CRtpMetaHeader::EMetaRead );
+    // Attributes
+    CRtpMetaHeader::SAttributes att;
+    metaheader->ReadAttributesL( att );
+    
+    // Details
+    GetDetailsL( att, aDetails, metaheader );
+    CleanupStack::PopAndDestroy( metaheader );
+    }
+
+// -----------------------------------------------------------------------------
+// CRtpClipManager::ProtectClipL
+// Protects clip from deleting automatically during recording.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CRtpClipManager::ProtectClipL(
+    const TDesC& aClipPath,
+    const TBool aProtected )
+    {
+    LOG1( "CRtpClipManager::ProtectClipL(), aClipPath: %S", &aClipPath );
+    LOG1( "CRtpClipManager::ProtectClipL(), aProtected: %d", aProtected );
+    
+    iFile.Close();
+    User::LeaveIfError( iFile.Open( iFs, aClipPath,
+                        EFileShareExclusive | EFileStream | EFileWrite ) );
+    CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC( 
+                                 iFile, CRtpMetaHeader::EMetaUpdate );
+    // Read Attributes
+    CRtpMetaHeader::SAttributes att;
+    metaheader->ReadAttributesL( att );
+    // Update protected attribute
+    if ( aProtected != att.iProtected )
+        {
+        att.iProtected = aProtected;
+        metaheader->WriteAttributesL( att );
+        }
+    
+    CleanupStack::PopAndDestroy( metaheader );
+    iFile.Close();
+    }
+    
+// -----------------------------------------------------------------------------
+// CRtpClipManager::FixMetaHeaderL
+// Fixes corrupted clip's meta header.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CRtpClipManager::FixMetaHeaderL(
+    MRtpClipRepairObserver* aObs,
+    const TDesC& aClipPath )
+    {
+    LOG( "RM-CRtpClipManager::FixMetaHeaderL()" );
+
+    iFile.Close();
+    if ( !iClipRepairer )
+        {
+        LOG1( "CRtpClipManager::FixMetaHeaderL(), Fix started: %S", &aClipPath );
+        AddClipToRepairQueueL( aClipPath );
+        iClipRepairer = CRtpClipRepairer::NewL( aObs );
+        iClipRepairer->CheckMetaHeaderL( aClipPath );
+        }
+    else
+        {
+        // Verify that not exist in queue
+        TInt loop( iRepairQueue.Count() - 1 );
+        for ( ; loop >= 0; loop-- )
+            {
+            if ( !aClipPath.CompareC( iRepairQueue[loop]->Des() ) )
+                {
+                break;
+                }
+            }
+
+        // Add to queue
+        if ( loop < 0 )
+            {
+            LOG1( "CRtpClipManager::FixMetaHeaderL(), Fix queued: %S", &aClipPath );
+            AddClipToRepairQueueL( aClipPath );
+            }
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CRtpClipManager::FixMetaHeaderL
+// Fixes corrupted clip's meta header syncronously.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CRtpClipManager::FixMetaHeaderL( const TDesC& aClipPath )
+    {
+    LOG1( "CRtpClipManager::FixMetaHeaderL(), aClipPath: %S", &aClipPath );
+
+    iFile.Close();
+    delete iClipRepairer; iClipRepairer = NULL;
+    iClipRepairer = CRtpClipRepairer::NewL( NULL );
+    iClipRepairer->CheckMetaHeaderL( aClipPath );
+    }
+    
+// -----------------------------------------------------------------------------
+// CRtpClipManager::DeleteRtpRepairer
+// Kills clip repairer after work done.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CRtpClipManager::DeleteRtpRepairer( MRtpClipRepairObserver* aObs )
+    {
+    // Remove handled name from the queue first
+    iFile.Close();
+    TInt last( iRepairQueue.Count() - 1 );
+    if ( last > KErrNotFound && iClipRepairer &&
+         !iRepairQueue[last]->Des().Compare( iClipRepairer->CurrentClipName() ) )
+        {
+        delete iRepairQueue[last];
+        iRepairQueue[last] = NULL;
+        iRepairQueue.Remove( last );
+        }
+
+    // Repairer must be deleted in any case
+    delete iClipRepairer; iClipRepairer = NULL;
+    TInt err( KErrNotFound );
+    last = iRepairQueue.Count() - 1;
+    LOG1( "CRtpClipManager::DeleteRtpRepairer(), queue count: %d", iRepairQueue.Count() );
+    
+    while ( last > KErrNotFound && err )
+        {
+        // Create new repairer and start it
+        TPath path( iRepairQueue[last]->Des() );
+        TRAP( err, iClipRepairer = CRtpClipRepairer::NewL( aObs ) );
+        if ( !err )
+            {
+            TRAP( err, iClipRepairer->CheckMetaHeaderL( path ) );
+            if ( err )
+                {
+                LOG1( "CRtpClipManager::DeleteRtpRepairerL(), CheckMetaHeaderL Leaved: %d", err );
+
+                // Remove clip which can't be repaired from the queue
+                delete iRepairQueue[last];
+                iRepairQueue[last] = NULL;
+                iRepairQueue.Remove( last );
+                
+                // Ready for the next clip
+                last = iRepairQueue.Count() - 1;
+                delete iClipRepairer; iClipRepairer = NULL;
+                }
+            }
+        else
+            {
+            LOG1( "CRtpClipManager::DeleteRtpRepairerL(), No memory for new repairer: %d", err );
+            break;
+            }
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CRtpClipManager::VerifyPostRuleL
+// Verifies post acqusition rule of clip.
+// -----------------------------------------------------------------------------
+//
+TInt CRtpClipManager::VerifyPostRuleL(
+    const TUint8 aPostRule,
+    CRtpMetaHeader* aMetaHeader )
+    {
+    LOG( "CRtpClipManager::VerifyPostRule()" );
+
+    switch ( aPostRule )
+        {
+        case EContentRightsRecordingAllowed:
+            LOG( "CRtpClipManager::VerifyPostRule(), EContentRightsRecordingAllowed !" );
+            break;
+        
+        case EContentRightsLockToDevice:
+            {
+            TName imei( KNullDesC );
+            aMetaHeader->ReadDeviceInfoL( imei );
+            if ( !iImei || imei.Compare( iImei->Des() ) )
+                {
+                LOG( "CRtpClipManager::VerifyPostRule(), EContentRightsLockToDevice" );
+                LOG1( "CRtpClipManager::VerifyPostRule(), ERmPlayDeviceLockError: %S", &imei );
+                LOG1( "CRtpClipManager::VerifyPostRule(), Phone's IMEI: %S", &*iImei );
+                return KErrAccessDenied;
+                }
+            }
+            break;
+        
+        default:
+            LOG1( "RM-CRtpClipManager::VerifyPostRule(), Default case: %d", aPostRule );
+            break;
+        }
+    
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRtpClipManager::GetDetailsL
+// Updates details from meta header attributes.
+// -----------------------------------------------------------------------------
+//
+void CRtpClipManager::GetDetailsL(
+    const CRtpMetaHeader::SAttributes& aAttributes,
+    SRtpClipDetails& aDetails,
+    CRtpMetaHeader* aMetaHeader )
+    {
+    aDetails.iRecOngoing = aAttributes.iOngoing;
+    aDetails.iCompleted = aAttributes.iCompleted;
+    aDetails.iProtected = aAttributes.iProtected;
+    aDetails.iFailed = aAttributes.iFailed;
+    aDetails.iQuality = aAttributes.iQuality;
+    aDetails.iPlayCount = aAttributes.iPlayCount;
+    aDetails.iPlaySpot = aAttributes.iPlaySpot;
+    aDetails.iParental = aAttributes.iParental;
+    
+    LOG1( "CRtpClipManager::GetDetailsL(), iRecOngoing: %d", aDetails.iRecOngoing );
+    LOG1( "CRtpClipManager::GetDetailsL(), iCompleted: %d", aDetails.iCompleted );
+    LOG1( "CRtpClipManager::GetDetailsL(), iProtected: %d", aDetails.iProtected );
+    LOG1( "CRtpClipManager::GetDetailsL(), iFailed: %d", aDetails.iFailed );
+    LOG1( "CRtpClipManager::GetDetailsL(), iQuality: %d", aDetails.iQuality );
+    LOG1( "CRtpClipManager::GetDetailsL(), iPlayCount: %d", aDetails.iPlayCount );
+    LOG1( "CRtpClipManager::GetDetailsL(), iPlaySpot: %d", aDetails.iPlaySpot );
+    LOG1( "CRtpClipManager::GetDetailsL(), iParental: %d", aDetails.iParental );
+
+    // ESG
+    aMetaHeader->ReadEsgDataL( aDetails.iService, aDetails.iProgram );
+    LOG1( "CRtpClipManager::GetDetailsL(), iService: %S", &aDetails.iService );
+    LOG1( "CRtpClipManager::GetDetailsL(), iProgram: %S", &aDetails.iProgram );
+    
+    // Start time
+    aMetaHeader->ReadStartTimeL( aDetails.iStartTime );
+    
+    // End time
+    aMetaHeader->ReadEndTimeL( aDetails.iEndTime );
+
+#if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
+    TName time( KNullDesC ); aDetails.iEndTime.FormatL( time, KTimeDateFormat );
+    LOG1( "CRtpClipManager::GetDetailsL(), End time: %S", &time );
+#endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
+
+    // Duration
+    aMetaHeader->ReadDurationL( aDetails.iDuration );
+    LOG1( "CRtpClipManager::GetDetailsL(), iDuration: %d", aDetails.iDuration );
+    aDetails.iDuration/= 1000; // convert to seconds
+
+    // Post acquisition
+    aDetails.iPostRuleOk = !VerifyPostRuleL( aAttributes.iPostRule, aMetaHeader );
+    LOG1( "CRtpClipManager::GetDetailsL(), iPostRuleOk: %d", aDetails.iPostRuleOk );
+    }
+
+// -----------------------------------------------------------------------------
+// CRtpClipManager::NewClipRootL
+// Root path of the new clip, depends on user media setting.
+// If memory card is selected, but not available, default saving to phone memory.
+// -----------------------------------------------------------------------------
+//
+void CRtpClipManager::NewClipRootL( TDes& aClipPath, const TDriveNumber aDrive )
+    {
+    // Begin of the save path
+    if ( aDrive == EDriveC )
+        {
+        aClipPath = PathInfo::PhoneMemoryRootPath();
+        aClipPath.Append( PathInfo::VideosPath() );
+        }
+    else
+        {
+        aClipPath = PathInfo::MemoryCardRootPath();
+        aClipPath.Append( PathInfo::VideosPath() );
+        }
+    
+    // Verify and create path if not exist
+    if ( !BaflUtils::PathExists( iFs, aClipPath ) )
+        {
+        TInt err( iFs.MkDirAll( aClipPath ) );
+        if ( err && aDrive != EDriveC )
+            {
+            LOG1( "CRtpClipManager::NewClipRootL(), Forced to Use Phone Memory !", err );
+
+            // Memorycard not acceptable -> Use phone memory
+            err = KErrNone;
+            aClipPath = PathInfo::PhoneMemoryRootPath();
+            aClipPath.Append( PathInfo::VideosPath() );
+            BaflUtils::EnsurePathExistsL( iFs, aClipPath );
+            }
+        
+        User::LeaveIfError( err );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRtpClipManager::NewIndexNameL
+// Creates new clip name from program name (eigth first letters + index).
+// If program name allready in use, adds indexing to the end of name.
+// -----------------------------------------------------------------------------
+//
+void CRtpClipManager::NewIndexNameL( TDes& aClipPath, const TDesC& aProgram )
+    {
+    LOG1( "CRtpClipManager::NewIndexNameL(), aClipPath  : %S", &aClipPath );
+    LOG1( "CRtpClipManager::NewIndexNameL(), aProgram   : %S", &aProgram );
+
+    // Remove special characters
+    TBuf<KMaxProgramChars> program( aProgram.Left( KMaxProgramChars ) );
+    for ( TInt i( program.Length() - 1 ); i >= 0; i-- )
+        {
+        TChar letter( program[i] );
+        // Remove if not alpha nor space
+        if ( !letter.IsAlphaDigit() && !letter.IsSpace() )
+            {
+            program.Delete( i, 1 );
+            }
+        }
+    program.TrimRight();
+    
+    TInt index( KFirstFileIndex );
+    
+    // Test name for existing clip check
+    TPath testName( aClipPath );
+    if ( program.Length() )
+        {
+        testName.Append( program );
+        }
+    else
+        {
+        // Zero length program name, start from "(01).rtp"
+        testName.AppendFormat( KIndexFormat, index++ );        
+        }
+
+    // Name already used ?
+    testName.Append( KDvrClipExtension );
+    if ( BaflUtils::FileExists( iFs, testName ) )
+        {
+        do
+            {
+            LOG1( "CRtpClipManager::NewIndexNameL(), Clip exist: %S", &testName );
+            
+            // Abort if file index exceeds "(99)"
+            User::LeaveIfError( ( index > KMaxFileIndex ) * KErrOverflow );
+            
+            // New test name
+            testName.Copy( aClipPath );
+            testName.Append( program );
+            testName.AppendFormat( KIndexFormat, index++ );
+            testName.Append( KDvrClipExtension );
+            }
+            while ( BaflUtils::FileExists( iFs, testName ) );
+        }
+    
+    // Return suitable filename
+    aClipPath.Copy( testName );
+    }
+    
+// -----------------------------------------------------------------------------
+// CRtpClipManager::AddClipToRepairQueueL
+// Inserts new clip name to the first in queue.
+// -----------------------------------------------------------------------------
+//
+void CRtpClipManager::AddClipToRepairQueueL( const TDesC& aClipPath )
+    {
+    HBufC* clip = aClipPath.AllocLC();
+    User::LeaveIfError( iRepairQueue.Insert( clip, 0 ) );
+    CleanupStack::Pop( clip );
+    }
+
+// End of File
+