diff -r 000000000000 -r 71ca22bcf22a mmserv/metadatautility/Src/MetaDataParserID3v24.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmserv/metadatautility/Src/MetaDataParserID3v24.cpp Tue Feb 02 01:08:46 2010 +0200 @@ -0,0 +1,823 @@ +/* +* 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 implements parsing of ID3v2.4 according to the +* specification found in www.id3.org. Note that only a selected +* frames are supported at this time. +* +*/ + + + +// INCLUDE FILES +#include +#include "MetaDataParserID3v24.h" + +// CONSTANTS +// (ID3v2.4 specification found in www.id3.org) +const TInt KID3v2HeaderLength = 10; +const TInt KID3v2ExtendedHeaderLength = 6; +const TInt KID3v2FrameHeaderLength = 10; +const TInt KID3v2FrameIdLength = 4; +const TInt KID3v2GenreNameLength = 24; + +_LIT8( KID3v2FrameIdTitle, "TIT2" ); +_LIT8( KID3v2FrameIdArtist, "TPE1" ); +_LIT8( KID3v2FrameIdAlbum, "TALB" ); +_LIT8( KID3v2FrameIdYear, "TDRC" ); +_LIT8( KID3v2FrameIdComment, "COMM" ); +_LIT8( KID3v2FrameIdTrack, "TRCK" ); +_LIT8( KID3v2FrameIdGenre, "TCON" ); +_LIT8( KID3v2FrameIdComposer, "TCOM" ); +_LIT8( KID3v2FrameIdCopyright, "TCOP" ); +_LIT8( KID3v2FrameIdOriginalArtist, "TOPE" ); +_LIT8( KID3v2FrameIdUrl, "WOAF" ); +_LIT8( KID3v2FrameIdUserUrl, "WXXX" ); +_LIT8( KID3v2FrameIdJpeg, "APIC" ); +_LIT8( KID3v2FrameIdDuration, "TLEN" ); +_LIT8( KID3v2FrameIdDate, "TDRC" ); // same as year +_LIT8( KID3v2FrameIdRating, "POPM" ); + +_LIT8( KID3v2ImageFormatPngMime, "image/png" ); +_LIT8( KID3v2ImageFormatPng, "png" ); +_LIT8( KID3v2ImageFormatJpegMime, "image/jpeg" ); +_LIT8( KID3v2ImageFormatJpgMime, "image/jpg" ); +_LIT8( KID3v2ImageFormatJpeg, "jpeg" ); + + +// ----------------------------------------------------------------------------- +// (ID3v2.4 specification found in www.id3.org) +// +// $00 ISO-8859-1 [ISO-8859-1]. Terminated with $00. +// $01 UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM. All +// strings in the same frame SHALL have the same byteorder. +// Terminated with $00 00. +// $02 UTF-16BE [UTF-16] encoded Unicode [UNICODE] without BOM. +// Terminated with $00 00. +// $03 UTF-8 [UTF-8] encoded Unicode [UNICODE]. Terminated with $00. +// ----------------------------------------------------------------------------- +const TInt KMetaDataParserAsciiEncoding = 0; +const TInt KMetaDataParserUnicodeEncoding = 1; +const TInt KMetaDataParserUnicodeBEEncoding = 2; +const TInt KMetaDataParserUnicode8Encoding = 3; + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::CMetaDataParserID3v24 +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CMetaDataParserID3v24::CMetaDataParserID3v24( + CMetaDataSource& aSource ) + : CMetaDataParserID3v2(aSource) + { + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::ConstructL() + { + User::LeaveIfError(iFs.Connect()); + iExists = ETrue; +#ifdef _DEBUG + RDebug::Print(_L("CMetaDataParserID3v24::ConstructL - Done")); +#endif + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CMetaDataParserID3v24* CMetaDataParserID3v24::NewL( + CMetaDataSource& aSource ) + { +#ifdef _DEBUG + RDebug::Print(_L("CMetaDataParserID3v24::NewL")); +#endif + CMetaDataParserID3v24* self = new( ELeave ) CMetaDataParserID3v24( aSource ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// Destructor +CMetaDataParserID3v24::~CMetaDataParserID3v24() + { + iFs.Close(); + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::PrepareToParseL +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::PrepareToParseL() + { +#ifdef _DEBUG + RDebug::Print(_L("CMetaDataParserID3v24::PrepareToParseL")); +#endif + // Most of validation was already done by builder. + TBuf8 header; + iSource->ReadL( 0, header ); + // ID3v2.4 header consists of following parts: + // File identifier "ID3" + // Version $04 00 + // Flags %abcd0000 + // Size 4 * %0xxxxxxx + + // Read the data length + iFrameDataSize = 0; + for ( TInt i = 6; i < 10; i++ ) + { + iFrameDataSize <<= 7; + iFrameDataSize |= header[i] & 0x7f; + } + + // Check if extended header is present; bit-b in Flags above + if ( header[5] & 0x40 ) + { + TBuf8 extHeader; + iSource->ReadL( KID3v2HeaderLength, extHeader ); + // ID3v2.4 extended header consists of following parts: + // Extended header size 4 * %0xxxxxxx + // Extended flags $01 + // Size of padding $xx + + // Read the data length + TInt extHeaderSize = 0; + for ( TInt i = 0; i < 4; i++ ) + { + extHeaderSize <<= 7; + extHeaderSize |= extHeader[i] & 0x7f; + } + iFrameOffset = KID3v2HeaderLength + KID3v2ExtendedHeaderLength + extHeaderSize; + } + else + { + iFrameOffset = KID3v2HeaderLength; + } + + // iFrameDataSize is the entire size of ID3 tag including the header + iFrameDataSize += iFrameOffset; + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::GetNextFieldL +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::GetNextFieldL( + TMetaDataFieldId& aFieldId, + TInt& aFrameHeaderSize, + TInt& aFrameSize ) + { + TBuf8 frameHeader; + iSource->ReadL( iFrameOffset, frameHeader ); + // ID3v2.4 frame header consists of following parts: + // Frame identifier $xx xx xx xx + // Size 4 * %0xxxxxxx + // Flags $xx xx + + aFrameSize = 0; + + if(!frameHeader.Length()) + User::Leave(KErrCorrupt); + + for ( TInt i = 4; i < 8; i++ ) + { + aFrameSize <<= 7; + aFrameSize |= frameHeader[i] & 0x7f; + } + + aFrameHeaderSize = KID3v2FrameHeaderLength; + TPtrC8 frameId = frameHeader.Left( KID3v2FrameIdLength ); + _LIT8(KEMPTY, "\0\0\0\0"); + TBuf8<10> empty (KEMPTY); + if ( aFrameSize == 0 && frameId == empty) + { + // We have hit the padding -> no more fields to read + aFieldId = EUnknownMetaDataField; + aFrameHeaderSize = 0; + return; + } + else if (aFrameSize == 0) + { + aFieldId = EUnknownMetaDataField; + return; + } + + if ( frameId.Compare( KID3v2FrameIdTitle ) == 0 ) + { + aFieldId = EMetaDataSongTitle; + } + else if ( frameId.Compare( KID3v2FrameIdArtist ) == 0 ) + { + aFieldId = EMetaDataArtist; + } + else if ( frameId.Compare( KID3v2FrameIdAlbum ) == 0 ) + { + aFieldId = EMetaDataAlbum; + } + else if ( frameId.Compare( KID3v2FrameIdYear ) == 0 ) + { + aFieldId = EMetaDataYear; + } + else if ( frameId.Compare( KID3v2FrameIdComment ) == 0 ) + { + aFieldId = EMetaDataComment; + } + else if ( frameId.Compare( KID3v2FrameIdTrack ) == 0 ) + { + aFieldId = EMetaDataAlbumTrack; + } + else if ( frameId.Compare( KID3v2FrameIdGenre ) == 0 ) + { + aFieldId = EMetaDataGenre; + } + else if ( frameId.Compare( KID3v2FrameIdComposer ) == 0 ) + { + aFieldId = EMetaDataComposer; + } + else if ( frameId.Compare( KID3v2FrameIdCopyright ) == 0 ) + { + aFieldId = EMetaDataCopyright; + } + else if ( frameId.Compare( KID3v2FrameIdOriginalArtist ) == 0 ) + { + aFieldId = EMetaDataOriginalArtist; + } + else if ( frameId.Compare( KID3v2FrameIdUrl ) == 0 ) + { + aFieldId = EMetaDataUrl; + } + else if ( frameId.Compare( KID3v2FrameIdUserUrl ) == 0 ) + { + aFieldId = EMetaDataUserUrl; + } + else if ( frameId.Compare( KID3v2FrameIdJpeg ) == 0 ) + { + aFieldId = EMetaDataJpeg; + } + else if ( frameId.Compare( KID3v2FrameIdDuration ) == 0 ) + { + aFieldId = EMetaDataDuration; + } + else if ( frameId.Compare( KID3v2FrameIdDate ) == 0 ) + { + aFieldId = EMetaDataDate; + } + else if ( frameId.Compare( KID3v2FrameIdRating ) == 0 ) + { + aFieldId = EMetaDataRating; + } + else + { + aFieldId = EUnknownMetaDataField; + } + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v23::GetUserUrlL +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::GetUserUrlL( + TInt aSize ) + { +#ifdef _DEBUG + RDebug::Print(_L("CMetaDataParserID3v23::GetUserUrlL")); +#endif + HBufC8* frame = HBufC8::NewLC( aSize ); + TPtr8 des( frame->Des() ); + + iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize ); + + if ( des.Length() < aSize ) + { + // Partial frame + User::Leave( KErrCorrupt ); + } + + TInt encoding = (TInt) (des.Left(1))[0]; + + if(encoding == 0x00) + { + _LIT8(KNULL, "\0"); + TInt descOffset = des.Find(KNULL); + if(descOffset + 2 > aSize) + { + CleanupStack::PopAndDestroy(); // frame + return; // empty frame + } + TPtrC8 info = des.Mid(descOffset + 2); + TInt length = info.Length(); + if ( length ) + { + HBufC* data16 = HBufC::NewLC( length ); + TPtr unicode( data16->Des() ); + unicode.Copy( info ); + iContainer->AppendL( EMetaDataUserUrl, unicode ); + CleanupStack::PopAndDestroy(); // data16 + } + } + else + { + _LIT8(KNULL, "\0\0"); + TInt descOffset = des.Find(KNULL); + if(descOffset + 3 > aSize) + { + CleanupStack::PopAndDestroy(); // frame + return; // empty frame + } + TPtrC8 info = des.Mid(descOffset + 3); + TInt length = info.Length(); + if ( length ) + { + HBufC* data16 = HBufC::NewLC( length ); + TPtr unicode( data16->Des() ); + unicode.Copy( info ); + iContainer->AppendL( EMetaDataUserUrl, unicode ); + CleanupStack::PopAndDestroy(); // data16 + } + } + + CleanupStack::PopAndDestroy(); // frame + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::GetTextInfoL +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::GetTextInfoL( + TMetaDataFieldId aFieldId, + TInt aSize ) + { + HBufC8* frame = HBufC8::NewLC( aSize ); + TPtr8 des( frame->Des() ); + + iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, 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 ) + { + HBufC* data16 = HBufC::NewLC( length ); + TPtr unicode( data16->Des() ); + if ( ConvertToUnicodeL(encoding, info, unicode) == KErrNone ) + { + iContainer->AppendL( aFieldId, unicode ); + } + CleanupStack::PopAndDestroy(); // data16 + } + + CleanupStack::PopAndDestroy(); // frame + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::GetGenreL +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::GetGenreL( + TInt aSize ) + { +#ifdef _DEBUG + RDebug::Print(_L("CMetaDataParserID3v24::GetGenreL")); +#endif + + HandleV2GetGenreL( aSize, KID3v2FrameHeaderLength, KID3v2GenreNameLength ); + } +// CMetaDataParserID3v24::GetTextYearL +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::GetTextYearL( + TInt aSize ) + { + HBufC8* frame = HBufC8::NewLC( aSize ); + TPtr8 des( frame->Des() ); + + iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize ); + + if ( des.Length() < aSize ) + { + // Partial frame + User::Leave( KErrCorrupt ); + } + + TInt encoding = (TInt) (des.Left(1))[0]; + // Timestamp may be one of the following formats: + // yyyy, yyyy-MM, yyyy-MM-dd, yyyy-MM-ddTHH, yyyy-MM-ddTHH:mm and yyyy-MM-ddTHH:mm:ss + // We are only interested in year. + TPtrC8 drc = StripTrailingZeroes( des.Mid(1), encoding ); + TInt length = drc.Length(); + if ( length >= 4) // 4 bytes year + { + TPtrC8 info = drc.Mid(0, 4); + length = info.Length(); + HBufC* data16 = HBufC::NewLC( length ); + TPtr unicode( data16->Des() ); + if ( ConvertToUnicodeL(encoding, info, unicode) == KErrNone ) + { + iContainer->AppendL( EMetaDataYear, unicode ); + } + CleanupStack::PopAndDestroy(); // data16 + } + + CleanupStack::PopAndDestroy(); // frame + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::GetCommentL +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::GetCommentL( + TInt aSize ) + { + HBufC8* frame = HBufC8::NewLC( aSize ); + TPtr8 des( frame->Des() ); + + iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize ); + + if ( des.Length() < aSize ) + { + // Partial frame + User::Leave( KErrCorrupt ); + } + + if(aSize <= 4) // emppty frame + { + CleanupStack::PopAndDestroy(); // frame + return; + } + TInt encoding = (TInt) (des.Left(1))[0]; + // Skip over TextEncoding(1 byte) and Language(3 bytes) + TPtr8 text = des.MidTPtr(4); + // Skip over Content description from Comment + TInt contentDesLength; + if(encoding == 0 || encoding == 3) + { + _LIT8(KNull, "\0"); + contentDesLength = text.Find(KNull); + text = text.MidTPtr(contentDesLength + 1); + } + else + { + _LIT8(KNull, "\0\0"); + contentDesLength = text.Find(KNull); + text = text.MidTPtr(contentDesLength + 2); + } + TPtrC8 info = StripTrailingZeroes( text, encoding); + TInt length = info.Length(); + if ( length ) + { + HBufC* data16 = HBufC::NewLC( length ); + TPtr unicode( data16->Des() ); + if ( ConvertToUnicodeL(encoding, info, unicode) == KErrNone ) + { + iContainer->AppendL( EMetaDataComment, unicode ); + } + CleanupStack::PopAndDestroy(); // data16 + } + + CleanupStack::PopAndDestroy(); // frame + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::GetUrlL +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::GetUrlL( + TInt aSize ) + { + HBufC8* frame = HBufC8::NewLC( aSize ); + TPtr8 des( frame->Des() ); + + iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize ); + + if ( des.Length() < aSize ) + { + // Partial frame + User::Leave( KErrCorrupt ); + } + + // Ignore information followed by termination $00 + TInt trueEnd( des.Locate(0) ); + if ( trueEnd == KErrNotFound ) + { + trueEnd = des.Length(); + } + + TPtrC8 info = des.Left( trueEnd ); + TInt length = info.Length(); + if ( length ) + { + HBufC* data16 = HBufC::NewLC( length ); + TPtr unicode( data16->Des() ); + unicode.Copy( info ); + iContainer->AppendL( EMetaDataUrl, unicode ); + CleanupStack::PopAndDestroy(); // data16 + } + + CleanupStack::PopAndDestroy(); // frame + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::GetJpegL +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::GetJpegL( + TInt aSize ) + { + HBufC8* frame = HBufC8::NewLC( aSize ); + TPtr8 des( frame->Des() ); + + iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize ); + + if ( des.Length() < aSize ) + { + // Partial frame + User::Leave( KErrCorrupt ); + } + + TInt encoding = (TInt) (des.Left(1))[0]; + + TInt mimeLength = des.Mid(1).Locate(0); + if(mimeLength <= 0 ) + { + User::Leave(KErrCorrupt); + } + TPtrC8 mime = des.Mid(1, mimeLength); + + if ( ( mime.Compare( KID3v2ImageFormatJpeg ) != 0 ) && + ( mime.Compare( KID3v2ImageFormatJpegMime ) != 0 ) && + ( mime.Compare( KID3v2ImageFormatJpgMime ) != 0 ) && + ( mime.Compare( KID3v2ImageFormatPngMime ) != 0 ) && + ( mime.Compare( KID3v2ImageFormatPng ) != 0 ) + ) + { + CleanupStack::PopAndDestroy(); // frame + return; + } + + if(mimeLength+3 > des.Length()) + { + CleanupStack::PopAndDestroy(); // frame + return; + } + + TInt pictureType = (TInt) (des.Mid(mimeLength + 2, 1))[0]; + if ( !NeedRetrieveAlbumArt(pictureType) ) + { + CleanupStack::PopAndDestroy(); // frame + return; + } + + TInt picOffset; + TPtrC8 text8 = des.Mid(mimeLength + 3 ); + if ( encoding == KMetaDataParserAsciiEncoding ) + { + picOffset = text8.Locate(0); + if ( picOffset == KErrNotFound ) + { + CleanupStack::PopAndDestroy(); // frame + return; + } + + picOffset++; // Description termination mark ($00) + } + else if ( encoding == KMetaDataParserUnicodeEncoding ) + { + _LIT8(KNULL, "\0\0"); // 2 bytes of NULL + picOffset = text8.Find(KNULL); + if ( picOffset == KErrNotFound ) + { + CleanupStack::PopAndDestroy(); // frame + return; + } + if (picOffset % 2) // check for offset odd number + { + picOffset++; // add 1 for word boundary + } + picOffset += 2; // Description termination mark ($00 00) + } + else + { + CleanupStack::PopAndDestroy(); // frame + return; + } + + TPtrC8 pic = des.Mid(picOffset + mimeLength + 3); + TInt length = pic.Length(); + if ( length ) + { + // save the offset and the size for retrieving the album art later + iAlbumOffset = picOffset + mimeLength + 3; + iAlbumType = pictureType; + + if (iAlbumPtr) + { + delete iAlbumPtr; // delete the previous buffer + } + CleanupStack::Pop(); // frame - pop from Cleanup stack + iAlbumPtr = frame; // save the buffer + } + else + { + CleanupStack::PopAndDestroy(); // frame + } + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::GetDurationL +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::GetDurationL( + TInt aSize ) + { +#ifdef _DEBUG + RDebug::Print(_L("CMetaDataParserID3v23::GetDurationL")); +#endif + HBufC8* frame = HBufC8::NewLC( aSize ); + TPtr8 des( frame->Des() ); + + iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, 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 ); // $00 + TInt length = info.Length(); + if ( length ) + { + TReal sec = (TReal) atoi((char*)info.Ptr()) / 1000; + TBuf16<10> info1; + info1.Num(sec, TRealFormat (9, 3)); + iContainer->AppendL( EMetaDataDuration, info1 ); + } + + CleanupStack::PopAndDestroy(); // frame + } + + + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::GetTextDateL +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::GetTextDateL( + TInt aSize ) + { +#ifdef _DEBUG + RDebug::Print(_L("CMetaDataParserID3v24::GetTextDateL")); +#endif + GetTextInfoL( EMetaDataDate, aSize ); + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::GetRatingL +// ----------------------------------------------------------------------------- +// +void CMetaDataParserID3v24::GetRatingL( TInt aSize ) + { +#ifdef _DEBUG + RDebug::Print(_L("CMetaDataParserID3v24::GetRatingL")); +#endif + HBufC8* frame = HBufC8::NewLC( aSize ); + TPtr8 des( frame->Des() ); + + iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize ); + + if ( des.Length() < aSize ) + { + // Partial frame + User::Leave( KErrCorrupt ); + } + _LIT8(KNull, "\0"); + TInt offset = des.Find(KNull); + if(offset == KErrNotFound) + { + CleanupStack::PopAndDestroy(); + return; + } + TUint8 rating = des[offset]; + if ( rating > 0) + { + TBuf<8> data16; + data16.AppendNum(rating); + iContainer->AppendL( EMetaDataRating, data16 ); + } + CleanupStack::PopAndDestroy(); // frame + } + +// ----------------------------------------------------------------------------- +// CMetaDataParserID3v24::ConvertToUnicodeL +// ----------------------------------------------------------------------------- +// +TInt CMetaDataParserID3v24::ConvertToUnicodeL( + TInt aEncoding, + const TDesC8& aDesc, + TDes16& aUnicode ) + { +#ifdef _DEBUG + RDebug::Print(_L("CMetaDataParserID3v23::ConvertToUnicodeL")); +#endif + TPtrC8 unicodeData; + TUint characterSetId = 0; + TInt err; + + CCnvCharacterSetConverter* charSetConv = CCnvCharacterSetConverter::NewLC(); + TInt state = CCnvCharacterSetConverter::KStateDefault; + + if ( aEncoding == KMetaDataParserAsciiEncoding ) + { + if(iAutoDetectChinese || iAutoDetectRussian || iAutoDetectJapanese) + { + err = AutoDetectL(aDesc, aUnicode); + CleanupStack::PopAndDestroy(); // charSetConv + return err; + } + else + { + // ISO-8859-1 + characterSetId = KCharacterSetIdentifierIso88591; + unicodeData.Set( aDesc ); + } + } + else if ( aEncoding == KMetaDataParserUnicodeEncoding ) + { + // UTF-16 Big Endian with BOM + TInt bom = UnicodeBOM(aDesc); + if ( bom == KUnicodeBOMBigEndian ) + { + //characterSetId = KCharacterSetIdentifierUcs2; + characterSetId = KCharacterSetIdentifierUnicodeBig; + // Skip BOM & Terminate marks + unicodeData.Set( aDesc.Mid( 2, aDesc.Length() - 2 ) ); + } + else if ( bom == KUnicodeBOMLittleEndian ) + { + characterSetId = KCharacterSetIdentifierUnicodeLittle; + // Skip BOM & Terminate marks + unicodeData.Set( aDesc.Mid( 2, aDesc.Length() - 2 ) ); + } + else + { + // UTF-16 Big Endian without BOM + characterSetId = KCharacterSetIdentifierUnicodeBig; + unicodeData.Set( aDesc ); + } + } + else if ( aEncoding == KMetaDataParserUnicodeBEEncoding ) + { + // UTF-16 Big Endian without BOM + characterSetId = KCharacterSetIdentifierUnicodeBig; + unicodeData.Set( aDesc ); + } + else if ( aEncoding == KMetaDataParserUnicode8Encoding ) + { + // UTF-8 + characterSetId = KCharacterSetIdentifierUtf8; + unicodeData.Set( aDesc ); + } + else + { + User::Leave(KErrNotSupported); + } + + charSetConv->PrepareToConvertToOrFromL(characterSetId, *iCharacterSet, iFs); + err = charSetConv->ConvertToUnicode(aUnicode, unicodeData, state); + +#ifdef _DEBUG + RDebug::Print(_L("CMetaDataParserID3v24::ConvertToUnicode :-> Tag Size[%d] Unicode Tag Size[%d]Bytes Unconverted[%d]"), + unicodeData.Length(), aUnicode.Length(), err); +#endif + + CleanupStack::PopAndDestroy(); // charSetConv + return err; + } + +// End of File