mmserv/metadatautility/Src/MetaDataParserID3v2.cpp
changeset 0 71ca22bcf22a
child 15 ab526b8cacfb
equal deleted inserted replaced
-1:000000000000 0:71ca22bcf22a
       
     1 /*
       
     2 * Copyright (c) 2004 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:  This class provides the base class for ID3v2 parsers.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include	"MetaDataParserID3v2.h"
       
    22 #include	"MetaDataParserID3v22.h"
       
    23 #include	"MetaDataParserID3v23.h"
       
    24 #include	"MetaDataParserID3v24.h"
       
    25 #include 	"MetaDataSourceDescriptor.h"
       
    26 
       
    27 #include    <barsc.h>
       
    28 #include    <barsread.h>
       
    29 #include	<TopCharacterSet.rsg>
       
    30 #include 	<data_caging_path_literals.hrh>
       
    31 
       
    32 // CONSTANTS
       
    33 // (ID3v2 specification found in www.id3.org)
       
    34 const TInt KID3v2HeaderLength 			= 10;
       
    35 const TInt KID3v2TagLength 				= 3;
       
    36 
       
    37 const TInt KMinimumConfidenceRequired = 90;
       
    38 const TInt KMinimumJapaneseConfidenceRequired = 75;
       
    39 const TUint KParseFromMemory	= 1000000; 
       
    40 
       
    41 //Album Type
       
    42 const TInt KPictureTypeOther				= 0x00;
       
    43 const TInt KPictureTypePixel                = 0x01;
       
    44 const TInt KPictureTypeFileIcon             = 0x02;
       
    45 const TInt KPictureTypeFrontCover			= 0x03;
       
    46 const TInt KPictureTypeBackCover            = 0x04;
       
    47 
       
    48 // Album Type priority
       
    49 const TInt K1stAlbumArt = KPictureTypeOther;
       
    50 const TInt K2ndAlbumArt = KPictureTypeFrontCover; 
       
    51 const TInt K3rdAlbumArt = KPictureTypeBackCover;
       
    52 
       
    53 _LIT8( KID3v2Tag, "ID3" );
       
    54 
       
    55 // ============================ MEMBER FUNCTIONS ===============================
       
    56 
       
    57 // -----------------------------------------------------------------------------
       
    58 // CMetaDataParserID3v2::CMetaDataParserID3v2
       
    59 // C++ default constructor can NOT contain any code, that
       
    60 // might leave.
       
    61 // -----------------------------------------------------------------------------
       
    62 //
       
    63 CMetaDataParserID3v2::CMetaDataParserID3v2(
       
    64 	CMetaDataSource& aSource )
       
    65 	:	iSource(&aSource),
       
    66         iParseFromDescriptor(EFalse),
       
    67         iAlbumType(-1),
       
    68         iAlbumPtr(NULL)
       
    69 	{
       
    70     }
       
    71 
       
    72 // -----------------------------------------------------------------------------
       
    73 // CMetaDataParserID3v2::CreateID3v2ParserL
       
    74 // Two-phased constructor.
       
    75 // -----------------------------------------------------------------------------
       
    76 //
       
    77 CMetaDataParserID3v2* CMetaDataParserID3v2::CreateID3v2ParserL(
       
    78 	CMetaDataSource& aSource )
       
    79     {
       
    80 #ifdef _DEBUG
       
    81 	RDebug::Print(_L("CMetaDataParserID3v2::CreateID3v2ParserL"));
       
    82 #endif
       
    83 	TInt version = VersionL(aSource);
       
    84 
       
    85 	CMetaDataParserID3v2* parser = NULL;
       
    86 	switch ( version )
       
    87 		{
       
    88 		case 2:
       
    89 			parser = STATIC_CAST( CMetaDataParserID3v2*, CMetaDataParserID3v22::NewL(aSource) );
       
    90 			break;
       
    91 		case 3:
       
    92 			parser = STATIC_CAST( CMetaDataParserID3v2*, CMetaDataParserID3v23::NewL(aSource) );
       
    93 			break;
       
    94 		case 4:
       
    95 			parser = STATIC_CAST( CMetaDataParserID3v2*, CMetaDataParserID3v24::NewL(aSource) );
       
    96 			break;
       
    97 		default:	// KErrNotFound
       
    98 			break;
       
    99 		}
       
   100 	return parser;
       
   101     }
       
   102 
       
   103 // Destructor
       
   104 CMetaDataParserID3v2::~CMetaDataParserID3v2()
       
   105 	{
       
   106 	if(iAutoDetectChinese || iAutoDetectRussian || iAutoDetectJapanese)
       
   107 		{
       
   108 		delete iCharacterSet;
       
   109 		delete iTopCharacterSet;
       
   110 		}
       
   111 	if(iParseFromDescriptor)
       
   112 		{
       
   113 		delete iTag;
       
   114 		delete iSourceDes;
       
   115 		}
       
   116 	if ( iAlbumPtr )
       
   117 		{
       
   118 		delete iAlbumPtr;
       
   119 		}
       
   120 
       
   121     }
       
   122 
       
   123 // -----------------------------------------------------------------------------
       
   124 // CMetaDataParserID3v2::ParseL
       
   125 // -----------------------------------------------------------------------------
       
   126 //
       
   127 void CMetaDataParserID3v2::ParseL(
       
   128 	const RArray<TMetaDataFieldId>& aWantedFields,
       
   129 	CMetaDataFieldContainer& aContainer )
       
   130     {
       
   131 #ifdef _DEBUG
       
   132 	RDebug::Print(_L("CMetaDataParserID3v2::ParseL"));
       
   133 #endif
       
   134 	iContainer = &aContainer;
       
   135 	PrepareToParseL();
       
   136 	CRepository *metadataRepository = CRepository::NewL(KCRUidMetadataUtility);
       
   137 	TInt err = KErrNone;
       
   138 	err = metadataRepository->Get(KMetadataUtilityAutoDetectChineseChars, iAutoDetectChinese);
       
   139 	if(err)
       
   140 	{
       
   141 		iAutoDetectChinese = EFalse;	
       
   142 	}
       
   143 	err = metadataRepository->Get(KMetadataUtilityAutoDetectJapaneseChars, iAutoDetectJapanese);
       
   144 	if(err)
       
   145 	{
       
   146 		iAutoDetectJapanese = EFalse;	
       
   147 	}
       
   148 	delete metadataRepository;
       
   149 	TLanguage lang = User::Language();
       
   150 	if(lang == ELangRussian || lang == ELangUkrainian)	
       
   151 		{
       
   152 		iAutoDetectRussian = ETrue;	
       
   153 		}
       
   154 	if(iAutoDetectChinese || iAutoDetectRussian || iAutoDetectJapanese)
       
   155 		{
       
   156 		CreateCharacterSetsL();
       
   157 		}
       
   158 	// choose if want to parse from descriptor
       
   159 	if(iFrameDataSize < KParseFromMemory) // 1Mb
       
   160 		{
       
   161 		iTag = HBufC8::NewL(iFrameDataSize);
       
   162 		TPtr8 des( iTag->Des() );
       
   163 		iSource->ReadL(0, des);
       
   164 		
       
   165 		iSourceDes = CMetaDataSourceDescriptor::NewL(des);
       
   166 		iSource = iSourceDes;
       
   167 		iParseFromDescriptor = ETrue;
       
   168 		}
       
   169 	if ( aWantedFields.Count() == 0 )
       
   170 		{
       
   171 		ParseFramesL();
       
   172 		}
       
   173 	else
       
   174 		{
       
   175 		ParseFramesL(aWantedFields);
       
   176 		}
       
   177     }
       
   178 
       
   179 // -----------------------------------------------------------------------------
       
   180 // CMetaDataParserID3v2::ParseFramesL
       
   181 // -----------------------------------------------------------------------------
       
   182 //
       
   183 void CMetaDataParserID3v2::ParseFramesL()
       
   184 	{
       
   185 #ifdef _DEBUG
       
   186 	RDebug::Print(_L("CMetaDataParserID3v2::ParseFramesL"));
       
   187 #endif
       
   188 	TMetaDataFieldId fieldId;
       
   189 	TInt frameSize;
       
   190 	TInt frameHeaderSize = 0;
       
   191 	while ( iFrameOffset < ( iFrameDataSize - 1 ) )
       
   192 		{
       
   193 		GetNextFieldL(fieldId, frameHeaderSize, frameSize);
       
   194 
       
   195 		if ( frameHeaderSize == 0 )
       
   196 			{
       
   197 			// We have hit the padding -> no more fields to read
       
   198             break;
       
   199             }
       
   200 
       
   201         if ( frameSize < 0 || frameSize > ( iFrameDataSize - iFrameOffset ) )
       
   202             {
       
   203             // Invalid frame size -> stop
       
   204             break;
       
   205             }
       
   206 		TInt err = KErrNone; // ignore err, as some entry may be extracted without exception
       
   207 		if ( fieldId != EUnknownMetaDataField )
       
   208 			{
       
   209 			switch ( fieldId )
       
   210 				{
       
   211 				case EMetaDataSongTitle:
       
   212 				case EMetaDataArtist:
       
   213 				case EMetaDataAlbum:
       
   214 				case EMetaDataAlbumTrack:
       
   215 				case EMetaDataComposer:
       
   216 				case EMetaDataCopyright:
       
   217 				case EMetaDataOriginalArtist:
       
   218 					TRAP(err, GetTextInfoL( fieldId, frameSize ));
       
   219 					break;
       
   220 
       
   221 				case EMetaDataGenre:
       
   222 					TRAP(err, GetGenreL( frameSize ));
       
   223 					break;
       
   224 
       
   225 				case EMetaDataYear:
       
   226 					TRAP(err, GetTextYearL( frameSize ));
       
   227 					break;
       
   228 
       
   229 				case EMetaDataComment:
       
   230 					TRAP(err, GetCommentL( frameSize ));
       
   231 					break;
       
   232 
       
   233 				case EMetaDataUrl:
       
   234 					TRAP(err, GetUrlL( frameSize ));
       
   235 					break;
       
   236 				
       
   237 				case EMetaDataUserUrl:
       
   238 					TRAP(err, GetUserUrlL( frameSize ));
       
   239 					break;
       
   240 					
       
   241 				case EMetaDataJpeg:
       
   242 				    // check for 1st album art
       
   243 				    if (iAlbumType != K1stAlbumArt)
       
   244 				        {
       
   245 	                    TRAP(err,GetJpegL( frameSize ));				        
       
   246 				        }
       
   247 					break;
       
   248 
       
   249 				case EMetaDataDuration:
       
   250 					TRAP(err, GetDurationL( frameSize ));
       
   251 					break;
       
   252 				
       
   253 				case EMetaDataDate:
       
   254 					TRAP(err, GetTextDateL( frameSize ));
       
   255 					break;
       
   256 						
       
   257 				case EMetaDataRating:
       
   258 					TRAP(err, GetRatingL( frameSize ));
       
   259 					break;
       
   260 							
       
   261 				default:
       
   262 					break;
       
   263 				}
       
   264 			}
       
   265 		iFrameOffset += (frameSize + frameHeaderSize);
       
   266 		}
       
   267     
       
   268     // retrieve the album art
       
   269     TRAPD (error, RetrieveAlbumArtL());
       
   270     if (error)
       
   271         {
       
   272         #ifdef _DEBUG
       
   273             RDebug::Print(_L("CMetaDataParserID3v2::ParseFramesL - RetrieveAlbumArt leave"));
       
   274         #endif        
       
   275         }
       
   276   
       
   277 	}
       
   278 
       
   279 // -----------------------------------------------------------------------------
       
   280 // CMetaDataParserID3v2::ParseFramesL
       
   281 // -----------------------------------------------------------------------------
       
   282 //
       
   283 void CMetaDataParserID3v2::ParseFramesL(
       
   284 	const RArray<TMetaDataFieldId>& aWantedFields )
       
   285 	{
       
   286 #ifdef _DEBUG
       
   287 	RDebug::Print(_L("CMetaDataParserID3v2::ParseFramesL - 2"));
       
   288 #endif
       
   289 	TMetaDataFieldId fieldId;
       
   290 	TInt frameSize;
       
   291 	TInt frameHeaderSize;
       
   292 	while ( iFrameOffset < ( iFrameDataSize - 1 ) )
       
   293 		{
       
   294 		GetNextFieldL(fieldId, frameHeaderSize, frameSize);
       
   295 
       
   296 		if ( frameHeaderSize == 0 )
       
   297 			{
       
   298 			// We have hit the padding -> no more fields to read
       
   299             break;
       
   300             }
       
   301 
       
   302         if ( frameSize < 0 || frameSize > ( iFrameDataSize - iFrameOffset ) )
       
   303             {
       
   304             // Invalid frame size -> stop
       
   305             break;
       
   306             }
       
   307 		TInt err = KErrNone; 
       
   308 		if ( fieldId != EUnknownMetaDataField )
       
   309 			{
       
   310             // Look for it in the wanted field array
       
   311             TInt count( aWantedFields.Count() );
       
   312             for ( TInt i = 0; i < count; i++ )
       
   313                 {
       
   314                 if ( aWantedFields[ i ] == fieldId )
       
   315                     {
       
   316 					switch ( fieldId )
       
   317 						{
       
   318 						case EMetaDataSongTitle:
       
   319 						case EMetaDataArtist:
       
   320 						case EMetaDataAlbum:
       
   321 						case EMetaDataAlbumTrack:
       
   322 						case EMetaDataComposer:
       
   323 						case EMetaDataCopyright:
       
   324 						case EMetaDataOriginalArtist:
       
   325 							TRAP(err, GetTextInfoL( fieldId, frameSize ));
       
   326 							break;
       
   327 
       
   328 						case EMetaDataGenre:
       
   329 							TRAP(err, GetGenreL( frameSize ));
       
   330 							break;
       
   331 
       
   332 						case EMetaDataYear:
       
   333 							TRAP(err, GetTextYearL( frameSize ));
       
   334 							break;
       
   335 
       
   336 						case EMetaDataComment:
       
   337 							TRAP(err, GetCommentL( frameSize ));
       
   338 							break;
       
   339 
       
   340 						case EMetaDataUrl:
       
   341 							TRAP(err, GetUrlL( frameSize ));
       
   342 							break;
       
   343 
       
   344 						case EMetaDataJpeg:
       
   345 		                    // check for 1st album art
       
   346 		                    if (iAlbumType != K1stAlbumArt)
       
   347 		                        {
       
   348 		                        TRAP(err,GetJpegL( frameSize ));                        
       
   349 		                        }
       
   350 							break;
       
   351 									
       
   352 						case EMetaDataUserUrl:
       
   353 							TRAP(err, GetUserUrlL( frameSize ));
       
   354 							break;
       
   355 							
       
   356 						case EMetaDataDuration:
       
   357 							TRAP(err, GetDurationL( frameSize ));
       
   358 							break;
       
   359 						
       
   360 						case EMetaDataDate:
       
   361 							TRAP(err, GetTextDateL( frameSize ));
       
   362 							break;
       
   363 							
       
   364 						case EMetaDataRating:
       
   365 							TRAP(err, GetRatingL( frameSize ));
       
   366 							break;
       
   367 						
       
   368 						default:
       
   369 							break;
       
   370 						}
       
   371 					}
       
   372 				}
       
   373 			}
       
   374 		iFrameOffset += (frameSize + frameHeaderSize);
       
   375 		}
       
   376 	
       
   377 	// retrieve the album art
       
   378     TRAPD (error, RetrieveAlbumArtL());
       
   379     if (error)
       
   380         {
       
   381         #ifdef _DEBUG
       
   382             RDebug::Print(_L("CMetaDataParserID3v2::ParseFramesL-2 - RetrieveAlbumArt leave"));
       
   383         #endif        
       
   384         }
       
   385  
       
   386 	}
       
   387 	
       
   388 // -----------------------------------------------------------------------------
       
   389 // CMetaDataParserID3v2::RetrieveAlbumArtL
       
   390 // -----------------------------------------------------------------------------
       
   391 //	
       
   392 void CMetaDataParserID3v2::RetrieveAlbumArtL()
       
   393     {
       
   394     // If album art exists, add to container
       
   395     if ( iAlbumPtr != NULL )
       
   396         {
       
   397         TPtr8 des( iAlbumPtr->Des() );       
       
   398         TPtrC8 pic = des.Mid(iAlbumOffset);
       
   399         TInt length = pic.Length();
       
   400         if ( length )
       
   401             {
       
   402             iContainer->AppendL( EMetaDataJpeg, pic );
       
   403             }
       
   404          
       
   405         // reset the album related variables
       
   406         iAlbumType = -1;
       
   407         iAlbumOffset = 0;
       
   408         delete iAlbumPtr;
       
   409         iAlbumPtr = NULL;
       
   410         }
       
   411     }
       
   412 
       
   413 // -----------------------------------------------------------------------------
       
   414 // CMetaDataParserID3v2::Handlev2GetGenreL
       
   415 // -----------------------------------------------------------------------------
       
   416 //
       
   417 void CMetaDataParserID3v2::HandleV2GetGenreL( TInt aSize, TInt aKID3v2FrameHeaderLength, TInt aKID3v2GenreNameLength )
       
   418 	{
       
   419 	#ifdef _DEBUG
       
   420 	RDebug::Print(_L("CMetaDataParserID3v2::GetGenreL"));
       
   421 	#endif
       
   422 
       
   423 	HBufC8* frame = HBufC8::NewLC( aSize );
       
   424 	TPtr8 des( frame->Des() );
       
   425 
       
   426 	iSource->ReadL( iFrameOffset + aKID3v2FrameHeaderLength, des, aSize );
       
   427 
       
   428 	if ( des.Length() < aSize )
       
   429 		{
       
   430 		// Partial frame
       
   431 		User::Leave( KErrCorrupt );
       
   432 		}
       
   433 
       
   434 	TInt encoding = (TInt) (des.Left(1))[0];
       
   435 	TPtrC8 info = StripTrailingZeroes( des.Mid(1), encoding);
       
   436 	TInt length = info.Length();
       
   437 
       
   438 	if(length <= 0)
       
   439 		{
       
   440 		CleanupStack::PopAndDestroy();  // frame
       
   441 		return;
       
   442 		}
       
   443 	else 
       
   444 		{
       
   445 		length = (length > aKID3v2GenreNameLength) ? length : aKID3v2GenreNameLength;
       
   446 		}
       
   447 
       
   448 	HBufC8* genreData = HBufC8::NewLC( length );
       
   449 	TPtr8 temp( genreData->Des() );
       
   450 	temp.Copy(info);
       
   451 
       
   452 	if ( encoding == 0 )
       
   453 		{
       
   454 		   if ( temp[0] == KID3v2format )
       
   455 			{
       
   456 			//temp.Delete(0,1); 
       
   457 			TLex8 lex(temp.Ptr() + 1);
       
   458 			TInt genreID = 0;
       
   459 			TInt err = lex.Val(genreID);	
       
   460 			if(err != KErrNone)
       
   461 				{
       
   462 					CleanupStack::PopAndDestroy(2);  // genreData, frame
       
   463 					return;
       
   464 				}
       
   465 			if(genreID >= 0 && genreID <= 125 || genreID == 199)
       
   466 				{
       
   467 				temp.FillZ(0);
       
   468 				MapID3GenreToStringL(genreID,temp);
       
   469 				}
       
   470 			}
       
   471 			
       
   472 			if( length )
       
   473 			 {
       
   474 			 HBufC* data16 = HBufC::NewLC( length );
       
   475 		 	 TPtr unicode( data16->Des() );
       
   476 		 	 if ( ConvertToUnicodeL(encoding, temp, unicode) == KErrNone )
       
   477 				{
       
   478 					iContainer->AppendL( EMetaDataGenre, unicode );
       
   479 				}
       
   480 			 CleanupStack::PopAndDestroy(data16);  // data16
       
   481 			 }
       
   482 		}
       
   483 	else // non ASCII 
       
   484 		{
       
   485 		HBufC* dataGen16 = HBufC::NewLC( length );
       
   486 		TPtr unicodeGen( dataGen16->Des() );
       
   487 		if ( ConvertToUnicodeL(encoding, temp, unicodeGen) == KErrNone )
       
   488 			{
       
   489 			if (temp.Length() <= 2)
       
   490 			    {
       
   491 		        CleanupStack::PopAndDestroy(3);  // dataGen16, genreData, frame
       
   492 				return;			    
       
   493 			    }
       
   494 			temp = temp.Mid(2);
       
   495 			if(temp[0] == KID3v2format)
       
   496 				{
       
   497 				TLex16 lex(unicodeGen.Ptr()+1);
       
   498 				TInt val=0;
       
   499 				TInt err = lex.Val(val);
       
   500 				if(err != KErrNone)
       
   501 					{
       
   502 					CleanupStack::PopAndDestroy(3);  // dataGen16, genreData, frame
       
   503 					return;
       
   504 					}
       
   505 					
       
   506 				if(val >= 0 && val <= 125 || val == 199)
       
   507 					{
       
   508 					unicodeGen.FillZ(0);
       
   509 					MapID3GenreToStringL(val,unicodeGen);
       
   510 					}
       
   511 				}
       
   512 			iContainer->AppendL( EMetaDataGenre, unicodeGen );				
       
   513 			}
       
   514 		CleanupStack::PopAndDestroy(dataGen16);  // dataGen16
       
   515 		}
       
   516 	CleanupStack::PopAndDestroy(genreData);  // genreData
       
   517 	CleanupStack::PopAndDestroy(frame);  // frame	
       
   518 	}
       
   519 
       
   520 // -----------------------------------------------------------------------------
       
   521 // CMetaDataParserID3v2::VersionL
       
   522 // -----------------------------------------------------------------------------
       
   523 //
       
   524 TInt CMetaDataParserID3v2::VersionL(
       
   525 	CMetaDataSource& aSource )
       
   526 	{
       
   527 	TInt size = 0;
       
   528 	aSource.Size( size );
       
   529 	if ( size < KID3v2HeaderLength )
       
   530 		{
       
   531 		// This isn't ID3v2
       
   532 		return KErrNotFound;
       
   533 		}
       
   534 
       
   535 	TBuf8<KID3v2HeaderLength> header;
       
   536 	aSource.ReadL( header );
       
   537 	// ID3v2 header consists of following parts:
       
   538     // - identifier "ID3", 3 bytes
       
   539     // - version, 2 bytes
       
   540     // - flags, 1 byte
       
   541     // - data length, 4 bytes
       
   542 
       
   543 	if ( header.Left( KID3v2TagLength ).Compare( KID3v2Tag ) != 0 )
       
   544 		{
       
   545 		return KErrNotFound;
       
   546 		}
       
   547 
       
   548 	TInt frameSize = 0;
       
   549 	for ( TInt i = 6; i < 10; i++ )
       
   550 		{
       
   551 		frameSize <<= 7;
       
   552 		frameSize |= header[i] & 0x7f;
       
   553 		}
       
   554 
       
   555 	if ( size < ( frameSize + KID3v2HeaderLength ) )
       
   556 		{
       
   557 		// Partial ID3v2 tag
       
   558 		User::Leave( KErrCorrupt );
       
   559 		}
       
   560 
       
   561 	return (TInt) header[3];
       
   562 	}
       
   563 
       
   564 // -----------------------------------------------------------------------------
       
   565 // CMetaDataParserID3v2::CreateCharacterSetsL
       
   566 // -----------------------------------------------------------------------------
       
   567 //
       
   568 void CMetaDataParserID3v2::CreateCharacterSetsL()
       
   569 	{
       
   570 	// Get list of charconv supported character sets
       
   571 	iCharacterSet = CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableL(iFs);
       
   572 	iTopCharacterSet = new (ELeave) CArrayFixFlat<CCnvCharacterSetConverter::SCharacterSet>(12);
       
   573 	GenerateTopCharacterSetsL();
       
   574 	}
       
   575 	
       
   576 // -----------------------------------------------------------------------------
       
   577 // CMetaDataParserID3v1::DetectCharacterSetL
       
   578 // -----------------------------------------------------------------------------
       
   579 //
       
   580 TInt CMetaDataParserID3v2::DetectCharacterSetL(
       
   581 	const TDesC8& aDesc)
       
   582 	{
       
   583 	TInt confidence = 0;
       
   584 	TInt highestConfidence = 0;
       
   585 	TUint charSetId;
       
   586 	TUint highestConfidencecharSetId = 0;
       
   587 
       
   588 	CCnvCharacterSetConverter* charSetConv = CCnvCharacterSetConverter::NewLC();
       
   589 	TInt count = iTopCharacterSet->Count();
       
   590 	for ( TInt i=0; i < iTopCharacterSet->Count(); i++)
       
   591 		{
       
   592 		charSetId = iTopCharacterSet->At(i).Identifier();
       
   593 		charSetConv->ConvertibleToCharSetL(confidence, charSetId, *iTopCharacterSet, aDesc);
       
   594 		if ( confidence > highestConfidence )
       
   595 			{
       
   596 			highestConfidence = confidence;
       
   597 			highestConfidencecharSetId = charSetId;
       
   598 			}
       
   599 		}
       
   600 	CleanupStack::PopAndDestroy(charSetConv);
       
   601 #ifdef _DEBUG
       
   602 	RDebug::Print(_L("CMetaDataParserID3v1::DetectCharacterSetL :-> Confidence[%d] CharSetId[%x]"),
       
   603 	        highestConfidence, highestConfidencecharSetId);
       
   604 #endif
       
   605 
       
   606 	if ( (highestConfidence >= KMinimumConfidenceRequired) || (iAutoDetectJapanese && highestConfidence >= KMinimumJapaneseConfidenceRequired ))
       
   607 		{
       
   608 		iCharacterSetId = highestConfidencecharSetId;
       
   609 		return KErrNone;
       
   610 		}
       
   611 	else
       
   612 		{
       
   613 		return KErrNotFound;
       
   614 		}
       
   615 	}
       
   616 
       
   617 // -----------------------------------------------------------------------------
       
   618 // CMetaDataParserID3v2::AutoDetectL
       
   619 // -----------------------------------------------------------------------------
       
   620 //
       
   621 TInt CMetaDataParserID3v2::AutoDetectL(const TDesC8& aDesc,
       
   622 	TDes16& aUnicode)
       
   623 {
       
   624 	if ( iCharacterSetId == 0 )
       
   625 		{
       
   626 		if ( DetectCharacterSetL(aDesc) == KErrNotFound )
       
   627 			{
       
   628 			return KErrNotFound;
       
   629 			}
       
   630 		}
       
   631 
       
   632 	CCnvCharacterSetConverter* charSetConv = CCnvCharacterSetConverter::NewLC();
       
   633 	TInt state = CCnvCharacterSetConverter::KStateDefault;
       
   634 	TInt numOfUnconvertibleChars = 0;
       
   635 
       
   636 	charSetConv->PrepareToConvertToOrFromL(iCharacterSetId, *iCharacterSet, iFs);
       
   637 	TInt retVal = charSetConv->ConvertToUnicode(aUnicode, aDesc, state, numOfUnconvertibleChars);
       
   638 #ifdef _DEBUG
       
   639 	RDebug::Print(_L("CMetaDataParserID3v1::ConvertToUnicode :-> Tag Size[%d] Unicode Tag Size[%d]Bytes Unconverted[%d] retVal[%d]"),
       
   640 		aDesc.Length(), aUnicode.Length(), numOfUnconvertibleChars, retVal);
       
   641 #endif
       
   642 	if ( retVal < 0 )
       
   643 		{
       
   644 		CleanupStack::PopAndDestroy();	// charSetConv
       
   645 		return retVal;
       
   646 		//return KErrGeneral;
       
   647 		}
       
   648 
       
   649 	if ( retVal > 0 || numOfUnconvertibleChars > 0 )
       
   650 		{
       
   651 		// This is different character set. Need to auto detect again
       
   652 		if ( DetectCharacterSetL(aDesc) == KErrNotFound )
       
   653 			{
       
   654 			CleanupStack::PopAndDestroy();	// charSetConv
       
   655 			return KErrNotFound;
       
   656 			}
       
   657 		state = CCnvCharacterSetConverter::KStateDefault;
       
   658 		numOfUnconvertibleChars = 0;
       
   659 		charSetConv->PrepareToConvertToOrFromL(iCharacterSetId, *iCharacterSet, iFs);
       
   660 		retVal = charSetConv->ConvertToUnicode(aUnicode, aDesc, state, numOfUnconvertibleChars);
       
   661 #ifdef _DEBUG
       
   662 	RDebug::Print(_L("CMetaDataParserID3v1::ConvertToUnicode :-> Tag Size[%d] Unicode Tag Size[%d]Bytes Unconverted[%d] retVal[%d]"),
       
   663 		aDesc.Length(), aUnicode.Length(), numOfUnconvertibleChars, retVal);
       
   664 #endif
       
   665         if ( retVal != 0 || numOfUnconvertibleChars > 0 )
       
   666 			{
       
   667 	        CleanupStack::PopAndDestroy();	// charSetConv
       
   668 	        return KErrGeneral;
       
   669 			}
       
   670 		}
       
   671 	CleanupStack::PopAndDestroy();	// charSetConv
       
   672 	return KErrNone;
       
   673 }
       
   674 
       
   675 
       
   676 
       
   677 // -----------------------------------------------------------------------------
       
   678 // CMetaDataParserID3v2::Version()
       
   679 // -----------------------------------------------------------------------------
       
   680 //
       
   681 TID3Version CMetaDataParserID3v2::ID3Version()
       
   682 {
       
   683 	return EID3Version2;
       
   684 }
       
   685 
       
   686 
       
   687 //-----------------------------------------------------------------------------
       
   688 // CMetaDataParserID3v2::NeedRetrieveAlbumArt( TInt aPicType )
       
   689 //-----------------------------------------------------------------------------
       
   690 //
       
   691 TBool CMetaDataParserID3v2::NeedRetrieveAlbumArt( TInt aPicType )
       
   692 {
       
   693     TBool ret = EFalse;
       
   694     
       
   695     switch (iAlbumType)
       
   696         {
       
   697         case K1stAlbumArt : 
       
   698             // return EFalse, no need to retrieve another album art
       
   699             break;
       
   700         case K2ndAlbumArt : 
       
   701             if (aPicType == K1stAlbumArt)
       
   702             {
       
   703                 ret = ETrue;            
       
   704             }
       
   705             break;
       
   706         case K3rdAlbumArt : 
       
   707             if ((aPicType == K1stAlbumArt) ||
       
   708                 (aPicType == K2ndAlbumArt))
       
   709             {
       
   710                 ret = ETrue;            
       
   711             }
       
   712             break;
       
   713         default:
       
   714             // There is no album art, or it is a priority album art
       
   715             if ((iAlbumType == -1) ||
       
   716                 (aPicType == K1stAlbumArt) ||
       
   717                 (aPicType == K2ndAlbumArt) ||
       
   718                 (aPicType == K3rdAlbumArt))
       
   719             {
       
   720                 ret = ETrue;            
       
   721             }
       
   722             // if the old one is bad, and the new one is good, use it
       
   723             else
       
   724             {
       
   725                 if ( IgnoreAlbumType(iAlbumType) && !IgnoreAlbumType(aPicType) )
       
   726                 {   
       
   727                     // get the new one
       
   728                     ret = ETrue;            
       
   729                 }
       
   730             }
       
   731 
       
   732         }
       
   733     
       
   734     return ret;
       
   735 }
       
   736 
       
   737 
       
   738 //-----------------------------------------------------------------------------
       
   739 // CMetaDataParserID3v2::IgnoreAlbumType( TInt aPicType )
       
   740 //-----------------------------------------------------------------------------
       
   741 //
       
   742 TBool CMetaDataParserID3v2::IgnoreAlbumType (TInt aPicType)
       
   743 {
       
   744     if (aPicType == KPictureTypePixel || aPicType == KPictureTypeFileIcon)
       
   745         {
       
   746         return ETrue;
       
   747         }
       
   748    
       
   749     return EFalse;
       
   750       
       
   751 }
       
   752 //  End of File