upnpavcontroller/upnpavcontrollerhelper/src/upnpitemutility.cpp
changeset 0 7f85d04be362
child 38 5360b7ddc251
equal deleted inserted replaced
-1:000000000000 0:7f85d04be362
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:      Utility for parsing upnp items
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 // INCLUDE FILES
       
    24 // System
       
    25 #include <e32std.h>
       
    26 
       
    27 // upnp stack api
       
    28 #include <upnpitem.h>
       
    29 #include <upnpdlnaprotocolinfo.h>
       
    30 
       
    31 // upnpframework / avcontroller helper api
       
    32 #include "upnpconstantdefs.h" // for KValueNotImplemented
       
    33 #include "upnpitemutility.h"
       
    34 
       
    35 _LIT( KComponentLogfile, "upnpavcontrollerhelper.txt");
       
    36 #include "upnplog.h"
       
    37 
       
    38 // CONSTANTS
       
    39 const TInt KDateStringLength        = 10;
       
    40 const TInt KDateTimeStringLength    = 19;
       
    41 const TInt KMaxDateStringLength     = 30;
       
    42 const TInt KCodeSemicolon           = 58;
       
    43 _LIT( KSeparator,                   ":" );
       
    44 _LIT( KNullTime,                    "000000" );
       
    45 _LIT8( KHttp,                       "http://" );
       
    46 _LIT8( KCiParam,                    "DLNA.ORG_CI" );
       
    47 
       
    48 /* removed due to M-DMC CTT test case 7.3.26.2
       
    49 _LIT8( KAudioSupport,               "audio/" );
       
    50 _LIT8( KImageSupport,               "image/" );
       
    51 _LIT8( KVideoSupport,               "video/" );
       
    52 */
       
    53 
       
    54 // ============================ LOCAL FUNCTIONS =============================
       
    55 
       
    56 // --------------------------------------------------------------------------
       
    57 // UPnPItemUtility::BelongsToClass
       
    58 //---------------------------------------------------------------------------
       
    59 EXPORT_C TBool UPnPItemUtility::BelongsToClass(
       
    60     const CUpnpObject& aObject,
       
    61     const TDesC8& aClass )
       
    62     {
       
    63     TBool beginsWith = 
       
    64         ( aObject.ObjectClass().Find( aClass ) == 0 );
       
    65     return beginsWith;
       
    66     }
       
    67 
       
    68 // --------------------------------------------------------------------------
       
    69 // UPnPItemUtility::GetResElements
       
    70 //---------------------------------------------------------------------------
       
    71 EXPORT_C void UPnPItemUtility::GetResElements(
       
    72     const CUpnpObject& aObject,
       
    73     RUPnPElementsArray& aResElementsArray )
       
    74     {
       
    75     const RUPnPElementsArray& array =
       
    76         const_cast<CUpnpObject&>(aObject).GetElements();
       
    77     
       
    78     for( TInt i = 0; i < array.Count(); i++ )
       
    79         {
       
    80         if( array[ i ]->Name() == KElementRes() )
       
    81             {
       
    82             aResElementsArray.Append( array[ i ] );
       
    83             }
       
    84         }    
       
    85     }
       
    86 
       
    87 // --------------------------------------------------------------------------
       
    88 // UPnPItemUtility::ResourceFromItemL
       
    89 //---------------------------------------------------------------------------
       
    90 EXPORT_C const CUpnpElement& UPnPItemUtility::ResourceFromItemL(
       
    91     const CUpnpItem& aItem )
       
    92     {
       
    93     __LOG( "UpnpItemUtility:ResourceFromItemL" );
       
    94 
       
    95     // Obtain list of item's res elements   
       
    96     RUPnPElementsArray elms;
       
    97     GetResElements( aItem, elms );
       
    98     TInt count = elms.Count();
       
    99 
       
   100     CUpnpDlnaProtocolInfo* pInfo = NULL;
       
   101     TBool found = EFalse;
       
   102     TInt i(0);
       
   103     // bestCandidate is an index of some res element in the list. This res
       
   104     // will be considered as the best candidate for desired res and that
       
   105     // candidate will be returned if no res element contains false CI-flag.
       
   106 
       
   107     const CUpnpElement* bestCandidate = 0;
       
   108 
       
   109     // determine which resource is the original one
       
   110     // 1. In DLNA 1.5 case, parse protocolInfo attribute and see if some res 
       
   111     //    element has CI-flag false (=not converted so that is what we want)
       
   112     // 2. In non-DLNA 1.5 case and in DLNA 1.5 case where CI-flag does not 
       
   113     //    exist, do the following:
       
   114     //      o filter out other than HTTP GET resources (internal uri's, RTP)
       
   115     //      o filter out resources that do not match itemtype (mime type of 
       
   116     //        audio file resources should start with "audio/" etc.)
       
   117     for( i = 0 ; i < count; i++ )
       
   118         {
       
   119         // Make sure that it is a HTTP GET resource. Otherwise continue.
       
   120         if( elms[ i ]->Value().Left( KHttp.iTypeLength ).Compare( KHttp() ) 
       
   121             != 0 )
       
   122             {
       
   123             continue;
       
   124             }
       
   125 
       
   126         // Obtain protocolInfo of the res element.
       
   127         const CUpnpAttribute* attr = FindAttributeByName(
       
   128             *elms[i], KAttributeProtocolInfo() );
       
   129         if ( attr ) 
       
   130             {           
       
   131             TRAP_IGNORE( pInfo = CUpnpDlnaProtocolInfo::NewL( attr->Value() ) );
       
   132             if( !pInfo )
       
   133                 {
       
   134                 //if pInfo, start next one!
       
   135                 continue;
       
   136                 }
       
   137             // check if CI parameter is false or it doesn't have CI parameters at all.
       
   138             //for upnp item, always the first res element is the best, resolution
       
   139             // should be checked in the future
       
   140             if ( ( attr->Value().Find( KCiParam() ) != KErrNotFound && 
       
   141                  pInfo->CiParameter() == EFalse ) || 
       
   142                  attr->Value().Find( KCiParam() ) == KErrNotFound )
       
   143                 {
       
   144                 // end loop, we found what we were looking for. 
       
   145                 found = ETrue;
       
   146                 delete pInfo; pInfo = NULL;
       
   147                 break;                
       
   148                 }
       
   149 
       
   150 /* removed due to M-DMC CTT test case 7.3.26.2            
       
   151             // check that mimetype corresponds to objectType
       
   152             TPtrC8 mime = pInfo->ThirdField();
       
   153             
       
   154             TPtrC8 objectClass = aItem.ObjectClass();
       
   155             if ( objectClass.Compare( KClassAudio ) == 0 ) 
       
   156                 {
       
   157                 if ( mime.Left( KAudioSupport().Length() ).CompareF( 
       
   158                                                     KAudioSupport() ) != 0 ) 
       
   159                     {
       
   160                     // if mime type does not match to object type, this is 
       
   161                     // not the correct resource.
       
   162                     delete pInfo; pInfo = NULL;
       
   163                     continue;
       
   164                     }
       
   165                 }
       
   166             else if ( objectClass.Compare( KClassVideo ) == 0 ) 
       
   167                 {
       
   168                 if ( mime.Left( KVideoSupport().Length() ).CompareF( 
       
   169                                                     KVideoSupport() ) != 0 ) 
       
   170                     {
       
   171                     // if mime type does not match to object type, this is 
       
   172                     // not the correct resource.
       
   173                     delete pInfo; pInfo = NULL;
       
   174                     continue;
       
   175                     }
       
   176                 }
       
   177             else if ( objectClass.Compare( KClassImage ) == 0 ) 
       
   178                 {
       
   179                 if ( mime.Left( KImageSupport().Length() ).CompareF( 
       
   180                                                     KImageSupport() ) != 0 ) 
       
   181                     {
       
   182                     // if mime type does not match to object type, this is 
       
   183                     // not the correct resource.
       
   184                     delete pInfo; pInfo = NULL;
       
   185                     continue;
       
   186                     }
       
   187                 }
       
   188  */
       
   189             // use the first suitable res field as candidate which will be
       
   190             // returned if better is not found.
       
   191             // More sophisticated solution would be to compare resolution
       
   192             // etc. attributes to determine the best candidate,
       
   193             if ( 0 == bestCandidate ) 
       
   194                 {
       
   195                 bestCandidate = elms[i];
       
   196                 }
       
   197             delete pInfo; pInfo = NULL;
       
   198             }
       
   199         else 
       
   200             {
       
   201             // No mandatory protocolinfo attribute. This is not what we want.
       
   202             }
       
   203         }
       
   204     if ( found ) 
       
   205         {
       
   206         bestCandidate = elms[i];
       
   207         }
       
   208 
       
   209     // close the elements array
       
   210     elms.Close();
       
   211 
       
   212     if( bestCandidate == 0 )
       
   213         {
       
   214         User::Leave( KErrNotFound );
       
   215         }
       
   216     return *bestCandidate;
       
   217     }
       
   218 
       
   219 
       
   220 // --------------------------------------------------------------------------
       
   221 // UPnPItemUtility::FindElementByName
       
   222 //---------------------------------------------------------------------------
       
   223 EXPORT_C const CUpnpElement* UPnPItemUtility::FindElementByName(
       
   224     const CUpnpObject& aObject, const TDesC8& aName )
       
   225     {
       
   226     __LOG( "UpnpItemUtility:FindElementByName" );
       
   227 
       
   228     CUpnpElement* element = NULL;
       
   229     const RUPnPElementsArray& array =
       
   230         const_cast<CUpnpObject&>(aObject).GetElements();
       
   231     for( TInt i = 0; i < array.Count(); i++ )
       
   232         {
       
   233         if( array[ i ]->Name() == aName )
       
   234             {
       
   235             element = array[ i ];
       
   236             i = array.Count();
       
   237             }
       
   238         }
       
   239     return element;
       
   240     }
       
   241 
       
   242 // --------------------------------------------------------------------------
       
   243 // UPnPItemUtility::FindElementByNameL
       
   244 //---------------------------------------------------------------------------
       
   245 EXPORT_C const CUpnpElement& UPnPItemUtility::FindElementByNameL(
       
   246     const CUpnpObject& aObject, const TDesC8& aName )
       
   247     {
       
   248     __LOG( "UpnpItemUtility:FindElementByNameL" );
       
   249 
       
   250     const CUpnpElement* element = FindElementByName(
       
   251         aObject, aName );
       
   252     if( !element )
       
   253         {
       
   254         User::Leave( KErrNotFound );
       
   255         }
       
   256     return *element;    
       
   257     }
       
   258 
       
   259 // --------------------------------------------------------------------------
       
   260 // UPnPItemUtility::FindAttributeByName
       
   261 //---------------------------------------------------------------------------
       
   262 EXPORT_C const CUpnpAttribute* UPnPItemUtility::FindAttributeByName(
       
   263     const CUpnpElement& aElement, const TDesC8& aName )
       
   264     {
       
   265     __LOG( "UpnpItemUtility:FindAttributeByName" );
       
   266 
       
   267     CUpnpAttribute* attribute = NULL;
       
   268     const RUPnPAttributesArray& array =
       
   269         const_cast<CUpnpElement&>(aElement).GetAttributes();
       
   270     
       
   271     for( TInt i = 0; i < array.Count(); i++ )
       
   272         {
       
   273         
       
   274         TBufC8<255> buf(array[ i ]->Name());
       
   275         if( array[ i ]->Name() == aName )
       
   276             {
       
   277             attribute = array[ i ];
       
   278             i = array.Count();
       
   279             }
       
   280         }
       
   281     return attribute;
       
   282     }
       
   283 
       
   284 // --------------------------------------------------------------------------
       
   285 // UPnPItemUtility::FindAttributeByNameL
       
   286 //---------------------------------------------------------------------------
       
   287 EXPORT_C const CUpnpAttribute& UPnPItemUtility::FindAttributeByNameL(
       
   288     const CUpnpElement& aElement, const TDesC8& aName )
       
   289     {
       
   290     __LOG( "UpnpItemUtility:FindAttributeByNameL" );
       
   291 
       
   292     const CUpnpAttribute* attribute = FindAttributeByName(
       
   293         aElement, aName );
       
   294     if( !attribute )
       
   295         {
       
   296         User::Leave( KErrNotFound );
       
   297         }
       
   298     return *attribute;        
       
   299     }
       
   300 
       
   301 // --------------------------------------------------------------------------
       
   302 // UPnPItemUtility::UpnpDateAsTTime
       
   303 //---------------------------------------------------------------------------
       
   304 EXPORT_C TInt UPnPItemUtility::UPnPDateAsTTime(
       
   305     const TDesC8& aUpnpDate, TTime& aTime )
       
   306     {
       
   307     __LOG( "UpnpItemUtility:UpnpDateAsTTime" );
       
   308 
       
   309     TRAPD( err, UPnPItemUtility::UPnPDateAsTTimeL( aUpnpDate, aTime ) );
       
   310     return err;
       
   311     }
       
   312 
       
   313 // --------------------------------------------------------------------------
       
   314 // UPnPItemUtility::UpnpDurationAsMilliseconds
       
   315 //---------------------------------------------------------------------------
       
   316 EXPORT_C TInt UPnPItemUtility::UPnPDurationAsMilliseconds(
       
   317     const TDesC8& aDuration, TInt& aMilliseconds )
       
   318     {
       
   319     __LOG( "UpnpItemUtility:UpnpDurationAsMilliseconds" );
       
   320 
       
   321     TInt retVal = KErrNone;    
       
   322     if( aDuration.Length() > 0 )
       
   323         {
       
   324         // Check if information is actually returned by the device
       
   325         if( aDuration.Compare( KValueNotImplemented ) != 0 )
       
   326             {        
       
   327             TInt time = 0;
       
   328             TChar separator( KCodeSemicolon );
       
   329             TInt lposit = aDuration.Locate( separator );
       
   330             
       
   331             if ( lposit != KErrNotFound )
       
   332                 {
       
   333                 TInt rposit = aDuration.LocateReverse( separator );
       
   334                 if( rposit != lposit )
       
   335                     {
       
   336                     // Hours
       
   337                     TLex8 lex( aDuration.Left( lposit ) );
       
   338                     retVal = lex.Val( time ); 
       
   339                     if( retVal == KErrNone  )
       
   340                         {
       
   341                         // Convert to ms and add
       
   342                         aMilliseconds += time * 3600 * 1000;
       
   343                         // Minutes
       
   344                         lex.Assign( aDuration.Mid(
       
   345                             lposit + 1, rposit - lposit - 1 ) );
       
   346                         retVal = lex.Val( time ); 
       
   347                         if( retVal == KErrNone )
       
   348                             {
       
   349                             // Convert to ms and add
       
   350                             aMilliseconds += time * 60* 1000;
       
   351                             // Seconds
       
   352                             lex.Assign( aDuration.Mid(
       
   353                                 rposit + 1, 2 ) );
       
   354                             retVal = lex.Val( time ); 
       
   355                             if( retVal  == KErrNone )
       
   356                                 {
       
   357                                 // Convert to ms and add
       
   358                                 aMilliseconds += time * 1000;
       
   359                                 }
       
   360                             }
       
   361                         }
       
   362                     }
       
   363                 else
       
   364                     {
       
   365                     retVal = KErrNotSupported;
       
   366                     }        
       
   367                 }
       
   368             else
       
   369                 {
       
   370                 retVal = KErrNotSupported;
       
   371                 }   
       
   372             }  
       
   373         else
       
   374             {
       
   375             retVal = KErrNotSupported;
       
   376             }
       
   377         }
       
   378     else
       
   379         {
       
   380         retVal = KErrNotSupported;
       
   381         }
       
   382         
       
   383     return retVal;
       
   384     }
       
   385 
       
   386 void UPnPItemUtility::UPnPDateAsTTimeL( const TDesC8& aUpnpDate,
       
   387     TTime& aTime )
       
   388     {
       
   389     // This method is capable of handling the most common dc:date formats:
       
   390     // CCYY-MM-DD and CCYY-MM-DDThh:mm:ss
       
   391     // Rest of the dc:date formats are handled as well, but they might not
       
   392     // be converted precisely
       
   393     
       
   394     TBuf<KMaxDateStringLength> formatDateString;
       
   395     HBufC* dateString = HBufC::NewL( aUpnpDate.Length() );
       
   396     dateString->Des().Copy( aUpnpDate );
       
   397 
       
   398     if( aUpnpDate.Length() >= KDateStringLength )
       
   399         {
       
   400         // CCYY-MM-DD --> CCYYMMDD
       
   401         formatDateString.Copy( dateString->Des().Left( 4 ) ); // Year
       
   402         formatDateString.Append( dateString->Des().Mid( 5,2 ) ); // Month
       
   403         formatDateString.Append( dateString->Des().Mid( 8,2 ) ); // Day        
       
   404 
       
   405         if( aUpnpDate.Length() >= KDateTimeStringLength )
       
   406             {
       
   407             // hh:mm:ss --> hhmmss
       
   408             formatDateString.Append( KSeparator );
       
   409             // Hours
       
   410             formatDateString.Append( dateString->Des().Mid( 11, 2 ) ); 
       
   411             // Minutes
       
   412             formatDateString.Append( dateString->Des().Mid( 14, 2 ) );
       
   413             // Seconds 
       
   414             formatDateString.Append( dateString->Des().Mid( 17, 2 ) ); 
       
   415             }
       
   416         else
       
   417             {
       
   418             // hh:mm:ss --> 000000
       
   419             formatDateString.Append( KSeparator );
       
   420             formatDateString.Append( KNullTime );
       
   421             }
       
   422         }
       
   423     delete dateString;
       
   424     
       
   425     User::LeaveIfError( aTime.Set( formatDateString ) );
       
   426     }
       
   427