diff -r 000000000000 -r a2952bb97e68 mmappcomponents/playbackhelper/src/streaminglinkmodel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmappcomponents/playbackhelper/src/streaminglinkmodel.cpp Thu Dec 17 08:55:47 2009 +0200 @@ -0,0 +1,739 @@ +/* +* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: Implementation of CStreamingLinkModel +* +*/ + +// Version : %version: 4 % + + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include + +#ifdef RD_MULTIPLE_DRIVE +#include +#endif //RD_MULTIPLE_DRIVE + +#include "playbackhelper_log.h" + +// CONSTANTS +const TInt KLocalFileIdLength(5); +const TInt KMaxLinkFileSize(5120); //5kB +const TInt KBothSlashes(2); +#ifndef RD_MULTIPLE_DRIVE +const TInt KDriveLetter(2); +#endif //RD_MULTIPLE_DRIVE + +_LIT( KLocalFileId, "file:"); +_LIT( KSlash, "/" ); +_LIT( KDoubleSlash, "//" ); +_LIT( KBackSlash, "\\" ); + +// ============================ MEMBER FUNCTIONS =================================================== + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::CStreamingLinkModel +// C++ default constructor can NOT contain any code, that +// might leave. +// ------------------------------------------------------------------------------------------------- +// +CStreamingLinkModel::CStreamingLinkModel() +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::CStreamingLinkModel()")); +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::ConstructL +// Symbian 2nd phase constructor can leave. +// ------------------------------------------------------------------------------------------------- +// +void CStreamingLinkModel::ConstructL() +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::ConstructL()")); + + User::LeaveIfError( iFs.Connect() ); +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::NewL +// Two-phased constructor. +// ------------------------------------------------------------------------------------------------- +// +EXPORT_C CStreamingLinkModel* CStreamingLinkModel::NewL() +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::NewL()")); + + CStreamingLinkModel* self = new( ELeave ) CStreamingLinkModel(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + return self; +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::~CStreamingLinkModel +// Destructor +// ------------------------------------------------------------------------------------------------- +// +EXPORT_C CStreamingLinkModel::~CStreamingLinkModel() +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::~CStreamingLinkModel()")); + + for ( TInt i = 0 ; i < iLinkArray.Count() ; i++ ) + { + delete iLinkArray[i]->link; + } + + iLinkArray.ResetAndDestroy(); + + iFileHandle.Close(); + iFs.Close(); +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::OpenLinkFileL +// ------------------------------------------------------------------------------------------------- +// +EXPORT_C TInt CStreamingLinkModel::OpenLinkFileL( const TDesC& aLinkFileName, + TBool aEnableFiltering ) +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::OpenLinkFileL()")); + + // + // exit if file is not found + // + if ( !BaflUtils::FileExists( iFs, aLinkFileName ) ) + { + User::Leave( KErrNotFound ); + } + + // + // open via file name + // + RFile ramFile; + TInt err = ramFile.Open( iFs, aLinkFileName, EFileRead | EFileShareReadersOnly ); + + if( err ) + { + err = ramFile.Open( iFs, aLinkFileName, EFileRead | EFileShareAny ); + } + + CleanupClosePushL( ramFile ); + + // + // populate the links + // + TInt result = PopulateRamLinksL( ramFile, aEnableFiltering ); + + CleanupStack::PopAndDestroy(); //ramFile + + return result; +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::OpenLinkFileL +// ------------------------------------------------------------------------------------------------- +// +EXPORT_C TInt CStreamingLinkModel::OpenLinkFileL( RFile& aFile, + TBool aEnableFiltering ) +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::OpenLinkFileL()")); + + RFile ramFile; + + if ( FileHandleExists(aFile) ) + { + iFileHandle.Close(); + User::LeaveIfError( iFileHandle.Duplicate( aFile ) ); + User::LeaveIfError( ramFile.Duplicate( iFileHandle ) ); + CleanupClosePushL( ramFile ); + } + else + { + User::Leave( KErrNotFound ); + } + + // + // populate the links + // + TInt result = PopulateRamLinksL( ramFile, aEnableFiltering ); + + CleanupStack::PopAndDestroy(); //ramFile + + return result; +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::MaxLinkLength +// ------------------------------------------------------------------------------------------------- +// +EXPORT_C TInt CStreamingLinkModel::MaxLinkLength() +{ + TInt length = 0; + + for ( TInt index = 0; index < iLinkArray.Count(); index++) + { + length = length + iLinkArray[index]->link->Length(); + } + + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::MaxLinkLength() max length = [%d] "), length ); + + return length; +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::GetNextLinkL +// ------------------------------------------------------------------------------------------------- +// +EXPORT_C TInt CStreamingLinkModel::GetNextLinkL( TDes& aLink, TBool& aLocalFile, TBool aParse ) +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::GetNextLinkL()") ); + + aLocalFile = EFalse; + TInt ret = KErrNone; + + if ( iLinkCount < iLinkArray.Count() ) + { + aLink = iLinkArray[iLinkCount]->link->Des(); + iLinkCount++; + + // local file --> parse it. + if ( aParse && !aLink.Left( KLocalFileIdLength ).CompareF( KLocalFileId ) ) + { + // remove "file:" + aLocalFile = ETrue; + aLink = aLink.Mid( KLocalFileIdLength ); + + // remove extra '/' from begin + while ( !aLink.Left( 1 ).CompareF( KSlash ) ) + { + aLink = aLink.Mid( 1 ); + } + + // change "//" and "/" inside body to "\" + TInt index = aLink.FindF( KDoubleSlash ); + while ( index != KErrNotFound ) + { + aLink.Replace( index, KBothSlashes, KBackSlash ); + index = aLink.FindF( KDoubleSlash ); + } + + index = aLink.FindF( KSlash ); + + while ( index != KErrNotFound ) + { + aLink.Replace( index, 1, KBackSlash ); + index = aLink.FindF( KSlash ); + } + } + } + else + { + ret = KErrNotFound; + } + + return ret; +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::IsSeekable +// ------------------------------------------------------------------------------------------------- +// +EXPORT_C TBool CStreamingLinkModel::IsSeekable() +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::IsSeekable()") ); + + TBool ret = ETrue; + + // link count has been incremented in the GetNextlink + if ( iLinkCount <= iLinkArray.Count() ) + { + ret = iLinkArray[iLinkCount-1]->seek; + } + + return ( ret ); +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::ReadNextLine +// ------------------------------------------------------------------------------------------------- +// +TInt CStreamingLinkModel::ReadNextLine( TDes& aLine ) +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::ReadNextLine()")); + + TInt ret = KErrNone; + TInt lineChange = iBufferPtr.LocateF( EKeyLineFeed ); + + if ( lineChange == KErrNotFound ) + { + // No line change was found --> last line had no line change + // Copy last line to (unicode) aLink + CnvUtfConverter::ConvertToUnicodeFromUtf8( aLine, iBufferPtr ); + ret = KErrEof; + } + else + { + //Found line change + TInt length = lineChange; + if ( ( length > 0 ) && ( iBufferPtr[length-1] == EKeyEnter ) ) + { + length--; + } + + // Copy line to (unicode) aLink + CnvUtfConverter::ConvertToUnicodeFromUtf8( aLine, iBufferPtr.Left( length ) ); + + // Move past the line feed + iBufferPtr.Set( iBufferPtr.Mid( ++lineChange ) ); + + if ( !iBufferPtr.Length() ) + { + // File end reached. + ret = KErrEof; + } + } + + return ret; +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::CreateNewLinkFileL +// ------------------------------------------------------------------------------------------------- +// +EXPORT_C TInt CStreamingLinkModel::CreateNewLinkFileL( const TDesC& aNewLinkFileName, + MDesCArray* aLinkArray, + TBool aOverWrite ) +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::CreateNewLinkFileL()")); + + TInt result = KErrNone; + + // check if file exists already + if ( !aOverWrite && BaflUtils::FileExists( iFs, aNewLinkFileName ) ) + { + result = KErrAlreadyExists; + } + else + { + //check disk space + TInt bytesRequired = 0; + TInt index = 0; + + for ( index = 0; index < aLinkArray->MdcaCount(); index++ ) + { + bytesRequired = bytesRequired + aLinkArray->MdcaPoint( index ).Size(); + } + + TParsePtrC parse(aNewLinkFileName); + +#ifdef RD_MULTIPLE_DRIVE + DriveInfo::TDriveArray driveArray; + TInt drive = 0; + + RFs::CharToDrive( parse.Drive()[0], drive ); + + //check disk space + if( SysUtil::DiskSpaceBelowCriticalLevelL( &iFs, bytesRequired, drive ) ) + { + result = KErrDiskFull; + } +#else //RD_MULTIPLE_DRIVE + if( parse.Drive().CompareF( PathInfo::MemoryCardRootPath().Left( KDriveLetter ) ) == 0 ) + { + if ( SysUtil::MMCSpaceBelowCriticalLevelL( &iFs, bytesRequired ) ) + { + result = KErrDiskFull; + } + } + else if ( SysUtil::FFSSpaceBelowCriticalLevelL( &iFs, bytesRequired ) ) + { + User::Leave( KErrDiskFull ); + } +#endif //RD_MULTIPLE_DRIVE + + if ( result == KErrNone ) + { + // save + RFile file; + User::LeaveIfError( file.Replace( iFs, aNewLinkFileName, EFileWrite ) ); + CleanupClosePushL( file ); + + for ( index = 0; result == KErrNone && index < aLinkArray->MdcaCount(); index++ ) + { + // Convert to ascii. Some special marks like '? might take 1-3 letters. + HBufC8* link = HBufC8::NewLC( aLinkArray->MdcaPoint( index ).Length() * 3 + 1 ); + TPtr8 ptr = link->Des(); + CnvUtfConverter::ConvertFromUnicodeToUtf8( ptr, aLinkArray->MdcaPoint( index ) ); + ptr.Append( EKeyLineFeed ); + + // write to file + result = file.Write( ptr ); + + CleanupStack::PopAndDestroy( link ); + } + + file.Flush(); + CleanupStack::PopAndDestroy(); // file + + } + } + + return result; +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::FreeFilehandle +// ------------------------------------------------------------------------------------------------- +// +EXPORT_C void CStreamingLinkModel::FreeFilehandle() +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::FreeFilehandle()")); + + iFileHandle.Close(); +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::FileHandleExists +// ------------------------------------------------------------------------------------------------- +// +TBool CStreamingLinkModel::FileHandleExists( RFile& aFile ) +{ + TInt size = 0; + TInt err = KErrNone; + TBool exist = EFalse; + + if ( aFile.SubSessionHandle() ) + { + err = aFile.Size( size ); + } + + if ( !err && size ) + { + exist = ETrue; + } + + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::FileHandleExists() exist = [%d]"), exist); + + return exist; +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::MaxLinkLength +// ------------------------------------------------------------------------------------------------- +// +EXPORT_C TInt CStreamingLinkModel::MultiLinksCount() +{ + TInt cnt = iLinkArray.Count(); + + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::MultiLinksCount() count = [%d]"), cnt); + + return cnt; +} + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::ResetLinkCount +// ------------------------------------------------------------------------------------------------- +// +EXPORT_C void CStreamingLinkModel::ResetLinkCount() +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::ResetLinkCount()")); + + iLinkCount = 0; +} + +// ----------------------------------------------------------------------------- +// CStreamingLinkModel::OpenAsxFileL +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CStreamingLinkModel::OpenAsxFileL( const TDesC& aLinkFileName, + TBool aEnableFiltering ) +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::OpenAsxFileL(%S,%d)"), + &aLinkFileName,aEnableFiltering); + TInt result = KErrNone; + +#ifdef __WINDOWS_MEDIA + + CAsxParser* asxParser = NULL; + TRAPD( err, + { + asxParser = CAsxParser::NewL( aLinkFileName ); + } ); //TRAPD + + if ( err ) + { + result = KErrNotSupported; + } + else + { + CleanupStack::PushL( asxParser ); + result = PopulateAsxLinksL( asxParser, aEnableFiltering ); + CleanupStack::PopAndDestroy(); // asxParser + } + + +#else // __WINDOWS_MEDIA + + result = KErrNotSupported; + +#endif // __WINDOWS_MEDIA + + return result; +} + +// ----------------------------------------------------------------------------- +// CStreamingLinkModel::OpenAsxFileL +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CStreamingLinkModel::OpenAsxFileL( RFile& aFile, + TBool aEnableFiltering ) +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::OpenAsxFileL(aFile,%d)"),aEnableFiltering); + + TInt result = KErrNone; + +#ifdef __WINDOWS_MEDIA + + CAsxParser* asxParser = NULL; + TRAPD( err, + { + asxParser = CAsxParser::NewL( aFile ); + } ); //TRAPD + + if ( err ) + { + result = KErrNotSupported; + } + else + { + CleanupStack::PushL( asxParser ); + result = PopulateAsxLinksL( asxParser, aEnableFiltering ); + CleanupStack::PopAndDestroy(); // asxParser + } + + +#else // __WINDOWS_MEDIA + + result = KErrNotSupported; + +#endif // __WINDOWS_MEDIA + + return result; +} + +// ----------------------------------------------------------------------------- +// CStreamingLinkModel::PopulateRamLinksL +// ----------------------------------------------------------------------------- +// +TInt CStreamingLinkModel::PopulateRamLinksL( RFile aRamFile, + TBool aEnableFiltering ) +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::PopulateRamLinksL()")); + + for ( TInt i = 0 ; i < iLinkArray.Count() ; i++ ) + { + delete iLinkArray[i]->link; + } + + iLinkArray.ResetAndDestroy(); + iLinkCount = 0; + + TInt size = 0; + TInt result = KErrNone; + + if ( aRamFile.Size( size ) == KErrNone && size <= KMaxLinkFileSize ) + { + HBufC8* buffer = HBufC8::NewLC( size ); + TPtr8 ptr = buffer->Des(); + TInt ret = KErrNone; + + // read file to buffer + User::LeaveIfError( aRamFile.Read( ptr ) ); + iBufferPtr.Set( ptr ); + + CMediaRecognizer* recognizer = CMediaRecognizer::NewL(); + CleanupStack::PushL( recognizer ); + + // Get links from buffer + while ( ret == KErrNone ) + { + // Create a linkitem ptr + LinkStruct* linkItem = new( ELeave ) LinkStruct; + CleanupStack::PushL( linkItem ); + + linkItem->seek = ETrue; + + linkItem->link = HBufC::NewLC( buffer->Length() ); + TPtr ptr2 = linkItem->link->Des(); + ret = ReadNextLine( ptr2 ); + + if ( aEnableFiltering ) + { + // check if line is link or not + if ( recognizer->IsValidUrlPrefix( ptr2 ) ) + { + ptr2.TrimRight(); + iLinkArray.Append( linkItem ); + } + } + else + { + iLinkArray.Append( linkItem ); + } + + CleanupStack::Pop(2); // pop the linkItem and the HbufC created for linkItem->link + } + + CleanupStack::PopAndDestroy(2); // buffer, recognizer + + if ( iLinkArray.Count() == 0 ) + { + result = KErrNotFound; + } + } + else + { + result = KErrNotSupported; + } + + return result; +} + +// ----------------------------------------------------------------------------- +// CStreamingLinkModel::PopulateAsxLinksL +// ----------------------------------------------------------------------------- +// +TInt CStreamingLinkModel::PopulateAsxLinksL( CAsxParser* aAsxParser, + TBool aEnableFiltering ) +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::PopulateAsxLinksL()")); + + for ( TInt i = 0 ; i < iLinkArray.Count() ; i++ ) + { + delete iLinkArray[i]->link; + } + + iLinkArray.ResetAndDestroy(); + iLinkCount = 0; + + TInt ret = KErrNone; + + if ( aAsxParser ) + { + TUint urlCount = 0; + AsxStruct* asxItem; + + aAsxParser->GetUrlCount( urlCount ); + if ( urlCount ) + { + CMediaRecognizer* recognizer = CMediaRecognizer::NewL(); + CleanupStack::PushL( recognizer ); + + for (TInt i=1; i <= urlCount; i++) + { + // Get the asx struct from the parser + asxItem = aAsxParser->GetUrl(i); + // Set the url to the bufferptr + iBufferPtr.Set(asxItem->url->Des()); + + // Create a linkitem ptr + LinkStruct* linkItem = new( ELeave ) LinkStruct; + // push onto the cleanup stack + CleanupStack::PushL( linkItem ); + + // Allocate heap mem for the link + linkItem->link = HBufC::NewLC( asxItem->url->Length() ); + //Get the ptr to the link + TPtr ptr2 = linkItem->link->Des(); + // read the asx url into the link ptr + ReadNextLine( ptr2 ); + + // Get the additional attibutes from the asx item + linkItem->seek = asxItem->seek; + + if ( aEnableFiltering ) + { + // check if line is link or not + if ( recognizer->IsValidUrlPrefix( ptr2 ) ) + { + ptr2.TrimRight(); + iLinkArray.Append( linkItem ); + } + } + else + { + iLinkArray.Append( linkItem ); + } + + CleanupStack::Pop(2); // pop the linkItem and the HbufC created for linkItem->link + + } + + CleanupStack::PopAndDestroy(); //recognizer + } + else + { + ret = KErrNotFound; + } + + if ( iLinkArray.Count() == 0 ) + { + ret = KErrNotFound; + } + } + else + { + ret = KErrNotSupported; + } + + return ret; + } + +// ------------------------------------------------------------------------------------------------- +// CStreamingLinkModel::AreAllLinksLocal +// returns true if all the links are local +// ------------------------------------------------------------------------------------------------- +// +EXPORT_C TBool CStreamingLinkModel::AreAllLinksLocal() +{ + PLAYBACKHELPER_DEBUG(_L("CStreamingLinkModel::AreAllLinksLocal()") ); + + TBool ret = ETrue; + + if ( iLinkArray.Count() ) + { + for ( TInt linkCount = 0 ; linkCount < iLinkArray.Count() ; linkCount++ ) + { + TPtr aLink = ( iLinkArray[linkCount]->link )->Des(); + + if ( aLink.Left( KLocalFileIdLength ).CompareF( KLocalFileId ) ) + { + ret = EFalse; + break; + } + } + } + + return ret; +} + +// End of File