mmserv/metadatautility/Src/MetaDataParserID3v22.cpp
changeset 0 71ca22bcf22a
child 11 03a293c97d5c
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 implements parsing of ID3v2.2 according to the
       
    15 *                specification found in www.id3.org. Note that only a selected
       
    16 *				 frames are supported at this time.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 
       
    22 // INCLUDE FILES
       
    23 #include    <libc/stdlib.h>
       
    24 
       
    25 #include	"MetaDataParserID3v22.h"
       
    26 
       
    27 // CONSTANTS
       
    28 // (ID3v2.2 specification found in www.id3.org)
       
    29 const TInt KID3v2HeaderLength 			= 10;
       
    30 const TInt KID3v2FrameHeaderLength 		= 6;
       
    31 const TInt KID3v2FrameIdLength 			= 3;
       
    32 const TInt KID3v2GenreNameLength		= 24;
       
    33 
       
    34 _LIT8( KID3v2FrameIdTitle, 			"TT2" );
       
    35 _LIT8( KID3v2FrameIdArtist, 		"TP1" );
       
    36 _LIT8( KID3v2FrameIdAlbum, 			"TAL" );
       
    37 _LIT8( KID3v2FrameIdYear, 			"TYE" );
       
    38 _LIT8( KID3v2FrameIdComment, 		"COM" );
       
    39 _LIT8( KID3v2FrameIdTrack, 			"TRK" );
       
    40 _LIT8( KID3v2FrameIdGenre, 			"TCO" );
       
    41 _LIT8( KID3v2FrameIdComposer, 		"TCM" );
       
    42 _LIT8( KID3v2FrameIdCopyright, 		"TCR" );
       
    43 _LIT8( KID3v2FrameIdOriginalArtist,	"TOA" );
       
    44 _LIT8( KID3v2FrameIdUrl, 			"WAF" );
       
    45 _LIT8( KID3v2FrameIdUserUrl, 		"WXX" );
       
    46 _LIT8( KID3v2FrameIdJpeg, 			"PIC" );
       
    47 _LIT8( KID3v2FrameIdDuration, 		"TLE" );
       
    48 _LIT8( KID3v2FrameIdDate, 			"TDA" );
       
    49 _LIT8( KID3v2FrameIdRating, 		"POP" );
       
    50 
       
    51 _LIT8( KID3v2ImageFormatPng, 		"PNG" );
       
    52 _LIT8( KID3v2ImageFormatJpeg, 		"JPG" );
       
    53 
       
    54 
       
    55 // -----------------------------------------------------------------------------
       
    56 //   (ID3v2.2 specification found in www.id3.org)
       
    57 //
       
    58 //   $00   ISO-8859-1 [ISO-8859-1]. Terminated with $00.
       
    59 //   $01   UCS-2 encoded Unicode [UNICODE].
       
    60 //         Terminated with $00 00.
       
    61 // -----------------------------------------------------------------------------
       
    62 const TInt KMetaDataParserAsciiEncoding		= 0;
       
    63 const TInt KMetaDataParserUnicodeEncoding	= 1;
       
    64 
       
    65 
       
    66 // ============================ MEMBER FUNCTIONS ===============================
       
    67 
       
    68 // -----------------------------------------------------------------------------
       
    69 // CMetaDataParserID3v22::CMetaDataParserID3v22
       
    70 // C++ default constructor can NOT contain any code, that
       
    71 // might leave.
       
    72 // -----------------------------------------------------------------------------
       
    73 //
       
    74 CMetaDataParserID3v22::CMetaDataParserID3v22(
       
    75 	CMetaDataSource& aSource )
       
    76 	:	CMetaDataParserID3v2(aSource)
       
    77 	{
       
    78     }
       
    79 
       
    80 // -----------------------------------------------------------------------------
       
    81 // CMetaDataParserID3v22::ConstructL
       
    82 // Symbian 2nd phase constructor can leave.
       
    83 // -----------------------------------------------------------------------------
       
    84 //
       
    85 void CMetaDataParserID3v22::ConstructL()
       
    86     {
       
    87 	User::LeaveIfError(iFs.Connect());
       
    88 	iExists = ETrue;
       
    89 #ifdef _DEBUG
       
    90 	RDebug::Print(_L("CMetaDataParserID3v22::ConstructL - Done"));
       
    91 #endif
       
    92     }
       
    93 
       
    94 // -----------------------------------------------------------------------------
       
    95 // CMetaDataParserID3v22::NewL
       
    96 // Two-phased constructor.
       
    97 // -----------------------------------------------------------------------------
       
    98 //
       
    99 CMetaDataParserID3v22* CMetaDataParserID3v22::NewL(
       
   100 	CMetaDataSource& aSource )
       
   101     {
       
   102 #ifdef _DEBUG
       
   103 	RDebug::Print(_L("CMetaDataParserID3v22::NewL"));
       
   104 #endif
       
   105 	CMetaDataParserID3v22* self = new( ELeave ) CMetaDataParserID3v22( aSource );
       
   106     CleanupStack::PushL( self );
       
   107     self->ConstructL();
       
   108     CleanupStack::Pop();
       
   109     return self;
       
   110     }
       
   111 
       
   112 // Destructor
       
   113 CMetaDataParserID3v22::~CMetaDataParserID3v22()
       
   114 	{
       
   115 	iFs.Close();
       
   116 	}
       
   117 
       
   118 // -----------------------------------------------------------------------------
       
   119 // CMetaDataParserID3v22::PrepareToParseL
       
   120 // -----------------------------------------------------------------------------
       
   121 //
       
   122 void CMetaDataParserID3v22::PrepareToParseL()
       
   123     {
       
   124 #ifdef _DEBUG
       
   125 	RDebug::Print(_L("CMetaDataParserID3v22::PrepareToParseL"));
       
   126 #endif
       
   127 	// Most of validation was already done by builder.
       
   128 	TBuf8<KID3v2HeaderLength> header;
       
   129 	iSource->ReadL( 0, header );
       
   130     // ID3v2.2 header consists of following parts:
       
   131 	// File identifier	"ID3"
       
   132 	// Version			$02 00
       
   133 	// Flags			%xx000000
       
   134 	// Size				4 * %0xxxxxxx
       
   135 
       
   136 	// Read the data length
       
   137 	iFrameDataSize = 0;
       
   138 	for ( TInt i = 6; i < 10; i++ )
       
   139 		{
       
   140 		iFrameDataSize <<= 7;
       
   141 		iFrameDataSize |= header[i] & 0x7f;
       
   142 		}
       
   143 
       
   144 	iFrameOffset = KID3v2HeaderLength;
       
   145 	// iFrameDataSize is the entire size of ID3 tag including the header
       
   146 	iFrameDataSize += iFrameOffset;
       
   147 	}
       
   148 
       
   149 // -----------------------------------------------------------------------------
       
   150 // CMetaDataParserID3v22::GetNextFieldL
       
   151 // -----------------------------------------------------------------------------
       
   152 //
       
   153 void CMetaDataParserID3v22::GetNextFieldL(
       
   154 	TMetaDataFieldId& aFieldId,
       
   155 	TInt& aFrameHeaderSize,
       
   156 	TInt& aFrameSize )
       
   157 	{
       
   158 	TBuf8<KID3v2FrameHeaderLength> frameHeader;
       
   159 	iSource->ReadL( iFrameOffset, frameHeader );
       
   160     // ID3v2.2 frame header consists of following parts:
       
   161 	// Frame identifier	$xx xx xx
       
   162 	// Size				$xx xx xx
       
   163 
       
   164 	aFrameSize = 0;
       
   165 
       
   166 	if(!frameHeader.Length())
       
   167 		User::Leave(KErrCorrupt);
       
   168 
       
   169 	for ( TInt i = 3; i < 6; i++ )
       
   170 		{
       
   171 		aFrameSize <<= 8;
       
   172 		aFrameSize |= frameHeader[i];
       
   173 		}
       
   174 
       
   175 	aFrameHeaderSize = KID3v2FrameHeaderLength;
       
   176 	TPtrC8 frameId = frameHeader.Left( KID3v2FrameIdLength );
       
   177 	_LIT8(KEMPTY, "\0\0\0");
       
   178 	TBuf8<3> empty (KEMPTY);
       
   179 	if ( aFrameSize == 0 && frameId == empty)
       
   180 		{
       
   181 		// We have hit the padding -> no more fields to read
       
   182 		aFieldId = EUnknownMetaDataField;
       
   183 		aFrameHeaderSize = 0;
       
   184 		return;
       
   185 		}
       
   186 	else if (aFrameSize == 0)
       
   187 	{
       
   188 		aFieldId = EUnknownMetaDataField;
       
   189 		return;
       
   190 	}
       
   191 
       
   192 	if ( frameId.Compare( KID3v2FrameIdTitle ) == 0 )
       
   193 		{
       
   194 		aFieldId = EMetaDataSongTitle;
       
   195 		}
       
   196 	else if ( frameId.Compare( KID3v2FrameIdArtist ) == 0 )
       
   197 		{
       
   198 		aFieldId = EMetaDataArtist;
       
   199 		}
       
   200 	else if ( frameId.Compare( KID3v2FrameIdAlbum ) == 0 )
       
   201 		{
       
   202 		aFieldId = EMetaDataAlbum;
       
   203 		}
       
   204 	else if ( frameId.Compare( KID3v2FrameIdYear ) == 0 )
       
   205 		{
       
   206 		aFieldId = EMetaDataYear;
       
   207 		}
       
   208 	else if ( frameId.Compare( KID3v2FrameIdComment ) == 0 )
       
   209 		{
       
   210 		aFieldId = EMetaDataComment;
       
   211 		}
       
   212 	else if ( frameId.Compare( KID3v2FrameIdTrack ) == 0 )
       
   213 		{
       
   214 		aFieldId = EMetaDataAlbumTrack;
       
   215 		}
       
   216 	else if ( frameId.Compare( KID3v2FrameIdGenre ) == 0 )
       
   217 		{
       
   218 		aFieldId = EMetaDataGenre;
       
   219 		}
       
   220 	else if ( frameId.Compare( KID3v2FrameIdComposer ) == 0 )
       
   221 		{
       
   222 		aFieldId = EMetaDataComposer;
       
   223 		}
       
   224 	else if ( frameId.Compare( KID3v2FrameIdCopyright ) == 0 )
       
   225 		{
       
   226 		aFieldId = EMetaDataCopyright;
       
   227 		}
       
   228 	else if ( frameId.Compare( KID3v2FrameIdOriginalArtist ) == 0 )
       
   229 		{
       
   230 		aFieldId = EMetaDataOriginalArtist;
       
   231 		}
       
   232 	else if ( frameId.Compare( KID3v2FrameIdUrl ) == 0 )
       
   233 		{
       
   234 		aFieldId = EMetaDataUrl;
       
   235 		}
       
   236 	else if ( frameId.Compare( KID3v2FrameIdUserUrl ) == 0 )
       
   237 		{
       
   238 		aFieldId = EMetaDataUserUrl;
       
   239 		}
       
   240 	else if ( frameId.Compare( KID3v2FrameIdJpeg ) == 0 )
       
   241 		{
       
   242 		aFieldId = EMetaDataJpeg;
       
   243 		}
       
   244 	else if ( frameId.Compare( KID3v2FrameIdDuration ) == 0 )
       
   245 		{
       
   246 		aFieldId = EMetaDataDuration;
       
   247 		}
       
   248 	else if ( frameId.Compare( KID3v2FrameIdDate ) == 0 )
       
   249 		{
       
   250 		aFieldId = EMetaDataDate;
       
   251 		}
       
   252 	else if ( frameId.Compare( KID3v2FrameIdRating ) == 0 )
       
   253 		{
       
   254 		aFieldId = EMetaDataRating;
       
   255 		}
       
   256 	else
       
   257 		{
       
   258 		aFieldId = EUnknownMetaDataField;
       
   259 		}
       
   260 	}
       
   261 
       
   262 // -----------------------------------------------------------------------------
       
   263 // CMetaDataParserID3v22::GetUserUrlL
       
   264 // -----------------------------------------------------------------------------
       
   265 //
       
   266 void CMetaDataParserID3v22::GetUserUrlL(
       
   267 	TInt aSize )
       
   268 	{
       
   269 #ifdef _DEBUG
       
   270 	RDebug::Print(_L("CMetaDataParserID3v23::GetUserUrlL"));
       
   271 #endif
       
   272 	HBufC8* frame = HBufC8::NewLC( aSize );
       
   273 	TPtr8 des( frame->Des() );
       
   274 
       
   275 	iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize );
       
   276 
       
   277 	if ( des.Length() < aSize )
       
   278 		{
       
   279 		// Partial frame
       
   280 		User::Leave( KErrCorrupt );
       
   281 		}
       
   282 
       
   283 	TInt encoding = (TInt) (des.Left(1))[0];
       
   284 
       
   285 	if(encoding == 0x00)
       
   286 	{
       
   287 		_LIT8(KNULL, "\0");
       
   288 		TInt descOffset = des.Find(KNULL);
       
   289 		if(descOffset + 2 > aSize)
       
   290 		{
       
   291 			CleanupStack::PopAndDestroy();  // frame
       
   292 			return; // empty frame
       
   293 		}
       
   294 		TPtrC8 info = des.Mid(descOffset + 2);
       
   295 		TInt length = info.Length();
       
   296 		if ( length )
       
   297 			{
       
   298 			HBufC* data16 = HBufC::NewLC( length );
       
   299 			TPtr unicode( data16->Des() );
       
   300 			unicode.Copy( info );
       
   301 			iContainer->AppendL( EMetaDataUserUrl, unicode );
       
   302 			CleanupStack::PopAndDestroy();  // data16
       
   303 			}
       
   304 	}
       
   305 	else
       
   306 	{
       
   307 		_LIT8(KNULL, "\0\0");
       
   308 		TInt descOffset = des.Find(KNULL);
       
   309 		if(descOffset + 3 > aSize)
       
   310 		{
       
   311 			CleanupStack::PopAndDestroy();  // frame
       
   312 			return; // empty frame
       
   313 		}
       
   314 		TPtrC8 info = des.Mid(descOffset + 3);
       
   315 		TInt length = info.Length();
       
   316 		if ( length )
       
   317 			{
       
   318 			HBufC* data16 = HBufC::NewLC( length );
       
   319 			TPtr unicode( data16->Des() );
       
   320 			unicode.Copy( info );
       
   321 			iContainer->AppendL( EMetaDataUserUrl, unicode );
       
   322 			CleanupStack::PopAndDestroy();  // data16
       
   323 			}
       
   324 	}
       
   325 
       
   326 	CleanupStack::PopAndDestroy();  // frame
       
   327 	}
       
   328 
       
   329 // -----------------------------------------------------------------------------
       
   330 // CMetaDataParserID3v22::GetTextInfoL
       
   331 // -----------------------------------------------------------------------------
       
   332 //
       
   333 void CMetaDataParserID3v22::GetTextInfoL(
       
   334 	TMetaDataFieldId aFieldId,
       
   335 	TInt aSize )
       
   336 	{
       
   337 #ifdef _DEBUG
       
   338 	RDebug::Print(_L("CMetaDataParserID3v22::GetTextInfoL"));
       
   339 #endif
       
   340 	HBufC8* frame = HBufC8::NewLC( aSize );
       
   341 	TPtr8 des( frame->Des() );
       
   342 
       
   343 	iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize );
       
   344 
       
   345 	if ( des.Length() < aSize )
       
   346 		{
       
   347 		// Partial frame
       
   348 		User::Leave( KErrCorrupt );
       
   349 		}
       
   350 
       
   351 	TInt encoding = (TInt) (des.Left(1))[0];
       
   352 	TPtrC8 info = StripTrailingZeroes( des.Mid(1), encoding);
       
   353 	TInt length = info.Length();
       
   354 	if ( length )
       
   355 		{
       
   356 		HBufC* data16 = HBufC::NewLC( length );
       
   357 		TPtr unicode( data16->Des() );
       
   358 		if ( ConvertToUnicodeL(encoding, info, unicode) == KErrNone )
       
   359 			{
       
   360 			iContainer->AppendL( aFieldId, unicode );
       
   361 			}
       
   362 		CleanupStack::PopAndDestroy();  // data16
       
   363 		}
       
   364 
       
   365 	CleanupStack::PopAndDestroy();  // frame
       
   366 	}
       
   367 
       
   368 // -----------------------------------------------------------------------------
       
   369 // CMetaDataParserID3v22::GetGenreL
       
   370 // -----------------------------------------------------------------------------
       
   371 //
       
   372 void CMetaDataParserID3v22::GetGenreL(
       
   373 	TInt aSize )
       
   374 	{
       
   375 #ifdef _DEBUG
       
   376 	RDebug::Print(_L("CMetaDataParserID3v22::GetGenreL"));
       
   377 #endif
       
   378 	
       
   379 	HandleV2GetGenreL( aSize, KID3v2FrameHeaderLength, KID3v2GenreNameLength );
       
   380 	}
       
   381 
       
   382 
       
   383 // -----------------------------------------------------------------------------
       
   384 // CMetaDataParserID3v22::GetTextYearL
       
   385 // -----------------------------------------------------------------------------
       
   386 //
       
   387 void CMetaDataParserID3v22::GetTextYearL(
       
   388 	TInt aSize )
       
   389 	{
       
   390 #ifdef _DEBUG
       
   391 	RDebug::Print(_L("CMetaDataParserID3v22::GetTextYearL"));
       
   392 #endif
       
   393 	GetTextInfoL( EMetaDataYear, aSize );
       
   394 	}
       
   395 
       
   396 // -----------------------------------------------------------------------------
       
   397 // CMetaDataParserID3v22::GetCommentL
       
   398 // -----------------------------------------------------------------------------
       
   399 //
       
   400 void CMetaDataParserID3v22::GetCommentL(
       
   401 	TInt aSize )
       
   402 	{
       
   403 #ifdef _DEBUG
       
   404 	RDebug::Print(_L("CMetaDataParserID3v22::GetCommentL"));
       
   405 #endif
       
   406 	HBufC8* frame = HBufC8::NewLC( aSize );
       
   407 	TPtr8 des( frame->Des() );
       
   408 
       
   409 	iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize );
       
   410 
       
   411 	if ( des.Length() < aSize )
       
   412 		{
       
   413 		// Partial frame
       
   414 		User::Leave( KErrCorrupt );
       
   415 		}
       
   416 
       
   417 	if(aSize <= 4) // emppty frame
       
   418 	{
       
   419 		CleanupStack::PopAndDestroy();  // frame
       
   420 		return;
       
   421 	}
       
   422 	TInt encoding = (TInt) (des.Left(1))[0];
       
   423 	// Skip over TextEncoding(1 byte) and Language(3 bytes)
       
   424 	TPtr8 text = des.MidTPtr(4);
       
   425 	// Skip over Content description from Comment
       
   426 	TInt contentDesLength;
       
   427 	if(encoding == 0)
       
   428 		{
       
   429 		_LIT8(KNull, "\0");
       
   430 		contentDesLength = text.Find(KNull);
       
   431 		text = text.MidTPtr(contentDesLength + 1);
       
   432 		}
       
   433 	else
       
   434 		{
       
   435 		_LIT8(KNull, "\0\0");
       
   436 		contentDesLength = text.Find(KNull);
       
   437 		text = text.MidTPtr(contentDesLength + 2);
       
   438 		}
       
   439 	TPtrC8 info = StripTrailingZeroes( text, encoding);
       
   440 	TInt length = info.Length();
       
   441 	if ( length )
       
   442 		{
       
   443 		HBufC* data16 = HBufC::NewLC( length );
       
   444 		TPtr unicode( data16->Des() );
       
   445 		if ( ConvertToUnicodeL(encoding, info, unicode) == KErrNone )
       
   446 			{
       
   447 			iContainer->AppendL( EMetaDataComment, unicode );
       
   448 			}
       
   449 		CleanupStack::PopAndDestroy();  // data16
       
   450 		}
       
   451 
       
   452 	CleanupStack::PopAndDestroy();  // frame
       
   453 	}
       
   454 
       
   455 // -----------------------------------------------------------------------------
       
   456 // CMetaDataParserID3v22::GetUrlL
       
   457 // -----------------------------------------------------------------------------
       
   458 //
       
   459 void CMetaDataParserID3v22::GetUrlL(
       
   460 	TInt aSize )
       
   461 	{
       
   462 #ifdef _DEBUG
       
   463 	RDebug::Print(_L("CMetaDataParserID3v22::GetUrlL"));
       
   464 #endif
       
   465 	HBufC8* frame = HBufC8::NewLC( aSize );
       
   466 	TPtr8 des( frame->Des() );
       
   467 
       
   468 	iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize );
       
   469 
       
   470 	if ( des.Length() < aSize )
       
   471 		{
       
   472 		// Partial frame
       
   473 		User::Leave( KErrCorrupt );
       
   474 		}
       
   475 
       
   476     // Ignore information followed by termination $00
       
   477     TInt trueEnd( des.Locate(0) );
       
   478     if ( trueEnd == KErrNotFound )
       
   479         {
       
   480         trueEnd = des.Length();
       
   481 		}
       
   482 
       
   483 	TPtrC8 info = des.Left( trueEnd );
       
   484 	TInt length = info.Length();
       
   485 	if ( length )
       
   486 		{
       
   487 		HBufC* data16 = HBufC::NewLC( length );
       
   488 		TPtr unicode( data16->Des() );
       
   489 		unicode.Copy( info );
       
   490 		iContainer->AppendL( EMetaDataUrl, unicode );
       
   491 		CleanupStack::PopAndDestroy();  // data16
       
   492 		}
       
   493 
       
   494 	CleanupStack::PopAndDestroy();  // frame
       
   495 	}
       
   496 
       
   497 // -----------------------------------------------------------------------------
       
   498 // CMetaDataParserID3v22::GetJpegL
       
   499 // -----------------------------------------------------------------------------
       
   500 //
       
   501 void CMetaDataParserID3v22::GetJpegL(
       
   502 	TInt aSize )
       
   503 	{
       
   504 #ifdef _DEBUG
       
   505 	RDebug::Print(_L("CMetaDataParserID3v22::GetJpegL"));
       
   506 #endif
       
   507     HBufC8* frame = HBufC8::NewLC( aSize );
       
   508     TPtr8 des( frame->Des() );
       
   509 
       
   510     iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize );
       
   511 
       
   512 	if ( des.Length() < aSize )
       
   513 		{
       
   514 		// Partial frame
       
   515 		User::Leave( KErrCorrupt );
       
   516 		}
       
   517 
       
   518 	TInt encoding = (TInt) (des.Left(1))[0];
       
   519 
       
   520 	TPtrC8 imageFormat = des.Mid(1, 3);
       
   521 	if ( imageFormat.Compare( KID3v2ImageFormatJpeg ) != 0  &&
       
   522 		imageFormat.Compare( KID3v2ImageFormatPng ) != 0 )
       
   523 		{
       
   524 		CleanupStack::PopAndDestroy();  // frame
       
   525 		return;
       
   526 		}
       
   527 
       
   528 	if(des.Length() < 5)
       
   529         {
       
   530         CleanupStack::PopAndDestroy();  // frame
       
   531         return;
       
   532         }
       
   533 
       
   534 	TInt pictureType = (TInt) (des.Mid(4, 1))[0];
       
   535 	if ( !NeedRetrieveAlbumArt(pictureType) )
       
   536 		{
       
   537 		CleanupStack::PopAndDestroy();  // frame
       
   538 		return;
       
   539 		}
       
   540 
       
   541     TInt picOffset;
       
   542 	TPtrC8 text8 = des.Mid(5);
       
   543 	if ( encoding == KMetaDataParserAsciiEncoding )
       
   544 		{
       
   545         picOffset = text8.Locate(0);
       
   546         if ( picOffset == KErrNotFound )
       
   547            {
       
   548            CleanupStack::PopAndDestroy();  // frame
       
   549            return;
       
   550            }
       
   551     
       
   552         picOffset++;        // Description termination mark ($00)
       
   553 		}
       
   554 	else if ( encoding == KMetaDataParserUnicodeEncoding )
       
   555 		{
       
   556         _LIT8(KNULL, "\0\0");               // 2 bytes of NULL
       
   557         picOffset = text8.Find(KNULL);
       
   558         if ( picOffset == KErrNotFound )
       
   559             {
       
   560             CleanupStack::PopAndDestroy();  // frame
       
   561             return;
       
   562             }
       
   563         if (picOffset % 2)      // check for offset odd number 
       
   564             {
       
   565             picOffset++;        // add 1 for word boundary
       
   566             }
       
   567 		picOffset += 2;		// Description termination mark ($00 00)
       
   568 		}
       
   569 	else
       
   570 		{
       
   571 		CleanupStack::PopAndDestroy();  // frame
       
   572 		return;
       
   573 		}
       
   574 	TPtrC8 pic = des.Mid(picOffset + 5);
       
   575 	TInt length = pic.Length();
       
   576 	if ( length )
       
   577 		{
       
   578         // save the offset and the size for retrieving the album art later
       
   579         iAlbumOffset = picOffset + 5;
       
   580         iAlbumType = pictureType;
       
   581         
       
   582         if (iAlbumPtr)
       
   583             {
       
   584             delete iAlbumPtr;       // delete the previous buffer
       
   585             }
       
   586         
       
   587         CleanupStack::Pop();        // frame - pop from Cleanup stack
       
   588         iAlbumPtr = frame;          // save the buffer
       
   589 		}
       
   590 	else
       
   591 	    {
       
   592 	    CleanupStack::PopAndDestroy();  // frame	    
       
   593 	    }
       
   594 	}
       
   595 
       
   596 // -----------------------------------------------------------------------------
       
   597 // CMetaDataParserID3v22::GetDurationL
       
   598 // -----------------------------------------------------------------------------
       
   599 //
       
   600 void CMetaDataParserID3v22::GetDurationL(
       
   601 	TInt aSize )
       
   602 	{
       
   603 #ifdef _DEBUG
       
   604 	RDebug::Print(_L("CMetaDataParserID3v23::GetDurationL"));
       
   605 #endif
       
   606 	HBufC8* frame = HBufC8::NewLC( aSize );
       
   607 	TPtr8 des( frame->Des() );
       
   608 
       
   609 	iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize );
       
   610 
       
   611 	if ( des.Length() < aSize )
       
   612 		{
       
   613 		// Partial frame
       
   614 		User::Leave( KErrCorrupt );
       
   615 		}
       
   616 
       
   617 	TInt encoding = (TInt) (des.Left(1))[0];
       
   618 	TPtrC8 info = StripTrailingZeroes( des.Mid(1), encoding ); // $00
       
   619 	TInt length = info.Length();
       
   620 	if ( length )
       
   621 		{
       
   622 		TReal sec = (TReal) atoi((char*)info.Ptr()) / 1000;
       
   623 		TBuf16<10> info1;
       
   624 		info1.Num(sec, TRealFormat (9, 3));
       
   625 		iContainer->AppendL( EMetaDataDuration, info1 );
       
   626 		}
       
   627 
       
   628 	CleanupStack::PopAndDestroy();  // frame
       
   629 	}
       
   630 
       
   631 
       
   632 // -----------------------------------------------------------------------------
       
   633 // CMetaDataParserID3v22::GetTextDateL
       
   634 // -----------------------------------------------------------------------------
       
   635 //
       
   636 void CMetaDataParserID3v22::GetTextDateL(
       
   637 	TInt aSize )
       
   638 	{
       
   639 #ifdef _DEBUG
       
   640 	RDebug::Print(_L("CMetaDataParserID3v22::GetTextDateL"));
       
   641 #endif
       
   642 	GetTextInfoL( EMetaDataDate, aSize );
       
   643 	}
       
   644 
       
   645 // -----------------------------------------------------------------------------
       
   646 // CMetaDataParserID3v22::GetRatingL
       
   647 // -----------------------------------------------------------------------------
       
   648 //
       
   649 void CMetaDataParserID3v22::GetRatingL(	TInt aSize )
       
   650 	{
       
   651 #ifdef _DEBUG
       
   652 	RDebug::Print(_L("CMetaDataParserID3v22::GetRatingL"));
       
   653 #endif
       
   654 	HBufC8* frame = HBufC8::NewLC( aSize );
       
   655 	TPtr8 des( frame->Des() );
       
   656 
       
   657 	iSource->ReadL( iFrameOffset + KID3v2FrameHeaderLength, des, aSize );
       
   658 
       
   659 	if ( des.Length() < aSize )
       
   660 		{
       
   661 		// Partial frame
       
   662 		User::Leave( KErrCorrupt );
       
   663 		}
       
   664 	_LIT8(KNull, "\0");
       
   665 	TInt offset = des.Find(KNull);
       
   666 	if(offset == KErrNotFound)
       
   667 		{
       
   668 		return;
       
   669 		}
       
   670 	TUint8 rating = des[offset + 1];
       
   671 	if ( rating > 0)
       
   672 		{
       
   673 		TBuf<8> data16;
       
   674 		data16.AppendNum(rating);
       
   675 		iContainer->AppendL( EMetaDataRating, data16 );
       
   676 		}
       
   677 	CleanupStack::PopAndDestroy();  // frame
       
   678 	}
       
   679 
       
   680 // -----------------------------------------------------------------------------
       
   681 // CMetaDataParserID3v22::ConvertToUnicodeL
       
   682 // -----------------------------------------------------------------------------
       
   683 //
       
   684 TInt CMetaDataParserID3v22::ConvertToUnicodeL(
       
   685 	TInt aEncoding,
       
   686 	const TDesC8& aDesc,
       
   687 	TDes16& aUnicode )
       
   688 	{
       
   689 #ifdef _DEBUG
       
   690 	RDebug::Print(_L("CMetaDataParserID3v22::ConvertToUnicodeL"));
       
   691 #endif
       
   692 	TPtrC8 unicodeData;
       
   693     TUint characterSetId = 0;
       
   694 	TInt err;
       
   695 
       
   696 	CCnvCharacterSetConverter* charSetConv = CCnvCharacterSetConverter::NewLC();
       
   697 	TInt state = CCnvCharacterSetConverter::KStateDefault;
       
   698 
       
   699 	if ( aEncoding == KMetaDataParserAsciiEncoding )
       
   700 		{
       
   701 		if(iAutoDetectChinese || iAutoDetectRussian || iAutoDetectJapanese)
       
   702 			{
       
   703 			err = AutoDetectL(aDesc, aUnicode);
       
   704 			CleanupStack::PopAndDestroy();	// charSetConv
       
   705 	        return err;
       
   706 			}
       
   707 		else
       
   708 			{
       
   709 			// ISO-8859-1
       
   710 			characterSetId = KCharacterSetIdentifierIso88591;
       
   711 			unicodeData.Set( aDesc );
       
   712 			}
       
   713 		}
       
   714 	else if ( aEncoding == KMetaDataParserUnicodeEncoding )
       
   715 		{
       
   716 		// USC-2 with BOM
       
   717 		TInt bom = UnicodeBOM(aDesc);
       
   718 		if ( bom == KUnicodeBOMBigEndian )
       
   719 			{
       
   720 			//characterSetId = KCharacterSetIdentifierUcs2;
       
   721 			characterSetId = KCharacterSetIdentifierUnicodeBig;
       
   722 			// Skip BOM & Terminate marks
       
   723 			unicodeData.Set( aDesc.Mid( 2, aDesc.Length() - 2 ) );
       
   724 			}
       
   725 		else if ( bom == KUnicodeBOMLittleEndian )
       
   726 			{
       
   727 			characterSetId = KCharacterSetIdentifierUnicodeLittle;
       
   728 			// Skip BOM & Terminate marks
       
   729 			unicodeData.Set( aDesc.Mid( 2, aDesc.Length() - 2 ) );
       
   730 			}
       
   731 		else
       
   732 			{
       
   733 			// USC-2 Big Endian without BOM
       
   734 			characterSetId = KCharacterSetIdentifierUnicodeBig;
       
   735 			unicodeData.Set( aDesc );
       
   736 			}
       
   737 		}
       
   738 	else
       
   739 		{
       
   740 		User::Leave(KErrNotSupported);
       
   741 		}
       
   742 
       
   743 	charSetConv->PrepareToConvertToOrFromL(characterSetId, *iCharacterSet, iFs);
       
   744 	err = charSetConv->ConvertToUnicode(aUnicode, unicodeData, state);
       
   745 
       
   746 #ifdef _DEBUG
       
   747 	RDebug::Print(_L("CMetaDataParserID3v22::ConvertToUnicode :-> Tag Size[%d] Unicode Tag Size[%d]Bytes Unconverted[%d]"),
       
   748 		unicodeData.Length(), aUnicode.Length(), err);
       
   749 #endif
       
   750 
       
   751 	CleanupStack::PopAndDestroy();	// charSetConv
       
   752 	return err;
       
   753 	}
       
   754 
       
   755 //  End of File