--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/upnpavcontroller/upnpavcontrollerhelper/src/upnpitemutility.cpp Thu Dec 17 08:52:00 2009 +0200
@@ -0,0 +1,427 @@
+/*
+* 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: Utility for parsing upnp items
+*
+*/
+
+
+
+
+
+
+// INCLUDE FILES
+// System
+#include <e32std.h>
+
+// upnp stack api
+#include <upnpitem.h>
+#include <upnpdlnaprotocolinfo.h>
+
+// upnpframework / avcontroller helper api
+#include "upnpconstantdefs.h" // for KValueNotImplemented
+#include "upnpitemutility.h"
+
+_LIT( KComponentLogfile, "upnpavcontrollerhelper.txt");
+#include "upnplog.h"
+
+// CONSTANTS
+const TInt KDateStringLength = 10;
+const TInt KDateTimeStringLength = 19;
+const TInt KMaxDateStringLength = 30;
+const TInt KCodeSemicolon = 58;
+_LIT( KSeparator, ":" );
+_LIT( KNullTime, "000000" );
+_LIT8( KHttp, "http://" );
+_LIT8( KCiParam, "DLNA.ORG_CI" );
+
+/* removed due to M-DMC CTT test case 7.3.26.2
+_LIT8( KAudioSupport, "audio/" );
+_LIT8( KImageSupport, "image/" );
+_LIT8( KVideoSupport, "video/" );
+*/
+
+// ============================ LOCAL FUNCTIONS =============================
+
+// --------------------------------------------------------------------------
+// UPnPItemUtility::BelongsToClass
+//---------------------------------------------------------------------------
+EXPORT_C TBool UPnPItemUtility::BelongsToClass(
+ const CUpnpObject& aObject,
+ const TDesC8& aClass )
+ {
+ TBool beginsWith =
+ ( aObject.ObjectClass().Find( aClass ) == 0 );
+ return beginsWith;
+ }
+
+// --------------------------------------------------------------------------
+// UPnPItemUtility::GetResElements
+//---------------------------------------------------------------------------
+EXPORT_C void UPnPItemUtility::GetResElements(
+ const CUpnpObject& aObject,
+ RUPnPElementsArray& aResElementsArray )
+ {
+ const RUPnPElementsArray& array =
+ const_cast<CUpnpObject&>(aObject).GetElements();
+
+ for( TInt i = 0; i < array.Count(); i++ )
+ {
+ if( array[ i ]->Name() == KElementRes() )
+ {
+ aResElementsArray.Append( array[ i ] );
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// UPnPItemUtility::ResourceFromItemL
+//---------------------------------------------------------------------------
+EXPORT_C const CUpnpElement& UPnPItemUtility::ResourceFromItemL(
+ const CUpnpItem& aItem )
+ {
+ __LOG( "UpnpItemUtility:ResourceFromItemL" );
+
+ // Obtain list of item's res elements
+ RUPnPElementsArray elms;
+ GetResElements( aItem, elms );
+ TInt count = elms.Count();
+
+ CUpnpDlnaProtocolInfo* pInfo = NULL;
+ TBool found = EFalse;
+ TInt i(0);
+ // bestCandidate is an index of some res element in the list. This res
+ // will be considered as the best candidate for desired res and that
+ // candidate will be returned if no res element contains false CI-flag.
+
+ const CUpnpElement* bestCandidate = 0;
+
+ // determine which resource is the original one
+ // 1. In DLNA 1.5 case, parse protocolInfo attribute and see if some res
+ // element has CI-flag false (=not converted so that is what we want)
+ // 2. In non-DLNA 1.5 case and in DLNA 1.5 case where CI-flag does not
+ // exist, do the following:
+ // o filter out other than HTTP GET resources (internal uri's, RTP)
+ // o filter out resources that do not match itemtype (mime type of
+ // audio file resources should start with "audio/" etc.)
+ for( i = 0 ; i < count; i++ )
+ {
+ // Make sure that it is a HTTP GET resource. Otherwise continue.
+ if( elms[ i ]->Value().Left( KHttp.iTypeLength ).Compare( KHttp() )
+ != 0 )
+ {
+ continue;
+ }
+
+ // Obtain protocolInfo of the res element.
+ const CUpnpAttribute* attr = FindAttributeByName(
+ *elms[i], KAttributeProtocolInfo() );
+ if ( attr )
+ {
+ TRAP_IGNORE( pInfo = CUpnpDlnaProtocolInfo::NewL( attr->Value() ) );
+ if( !pInfo )
+ {
+ //if pInfo, start next one!
+ continue;
+ }
+ // check if CI parameter is false or it doesn't have CI parameters at all.
+ //for upnp item, always the first res element is the best, resolution
+ // should be checked in the future
+ if ( ( attr->Value().Find( KCiParam() ) != KErrNotFound &&
+ pInfo->CiParameter() == EFalse ) ||
+ attr->Value().Find( KCiParam() ) == KErrNotFound )
+ {
+ // end loop, we found what we were looking for.
+ found = ETrue;
+ delete pInfo; pInfo = NULL;
+ break;
+ }
+
+/* removed due to M-DMC CTT test case 7.3.26.2
+ // check that mimetype corresponds to objectType
+ TPtrC8 mime = pInfo->ThirdField();
+
+ TPtrC8 objectClass = aItem.ObjectClass();
+ if ( objectClass.Compare( KClassAudio ) == 0 )
+ {
+ if ( mime.Left( KAudioSupport().Length() ).CompareF(
+ KAudioSupport() ) != 0 )
+ {
+ // if mime type does not match to object type, this is
+ // not the correct resource.
+ delete pInfo; pInfo = NULL;
+ continue;
+ }
+ }
+ else if ( objectClass.Compare( KClassVideo ) == 0 )
+ {
+ if ( mime.Left( KVideoSupport().Length() ).CompareF(
+ KVideoSupport() ) != 0 )
+ {
+ // if mime type does not match to object type, this is
+ // not the correct resource.
+ delete pInfo; pInfo = NULL;
+ continue;
+ }
+ }
+ else if ( objectClass.Compare( KClassImage ) == 0 )
+ {
+ if ( mime.Left( KImageSupport().Length() ).CompareF(
+ KImageSupport() ) != 0 )
+ {
+ // if mime type does not match to object type, this is
+ // not the correct resource.
+ delete pInfo; pInfo = NULL;
+ continue;
+ }
+ }
+ */
+ // use the first suitable res field as candidate which will be
+ // returned if better is not found.
+ // More sophisticated solution would be to compare resolution
+ // etc. attributes to determine the best candidate,
+ if ( 0 == bestCandidate )
+ {
+ bestCandidate = elms[i];
+ }
+ delete pInfo; pInfo = NULL;
+ }
+ else
+ {
+ // No mandatory protocolinfo attribute. This is not what we want.
+ }
+ }
+ if ( found )
+ {
+ bestCandidate = elms[i];
+ }
+
+ // close the elements array
+ elms.Close();
+
+ if( bestCandidate == 0 )
+ {
+ User::Leave( KErrNotFound );
+ }
+ return *bestCandidate;
+ }
+
+
+// --------------------------------------------------------------------------
+// UPnPItemUtility::FindElementByName
+//---------------------------------------------------------------------------
+EXPORT_C const CUpnpElement* UPnPItemUtility::FindElementByName(
+ const CUpnpObject& aObject, const TDesC8& aName )
+ {
+ __LOG( "UpnpItemUtility:FindElementByName" );
+
+ CUpnpElement* element = NULL;
+ const RUPnPElementsArray& array =
+ const_cast<CUpnpObject&>(aObject).GetElements();
+ for( TInt i = 0; i < array.Count(); i++ )
+ {
+ if( array[ i ]->Name() == aName )
+ {
+ element = array[ i ];
+ i = array.Count();
+ }
+ }
+ return element;
+ }
+
+// --------------------------------------------------------------------------
+// UPnPItemUtility::FindElementByNameL
+//---------------------------------------------------------------------------
+EXPORT_C const CUpnpElement& UPnPItemUtility::FindElementByNameL(
+ const CUpnpObject& aObject, const TDesC8& aName )
+ {
+ __LOG( "UpnpItemUtility:FindElementByNameL" );
+
+ const CUpnpElement* element = FindElementByName(
+ aObject, aName );
+ if( !element )
+ {
+ User::Leave( KErrNotFound );
+ }
+ return *element;
+ }
+
+// --------------------------------------------------------------------------
+// UPnPItemUtility::FindAttributeByName
+//---------------------------------------------------------------------------
+EXPORT_C const CUpnpAttribute* UPnPItemUtility::FindAttributeByName(
+ const CUpnpElement& aElement, const TDesC8& aName )
+ {
+ __LOG( "UpnpItemUtility:FindAttributeByName" );
+
+ CUpnpAttribute* attribute = NULL;
+ const RUPnPAttributesArray& array =
+ const_cast<CUpnpElement&>(aElement).GetAttributes();
+
+ for( TInt i = 0; i < array.Count(); i++ )
+ {
+
+ TBufC8<255> buf(array[ i ]->Name());
+ if( array[ i ]->Name() == aName )
+ {
+ attribute = array[ i ];
+ i = array.Count();
+ }
+ }
+ return attribute;
+ }
+
+// --------------------------------------------------------------------------
+// UPnPItemUtility::FindAttributeByNameL
+//---------------------------------------------------------------------------
+EXPORT_C const CUpnpAttribute& UPnPItemUtility::FindAttributeByNameL(
+ const CUpnpElement& aElement, const TDesC8& aName )
+ {
+ __LOG( "UpnpItemUtility:FindAttributeByNameL" );
+
+ const CUpnpAttribute* attribute = FindAttributeByName(
+ aElement, aName );
+ if( !attribute )
+ {
+ User::Leave( KErrNotFound );
+ }
+ return *attribute;
+ }
+
+// --------------------------------------------------------------------------
+// UPnPItemUtility::UpnpDateAsTTime
+//---------------------------------------------------------------------------
+EXPORT_C TInt UPnPItemUtility::UPnPDateAsTTime(
+ const TDesC8& aUpnpDate, TTime& aTime )
+ {
+ __LOG( "UpnpItemUtility:UpnpDateAsTTime" );
+
+ TRAPD( err, UPnPItemUtility::UPnPDateAsTTimeL( aUpnpDate, aTime ) );
+ return err;
+ }
+
+// --------------------------------------------------------------------------
+// UPnPItemUtility::UpnpDurationAsMilliseconds
+//---------------------------------------------------------------------------
+EXPORT_C TInt UPnPItemUtility::UPnPDurationAsMilliseconds(
+ const TDesC8& aDuration, TInt& aMilliseconds )
+ {
+ __LOG( "UpnpItemUtility:UpnpDurationAsMilliseconds" );
+
+ TInt retVal = KErrNone;
+ if( aDuration.Length() > 0 )
+ {
+ // Check if information is actually returned by the device
+ if( aDuration.Compare( KValueNotImplemented ) != 0 )
+ {
+ TInt time = 0;
+ TChar separator( KCodeSemicolon );
+ TInt lposit = aDuration.Locate( separator );
+
+ if ( lposit != KErrNotFound )
+ {
+ TInt rposit = aDuration.LocateReverse( separator );
+ if( rposit != lposit )
+ {
+ // Hours
+ TLex8 lex( aDuration.Left( lposit ) );
+ retVal = lex.Val( time );
+ if( retVal == KErrNone )
+ {
+ // Convert to ms and add
+ aMilliseconds += time * 3600 * 1000;
+ // Minutes
+ lex.Assign( aDuration.Mid(
+ lposit + 1, rposit - lposit - 1 ) );
+ retVal = lex.Val( time );
+ if( retVal == KErrNone )
+ {
+ // Convert to ms and add
+ aMilliseconds += time * 60* 1000;
+ // Seconds
+ lex.Assign( aDuration.Mid(
+ rposit + 1, 2 ) );
+ retVal = lex.Val( time );
+ if( retVal == KErrNone )
+ {
+ // Convert to ms and add
+ aMilliseconds += time * 1000;
+ }
+ }
+ }
+ }
+ else
+ {
+ retVal = KErrNotSupported;
+ }
+ }
+ else
+ {
+ retVal = KErrNotSupported;
+ }
+ }
+ else
+ {
+ retVal = KErrNotSupported;
+ }
+ }
+ else
+ {
+ retVal = KErrNotSupported;
+ }
+
+ return retVal;
+ }
+
+void UPnPItemUtility::UPnPDateAsTTimeL( const TDesC8& aUpnpDate,
+ TTime& aTime )
+ {
+ // This method is capable of handling the most common dc:date formats:
+ // CCYY-MM-DD and CCYY-MM-DDThh:mm:ss
+ // Rest of the dc:date formats are handled as well, but they might not
+ // be converted precisely
+
+ TBuf<KMaxDateStringLength> formatDateString;
+ HBufC* dateString = HBufC::NewL( aUpnpDate.Length() );
+ dateString->Des().Copy( aUpnpDate );
+
+ if( aUpnpDate.Length() >= KDateStringLength )
+ {
+ // CCYY-MM-DD --> CCYYMMDD
+ formatDateString.Copy( dateString->Des().Left( 4 ) ); // Year
+ formatDateString.Append( dateString->Des().Mid( 5,2 ) ); // Month
+ formatDateString.Append( dateString->Des().Mid( 8,2 ) ); // Day
+
+ if( aUpnpDate.Length() >= KDateTimeStringLength )
+ {
+ // hh:mm:ss --> hhmmss
+ formatDateString.Append( KSeparator );
+ // Hours
+ formatDateString.Append( dateString->Des().Mid( 11, 2 ) );
+ // Minutes
+ formatDateString.Append( dateString->Des().Mid( 14, 2 ) );
+ // Seconds
+ formatDateString.Append( dateString->Des().Mid( 17, 2 ) );
+ }
+ else
+ {
+ // hh:mm:ss --> 000000
+ formatDateString.Append( KSeparator );
+ formatDateString.Append( KNullTime );
+ }
+ }
+ delete dateString;
+
+ User::LeaveIfError( aTime.Set( formatDateString ) );
+ }
+