mmserv/metadatautility/Src/MetaDataParserID3v2.cpp
changeset 0 71ca22bcf22a
child 28 ebf79c79991a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmserv/metadatautility/Src/MetaDataParserID3v2.cpp	Tue Feb 02 01:08:46 2010 +0200
@@ -0,0 +1,752 @@
+/*
+* Copyright (c) 2004 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:  This class provides the base class for ID3v2 parsers.
+*
+*/
+
+
+
+// INCLUDE FILES
+#include	"MetaDataParserID3v2.h"
+#include	"MetaDataParserID3v22.h"
+#include	"MetaDataParserID3v23.h"
+#include	"MetaDataParserID3v24.h"
+#include 	"MetaDataSourceDescriptor.h"
+
+#include    <barsc.h>
+#include    <barsread.h>
+#include	<TopCharacterSet.rsg>
+#include 	<data_caging_path_literals.hrh>
+
+// CONSTANTS
+// (ID3v2 specification found in www.id3.org)
+const TInt KID3v2HeaderLength 			= 10;
+const TInt KID3v2TagLength 				= 3;
+
+const TInt KMinimumConfidenceRequired = 90;
+const TInt KMinimumJapaneseConfidenceRequired = 75;
+const TUint KParseFromMemory	= 1000000; 
+
+//Album Type
+const TInt KPictureTypeOther				= 0x00;
+const TInt KPictureTypePixel                = 0x01;
+const TInt KPictureTypeFileIcon             = 0x02;
+const TInt KPictureTypeFrontCover			= 0x03;
+const TInt KPictureTypeBackCover            = 0x04;
+
+// Album Type priority
+const TInt K1stAlbumArt = KPictureTypeOther;
+const TInt K2ndAlbumArt = KPictureTypeFrontCover; 
+const TInt K3rdAlbumArt = KPictureTypeBackCover;
+
+_LIT8( KID3v2Tag, "ID3" );
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CMetaDataParserID3v2::CMetaDataParserID3v2
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CMetaDataParserID3v2::CMetaDataParserID3v2(
+	CMetaDataSource& aSource )
+	:	iSource(&aSource),
+        iParseFromDescriptor(EFalse),
+        iAlbumType(-1),
+        iAlbumPtr(NULL)
+	{
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataParserID3v2::CreateID3v2ParserL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CMetaDataParserID3v2* CMetaDataParserID3v2::CreateID3v2ParserL(
+	CMetaDataSource& aSource )
+    {
+#ifdef _DEBUG
+	RDebug::Print(_L("CMetaDataParserID3v2::CreateID3v2ParserL"));
+#endif
+	TInt version = VersionL(aSource);
+
+	CMetaDataParserID3v2* parser = NULL;
+	switch ( version )
+		{
+		case 2:
+			parser = STATIC_CAST( CMetaDataParserID3v2*, CMetaDataParserID3v22::NewL(aSource) );
+			break;
+		case 3:
+			parser = STATIC_CAST( CMetaDataParserID3v2*, CMetaDataParserID3v23::NewL(aSource) );
+			break;
+		case 4:
+			parser = STATIC_CAST( CMetaDataParserID3v2*, CMetaDataParserID3v24::NewL(aSource) );
+			break;
+		default:	// KErrNotFound
+			break;
+		}
+	return parser;
+    }
+
+// Destructor
+CMetaDataParserID3v2::~CMetaDataParserID3v2()
+	{
+	if(iAutoDetectChinese || iAutoDetectRussian || iAutoDetectJapanese)
+		{
+		delete iCharacterSet;
+		delete iTopCharacterSet;
+		}
+	if(iParseFromDescriptor)
+		{
+		delete iTag;
+		delete iSourceDes;
+		}
+	if ( iAlbumPtr )
+		{
+		delete iAlbumPtr;
+		}
+
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataParserID3v2::ParseL
+// -----------------------------------------------------------------------------
+//
+void CMetaDataParserID3v2::ParseL(
+	const RArray<TMetaDataFieldId>& aWantedFields,
+	CMetaDataFieldContainer& aContainer )
+    {
+#ifdef _DEBUG
+	RDebug::Print(_L("CMetaDataParserID3v2::ParseL"));
+#endif
+	iContainer = &aContainer;
+	PrepareToParseL();
+	CRepository *metadataRepository = CRepository::NewL(KCRUidMetadataUtility);
+	TInt err = KErrNone;
+	err = metadataRepository->Get(KMetadataUtilityAutoDetectChineseChars, iAutoDetectChinese);
+	if(err)
+	{
+		iAutoDetectChinese = EFalse;	
+	}
+	err = metadataRepository->Get(KMetadataUtilityAutoDetectJapaneseChars, iAutoDetectJapanese);
+	if(err)
+	{
+		iAutoDetectJapanese = EFalse;	
+	}
+	delete metadataRepository;
+	TLanguage lang = User::Language();
+	if(lang == ELangRussian || lang == ELangUkrainian)	
+		{
+		iAutoDetectRussian = ETrue;	
+		}
+	if(iAutoDetectChinese || iAutoDetectRussian || iAutoDetectJapanese)
+		{
+		CreateCharacterSetsL();
+		}
+	// choose if want to parse from descriptor
+	if(iFrameDataSize < KParseFromMemory) // 1Mb
+		{
+		iTag = HBufC8::NewL(iFrameDataSize);
+		TPtr8 des( iTag->Des() );
+		iSource->ReadL(0, des);
+		
+		iSourceDes = CMetaDataSourceDescriptor::NewL(des);
+		iSource = iSourceDes;
+		iParseFromDescriptor = ETrue;
+		}
+	if ( aWantedFields.Count() == 0 )
+		{
+		ParseFramesL();
+		}
+	else
+		{
+		ParseFramesL(aWantedFields);
+		}
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataParserID3v2::ParseFramesL
+// -----------------------------------------------------------------------------
+//
+void CMetaDataParserID3v2::ParseFramesL()
+	{
+#ifdef _DEBUG
+	RDebug::Print(_L("CMetaDataParserID3v2::ParseFramesL"));
+#endif
+	TMetaDataFieldId fieldId;
+	TInt frameSize;
+	TInt frameHeaderSize = 0;
+	while ( iFrameOffset < ( iFrameDataSize - 1 ) )
+		{
+		GetNextFieldL(fieldId, frameHeaderSize, frameSize);
+
+		if ( frameHeaderSize == 0 )
+			{
+			// We have hit the padding -> no more fields to read
+            break;
+            }
+
+        if ( frameSize < 0 || frameSize > ( iFrameDataSize - iFrameOffset ) )
+            {
+            // Invalid frame size -> stop
+            break;
+            }
+		TInt err = KErrNone; // ignore err, as some entry may be extracted without exception
+		if ( fieldId != EUnknownMetaDataField )
+			{
+			switch ( fieldId )
+				{
+				case EMetaDataSongTitle:
+				case EMetaDataArtist:
+				case EMetaDataAlbum:
+				case EMetaDataAlbumTrack:
+				case EMetaDataComposer:
+				case EMetaDataCopyright:
+				case EMetaDataOriginalArtist:
+					TRAP(err, GetTextInfoL( fieldId, frameSize ));
+					break;
+
+				case EMetaDataGenre:
+					TRAP(err, GetGenreL( frameSize ));
+					break;
+
+				case EMetaDataYear:
+					TRAP(err, GetTextYearL( frameSize ));
+					break;
+
+				case EMetaDataComment:
+					TRAP(err, GetCommentL( frameSize ));
+					break;
+
+				case EMetaDataUrl:
+					TRAP(err, GetUrlL( frameSize ));
+					break;
+				
+				case EMetaDataUserUrl:
+					TRAP(err, GetUserUrlL( frameSize ));
+					break;
+					
+				case EMetaDataJpeg:
+				    // check for 1st album art
+				    if (iAlbumType != K1stAlbumArt)
+				        {
+	                    TRAP(err,GetJpegL( frameSize ));				        
+				        }
+					break;
+
+				case EMetaDataDuration:
+					TRAP(err, GetDurationL( frameSize ));
+					break;
+				
+				case EMetaDataDate:
+					TRAP(err, GetTextDateL( frameSize ));
+					break;
+						
+				case EMetaDataRating:
+					TRAP(err, GetRatingL( frameSize ));
+					break;
+							
+				default:
+					break;
+				}
+			}
+		iFrameOffset += (frameSize + frameHeaderSize);
+		}
+    
+    // retrieve the album art
+    TRAPD (error, RetrieveAlbumArtL());
+    if (error)
+        {
+        #ifdef _DEBUG
+            RDebug::Print(_L("CMetaDataParserID3v2::ParseFramesL - RetrieveAlbumArt leave"));
+        #endif        
+        }
+  
+	}
+
+// -----------------------------------------------------------------------------
+// CMetaDataParserID3v2::ParseFramesL
+// -----------------------------------------------------------------------------
+//
+void CMetaDataParserID3v2::ParseFramesL(
+	const RArray<TMetaDataFieldId>& aWantedFields )
+	{
+#ifdef _DEBUG
+	RDebug::Print(_L("CMetaDataParserID3v2::ParseFramesL - 2"));
+#endif
+	TMetaDataFieldId fieldId;
+	TInt frameSize;
+	TInt frameHeaderSize;
+	while ( iFrameOffset < ( iFrameDataSize - 1 ) )
+		{
+		GetNextFieldL(fieldId, frameHeaderSize, frameSize);
+
+		if ( frameHeaderSize == 0 )
+			{
+			// We have hit the padding -> no more fields to read
+            break;
+            }
+
+        if ( frameSize < 0 || frameSize > ( iFrameDataSize - iFrameOffset ) )
+            {
+            // Invalid frame size -> stop
+            break;
+            }
+		TInt err = KErrNone; 
+		if ( fieldId != EUnknownMetaDataField )
+			{
+            // Look for it in the wanted field array
+            TInt count( aWantedFields.Count() );
+            for ( TInt i = 0; i < count; i++ )
+                {
+                if ( aWantedFields[ i ] == fieldId )
+                    {
+					switch ( fieldId )
+						{
+						case EMetaDataSongTitle:
+						case EMetaDataArtist:
+						case EMetaDataAlbum:
+						case EMetaDataAlbumTrack:
+						case EMetaDataComposer:
+						case EMetaDataCopyright:
+						case EMetaDataOriginalArtist:
+							TRAP(err, GetTextInfoL( fieldId, frameSize ));
+							break;
+
+						case EMetaDataGenre:
+							TRAP(err, GetGenreL( frameSize ));
+							break;
+
+						case EMetaDataYear:
+							TRAP(err, GetTextYearL( frameSize ));
+							break;
+
+						case EMetaDataComment:
+							TRAP(err, GetCommentL( frameSize ));
+							break;
+
+						case EMetaDataUrl:
+							TRAP(err, GetUrlL( frameSize ));
+							break;
+
+						case EMetaDataJpeg:
+		                    // check for 1st album art
+		                    if (iAlbumType != K1stAlbumArt)
+		                        {
+		                        TRAP(err,GetJpegL( frameSize ));                        
+		                        }
+							break;
+									
+						case EMetaDataUserUrl:
+							TRAP(err, GetUserUrlL( frameSize ));
+							break;
+							
+						case EMetaDataDuration:
+							TRAP(err, GetDurationL( frameSize ));
+							break;
+						
+						case EMetaDataDate:
+							TRAP(err, GetTextDateL( frameSize ));
+							break;
+							
+						case EMetaDataRating:
+							TRAP(err, GetRatingL( frameSize ));
+							break;
+						
+						default:
+							break;
+						}
+					}
+				}
+			}
+		iFrameOffset += (frameSize + frameHeaderSize);
+		}
+	
+	// retrieve the album art
+    TRAPD (error, RetrieveAlbumArtL());
+    if (error)
+        {
+        #ifdef _DEBUG
+            RDebug::Print(_L("CMetaDataParserID3v2::ParseFramesL-2 - RetrieveAlbumArt leave"));
+        #endif        
+        }
+ 
+	}
+	
+// -----------------------------------------------------------------------------
+// CMetaDataParserID3v2::RetrieveAlbumArtL
+// -----------------------------------------------------------------------------
+//	
+void CMetaDataParserID3v2::RetrieveAlbumArtL()
+    {
+    // If album art exists, add to container
+    if ( iAlbumPtr != NULL )
+        {
+        TPtr8 des( iAlbumPtr->Des() );       
+        TPtrC8 pic = des.Mid(iAlbumOffset);
+        TInt length = pic.Length();
+        if ( length )
+            {
+            iContainer->AppendL( EMetaDataJpeg, pic );
+            }
+         
+        // reset the album related variables
+        iAlbumType = -1;
+        iAlbumOffset = 0;
+        delete iAlbumPtr;
+        iAlbumPtr = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataParserID3v2::Handlev2GetGenreL
+// -----------------------------------------------------------------------------
+//
+void CMetaDataParserID3v2::HandleV2GetGenreL( TInt aSize, TInt aKID3v2FrameHeaderLength, TInt aKID3v2GenreNameLength )
+	{
+	#ifdef _DEBUG
+	RDebug::Print(_L("CMetaDataParserID3v2::GetGenreL"));
+	#endif
+
+	HBufC8* frame = HBufC8::NewLC( aSize );
+	TPtr8 des( frame->Des() );
+
+	iSource->ReadL( iFrameOffset + aKID3v2FrameHeaderLength, des, aSize );
+
+	if ( des.Length() < aSize )
+		{
+		// Partial frame
+		User::Leave( KErrCorrupt );
+		}
+
+	TInt encoding = (TInt) (des.Left(1))[0];
+	TPtrC8 info = StripTrailingZeroes( des.Mid(1), encoding);
+	TInt length = info.Length();
+
+	if(length <= 0)
+		{
+		CleanupStack::PopAndDestroy();  // frame
+		return;
+		}
+	else 
+		{
+		length = (length > aKID3v2GenreNameLength) ? length : aKID3v2GenreNameLength;
+		}
+
+	HBufC8* genreData = HBufC8::NewLC( length );
+	TPtr8 temp( genreData->Des() );
+	temp.Copy(info);
+
+	if ( encoding == 0 )
+		{
+		   if ( temp[0] == KID3v2format )
+			{
+			//temp.Delete(0,1); 
+			TLex8 lex(temp.Ptr() + 1);
+			TInt genreID = 0;
+			TInt err = lex.Val(genreID);	
+			if(err != KErrNone)
+				{
+					CleanupStack::PopAndDestroy(2);  // genreData, frame
+					return;
+				}
+			if(genreID >= 0 && genreID <= 125 || genreID == 199)
+				{
+				temp.FillZ(0);
+				MapID3GenreToStringL(genreID,temp);
+				}
+			}
+			
+			if( length )
+			 {
+			 HBufC* data16 = HBufC::NewLC( length );
+		 	 TPtr unicode( data16->Des() );
+		 	 if ( ConvertToUnicodeL(encoding, temp, unicode) == KErrNone )
+				{
+					iContainer->AppendL( EMetaDataGenre, unicode );
+				}
+			 CleanupStack::PopAndDestroy(data16);  // data16
+			 }
+		}
+	else // non ASCII 
+		{
+		HBufC* dataGen16 = HBufC::NewLC( length );
+		TPtr unicodeGen( dataGen16->Des() );
+		if ( ConvertToUnicodeL(encoding, temp, unicodeGen) == KErrNone )
+			{
+			if (temp.Length() <= 2)
+			    {
+		        CleanupStack::PopAndDestroy(3);  // dataGen16, genreData, frame
+				return;			    
+			    }
+			temp = temp.Mid(2);
+			if(temp[0] == KID3v2format)
+				{
+				TLex16 lex(unicodeGen.Ptr()+1);
+				TInt val=0;
+				TInt err = lex.Val(val);
+				if(err != KErrNone)
+					{
+					CleanupStack::PopAndDestroy(3);  // dataGen16, genreData, frame
+					return;
+					}
+					
+				if(val >= 0 && val <= 125 || val == 199)
+					{
+					unicodeGen.FillZ(0);
+					MapID3GenreToStringL(val,unicodeGen);
+					}
+				}
+			iContainer->AppendL( EMetaDataGenre, unicodeGen );				
+			}
+		CleanupStack::PopAndDestroy(dataGen16);  // dataGen16
+		}
+	CleanupStack::PopAndDestroy(genreData);  // genreData
+	CleanupStack::PopAndDestroy(frame);  // frame	
+	}
+
+// -----------------------------------------------------------------------------
+// CMetaDataParserID3v2::VersionL
+// -----------------------------------------------------------------------------
+//
+TInt CMetaDataParserID3v2::VersionL(
+	CMetaDataSource& aSource )
+	{
+	TInt size = 0;
+	aSource.Size( size );
+	if ( size < KID3v2HeaderLength )
+		{
+		// This isn't ID3v2
+		return KErrNotFound;
+		}
+
+	TBuf8<KID3v2HeaderLength> header;
+	aSource.ReadL( header );
+	// ID3v2 header consists of following parts:
+    // - identifier "ID3", 3 bytes
+    // - version, 2 bytes
+    // - flags, 1 byte
+    // - data length, 4 bytes
+
+	if ( header.Left( KID3v2TagLength ).Compare( KID3v2Tag ) != 0 )
+		{
+		return KErrNotFound;
+		}
+
+	TInt frameSize = 0;
+	for ( TInt i = 6; i < 10; i++ )
+		{
+		frameSize <<= 7;
+		frameSize |= header[i] & 0x7f;
+		}
+
+	if ( size < ( frameSize + KID3v2HeaderLength ) )
+		{
+		// Partial ID3v2 tag
+		User::Leave( KErrCorrupt );
+		}
+
+	return (TInt) header[3];
+	}
+
+// -----------------------------------------------------------------------------
+// CMetaDataParserID3v2::CreateCharacterSetsL
+// -----------------------------------------------------------------------------
+//
+void CMetaDataParserID3v2::CreateCharacterSetsL()
+	{
+	// Get list of charconv supported character sets
+	iCharacterSet = CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableL(iFs);
+	iTopCharacterSet = new (ELeave) CArrayFixFlat<CCnvCharacterSetConverter::SCharacterSet>(12);
+	GenerateTopCharacterSetsL();
+	}
+	
+// -----------------------------------------------------------------------------
+// CMetaDataParserID3v1::DetectCharacterSetL
+// -----------------------------------------------------------------------------
+//
+TInt CMetaDataParserID3v2::DetectCharacterSetL(
+	const TDesC8& aDesc)
+	{
+	TInt confidence = 0;
+	TInt highestConfidence = 0;
+	TUint charSetId;
+	TUint highestConfidencecharSetId = 0;
+
+	CCnvCharacterSetConverter* charSetConv = CCnvCharacterSetConverter::NewLC();
+	TInt count = iTopCharacterSet->Count();
+	for ( TInt i=0; i < iTopCharacterSet->Count(); i++)
+		{
+		charSetId = iTopCharacterSet->At(i).Identifier();
+		charSetConv->ConvertibleToCharSetL(confidence, charSetId, *iTopCharacterSet, aDesc);
+		if ( confidence > highestConfidence )
+			{
+			highestConfidence = confidence;
+			highestConfidencecharSetId = charSetId;
+			}
+		}
+	CleanupStack::PopAndDestroy(charSetConv);
+#ifdef _DEBUG
+	RDebug::Print(_L("CMetaDataParserID3v1::DetectCharacterSetL :-> Confidence[%d] CharSetId[%x]"),
+	        highestConfidence, highestConfidencecharSetId);
+#endif
+
+	if ( (highestConfidence >= KMinimumConfidenceRequired) || (iAutoDetectJapanese && highestConfidence >= KMinimumJapaneseConfidenceRequired ))
+		{
+		iCharacterSetId = highestConfidencecharSetId;
+		return KErrNone;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CMetaDataParserID3v2::AutoDetectL
+// -----------------------------------------------------------------------------
+//
+TInt CMetaDataParserID3v2::AutoDetectL(const TDesC8& aDesc,
+	TDes16& aUnicode)
+{
+	if ( iCharacterSetId == 0 )
+		{
+		if ( DetectCharacterSetL(aDesc) == KErrNotFound )
+			{
+			return KErrNotFound;
+			}
+		}
+
+	CCnvCharacterSetConverter* charSetConv = CCnvCharacterSetConverter::NewLC();
+	TInt state = CCnvCharacterSetConverter::KStateDefault;
+	TInt numOfUnconvertibleChars = 0;
+
+	charSetConv->PrepareToConvertToOrFromL(iCharacterSetId, *iCharacterSet, iFs);
+	TInt retVal = charSetConv->ConvertToUnicode(aUnicode, aDesc, state, numOfUnconvertibleChars);
+#ifdef _DEBUG
+	RDebug::Print(_L("CMetaDataParserID3v1::ConvertToUnicode :-> Tag Size[%d] Unicode Tag Size[%d]Bytes Unconverted[%d] retVal[%d]"),
+		aDesc.Length(), aUnicode.Length(), numOfUnconvertibleChars, retVal);
+#endif
+	if ( retVal < 0 )
+		{
+		CleanupStack::PopAndDestroy();	// charSetConv
+		return retVal;
+		//return KErrGeneral;
+		}
+
+	if ( retVal > 0 || numOfUnconvertibleChars > 0 )
+		{
+		// This is different character set. Need to auto detect again
+		if ( DetectCharacterSetL(aDesc) == KErrNotFound )
+			{
+			CleanupStack::PopAndDestroy();	// charSetConv
+			return KErrNotFound;
+			}
+		state = CCnvCharacterSetConverter::KStateDefault;
+		numOfUnconvertibleChars = 0;
+		charSetConv->PrepareToConvertToOrFromL(iCharacterSetId, *iCharacterSet, iFs);
+		retVal = charSetConv->ConvertToUnicode(aUnicode, aDesc, state, numOfUnconvertibleChars);
+#ifdef _DEBUG
+	RDebug::Print(_L("CMetaDataParserID3v1::ConvertToUnicode :-> Tag Size[%d] Unicode Tag Size[%d]Bytes Unconverted[%d] retVal[%d]"),
+		aDesc.Length(), aUnicode.Length(), numOfUnconvertibleChars, retVal);
+#endif
+        if ( retVal != 0 || numOfUnconvertibleChars > 0 )
+			{
+	        CleanupStack::PopAndDestroy();	// charSetConv
+	        return KErrGeneral;
+			}
+		}
+	CleanupStack::PopAndDestroy();	// charSetConv
+	return KErrNone;
+}
+
+
+
+// -----------------------------------------------------------------------------
+// CMetaDataParserID3v2::Version()
+// -----------------------------------------------------------------------------
+//
+TID3Version CMetaDataParserID3v2::ID3Version()
+{
+	return EID3Version2;
+}
+
+
+//-----------------------------------------------------------------------------
+// CMetaDataParserID3v2::NeedRetrieveAlbumArt( TInt aPicType )
+//-----------------------------------------------------------------------------
+//
+TBool CMetaDataParserID3v2::NeedRetrieveAlbumArt( TInt aPicType )
+{
+    TBool ret = EFalse;
+    
+    switch (iAlbumType)
+        {
+        case K1stAlbumArt : 
+            // return EFalse, no need to retrieve another album art
+            break;
+        case K2ndAlbumArt : 
+            if (aPicType == K1stAlbumArt)
+            {
+                ret = ETrue;            
+            }
+            break;
+        case K3rdAlbumArt : 
+            if ((aPicType == K1stAlbumArt) ||
+                (aPicType == K2ndAlbumArt))
+            {
+                ret = ETrue;            
+            }
+            break;
+        default:
+            // There is no album art, or it is a priority album art
+            if ((iAlbumType == -1) ||
+                (aPicType == K1stAlbumArt) ||
+                (aPicType == K2ndAlbumArt) ||
+                (aPicType == K3rdAlbumArt))
+            {
+                ret = ETrue;            
+            }
+            // if the old one is bad, and the new one is good, use it
+            else
+            {
+                if ( IgnoreAlbumType(iAlbumType) && !IgnoreAlbumType(aPicType) )
+                {   
+                    // get the new one
+                    ret = ETrue;            
+                }
+            }
+
+        }
+    
+    return ret;
+}
+
+
+//-----------------------------------------------------------------------------
+// CMetaDataParserID3v2::IgnoreAlbumType( TInt aPicType )
+//-----------------------------------------------------------------------------
+//
+TBool CMetaDataParserID3v2::IgnoreAlbumType (TInt aPicType)
+{
+    if (aPicType == KPictureTypePixel || aPicType == KPictureTypeFileIcon)
+        {
+        return ETrue;
+        }
+   
+    return EFalse;
+      
+}
+//  End of File