1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 /**
19 * @file pv_id3_parcom_types.cpp
20 * @brief Type definitions for ID3 Parser-Composer
21 */
22
23 #ifndef PV_ID3_PARCOM_H_INCLUDED
24 #include "pv_id3_parcom.h"
25 #endif
26 #ifndef PV_ID3_PARCOM_CONSTANTS_H_INCLUDED
27 #include "pv_id3_parcom_constants.h"
28 #endif
29 #ifndef OSCL_SNPRINTF_H_INCLUDED
30 #include "oscl_snprintf.h"
31 #endif
32 #ifndef PVLOGGER_H_INCLUDED
33 #include "pvlogger.h"
34 #endif
35 #ifndef PVMI_KVP_UTIL_H_INCLUDED
36 #include "pvmi_kvp_util.h"
37 #endif
38 #ifndef OSCL_MIME_STRING_UTILS_H
39 #include "pv_mime_string_utils.h"
40 #endif
41 #ifndef OSCL_DLL_H_INCLUDED
42 #include "oscl_dll.h"
43 #endif
44 #ifndef WCHAR_SIZE_UTILS_H_INCLUDED
45 #include "wchar_size_utils.h"
46 #endif
47
48 #define LOG_STACK_TRACE(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, m);
49 #define LOG_DEBUG(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, m);
50 #define LOG_ERR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
51
52 #ifndef NULL_TERM_CHAR
53 #define NULL_TERM_CHAR '\0'
54 #endif
55
56 // DLL entry point
57 OSCL_DLL_ENTRY_POINT_DEFAULT()
58
59 ////////////////////////////////////////////////////////////////////////////
60 class PVID3ParComKvpCleanupDA : public OsclDestructDealloc
61 {
62 public:
PVID3ParComKvpCleanupDA(Oscl_DefAlloc * in_gen_alloc)63 PVID3ParComKvpCleanupDA(Oscl_DefAlloc* in_gen_alloc) :
64 gen_alloc(in_gen_alloc) {};
~PVID3ParComKvpCleanupDA()65 virtual ~PVID3ParComKvpCleanupDA() {};
66
destruct_and_dealloc(OsclAny * ptr)67 virtual void destruct_and_dealloc(OsclAny* ptr)
68 {
69 // no need to call destructors in this case just dealloc
70 gen_alloc->deallocate(ptr);
71 }
72
73 private:
74 Oscl_DefAlloc* gen_alloc;
75 };
76
77 ////////////////////////////////////////////////////////////////////////////
PVID3ParCom()78 OSCL_EXPORT_REF PVID3ParCom::PVID3ParCom()
79 : iInputFile(NULL),
80 iTitleFoundFlag(false),
81 iArtistFoundFlag(false),
82 iAlbumFoundFlag(false),
83 iYearFoundFlag(false),
84 iCommentFoundFlag(false),
85 iTrackNumberFoundFlag(false),
86 iGenereFoundFlag(false),
87 iFileSizeInBytes(0),
88 iByteOffsetToStartOfAudioFrames(0),
89 iID3V1Present(false),
90 iID3V2Present(false),
91 iVersion(PV_ID3_INVALID_VERSION),
92 iUseMaxTagSize(false),
93 iMaxTagSize(0),
94 iUsePadding(false),
95 iTagAtBof(false),
96 iSeekFrameFound(false)
97 {
98 iLogger = PVLogger::GetLoggerObject("PVID3ParCom");
99 iID3TagInfo.iID3V2ExtendedHeaderSize = 0;
100 iID3TagInfo.iID3V2FrameSize = 0;
101 iID3TagInfo.iID3V2TagFlagsV2 = 0;
102 iID3TagInfo.iID3V2TagSize = 0 ;
103 iID3TagInfo.iFooterPresent = false;
104
105 oscl_memset(&iID3TagInfo.iID3V2FrameFlag, 0, sizeof(iID3TagInfo.iID3V2FrameFlag));
106
107 }
108
109 ////////////////////////////////////////////////////////////////////////////
~PVID3ParCom()110 OSCL_EXPORT_REF PVID3ParCom::~PVID3ParCom()
111 {
112 iFrames.clear();
113 }
114
115 ////////////////////////////////////////////////////////////////////////////
GetID3TagSize(PVFile * aFile)116 OSCL_EXPORT_REF uint32 PVID3ParCom::GetID3TagSize(PVFile* aFile)
117 {
118 if (!aFile)
119 {
120 return 0;
121 }
122
123 iInputFile = aFile;
124
125 if (iInputFile->Seek(0, Oscl_File::SEEKSET) == -1)
126 {
127 iFileSizeInBytes = 0;
128 }
129 else
130 {
131 iInputFile->GetRemainingBytes((uint32&)iFileSizeInBytes);
132 if (iInputFile->Seek(0, Oscl_File::SEEKSET) == -1)
133 {
134 return 0;
135 }
136 }
137
138 uint32 buffsize = 100; //number of bytes to search , from the end of file, to look for footer
139 if (CheckForTagID3V2()
140 || (LookForV2_4Footer(buffsize, 0) == PVMFSuccess))
141 {
142 if (iInputFile->Seek(2, Oscl_File::SEEKCUR) == -1)
143 {
144 return 0;
145 }
146
147 // Read and convert tag flags
148 uint8 flags = 0;
149 if (read8(iInputFile, flags) == false)
150 {
151 return 0;
152 }
153
154 // Read and convert tag size
155 uint32 synchIntTagSize;
156 if (read32(iInputFile, synchIntTagSize) == false)
157 {
158 return 0;
159 }
160
161 // tagSize will store the file's Id3v2 tag size
162 uint32 tagSize = SafeSynchIntToInt32(synchIntTagSize) + ID3V2_TAG_NUM_BYTES_HEADER;
163
164 //check if footer is present
165 if ((iVersion == PV_ID3_V2_4) && (flags & FTR_FLAGMASK))
166 tagSize += ID3V2_TAG_NUM_BYTES_HEADER; // add 10 bytes for footer
167
168 return tagSize;
169 }
170 else
171 {
172 if (CheckForTagID3V1())
173 {
174 return ID3V1_MAX_NUM_BYTES_TOTAL;
175 }
176 }
177 return 0;
178 }
179
180 ////////////////////////////////////////////////////////////////////////////
GetID3TagSize()181 OSCL_EXPORT_REF uint32 PVID3ParCom::GetID3TagSize()
182 {
183 uint32 composedTagSize = 0;
184 switch (iVersion)
185 {
186 case PV_ID3_V2_2:
187 case PV_ID3_V2_3:
188 case PV_ID3_V2_4:
189 {
190 composedTagSize = ID3V2_TAG_NUM_BYTES_HEADER + iID3TagInfo.iID3V2TagSize;
191
192 if (iID3TagInfo.iFooterPresent)
193 composedTagSize += ID3V2_TAG_NUM_BYTES_HEADER; //footer is replica of Tag Header
194 }
195 break;
196
197 case PV_ID3_V1:
198 case PV_ID3_V1_1:
199 composedTagSize = 128; // ID3v1 tag has fix size
200 break;
201 default:
202 composedTagSize = 0;
203
204 }
205
206 return composedTagSize;
207 }
208
209 ////////////////////////////////////////////////////////////////////////////
SetMaxID3TagSize(bool aUseMaxSize,uint32 aMaxSize,bool aUsePadding)210 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::SetMaxID3TagSize(bool aUseMaxSize, uint32 aMaxSize, bool aUsePadding)
211 {
212 switch (iVersion)
213 {
214 case PV_ID3_V1:
215 case PV_ID3_V1_1:
216 case PV_ID3_INVALID_VERSION:
217 {
218 LOG_ERR((0, "PVID3Parcom::SetMaxID3TagSize: Error - Fix size ID3 tag"));
219 return PVMFErrNotSupported;
220 }
221 case PV_ID3_V2_2:
222 // Minimum for an ID3v2_2 tag is tag header plus 1 frame. The minimum data length of
223 // a frame is 1 byte
224 {
225 if (aUseMaxSize && aMaxSize < (ID3V2_TAG_NUM_BYTES_HEADER + ID3V2_2_FRAME_NUM_BYTES_HEADER + 1))
226 {
227 LOG_ERR((0, "PVID3ParCom::SetMaxID3TagSize: Error - Minimum tag size is 17 bytes"));
228 return PVMFErrArgument;
229 }
230 }
231 break;
232 case PV_ID3_V2_3:
233 case PV_ID3_V2_4:
234 // Minimum for an ID3v2 tag is tag header plus 1 frame. The minimum data length of
235 // a frame is 1 byte
236 if (aUseMaxSize && aMaxSize < (ID3V2_TAG_NUM_BYTES_HEADER + ID3V2_FRAME_NUM_BYTES_HEADER + 1))
237 {
238 LOG_ERR((0, "PVID3ParCom::SetMaxID3TagSize: Error - Minimum tag size is 21 bytes"));
239 return PVMFErrArgument;
240 }
241 }
242
243 iUseMaxTagSize = aUseMaxSize;
244 if (iUseMaxTagSize)
245 {
246 iMaxTagSize = aMaxSize;
247 iUsePadding = aUsePadding;
248 }
249 else
250 {
251 iMaxTagSize = 0;
252 iUsePadding = false;
253 }
254
255 return PVMFSuccess;
256 }
257
258 ////////////////////////////////////////////////////////////////////////////
ParseID3Tag(PVFile * aFile,uint32 buffsize)259 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::ParseID3Tag(PVFile* aFile, uint32 buffsize)
260 {
261 if (!aFile)
262 {
263 return PVMFFailure;
264 }
265
266 iInputFile = aFile;
267
268 int32 currentFilePosn = 0;
269
270 // SEEK TO THE END OF THE FILE AND GET FILE SIZE
271 currentFilePosn = iInputFile->Tell();
272 if (currentFilePosn == -1)
273 {
274 return PVMFFailure;
275 }
276
277 if (iInputFile->Seek(0, Oscl_File::SEEKSET) == -1)
278 {
279 iFileSizeInBytes = 0;
280 }
281 else
282 {
283 iInputFile->GetRemainingBytes((uint32&)iFileSizeInBytes);
284 if (iInputFile->Seek(currentFilePosn, Oscl_File::SEEKSET) == -1)
285 {
286 iInputFile = NULL;
287 return PVMFFailure;
288 }
289 }
290
291 bool readTags = false;
292 //check for ID3 Version 2
293 if (CheckForTagID3V2() || (LookForV2_4Footer(buffsize, 0) == PVMFSuccess))
294 {
295 //Read the header
296 readTags = ReadHeaderID3V2();
297
298 //check for ID3 Version 1
299 if (CheckForTagID3V1())
300 {
301 iVersion = PV_ID3_V1;
302 ReadID3V1Tag();
303 }
304 if (iInputFile->Seek(currentFilePosn, Oscl_File::SEEKSET) == -1)
305 {
306 iInputFile = NULL;
307 return PVMFFailure;
308 }
309 }
310 else if (!readTags && CheckForTagID3V1())
311 {
312 //check for ID3 Version 1
313 iVersion = PV_ID3_V1;
314 //Read the header
315 ReadID3V1Tag();
316
317 iByteOffsetToStartOfAudioFrames = 0;
318 if (iInputFile->Seek(currentFilePosn, Oscl_File::SEEKSET) == -1)
319 {
320 iInputFile = NULL;
321 return PVMFFailure;
322 }
323 }
324 else
325 {
326 return PVMFFailure;
327 }
328
329 iInputFile = NULL;
330 return PVMFSuccess;
331 }
332
333 ////////////////////////////////////////////////////////////////////////////
GetID3Version() const334 OSCL_EXPORT_REF PVID3Version PVID3ParCom::GetID3Version() const
335 {
336 return iVersion;
337 }
338
339 ////////////////////////////////////////////////////////////////////////////
IsID3V1Present() const340 OSCL_EXPORT_REF bool PVID3ParCom::IsID3V1Present() const
341 {
342 return iID3V1Present;
343 }
344
345 ////////////////////////////////////////////////////////////////////////////
IsID3V2Present() const346 OSCL_EXPORT_REF bool PVID3ParCom::IsID3V2Present() const
347 {
348 return iID3V2Present;
349 }
350
351 ////////////////////////////////////////////////////////////////////////////
GetID3Frames(PvmiKvpSharedPtrVector & aFrames)352 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::GetID3Frames(PvmiKvpSharedPtrVector& aFrames)
353 {
354 aFrames = iFrames;
355 return PVMFSuccess;
356 }
357
358 ////////////////////////////////////////////////////////////////////////////
GetID3Frame(const OSCL_String & aFrameType,PvmiKvpSharedPtrVector & aFrameVector)359 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::GetID3Frame(const OSCL_String& aFrameType, PvmiKvpSharedPtrVector& aFrameVector)
360 {
361 uint32 i;
362 for (i = 0; i < iFrames.size(); i++)
363 {
364 if (pv_mime_strcmp(iFrames[i]->key, aFrameType.get_str()) == 0)
365 {
366 return PushFrameToFrameVector(iFrames[i], aFrameVector);
367 }
368 }
369
370 return PVMFSuccess;
371 }
372
373 ////////////////////////////////////////////////////////////////////////////
IsID3FrameAvailable(const OSCL_String & aFrameType)374 OSCL_EXPORT_REF bool PVID3ParCom::IsID3FrameAvailable(const OSCL_String& aFrameType)
375 {
376 uint32 i;
377 for (i = 0; i < iFrames.size(); i++)
378 {
379 if (pv_mime_strcmp(iFrames[i]->key, aFrameType.get_str()) == 0)
380 {
381 return true;
382 }
383 }
384
385 return false;
386 }
387
388 ////////////////////////////////////////////////////////////////////////////
SetID3Version(PVID3Version aVersion)389 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::SetID3Version(PVID3Version aVersion)
390 {
391 iVersion = aVersion;
392 return PVMFSuccess;
393 }
394
395 ////////////////////////////////////////////////////////////////////////////
SetID3Frame(const PvmiKvp & aFrame)396 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::SetID3Frame(const PvmiKvp& aFrame)
397 {
398 uint32 i;
399 OSCL_StackString<4> frameID;
400 PVID3FrameType newFrameType;
401 PVID3FrameType existingFrameType;
402 PVMFStatus status = PVMFSuccess;
403
404 // Find an existing entry in iFrames with matching frame type
405 status = GetFrameTypeFromKvp(aFrame, frameID, newFrameType);
406 for (i = 0; status == PVMFSuccess && i < iFrames.size(); i++)
407 {
408 status = GetFrameTypeFromKvp(iFrames[i], frameID, existingFrameType);
409 if (status != PVMFSuccess)
410 {
411 LOG_ERR((0, "PVID3ParCom::SetID3Frame: Error - GetFrameTypeFromKvp failed"));
412 break;
413 }
414 if (existingFrameType == newFrameType)
415 {
416 iFrames.erase(iFrames.begin() + i);
417 break;
418 }
419
420 }
421
422 if (status != PVMFSuccess)
423 {
424 return status;
425 }
426
427 PvmiKvpValueType kvpValueType = GetValTypeFromKeyString(aFrame.key);
428 OSCL_StackString<128> key = _STRLIT_CHAR(aFrame.key);
429 uint32 valueSize = 0;
430 uint32 valueStrLen = 0;
431 switch (kvpValueType)
432 {
433 case PVMI_KVPVALTYPE_CHARPTR:
434 valueStrLen = oscl_strlen(aFrame.value.pChar_value);
435 valueSize = valueStrLen + 1;
436 break;
437 case PVMI_KVPVALTYPE_WCHARPTR:
438 valueStrLen = oscl_strlen(aFrame.value.pWChar_value);
439 valueSize = (valueStrLen + 2) * sizeof(oscl_wchar);
440 break;
441 case PVMI_KVPVALTYPE_KSV:
442 // Comment field
443 break;
444 case PVMI_KVPVALTYPE_UINT32:
445 valueSize = 0;
446 break;
447 default:
448 return PVMFErrNotSupported;
449 }
450
451 status = PVMFSuccess;
452 PvmiKvpSharedPtr kvp;
453 bool truncate = false;
454 kvp = HandleErrorForKVPAllocation(key, kvpValueType, valueSize, truncate, status);
455
456 if (truncate || (PVMFSuccess != status) || !kvp)
457 {
458 return PVMFErrNoMemory;
459 }
460
461 switch (kvpValueType)
462 {
463 case PVMI_KVPVALTYPE_CHARPTR:
464 oscl_strncpy(kvp->value.pChar_value, aFrame.value.pChar_value, valueStrLen);
465 kvp->value.pChar_value[valueStrLen] = NULL_TERM_CHAR;
466 break;
467 case PVMI_KVPVALTYPE_WCHARPTR:
468 oscl_strncpy(kvp->value.pWChar_value, aFrame.value.pWChar_value, valueStrLen);
469 kvp->value.pWChar_value[valueStrLen] = NULL_TERM_CHAR;
470 break;
471 case PVMI_KVPVALTYPE_UINT32:
472 kvp->value.uint32_value = aFrame.value.uint32_value;
473 break;
474 case PVMI_KVPVALTYPE_KSV:
475 // comment field
476 default:
477 return PVMFErrNotSupported;
478 }
479
480
481 if (PVMFSuccess != PushFrameToFrameVector(kvp, iFrames))
482 {
483 return PVMFErrNoMemory;
484 }
485 return PVMFSuccess;
486 }
487
488 ////////////////////////////////////////////////////////////////////////////
RemoveID3Frame(const OSCL_String & aFrameType)489 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::RemoveID3Frame(const OSCL_String& aFrameType)
490 {
491 uint32 i;
492 for (i = 0; i < iFrames.size(); i++)
493 {
494 if (pv_mime_strcmp(iFrames[i]->key, aFrameType.get_str()) == 0)
495 {
496 iFrames.erase(iFrames.begin() + i);
497 return PVMFSuccess;
498 }
499 }
500
501 // Frame of specified type is not found
502 return PVMFErrArgument;
503 }
504
505 ////////////////////////////////////////////////////////////////////////////
ComposeID3Tag(OsclRefCounterMemFrag & aTag)506 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::ComposeID3Tag(OsclRefCounterMemFrag& aTag)
507 {
508 switch (iVersion)
509 {
510 case PV_ID3_V2_2:
511 case PV_ID3_V2_3:
512 case PV_ID3_V2_4:
513 return ComposeID3v2Tag(aTag);
514 default:
515 return PVMFErrNotSupported;
516 }
517 }
518
519 ////////////////////////////////////////////////////////////////////////////
Reset()520 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::Reset()
521 {
522 iFrames.clear();
523 return PVMFSuccess;
524 }
525
526 ////////////////////////////////////////////////////////////////////////////
CheckForTagID3V1()527 bool PVID3ParCom::CheckForTagID3V1()
528 {
529 uint8 tagHeader[ID3V1_TAG_NUM_BYTES_HEADER+1] = {0};
530
531 // Make sure file is big enough to contain a tag
532 if (iFileSizeInBytes >= ID3V1_MAX_NUM_BYTES_TOTAL)
533 {
534 uint32 nBytes = 0;
535 // Read the value at the tag position
536
537 nBytes = iFileSizeInBytes - ID3V1_MAX_NUM_BYTES_TOTAL;
538 if (iInputFile->Seek(nBytes, Oscl_File::SEEKSET) == -1)
539 {
540 return false;
541 }
542
543
544 if (!readByteData(iInputFile, ID3V1_TAG_NUM_BYTES_HEADER, tagHeader))
545 {
546 return false;
547 }
548
549 // Read in ID3 Tags at the front of the file.
550 if (oscl_memcmp(ID3_V1_IDENTIFIER, tagHeader, ID3V1_TAG_NUM_BYTES_HEADER) == 0)
551 {
552 iID3V1Present = true;
553 return true;
554 }
555 }
556 return false;
557 }
558
559 ////////////////////////////////////////////////////////////////////////////
CheckForTagID3V2()560 bool PVID3ParCom::CheckForTagID3V2()
561 {
562 uint8 id3Header[ID3V2_TAG_NUM_BYTES_HEADER+1] = {0};
563
564 if (!readByteData(iInputFile, ID3V2_TAG_NUM_BYTES_ID, id3Header))
565 {
566 return false;
567 }
568
569 // Read in ID3 Tags at the front of the file.
570 if (oscl_memcmp(ID3_V2_IDENTIFIER, id3Header, ID3V2_TAG_NUM_BYTES_ID) == 0)
571 {
572 iTagAtBof = true;
573 iID3V2Present = true;
574 return true;
575 }
576 return false;
577 }
578
IsID3V2Present(PVFile * aFile,uint32 & aTagSize)579 OSCL_EXPORT_REF bool PVID3ParCom::IsID3V2Present(PVFile* aFile, uint32& aTagSize)
580 {
581 iInputFile = aFile;
582 if (iID3V2Present)
583 {
584 // if id3 tag has already been discovered, just return the tag size
585 aTagSize = iByteOffsetToStartOfAudioFrames;
586 return true;
587 }
588
589 if (CheckForTagID3V2())
590 {
591 // we dont want to parse the id3 frames, just read the id3 header
592
593 ReadHeaderID3V2(false);
594 aTagSize = iByteOffsetToStartOfAudioFrames;
595 return true;
596 }
597 return false;
598 }
599
LookForV2_4Footer(uint32 aBuffSz,uint32 aFileOffset)600 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::LookForV2_4Footer(uint32 aBuffSz, uint32 aFileOffset)
601 {
602 if (iTagAtBof) //already found tag. no need to search from the end.
603 return PVMFFailure;
604
605 uint32 footer_location = SearchTagV2_4(aBuffSz, aFileOffset);
606
607 if (footer_location == 0)
608 return PVMFFailure;
609
610 if (iInputFile->Seek(footer_location + ID3V2_TAG_NUM_BYTES_ID + ID3V2_TAG_NUM_BYTES_VERSION + ID3V2_TAG_NUM_BYTES_FLAG,
611 Oscl_File::SEEKSET) == -1)
612 {
613 return PVMFFailure;
614 }
615
616 uint32 tag_size = 0, size = 0;
617
618 if (read32(iInputFile, size) == false)
619 {
620 return PVMFFailure;
621 }
622
623 tag_size = SafeSynchIntToInt32(size);
624
625 if (iInputFile->Seek(-(int32)(tag_size + ID3V2_TAG_NUM_BYTES_HEADER + (ID3V2_TAG_NUM_BYTES_HEADER - ID3V2_TAG_NUM_BYTES_ID)),
626 Oscl_File::SEEKCUR) == -1)
627 {
628 return PVMFFailure;
629 }
630
631 return PVMFSuccess;
632 }
633 ////////////////////////////////////////////////////////////////////////////
634 // (if an error is detected, this returns 0)
635
SearchTagV2_4(uint32 aBuffSz,uint32 aFileOffset)636 uint32 PVID3ParCom::SearchTagV2_4(uint32 aBuffSz, uint32 aFileOffset)
637 {
638
639 if (iFileSizeInBytes == 0)
640 return 0;
641
642 uint8 *buff = (uint8 *)oscl_malloc(aBuffSz);
643 if (! buff) // malloc might fail
644 return 0;
645
646 int remaining_bytes = 0;
647
648 int num_bytes_read = aBuffSz + aFileOffset;
649
650 //in case we have almost reached to the begining of file,
651 //and remaining bytes are less than the buffer size,
652 //look for ID3 tag in the remaining bytes only.
653
654 if (num_bytes_read > iFileSizeInBytes)
655 remaining_bytes = iFileSizeInBytes - (num_bytes_read - aBuffSz);
656
657 if (remaining_bytes > 0)
658 {
659
660 if (iInputFile->Seek(0 , Oscl_File::SEEKSET) == -1)
661 {
662 oscl_free(buff);
663 return 0;
664 }
665
666 if (readByteData(iInputFile, remaining_bytes, buff) == false)
667 {
668 oscl_free(buff);
669 return 0;
670 }
671
672 for (int i = 0; i < remaining_bytes; i++)
673 {
674 if (oscl_memcmp(buff + i, ID3_V2_4_TAG_FOOTER, ID3V2_TAG_NUM_BYTES_ID) == 0)
675 {
676 oscl_free(buff);
677 return i;
678 }
679
680 }
681
682 oscl_free(buff);
683 return 0;
684 }
685 else
686 {
687
688 if (iInputFile->Seek((iFileSizeInBytes - (aFileOffset + aBuffSz)), Oscl_File::SEEKSET) == -1)
689 {
690 oscl_free(buff);
691 return 0;
692 }
693
694 if (readByteData(iInputFile, aBuffSz, buff) == false)
695 {
696 oscl_free(buff);
697 return 0;
698 }
699
700 for (uint i = 0; i < aBuffSz; i++)
701 {
702 if (oscl_memcmp(buff + i, ID3_V2_4_TAG_FOOTER, ID3V2_TAG_NUM_BYTES_ID) == 0)
703 {
704 oscl_free(buff);
705 return ((iFileSizeInBytes - ((aFileOffset + aBuffSz) - i)));
706 }
707
708 }
709
710 }
711
712 oscl_free(buff);
713 return 0;
714 }
715
716 ////////////////////////////////////////////////////////////////////////////
ReadID3V1Tag(void)717 void PVID3ParCom::ReadID3V1Tag(void)
718 {
719
720 PVMFStatus status = PVMFSuccess;
721 bool truncate = false;
722
723 if (!iTitleFoundFlag)
724 {
725 //Title
726 status = ReadStringValueFrame(PV_ID3_FRAME_TITLE, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_TITLE);
727 if (status != PVMFSuccess)
728 {
729 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for title"));
730 OSCL_LEAVE(OsclErrGeneral);
731 }
732 iTitleFoundFlag = true;
733 }
734 else
735 {
736
737 if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_TITLE, Oscl_File::SEEKCUR) == -1)
738 {
739 return;
740 }
741
742 }
743 if (!iArtistFoundFlag)
744 {
745 //Artist
746 status = ReadStringValueFrame(PV_ID3_FRAME_ARTIST, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_ARTIST);
747 if (status != PVMFSuccess)
748 {
749 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for artist"));
750 OSCL_LEAVE(OsclErrGeneral);
751 }
752 iArtistFoundFlag = true;
753 }
754 else
755 {
756 if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_ARTIST, Oscl_File::SEEKCUR) == -1)
757 {
758 return;
759 }
760 }
761
762 if (!iAlbumFoundFlag)
763 {
764 // Album
765 status = ReadStringValueFrame(PV_ID3_FRAME_ALBUM, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_ALBUM);
766 if (status != PVMFSuccess)
767 {
768 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for album"));
769 OSCL_LEAVE(OsclErrGeneral);
770 }
771 iAlbumFoundFlag = true;
772 }
773 else
774 {
775 if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_ALBUM, Oscl_File::SEEKCUR) == -1)
776 {
777 return;
778 }
779 }
780
781 if (!iYearFoundFlag)
782 {
783 //Year
784 status = ReadStringValueFrame(PV_ID3_FRAME_YEAR, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_YEAR);
785 if (status != PVMFSuccess)
786 {
787 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for year"));
788 OSCL_LEAVE(OsclErrGeneral);
789 }
790 iYearFoundFlag = true;
791 }
792 else
793 {
794 if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_YEAR, Oscl_File::SEEKCUR) == -1)
795 {
796 return;
797 }
798 }
799 OSCL_StackString<128> keyStr;
800 PvmiKvpSharedPtr kvpPtr;
801 uint8* frameData = NULL;
802
803 if (!iCommentFoundFlag || !iTrackNumberFoundFlag)
804 {
805 frameData = NULL;
806 //Comment or Track Number
807 // Read and convert comment & track number
808 uint32 frameDataSize = ID3V1_MAX_NUM_BYTES_FIELD_SIZE + 1;
809 int32 err = OsclErrNone;
810 frameData = (uint8*) AllocateValueArray(err, PVMI_KVPVALTYPE_UINT8PTR, frameDataSize, &iAlloc);
811 if (OsclErrNone != err || !frameData)
812 {
813 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - Out of memory"));
814 OSCL_LEAVE(OsclErrNoMemory);
815 }
816 oscl_memset(frameData, 0, frameDataSize);
817
818 if (readByteData(iInputFile, ID3V1_MAX_NUM_BYTES_COMMENT, frameData) == false)
819 {
820 iAlloc.deallocate(frameData);
821 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - readByteData failed"));
822 OSCL_LEAVE(OsclErrGeneral);
823 }
824
825
826 if (frameData[ID3V1_MAX_NUM_BYTES_COMMENT-2] == 0 &&
827 frameData[ID3V1_MAX_NUM_BYTES_COMMENT-1] != 0)
828 {
829 if (!iTrackNumberFoundFlag)
830 {
831 // This would mean its an ID3v1.1 tag and hence has the
832 // the track number also, so extract it
833 iVersion = PV_ID3_V1_1;
834
835 if (ConstructKvpKey(keyStr, PV_ID3_FRAME_TRACK_NUMBER, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
836 {
837 iAlloc.deallocate(frameData);
838 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - ConstructKvpKey failed for tracknumber"));
839 OSCL_LEAVE(OsclErrNotSupported);
840 }
841
842 // Allocate key-value pair
843 OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_UINT32, 1, truncate););
844 if (OsclErrNone != err || !kvpPtr)
845 {
846 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - AllocateKvp failed. err=%d", err));
847 iAlloc.deallocate(frameData);
848 OSCL_LEAVE(OsclErrNoMemory);
849 return;
850 }
851
852 if (!truncate)
853 {
854 kvpPtr->value.uint32_value = (uint32)frameData[ID3V1_MAX_NUM_BYTES_COMMENT - 1];
855 }
856 OSCL_TRY(err, iFrames.push_back(kvpPtr););
857 OSCL_FIRST_CATCH_ANY(err,
858 LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - iFrame.push_back failed"));
859 iAlloc.deallocate(frameData);
860 OSCL_LEAVE(OsclErrNoMemory);
861 return;
862 );
863 iTrackNumberFoundFlag = true;
864 }
865 }
866 if (!iCommentFoundFlag)
867 {
868
869 // Comment frame
870 frameData[ID3V1_MAX_NUM_BYTES_COMMENT] = 0;
871 if (ConstructKvpKey(keyStr, PV_ID3_FRAME_COMMENT, PV_ID3_CHARSET_ISO88591) != PVMFSuccess)
872 {
873 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - ConstructKvpKey failed for tracknumber"));
874 iAlloc.deallocate(frameData);
875 OSCL_LEAVE(OsclErrNotSupported);
876 }
877
878 uint32 dataSize = ID3V1_MAX_NUM_BYTES_COMMENT + 1;
879 // Allocate key-value pair
880 OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, dataSize, truncate););
881 if (OsclErrNone != err || !kvpPtr)
882 {
883 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - AllocateKvp failed. err=%d", err));
884 iAlloc.deallocate(frameData);
885 OSCL_LEAVE(OsclErrNoMemory);
886 return;
887 }
888
889 if (!truncate)
890 {
891 uint32 comment_size = oscl_strlen((char*) frameData);
892 oscl_strncpy(kvpPtr->value.pChar_value, (char *)frameData, dataSize);
893 kvpPtr->value.pChar_value[comment_size] = 0;
894 kvpPtr->length = comment_size + 1;
895 }
896
897 if (PVMFSuccess != PushFrameToFrameVector(kvpPtr, iFrames))
898 {
899 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - iFrame.push_back failed"));
900 iAlloc.deallocate(frameData);
901 return ;
902 }
903 iCommentFoundFlag = true;
904
905 }
906 iAlloc.deallocate(frameData);
907 }
908 else
909 {
910 if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_FIELD_SIZE, Oscl_File::SEEKCUR) == -1)
911 {
912 return;
913 }
914 }
915 if (!iGenereFoundFlag)
916 {
917 // Genre frame
918 uint32 frameDataSize = ID3V1_MAX_NUM_BYTES_GENRE + 1;
919 int32 err = 0;
920 frameData = (uint8*) AllocateValueArray(err, PVMI_KVPVALTYPE_UINT8PTR, frameDataSize, &iAlloc);
921 if (OsclErrNone != err || !frameData)
922 {
923 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - Out of memory"));
924 OSCL_LEAVE(OsclErrNoMemory);
925 }
926 oscl_memset(frameData, 0, frameDataSize);
927
928 if (readByteData(iInputFile, ID3V1_MAX_NUM_BYTES_GENRE, frameData) == false)
929 {
930 iAlloc.deallocate(frameData);
931 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - readByteData failed"));
932 OSCL_LEAVE(OsclErrGeneral);
933 }
934
935 if (ConstructKvpKey(keyStr, PV_ID3_FRAME_GENRE, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
936 {
937 iAlloc.deallocate(frameData);
938 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - ConstructKvpKey failed for genre"));
939 OSCL_LEAVE(OsclErrNotSupported);
940 }
941
942 OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_UINT32, 1, truncate););
943 if (OsclErrNone != err || !kvpPtr)
944 {
945 iAlloc.deallocate(frameData);
946 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - AllocateKvp failed. err=%d", err));
947 OSCL_LEAVE(OsclErrNoMemory);
948 return;
949 }
950
951 if (!truncate)
952 {
953 kvpPtr->value.uint32_value = (uint32)(frameData[ID3V1_MAX_NUM_BYTES_GENRE - 1]);
954 }
955 OSCL_TRY(err, iFrames.push_back(kvpPtr););
956 OSCL_FIRST_CATCH_ANY(err,
957 iAlloc.deallocate(frameData);
958 LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - iFrame.push_back failed"));
959 OSCL_LEAVE(OsclErrNoMemory);
960 return;
961 );
962 iAlloc.deallocate(frameData);
963 iGenereFoundFlag = true;
964 }
965 else
966 {
967 if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_GENRE, Oscl_File::SEEKCUR) == -1)
968 {
969 return;
970 }
971 }
972 }
973
974 ////////////////////////////////////////////////////////////////////////////
ReadHeaderID3V2(bool aReadTags)975 bool PVID3ParCom::ReadHeaderID3V2(bool aReadTags)
976 {
977 bool result = false;
978
979 // Read and convert tag versions, Major and Minor
980 uint8 ID3V2MajorVer, ID3V2MinorVer;
981 if (read8(iInputFile, ID3V2MajorVer) == false)
982 {
983 return false;
984 }
985 if (read8(iInputFile, ID3V2MinorVer) == false)
986 {
987 return false;
988 }
989
990 switch (ID3V2MajorVer)
991 {
992 case PV_ID3_V2_2:
993 iVersion = PV_ID3_V2_2;
994 break;
995 case PV_ID3_V2_3:
996 iVersion = PV_ID3_V2_3;
997 break;
998 case PV_ID3_V2_4:
999 iVersion = PV_ID3_V2_4;
1000 break;
1001 }
1002
1003 BEGIN_V2:
1004 // Read and convert tag flags
1005 if (read8(iInputFile, iID3TagInfo.iID3V2TagFlagsV2) == false)
1006 {
1007 return false;
1008 }
1009
1010 uint32 tagsize = 0;
1011
1012 // Read and convert tag size
1013 if (read32(iInputFile, tagsize) == false)
1014 {
1015 return false;
1016 }
1017
1018 // Now check if an extended header exists
1019 bool extHeaderFlag = false;
1020 if (iID3TagInfo.iID3V2TagFlagsV2 & EXT_FLAGMASK)
1021 {
1022 if (iVersion == PV_ID3_V2_2)
1023 {
1024 // Since no compression scheme has been decided yet, just ignore the entire tag
1025 LOG_ERR((0, "PVID3ParCom::ReadHeaderID3V2(): Error - cannot process a compressed tag"));
1026 OSCL_LEAVE(OsclErrGeneral);
1027 }
1028
1029 extHeaderFlag = true;
1030 //read extended header data
1031 if (!ReadExtendedHeader())
1032 return false;
1033 }
1034
1035 //check if footer is present.
1036 if (iID3TagInfo.iID3V2TagFlagsV2 & FTR_FLAGMASK)
1037 {
1038 iID3TagInfo.iFooterPresent = true;
1039 }
1040
1041 // tagSize will store the file's Id3v2 tag size
1042 iID3TagInfo.iID3V2TagSize = SafeSynchIntToInt32(tagsize);
1043
1044 //calculate start of audio frame.
1045 if (iTagAtBof)
1046 {
1047 // set iByteOffsetToStartOfAudioFrames and it must account for the frame header
1048 iByteOffsetToStartOfAudioFrames =
1049 iID3TagInfo.iID3V2TagSize + ID3V2_TAG_NUM_BYTES_HEADER;
1050
1051 if (iID3TagInfo.iFooterPresent)
1052 iByteOffsetToStartOfAudioFrames += ID3V2_TAG_NUM_BYTES_HEADER; //header & footer are of same size.
1053 }
1054 else
1055 {
1056 iByteOffsetToStartOfAudioFrames = 0;
1057 }
1058
1059 // Header read is completed, now check whether we need to read the tags or not
1060 if (!aReadTags)
1061 {
1062 return false;
1063 }
1064 else
1065 {
1066 int count = ReadTagID3V2(iVersion);
1067 if (count > 0)
1068 {
1069 // we found some tags
1070 result = true;
1071 }
1072
1073 if (iSeekFrameFound)
1074 {
1075 //jump to the new tag location skipping 5 bytes of tag ID and version.
1076 uint32 seek_size = iID3TagInfo.iID3V2TagSize + ID3V2_TAG_NUM_BYTES_HEADER + (iID3TagInfo.iFooterPresent ? ID3V2_TAG_NUM_BYTES_HEADER : 0);
1077 if (iInputFile->Seek(seek_size, Oscl_File::SEEKSET) == -1)
1078 {
1079 return false;
1080 }
1081
1082 //skip 5 bytes of tag ID and version.
1083 if (iInputFile->Seek(iID3TagInfo.iID3V2SeekOffset, Oscl_File::SEEKCUR) == -1)
1084 {
1085 return false;
1086 }
1087
1088 if (!CheckForTagID3V2())
1089 return false;
1090
1091 if (read8(iInputFile, ID3V2MajorVer) == false)
1092 {
1093 return false;
1094 }
1095
1096 if (read8(iInputFile, ID3V2MinorVer) == false)
1097 {
1098 return false;
1099 }
1100
1101 if (ID3V2MajorVer != PV_ID3_V2_4)
1102 return false;
1103
1104 //parse new tag, located at the seek offset.
1105 iSeekFrameFound = false;
1106 goto BEGIN_V2;
1107 }
1108 }
1109 return result;
1110 }
1111
1112 /////////////////////////////////////////////////////////////////////////////////
ReadExtendedHeader()1113 bool PVID3ParCom::ReadExtendedHeader()
1114 {
1115
1116 uint32 extsize = 0;
1117 if (read32(iInputFile, extsize) == false)
1118 {
1119 return false;
1120 }
1121
1122 // Calculate the length of the extended header.
1123 iID3TagInfo.iID3V2ExtendedHeaderSize = SafeSynchIntToInt32(extsize);
1124
1125
1126 if (iVersion == PV_ID3_V2_4)
1127 {
1128 //subtract "ext hdr size" field size from the header size.
1129 iID3TagInfo.iID3V2ExtendedHeaderSize = iID3TagInfo.iID3V2ExtendedHeaderSize - ID3V2_TAG_EXTENDED_HEADER_SIZE;
1130
1131 //check if this tag is an update of previous tag.
1132 uint8 flgsize = 0, exthdrflg = 0;
1133 // Read and ext hdr flg size tag flags
1134 if (read8(iInputFile, flgsize) == false)
1135 {
1136 return false;
1137 }
1138 if (flgsize > 0x01) //flg size should be 1 byte in V2.4
1139 return false ;
1140 // Read tag flags
1141 if (read8(iInputFile, exthdrflg) == false)
1142 {
1143 return false;
1144 }
1145 //if this tag is not an update flag, ignore any tag found before this one
1146 if (!(exthdrflg & EXTHDR_UPDMASK) && (iFrames.size() > 0))
1147 {
1148 while (iFrames.size() > 0)
1149 iFrames.pop_back();
1150 }
1151
1152 //subtract 2 bytes for flg size and flg from ext hdr size.
1153 iID3TagInfo.iID3V2ExtendedHeaderSize = iID3TagInfo.iID3V2ExtendedHeaderSize - 2;
1154 }
1155
1156 if (iVersion == PV_ID3_V2_3)
1157 {
1158 //V2.3 extended hdr size field does not include 6 byte size of the header
1159 iID3TagInfo.iID3V2ExtendedHeaderSize += ID3V2_TAG_EXTENDED_HEADER_TOTAL_SIZE;
1160 }
1161
1162 return true;
1163 }
1164
1165 /////////////////////////////////////////////////////////////////////////////////
ReadTagID3V2(PVID3Version aVersion)1166 int PVID3ParCom::ReadTagID3V2(PVID3Version aVersion)
1167 {
1168 PVID3FrameType frameType = PV_ID3_FRAME_EEND;
1169 uint32 i = 0;
1170 uint32 currFrameLength = 0;
1171 uint32 current_file_pos = iInputFile->Tell();
1172 uint32 data_len_indicator_size = 0;
1173 uint32 count = 0;
1174
1175 if (iID3TagInfo.iID3V2ExtendedHeaderSize > 0)
1176 i += iID3TagInfo.iID3V2ExtendedHeaderSize ;
1177
1178 while (i <= (iID3TagInfo.iID3V2TagSize))
1179 {
1180 // Read the frame header
1181 if (iInputFile->Seek(current_file_pos + i, Oscl_File::SEEKSET) == -1)
1182 {
1183 return count;
1184 }
1185
1186 ReadFrameHeaderID3V2(aVersion);
1187
1188 currFrameLength = iID3TagInfo.iID3V2FrameSize;
1189 frameType = FrameSupportedID3V2(aVersion);
1190
1191 if ((frameType != PV_ID3_FRAME_SEEK) && (currFrameLength > iID3TagInfo.iID3V2TagSize))
1192 {
1193 break;
1194 }
1195 // handle the frame header
1196
1197 uint32 frame_header_size = 0;
1198 if (aVersion == PV_ID3_V2_2)
1199 frame_header_size = ID3V2_2_FRAME_NUM_BYTES_HEADER;
1200 else
1201 frame_header_size = ID3V2_FRAME_NUM_BYTES_HEADER;
1202
1203
1204 if ((currFrameLength == 0) && (frameType != PV_ID3_FRAME_EEND))
1205 {
1206 i += frame_header_size;
1207 continue;
1208 }
1209 if (aVersion == PV_ID3_V2_3)
1210 {
1211 if (iID3TagInfo.iID3V2FrameFlag[1] & ENCR_COMP_3_FLAGMASK)
1212 frameType = PV_ID3_FRAME_UNRECOGNIZED;
1213 }
1214 else if (aVersion == PV_ID3_V2_4)
1215 {
1216 if (iID3TagInfo.iID3V2FrameFlag[1] & ENCR_COMP_4_FLAGMASK)
1217 frameType = PV_ID3_FRAME_UNRECOGNIZED;
1218 }
1219
1220 if (frameType == PV_ID3_FRAME_SEEK)
1221 {
1222 iSeekFrameFound = true;
1223 iID3TagInfo.iID3V2SeekOffset = iID3TagInfo.iID3V2FrameSize;
1224 return count;
1225 }
1226
1227 // Check if data length indicator is present
1228 if (aVersion == PV_ID3_V2_4 && (iID3TagInfo.iID3V2FrameFlag[1] & FRAME_LENGTH_INDICATOR_FLAGMASK))
1229 {
1230 uint32 temp = 0;
1231 // Read data length indicator
1232 if (read32(iInputFile, temp) == false)
1233 {
1234 return count;
1235 }
1236 // stored as syncsafe integer
1237 currFrameLength = SafeSynchIntToInt32(temp);
1238
1239 data_len_indicator_size = ID3V2_4_DATA_LENGTH_INDICATOR_SIZE;
1240 }
1241
1242 if (((currFrameLength > 1) && (frameType != PV_ID3_FRAME_UNRECOGNIZED
1243 && frameType != PV_ID3_FRAME_INVALID
1244 && frameType != PV_ID3_FRAME_EEND
1245 && frameType != PV_ID3_FRAME_CANDIDATE)))
1246 {
1247 uint8 unicodeCheck;
1248
1249 if (read8(iInputFile, unicodeCheck) == false)
1250 {
1251 return count;
1252 }
1253
1254 if ((frameType == PV_ID3_FRAME_LYRICS) || (frameType == PV_ID3_FRAME_COMMENT))
1255 {
1256 ReadLyricsCommFrame(unicodeCheck, currFrameLength - 1, frameType);
1257
1258 }
1259 else if ((frameType == PV_ID3_FRAME_APIC) || (frameType == PV_ID3_FRAME_PIC))
1260 {
1261 if (currFrameLength > 3000000)
1262 {
1263 // TODO: scale down album art to something manageable right here
1264 LOG_DEBUG((0, "PVID3ParCom::ReadTagID3V2: skipping > 3MB album art"));
1265 }
1266 else
1267 {
1268 if (ReadAlbumArtFrame(frameType, unicodeCheck, currFrameLength) != PVMFSuccess)
1269 {
1270 LOG_ERR((0, "PVID3ParCom::ReadTagID3V2: Error - ReadAPICFrame failed"));
1271 return count;
1272 }
1273 }
1274 }
1275 else if (unicodeCheck < PV_ID3_CHARSET_END)
1276 {
1277
1278 if (!ReadFrameData(unicodeCheck, frameType,
1279 current_file_pos + i + frame_header_size + data_len_indicator_size + 1,
1280 currFrameLength))
1281 {
1282 return count;
1283 }
1284 }
1285 else
1286 {
1287 // This case is when no text type is defined in the frame.
1288 HandleID3V2FrameDataASCII(frameType, i + frame_header_size + data_len_indicator_size, currFrameLength);
1289 }
1290 count++;
1291 }
1292 else
1293 {
1294 if (frameType == PV_ID3_FRAME_EEND ||
1295 frameType == PV_ID3_FRAME_INVALID)
1296 {
1297 i = iID3TagInfo.iID3V2TagSize + 1;
1298 }
1299 else if (frameType == PV_ID3_FRAME_UNRECOGNIZED ||
1300 frameType == PV_ID3_FRAME_CANDIDATE) // handle candidate frames as we do unsupported
1301 {
1302 if (i < iID3TagInfo.iID3V2TagSize)
1303 {
1304 HandleID3V2FrameUnsupported(frameType,
1305 current_file_pos + i,
1306 currFrameLength + frame_header_size + data_len_indicator_size);
1307 }
1308 }
1309 }
1310
1311 i += iID3TagInfo.iID3V2FrameSize + frame_header_size;
1312 }
1313 return count;
1314 }
1315
ValidateFrameV2_4(PVID3FrameType & frameType,bool bUseSyncSafeFrameSize)1316 bool PVID3ParCom::ValidateFrameV2_4(PVID3FrameType& frameType, bool bUseSyncSafeFrameSize)
1317 {
1318 // Initialize OUT param
1319 frameType = PV_ID3_FRAME_INVALID;
1320
1321 uint8 frameid[ID3V2_FRAME_NUM_BYTES_ID + 1] = {0};
1322 // read frame id for next frame
1323 if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_ID, frameid) == false)
1324 {
1325 return false;
1326 }
1327 frameid[ID3V2_FRAME_NUM_BYTES_ID] = 0;
1328
1329 // Get frame type from frame ID
1330 frameType = FrameSupportedID3V2(PV_ID3_V2_4, frameid);
1331 if (PV_ID3_FRAME_INVALID == frameType ||
1332 PV_ID3_FRAME_EEND == frameType)
1333 {
1334 return false;
1335 }
1336 else
1337 {
1338 uint32 frameSize = 0;
1339 uint8 frameflags[ID3V2_FRAME_NUM_BYTES_FLAG] = {0};
1340
1341 // Validate frame size and flags
1342
1343 if (read32(iInputFile, frameSize) == false)
1344 {
1345 return false;
1346 }
1347 if (bUseSyncSafeFrameSize)
1348 {
1349 frameSize = SafeSynchIntToInt32(frameSize);
1350 }
1351
1352 if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_FLAG, frameflags) == false)
1353 {
1354 return false;
1355 }
1356
1357 if ((0 == frameSize ||
1358 (frameSize + ID3V2_FRAME_NUM_BYTES_HEADER) > iID3TagInfo.iID3V2TagSize) ||
1359 ((frameflags[0] & ID3V2_4_MASK_FRAME_FLAG_VERIFICATION) ||
1360 (frameflags[1] & ID3V2_4_MASK_FRAME_FLAG_VERIFICATION)))
1361 {
1362 // validation for frame size or flags failed
1363 return false;
1364 }
1365 else
1366 {
1367 return true;
1368 }
1369 }
1370 }
1371
ValidateFrameLengthV2_4(uint32 aFrameSize)1372 uint32 PVID3ParCom::ValidateFrameLengthV2_4(uint32 aFrameSize)
1373 {
1374 int32 currFilePos = iInputFile->Tell();
1375 int32 errCode = -1;
1376 int32 actualFrameLen = 0;
1377
1378 // we have already read the complete current frame header
1379
1380 do
1381 {
1382 // Assuming syncsafe frame size
1383 actualFrameLen = SafeSynchIntToInt32(aFrameSize);
1384
1385 //
1386 /* validate frame using syncsafe size */
1387 //
1388
1389 // Seek to next frame boundary with syncsafe size
1390 errCode = iInputFile->Seek(actualFrameLen, Oscl_File::SEEKCUR);
1391 if (-1 == errCode)
1392 {
1393 // proceed with default syncsafe handling
1394 break;
1395 }
1396
1397 bool bIsSyncSafeFrameValid = false;
1398 PVID3FrameType frameTypeUsingSyncSafeSize = PV_ID3_FRAME_INVALID;
1399 // Get the validation status and frame type
1400 bIsSyncSafeFrameValid = ValidateFrameV2_4(frameTypeUsingSyncSafeSize);
1401
1402 //
1403 /* validate frame using non-syncsafe size */
1404 //
1405
1406 // FrameSize is not even stored as non-syncsafe
1407 if ((aFrameSize + ID3V2_FRAME_NUM_BYTES_HEADER) > iID3TagInfo.iID3V2TagSize)
1408 {
1409 // proceed with syncsafe, as non-syncsafe length not valid
1410 break;
1411 }
1412
1413 // Seek back
1414 errCode = iInputFile->Seek(currFilePos, Oscl_File::SEEKSET);
1415 if (-1 == errCode)
1416 {
1417 LOG_ERR((0, "PVID3ParCom::ValidateFrameLengthV2_4: Error - iInputFile->Seek failed"));
1418 OSCL_LEAVE(OsclErrGeneral);
1419 }
1420 // Seek to next frame boundary with non-syncsafe size
1421 errCode = iInputFile->Seek(aFrameSize, Oscl_File::SEEKCUR);
1422 if (-1 == errCode)
1423 {
1424 // proceed with default syncsafe handling
1425 break;
1426 }
1427
1428 bool bIsNonSyncSafeFrameValid = false;
1429 PVID3FrameType frameTypeUsingNonSyncSafeSize = PV_ID3_FRAME_INVALID;
1430 // Get the validation status and frame type
1431 bIsNonSyncSafeFrameValid = ValidateFrameV2_4(frameTypeUsingNonSyncSafeSize, false);
1432
1433 // - Give more priority to non-syncsafe VALID frame ID,
1434 // than syncsafe candidate frame ID (frame validation is true for both)
1435 // - In case, we have frame validation true for both syncsafe and non-syncsafe size,
1436 // we will use default syncsafe representation
1437 // - In case, we have frame validation false for both syncsafe and non-syncsafe size,
1438 // we will use default syncsafe representation
1439 if (bIsSyncSafeFrameValid && frameTypeUsingSyncSafeSize != PV_ID3_FRAME_CANDIDATE)
1440 {
1441 // syncsafe representation
1442 }
1443 else if (bIsNonSyncSafeFrameValid && frameTypeUsingNonSyncSafeSize != PV_ID3_FRAME_CANDIDATE)
1444 {
1445 // non-syncsafe representation
1446 actualFrameLen = aFrameSize;
1447 }
1448 else if (!bIsSyncSafeFrameValid && bIsNonSyncSafeFrameValid)
1449 {
1450 // non-syncsafe representation
1451 actualFrameLen = aFrameSize;
1452 }
1453 else
1454 {
1455 // consider rest all syncsafe representation
1456 }
1457
1458 }
1459 while (false);
1460
1461 // Seek back
1462 errCode = iInputFile->Seek(currFilePos, Oscl_File::SEEKSET);
1463 if (-1 == errCode)
1464 {
1465 LOG_ERR((0, "PVID3ParCom::ValidateFrameLengthV2_4: Error - iInputFile->Seek failed"));
1466 OSCL_LEAVE(OsclErrGeneral);
1467 }
1468
1469 return actualFrameLen;
1470 }
1471
1472 //////////////////////////////////////////////////////////////////////////
ReadFrameData(uint8 unicodeCheck,PVID3FrameType frameType,uint32 pos,uint32 currFrameLength)1473 bool PVID3ParCom::ReadFrameData(uint8 unicodeCheck, PVID3FrameType frameType, uint32 pos, uint32 currFrameLength)
1474 {
1475 if (unicodeCheck == PV_ID3_CHARSET_ISO88591)
1476 {
1477 // This frame contains normal ASCII text strings. (ISO-8859-1)
1478 iID3TagInfo.iTextType = PV_ID3_CHARSET_ISO88591;
1479 HandleID3V2FrameDataASCII(frameType, pos, currFrameLength - 1);
1480 }
1481 else if (unicodeCheck == PV_ID3_CHARSET_UTF16)
1482 {
1483 uint16 endianCheck;
1484
1485 if (read16(iInputFile, endianCheck) == false)
1486 {
1487 return false;
1488 }
1489
1490 // This frame's text strings are Unicode and the frame
1491 // does include a BOM value. (UTF-16)
1492 iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16;
1493 uint32 endianType;
1494 if (endianCheck == UNICODE_LITTLE_ENDIAN_INDICATOR_FULL)
1495 {
1496 endianType = UNICODE_LITTLE_ENDIAN;
1497 }
1498 else if (endianCheck == UNICODE_BIG_ENDIAN_INDICATOR_FULL)
1499 {
1500 endianType = UNICODE_BIG_ENDIAN;
1501 }
1502 else
1503 {
1504 return false;
1505 }
1506
1507 // value of 2 is for BOM Character
1508 HandleID3V2FrameDataUnicode16(frameType, pos + 2, currFrameLength - 3, endianType);
1509 }
1510 else if (unicodeCheck == PV_ID3_CHARSET_UTF16BE)
1511 {
1512 // This frame's text strings are Unicode but the frame
1513 // does not contain a BOM(byte order mark) (UTF-16BE)
1514 iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16BE;
1515 // Default ID3V2 endian type to Big Endian
1516 uint32 endianType = UNICODE_BIG_ENDIAN;
1517 // Big Endian is assumed since the frame did not specify the endian type.
1518 HandleID3V2FrameDataUnicode16(frameType, pos, currFrameLength - 1, endianType);
1519 }
1520 else if (unicodeCheck == PV_ID3_CHARSET_UTF8)
1521 {
1522 // This frame's text strings are Unicode (UTF-8)
1523 iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF8;
1524 HandleID3V2FrameDataUTF8(frameType, pos, currFrameLength - 1);
1525 }
1526 return true;
1527 }
1528
1529 ////////////////////////////////////////////////////////////////////////////
ReadFrameHeaderID3V2(PVID3Version aVersion)1530 void PVID3ParCom::ReadFrameHeaderID3V2(PVID3Version aVersion)
1531 {
1532 if (aVersion == PV_ID3_V2_2)
1533 {
1534 ReadFrameHeaderID3V2_2();
1535 }
1536 else
1537 {
1538 // Read frame ID
1539 if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_ID, iID3TagInfo.iID3V2FrameID) == false)
1540 {
1541 return;
1542 }
1543 iID3TagInfo.iID3V2FrameID[ID3V2_FRAME_NUM_BYTES_ID] = 0;
1544 // Read frame size
1545 if (read32(iInputFile, iID3TagInfo.iID3V2FrameSize) == false)
1546 {
1547 return;
1548 }
1549 // Read frame flag
1550 if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_FLAG, iID3TagInfo.iID3V2FrameFlag) == false)
1551 {
1552 return;
1553 }
1554
1555 if (PV_ID3_V2_4 == aVersion)
1556 {
1557 if (iID3TagInfo.iID3V2FrameSize > MAX_SYNCSAFE_LEN)
1558 {
1559 // Verify whether frame length is SyncSafe or Non-SyncSafe
1560 iID3TagInfo.iID3V2FrameSize = ValidateFrameLengthV2_4(iID3TagInfo.iID3V2FrameSize);
1561 }
1562 }
1563 }
1564 return;
1565 }
1566
1567 ////////////////////////////////////////////////////////////////////////////
ReadFrameHeaderID3V2_2()1568 void PVID3ParCom::ReadFrameHeaderID3V2_2()
1569 {
1570 if (readByteData(iInputFile, ID3V2_2_FRAME_NUM_BYTES_ID, iID3TagInfo.iID3V2FrameID) == false)
1571 {
1572 return;
1573 }
1574 iID3TagInfo.iID3V2FrameID[ID3V2_2_FRAME_NUM_BYTES_ID] = 0;
1575 if (read24(iInputFile, iID3TagInfo.iID3V2FrameSize) == false)
1576 {
1577 return;
1578 }
1579
1580 return;
1581 }
1582
1583 //////////////////////////////////////////////////////////////////////////////
HandleID3V2FrameDataASCII(PVID3FrameType aFrameType,uint32 aPos,uint32 aSize)1584 void PVID3ParCom::HandleID3V2FrameDataASCII(PVID3FrameType aFrameType,
1585 uint32 aPos,
1586 uint32 aSize)
1587 {
1588 OSCL_StackString<128> keyStr;
1589 PvmiKvpSharedPtr kvpPtr;
1590 PVMFStatus status = PVMFSuccess;
1591 if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1)
1592 {
1593 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - iInputFile->Seek failed"));
1594 OSCL_LEAVE(OsclErrGeneral);
1595 }
1596
1597 switch (aFrameType)
1598 {
1599 case PV_ID3_FRAME_TRACK_LENGTH:
1600 status = ReadTrackLengthFrame(aSize, PV_ID3_CHARSET_ISO88591);
1601 if (status != PVMFSuccess)
1602 {
1603 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - ReadTrackLengthFrame failed. status=%d", status));
1604 OSCL_LEAVE(OsclErrGeneral);
1605 }
1606 break;
1607 case PV_ID3_FRAME_TITLE:
1608 case PV_ID3_FRAME_ARTIST:
1609 case PV_ID3_FRAME_ALBUM:
1610 case PV_ID3_FRAME_YEAR:
1611 case PV_ID3_FRAME_TRACK_NUMBER:
1612 case PV_ID3_FRAME_GENRE:
1613 case PV_ID3_FRAME_COPYRIGHT:
1614 case PV_ID3_FRAME_DATE:
1615 case PV_ID3_FRAME_RECORDING_TIME:
1616 //new frames support
1617 case PV_ID3_FRAME_AUTHOR:
1618 case PV_ID3_FRAME_COMPOSER:
1619 case PV_ID3_FRAME_DESCRIPTION:
1620 case PV_ID3_FRAME_VERSION:
1621 case PV_ID3_FRAME_PART_OF_SET:
1622
1623 status = ReadStringValueFrame(aFrameType, PV_ID3_CHARSET_ISO88591, aSize);
1624 if (status != PVMFSuccess)
1625 {
1626 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - ReadStringValueFrame failed. status=%d", status));
1627 OSCL_LEAVE(OsclErrGeneral);
1628 }
1629 if (aFrameType == PV_ID3_FRAME_TITLE)
1630 iTitleFoundFlag = true;
1631 if (aFrameType == PV_ID3_FRAME_ARTIST)
1632 iArtistFoundFlag = true;
1633 if (aFrameType == PV_ID3_FRAME_ALBUM)
1634 iAlbumFoundFlag = true;
1635 if (aFrameType == PV_ID3_FRAME_YEAR)
1636 iYearFoundFlag = true;
1637 if (aFrameType == PV_ID3_FRAME_TRACK_NUMBER)
1638 iTrackNumberFoundFlag = true;
1639 if (aFrameType == PV_ID3_FRAME_GENRE)
1640 iGenereFoundFlag = true;
1641
1642 break;
1643
1644 default:
1645 break;
1646 }
1647 }
1648
HandleID3V2FrameUnsupported(PVID3FrameType aFrameType,uint32 aPos,uint32 aSize)1649 void PVID3ParCom::HandleID3V2FrameUnsupported(PVID3FrameType aFrameType,
1650 uint32 aPos,
1651 uint32 aSize)
1652 {
1653 // In Android, don't try to read unsupported metadata, because a) we don't
1654 // know what to do with it anyway, and b) we end up here for corrupted files
1655 // too, in which case the size is likely bogus and will result in running
1656 // out of RAM.
1657 #ifndef ANDROID
1658 OSCL_StackString<128> keyStr;
1659 PvmiKvpSharedPtr kvpPtr;
1660 PVMFStatus status = PVMFSuccess;
1661 if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1)
1662 {
1663 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - iInputFile->Seek failed"));
1664 OSCL_LEAVE(OsclErrGeneral);
1665 }
1666
1667 status = ReadFrame(aFrameType, aSize);
1668 if (status != PVMFSuccess)
1669 {
1670 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - ReadStringValueFrame failed. status=%d", status));
1671 OSCL_LEAVE(OsclErrGeneral);
1672 }
1673 #endif
1674 }
1675
1676 ////////////////////////////////////////////////////////////////////////////
HandleID3V2FrameDataUnicode16(PVID3FrameType aFrameType,uint32 aPos,uint32 aSize,uint32 aEndianType)1677 void PVID3ParCom::HandleID3V2FrameDataUnicode16(PVID3FrameType aFrameType,
1678 uint32 aPos,
1679 uint32 aSize,
1680 uint32 aEndianType)
1681 {
1682 // seek to the beginning of the current frame data
1683 if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1)
1684 {
1685 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUnicode16: Error - iInputFile->Seek failed"));
1686 OSCL_LEAVE(OsclErrGeneral);
1687 return;
1688 }
1689
1690 PVMFStatus status = PVMFSuccess;
1691 PVID3CharacterSet charSet;
1692 if (aEndianType == UNICODE_BIG_ENDIAN)
1693 charSet = PV_ID3_CHARSET_UTF16BE;
1694 else
1695 charSet = PV_ID3_CHARSET_UTF16;
1696
1697 switch (aFrameType)
1698 {
1699
1700 case PV_ID3_FRAME_TRACK_LENGTH:
1701 //is a numeric string and does not depend on text encoding.
1702 status = ReadTrackLengthFrame(aSize, charSet);
1703 if (status != PVMFSuccess)
1704 {
1705 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUnicode16: Error - ReadTrackLengthFrame failed. status=%d", status));
1706 OSCL_LEAVE(OsclErrGeneral);
1707 return;
1708 }
1709 break;
1710 case PV_ID3_FRAME_TITLE:
1711 case PV_ID3_FRAME_ARTIST:
1712 case PV_ID3_FRAME_ALBUM:
1713 case PV_ID3_FRAME_YEAR:
1714 case PV_ID3_FRAME_TRACK_NUMBER:
1715 case PV_ID3_FRAME_GENRE:
1716 case PV_ID3_FRAME_COPYRIGHT:
1717 case PV_ID3_FRAME_DATE:
1718 case PV_ID3_FRAME_RECORDING_TIME:
1719 //new frames support
1720 case PV_ID3_FRAME_AUTHOR:
1721 case PV_ID3_FRAME_COMPOSER:
1722 case PV_ID3_FRAME_DESCRIPTION:
1723 case PV_ID3_FRAME_VERSION:
1724 case PV_ID3_FRAME_PART_OF_SET:
1725
1726 status = ReadStringValueFrame(aFrameType, charSet, aSize);
1727 if (status != PVMFSuccess)
1728 {
1729 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUnicode16: Error - ReadStringValueFrame failed. status=%d", status));
1730 OSCL_LEAVE(OsclErrGeneral);
1731 return;
1732 }
1733 if (aFrameType == PV_ID3_FRAME_TITLE)
1734 iTitleFoundFlag = true;
1735 if (aFrameType == PV_ID3_FRAME_ARTIST)
1736 iArtistFoundFlag = true;
1737 if (aFrameType == PV_ID3_FRAME_ALBUM)
1738 iAlbumFoundFlag = true;
1739 if (aFrameType == PV_ID3_FRAME_YEAR)
1740 iYearFoundFlag = true;
1741 if (aFrameType == PV_ID3_FRAME_TRACK_NUMBER)
1742 iTrackNumberFoundFlag = true;
1743 if (aFrameType == PV_ID3_FRAME_GENRE)
1744 iGenereFoundFlag = true;
1745
1746 break;
1747
1748 default:
1749 break;
1750 }
1751 }
1752
1753 ////////////////////////////////////////////////////////////////////////////
HandleID3V2FrameDataUTF8(PVID3FrameType aFrameType,uint32 aPos,uint32 aSize)1754 void PVID3ParCom::HandleID3V2FrameDataUTF8(PVID3FrameType aFrameType,
1755 uint32 aPos,
1756 uint32 aSize)
1757 {
1758 if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1)
1759 {
1760 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUTF8: Error - iInputFile->Seek failed"));
1761 OSCL_LEAVE(OsclErrGeneral);
1762 }
1763
1764 PVMFStatus status = PVMFSuccess;
1765 switch (aFrameType)
1766 {
1767
1768 case PV_ID3_FRAME_TRACK_LENGTH:
1769 status = ReadTrackLengthFrame(aSize, PV_ID3_CHARSET_UTF8);
1770 if (status != PVMFSuccess)
1771 {
1772 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUTF8: Error - ReadTrackLengthFrame failed. status=%d", status));
1773 OSCL_LEAVE(OsclErrGeneral);
1774 }
1775 break;
1776
1777 case PV_ID3_FRAME_TITLE:
1778 case PV_ID3_FRAME_ARTIST:
1779 case PV_ID3_FRAME_ALBUM:
1780 case PV_ID3_FRAME_YEAR:
1781 case PV_ID3_FRAME_TRACK_NUMBER:
1782 case PV_ID3_FRAME_GENRE:
1783 case PV_ID3_FRAME_COPYRIGHT:
1784 case PV_ID3_FRAME_DATE:
1785 case PV_ID3_FRAME_RECORDING_TIME:
1786 //new frames support
1787 case PV_ID3_FRAME_AUTHOR:
1788 case PV_ID3_FRAME_COMPOSER:
1789 case PV_ID3_FRAME_DESCRIPTION:
1790 case PV_ID3_FRAME_VERSION:
1791 case PV_ID3_FRAME_PART_OF_SET:
1792
1793 status = ReadStringValueFrame(aFrameType, PV_ID3_CHARSET_UTF8, aSize);
1794 if (status != PVMFSuccess)
1795 {
1796 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUTF8: Error - ReadStringValueFrame failed. status=%d", status));
1797 OSCL_LEAVE(OsclErrGeneral);
1798 }
1799 if (aFrameType == PV_ID3_FRAME_TITLE)
1800 iTitleFoundFlag = true;
1801 if (aFrameType == PV_ID3_FRAME_ARTIST)
1802 iArtistFoundFlag = true;
1803 if (aFrameType == PV_ID3_FRAME_ALBUM)
1804 iAlbumFoundFlag = true;
1805 if (aFrameType == PV_ID3_FRAME_YEAR)
1806 iYearFoundFlag = true;
1807 if (aFrameType == PV_ID3_FRAME_TRACK_NUMBER)
1808 iTrackNumberFoundFlag = true;
1809 if (aFrameType == PV_ID3_FRAME_GENRE)
1810 iGenereFoundFlag = true;
1811
1812 break;
1813
1814 default:
1815 break;
1816 }
1817 }
1818
1819 //----------------------------------------------------------------------------
1820 // FUNCTION NAME: PVID3ParCom::FrameSupportedID3V2(PVID3Version)
1821 //----------------------------------------------------------------------------
1822 // INPUT AND OUTPUT DEFINITIONS
1823 //
1824 // Inputs: None
1825 //
1826 // Outputs: None
1827 //
1828 // Returns:
1829 // ID3V2FrameTypeReturnValue - The value that describes the current frame.
1830 // of type enum TID3V2FrameType
1831 //
1832 // Global Variables Used:
1833 // TID3V2FrameType - The enum table containing the supported frame types
1834 //
1835 //----------------------------------------------------------------------------
1836 // FUNCTION DESCRIPTION
1837 //
1838 // This function detects the ID3V2FrameType and returns the enum value that
1839 // corresponds to the current frame.
1840 //
1841 //------------------------------------------------------------------------------
1842
FrameSupportedID3V2(PVID3Version aVersion,uint8 * aframeid)1843 PVID3ParCom::PVID3FrameType PVID3ParCom::FrameSupportedID3V2(PVID3Version aVersion, uint8* aframeid)
1844 {
1845 PVID3FrameType ID3V2FrameTypeReturnValue;
1846 uint8* pFrameID = (aframeid) ? aframeid : iID3TagInfo.iID3V2FrameID;
1847
1848 if (0xff == pFrameID[0])
1849 {
1850 //possibly start of mp3 frame. Stop further parsing.
1851 return PV_ID3_FRAME_EEND;
1852 }
1853
1854 if (aVersion == PV_ID3_V2_2)
1855 {
1856 ID3V2FrameTypeReturnValue = FrameSupportedID3V2_2();
1857 }
1858 else //for v2.3 & v2.4
1859 {
1860 uint8 endTestBuf[ID3V2_FRAME_NUM_BYTES_ID] = {0};
1861
1862 if (oscl_memcmp(pFrameID, ID3_FRAME_ID_TITLE, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1863 {
1864 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_TITLE;
1865 iTitleFoundFlag = true;
1866 }
1867 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_ARTIST, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1868 {
1869 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_ARTIST;
1870 iArtistFoundFlag = true;
1871 }
1872 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_PART_OF_SET, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1873 {
1874 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_PART_OF_SET;
1875 }
1876 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_ALBUM, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1877 {
1878 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_ALBUM;
1879 iAlbumFoundFlag = true;
1880 }
1881 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_COPYRIGHT, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1882 {
1883 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_COPYRIGHT;
1884 }
1885 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_GENRE, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1886 {
1887 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_GENRE;
1888 iGenereFoundFlag = true;
1889 }
1890 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_TRACK_NUMBER, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1891 {
1892 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_NUMBER;
1893 iTrackNumberFoundFlag = true;
1894 }
1895 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_TRACK_LENGTH, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1896 {
1897 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_LENGTH;
1898 }
1899 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_COMMENT, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1900 {
1901 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_COMMENT;
1902 iCommentFoundFlag = true;
1903 }
1904 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_YEAR, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1905 {
1906 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_YEAR;
1907 iYearFoundFlag = true;
1908 }
1909 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_RECORDING_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1910 {
1911 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_RECORDING_TIME;
1912 iYearFoundFlag = true;
1913 }
1914 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_DATE, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1915 {
1916 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_DATE;
1917 }
1918
1919 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_ALBUMART, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1920 {
1921 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_APIC;
1922 }
1923 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_LYRICIST, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1924 {
1925 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_LYRICS;
1926 }
1927
1928 // For the seek frame.
1929 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_SEEK, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1930 {
1931 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_SEEK;
1932 }
1933 //new frames support
1934 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_AUTHOR, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1935 {
1936 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_AUTHOR;
1937 }
1938 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_COMPOSER, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1939 {
1940 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_COMPOSER;
1941 }
1942 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_DESCRIPTION, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1943 {
1944 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_DESCRIPTION;
1945 }
1946 else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_VERSION, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1947 {
1948 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_VERSION;
1949 }
1950 else if (oscl_memcmp(pFrameID, endTestBuf, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1951 {
1952 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_EEND;
1953 }
1954 else if (oscl_memcmp(pFrameID, endTestBuf, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1955 {
1956 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_EEND;
1957 }
1958 else
1959 {
1960 // Find whether frame is invalid or unsupported
1961 ID3V2FrameTypeReturnValue = FrameValidatedID3V2_4(pFrameID);
1962 }
1963 }
1964 return ID3V2FrameTypeReturnValue;
1965 }
1966
1967 //----------------------------------------------------------------------------
1968 // FUNCTION NAME: PVID3ParCom::FrameSupportedID3V2_2(void)
1969 //----------------------------------------------------------------------------
1970 // INPUT AND OUTPUT DEFINITIONS
1971 //
1972 // Inputs: None
1973 //
1974 // Outputs: None
1975 //
1976 // Returns:
1977 // ID3V2_2FrameTypeReturnValue - The value that describes the current frame.
1978 // of type enum TID3V2FrameType
1979 //
1980 // Global Variables Used:
1981 // TID3V2_2FrameType - The enum table containing the supported frame types
1982 //
1983 //----------------------------------------------------------------------------
1984 // FUNCTION DESCRIPTION
1985 //
1986 // This function detects the ID3V2_2FrameType and returns the enum value that
1987 // corresponds to the current frame.
1988 //
1989 //------------------------------------------------------------------------------
1990
FrameSupportedID3V2_2(void)1991 PVID3ParCom::PVID3FrameType PVID3ParCom::FrameSupportedID3V2_2(void)
1992 {
1993 uint8 endTestBuf[ID3V2_2_FRAME_NUM_BYTES_ID] = {0};
1994 PVID3FrameType ID3V2_2FrameTypeReturnValue;
1995
1996 if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_TITLE, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
1997 {
1998 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_TITLE;
1999 iTitleFoundFlag = true;
2000 }
2001 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_ARTIST, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2002 {
2003 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_ARTIST;
2004 iArtistFoundFlag = true;
2005 }
2006 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_PART_OF_SET, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2007 {
2008 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_PART_OF_SET;
2009 }
2010 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_ALBUM, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2011 {
2012 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_ALBUM;
2013 iAlbumFoundFlag = true;
2014 }
2015 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_COPYRIGHT, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2016 {
2017 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_COPYRIGHT;
2018 }
2019 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_GENRE, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2020 {
2021 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_GENRE;
2022 iGenereFoundFlag = true;
2023 }
2024 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_TRACK_NUMBER, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2025 {
2026 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_NUMBER;
2027 iTrackNumberFoundFlag = true;
2028 }
2029 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_TRACK_LENGTH, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2030 {
2031 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_LENGTH;
2032 }
2033 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_COMMENT, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2034 {
2035 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_COMMENT;
2036 iCommentFoundFlag = true;
2037 }
2038 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_YEAR, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2039 {
2040 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_YEAR;
2041 iYearFoundFlag = true;
2042 }
2043 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_DATE, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2044 {
2045 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_DATE;
2046 }
2047 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_ALBUMART, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2048 {
2049 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_PIC;
2050 }
2051 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_LYRICIST, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2052 {
2053 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_LYRICS;
2054 }
2055 //new frames support
2056 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_AUTHOR, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2057 {
2058 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_AUTHOR;
2059 }
2060 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_COMPOSER, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2061 {
2062 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_COMPOSER;
2063 }
2064 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_DESCRIPTION, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2065 {
2066 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_DESCRIPTION;
2067 }
2068 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_VERSION, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2069 {
2070 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_VERSION;
2071 }
2072
2073 else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, endTestBuf, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2074 {
2075 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_EEND;
2076 }
2077
2078 else
2079 {
2080 ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_UNRECOGNIZED;
2081 }
2082
2083 return ID3V2_2FrameTypeReturnValue;
2084 }
2085
2086 //----------------------------------------------------------------------------
2087 // FUNCTION NAME: PVID3ParCom::EightBitToWideCharBufferTransfer(
2088 // const TPtr8& aPtrFrameData8,
2089 // uint32 aSize,
2090 // uint32 aEndianType,
2091 // TPtr16& aPtrFrameData16)
2092 //----------------------------------------------------------------------------
2093 // INPUT AND OUTPUT DEFINITIONS
2094 //
2095 // Inputs:
2096 // aPtrFrameData8 - pointer to intput string format of either big
2097 // or little endian.
2098 // aSize - number of character elements in aPtrFrameData8
2099 // aEndianType - This describes if the encoded Unicode text in the
2100 // aPtrFrameData8 buffer is in big or little endian.
2101 // Outputs:
2102 // aPtrFrameDataWCBase - pointer to the output string in unicode format.
2103 //
2104 // Returns: size of data in aPtrFrameDataWCBase
2105 //
2106 // Global Variables Used: None
2107 //
2108 //----------------------------------------------------------------------------
2109 // FUNCTION DESCRIPTION
2110 //
2111 // This function moves unicode data sotred in uint8 buffer to wchar buffer.
2112 // The endian is taken care of by this function as well.
2113 //
2114 //------------------------------------------------------------------------------
EightBitToWideCharBufferTransfer(const uint8 * aPtrFrameData8,uint32 aSize,uint32 aEndianType,oscl_wchar * aPtrFrameDataWCBase)2115 uint32 PVID3ParCom::EightBitToWideCharBufferTransfer(const uint8 * aPtrFrameData8,
2116 uint32 aSize,
2117 uint32 aEndianType,
2118 oscl_wchar * aPtrFrameDataWCBase)
2119 {
2120 if (aPtrFrameData8 == NULL || aPtrFrameDataWCBase == NULL)
2121 {
2122 return 0;
2123 }
2124
2125 oscl_wchar * aPtrFrameDataWC = aPtrFrameDataWCBase;
2126 uint16 tempFrameData16;
2127 oscl_wchar tempFrameDataWC = 0;
2128 uint32 index = 0;
2129 uint32 z = 0, x = 0;
2130 uint8 tempByteOne, tempByteTwo;
2131 if (aEndianType != UNICODE_BIG_ENDIAN)
2132 // Indication check of big-endian vs. little endian
2133 {
2134 z = 0;
2135 for (x = 0; x < (aSize >> 1); x++)
2136 {
2137 z = x << 1;
2138 tempByteOne = aPtrFrameData8[z];
2139 tempByteTwo = aPtrFrameData8[z + 1];
2140 if ((tempByteOne == 0) && (tempByteTwo == 0))
2141 {
2142 x++;
2143 // End of string here and skip to start of next string.
2144 aPtrFrameDataWC[index++] = ((oscl_wchar)'\0');
2145 }
2146 else
2147 {
2148 tempFrameData16 = (uint16)((((uint16)(tempByteTwo << 8)) | tempByteOne));
2149 tempFrameDataWC = tempFrameData16;
2150 aPtrFrameDataWC[index++] = tempFrameDataWC;
2151 }
2152 }
2153 }
2154 else
2155 {
2156 z = 0;
2157 for (x = 0; x < (aSize >> 1); x++)
2158 {
2159 z = x << 1;
2160 tempByteOne = aPtrFrameData8[z];
2161 tempByteTwo = aPtrFrameData8[z + 1];
2162 if ((tempByteTwo == 0) && (tempByteOne == 0))
2163 {
2164 x++;
2165 // End of string here and skip to start of next string.
2166 aPtrFrameDataWC[index++] = ((oscl_wchar)'\0');
2167 }
2168 else
2169 {
2170 tempFrameData16 = (uint16)((((uint16)(tempByteOne << 8)) | tempByteTwo));
2171 int32 l = sizeof(oscl_wchar);
2172 if (l == 4)
2173 tempFrameDataWC = (tempFrameData16 << 16) && 0xff00;
2174 else if (l == 2)
2175 tempFrameDataWC = tempFrameData16;
2176 else
2177 return 0;
2178 aPtrFrameDataWC[index++] = tempFrameDataWC;
2179 }
2180 }
2181 }
2182 return (index);
2183 }
2184
ConvertToSyncSafeInt(uint32 src)2185 uint32 PVID3ParCom::ConvertToSyncSafeInt(uint32 src)
2186 {
2187 uint32 dest = (src & 0x0FE00000) << 3;
2188 dest |= (src & 0x001FC000) << 2;
2189 dest |= (src & 0x00003f80) << 1;
2190 dest |= (src & 0x0000007f);
2191
2192 return dest;
2193 }
2194
2195 ////////////////////////////////////////////////////////////////////////////
SafeSynchIntToInt32(uint32 aSafeSynchInteger)2196 uint32 PVID3ParCom::SafeSynchIntToInt32(uint32 aSafeSynchInteger)
2197 {
2198 uint8 * pBuf = (uint8 *) & (aSafeSynchInteger);
2199 uint8 tmpByte = 0;
2200 int32 i = 0;
2201 uint32 integer = 0;
2202
2203 // This loop will calculate the correct size from the bytes designated for size
2204 // It is stored as a SynchSafe Integer. This means the 8th bit is reserved in
2205 // each byte and not used for integer precision.. The number is effectively 28
2206 // bits in length/precision.
2207 // Assumes: sizeof(uint32) = 4 Bytes
2208 for (i = 0; i < 4; i++)
2209 {
2210 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
2211 tmpByte = (uint8)(pBuf[i] & MASK127);
2212 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
2213 tmpByte = pBuf[4-i-1] & MASK127;
2214 #else
2215 #error "Must Specify ENDIANNESS"
2216 #endif
2217 // now shift the data to it's correct place
2218 integer += tmpByte << VALID_BITS_IN_SYNC_SAFE_BYTE * i;
2219 }
2220
2221 return integer;
2222 }
2223
2224 ////////////////////////////////////////////////////////////////////////////
readByteData(PVFile * aInputFile,uint32 length,uint8 * aData)2225 bool PVID3ParCom::readByteData(PVFile* aInputFile, uint32 length, uint8 *aData)
2226 {
2227 if (length > 0)
2228 {
2229 uint32 bytesRead;
2230 bytesRead = aInputFile->Read(aData, 1, length);
2231
2232 if (bytesRead < (uint32)length) // read byte data failed
2233 {
2234 return false;
2235 }
2236 }
2237 return true;
2238 }
2239
2240 ////////////////////////////////////////////////////////////////////////////
read32(PVFile * aInputFile,uint32 & aData)2241 bool PVID3ParCom::read32(PVFile* aInputFile, uint32 &aData)
2242 {
2243 const int32 N = 4;
2244 uint8 bytes[N];
2245 aData = 0;
2246
2247 int32 retVal = (int32)(aInputFile->Read((void*)bytes, 1, N));
2248
2249 if (retVal < N)
2250 return false;
2251
2252 for (int32 i = 0; i < N; i++)
2253 aData = (aData << 8) | bytes[i];
2254
2255 return true;
2256 }
2257 ////////////////////////////////////////////////////////////////////////////
read16(PVFile * aInputFile,uint16 & aData)2258 bool PVID3ParCom::read16(PVFile* aInputFile, uint16 &aData)
2259 {
2260 const int32 N = 2;
2261 uint8 bytes[N];
2262 aData = 0;
2263
2264 int32 retVal = (int32)(aInputFile->Read((void*)bytes, 1, N));
2265
2266 if (retVal < N)
2267 return false;
2268
2269 for (int32 i = 0; i < N; i++)
2270 aData = (uint16)((aData << 8) | bytes[i]);
2271
2272 return true;
2273 }
2274
2275 ////////////////////////////////////////////////////////////////////////////
read24(PVFile * aInputFile,uint32 & aData)2276 bool PVID3ParCom::read24(PVFile* aInputFile, uint32 &aData)
2277 {
2278 const int32 N = 3;
2279 uint8 bytes[N];
2280 aData = 0;
2281
2282 int32 retVal = (int32)(aInputFile->Read((void*)bytes, 1, N));
2283
2284 if (retVal < N)
2285 return false;
2286
2287 for (int32 i = 0; i < N; i++)
2288 aData = (aData << 8) | bytes[i];
2289
2290 return true;
2291 }
2292
2293 ////////////////////////////////////////////////////////////////////////////
read8(PVFile * aInputFile,uint8 & aData)2294 bool PVID3ParCom::read8(PVFile* aInputFile, uint8 &aData)
2295 {
2296 aData = 0;
2297
2298 int32 retVal = (int32)(aInputFile->Read((void*) & aData, 1, 1));
2299
2300 if (retVal < 1)
2301 return false;
2302
2303 return true;
2304 }
2305
2306 ////////////////////////////////////////////////////////////////////////////
2307
AllocateKvp(OSCL_String & aKey,PvmiKvpValueType aValueType,uint32 aValueSize,bool & truncate)2308 PvmiKvpSharedPtr PVID3ParCom::AllocateKvp(OSCL_String& aKey, PvmiKvpValueType aValueType, uint32 aValueSize, bool &truncate)
2309 {
2310 uint8* myPtr = NULL;
2311 OsclRefCounter* refCounter;
2312
2313 uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
2314 uint aligned_cleanup_size = oscl_mem_aligned_size(sizeof(PVID3ParComKvpCleanupDA));
2315 uint aligned_kvp_size = oscl_mem_aligned_size(sizeof(PvmiKvp));
2316 uint32 key_size = oscl_mem_aligned_size(aKey.get_size() + 1);
2317 uint32 total_size = aligned_refcnt_size + aligned_cleanup_size +
2318 aligned_kvp_size + key_size + aValueSize;
2319
2320 int32 error = 0;
2321 myPtr = (uint8*) AllocateValueArray(error, PVMI_KVPVALTYPE_UINT8PTR, total_size, &iAlloc);
2322 if ((error != OsclErrNone) || (!myPtr) || (total_size < aValueSize))
2323 {
2324 if (myPtr)
2325 {
2326 iAlloc.deallocate(myPtr);
2327 }
2328
2329 char str_data_len[MAX_RANGE_INT_SIZE + 1] = {0};
2330 oscl_snprintf(str_data_len, MAX_RANGE_INT_SIZE + 1, "%d", aValueSize);
2331 aKey += SEMI_COLON;
2332 aKey += KVP_VALTYPE_REQSIZE;
2333 aKey += _STRLIT_CHAR((char *)str_data_len);
2334 uint32 new_key_size = oscl_mem_aligned_size(aKey.get_size() + 1);
2335 error = OsclErrNone;
2336 total_size = aligned_refcnt_size + aligned_cleanup_size + aligned_kvp_size + new_key_size;
2337 myPtr = (uint8*) AllocateValueArray(error, PVMI_KVPVALTYPE_UINT8PTR, total_size, &iAlloc);
2338 truncate = true;
2339 if (OsclErrNone != error)
2340 {
2341 OSCL_LEAVE(OsclErrNoMemory);
2342 }
2343 }
2344 oscl_memset(myPtr, 0, total_size);
2345
2346 PVID3ParComKvpCleanupDA* kvpCleanup = OSCL_PLACEMENT_NEW(myPtr + aligned_refcnt_size, PVID3ParComKvpCleanupDA(&iAlloc));
2347 refCounter = OSCL_PLACEMENT_NEW(myPtr, OsclRefCounterDA(myPtr, kvpCleanup));
2348 myPtr += aligned_refcnt_size + aligned_cleanup_size;
2349
2350 PvmiKvp* kvp = OSCL_STATIC_CAST(PvmiKvp *, myPtr) ;
2351 myPtr += aligned_kvp_size;
2352
2353 kvp->key = OSCL_STATIC_CAST(char* , myPtr);
2354 myPtr += key_size;
2355 oscl_strncpy(kvp->key, aKey.get_cstr(), key_size);
2356 if (!truncate)
2357 {
2358 switch (aValueType)
2359 {
2360 case PVMI_KVPVALTYPE_WCHARPTR:
2361 kvp->value.pWChar_value = OSCL_STATIC_CAST(oscl_wchar*, myPtr);
2362 break;
2363 case PVMI_KVPVALTYPE_CHARPTR:
2364 kvp->value.pChar_value = OSCL_STATIC_CAST(char* , myPtr);
2365 break;
2366 case PVMI_KVPVALTYPE_UINT8PTR:
2367 kvp->value.pUint8_value = OSCL_STATIC_CAST(uint8*, myPtr);
2368 break;
2369 case PVMI_KVPVALTYPE_INT32PTR:
2370 kvp->value.pInt32_value = OSCL_STATIC_CAST(int32*, myPtr);
2371 break;
2372 case PVMI_KVPVALTYPE_UINT32PTR:
2373 kvp->value.pUint32_value = OSCL_STATIC_CAST(uint32*, myPtr);
2374 break;
2375 case PVMI_KVPVALTYPE_INT64PTR:
2376 kvp->value.pInt64_value = OSCL_STATIC_CAST(int64* , myPtr);
2377 break;
2378 case PVMI_KVPVALTYPE_UINT64PTR:
2379 kvp->value.pUint64_value = OSCL_STATIC_CAST(uint64* , myPtr);
2380 break;
2381 case PVMI_KVPVALTYPE_FLOATPTR:
2382 kvp->value.pFloat_value = OSCL_STATIC_CAST(float* , myPtr);
2383 break;
2384 case PVMI_KVPVALTYPE_DOUBLEPTR:
2385 kvp->value.pDouble_value = OSCL_STATIC_CAST(double*, myPtr);
2386 break;
2387 case PVMI_KVPVALTYPE_KSV:
2388 kvp->value.key_specific_value = OSCL_STATIC_CAST(OsclAny*, myPtr);
2389 default:
2390 break;
2391 }
2392 kvp->length = aValueSize;
2393 kvp->capacity = aValueSize;
2394 }
2395 else
2396 {
2397 kvp->length = 0;
2398 kvp->capacity = 0;
2399
2400 }
2401 PvmiKvpSharedPtr sharedPtr(kvp, refCounter);
2402 return sharedPtr;
2403 }
2404
2405 ////////////////////////////////////////////////////////////////////////////
ConstructKvpKey(OSCL_String & aKey,PVID3FrameType aType,PVID3CharacterSet aCharSet)2406 PVMFStatus PVID3ParCom::ConstructKvpKey(OSCL_String& aKey, PVID3FrameType aType, PVID3CharacterSet aCharSet)
2407 {
2408 aKey = _STRLIT_CHAR("");
2409
2410 switch (aType)
2411 {
2412 case PV_ID3_FRAME_TITLE:
2413 aKey += _STRLIT_CHAR(KVP_KEY_TITLE);
2414 break;
2415 case PV_ID3_FRAME_ARTIST:
2416 aKey += _STRLIT_CHAR(KVP_KEY_ARTIST);
2417 break;
2418 case PV_ID3_FRAME_PART_OF_SET:
2419 aKey += _STRLIT_CHAR(KVP_KEY_PART_OF_SET);
2420 break;
2421 case PV_ID3_FRAME_ALBUM:
2422 aKey += _STRLIT_CHAR(KVP_KEY_ALBUM);
2423 break;
2424 case PV_ID3_FRAME_COPYRIGHT:
2425 aKey += _STRLIT_CHAR(KVP_KEY_COPYRIGHT);
2426 break;
2427 case PV_ID3_FRAME_GENRE:
2428 aKey += _STRLIT_CHAR(KVP_KEY_GENRE);
2429 if (aCharSet == PV_ID3_CHARSET_INVALID)
2430 {
2431 // ID3 V1 genre is a uint32 value
2432 aKey += SEMI_COLON;
2433 aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_STRING);
2434 aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING);
2435 aKey += SEMI_COLON;
2436 aKey += _STRLIT_CHAR(KVP_FORMAT_ID3V1);
2437 return PVMFSuccess;
2438 }
2439 break;
2440 case PV_ID3_FRAME_TRACK_NUMBER:
2441 aKey += _STRLIT_CHAR(KVP_KEY_TRACK_NUMBER);
2442 if (aCharSet == PV_ID3_CHARSET_INVALID)
2443 {
2444 // ID3 V1 track number is a uint32 value
2445 aKey += SEMI_COLON;
2446 aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_STRING);
2447 aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING);
2448 return PVMFSuccess;
2449 }
2450 break;
2451 case PV_ID3_FRAME_YEAR:
2452 aKey += _STRLIT_CHAR(KVP_KEY_YEAR);
2453 break;
2454 case PV_ID3_FRAME_DATE:
2455 aKey += _STRLIT_CHAR(KVP_KEY_DATE);
2456 break;
2457 case PV_ID3_FRAME_RECORDING_TIME:
2458 aKey += _STRLIT_CHAR(KVP_KEY_RECORDING_TIME);
2459 break;
2460 //new frames support
2461 case PV_ID3_FRAME_AUTHOR:
2462 aKey += _STRLIT_CHAR(KVP_KEY_AUTHOR);
2463 break;
2464 case PV_ID3_FRAME_COMPOSER:
2465 aKey += _STRLIT_CHAR(KVP_KEY_COMPOSER);
2466 break;
2467 case PV_ID3_FRAME_DESCRIPTION:
2468 aKey += _STRLIT_CHAR(KVP_KEY_DESCRIPTION);
2469 break;
2470 case PV_ID3_FRAME_VERSION:
2471 aKey += _STRLIT_CHAR(KVP_KEY_VERSION);
2472 break;
2473 case PV_ID3_FRAME_COMMENT:
2474 aKey += _STRLIT_CHAR(KVP_KEY_COMMENT);
2475 if ((iVersion != PV_ID3_V1_1) && (iVersion != PV_ID3_V1))
2476 {
2477 aKey += SEMI_COLON;
2478 aKey += KVP_VALTYPE_LYRICS;
2479 }
2480 break;
2481 case PV_ID3_FRAME_TRACK_LENGTH:
2482 aKey += _STRLIT_CHAR(KVP_KEY_ID3DURATION);
2483 aKey += SEMI_COLON;
2484 aKey += _STRLIT_CHAR(KVP_VALTYPE_DURATION);
2485 return PVMFSuccess; // No character set for track length
2486 case PV_ID3_FRAME_PIC:
2487 case PV_ID3_FRAME_APIC:
2488 aKey += _STRLIT_CHAR(KVP_KEY_ALBUMART);
2489 aKey += SEMI_COLON;
2490 return PVMFSuccess;
2491 case PV_ID3_FRAME_LYRICS:
2492 aKey += _STRLIT_CHAR(KVP_KEY_LYRICS);
2493 aKey += SEMI_COLON;
2494 aKey += KVP_VALTYPE_LYRICS;
2495 break;
2496 case PV_ID3_FRAME_UNRECOGNIZED:
2497 case PV_ID3_FRAME_CANDIDATE:
2498 aKey += _STRLIT_CHAR(KVP_ID3V2_VALUE);
2499 aKey += FORWARD_SLASH;
2500 aKey += _STRLIT_CHAR((char *)iID3TagInfo.iID3V2FrameID);
2501 aKey += SEMI_COLON;
2502 aKey += _STRLIT_CHAR(KVP_VALTYPE_UINT8PTR_STRING);
2503 return PVMFSuccess;
2504 break;
2505 default:
2506 return PVMFErrNotSupported;
2507 }
2508
2509
2510 //add language code to lyrics key
2511 if ((aType == PV_ID3_FRAME_LYRICS) || (aType == PV_ID3_FRAME_COMMENT))
2512 {
2513 //not valid for id3 v1
2514 if ((iVersion != PV_ID3_V1_1) && (iVersion != PV_ID3_V1))
2515 {
2516 aKey += SEMI_COLON;
2517 aKey += _STRLIT_CHAR(KVP_PARAM_LANGUAGE_CODE);
2518 aKey += _STRLIT_CHAR((char*)iID3TagInfo.iID3V2LanguageID);
2519 return PVMFSuccess;
2520 }
2521 }
2522 aKey += SEMI_COLON;
2523 switch (aCharSet)
2524 {
2525 case PV_ID3_CHARSET_ISO88591:
2526 aKey += _STRLIT_CHAR(KVP_VALTYPE_ISO88591_CHAR);
2527 break;
2528 case PV_ID3_CHARSET_UTF16:
2529 aKey += _STRLIT_CHAR(KVP_VALTYPE_UTF16_WCHAR);
2530 break;
2531 case PV_ID3_CHARSET_UTF16BE:
2532 aKey += _STRLIT_CHAR(KVP_VALTYPE_UTF16BE_WCHAR);
2533 break;
2534 case PV_ID3_CHARSET_UTF8:
2535 aKey += _STRLIT_CHAR(KVP_VALTYPE_UTF8_CHAR);
2536 break;
2537 default:
2538 return PVMFErrNotSupported;
2539 }
2540
2541 aKey += NULL_CHARACTER;
2542
2543 return PVMFSuccess;
2544 }
2545
2546 ////////////////////////////////////////////////////////////////////////////
ReadStringValueFrame(PVID3FrameType aFrameType,PVID3CharacterSet aCharSet,uint32 aValueSize)2547 PVMFStatus PVID3ParCom::ReadStringValueFrame(PVID3FrameType aFrameType, PVID3CharacterSet aCharSet, uint32 aValueSize)
2548 {
2549 // Construct key string
2550 OSCL_StackString<128> keyStr;
2551 if (ConstructKvpKey(keyStr, aFrameType, aCharSet) != PVMFSuccess)
2552 {
2553 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - ConstructKvpKey failed"));
2554 return PVMFErrNotSupported;
2555 }
2556
2557 // Allocate key-value pair
2558 int32 err = OsclErrNone;
2559 PvmiKvpSharedPtr kvpPtr;
2560 bool truncate = false;
2561 switch (aCharSet)
2562 {
2563 case PV_ID3_CHARSET_ISO88591:
2564 case PV_ID3_CHARSET_UTF8:
2565 OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, aValueSize + 1, truncate););
2566 if (OsclErrNone != err || !kvpPtr)
2567 {
2568 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - AllocateKvp failed. err=%d", err));
2569 return PVMFErrNoMemory;
2570 }
2571
2572 if (truncate)
2573 {
2574 iInputFile->Seek(aValueSize, Oscl_File::SEEKCUR);
2575 kvpPtr->length = 0;
2576 }
2577 else
2578 {
2579 if (readByteData(iInputFile, aValueSize, (uint8*)kvpPtr->value.pChar_value) == false)
2580 {
2581 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - readByteData failed"));
2582 return PVMFFailure;
2583 }
2584
2585 int32 valueLen = aValueSize;
2586 valueLen = oscl_strlen((char*)kvpPtr->value.pChar_value);
2587
2588 kvpPtr->value.pChar_value[valueLen] = NULL_TERM_CHAR;
2589 kvpPtr->length = valueLen + 1;
2590 }
2591 // Add to frame vector
2592 OSCL_TRY(err, iFrames.push_back(kvpPtr););
2593 OSCL_FIRST_CATCH_ANY(err,
2594 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - iFrames.push_back failed. err=%d", err));
2595 return PVMFErrNoMemory;
2596 );
2597 break;
2598
2599 case PV_ID3_CHARSET_UTF16:
2600 case PV_ID3_CHARSET_UTF16BE:
2601 {
2602 // create buffers to store frame data
2603 uint8* ptrFrameData = NULL;
2604 ptrFrameData = (uint8*) AllocateValueArray(err, PVMI_KVPVALTYPE_UINT8PTR, aValueSize + 2, &iAlloc);
2605 if (OsclErrNone != err || !ptrFrameData)
2606 {
2607 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - frameData allocation failed"));
2608 return PVMFErrNoMemory;
2609 }
2610 oscl_memset(ptrFrameData, 0, aValueSize + 2);
2611 uint32 wchar_size = sizeof(oscl_wchar); //for platforms where wchar is 4 bytes.
2612 // Allocate key-value pair
2613 OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_WCHARPTR, (wchar_size / 2) * (aValueSize + 2), truncate););
2614 if (OsclErrNone != err || !kvpPtr)
2615 {
2616 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - AllocateKvp failed. err=%d", err));
2617 return PVMFErrNoMemory;
2618 }
2619
2620 if (truncate)
2621 {
2622 iAlloc.deallocate(ptrFrameData);
2623 iInputFile->Seek(aValueSize, Oscl_File::SEEKCUR);
2624 kvpPtr->length = 0;
2625 }
2626 else
2627 {
2628 if (readByteData(iInputFile, aValueSize, ptrFrameData) == false)
2629 {
2630 iAlloc.deallocate(ptrFrameData);
2631 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - readByteData failed"));
2632 return PVMFFailure;
2633 }
2634 ptrFrameData[aValueSize] = 0;
2635 ptrFrameData[aValueSize+1] = 0;
2636
2637 uint32 endianType = UNICODE_LITTLE_ENDIAN;
2638 if (aCharSet == PV_ID3_CHARSET_UTF16BE)
2639 {
2640 endianType = UNICODE_BIG_ENDIAN;
2641 }
2642
2643 uint32 wcSize = EightBitToWideCharBufferTransfer(ptrFrameData, aValueSize, endianType, kvpPtr->value.pWChar_value);
2644 kvpPtr->value.pWChar_value[wcSize] = NULL_TERM_CHAR;
2645 iAlloc.deallocate(ptrFrameData);
2646 kvpPtr->length = wcSize;
2647 }
2648 OSCL_TRY(err, iFrames.push_back(kvpPtr););
2649 OSCL_FIRST_CATCH_ANY(err,
2650 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - iFrame.push_back failed"));
2651 iAlloc.deallocate((OsclAny*)ptrFrameData);
2652 return PVMFErrNoMemory;
2653 );
2654 }
2655 break;
2656 default:
2657 return PVMFFailure;
2658 }
2659
2660 return PVMFSuccess;
2661 }
2662
2663
2664 ////////////////////////////////////////////////////////////////////////////
ReadFrame(PVID3FrameType aFrameType,uint32 aValueSize)2665 PVMFStatus PVID3ParCom::ReadFrame(PVID3FrameType aFrameType, uint32 aValueSize)
2666 {
2667
2668 // Construct key string
2669 OSCL_StackString<128> keyStr;
2670 if (ConstructKvpKey(keyStr, aFrameType, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
2671 {
2672 LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - ConstructKvpKey failed"));
2673 return PVMFErrNotSupported;
2674 }
2675
2676 // Allocate key-value pair
2677 int32 err = OsclErrNone;
2678 PvmiKvpSharedPtr kvpPtr;
2679 bool truncate = false;
2680 OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, aValueSize + 1 + VERSION_SIZE, truncate););
2681 if (OsclErrNone != err || !kvpPtr)
2682 {
2683 LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - AllocateKvp failed. err=%d", err));
2684 return PVMFErrNoMemory;
2685 }
2686
2687 if (truncate)
2688 {
2689 iInputFile->Seek(aValueSize, Oscl_File::SEEKCUR);
2690 kvpPtr->length = 0;
2691 }
2692 else
2693 {
2694 kvpPtr->value.pUint8_value[0] = (uint8)iVersion;
2695 kvpPtr->value.pUint8_value[1] = 0;
2696
2697 if (readByteData(iInputFile, aValueSize, (uint8*)kvpPtr->value.pUint8_value + VERSION_SIZE) == false)
2698 {
2699 LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - readByteData failed"));
2700 return PVMFFailure;
2701 }
2702 kvpPtr->value.pUint8_value[aValueSize+VERSION_SIZE] = 0;
2703 kvpPtr->length = aValueSize + VERSION_SIZE;
2704 }
2705 // Add to frame vector
2706 OSCL_TRY(err, iFrames.push_back(kvpPtr););
2707 OSCL_FIRST_CATCH_ANY(err,
2708 LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - iFrames.push_back failed. err=%d", err));
2709 return PVMFErrNoMemory;
2710 );
2711
2712
2713 return PVMFSuccess;
2714 }
2715
2716
2717 ////////////////////////////////////////////////////////////////////////////
2718
2719 // Read in a NULL terminated UNICODE string byte by byte and take most significant byte first
2720 PVMFStatus
readNullTerminatedUnicodeString(PVFile * aInputFile,OSCL_wHeapString<OsclMemAllocator> & aData,uint32 & bomSz)2721 PVID3ParCom::readNullTerminatedUnicodeString(PVFile* aInputFile, OSCL_wHeapString<OsclMemAllocator> &aData, uint32 &bomSz)
2722 {
2723 uint8 buff[ID3_MAX_STRING_FRAME_LEN];
2724 uint32 index = 0;
2725 uint16 endianCheck;
2726 if (read16(aInputFile, endianCheck) == false)
2727 {
2728 return PVMFFailure;
2729 }
2730
2731 iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16;
2732 uint32 endianType = 0;
2733
2734 //some id3 tools does not add BOM with null strings.
2735 if (endianCheck != 0)
2736 {
2737 bomSz = UNICODE_BOM_SIZE;
2738 // This frame's text strings are Unicode and the frame
2739 // does include a BOM value. (UTF-16)
2740 if (endianCheck == UNICODE_LITTLE_ENDIAN_INDICATOR_FULL)
2741 {
2742 endianType = UNICODE_LITTLE_ENDIAN;
2743 }
2744 else if (endianCheck == UNICODE_BIG_ENDIAN_INDICATOR_FULL)
2745 {
2746 endianType = UNICODE_BIG_ENDIAN;
2747 }
2748 //read frame data from file
2749 bool more = true;
2750 while (more && (index < ID3_MAX_STRING_FRAME_LEN))
2751 {
2752 if (read8(iInputFile, buff[index]) == false)
2753 return PVMFFailure;
2754
2755 if ((index > 0) && (buff[index] == 0) && (buff[index -1] == 0))
2756 more = false;
2757 index++;
2758 }
2759
2760 //read remaining characters if any.
2761 if (more)
2762 {
2763 uint16 temp = 1;
2764 while (temp != 0)
2765 if (read16(iInputFile, temp) == false)
2766 return PVMFFailure;
2767 }
2768
2769 }
2770 else
2771 {
2772 buff[0] = 0;
2773 buff[1] = 0;
2774 bomSz = 0;
2775 index = 2;
2776 }
2777
2778 int32 err = OsclErrNone;
2779 oscl_wchar *tmpData = NULL;
2780 tmpData = (oscl_wchar*) AllocateValueArray(err, PVMI_KVPVALTYPE_WCHARPTR, index);
2781 if (OsclErrNone != err || !tmpData)
2782 {
2783 LOG_ERR((0, "PVID3ParCom::readNullTerminatedUnicodeString: Error - allocation failed"));
2784 return PVMFErrNoMemory;
2785 }
2786
2787 uint32 wcSize = EightBitToWideCharBufferTransfer(buff, index, endianType, tmpData);
2788 tmpData[wcSize] = 0;
2789 aData = tmpData;
2790 OSCL_ARRAY_DELETE(tmpData);
2791 return PVMFSuccess;
2792 }
2793
2794 bool
readNullTerminatedAsciiString(PVFile * aInputFile,OSCL_HeapString<OsclMemAllocator> & aData)2795 PVID3ParCom::readNullTerminatedAsciiString(PVFile* aInputFile, OSCL_HeapString<OsclMemAllocator> &aData)
2796 {
2797 uint8 buf[256];
2798 int32 index = 0;
2799
2800 if (!read8(aInputFile, buf[index]))
2801 return PVMFFailure;
2802
2803 bool nextChar = (buf[index] == 0) ? false : true;
2804
2805 while (nextChar && (index < 256))
2806 {
2807 index++;
2808
2809 if (!read8(aInputFile, buf[index]))
2810 return PVMFFailure;
2811
2812 nextChar = (buf[index] == 0) ? false : true;
2813 }
2814
2815 OSCL_HeapString<OsclMemAllocator> temp((const char *)buf);
2816 aData = temp;
2817 return true;
2818 }
2819
ReadAlbumArtFrame(PVID3FrameType aFrameType,uint8 unicode,uint32 aFrameSize)2820 PVMFStatus PVID3ParCom::ReadAlbumArtFrame(PVID3FrameType aFrameType, uint8 unicode, uint32 aFrameSize)
2821 {
2822 PvmfApicStruct* aApicStruct = NULL;
2823 uint8 picType;
2824 uint32 dataLen;
2825 OSCL_HeapString<OsclMemAllocator> ImageFormat;
2826 bool pic_as_url = false;
2827 bool truncate = false;
2828 int32 err = OsclErrNone;
2829 PvmiKvpSharedPtr kvpPtr;
2830 OSCL_StackString<128> keyStr;
2831
2832 if (ConstructKvpKey(keyStr, PV_ID3_FRAME_APIC, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
2833 {
2834 LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - ConstructKvpKey failed"));
2835 return PVMFErrNotSupported;
2836 }
2837
2838 switch (unicode)
2839 {
2840 case PV_ID3_CHARSET_ISO88591:
2841 case PV_ID3_CHARSET_UTF8:
2842 {
2843 OSCL_HeapString<OsclMemAllocator> description;
2844
2845 if (GetAlbumArtInfo(aFrameType, aFrameSize, ImageFormat, picType, description, dataLen) != PVMFSuccess)
2846 return PVMFFailure;
2847
2848 if (!oscl_strcmp(ImageFormat.get_cstr(), "-->"))
2849 {
2850 pic_as_url = true;
2851 break;
2852 }
2853
2854 keyStr += KVP_FORMAT_ALBUMART;
2855 keyStr += SEMI_COLON;
2856 keyStr += KVP_VALTYPE_ALBUMART;
2857
2858 //description and image format are stored as wchar.
2859 uint32 rfs = aFrameSize - (ImageFormat.get_size() + description.get_size());
2860 uint32 wchar_size = sizeof(oscl_wchar); //for platforms that store wchar as 4 bytes.
2861 uint32 total_size = sizeof(PvmfApicStruct) + rfs + ((wchar_size) * (ImageFormat.get_size() + description.get_size())) + 2 * sizeof(oscl_wchar) ;
2862
2863 // Allocate key-value pair
2864 OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_KSV, total_size, truncate););
2865 if (OsclErrNone != err || !kvpPtr)
2866 {
2867 LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - AllocateKvp failed. err=%d", err));
2868 return PVMFFailure;
2869 }
2870
2871 if (truncate)
2872 {
2873 iInputFile->Seek(dataLen, Oscl_File::SEEKCUR);
2874 kvpPtr->capacity = 0;
2875 kvpPtr->length = 0;
2876
2877 OSCL_TRY(err, iFrames.push_back(kvpPtr););
2878 OSCL_FIRST_CATCH_ANY(err,
2879 LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
2880 return PVMFErrNoMemory;);
2881
2882 return PVMFSuccess;
2883
2884 }
2885
2886 kvpPtr->capacity = total_size;
2887 kvpPtr->length = total_size;
2888
2889 //convert raw data to struct
2890 PVMFStatus status;
2891 status = ConvertAsciiDataToApic(ImageFormat.get_str(), description.get_str(), picType,
2892 dataLen, kvpPtr->value.key_specific_value, total_size);
2893 }
2894 break;
2895
2896
2897 case PV_ID3_CHARSET_UTF16:
2898 case PV_ID3_CHARSET_UTF16BE:
2899 {
2900 OSCL_wHeapString<OsclMemAllocator> description;
2901 if (GetAlbumArtInfo(aFrameType, aFrameSize, ImageFormat, picType, description, dataLen) != PVMFSuccess)
2902 return PVMFFailure;
2903
2904 if (!oscl_strcmp(ImageFormat.get_cstr(), "-->"))
2905 {
2906 pic_as_url = true;
2907 break;
2908 }
2909
2910 keyStr += KVP_FORMAT_ALBUMART;
2911 keyStr += SEMI_COLON;
2912 keyStr += KVP_VALTYPE_ALBUMART;
2913
2914 //image format is stored as wchar.
2915 uint32 rfs = aFrameSize - (ImageFormat.get_size() + (2 * oscl_strlen(description.get_str())));
2916 uint32 wchar_size = sizeof(oscl_wchar); //for platforms that store wchar as 4 bytes.
2917 uint32 total_size = sizeof(PvmfApicStruct) + rfs + (wchar_size * (ImageFormat.get_size() + description.get_size())) + (2 * wchar_size);
2918
2919 // Allocate key-value pair
2920 OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_KSV, total_size, truncate););
2921 if (OsclErrNone != err || !kvpPtr)
2922 {
2923 LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - AllocateKvp failed. err=%d", err));
2924 return PVMFFailure;
2925 }
2926
2927 if (truncate)
2928 {
2929 iInputFile->Seek(dataLen, Oscl_File::SEEKCUR);
2930 kvpPtr->capacity = 0;
2931 kvpPtr->length = 0;
2932
2933 OSCL_TRY(err, iFrames.push_back(kvpPtr););
2934 OSCL_FIRST_CATCH_ANY(err,
2935 LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
2936 return PVMFErrNoMemory;);
2937
2938 return PVMFSuccess;
2939
2940 }
2941
2942 kvpPtr->capacity = total_size;
2943 kvpPtr->length = total_size;
2944
2945 //convert raw data to struct
2946 PVMFStatus status;
2947 status = ConvertUnicodeDataToApic(ImageFormat.get_str(), description.get_str(), picType,
2948 dataLen , kvpPtr->value.key_specific_value, total_size);
2949 }
2950 break;
2951 default:
2952 return PVMFFailure;
2953
2954 }
2955
2956 if (pic_as_url)
2957 {
2958
2959 keyStr += KVP_VALTYPE_ISO88591_CHAR;
2960 bool truncate = false;
2961 // Allocate key-value pair
2962 OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, dataLen, truncate););
2963 if (OsclErrNone != err || !kvpPtr)
2964 {
2965 LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - AllocateKvp failed. err=%d", err));
2966 return PVMFFailure;
2967 }
2968
2969 if (truncate)
2970 {
2971 iInputFile->Seek(dataLen, Oscl_File::SEEKCUR);
2972 kvpPtr->length = 0;
2973
2974 OSCL_TRY(err, iFrames.push_back(kvpPtr););
2975 OSCL_FIRST_CATCH_ANY(err,
2976 LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
2977 return PVMFErrNoMemory;);
2978
2979 return PVMFSuccess;
2980
2981 }
2982 else
2983 {
2984 if (readByteData(iInputFile, dataLen, (uint8 *)kvpPtr->value.pChar_value) == false)
2985 return PVMFFailure;
2986 kvpPtr->value.pChar_value[dataLen] = NULL_TERM_CHAR;
2987 kvpPtr->length = dataLen;
2988 }
2989 }
2990 else
2991 {
2992 aApicStruct = OSCL_STATIC_CAST(PvmfApicStruct *, kvpPtr->value.key_specific_value);
2993 if (readByteData(iInputFile, dataLen, aApicStruct->iGraphicData) == false)
2994 return PVMFFailure;
2995 }
2996
2997
2998 OSCL_TRY(err, iFrames.push_back(kvpPtr););
2999 OSCL_FIRST_CATCH_ANY(err,
3000 LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - iFrame.push_back failed"));
3001 return PVMFErrNoMemory;
3002 );
3003
3004 return PVMFSuccess;
3005 }
3006
ReadLyricsCommFrame(uint8 unicodeCheck,uint32 aFramesize,PVID3FrameType aFrameType)3007 PVMFStatus PVID3ParCom::ReadLyricsCommFrame(uint8 unicodeCheck, uint32 aFramesize, PVID3FrameType aFrameType)
3008 {
3009
3010 uint32 framesize = aFramesize;
3011 bool truncate = false;
3012 if (readByteData(iInputFile, ID3V2_LANGUAGE_SIZE, iID3TagInfo.iID3V2LanguageID) == false)
3013 {
3014 return PVMFFailure;
3015 }
3016
3017 iID3TagInfo.iID3V2LanguageID[ID3V2_LANGUAGE_SIZE] = 0;
3018
3019 //subtract 3 bytes of language from the frame size.
3020 framesize = aFramesize - ID3V2_LANGUAGE_SIZE ;
3021 if ((framesize == 0) || (framesize > aFramesize))
3022 {
3023 return PVMFFailure;
3024 }
3025 //construct kvp for lyrics frame
3026 OSCL_StackString<128> keyStr;
3027 if (ConstructKvpKey(keyStr, aFrameType, (PVID3ParCom::PVID3CharacterSet)unicodeCheck) != PVMFSuccess)
3028 {
3029 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - ConstructKvpKey failed"));
3030 return PVMFErrNotSupported;
3031 }
3032
3033 int32 err = OsclErrNone;
3034 PvmiKvpSharedPtr kvpPtr;
3035 uint32 wchar_size = sizeof(oscl_wchar); //for platforms where wchar is 4 bytes.
3036 uint32 total_size = (wchar_size * framesize) + sizeof(PvmfLyricsCommStruct) + (2 * wchar_size) ;
3037 uint32 used_size = 0;
3038 // Allocate key-value pair
3039 OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_KSV, total_size , truncate););
3040 if (OsclErrNone != err || !kvpPtr)
3041 {
3042 LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - AllocateKvp failed. err=%d", err));
3043 return PVMFFailure;
3044 }
3045
3046 if (truncate)
3047 {
3048 iInputFile->Seek(framesize, Oscl_File::SEEKCUR);
3049 kvpPtr->capacity = 0;
3050 kvpPtr->length = 0;
3051
3052 OSCL_TRY(err, iFrames.push_back(kvpPtr););
3053 OSCL_FIRST_CATCH_ANY(err,
3054 LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
3055 return PVMFErrNoMemory;);
3056
3057 return PVMFSuccess;
3058
3059 }
3060
3061 PvmfLyricsCommStruct *lcStruct = NULL;
3062 uint8 *ptr = NULL;
3063 lcStruct = OSCL_STATIC_CAST(PvmfLyricsCommStruct *, kvpPtr->value.key_specific_value);
3064 ptr = (uint8 *)kvpPtr->value.key_specific_value;
3065 if (!ptr)
3066 {
3067 return PVMFFailure;
3068 }
3069
3070 ptr += sizeof(PvmfLyricsCommStruct);
3071 used_size += sizeof(PvmfLyricsCommStruct);
3072
3073 switch (unicodeCheck)
3074 {
3075 case PV_ID3_CHARSET_ISO88591:
3076 case PV_ID3_CHARSET_UTF8:
3077 {
3078 OSCL_HeapString<OsclMemAllocator> descriptor;
3079
3080 if (readNullTerminatedAsciiString(iInputFile, descriptor) == false)
3081 {
3082 iAlloc.deallocate(lcStruct);
3083 return PVMFFailure;
3084 }
3085
3086 uint32 desc_sz = descriptor.get_size();
3087 framesize = framesize - desc_sz - 1 ; //subtract 1 for null character
3088
3089 if ((framesize > aFramesize) || (framesize == 0))
3090 {
3091 lcStruct->iDescription = NULL;
3092 lcStruct->iData = NULL;
3093 break;
3094 }
3095
3096 lcStruct->iDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3097 ptr += wchar_size * (desc_sz + 1); //1 for null char
3098
3099 used_size += wchar_size * (desc_sz + 1);
3100 if (used_size > total_size)
3101 return PVMFErrOverflow;
3102 if (desc_sz > 0)
3103 {
3104 uint32 sz = desc_sz + 1;
3105 oscl_UTF8ToUnicode((const char *)descriptor.get_cstr(), descriptor.get_size(), lcStruct->iDescription, sz);
3106 lcStruct->iDescription[sz] = 0;
3107 }
3108 else
3109 {
3110 lcStruct->iDescription[desc_sz] = 0;
3111 }
3112
3113 uint8 *data = NULL;
3114 uint32 datasz = framesize + 1;
3115 OSCL_TRY(err, data = (uint8*)iAlloc.allocate(datasz););
3116
3117 if (OsclErrNone != err || !(data))
3118 {
3119 LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - allocation failed"));
3120 iInputFile->Seek(framesize, Oscl_File::SEEKCUR);
3121
3122 }
3123
3124 else
3125 {
3126
3127 if ((readByteData(iInputFile, framesize, data) == false))
3128 {
3129 iAlloc.deallocate(data);
3130 return PVMFFailure;
3131 }
3132
3133 lcStruct->iData = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3134 used_size += datasz;
3135
3136 if (used_size > total_size)
3137 return PVMFErrOverflow;
3138 oscl_UTF8ToUnicode((const char *)data, framesize, lcStruct->iData, datasz);
3139 lcStruct->iData[datasz] = 0;
3140
3141 iAlloc.deallocate(data);
3142 }
3143 }
3144
3145 break;
3146
3147 case PV_ID3_CHARSET_UTF16:
3148 case PV_ID3_CHARSET_UTF16BE:
3149 {
3150
3151 uint32 bomSize = 0;
3152 OSCL_wHeapString<OsclMemAllocator> description ;
3153
3154 if (readNullTerminatedUnicodeString(iInputFile, description, bomSize) == false)
3155 {
3156 return PVMFFailure;
3157 }
3158
3159 uint32 desc_len = oscl_strlen(description.get_str()) ;
3160 framesize = framesize - (2 * desc_len) - 2 - bomSize; // description(2 byte unicode in id3 tag), null char, bom
3161 if ((framesize > aFramesize) || (framesize == 0))
3162 {
3163 lcStruct->iDescription = NULL;
3164 lcStruct->iData = NULL;
3165 break;
3166 }
3167
3168 lcStruct->iDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3169 ptr += wchar_size * (desc_len + 1); //1 for null char
3170
3171 used_size += wchar_size * (desc_len + 1);
3172 if (used_size > total_size)
3173 return PVMFErrOverflow;
3174
3175 if (desc_len > 0)
3176 {
3177 oscl_strncpy(lcStruct->iDescription, description.get_str(), desc_len);
3178 lcStruct->iDescription[desc_len + 1] = 0;
3179 }
3180 else
3181 {
3182 lcStruct->iDescription[desc_len] = 0;
3183 }
3184
3185
3186 uint16 endianCheck = 0;
3187 //check endian type
3188 if (read16(iInputFile, endianCheck) == false)
3189 {
3190
3191 return PVMFFailure;
3192 }
3193
3194 // This frame's text strings are Unicode and the frame
3195 // does include a BOM value. (UTF-16)
3196 iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16;
3197 uint32 endianType = 0;
3198
3199 if (endianCheck == UNICODE_LITTLE_ENDIAN_INDICATOR_FULL)
3200 {
3201 endianType = UNICODE_LITTLE_ENDIAN;
3202 }
3203 else if (endianCheck == UNICODE_BIG_ENDIAN_INDICATOR_FULL)
3204 {
3205 endianType = UNICODE_BIG_ENDIAN;
3206 }
3207
3208 framesize -= UNICODE_BOM_SIZE;
3209 if ((framesize > aFramesize) || (framesize == 0))
3210 {
3211 lcStruct->iDescription = NULL;
3212 lcStruct->iData = NULL;
3213 break;
3214 }
3215
3216 uint8 *data = NULL;
3217 uint32 datasz = framesize + 2;
3218 int32 err = OsclErrNone;
3219 OSCL_TRY(err, data = (uint8*)iAlloc.allocate(datasz););
3220 if (OsclErrNone != err || !(data))
3221 {
3222 LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - allocation failed"));
3223 truncate = true;
3224 }
3225 else
3226 {
3227
3228 oscl_memset(data, 0, datasz);
3229 if ((readByteData(iInputFile, framesize, data) == false))
3230 {
3231 iAlloc.deallocate(data);
3232 return PVMFFailure;
3233 }
3234 lcStruct->iData = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3235
3236 used_size += wchar_size * (framesize / 2); //UCS-2 unicode
3237 if (used_size > total_size)
3238 return PVMFErrOverflow;
3239
3240 uint32 sz = EightBitToWideCharBufferTransfer(data, framesize, endianType , lcStruct->iData);
3241 lcStruct->iData[sz] = 0;
3242
3243 iAlloc.deallocate(data);
3244 }
3245 }
3246 break;
3247
3248 default:
3249 return PVMFFailure;
3250
3251 }
3252
3253 kvpPtr->capacity = (aFramesize - ID3V2_LANGUAGE_SIZE) + sizeof(PvmfLyricsCommStruct) ;
3254 kvpPtr->length = (aFramesize - ID3V2_LANGUAGE_SIZE) + sizeof(PvmfLyricsCommStruct) ;
3255
3256 OSCL_TRY(err, iFrames.push_back(kvpPtr););
3257 OSCL_FIRST_CATCH_ANY(err,
3258 LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
3259 return PVMFErrNoMemory;
3260 );
3261
3262
3263 return PVMFSuccess;
3264 }
3265
ConvertAsciiDataToApic(char * aMimeTypeID3,char * aDescriptionID3,uint8 aGraphicType,uint32 aGraphicDataLen,void * key_specific_value,uint32 total_size)3266 PVMFStatus PVID3ParCom::ConvertAsciiDataToApic(char* aMimeTypeID3, char* aDescriptionID3,
3267 uint8 aGraphicType, uint32 aGraphicDataLen,
3268 void *key_specific_value, uint32 total_size)
3269 {
3270 uint32 used_size = 0;
3271 uint8 *ptr = (uint8 *)key_specific_value;
3272 PvmfApicStruct* aAPICStruct = OSCL_STATIC_CAST(PvmfApicStruct*, key_specific_value);
3273 uint32 mime_string_size;
3274 uint32 description_size;
3275 mime_string_size = oscl_strlen(aMimeTypeID3) + 1;
3276 description_size = oscl_strlen(aDescriptionID3) + 1;
3277 ptr += sizeof(PvmfApicStruct);
3278 used_size += sizeof(PvmfApicStruct);
3279 if (used_size > total_size)
3280 return PVMFErrOverflow;
3281 aAPICStruct->iGraphicMimeType = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3282 ptr += sizeof(oscl_wchar) * (mime_string_size);
3283 used_size += sizeof(oscl_wchar) * (mime_string_size);
3284 if (used_size > total_size)
3285 return PVMFErrOverflow;
3286 aAPICStruct->iGraphicDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3287 ptr += sizeof(oscl_wchar) * (description_size);
3288 used_size += sizeof(oscl_wchar) * (description_size);
3289 if (used_size > total_size)
3290 return PVMFErrOverflow;
3291
3292 oscl_memset(aAPICStruct->iGraphicDescription, 0 , description_size);
3293 oscl_memset(aAPICStruct->iGraphicMimeType , 0 , mime_string_size);
3294 oscl_UTF8ToUnicode((const char *)aDescriptionID3, description_size , aAPICStruct->iGraphicDescription, description_size);
3295 oscl_UTF8ToUnicode((const char *)aMimeTypeID3, mime_string_size, aAPICStruct->iGraphicMimeType, mime_string_size);
3296
3297 //push the data to PvmfApicStruct
3298 aAPICStruct->iGraphicType = aGraphicType;
3299
3300 aAPICStruct->iGraphicData = OSCL_STATIC_CAST(uint8 *, ptr);
3301
3302 aAPICStruct->iGraphicDataLen = aGraphicDataLen;
3303
3304 used_size += aGraphicDataLen;
3305 if (used_size > total_size)
3306 return PVMFErrOverflow;
3307 return PVMFSuccess;
3308 }
3309
ConvertUnicodeDataToApic(char * aMimeTypeID3,oscl_wchar * aDescriptionID3,uint8 aGraphicType,uint32 aGraphicDataLen,void * key_specific_value,uint32 total_size)3310 PVMFStatus PVID3ParCom::ConvertUnicodeDataToApic(char* aMimeTypeID3, oscl_wchar* aDescriptionID3,
3311 uint8 aGraphicType, uint32 aGraphicDataLen,
3312 void *key_specific_value, uint32 total_size)
3313 {
3314 uint32 used_size = 0;
3315 uint8 *ptr = (uint8 *)key_specific_value;
3316 PvmfApicStruct* aAPICStruct = OSCL_STATIC_CAST(PvmfApicStruct*, key_specific_value);
3317 uint32 mime_string_size;
3318 uint32 description_size;
3319
3320 mime_string_size = oscl_strlen(aMimeTypeID3) + 1;
3321 description_size = oscl_strlen(aDescriptionID3) + 1;
3322
3323 ptr += sizeof(PvmfApicStruct);
3324 used_size += sizeof(PvmfApicStruct);
3325 if (used_size > total_size)
3326 return PVMFErrOverflow;
3327
3328 aAPICStruct->iGraphicMimeType = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3329 ptr += sizeof(oscl_wchar) * mime_string_size;
3330 used_size += sizeof(oscl_wchar) * mime_string_size;
3331 if (used_size > total_size)
3332 return PVMFErrOverflow;
3333 aAPICStruct->iGraphicDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3334 ptr += sizeof(oscl_wchar) * description_size;
3335 used_size += sizeof(oscl_wchar) * description_size;
3336 if (used_size > total_size)
3337 return PVMFErrOverflow;
3338 //push the data to PvmfApicStruct
3339 oscl_memset(aAPICStruct->iGraphicDescription, '\0', sizeof(oscl_wchar)*description_size);
3340 oscl_memset(aAPICStruct->iGraphicMimeType , '\0', sizeof(oscl_wchar)*mime_string_size);
3341 oscl_UTF8ToUnicode((const char *)aMimeTypeID3, mime_string_size - 1, aAPICStruct->iGraphicMimeType, mime_string_size);
3342 aAPICStruct->iGraphicMimeType[mime_string_size] = 0;
3343
3344 oscl_strncpy(aAPICStruct->iGraphicDescription, aDescriptionID3, description_size);
3345 aAPICStruct->iGraphicDescription[description_size] = 0;
3346 aAPICStruct->iGraphicType = aGraphicType;
3347 aAPICStruct->iGraphicDataLen = aGraphicDataLen;
3348 aAPICStruct->iGraphicData = OSCL_STATIC_CAST(uint8 *, ptr);
3349 used_size += aGraphicDataLen;
3350 if (used_size > total_size)
3351 return PVMFErrOverflow;
3352
3353 return PVMFSuccess;
3354 }
3355
GetAlbumArtInfo(PVID3FrameType aFrameType,uint32 aFrameSize,OSCL_HeapString<OsclMemAllocator> & aImageFormat,uint8 & aPicType,OSCL_HeapString<OsclMemAllocator> & aDescription,uint32 & aDataLen)3356 PVMFStatus PVID3ParCom::GetAlbumArtInfo(PVID3FrameType aFrameType, uint32 aFrameSize, OSCL_HeapString<OsclMemAllocator> &aImageFormat,
3357 uint8 &aPicType, OSCL_HeapString<OsclMemAllocator> &aDescription, uint32 &aDataLen)
3358 {
3359 uint8 image_format[4] = {0};
3360 PVMFStatus status = 0;
3361 uint32 size = 0;
3362 uint32 currentfilepos = 0 ;
3363 if (aFrameType == PV_ID3_FRAME_PIC)
3364 {
3365 if (readByteData(iInputFile, ID3V2_IMAGE_FORMAT_SIZE, image_format) == false)
3366 {
3367 return PVMFFailure;
3368 }
3369 else
3370 {
3371 aImageFormat = (char *)image_format;
3372 }
3373 if (read8(iInputFile, aPicType) == false)
3374 {
3375 return PVMFFailure;
3376 }
3377
3378 currentfilepos = iInputFile->Tell();
3379 //read description from file
3380 status = readNullTerminatedAsciiString(iInputFile, aDescription);
3381 if (status != PVMFSuccess)
3382 {
3383 iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3384 return PVMFFailure;
3385 }
3386 //get the graphic data len
3387 size = aDescription.get_size() + 1 ; // 1 byte for null char
3388 aDataLen = aFrameSize - (ID3V2_PIC_CONST_SIZE + size);
3389 if (aDataLen > aFrameSize)
3390 {
3391 iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3392 aDataLen = 0;
3393 return PVMFFailure;
3394 }
3395
3396
3397
3398 }
3399 else if (aFrameType == PV_ID3_FRAME_APIC)
3400 {
3401 uint32 mimeSize;
3402 uint32 desSize;
3403
3404 currentfilepos = iInputFile->Tell();
3405 status = readNullTerminatedAsciiString(iInputFile, aImageFormat);
3406 if (status != PVMFSuccess)
3407 {
3408 iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3409 return PVMFFailure;
3410 }
3411 if (read8(iInputFile, aPicType) == false)
3412 {
3413 return PVMFFailure;
3414 }
3415 currentfilepos = iInputFile->Tell();
3416 status = readNullTerminatedAsciiString(iInputFile, aDescription);
3417 if (status != PVMFSuccess)
3418 {
3419 iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3420 return status;
3421 }
3422
3423 //get the graphic data len
3424 mimeSize = aImageFormat.get_size() + 1; //for null string
3425 desSize = aDescription.get_size() + 1; //for null string
3426
3427 aDataLen = aFrameSize - (ID3V2_APIC_CONST_SIZE + mimeSize + desSize);
3428
3429 if (aDataLen > aFrameSize)
3430 {
3431 iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3432 aDataLen = 0;
3433 return PVMFFailure;
3434 }
3435
3436
3437 }
3438 return PVMFSuccess;
3439 }
3440
GetAlbumArtInfo(PVID3FrameType aFrameType,uint32 aFrameSize,OSCL_HeapString<OsclMemAllocator> & aImageFormat,uint8 & aPicType,OSCL_wHeapString<OsclMemAllocator> & aDescription,uint32 & aDataLen)3441 PVMFStatus PVID3ParCom::GetAlbumArtInfo(PVID3FrameType aFrameType, uint32 aFrameSize, OSCL_HeapString<OsclMemAllocator> &aImageFormat,
3442 uint8 &aPicType, OSCL_wHeapString<OsclMemAllocator> &aDescription, uint32 &aDataLen)
3443 {
3444 uint8 image_format[4] = {0};
3445 uint32 currentfilepos = 0;
3446 uint32 size = 0;
3447 if (aFrameType == PV_ID3_FRAME_PIC)
3448 {
3449 if (readByteData(iInputFile, ID3V2_IMAGE_FORMAT_SIZE, image_format) == false)
3450 {
3451 return PVMFFailure;
3452 }
3453 else
3454 {
3455 aImageFormat = (char *)image_format;
3456 }
3457 if (read8(iInputFile, aPicType) == false)
3458 {
3459 return PVMFFailure;
3460 }
3461
3462 uint32 bomSz = 0;
3463 currentfilepos = iInputFile->Tell();
3464 //read description from file
3465 if (readNullTerminatedUnicodeString(iInputFile, aDescription, bomSz) == false)
3466 {
3467 iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3468 return PVMFFailure;
3469 }
3470
3471 //get the graphic data len
3472 size = (2 * oscl_strlen(aDescription.get_str())) + bomSz + sizeof(oscl_wchar) * 1; //2 byte null character
3473 aDataLen = aFrameSize - (ID3V2_PIC_CONST_SIZE + size);
3474 if (aDataLen > aFrameSize)
3475 {
3476 iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3477 aDataLen = 0;
3478 return PVMFFailure;
3479 }
3480
3481
3482 }
3483 else if (aFrameType == PV_ID3_FRAME_APIC)
3484 {
3485 uint32 mimeSize;
3486 uint32 desSize;
3487 currentfilepos = iInputFile->Tell();
3488 //read the mime type information
3489 if (readNullTerminatedAsciiString(iInputFile, aImageFormat) == false)
3490 {
3491 iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3492 return PVMFFailure;
3493 }
3494 //read the picture type information
3495 if (read8(iInputFile, aPicType) == false)
3496 {
3497 return PVMFFailure;
3498 }
3499 uint32 bomSz = 0;
3500 currentfilepos = iInputFile->Tell();
3501 //read the null terminated description information
3502 if (readNullTerminatedUnicodeString(iInputFile, aDescription, bomSz) == false)
3503 {
3504 iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3505 return PVMFFailure;
3506 }
3507 //get the graphic data len
3508 mimeSize = aImageFormat.get_size() + 1;
3509 desSize = (2 * oscl_strlen(aDescription.get_str())) + bomSz + sizeof(oscl_wchar) * 1; //2 bytes for null character
3510 aDataLen = aFrameSize - (ID3V2_APIC_CONST_SIZE + mimeSize + desSize);
3511 if (aDataLen > aFrameSize)
3512 {
3513 iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3514 aDataLen = 0;
3515 return PVMFFailure;
3516 }
3517
3518
3519
3520 }
3521 return PVMFSuccess;
3522 }
3523
3524
3525 ////////////////////////////////////////////////////////////////////////////
ReadTrackLengthFrame(uint32 aValueSize,PVID3CharacterSet aCharSet)3526 PVMFStatus PVID3ParCom::ReadTrackLengthFrame(uint32 aValueSize, PVID3CharacterSet aCharSet)
3527 {
3528 OSCL_StackString<128> keyStr;
3529 if (ConstructKvpKey(keyStr, PV_ID3_FRAME_TRACK_LENGTH, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
3530 {
3531 LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - ConstructKvpKey failed"));
3532 return PVMFErrNotSupported;
3533 }
3534
3535 int32 err = OsclErrNone;
3536 uint8* ptrFrameData = NULL;
3537 ptrFrameData = (uint8*) AllocateValueArray(err, PVMI_KVPVALTYPE_UINT8PTR, aValueSize + 2, &iAlloc);
3538 if (OsclErrNone != err || !ptrFrameData)
3539 {
3540 LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - ptrFrameData allocation failed"));
3541 return PVMFErrNoMemory;
3542 }
3543
3544 if (readByteData(iInputFile, aValueSize, ptrFrameData) == false)
3545 {
3546 iAlloc.deallocate((OsclAny*)ptrFrameData);
3547 LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - readByteData failed"));
3548 return PVMFFailure;
3549 }
3550 ptrFrameData[aValueSize] = 0;
3551 ptrFrameData[aValueSize+1] = 0;
3552
3553 switch (aCharSet)
3554 {
3555 case PV_ID3_CHARSET_UTF16:
3556 case PV_ID3_CHARSET_UTF16BE:
3557 {
3558 //it uses 16-bit unicode 2.0 (ISO/IEC 10646-1:1993, UCS-2)
3559
3560 char* tmpData = NULL;
3561 int len = aValueSize / UNICODE_CHAR_SIZE + 1;
3562 tmpData = (char*) AllocateValueArray(err, PVMI_KVPVALTYPE_CHARPTR, len, &iAlloc);
3563
3564 if (sizeof(oscl_wchar) == UNICODE_CHAR_SIZE)
3565 {
3566 oscl_UnicodeToUTF8((oscl_wchar*)ptrFrameData, aValueSize / sizeof(oscl_wchar), tmpData, len);
3567 }
3568 else
3569 {
3570 oscl_wchar* tmpData2 = NULL;
3571
3572 tmpData2 = (oscl_wchar*) AllocateValueArray(err, PVMI_KVPVALTYPE_WCHARPTR, len);
3573 // convert 2 byte unicode data to 4 byte wchar data
3574 ExpandWChar2BytesTo4Bytes(tmpData2, (uint16*)ptrFrameData, len);
3575
3576 oscl_UnicodeToUTF8(tmpData2, aValueSize / UNICODE_CHAR_SIZE, tmpData, len);
3577
3578 OSCL_ARRAY_DELETE(tmpData2);
3579 }
3580
3581 // copy the UTF8 string back to ptrFrameData
3582 oscl_strncpy((char*)ptrFrameData, tmpData, len);
3583
3584 iAlloc.deallocate((OsclAny*)tmpData);
3585 }
3586 break;
3587 case PV_ID3_CHARSET_ISO88591:
3588 case PV_ID3_CHARSET_UTF8:
3589 break;
3590 default:
3591 return PVMFFailure;
3592 }
3593
3594 // The ID3 Track Length is a numeric string in milliseconds.
3595 uint32 duration = 0;
3596 int32 numericStringLen = oscl_strlen((const char*)ptrFrameData);
3597
3598 if (!PV_atoi((const char *)ptrFrameData, 'd', numericStringLen, duration))
3599 {
3600 uint8* ptr = ptrFrameData;
3601 bool invalid_frame = false;
3602 while (ptr - ptrFrameData < numericStringLen)
3603 {
3604 // if the charater read is a digit or decimal point
3605 // then truncate it to integer value
3606 if (!(((*ptr >= ZERO_CHARACTER_ASCII_VALUE) &&
3607 (*ptr <= NINE_CHARACTER_ASCII_VALUE)) ||
3608 (*ptr == PERIOD_CHARACTER_ASCII_VALUE) ||
3609 (*ptr == COMMA_CHARACTER_ASCII_VALUE)))
3610 {
3611 invalid_frame = true;
3612 break;
3613 }
3614 else if (*ptr == PERIOD_CHARACTER_ASCII_VALUE ||
3615 *ptr == COMMA_CHARACTER_ASCII_VALUE)
3616 {
3617 numericStringLen = ptr - ptrFrameData;
3618 break;
3619 }
3620 ptr++;
3621 }
3622
3623 if (!invalid_frame)
3624 {
3625 numericStringLen = ptr - ptrFrameData;
3626 }
3627 else
3628 {
3629 iAlloc.deallocate((OsclAny*)ptrFrameData);
3630 numericStringLen = 0;
3631 return PVMFSuccess;
3632 }
3633 }
3634
3635 // Allocate key-value pair
3636 bool truncate = false;
3637 PvmiKvpSharedPtr kvpPtr;
3638 PVMFStatus status = PVMFSuccess;
3639 kvpPtr = HandleErrorForKVPAllocation(keyStr, PVMI_KVPVALTYPE_UINT32, 1, truncate, status);
3640 if (PVMFSuccess != status || !kvpPtr)
3641 {
3642 iAlloc.deallocate((OsclAny*)ptrFrameData);
3643 return PVMFErrNoMemory;
3644 }
3645
3646 kvpPtr->value.uint32_value = duration; // Track length in milliseconds
3647 kvpPtr->length = numericStringLen;
3648
3649 iAlloc.deallocate((OsclAny*)ptrFrameData);
3650
3651 OSCL_TRY(err, iFrames.push_back(kvpPtr););
3652 OSCL_FIRST_CATCH_ANY(err,
3653 LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - iFrame.push_back failed"));
3654 return PVMFErrNoMemory;
3655 );
3656
3657 return PVMFSuccess;
3658 }
3659
3660
3661 ////////////////////////////////////////////////////////////////////////////
GetKvpValueType(PvmiKvpSharedPtr aKvp,PvmiKvpValueType & aValueType,PVID3CharacterSet & aCharSet)3662 PVMFStatus PVID3ParCom::GetKvpValueType(PvmiKvpSharedPtr aKvp,
3663 PvmiKvpValueType& aValueType,
3664 PVID3CharacterSet& aCharSet)
3665 {
3666 aValueType = GetValTypeFromKeyString(aKvp->key);
3667 aCharSet = PV_ID3_CHARSET_INVALID;
3668 char* param = NULL;
3669 switch (aValueType)
3670 {
3671 case PVMI_KVPVALTYPE_CHARPTR:
3672 aCharSet = PV_ID3_CHARSET_ISO88591;
3673 if (pv_mime_string_parse_param(aKvp->key, (char*) KVP_PARAM_CHAR_ENCODING_UTF8, param) > 0)
3674 aCharSet = PV_ID3_CHARSET_UTF8;
3675 break;
3676 case PVMI_KVPVALTYPE_WCHARPTR:
3677 aCharSet = PV_ID3_CHARSET_UTF16;
3678 if (pv_mime_string_parse_param(aKvp->key, (char*) KVP_PARAM_CHAR_ENCODING_UTF16BE, param) > 0)
3679 aCharSet = PV_ID3_CHARSET_UTF16BE;
3680 break;
3681 case PVMI_KVPVALTYPE_KSV:
3682 // Comment field
3683 break;
3684 case PVMI_KVPVALTYPE_UNKNOWN:
3685 return PVMFFailure;
3686 default:
3687 break;
3688 }
3689
3690 return PVMFSuccess;
3691 }
3692
3693 ////////////////////////////////////////////////////////////////////////////
GetFrameTypeFromKvp(PvmiKvpSharedPtr aKvp,OSCL_String & aFrameID,PVID3FrameType & aFrameType)3694 PVMFStatus PVID3ParCom::GetFrameTypeFromKvp(PvmiKvpSharedPtr aKvp,
3695 OSCL_String& aFrameID,
3696 PVID3FrameType& aFrameType)
3697 {
3698 return GetFrameTypeFromKvp(*aKvp, aFrameID, aFrameType);
3699 }
3700
3701 ////////////////////////////////////////////////////////////////////////////
GetFrameTypeFromKvp(const PvmiKvp & aKvp,OSCL_String & aFrameID,PVID3FrameType & aFrameType)3702 PVMFStatus PVID3ParCom::GetFrameTypeFromKvp(const PvmiKvp& aKvp,
3703 OSCL_String& aFrameID,
3704 PVID3FrameType& aFrameType)
3705 {
3706 if (iVersion == PV_ID3_V2_2)
3707 {
3708 if (pv_mime_strcmp(aKvp.key, KVP_KEY_TITLE) == 0)
3709 {
3710 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_TITLE);
3711 aFrameType = PV_ID3_FRAME_TITLE;
3712 }
3713 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ARTIST) == 0)
3714 {
3715 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_ARTIST);
3716 aFrameType = PV_ID3_FRAME_ARTIST;
3717 }
3718 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_PART_OF_SET) == 0)
3719 {
3720 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_PART_OF_SET);
3721 aFrameType = PV_ID3_FRAME_PART_OF_SET;
3722 }
3723 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUM) == 0)
3724 {
3725 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_ALBUM);
3726 aFrameType = PV_ID3_FRAME_ALBUM;
3727 }
3728 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_TRACK_NUMBER) == 0)
3729 {
3730 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_TRACK_NUMBER);
3731 aFrameType = PV_ID3_FRAME_TRACK_NUMBER;
3732 }
3733 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_GENRE) == 0)
3734 {
3735 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_GENRE);
3736 aFrameType = PV_ID3_FRAME_GENRE;
3737 }
3738 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_YEAR) == 0)
3739 {
3740 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_YEAR);
3741 aFrameType = PV_ID3_FRAME_YEAR;
3742 }
3743 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COPYRIGHT) == 0)
3744 {
3745 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_COPYRIGHT);
3746 aFrameType = PV_ID3_FRAME_COPYRIGHT;
3747 }
3748 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMMENT) == 0)
3749 {
3750 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_COMMENT);
3751 aFrameType = PV_ID3_FRAME_COMMENT;
3752 }
3753 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ID3DURATION) == 0)
3754 {
3755 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_TRACK_LENGTH);
3756 aFrameType = PV_ID3_FRAME_TRACK_LENGTH;
3757 }
3758 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DATE) == 0)
3759 {
3760 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_DATE);
3761 aFrameType = PV_ID3_FRAME_DATE;
3762 }
3763 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUMART) == 0)
3764 {
3765 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_ALBUMART);
3766 aFrameType = PV_ID3_FRAME_PIC;
3767 }
3768 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_LYRICS) == 0)
3769 {
3770 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_LYRICIST);
3771 aFrameType = PV_ID3_FRAME_LYRICS;
3772 }
3773 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_AUTHOR) == 0)
3774 {
3775 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_AUTHOR);
3776 aFrameType = PV_ID3_FRAME_AUTHOR;
3777 }
3778 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMPOSER) == 0)
3779 {
3780 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_COMPOSER);
3781 aFrameType = PV_ID3_FRAME_COMPOSER;
3782 }
3783 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DESCRIPTION) >= 0)
3784 {
3785 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_DESCRIPTION);
3786 aFrameType = PV_ID3_FRAME_DESCRIPTION;
3787 }
3788 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_VERSION) == 0)
3789 {
3790 aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_VERSION);
3791 aFrameType = PV_ID3_FRAME_VERSION;
3792 }
3793 else
3794 {
3795 LOG_ERR((0, "PVID3ParCom::GetFrameTypeFromKvp: Error : Frame type not supported for composing"));
3796 return PVMFErrNotSupported;
3797 }
3798 }
3799 else
3800 {
3801 if (pv_mime_strcmp(aKvp.key, KVP_KEY_TITLE) == 0)
3802 {
3803 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_TITLE);
3804 aFrameType = PV_ID3_FRAME_TITLE;
3805 }
3806 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ARTIST) == 0)
3807 {
3808 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_ARTIST);
3809 aFrameType = PV_ID3_FRAME_ARTIST;
3810 }
3811 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_PART_OF_SET) == 0)
3812 {
3813 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_PART_OF_SET);
3814 aFrameType = PV_ID3_FRAME_PART_OF_SET;
3815 }
3816 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUM) == 0)
3817 {
3818 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_ALBUM);
3819 aFrameType = PV_ID3_FRAME_ALBUM;
3820 }
3821 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_TRACK_NUMBER) == 0)
3822 {
3823 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_TRACK_NUMBER);
3824 aFrameType = PV_ID3_FRAME_TRACK_NUMBER;
3825 }
3826 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_GENRE) == 0)
3827 {
3828 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_GENRE);
3829 aFrameType = PV_ID3_FRAME_GENRE;
3830 }
3831 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_YEAR) == 0)
3832 {
3833 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_YEAR);
3834 aFrameType = PV_ID3_FRAME_YEAR;
3835 }
3836 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COPYRIGHT) == 0)
3837 {
3838 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_COPYRIGHT);
3839 aFrameType = PV_ID3_FRAME_COPYRIGHT;
3840 }
3841 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMMENT) == 0)
3842 {
3843 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_COMMENT);
3844 aFrameType = PV_ID3_FRAME_COMMENT;
3845 }
3846 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ID3DURATION) == 0)
3847 {
3848 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_TRACK_LENGTH);
3849 aFrameType = PV_ID3_FRAME_TRACK_LENGTH;
3850 }
3851 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_RECORDING_TIME) == 0)
3852 {
3853 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_RECORDING_TIME);
3854 aFrameType = PV_ID3_FRAME_RECORDING_TIME;
3855 }
3856 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_AUTHOR) == 0)
3857 {
3858 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_AUTHOR);
3859 aFrameType = PV_ID3_FRAME_AUTHOR;
3860 }
3861 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMPOSER) == 0)
3862 {
3863 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_COMPOSER);
3864 aFrameType = PV_ID3_FRAME_COMPOSER;
3865 }
3866 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DESCRIPTION) == 0)
3867 {
3868 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_DESCRIPTION);
3869 aFrameType = PV_ID3_FRAME_DESCRIPTION;
3870 }
3871 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_VERSION) == 0)
3872 {
3873 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_VERSION);
3874 aFrameType = PV_ID3_FRAME_VERSION;
3875 }
3876 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DATE) == 0)
3877 {
3878 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_DATE);
3879 aFrameType = PV_ID3_FRAME_DATE;
3880 }
3881 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_LYRICS) == 0)
3882 {
3883 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_LYRICIST);
3884 aFrameType = PV_ID3_FRAME_LYRICS;
3885 }
3886 else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUMART) == 0)
3887 {
3888 aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_ALBUMART);
3889 aFrameType = PV_ID3_FRAME_APIC;
3890 }
3891 else
3892 {
3893 LOG_ERR((0, "PVID3ParCom::GetFrameTypeFromKvp: Error : Frame type not supported for composing"));
3894 return PVMFErrNotSupported;
3895 }
3896 }
3897
3898 return PVMFSuccess;
3899 }
3900
3901 ////////////////////////////////////////////////////////////////////////////
GetID3v2FrameDataSize(PvmiKvpSharedPtr aKvp,PvmiKvpValueType aValueType,PVID3CharacterSet aCharSet,uint32 & aSize)3902 PVMFStatus PVID3ParCom::GetID3v2FrameDataSize(PvmiKvpSharedPtr aKvp,
3903 PvmiKvpValueType aValueType,
3904 PVID3CharacterSet aCharSet,
3905 uint32& aSize)
3906 {
3907 aSize = 0;
3908 switch (aValueType)
3909 {
3910 case PVMI_KVPVALTYPE_CHARPTR:
3911 aSize += (BYTE_FOR_CHARACTERSET_FORMAT + oscl_strlen(aKvp->value.pChar_value) + 1);
3912 break;
3913 case PVMI_KVPVALTYPE_WCHARPTR:
3914 aSize += (BYTE_FOR_CHARACTERSET_FORMAT +
3915 (oscl_strlen(aKvp->value.pWChar_value) + 1) * sizeof(oscl_wchar));
3916 break;
3917 case PVMI_KVPVALTYPE_KSV:
3918 // Comment field
3919 break;
3920 case PVMI_KVPVALTYPE_UINT32:
3921 uint32 value;
3922 value = aKvp->value.uint32_value;
3923 if (value == 0)
3924 return PVMFSuccess;
3925 while (value > 0)
3926 {
3927 value = value / 10;
3928 ++aSize;
3929 }
3930 break;
3931 default:
3932 return PVMFErrNotSupported;
3933 }
3934
3935 // Add 1 byte for BOM value to indicate byte order
3936 if (aCharSet == PV_ID3_CHARSET_UTF16)
3937 ++aSize;
3938
3939 return PVMFSuccess;
3940 }
3941
3942 ////////////////////////////////////////////////////////////////////////////
ComposeID3v2Tag(OsclRefCounterMemFrag & aTag)3943 PVMFStatus PVID3ParCom::ComposeID3v2Tag(OsclRefCounterMemFrag& aTag)
3944 {
3945 uint8* memFragPtr;
3946 uint32 index = 0;
3947 uint32 composedTagSize = 0;
3948 uint32 frameDataSize = 0;
3949 uint32 i = 0;
3950 char bufTrackLength[16];
3951 oscl_wchar wbufTrackLength[16];
3952 oscl_memset(bufTrackLength, 0, 16);
3953 oscl_memset(wbufTrackLength, 0, 16);
3954 PvmiKvpValueType kvpValueType;
3955 PVID3CharacterSet charSet;
3956 PVMFStatus status = PVMFSuccess;
3957
3958 // At least one frame should be present for a valid ID3 tag to be composed
3959 if (iFrames.empty())
3960 {
3961 LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - No Frames are available to add"));
3962 return PVMFFailure;
3963 }
3964
3965 // Calculate the size of composed ID3tag
3966 composedTagSize = GetID3TagSize();
3967 if (composedTagSize == 0)
3968 {
3969 LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetID3TagSize failed"));
3970 return PVMFFailure;
3971 }
3972
3973 //iUseMaxTagSize on but the max tag size set is smaller than the total tag size.
3974 if (iUseMaxTagSize && (iMaxTagSize < composedTagSize))
3975 {
3976 LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - Max tag size is smaller than size of composed tag"));
3977 return PVMFFailure;
3978 }
3979
3980 //if maxsize is greater than tagsize and padding is ON, allocate memory equal to iMaxTagSize
3981 if (iUseMaxTagSize && iUsePadding)
3982 composedTagSize = iMaxTagSize;
3983
3984 //if the fragment buffer size is not sufficient, allocate memory
3985 OsclMemoryFragment& my_memfrag = aTag.getMemFrag();
3986 if (composedTagSize > aTag.getMemFragSize())
3987 {
3988 OsclRefCounter* my_refcnt;
3989
3990 // Create mem frag for ID3 tag
3991 OsclMemAllocDestructDealloc<uint8> my_alloc;
3992 uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >));
3993 uint8* myPtr = (uint8*) my_alloc.allocate(aligned_refcnt_size + composedTagSize);
3994 my_refcnt = OSCL_PLACEMENT_NEW(myPtr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(myPtr));
3995 myPtr += aligned_refcnt_size;
3996
3997 my_memfrag.ptr = myPtr;
3998 my_memfrag.len = 0;
3999
4000 OsclRefCounterMemFrag mynewRefCntMemFrag(my_memfrag, my_refcnt, composedTagSize);
4001
4002 //frees the old memeory and make the RefCounterMemFrag point to newly allocated memory
4003 aTag = mynewRefCntMemFrag;
4004 }
4005
4006 memFragPtr = (uint8*)aTag.getMemFragPtr();
4007 oscl_memset(memFragPtr, 0, composedTagSize);
4008
4009 // Form the tag header and place it into the tag buffer
4010 oscl_memcpy(memFragPtr, ID3_V2_IDENTIFIER, ID3V2_TAG_NUM_BYTES_ID);
4011 index += ID3V2_TAG_NUM_BYTES_ID;
4012
4013 // Store ID3 tag version
4014 memFragPtr[index++] = (uint8)iVersion;
4015 memFragPtr[index++] = 0;
4016
4017 // ID3v2 flags
4018 memFragPtr[index++] = ID3V2_FLAGS;
4019
4020 // Tag size (4 bytes)
4021 uint32 syncSafeInt = ConvertToSyncSafeInt(composedTagSize - 10); // Total Size of ID3 tag - 10 bytes for header
4022 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
4023 memFragPtr[index++] = (uint8)((syncSafeInt & 0xFF000000) >> 24);
4024 memFragPtr[index++] = (uint8)((syncSafeInt & 0x00FF0000) >> 16);
4025 memFragPtr[index++] = (uint8)((syncSafeInt & 0x0000FF00) >> 8);
4026 memFragPtr[index++] = (uint8)(syncSafeInt & 0x000000FF);
4027 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
4028 uint32* sizePtr = (uint32*)(memFragPtr + index);
4029 *sizePtr = syncSafeInt;
4030 index += 4;
4031 #else
4032 #error "Byte order is not specified in OSCL"
4033 #endif
4034
4035 //iterate the frames and write into the tag buffer
4036 OSCL_StackString<4> frameID;
4037 PVID3FrameType frameType;
4038 for (i = 0; i < iFrames.size(); i++)
4039 {
4040 // 4 character Frame ID
4041 status = GetFrameTypeFromKvp(iFrames[i], frameID, frameType);
4042
4043 //ignore unsupported frames.
4044 if ((status == PVMFErrNotSupported) || (frameType == PV_ID3_FRAME_LYRICS) ||
4045 (frameType == PV_ID3_FRAME_APIC) || (frameType == PV_ID3_FRAME_PIC) ||
4046 (frameType == PV_ID3_FRAME_COMMENT))
4047 {
4048 continue;
4049 }
4050
4051 if ((status != PVMFSuccess))
4052 {
4053 LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetFrameTypeFromKvp failed. status=%d", status));
4054 return status;
4055 }
4056 if (iVersion == PV_ID3_V2_2)
4057 {
4058 oscl_memcpy(memFragPtr + index, frameID.get_cstr(), ID3V2_2_FRAME_NUM_BYTES_ID);
4059 index += ID3V2_2_FRAME_NUM_BYTES_ID;
4060 }
4061 else
4062 {
4063 oscl_memcpy(memFragPtr + index, frameID.get_cstr(), ID3V2_FRAME_NUM_BYTES_ID);
4064 index += ID3V2_FRAME_NUM_BYTES_ID;
4065 }
4066 status = GetKvpValueType(iFrames[i], kvpValueType, charSet);
4067 if (status != PVMFSuccess)
4068 {
4069 LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetKvpValueType failed. status=%d", status));
4070 return status;
4071 }
4072
4073 // Size of Frame (4 byte sync safe integer)
4074 status = GetID3v2FrameDataSize(iFrames[i], kvpValueType, charSet, frameDataSize);
4075 if (status != PVMFSuccess)
4076 {
4077 LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetID3v2FrameDataSize failed. status=%d", status));
4078 return status;
4079 }
4080 // syncSafeInt = ConvertToSyncSafeInt(frameDataSize);
4081 syncSafeInt = frameDataSize;
4082
4083 if (iVersion == PV_ID3_V2_2)
4084 {
4085 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
4086 memFragPtr[index++] = (uint8)((syncSafeInt & 0x00FF0000) >> 16);
4087 memFragPtr[index++] = (uint8)((syncSafeInt & 0x0000FF00) >> 8);
4088 memFragPtr[index++] = (uint8)(syncSafeInt & 0x000000FF);
4089 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
4090 sizePtr = (uint32*)(memFragPtr + index);
4091 *sizePtr = syncSafeInt;
4092 index += 3;
4093 #else
4094 #error "Byte order not specified in OSCL"
4095 #endif
4096
4097 }
4098 else
4099 {
4100 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
4101 memFragPtr[index++] = (uint8)((syncSafeInt & 0xFF000000) >> 24);
4102 memFragPtr[index++] = (uint8)((syncSafeInt & 0x00FF0000) >> 16);
4103 memFragPtr[index++] = (uint8)((syncSafeInt & 0x0000FF00) >> 8);
4104 memFragPtr[index++] = (uint8)(syncSafeInt & 0x000000FF);
4105 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
4106 sizePtr = (uint32*)(memFragPtr + index);
4107 *sizePtr = syncSafeInt;
4108 index += 4;
4109 #else
4110 #error "Byte order not specified in OSCL"
4111 #endif
4112
4113 //frame Flag for status messages
4114 memFragPtr[index++] = ID3V2_FLAGS;
4115
4116 //frame flag for format description
4117 memFragPtr[index++] = ID3V2_FLAGS;
4118 }
4119
4120 switch (kvpValueType)
4121 {
4122 case PVMI_KVPVALTYPE_CHARPTR:
4123 memFragPtr[index++] = (uint8) charSet;
4124 frameDataSize -= 2; // Minus 1 byte for the character set and 1 byte for NULL character
4125 oscl_memcpy(memFragPtr + index, iFrames[i]->value.pChar_value, frameDataSize);
4126 index += frameDataSize;
4127 memFragPtr[index++] = 0; // NULL terminate the string
4128 break;
4129 case PVMI_KVPVALTYPE_WCHARPTR:
4130 memFragPtr[index++] = (uint8)charSet;
4131 frameDataSize -= 3; // Minus 1 byte for the character set and 2 bytes for NULL character
4132 if (charSet == PV_ID3_CHARSET_UTF16)
4133 {
4134 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
4135 memFragPtr[index++] = UNICODE_LITTLE_ENDIAN_INDICATOR;
4136 memFragPtr[index++] = UNICODE_BIG_ENDIAN_INDICATOR;
4137 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
4138 memFragPtr[index++] = UNICODE_BIG_ENDIAN_INDICATOR;
4139 memFragPtr[index++] = UNICODE_LITTLE_ENDIAN_INDICATOR;
4140
4141 #else
4142 #error "Byte order not specified"
4143 #endif
4144 frameDataSize -= 2; // Minus 1 byte for byte order
4145 }
4146 oscl_memcpy(memFragPtr + index, iFrames[i]->value.pWChar_value, frameDataSize);
4147 index += frameDataSize;
4148 memFragPtr[index++] = 0; // NULL terminate the string
4149 memFragPtr[index++] = 0; // NULL terminate the string
4150 break;
4151 case PVMI_KVPVALTYPE_UINT32:
4152 // Track length frame
4153 oscl_snprintf((char*)(memFragPtr + index), frameDataSize, "%d\0", iFrames[i]->value.uint32_value);
4154 break;
4155 case PVMI_KVPVALTYPE_KSV:
4156 // Comment frame
4157 memFragPtr[index++] = (uint8)charSet;
4158 frameDataSize -= 1; // Minus 1 byte for the character set
4159 break;
4160 default:
4161 LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - Unsupported key-value pair value type"));
4162 return PVMFErrNotSupported;
4163 }
4164
4165 }
4166
4167 //if padding is on and the tag size is less than the maximum tag specified, do the padding
4168 if (iUseMaxTagSize && iUsePadding && (index < iMaxTagSize))
4169 {
4170 oscl_memset((OsclAny*)(memFragPtr + index), 0, (iMaxTagSize - index));
4171 my_memfrag.len = iMaxTagSize;
4172 }
4173 else
4174 {
4175 //save the filesize into the memory fragment
4176 my_memfrag.len = index;
4177 }
4178
4179 return PVMFSuccess;
4180 }
4181
4182 ////////////////////////////////////////////////////////////////////////////
FrameValidatedID3V2_4(uint8 * aFrameID)4183 PVID3ParCom::PVID3FrameType PVID3ParCom::FrameValidatedID3V2_4(uint8* aFrameID)
4184 {
4185 PVID3FrameType ID3V2FrameTypeReturnValue;
4186
4187 if ((oscl_memcmp(aFrameID, ID3_FRAME_ID_ENCRYPTION, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4188 (oscl_memcmp(aFrameID, ID3_FRAME_ID_AUDIO_SEEK_POINT_INDEX, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4189 (oscl_memcmp(aFrameID, ID3_FRAME_ID_COMMERCIAL_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4190 (oscl_memcmp(aFrameID, ID3_FRAME_ID_ENCRYPTION_REGISTRATION, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4191 (oscl_memcmp(aFrameID, ID3_FRAME_ID_EQUALIZATION2, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4192 (oscl_memcmp(aFrameID, ID3_FRAME_ID_EVENT_TIMING_CODES, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4193 (oscl_memcmp(aFrameID, ID3_FRAME_ID_GENERAL_ENCAPSULATED_OBJECT, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4194 (oscl_memcmp(aFrameID, ID3_FRAME_ID_GROUP_IDENTITY_REGISTRATION, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4195 (oscl_memcmp(aFrameID, ID3_FRAME_ID_LINKED_INFORMATION, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4196 (oscl_memcmp(aFrameID, ID3_FRAME_ID_MUSIC_CD_IDENTIFIER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4197 (oscl_memcmp(aFrameID, ID3_FRAME_ID_MPEG_LOCATION_LOOKUP_TABLE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4198 (oscl_memcmp(aFrameID, ID3_FRAME_ID_OWNERSHIP_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4199 (oscl_memcmp(aFrameID, ID3_FRAME_ID_PRIVATE_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4200 (oscl_memcmp(aFrameID, ID3_FRAME_ID_PLAY_COUNTER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4201 (oscl_memcmp(aFrameID, ID3_FRAME_ID_POPULARIMETER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4202 (oscl_memcmp(aFrameID, ID3_FRAME_ID_POSITION_SYNCH_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4203 (oscl_memcmp(aFrameID, ID3_FRAME_ID_RECOMMENDED_BUFFER_SIZE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4204 (oscl_memcmp(aFrameID, ID3_FRAME_ID_RELATIVE_VOLUME_ADJUSTMENT2, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4205 (oscl_memcmp(aFrameID, ID3_FRAME_ID_REVERB, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4206 (oscl_memcmp(aFrameID, ID3_FRAME_ID_SYNCHRONIZED_LYRICS_TEXT, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4207 (oscl_memcmp(aFrameID, ID3_FRAME_ID_SYNCHRONIZED_TEMPO_CODES, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4208 (oscl_memcmp(aFrameID, ID3_FRAME_ID_BPM, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4209 (oscl_memcmp(aFrameID, ID3_FRAME_ID_PLAYLIST_DELAY, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4210 (oscl_memcmp(aFrameID, ID3_FRAME_ID_FILE_TYPE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4211 (oscl_memcmp(aFrameID, ID3_FRAME_ID_CONTENT_GROUP_DESC, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4212 (oscl_memcmp(aFrameID, ID3_FRAME_ID_INITIAL_KEY, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4213 (oscl_memcmp(aFrameID, ID3_FRAME_ID_LANGUAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4214 (oscl_memcmp(aFrameID, ID3_FRAME_ID_MEDIA_TYPE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4215 (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_ALBUM, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4216 (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_FILENAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4217 (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_LYRICIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4218 (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_ARTIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4219 (oscl_memcmp(aFrameID, ID3_FRAME_ID_FILE_LICENSEE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4220 (oscl_memcmp(aFrameID, ID3_FRAME_ID_BAND, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4221 (oscl_memcmp(aFrameID, ID3_FRAME_ID_CONDUCTOR, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4222 (oscl_memcmp(aFrameID, ID3_FRAME_ID_MODIFIER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4223 (oscl_memcmp(aFrameID, ID3_FRAME_ID_PART_OF_SET, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4224 (oscl_memcmp(aFrameID, ID3_FRAME_ID_PUBLISHER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4225 (oscl_memcmp(aFrameID, ID3_FRAME_ID_INTERNET_RADIO_STATION_NAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4226 (oscl_memcmp(aFrameID, ID3_FRAME_ID_INTERNET_RADIO_STATION_OWNER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4227 (oscl_memcmp(aFrameID, ID3_FRAME_ID_RECORDING_CODE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4228 (oscl_memcmp(aFrameID, ID3_FRAME_ID_SOFTWARE_SETTING_ENCODE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4229 (oscl_memcmp(aFrameID, ID3_FRAME_ID_UNIQUE_FILE_IDENTIFIER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4230 (oscl_memcmp(aFrameID, ID3_FRAME_ID_TERMS_OF_USE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4231 (oscl_memcmp(aFrameID, ID3_FRAME_ID_COMMERCIAL_INFO, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4232 (oscl_memcmp(aFrameID, ID3_FRAME_ID_LEGAL_INFO, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4233 (oscl_memcmp(aFrameID, ID3_FRAME_ID_OFFICIAL_AUDIO_FILE_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4234 (oscl_memcmp(aFrameID, ID3_FRAME_ID_OFFICIAL_ARTIST_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4235 (oscl_memcmp(aFrameID, ID3_FRAME_ID_OFFICIAL_AUDIO__SOURCE_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4236 (oscl_memcmp(aFrameID, ID3_FRAME_ID_OFFICIAL_RADIO_STATION_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4237 (oscl_memcmp(aFrameID, ID3_FRAME_ID_PAYMENT, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4238 (oscl_memcmp(aFrameID, ID3_FRAME_ID_PUBLISHER_OFFICIAL_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4239 (oscl_memcmp(aFrameID, ID3_FRAME_ID_USER_DEFINED_URL_LINK_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4240 (oscl_memcmp(aFrameID, ID3_FRAME_ID_SIGNATURE_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4241 (oscl_memcmp(aFrameID, ID3_FRAME_ID_ENCODING_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4242 (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_RELEASE_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4243 (oscl_memcmp(aFrameID, ID3_FRAME_ID_RELEASE_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4244 (oscl_memcmp(aFrameID, ID3_FRAME_ID_TAGGING_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4245 (oscl_memcmp(aFrameID, ID3_FRAME_ID_INVOLVED_PEOPLE_LIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4246 (oscl_memcmp(aFrameID, ID3_FRAME_ID_MUSICIAN_CREDITS_LIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4247 (oscl_memcmp(aFrameID, ID3_FRAME_ID_MOOD, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4248 (oscl_memcmp(aFrameID, ID3_FRAME_ID_PRODUCED_NOTICE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4249 (oscl_memcmp(aFrameID, ID3_FRAME_ID_ALBUM_SORT_ORDER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4250 (oscl_memcmp(aFrameID, ID3_FRAME_ID_PERFORMER_SORT_ORDER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4251 (oscl_memcmp(aFrameID, ID3_FRAME_ID_TITLE_SORT_ORDER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4252 (oscl_memcmp(aFrameID, ID3_FRAME_ID_SET_SUBTITLE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4253 (oscl_memcmp(aFrameID, ID3_FRAME_ID_USER_DEFINED_TEXT_INFO, ID3V2_FRAME_NUM_BYTES_ID) == 0)
4254 )
4255 {
4256 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_UNRECOGNIZED;
4257 }
4258 // The frame ID made out of the characters capital A-Z and 0-9.
4259 else if (IS_POTENTIAL_FRAME_ID(aFrameID))
4260 {
4261 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_CANDIDATE;
4262 }
4263 else
4264 {
4265 // Frame ID doesn't match with defined/possible frame Ids
4266 ID3V2FrameTypeReturnValue = PV_ID3_FRAME_INVALID;
4267 }
4268 return ID3V2FrameTypeReturnValue;
4269 }
4270
PushFrameToFrameVector(PvmiKvpSharedPtr & aFrame,PvmiKvpSharedPtrVector & aFrameVector)4271 PVMFStatus PVID3ParCom::PushFrameToFrameVector(PvmiKvpSharedPtr& aFrame, PvmiKvpSharedPtrVector& aFrameVector)
4272 {
4273 int32 err = OsclErrNone;
4274 OSCL_TRY(err, aFrameVector.push_back(aFrame););
4275 OSCL_FIRST_CATCH_ANY(err,
4276 LOG_ERR((0, "PVID3ParCom::GetID3Frame: Error - aFrame.push_back failed"));
4277 return PVMFErrNoMemory;);
4278 return PVMFSuccess;
4279 }
4280
AllocateValueArray(int32 & aLeaveCode,PvmiKvpValueType aValueType,int32 aNumElements,OsclMemAllocator * aMemAllocator)4281 OsclAny* PVID3ParCom::AllocateValueArray(int32& aLeaveCode, PvmiKvpValueType aValueType, int32 aNumElements, OsclMemAllocator* aMemAllocator)
4282 {
4283 int32 leaveCode = OsclErrNone;
4284 OsclAny* buffer = NULL;
4285 switch (aValueType)
4286 {
4287 case PVMI_KVPVALTYPE_WCHARPTR:
4288 if (aMemAllocator)
4289 {
4290 OSCL_TRY(leaveCode,
4291 buffer = (oscl_wchar*) aMemAllocator->ALLOCATE(aNumElements););
4292 }
4293 else
4294 {
4295 OSCL_TRY(leaveCode,
4296 buffer = (oscl_wchar*) OSCL_ARRAY_NEW(oscl_wchar, aNumElements););
4297 }
4298 break;
4299
4300 case PVMI_KVPVALTYPE_CHARPTR:
4301 if (aMemAllocator)
4302 {
4303 OSCL_TRY(leaveCode,
4304 buffer = (char*) aMemAllocator->ALLOCATE(aNumElements););
4305 }
4306 else
4307 {
4308 OSCL_TRY(leaveCode,
4309 buffer = (char*) OSCL_ARRAY_NEW(char, aNumElements););
4310 }
4311 break;
4312 case PVMI_KVPVALTYPE_UINT8PTR:
4313 if (aMemAllocator)
4314 {
4315 OSCL_TRY(leaveCode,
4316 buffer = (uint8*) aMemAllocator->ALLOCATE(aNumElements););
4317 }
4318 else
4319 {
4320 OSCL_TRY(leaveCode,
4321 buffer = (uint8*) OSCL_ARRAY_NEW(char, aNumElements););
4322 }
4323 break;
4324 default:
4325 break;
4326 }
4327 aLeaveCode = leaveCode;
4328 return buffer;
4329 }
4330
HandleErrorForKVPAllocation(OSCL_String & aKey,PvmiKvpValueType aValueType,uint32 aValueSize,bool & truncate,PVMFStatus & aStatus)4331 PvmiKvpSharedPtr PVID3ParCom::HandleErrorForKVPAllocation(OSCL_String& aKey, PvmiKvpValueType aValueType, uint32 aValueSize, bool &truncate, PVMFStatus &aStatus)
4332 {
4333 PvmiKvpSharedPtr kvp;
4334 int32 err = OsclErrNone;
4335 aStatus = PVMFSuccess;
4336 OSCL_TRY(err, kvp = AllocateKvp(aKey, aValueType, aValueSize, truncate););
4337 if (OsclErrNone != err)
4338 {
4339 LOG_ERR((0, "PVID3ParCom::SetID3Frame: Error - AllocateKvp failed"));
4340 aStatus = PVMFErrNoMemory;
4341 }
4342 return kvp;
4343 }
4344