diff -r 6369bfd1b60d -r 08b5eae9f9ff upnpmpxplugins/upnpplaybackplugins/src/upnptrack.cpp --- a/upnpmpxplugins/upnpplaybackplugins/src/upnptrack.cpp Mon Nov 01 13:44:24 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,754 +0,0 @@ -/* -* 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: Class for containing and obtaining music track-specific data -* from media server -* -*/ - - - - - - -// INCLUDES -#include -#include -#include -#include -#include -#include -#include // for messaging -#include // for messaging - -#include // for unicode conversion - -#include -#include -#include "upnpitemutility.h" // for FindElementByName & ResourceFromItemL -#include "upnpfileutility.h" // for IsFileProtectedL -#include "upnpconstantdefs.h" // browse filtering and item element names -#include // for resolving object mimetype -#include "upnpavcontroller.h" -#include "upnpavbrowsingsession.h" -#include "upnpavdevice.h" -#include "upnpavdevicelist.h" - -#include "upnpitemresolverobserver.h" // MUPnPItemResolverObserver -#include "upnpitemresolverfactory.h" // factory class -#include "upnpitemresolver.h" // MUPnPItemResolver - -#include "upnptrackobserver.h" -#include "upnptrack.h" - -_LIT( KComponentLogfile, "musicplugins.txt"); -#include "upnplog.h" - -// CONSTANTS -_LIT16( KUPnPPrefix, "upnp:" ); // Prefix for separate local/remote song -const TInt KUPnPPrefixLength = 5; -const TInt KCharCodeColon = 58; -const TInt KCharCodeSeparate = 42; -const TInt InitialTrackDuration = 1; -_LIT( KTimeFormatYearOnly, "%F%Y" ); - -// ======== MEMBER FUNCTIONS ======== - -// -------------------------------------------------------------------------- -// CUPnPTrack::NewL -// 1st phase constructor. -// -------------------------------------------------------------------------- -// -CUPnPTrack* CUPnPTrack::NewL( MUPnPAVController& aAvController ) - { - __LOG( "CUPnPTrack::NewL" ); - CUPnPTrack* self = new( ELeave ) CUPnPTrack( aAvController ); - return self; - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::Delete -// deletor -// -------------------------------------------------------------------------- -// -void CUPnPTrack::Delete() - { - __LOG1( "CUPnPTrack::Delete, state=%d", iState ); - if ( iState == EStateResolving ) - { - // asynchronous delete - will be deleted after - // asynchronous operation is complete. This is because the - // S60 command can not be cancelled - iState = EStateSelfDestruct; - } - else - { - delete this; - } - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::CUPnPTrack -// Default constructor. -// -------------------------------------------------------------------------- -// -CUPnPTrack::CUPnPTrack( MUPnPAVController& aAvController ) - : iAvController( aAvController ) - , iQueriedAttributes() - { - iBrowsingSession = NULL; - iOriginalURI = NULL; - iMediaServer = NULL; - iObjectId = NULL; - iTrackObserver = NULL; - // Use initial duration value (1). It will guarantee that in - // case were remote device does not support duration query and playback - // is unpaused, SetPosition is called with real value even - // if remote player does not return real value for getposition - // call. Note that SetPosition(0) is used when user really wants - // to move to track beginning. - iTrackDuration = InitialTrackDuration; - iIsItemSolved = EFalse; - iState = EStateIdle; - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::~CUPnPTrack -// destructor. -// -------------------------------------------------------------------------- -// -CUPnPTrack::~CUPnPTrack() - { - __LOG( "CUPnPTrack::~CUPnPTrack()" ); - StopBrowsingSession(); - - // Free memory of owned members - delete iOriginalURI; - delete iMediaServer; - delete iObjectId; - delete iItemResolver; - iItemResolver = 0; - __LOG( "CUPnPTrack::~CUPnPTrack End" ); - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::ResolveURIL -// Resolve local / remote URI. -// -------------------------------------------------------------------------- -// -void CUPnPTrack::ResolveURIL( const TDesC& aCodedTrackUri, - MUPnPTrackObserver& aTrackObserver, - TPlaybackDirection aPlaybackDirection ) - { - __LOG( "CUPnPTrack::ResolveURI" ); - - delete iOriginalURI; - iOriginalURI = 0; - delete iMediaServer; - iMediaServer = 0; - delete iObjectId; - iObjectId = 0; - iTrackObserver = &aTrackObserver; - - // Either local to remote or remote to remote - if( aPlaybackDirection == EDirectionRemote ) - { - if( aCodedTrackUri.Find( KUPnPPrefix ) == 0 ) - { - // track is located in remote - iTrackLocation = ETrackLocationRemote; - // parse and save media server id and object id - ParsePiecesL( aCodedTrackUri ); - // start a browsing session - StartBrowsingSessionL(); - // create resolver - iItemResolver = - UPnPItemResolverFactory::NewRemoteItemResolverL( - *iObjectId, *iBrowsingSession, - iDefaultSelector, KFilterCommon ); - } - else // Local stored. Save URI to local member - { - // track is located in local file system - iTrackLocation = ETrackLocationLocal; - // store original URI - iOriginalURI = HBufC::NewL( aCodedTrackUri.Length() ); - iOriginalURI->Des().Copy( aCodedTrackUri ); - // check for DRM protection - if ( UPnPFileUtility::IsFileProtectedL( iOriginalURI->Des() ) ) - { - // call back directly with an error code - iTrackObserver->ResolveURIComplete( KErrNotSupported ); - return; - } - else - { - // create resolver. - iItemResolver = - UPnPItemResolverFactory::NewLocalItemResolverL( - *iOriginalURI, iAvController, iFirstSelector, - UPnPItemResolverFactory::EOmitDrmCheck ); - } - } - } - else // Remote to local direction - { - // track is located in remote - iTrackLocation = ETrackLocationRemote; - // parse and save media server id and object id - ParsePiecesL( aCodedTrackUri ); - // start a browsing session - StartBrowsingSessionL(); - // create resolver - iItemResolver = - UPnPItemResolverFactory::NewDownloadItemResolverL( - *iObjectId, iAvController, *iBrowsingSession, - iFirstSelector, KFilterCommon ); - } - - // Resolve remote item. Calls back to ResolveComplete - iState = EStateResolving; - TRAPD( e, iItemResolver->ResolveL( *this ); ) - if ( e != KErrNone ) - { - if ( iState == EStateSelfDestruct ) - { - __LOG( "CUPnPTrack: self-destructing" ); - delete this; - } - else - { - iState = EStateIdle; - User::Leave( e ); - } - } - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::StartBrowsingSessionL -// Finds the apropriate mediaserver and starts a browsing session -// -------------------------------------------------------------------------- -// -void CUPnPTrack::StartBrowsingSessionL() - { - // Get list of media servers - CUpnpAVDeviceList* devices = iAvController.GetMediaServersL(); - CleanupStack::PushL( devices ); - - // Find out index of wanted media server from media server list - TInt index = KErrNotFound; - TInt count = devices->Count(); - - for( TInt i = 0; i < count; i++ ) - { - // If media server id match. - if( !iMediaServer->Compare( (*devices)[ i ]->Uuid() ) ) - { - index = i; - break; - } - } - - // Leave if media server does not find by id - if( index == KErrNotFound ) - { - __LOG1( "CUPnPTrack: Media server not found: %S", - iMediaServer ); - User::Leave( KErrNotFound ); - } - - // start a browsing session - iBrowsingSession = &iAvController.StartBrowsingSessionL( - *(*devices)[ index ] ); - CleanupStack::PopAndDestroy( devices ); - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::StopBrowsingSession -// Finds the apropriate mediaserver and starts a browsing session -// -------------------------------------------------------------------------- -// -void CUPnPTrack::StopBrowsingSession() - { - // Stop browsing session if exist. - if( iBrowsingSession ) - { - __LOG( "Stop browsing session" ); - iAvController.StopBrowsingSession( *iBrowsingSession ); - iBrowsingSession = 0; - } - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::URI -// Return original URI of track. -// -------------------------------------------------------------------------- -// -const TDesC& CUPnPTrack::URI() const - { - __ASSERTD( iOriginalURI != 0,__FILE__, __LINE__ ); - return *iOriginalURI; - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::UpnpURI -// Return True UPNP URI of track. -// -------------------------------------------------------------------------- -// -const TDesC8& CUPnPTrack::UpnpURI() const - { - __ASSERTD( iIsItemSolved,__FILE__, __LINE__ ); - return iItemResolver->Resource().Value(); - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::UpnpItem -// Return True UPNP item representing the track -// -------------------------------------------------------------------------- -// -const CUpnpItem& CUPnPTrack::UpnpItem() const - { - __ASSERTD( iIsItemSolved,__FILE__, __LINE__ ); - return iItemResolver->Item(); - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::FilePath -// Returns the file path of local item -// -------------------------------------------------------------------------- -// -const TDesC& CUPnPTrack::FilePath() const - { - __ASSERTD( iTrackLocation == ETrackLocationRemote, __FILE__, __LINE__ ); - __ASSERTD( iIsItemSolved,__FILE__, __LINE__ ); - return iItemResolver->Resource().FilePath(); - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::IsRemote -// Return location of track. ETrue = remote. EFalse = local -// -------------------------------------------------------------------------- -// -TBool CUPnPTrack::IsRemote() const - { - return iTrackLocation == ETrackLocationRemote; - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::TrackDuration -// returns duration of the track -// -------------------------------------------------------------------------- -// -TInt CUPnPTrack::TrackDuration() - { - __LOG1( "CUPnPTrack::TrackDuration duration: %d", iTrackDuration ); - TInt ms = InitialTrackDuration; - if ( iTrackDuration > InitialTrackDuration ) - { - ms = iTrackDuration; - } - else if ( iIsItemSolved ) - { - const CUpnpAttribute* attr = UPnPItemUtility - ::FindAttributeByName( iItemResolver->Resource(), - KAttributeDuration ); - if ( attr != 0 ) - { - if ( UPnPItemUtility::UPnPDurationAsMilliseconds( - attr->Value(), ms ) == KErrNone ) - { - // store duration for quicker future queries - iTrackDuration = ms; - __LOG1( "store duration: %d", iTrackDuration ); - } - } - } - return ms; - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::SetTrackDuration -// overrides duration of the track -// -------------------------------------------------------------------------- -// -void CUPnPTrack::SetTrackDuration( TInt aMilliseconds ) - { - iTrackDuration = aMilliseconds; - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::GetMetaDataL -// Get metadata information for track from media server -// -------------------------------------------------------------------------- -// -void CUPnPTrack::GetMetaDataL( const TArray& aAttrs, - MMPXPlaybackPluginObserver& aObs ) - { - // Check if remote track - if( iTrackLocation == ETrackLocationLocal ) - { - __LOG( "CUPnPTrack::GetMetaData - No metadata for local track!" ); - User::Leave( KErrNotSupported ); - } - - if ( iIsItemSolved ) - { - __LOG( "CUPnPTrack::GetMetaDataL" ); - DeliverMedataL( aAttrs, aObs ); - } - else - { - __LOG( "CUPnPTrack::GetMetaDataL - pending" ); - iMetadataObserver = &aObs; - for( TInt i = 0; i < aAttrs.Count(); ++i ) - { - iQueriedAttributes.AppendL( aAttrs[i] ); - } - } - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::SendMediaChangedEventL -// -------------------------------------------------------------------------- -// -void CUPnPTrack::SendMediaChangedEventL( - MMPXPlaybackPluginObserver& aObs ) - { - RArray attrs; - CleanupClosePushL( attrs ); - attrs.AppendL( KMPXMediaGeneralTitle ); - attrs.AppendL( KMPXMediaMusicArtist ); - attrs.AppendL( KMPXMediaMusicAlbum ); - attrs.AppendL( KMPXMediaMusicGenre ); - attrs.AppendL( KMPXMediaGeneralDate ); - attrs.AppendL( KMPXMediaMusicYear ); - attrs.AppendL( KMPXMediaGeneralComment ); - attrs.AppendL( KMPXMediaGeneralMimeType ); - - // Create and fill CMPXMedia class - RArray suppIds; - CleanupClosePushL( suppIds ); - suppIds.AppendL( KMPXMediaIdMusic ); - suppIds.AppendL( KMPXMediaIdGeneral ); - suppIds.AppendL( KMPXMediaIdAudio ); - CMPXMedia* media = CMPXMedia::NewL( suppIds.Array() ); - CleanupStack::PopAndDestroy( &suppIds ); - CleanupStack::PushL( media ); - FillMediaFromItemL( *media, attrs.Array() ); - - // create an MPX message - CMPXMessage* msg = CMPXMessage::NewL(); - CleanupStack::PushL( msg ); - msg->SetTObjectValueL( - KMPXMessageGeneralId, KMPXMessagePbMediaChanged ); - msg->SetCObjectValueL( - KMPXMessagePbMedia, media ); - - // send message - aObs.HandlePlaybackMessage( *msg ); - - CleanupStack::PopAndDestroy( msg ); - CleanupStack::PopAndDestroy( media ); - CleanupStack::PopAndDestroy( &attrs ); - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::DeliverMedatataL -// -------------------------------------------------------------------------- -// -void CUPnPTrack::DeliverMedataL( const TArray& aAttrs, - MMPXPlaybackPluginObserver& aObs, TInt aError ) - { - __LOG( "CUPnPTrack::DeliverMedatata"); - - // Create and fill CMPXMedia class - RArray suppIds; - CleanupClosePushL( suppIds ); - suppIds.AppendL( KMPXMediaIdMusic ); - suppIds.AppendL( KMPXMediaIdGeneral ); - suppIds.AppendL( KMPXMediaIdAudio ); - CMPXMedia* media = CMPXMedia::NewL( suppIds.Array() ); - CleanupStack::PopAndDestroy( &suppIds ); - CleanupStack::PushL( media ); - - if ( aError == KErrNone ) - { - FillMediaFromItemL( *media, aAttrs ); - } - - // Return metadata - aObs.HandleMedia( *media, aError ); - CleanupStack::PopAndDestroy( media ); - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::FillMediaFromItemL -// -------------------------------------------------------------------------- -// -void CUPnPTrack::FillMediaFromItemL( CMPXMedia& aMedia, - const TArray& aAttrs ) - { - __ASSERTD( iIsItemSolved,__FILE__, __LINE__ ); - - // Fill metadata - const CUpnpElement* elem; - // Song title - if( Exists( aAttrs, KMPXMediaGeneralTitle ) ) - { - __LOG( "CUPnPTrack: Metadata: Title"); - aMedia.SetTextValueL( - KMPXMediaGeneralTitle, *To16LC( - iItemResolver->Item().Title() ) ); - CleanupStack::PopAndDestroy(); - } - // Artist - if( Exists( aAttrs, KMPXMediaMusicArtist ) ) - { - if ( ( elem = UPnPItemUtility::FindElementByName( - iItemResolver->Item(), KElementArtist ) ) != 0 ) - { - __LOG( "CUPnPTrack: Metadata: Artist" ); - aMedia.SetTextValueL( - KMPXMediaMusicArtist, *To16LC( elem->Value() ) ); - CleanupStack::PopAndDestroy(); - } - else if ( ( elem = UPnPItemUtility::FindElementByName( - iItemResolver->Item(), KElementCreator ) ) != 0 ) - { - __LOG( "CUPnPTrack: Metadata Creator" ); - aMedia.SetTextValueL( - KMPXMediaMusicArtist, *To16LC( elem->Value() ) ); - CleanupStack::PopAndDestroy(); - } - } - // Album - if( Exists( aAttrs, KMPXMediaMusicAlbum ) ) - { - if ( ( elem = UPnPItemUtility::FindElementByName( - iItemResolver->Item(), KElementAlbum ) ) != 0 ) - { - __LOG( "CUPnPTrack: Metadata: Album"); - aMedia.SetTextValueL( - KMPXMediaMusicAlbum, *To16LC( elem->Value() ) ); - CleanupStack::PopAndDestroy(); - } - } - // Genre - if( Exists( aAttrs, KMPXMediaMusicGenre ) ) - { - if ( ( elem = UPnPItemUtility::FindElementByName( - iItemResolver->Item(), KElementGenre ) ) != 0 ) - { - __LOG( "CUPnPTrack: Metadata: Genre" ); - aMedia.SetTextValueL( - KMPXMediaMusicGenre, *To16LC( elem->Value() ) ); - CleanupStack::PopAndDestroy(); - } - } - // Date / Year - if( ( elem = UPnPItemUtility::FindElementByName( - iItemResolver->Item(), KElementDate ) ) != 0 ) - { - TTime timestamp; - TInt conversionError = - UPnPItemUtility::UPnPDateAsTTime( elem->Value(), timestamp ); - if ( conversionError == KErrNone ) - { - if ( Exists( aAttrs, KMPXMediaGeneralDate ) ) - { - __LOG( "CUPnPTrack: Metadata: Date" ); - aMedia.SetTextValueL( - KMPXMediaGeneralDate, iTempBuf ); - } - if ( Exists( aAttrs, KMPXMediaMusicYear ) ) - { - __LOG( "CUPnPTrack: Metadata: Year" ); - timestamp.FormatL( iTempBuf, KTimeFormatYearOnly ); - aMedia.SetTextValueL( - KMPXMediaMusicYear, iTempBuf ); - } - } - } - // Duration - if( Exists( aAttrs, KMPXMediaGeneralDuration ) ) - { - TInt duration = TrackDuration(); - if ( duration >= 0 ) - { - aMedia.SetTObjectValueL( - KMPXMediaGeneralDuration, duration ); - } - } - // Size - if( Exists( aAttrs, KMPXMediaGeneralSize ) ) - { - const CUpnpAttribute* attr = UPnPItemUtility - ::FindAttributeByName( iItemResolver->Resource(), - KAttributeSize ); - if ( attr != 0 ) - { - __LOG( "CUPnPTrack: Metadata: Size" ); - TInt size; - TLex8 sizeconvert( attr->Value() ); - if ( sizeconvert.Val( size ) == KErrNone ) - { - aMedia.SetTObjectValueL( - KMPXMediaGeneralSize, size ); - } - } - } - // Mimetype - if( Exists( aAttrs, KMPXMediaGeneralMimeType ) ) - { - const CUpnpAttribute* attr = UPnPItemUtility - ::FindAttributeByName( iItemResolver->Resource(), - KAttributeProtocolInfo ); - if ( attr != 0 ) - { - __LOG( "CUPnPTrack: Metadata: MimeType" ); - CUpnpDlnaProtocolInfo* pInfo = - CUpnpDlnaProtocolInfo::NewL( attr->Value() ); - CleanupStack::PushL( pInfo ); - aMedia.SetTextValueL( - KMPXMediaGeneralMimeType, *To16LC( pInfo->ThirdField() ) ); - CleanupStack::PopAndDestroy(); - CleanupStack::PopAndDestroy( pInfo ); - pInfo = NULL; - } - } - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::Exists -// -------------------------------------------------------------------------- -// -TBool CUPnPTrack::Exists( const TArray& aAttrs, - const TMPXAttributeData& aAttrData ) const - { - TBool found = EFalse; - for( TInt i = 0; i < aAttrs.Count() && !found; ++i ) - { - if ( aAttrs[i].ContentId() == aAttrData.iContentId && - aAttrs[i].AttributeId() & aAttrData.iAttributeId ) - { - found = ETrue; - } - } - return found; - } - -// -------------------------------------------------------------------------- -// CUPnPTrack::To16LC -// -------------------------------------------------------------------------- -// -const HBufC16* CUPnPTrack::To16LC( const TDesC8& aText ) - { - HBufC16* result = 0; - result = EscapeUtils::ConvertToUnicodeFromUtf8L( aText ); - CleanupStack::PushL( result ); - return result; - } - -// -------------------------------------------------------------------------- -// callbacks from MUPnPItemResolverObserver -// -------------------------------------------------------------------------- -// -void CUPnPTrack::ResolveComplete( const MUPnPItemResolver& /*aResolver*/, - TInt aError ) - { - __LOG1( "CUPnPTrack::ResolveComplete err: %d", aError ); - iIsItemSolved = ETrue; - if ( iState == EStateResolving ) - { - iState = EStateReady; - - // handle pending metadata query - if ( iTrackLocation == ETrackLocationRemote && iMetadataObserver ) - { - __LOG( "Handle pending metadata query"); - TRAP_IGNORE( - DeliverMedataL( iQueriedAttributes.Array(), *iMetadataObserver, - aError ) ); - iMetadataObserver = 0; - iQueriedAttributes.Reset(); - } - - // call back - MUPnPTrackObserver& observer = *iTrackObserver; - iTrackObserver = 0; - observer.ResolveURIComplete( aError ); - } - else if ( iState == EStateSelfDestruct ) - { - __LOG( "CUPnPTrack: self-destructing" ); - delete this; - } - } - -// -------------------------------------------------------------------------- -// Private methods of CUPnPTrack -// -------------------------------------------------------------------------- - -// -------------------------------------------------------------------------- -// CUPnPTrack::ParsePiecesL -// Parse and save media server id and object id from given descriptor -// -------------------------------------------------------------------------- -// -void CUPnPTrack::ParsePiecesL( const TDesC& aSong ) - { - // Delete if already exist - if( iMediaServer ) - { - delete iMediaServer; - iMediaServer = 0; - } - if( iObjectId ) - { - delete iObjectId; - iObjectId = 0; - } - - // Leave if argument is not valid - if( aSong.Length() < KUPnPPrefixLength ) - { - User::Leave( KErrArgument ); - } - - TInt lenght = aSong.Length(); - TInt position = 0; - TChar colon( KCharCodeColon ); - TChar separate( KCharCodeSeparate ); - - // At first separe "upnp:" prefix from descriptor - position = aSong.Locate( colon ); - TPtrC tmp = aSong.Mid( position + 1, (lenght - KUPnPPrefixLength ) ); - - // Get media server id - position = tmp.Locate( separate ); - // Leave if separator character not found - if( position == KErrNotFound ) - { - User::Leave( KErrNotFound ); - } - TPtrC mediaserverId = tmp.Left( position ); - iMediaServer = HBufC8::NewL( mediaserverId.Length() ); - iMediaServer->Des().Copy( mediaserverId ); - - // Get object id - TPtrC objId = tmp.Mid( position + 1, ( (tmp.Length() - - mediaserverId.Length() ) - 1 ) ); - iObjectId = HBufC8::NewL( objId.Length() ); - iObjectId->Des().Copy( objId ); - } - -