diff -r 000000000000 -r 7f85d04be362 upnpavcontroller/upnpavcontrollerhelper/src/upnpdownloaditemresolver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/upnpavcontroller/upnpavcontrollerhelper/src/upnpdownloaditemresolver.cpp Thu Dec 17 08:52:00 2009 +0200 @@ -0,0 +1,596 @@ +/* +* 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 "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: Resolver for downloading remote items +* +*/ + + + + + + +// INCLUDE FILES +// System +#include +#include + +// upnp stack api's +#include +#include +#include +#include // for getting resource protocol info +#include // for resolving object mimetype + +// upnpframework / avcontroller api +#include "upnpavcontroller.h" // avcontrol services +#include "upnpavdevice.h" // avcontroller device class +#include "upnpavbrowsingsession.h" // avcontrol browsing session +#include "upnpfiledownloadsession.h" // avcontrol download session + +// upnpframework / avcontroller helper api +#include "upnpconstantdefs.h" // for element names +#include "upnpitemutility.h" // for FindAttributeByName +#include "upnpresourceselector.h" // MUPnPResourceSelector +#include "upnpitemresolverobserver.h" // observer for this class +#include "upnpdlnautility.h" // IsSupportedDlnaProfile + +// upnpframework / internal api's +#include "upnpcommonutils.h" // for FileExtensionByMimeTypeL +#include "upnpsettingsengine.h" // get selected download location + +// avcontroller helper internal +#include "upnpremoteitemresolver.h" // remote item resolver impl. +#include "upnpdownloaditemresolver.h" // download item resolver impl. + +_LIT( KComponentLogfile, "upnpavcontrollerhelper.txt"); +#include "upnplog.h" + +// CONSTANTS +_LIT( KTempPrefix, "upnpfwtemp"); + +// METHODS + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::NewL +//--------------------------------------------------------------------------- +CUPnPDownloadItemResolver* CUPnPDownloadItemResolver::NewL( + const TDesC8& aItemId, + MUPnPAVController& aAvController, + MUPnPAVBrowsingSession& aHostSession, + MUPnPResourceSelector& aSelector, + const TDesC8& aBrowseFilter ) + { + CUPnPDownloadItemResolver* self = new (ELeave) CUPnPDownloadItemResolver( + aItemId, aAvController, aHostSession, aSelector, aBrowseFilter ); + CleanupStack::PushL( self ); + self->ConstructL( + aItemId, aAvController, aHostSession, aSelector, aBrowseFilter ); + CleanupStack::Pop( self ); + return self; + } + + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::CUPnPDownloadItemResolver +//--------------------------------------------------------------------------- +CUPnPDownloadItemResolver::CUPnPDownloadItemResolver( + const TDesC8& /*aItemId*/, + MUPnPAVController& aAvController, + MUPnPAVBrowsingSession& /*aHostSession*/, + MUPnPResourceSelector& aSelector, + const TDesC8& /*aBrowseFilter*/ ) + : iAvController( aAvController ), + iState( EStateIdle ),iSelector(aSelector) + { + + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::ConstructL +//--------------------------------------------------------------------------- +void CUPnPDownloadItemResolver::ConstructL( + const TDesC8& aItemId, + MUPnPAVController& /*aAvController*/, + MUPnPAVBrowsingSession& aHostSession, + MUPnPResourceSelector& aSelector, + const TDesC8& aBrowseFilter ) + { + iRemoteResolver = CUPnPRemoteItemResolver::NewL( + aItemId, aHostSession, aSelector, aBrowseFilter ); + iRemoteDevice = CUpnpAVDevice::NewL( aHostSession.Device() ); + iSettingsEngine = CUPnPSettingsEngine::NewL(); + + // Open File Server session + User::LeaveIfError( iFsSession.Connect() ); + User::LeaveIfError( iFsSession.ShareProtected() ); + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::~CUPnPDownloadItemResolver +//--------------------------------------------------------------------------- +CUPnPDownloadItemResolver::~CUPnPDownloadItemResolver() + { + Cleanup(); + delete iRemoteResolver; + iRemoteResolver = 0; + delete iRemoteDevice; + iRemoteDevice= 0; + delete iSettingsEngine; + iSettingsEngine = 0; + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::ResolveL +//--------------------------------------------------------------------------- +void CUPnPDownloadItemResolver::ResolveL( + MUPnPItemResolverObserver& aObserver ) + { + __LOG( "DownloadItemResolver:Resolve()" ); + __ASSERTD( iState == EStateIdle, __FILE__, __LINE__ ); + + // change state + iObserver = &aObserver; + + // first resolve the item + iRemoteResolver->ResolveL( *this ); + iState = EStateResolving; + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::ResolveComplete +//--------------------------------------------------------------------------- +void CUPnPDownloadItemResolver::ResolveComplete( + const MUPnPItemResolver& /*aResolver*/, TInt aError ) + { + __LOG1( "DownloadItemResolver:ResolveComplete(%d)", aError ); + __ASSERTD( iState == EStateResolving, __FILE__, __LINE__ ); + + if ( aError == KErrNone ) + { + TRAP( aError, + const CUpnpElement& res = + iSelector.SelectResourceL( iRemoteResolver->Item() ); + IsLocallySupportedL( res ); + ); + if( aError ) + { + Complete( aError ); + } + else + { + TRAPD( err, InitiateDownloadL() ); + if ( err != KErrNone ) + { + Complete( err ); + } + } + } + else + { + Complete( aError ); + } + + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::InitiateDownloadL +//--------------------------------------------------------------------------- +void CUPnPDownloadItemResolver::InitiateDownloadL() + { + __LOG( "CUPnPDownloadItemResolver::InitiateDownloadL"); + // start a download session if not already started + if( !iDownloadSession ) + { + iDownloadSession = + &iAvController.StartDownloadSessionL( *iRemoteDevice ); + } + iDownloadSession->SetObserver( *this ); + + // Get selected download location. + HBufC* copyLocation = GetSelectedDownloadLocationL(); + CleanupStack::PushL( copyLocation ); + _LIT(KTempFolder, "temp\\"); + // Create temp file name + HBufC* tempFileName = CreateTmpFileNameL(); + CleanupStack::PushL( tempFileName ); + + // Create and save full file path. + if( iLocalFile ) + { + // delete if already allocated. + delete iLocalFile; + iLocalFile = 0; + } + + iLocalFile = HBufC::NewL( copyLocation->Length() + + KTempFolder().Length() ); + iLocalFile->Des().Append( *copyLocation ); + iLocalFile->Des().Append( KTempFolder ); + //check the existence of the target folder + if( !BaflUtils::FolderExists( iFsSession, *iLocalFile ) ) + { + User::LeaveIfError( iFsSession.MkDirAll( *iLocalFile ) ); + } + + User::LeaveIfError( iFsSession.SetAtt( *iLocalFile, + KEntryAttHidden, + KEntryAttNormal ) ); + + iLocalFile = iLocalFile->ReAllocL( + iLocalFile->Length() + tempFileName->Length() ); + + iLocalFile->Des().Append( *tempFileName ); + + // write the file path into the item + CUpnpElement& writableRes = + const_cast( iRemoteResolver->Resource() ); + writableRes.SetFilePathL( *iLocalFile ); + CleanupStack::PopAndDestroy( tempFileName ); + CleanupStack::PopAndDestroy( copyLocation ); + + // Create local target file for dowload item + TInt err = CreateRFile( *iLocalFile ); + + if( err == KErrNone ) + { + __LOG( "StartDownloading..."); + // initiate download + + iDownloadSession->StartDownloadL( writableRes, + iRemoteResolver->Item(), + iFile, + (TInt)this ); + + iState = EStateDownloading; + } + else // Create download target failed! + { + __LOG( "Create download target failed!"); + User::Leave( err ); + } + __LOG( "CUPnPDownloadItemResolver::InitiateDownloadL -End"); + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::TransferStarted +//--------------------------------------------------------------------------- +void CUPnPDownloadItemResolver::TransferStarted( TInt /*aKey*/, + TInt /*aStatus*/ ) + { + __LOG( "DownloadItemResolver:TransferStarted"); + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::TransferCompleted +//--------------------------------------------------------------------------- +void CUPnPDownloadItemResolver::TransferCompleted( TInt /*aKey*/, + TInt aStatus, const TDesC& /*aFilePath*/ ) + { + __LOG1( "DownloadItemResolver:TransferCompleted(%d)", aStatus ); + iFile.Close(); + Complete( aStatus ); + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::TransferProgress +//--------------------------------------------------------------------------- +void CUPnPDownloadItemResolver::TransferProgress( TInt /*aKey*/, + TInt /*aBytes*/, TInt /*aTotalBytes*/ ) + { + __LOG( "DownloadItemResolver:TransferProgress"); + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::MediaServerDisappeared +//--------------------------------------------------------------------------- +void CUPnPDownloadItemResolver::MediaServerDisappeared( + TUPnPDeviceDisconnectedReason /*aReason*/ ) + { + __LOG( "DownloadItemResolver:MediaServerDisappeared" ); + Complete( KErrDisconnected ); + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::Item +//--------------------------------------------------------------------------- +const CUpnpItem& CUPnPDownloadItemResolver::Item() const + { + __ASSERTD( iState == EStateReady, __FILE__, __LINE__ ); + + return iRemoteResolver->Item(); + } + + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::Resource +//--------------------------------------------------------------------------- +const CUpnpElement& CUPnPDownloadItemResolver::Resource() const + { + __ASSERTD( iState == EStateReady, __FILE__, __LINE__ ); + + return iRemoteResolver->Resource(); + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::DeleteTempFilesL +// -------------------------------------------------------------------------- +EXPORT_C void CUPnPDownloadItemResolver::DeleteTempDownloadFilesL() + { + __LOG("CUPnPDownloadItemResolver::DeleteTempDownloadFilesL begin"); + + RFs fs; + User::LeaveIfError( fs.Connect() ); + CleanupClosePushL( fs ); + + CFileMan* fileMan = CFileMan::NewL( fs ); + CleanupStack::PushL( fileMan ); + _LIT( KAnyChar, "*"); + _LIT( KAnyExtension, "*.*"); + _LIT( KUpnpUploadTempDirectory, "temp\\" ); + + // clean selected download directory + HBufC* path = HBufC::NewLC( KMaxFileName ); + CUPnPSettingsEngine* settingsEngine = CUPnPSettingsEngine::NewL(); + CleanupStack::PushL( settingsEngine ); + HBufC* copyLocation = HBufC::NewL( KMaxFileName ); + CleanupStack::PushL( copyLocation ); + TBool copyLocationIsPhoneMemory = 0; // not used in this case + TPtr copyLocationPtr( copyLocation->Des() ); + settingsEngine->GetCopyLocationL( copyLocationPtr, + copyLocationIsPhoneMemory ); + path->Des().Append( *copyLocation ); + path->Des().Append( KAnyChar ); + path->Des().Append( KTempPrefix ); + path->Des().Append( KAnyExtension ); + fileMan->Delete( *path ); + + path->Des().Zero(); + path->Des().Append( *copyLocation ); + path->Des().Append( KUpnpUploadTempDirectory ); + path->Des().Append( KAnyExtension ); + fileMan->Delete( *path ); + + CleanupStack::PopAndDestroy( copyLocation ); + CleanupStack::PopAndDestroy( settingsEngine ); + CleanupStack::PopAndDestroy( path ); + + CleanupStack::PopAndDestroy( fileMan ); + CleanupStack::PopAndDestroy( &fs ); + + __LOG("CUPnPDownloadItemResolver::DeleteTempDownloadFilesL End"); + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::Complete +//--------------------------------------------------------------------------- +void CUPnPDownloadItemResolver::Complete( TInt aError ) + { + __ASSERTD( iState == EStateResolving || iState == EStateDownloading, + __FILE__, __LINE__ ); + + if ( iDownloadSession != 0 ) + { + iAvController.StopDownloadSession( *iDownloadSession ); + iDownloadSession = 0; + } + + MUPnPItemResolverObserver& observer = *iObserver; + iObserver = 0; + if ( aError == KErrNone ) + { + iState = EStateReady; + } + else + { + iState = EStateIdle; + Cleanup(); + } + + observer.ResolveComplete( *this, aError ); + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::Cleanup +//--------------------------------------------------------------------------- +void CUPnPDownloadItemResolver::Cleanup() + { + iObserver = 0; + iFile.Close(); + + if ( iDownloadSession != 0 ) + { + iAvController.StopDownloadSession( *iDownloadSession ); + iDownloadSession = 0; + } + + if ( iLocalFile ) + { + // delete the local file + iFsSession.Delete( iLocalFile->Des() ); + __LOG1( "DownloadItemResolver: deleted local file(%d)", iLocalFile ); + delete iLocalFile; + iLocalFile = 0; + } + + iFsSession.Close(); + + iState = EStateIdle; + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::CreateTmpFileNameL +//--------------------------------------------------------------------------- +HBufC* CUPnPDownloadItemResolver::CreateTmpFileNameL() + { + __LOG( "DownloadItemResolver::CreateTmpFileName" ); + __ASSERTD( iState == EStateResolving, __FILE__, __LINE__ ); + + HBufC* tempfilename = NULL; + HBufC* fileExt = NULL; + + // Get file extension + const CUpnpAttribute* attr = UPnPItemUtility + ::FindAttributeByName( iRemoteResolver->Resource(), + KAttributeProtocolInfo ); + if ( attr != 0 ) + { + CUpnpDlnaProtocolInfo* pInfo = + CUpnpDlnaProtocolInfo::NewL( attr->Value() ); + CleanupStack::PushL( pInfo ); + fileExt = UPnPCommonUtils::FileExtensionByMimeTypeL( + pInfo->ThirdField() ); + CleanupStack::PopAndDestroy( pInfo ); + pInfo = NULL; + } + + // If file extension exist create whole file name. + if( fileExt ) + { + CleanupStack::PushL( fileExt ); + tempfilename = HBufC::NewL( + KTempPrefix().Length() + + iRemoteResolver->Item().Id().Length() + + fileExt->Length() ); + CleanupStack::PushL( tempfilename ); + // Add prefix + tempfilename->Des().Append( KTempPrefix ); + // Add item name. Convert 8 to 16 and replace illeagal characters. + HBufC8* tmpItemName8 = + UPnPCommonUtils::ReplaceIllegalFilenameCharactersL( + iRemoteResolver->Item().Id() ); + CleanupStack::PushL( tmpItemName8 ); + HBufC* itemname = HBufC::NewL( tmpItemName8->Length() ); + CleanupStack::PushL( itemname ); + itemname->Des().Copy( *tmpItemName8 ); + tempfilename->Des().Append( *itemname ); + CleanupStack::PopAndDestroy( itemname ); + CleanupStack::PopAndDestroy( tmpItemName8 ); + // Add file extension + tempfilename->Des().Append( *fileExt ); + + CleanupStack::Pop( tempfilename ); + CleanupStack::PopAndDestroy( fileExt ); + } + else // Create without file extension + { + tempfilename = HBufC::NewL( + KTempPrefix().Length() + iRemoteResolver->Item().Id().Length() ); + CleanupStack::PushL( tempfilename ); + // Add prefix + tempfilename->Des().Append( KTempPrefix ); + // Add item name. Convert 8 to 16 and replace illeagal characters. + HBufC8* tmpItemName8 = + UPnPCommonUtils::ReplaceIllegalFilenameCharactersL( + iRemoteResolver->Item().Id() ); + CleanupStack::PushL( tmpItemName8 ); + HBufC* itemname = HBufC::NewL( tmpItemName8->Length() ); + CleanupStack::PushL( itemname ); + itemname->Des().Copy( *tmpItemName8 ); + tempfilename->Des().Append( *itemname ); + CleanupStack::PopAndDestroy( itemname ); + CleanupStack::PopAndDestroy( tmpItemName8 ); + + CleanupStack::Pop( tempfilename ); + } + + return tempfilename; //transfer ownership + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::GetSelectedDownloadLocationL +//--------------------------------------------------------------------------- +HBufC* CUPnPDownloadItemResolver::GetSelectedDownloadLocationL() + { + __LOG( "DownloadItemResolver::GetSelectedDownloadLocationL" ); + + HBufC* copyLocation = HBufC::NewL( KMaxFileName ); + CleanupStack::PushL( copyLocation ); + TBool copyLocationIsPhoneMemory = 0; + TPtr copyLocationPtr( copyLocation->Des() ); + TRAPD( error, iSettingsEngine->GetCopyLocationL( + copyLocationPtr, copyLocationIsPhoneMemory ) ) + + // Something wrong in getting copy location. Default to + // phone memory. + if( error != KErrNone ) + { + TPtrC phoneDrive( PathInfo::PhoneMemoryRootPath() ); + copyLocation->Des().Append( phoneDrive ); + } + + CleanupStack::Pop( copyLocation ); + return copyLocation; + } + +// ----------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::CreateRFile +// ----------------------------------------------------------------------------- +// +TInt CUPnPDownloadItemResolver::CreateRFile( const TDesC& aFilePath ) + { + __LOG( "DownloadItemResolver::CreateRFile" ); + iFile.Close(); + + // In some special case, the function Replace() will fail + // with error -14(KErrInUse) by using 'EFileWrite' mode. + // Maybe some other handler does not close the file. + TInt err = iFile.Replace( + iFsSession, + aFilePath, + EFileShareReadersOrWriters ); + + if( KErrPathNotFound == err ) + { + __LOG( "Directory not available -> create new" ); + iFsSession.MkDirAll( aFilePath ); + err = iFile.Create( iFsSession, aFilePath, EFileWrite ); + } + return err; + } + +// -------------------------------------------------------------------------- +// CUPnPDownloadItemResolver::IsLocallySupportedL() +// Check if the audio is DLNA supported in remote to local playback +// -------------------------------------------------------------------------- +// +void CUPnPDownloadItemResolver::IsLocallySupportedL( const CUpnpElement& aRes ) + { + const CUpnpAttribute* attr = + &UPnPItemUtility::FindAttributeByNameL( + aRes, KAttributeProtocolInfo ); + // parse protocol info + CUpnpDlnaProtocolInfo* pInfo = NULL; + pInfo = CUpnpDlnaProtocolInfo::NewL( attr->Value() ); + + //if DLNA compliant item + if ( pInfo->PnParameter() != KNullDesC8() ) + { + if( !UPnPDlnaUtility::IsSupportedDlnaProfile( + pInfo->PnParameter() ) ) + { + User::Leave(KErrNotSupported); + } + } + else //if not, check MIME type + { + if( !UPnPDlnaUtility::IsSupportedMimeType( pInfo->ThirdField() ) ) + { + User::Leave(KErrNotSupported); + } + + } + } + + +