diff -r 000000000000 -r 7f85d04be362 upnpsharing/upnpdlnaprofiler/src/upnpresresolver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/upnpsharing/upnpdlnaprofiler/src/upnpresresolver.cpp Thu Dec 17 08:52:00 2009 +0200 @@ -0,0 +1,440 @@ +/* +* Copyright (c) 2006-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: Implementation file of CUpnpResResolver class. +* CUpnpResResolver is a class used for resolving res field +* attributes for a given file. +* +*/ + + + + + + +// system includes +#include // RFile +#include // RApaLsSession +#include // CUpnpDlnaProtocolInfo +#include // CImageDecoder +#include // ContentAccess +#include <3gplibrary/mp4lib.h> // MP4ParseRequestAudioDescription +#include // EscapeUtils::ConvertFromUnicodeToUtf8L + +// user includes +#include "upnpresresolver.h" +#include "upnpdlnaprofiler.h" +#include "upnpresparameters.h" + +_LIT( KComponentLogfile, "dlnaprofiler.txt"); +#include "upnplog.h" + +// constants +_LIT8( KHttpGet8, "http-get" ); +_LIT8( KStar8, "*" ); + +const TInt KMicrosecondsInSecond = 1000000; +const TInt KMilliSecondsInSecond = 1000; + +// ======== LOCAL FUNCTIONS ======== +// NONE + +// ======== MEMBER FUNCTIONS ======== + +// -------------------------------------------------------------------------- +// CUpnpResResolver C++ constructor +// -------------------------------------------------------------------------- +// +CUpnpResResolver::CUpnpResResolver() : iDuration(0) + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver constructor" ); + } + + +// -------------------------------------------------------------------------- +// CUpnpResResolver::ConstructL +// -------------------------------------------------------------------------- +// +void CUpnpResResolver::ConstructL() + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::ConstructL" ); + } + + +// -------------------------------------------------------------------------- +// CUpnpResResolver::NewL +// -------------------------------------------------------------------------- +// +EXPORT_C CUpnpResResolver* CUpnpResResolver::NewL() + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::NewL" ); + CUpnpResResolver* self = CUpnpResResolver::NewLC(); + CleanupStack::Pop( self ); + return self; + } + + +// -------------------------------------------------------------------------- +// CUpnpResResolver::NewLC +// -------------------------------------------------------------------------- +// +EXPORT_C CUpnpResResolver* CUpnpResResolver::NewLC() + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::NewLC" ); + CUpnpResResolver* self = new( ELeave ) CUpnpResResolver; + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + + +// -------------------------------------------------------------------------- +// CUpnpResResolver destructor +// -------------------------------------------------------------------------- +// +CUpnpResResolver::~CUpnpResResolver() + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver destructor" ); + } + + +// -------------------------------------------------------------------------- +// CUpnpResResolver::GetResParametersL +// -------------------------------------------------------------------------- +// +EXPORT_C CUpnpResParameters* CUpnpResResolver::GetResParametersL( + const TDesC& aFilename ) + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetResParametersL" ); + // check that aFileName is reasonable + if ( aFilename.Length() <= 0 ) + { + User::Leave( KErrArgument ); + } + + // Create object that will be returned. + CUpnpResParameters* retval = CUpnpResParameters::NewLC(); + + // try to open file specified by aFileName + RFs fsSession; + User::LeaveIfError( fsSession.Connect() ); // connect session + CleanupClosePushL( fsSession ); + // without calling ShareProtected() RApaLsSession::RecognizeData + // does not work (leaves with KErrBadHandle). + fsSession.ShareProtected(); + + RFile file; + User::LeaveIfError( file.Open( fsSession, + aFilename, + EFileShareReadersOrWriters|EFileRead ) ); + CleanupClosePushL( file ); + + // Obtain mimetype of the file + HBufC8* mimetype = GetMimetypeL( file ); + CleanupStack::PushL( mimetype ); + retval->SetMimetypeL( *mimetype ); + + // Obtain file size + TInt filesize = GetFileSizeL( file ); + retval->SetFileSize( filesize ); + + // Obtain duration for video&audio files and resolution for images. + TSize imageResolution( KErrNotFound, KErrNotFound ); + if ( mimetype->Left( KMimeStartLength ).Compare( KVideo() ) == 0 ) + { + GetVideoDurationL( file ); + retval->SetDurationInSeconds( iDuration.Int64() ); + } + else if ( mimetype->Left( KMimeStartLength ).Compare( KAudio() ) == 0 ) + { + GetAudioDurationL( aFilename ); + retval->SetDurationInSeconds( + iDuration.Int64() / KMicrosecondsInSecond ); + } + else if ( mimetype->Left( KMimeStartLength ).Compare( KImage() ) == 0 ) + { + TRAPD( err, imageResolution = GetImageResolutionL( file, + *mimetype ) ); + if ( !err ) + { + retval->SetResolution( imageResolution ); + } + } + + // Construct CUpnpDlnaProtocolInfo object. + CUpnpDlnaProtocolInfo* protocolInfo = CUpnpDlnaProtocolInfo::NewL(); + CleanupStack::PushL( protocolInfo ); + protocolInfo->SetFirstFieldL( KHttpGet8() ); + protocolInfo->SetSecondFieldL( KStar8() ); + protocolInfo->SetThirdFieldL( *mimetype ); + + // Obtain DLNA Profile ID + CUpnpDlnaProfiler* profiler = CUpnpDlnaProfiler::NewLC(); + HBufC* PnParameter = NULL; + TRAPD( profileErr, + PnParameter = profiler->ProfileForFileL( aFilename, + file, + *retval ) ); + CleanupStack::PopAndDestroy( profiler ); + + if ( PnParameter && !profileErr ) + { + // Set DLNA Profile name (PN parameter) + CleanupStack::PushL( PnParameter ); + HBufC8* profileName8bit = + EscapeUtils::ConvertFromUnicodeToUtf8L( *PnParameter ); + CleanupStack::PushL( profileName8bit ); + protocolInfo->SetPnParameterL( *profileName8bit ); + CleanupStack::PopAndDestroy( profileName8bit ); + + // OP parameter is always the same in our CDS. + protocolInfo->SetOpParameterL( + UpnpDlnaProtocolInfo::KDEFAULT_DLNA_OP ); + + // Set Flags according to file type. + if ( mimetype->Left( KMimeStartLength ).Compare( KVideo() ) == 0 ) + { + protocolInfo->SetFlagsParameterL( + UpnpDlnaProtocolInfo::KDEFAULT_DLNA_FLAGS_AV ); + } + else if + ( mimetype->Left( KMimeStartLength ).Compare( KAudio() ) == 0 ) + { + protocolInfo->SetFlagsParameterL( + UpnpDlnaProtocolInfo::KDEFAULT_DLNA_FLAGS_AUDIO ); + } + else if + ( mimetype->Left( KMimeStartLength ).Compare( KImage() ) == 0 ) + { + protocolInfo->SetFlagsParameterL( + UpnpDlnaProtocolInfo::KDEFAULT_DLNA_FLAGS_IMAGE ); + } + + CleanupStack::PopAndDestroy( PnParameter ); + } + + retval->SetProtocolInfoL( protocolInfo->ProtocolInfoL() ); + + // clean up + CleanupStack::PopAndDestroy( protocolInfo ); + CleanupStack::PopAndDestroy( mimetype ); + CleanupStack::PopAndDestroy( &file ); + CleanupStack::PopAndDestroy( &fsSession ); + CleanupStack::Pop( retval ); + return retval; + + } + + +// -------------------------------------------------------------------------- +// CUpnpResResolver::GetMimetypeL +// -------------------------------------------------------------------------- +// +HBufC8* CUpnpResResolver::GetMimetypeL( RFile& aFile ) + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetMimetypeL" ); + HBufC8* retval = NULL; + // Create an AppArc server session for mime type recognition + RApaLsSession sess; + User::LeaveIfError( sess.Connect() ); + CleanupClosePushL( sess ); + + // Try to get mime type from AppArc server + TDataRecognitionResult mimeResult; + User::LeaveIfError( sess.RecognizeData( aFile, mimeResult ) ); + + // close session handle + CleanupStack::PopAndDestroy( &sess ); + + // Data recognition done. Check results. + retval = mimeResult.iDataType.Des8().AllocL(); + return retval; + } + + +// -------------------------------------------------------------------------- +// CUpnpResResolver::GetVideoDurationL +// -------------------------------------------------------------------------- +// +void CUpnpResResolver::GetVideoDurationL( RFile& aFile ) + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetVideoDurationL" ); + mp4_u32 videolength = 0; + mp4_double framerate = 0; + mp4_u32 videotype = 0; + mp4_u32 videowidth = 0; + mp4_u32 videoheight = 0; + mp4_u32 timescale = 0; + + MP4Handle myMp4Handle; + + // try open mp4 file handle + MP4Err openerr = MP4ParseOpenFileHandle( &myMp4Handle, &aFile ); + switch ( openerr ) + { + case MP4_OK : + { + // obtain necessary information from file + MP4Err requesterr = MP4ParseRequestVideoDescription( + myMp4Handle, + &videolength, + &framerate, + &videotype, + &videowidth, + &videoheight, + ×cale ); + + // close mp4 file handle + MP4Err closeerr = MP4ParseClose( myMp4Handle ); + if ( closeerr || requesterr ) + { + User::Leave( KErrGeneral ); + } + } + break; + case MP4_ERROR : + { + User::Leave( KErrGeneral ); + } + break; + case MP4_OUT_OF_MEMORY : + { + User::Leave( KErrNoMemory ); + } + break; + case MP4_FILE_ERROR : + { + User::Leave( KErrAccessDenied ); + } + break; + default : + User::Leave( KErrGeneral ); + break; + } + // videolength in milliseconds + iDuration = videolength/KMilliSecondsInSecond; + } + +// -------------------------------------------------------------------------- +// CUpnpResResolver::GetAudioDurationL +// -------------------------------------------------------------------------- +// +void CUpnpResResolver::GetAudioDurationL( const TDesC& aFilename ) + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetAudioDurationL" ); + + // create audioplayer if it does not exist + if ( !iAudioplayer ) + { + iAudioplayer = CMdaAudioPlayerUtility::NewL( *this ); + } + + // Create iWait if it does not exist. Create it here rather than after + // OpenL-call so that there will be no problems if somehow OpenFileL + // calls MapcInitComplete-callback before iWait is created and started. + if ( !iWait ) + { + iWait = new( ELeave ) CActiveSchedulerWait; + } + + // Open file specified in aFilename. This is an asynchronic operation. + // Calls MapcInitComplete callback after completed. + iAudioplayer->OpenFileL( aFilename ); + + // start CActiveSchedulerWait which is completed in MapcInitComplete + iWait->Start(); + + // clean up + delete iAudioplayer; + iAudioplayer = NULL; + + delete iWait; + iWait = NULL; + } + + +// -------------------------------------------------------------------------- +// CUpnpResResolver::GetFileSizeL +// -------------------------------------------------------------------------- +// +TInt CUpnpResResolver::GetFileSizeL( RFile& aFile ) + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetFileSizeL" ); + TInt retval = KErrNone; + User::LeaveIfError( aFile.Size( retval ) ); + return retval; + } + + +// -------------------------------------------------------------------------- +// CUpnpResResolver::GetImageResolutionL +// -------------------------------------------------------------------------- +// +TSize CUpnpResResolver::GetImageResolutionL( RFile& aFile, + const TDesC8& aMimetype ) + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetImageResolutionL" ); + CImageDecoder* imageDecoder = NULL; + TRAPD( createError, imageDecoder = CImageDecoder::FileNewL( + aFile, + aMimetype, + ContentAccess::EPeek ) ); + + if ( createError ) + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetImageResolutionL \ +CreateError" ); + User::Leave( createError ); + } + + CleanupStack::PushL( imageDecoder ); + TSize imageResolution = imageDecoder->FrameInfo().iOverallSizeInPixels; + CleanupStack::PopAndDestroy( imageDecoder ); + + return imageResolution; + } + +// -------------------------------------------------------------------------- +// From class MMdaAudioPlayerCallback. +// MapcPlayComplete callback (not used) +// -------------------------------------------------------------------------- +// +void CUpnpResResolver::MapcPlayComplete( TInt /*aError*/ ) + { + //this callback is not needed + } + +// -------------------------------------------------------------------------- +// From class MMdaAudioPlayerCallback. +// MapcInitComplete callback is called after a call to +// CMdaAudioConvertUtility::OpenL has completed. +// -------------------------------------------------------------------------- +// +void CUpnpResResolver::MapcInitComplete( + TInt aError, + const TTimeIntervalMicroSeconds& aDuration ) + { + __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::MapcInitComplete" ); + + // if opening was successful, save duration to member variable + if( KErrNone == aError ) + { + iDuration = aDuration; + } + + // continue execution in GetAudioDurationL-method by stopping + // ActiveSchedulerWait + iWait->AsyncStop(); + } + +// end of file