| /* ------------------------------------------------------------------ |
| * Copyright (C) 2008 PacketVideo |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| * express or implied. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * ------------------------------------------------------------------- |
| */ |
| /** |
| * @file pv_id3_parcom_types.cpp |
| * @brief Type definitions for ID3 Parser-Composer |
| */ |
| |
| #ifndef PV_ID3_PARCOM_H_INCLUDED |
| #include "pv_id3_parcom.h" |
| #endif |
| #ifndef PV_ID3_PARCOM_CONSTANTS_H_INCLUDED |
| #include "pv_id3_parcom_constants.h" |
| #endif |
| #ifndef OSCL_SNPRINTF_H_INCLUDED |
| #include "oscl_snprintf.h" |
| #endif |
| #ifndef PVLOGGER_H_INCLUDED |
| #include "pvlogger.h" |
| #endif |
| #ifndef PVMI_KVP_UTIL_H_INCLUDED |
| #include "pvmi_kvp_util.h" |
| #endif |
| #ifndef OSCL_MIME_STRING_UTILS_H |
| #include "pv_mime_string_utils.h" |
| #endif |
| #ifndef OSCL_DLL_H_INCLUDED |
| #include "oscl_dll.h" |
| #endif |
| |
| #define LOG_STACK_TRACE(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, m); |
| #define LOG_DEBUG(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, m); |
| #define LOG_ERR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m); |
| |
| #ifndef NULL_TERM_CHAR |
| #define NULL_TERM_CHAR '\0' |
| #endif |
| // DLL entry point |
| OSCL_DLL_ENTRY_POINT_DEFAULT() |
| |
| //////////////////////////////////////////////////////////////////////////// |
| class PVID3ParComKvpCleanupDA : public OsclDestructDealloc |
| { |
| public: |
| PVID3ParComKvpCleanupDA(Oscl_DefAlloc* in_gen_alloc) : |
| gen_alloc(in_gen_alloc) {}; |
| virtual ~PVID3ParComKvpCleanupDA() {}; |
| |
| virtual void destruct_and_dealloc(OsclAny* ptr) |
| { |
| // no need to call destructors in this case just dealloc |
| gen_alloc->deallocate(ptr); |
| } |
| |
| private: |
| Oscl_DefAlloc* gen_alloc; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF PVID3ParCom::PVID3ParCom() |
| : iInputFile(NULL), |
| iTitleFoundFlag(false), |
| iFileSizeInBytes(0), |
| iByteOffsetToStartOfAudioFrames(0), |
| iVersion(PV_ID3_INVALID_VERSION), |
| iID3V1Present(false), |
| iID3V2Present(false), |
| iUseMaxTagSize(false), |
| iMaxTagSize(0), |
| iUsePadding(false), |
| iTagAtBof(false), |
| iSeekFrameFound(false) |
| { |
| iLogger = PVLogger::GetLoggerObject("PVID3ParCom"); |
| iID3TagInfo.iID3V2ExtendedHeaderSize = 0; |
| iID3TagInfo.iID3V2FrameSize = 0; |
| iID3TagInfo.iID3V2TagFlagsV2 = 0; |
| iID3TagInfo.iID3V2TagSize = 0 ; |
| iID3TagInfo.iFooterPresent = false; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF PVID3ParCom::~PVID3ParCom() |
| { |
| iFrames.clear(); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF uint32 PVID3ParCom::GetID3TagSize(PVFile* aFile) |
| { |
| if (!aFile) |
| { |
| return 0; |
| } |
| |
| iInputFile = aFile; |
| |
| if (iInputFile->Seek(0, Oscl_File::SEEKSET) == -1) |
| { |
| iFileSizeInBytes = 0; |
| } |
| else |
| { |
| iInputFile->GetRemainingBytes((uint32&)iFileSizeInBytes); |
| if (iInputFile->Seek(0, Oscl_File::SEEKSET) == -1) |
| { |
| return 0; |
| } |
| } |
| |
| uint32 buffsize = 100; //number of bytes to search , from the end of file, to look for footer |
| if (CheckForTagID3V2() |
| || (LookForV2_4Footer(buffsize, 0) == PVMFSuccess)) |
| { |
| if (iInputFile->Seek(2, Oscl_File::SEEKCUR) == -1) |
| { |
| return 0; |
| } |
| |
| // Read and convert tag flags |
| uint8 flags = 0; |
| if (read8(iInputFile, flags) == false) |
| { |
| return 0; |
| } |
| |
| // Read and convert tag size |
| uint32 synchIntTagSize; |
| if (read32(iInputFile, synchIntTagSize) == false) |
| { |
| return 0; |
| } |
| |
| // tagSize will store the file's Id3v2 tag size |
| uint32 tagSize = SafeSynchIntToInt32(synchIntTagSize) + ID3V2_TAG_NUM_BYTES_HEADER; |
| |
| //check if footer is present |
| if ((iVersion == PV_ID3_V2_4) && (flags & FTR_FLAGMASK)) |
| tagSize += ID3V2_TAG_NUM_BYTES_HEADER; // add 10 bytes for footer |
| |
| return tagSize; |
| } |
| else |
| { |
| if (CheckForTagID3V1()) |
| { |
| return ID3V1_MAX_NUM_BYTES_TOTAL; |
| } |
| } |
| return 0; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF uint32 PVID3ParCom::GetID3TagSize() |
| { |
| uint32 composedTagSize = 0; |
| switch (iVersion) |
| { |
| case PV_ID3_V2_2: |
| case PV_ID3_V2_3: |
| case PV_ID3_V2_4: |
| { |
| composedTagSize = ID3V2_TAG_NUM_BYTES_HEADER + iID3TagInfo.iID3V2TagSize; |
| |
| if (iID3TagInfo.iFooterPresent) |
| composedTagSize += ID3V2_TAG_NUM_BYTES_HEADER; //footer is replica of Tag Header |
| } |
| break; |
| |
| case PV_ID3_V1: |
| case PV_ID3_V1_1: |
| composedTagSize = 128; // ID3v1 tag has fix size |
| break; |
| default: |
| composedTagSize = 0; |
| |
| } |
| |
| return composedTagSize; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF PVMFStatus PVID3ParCom::SetMaxID3TagSize(bool aUseMaxSize, uint32 aMaxSize, bool aUsePadding) |
| { |
| switch (iVersion) |
| { |
| case PV_ID3_V1: |
| case PV_ID3_V1_1: |
| case PV_ID3_INVALID_VERSION: |
| { |
| LOG_ERR((0, "PVID3Parcom::SetMaxID3TagSize: Error - Fix size ID3 tag")); |
| return PVMFErrNotSupported; |
| } |
| case PV_ID3_V2_2: |
| // Minimum for an ID3v2_2 tag is tag header plus 1 frame. The minimum data length of |
| // a frame is 1 byte |
| { |
| if (aUseMaxSize && aMaxSize < (ID3V2_TAG_NUM_BYTES_HEADER + ID3V2_2_FRAME_NUM_BYTES_HEADER + 1)) |
| { |
| LOG_ERR((0, "PVID3ParCom::SetMaxID3TagSize: Error - Minimum tag size is 17 bytes")); |
| return PVMFErrArgument; |
| } |
| } |
| break; |
| case PV_ID3_V2_3: |
| case PV_ID3_V2_4: |
| // Minimum for an ID3v2 tag is tag header plus 1 frame. The minimum data length of |
| // a frame is 1 byte |
| if (aUseMaxSize && aMaxSize < (ID3V2_TAG_NUM_BYTES_HEADER + ID3V2_FRAME_NUM_BYTES_HEADER + 1)) |
| { |
| LOG_ERR((0, "PVID3ParCom::SetMaxID3TagSize: Error - Minimum tag size is 21 bytes")); |
| return PVMFErrArgument; |
| } |
| } |
| |
| iUseMaxTagSize = aUseMaxSize; |
| if (iUseMaxTagSize) |
| { |
| iMaxTagSize = aMaxSize; |
| iUsePadding = aUsePadding; |
| } |
| else |
| { |
| iMaxTagSize = 0; |
| iUsePadding = false; |
| } |
| |
| return PVMFSuccess; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF PVMFStatus PVID3ParCom::ParseID3Tag(PVFile* aFile, uint32 buffsize) |
| { |
| if (!aFile) |
| { |
| return PVMFFailure; |
| } |
| |
| iInputFile = aFile; |
| |
| int32 currentFilePosn = 0; |
| |
| // SEEK TO THE END OF THE FILE AND GET FILE SIZE |
| currentFilePosn = iInputFile->Tell(); |
| if (currentFilePosn == -1) |
| { |
| return PVMFFailure; |
| } |
| |
| if (iInputFile->Seek(0, Oscl_File::SEEKSET) == -1) |
| { |
| iFileSizeInBytes = 0; |
| } |
| else |
| { |
| iInputFile->GetRemainingBytes((uint32&)iFileSizeInBytes); |
| if (iInputFile->Seek(currentFilePosn, Oscl_File::SEEKSET) == -1) |
| { |
| iInputFile = NULL; |
| return PVMFFailure; |
| } |
| } |
| |
| bool readTags = false; |
| //check for ID3 Version 2 |
| if (CheckForTagID3V2() || (LookForV2_4Footer(buffsize, 0) == PVMFSuccess)) |
| { |
| //Read the header |
| readTags = ReadHeaderID3V2(); |
| |
| //check for ID3 Version 1 |
| if (CheckForTagID3V1()) |
| { |
| if (!iTitleFoundFlag) |
| { |
| //Read the header |
| ReadID3V1Tag(true); |
| } |
| } |
| if (iInputFile->Seek(currentFilePosn, Oscl_File::SEEKSET) == -1) |
| { |
| iInputFile = NULL; |
| return PVMFFailure; |
| } |
| } |
| if (!readTags && CheckForTagID3V1()) |
| { |
| //check for ID3 Version 1 |
| iVersion = PV_ID3_V1; |
| //Read the header |
| ReadID3V1Tag(false); |
| |
| iByteOffsetToStartOfAudioFrames = 0; |
| if (iInputFile->Seek(currentFilePosn, Oscl_File::SEEKSET) == -1) |
| { |
| iInputFile = NULL; |
| return PVMFFailure; |
| } |
| } |
| else if (!readTags) |
| { |
| //Neither ID3V1 nor ID3V2 are present |
| return PVMFFailure; |
| } |
| |
| iInputFile = NULL; |
| return PVMFSuccess; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF PVID3Version PVID3ParCom::GetID3Version() const |
| { |
| return iVersion; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF bool PVID3ParCom::IsID3V1Present() const |
| { |
| return iID3V1Present; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF bool PVID3ParCom::IsID3V2Present() const |
| { |
| return iID3V2Present; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF PVMFStatus PVID3ParCom::GetID3Frames(PvmiKvpSharedPtrVector& aFrames) |
| { |
| aFrames = iFrames; |
| return PVMFSuccess; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF PVMFStatus PVID3ParCom::GetID3Frame(const OSCL_String& aFrameType, PvmiKvpSharedPtrVector& aFrame) |
| { |
| uint32 i; |
| int32 err = 0; |
| for (i = 0; i < iFrames.size(); i++) |
| { |
| if (pv_mime_strcmp(iFrames[i]->key, aFrameType.get_str()) == 0) |
| { |
| OSCL_TRY(err, aFrame.push_back(iFrames[i]);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::GetID3Frame: Error - aFrame.push_back failed")); |
| return PVMFErrNoMemory; |
| ); |
| } |
| } |
| |
| return PVMFSuccess; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF bool PVID3ParCom::IsID3FrameAvailable(const OSCL_String& aFrameType) |
| { |
| uint32 i; |
| for (i = 0; i < iFrames.size(); i++) |
| { |
| if (pv_mime_strcmp(iFrames[i]->key, aFrameType.get_str()) == 0) |
| { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF PVMFStatus PVID3ParCom::SetID3Version(PVID3Version aVersion) |
| { |
| iVersion = aVersion; |
| return PVMFSuccess; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF PVMFStatus PVID3ParCom::SetID3Frame(const PvmiKvp& aFrame) |
| { |
| uint32 i; |
| OSCL_StackString<4> frameID; |
| PVID3FrameType newFrameType; |
| PVID3FrameType existingFrameType; |
| PVMFStatus status = PVMFSuccess; |
| |
| // Find an existing entry in iFrames with matching frame type |
| status = GetFrameTypeFromKvp(aFrame, frameID, newFrameType); |
| for (i = 0; status == PVMFSuccess && i < iFrames.size(); i++) |
| { |
| status = GetFrameTypeFromKvp(iFrames[i], frameID, existingFrameType); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::SetID3Frame: Error - GetFrameTypeFromKvp failed")); |
| break; |
| } |
| if (existingFrameType == newFrameType) |
| { |
| iFrames.erase(iFrames.begin() + i); |
| break; |
| } |
| |
| } |
| |
| if (status != PVMFSuccess) |
| { |
| return status; |
| } |
| |
| PvmiKvpValueType kvpValueType = GetValTypeFromKeyString(aFrame.key); |
| OSCL_StackString<128> key = _STRLIT_CHAR(aFrame.key); |
| uint32 valueSize = 0; |
| uint32 valueStrLen = 0; |
| switch (kvpValueType) |
| { |
| case PVMI_KVPVALTYPE_CHARPTR: |
| valueStrLen = oscl_strlen(aFrame.value.pChar_value); |
| valueSize = valueStrLen + 1; |
| break; |
| case PVMI_KVPVALTYPE_WCHARPTR: |
| valueStrLen = oscl_strlen(aFrame.value.pWChar_value); |
| valueSize = (valueStrLen + 2) * sizeof(oscl_wchar); |
| break; |
| case PVMI_KVPVALTYPE_KSV: |
| // Comment field |
| break; |
| case PVMI_KVPVALTYPE_UINT32: |
| valueSize = 0; |
| break; |
| default: |
| return PVMFErrNotSupported; |
| } |
| |
| int32 err = 0; |
| PvmiKvpSharedPtr kvp; |
| bool truncate = false; |
| OSCL_TRY(err, kvp = AllocateKvp(key, kvpValueType, valueSize, truncate);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::SetID3Frame: Error - AllocateKvp failed")); |
| return PVMFErrNoMemory; |
| ); |
| if (truncate) |
| return PVMFErrNoMemory; |
| |
| switch (kvpValueType) |
| { |
| case PVMI_KVPVALTYPE_CHARPTR: |
| oscl_strncpy(kvp->value.pChar_value, aFrame.value.pChar_value, valueStrLen); |
| kvp->value.pChar_value[valueStrLen] = NULL_TERM_CHAR; |
| break; |
| case PVMI_KVPVALTYPE_WCHARPTR: |
| oscl_strncpy(kvp->value.pWChar_value, aFrame.value.pWChar_value, valueStrLen); |
| kvp->value.pWChar_value[valueStrLen] = NULL_TERM_CHAR; |
| break; |
| case PVMI_KVPVALTYPE_KSV: |
| // Comment field |
| break; |
| case PVMI_KVPVALTYPE_UINT32: |
| kvp->value.uint32_value = aFrame.value.uint32_value; |
| break; |
| default: |
| return PVMFErrNotSupported; |
| } |
| |
| OSCL_TRY(err, iFrames.push_back(kvp);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::SetID3Frame: Error - iFrames.push_back() failed")); |
| return PVMFErrNoMemory; |
| ); |
| |
| return PVMFSuccess; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF PVMFStatus PVID3ParCom::RemoveID3Frame(const OSCL_String& aFrameType) |
| { |
| uint32 i; |
| for (i = 0; i < iFrames.size(); i++) |
| { |
| if (pv_mime_strcmp(iFrames[i]->key, aFrameType.get_str()) == 0) |
| { |
| iFrames.erase(iFrames.begin() + i); |
| return PVMFSuccess; |
| } |
| } |
| |
| // Frame of specified type is not found |
| return PVMFErrArgument; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF PVMFStatus PVID3ParCom::ComposeID3Tag(OsclRefCounterMemFrag& aTag) |
| { |
| switch (iVersion) |
| { |
| case PV_ID3_V2_2: |
| case PV_ID3_V2_3: |
| case PV_ID3_V2_4: |
| return ComposeID3v2Tag(aTag); |
| default: |
| return PVMFErrNotSupported; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| OSCL_EXPORT_REF PVMFStatus PVID3ParCom::Reset() |
| { |
| iFrames.clear(); |
| return PVMFSuccess; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| bool PVID3ParCom::CheckForTagID3V1() |
| { |
| uint8 tagHeader[ID3V1_TAG_NUM_BYTES_HEADER+1] = {0}; |
| |
| // Make sure file is big enough to contain a tag |
| if (iFileSizeInBytes >= ID3V1_MAX_NUM_BYTES_TOTAL) |
| { |
| uint32 nBytes = 0; |
| // Read the value at the tag position |
| |
| nBytes = iFileSizeInBytes - ID3V1_MAX_NUM_BYTES_TOTAL; |
| if (iInputFile->Seek(nBytes, Oscl_File::SEEKSET) == -1) |
| { |
| return false; |
| } |
| |
| |
| if (!readByteData(iInputFile, ID3V1_TAG_NUM_BYTES_HEADER, tagHeader)) |
| { |
| return false; |
| } |
| |
| // Read in ID3 Tags at the front of the file. |
| if (oscl_memcmp(ID3_V1_IDENTIFIER, tagHeader, ID3V1_TAG_NUM_BYTES_HEADER) == 0) |
| { |
| iID3V1Present = true; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| bool PVID3ParCom::CheckForTagID3V2() |
| { |
| uint8 id3Header[ID3V2_TAG_NUM_BYTES_HEADER+1] = {0}; |
| |
| if (!readByteData(iInputFile, ID3V2_TAG_NUM_BYTES_ID, id3Header)) |
| { |
| return false; |
| } |
| |
| // Read in ID3 Tags at the front of the file. |
| if (oscl_memcmp(ID3_V2_IDENTIFIER, id3Header, ID3V2_TAG_NUM_BYTES_ID) == 0) |
| { |
| iTagAtBof = true; |
| iID3V2Present = true; |
| return true; |
| } |
| return false; |
| } |
| |
| OSCL_EXPORT_REF bool PVID3ParCom::IsID3V2Present(PVFile* aFile, uint32& aTagSize) |
| { |
| iInputFile = aFile; |
| |
| if (iID3V2Present) |
| { |
| // if id3 tag has already been discovered, just return the tag size |
| aTagSize = iByteOffsetToStartOfAudioFrames; |
| return true; |
| } |
| |
| if (CheckForTagID3V2()) |
| { |
| // we dont want to parse the id3 frames, just read the id3 header |
| |
| ReadHeaderID3V2(false); |
| aTagSize = iByteOffsetToStartOfAudioFrames; |
| return true; |
| } |
| return false; |
| } |
| |
| OSCL_EXPORT_REF PVMFStatus PVID3ParCom::LookForV2_4Footer(uint32 aBuffSz, uint32 aFileOffset) |
| { |
| if (iTagAtBof) //already found tag. no need to search from the end. |
| return PVMFFailure; |
| |
| uint32 footer_location = SearchTagV2_4(aBuffSz, aFileOffset); |
| |
| if (footer_location == 0) |
| return PVMFFailure; |
| |
| if (iInputFile->Seek(footer_location + ID3V2_TAG_NUM_BYTES_ID + ID3V2_TAG_NUM_BYTES_VERSION + ID3V2_TAG_NUM_BYTES_FLAG, |
| Oscl_File::SEEKSET) == -1) |
| { |
| return PVMFFailure; |
| } |
| |
| uint32 tag_size = 0, size = 0; |
| |
| if (read32(iInputFile, size) == false) |
| { |
| return PVMFFailure; |
| } |
| |
| tag_size = SafeSynchIntToInt32(size); |
| |
| if (iInputFile->Seek(-(int32)(tag_size + 1 + ID3V2_TAG_NUM_BYTES_HEADER + (ID3V2_TAG_NUM_BYTES_HEADER - ID3V2_TAG_NUM_BYTES_ID)), |
| Oscl_File::SEEKCUR) == -1) |
| { |
| return PVMFFailure; |
| } |
| |
| return PVMFSuccess; |
| } |
| //////////////////////////////////////////////////////////////////////////// |
| // (if an error is detected, this returns 0) |
| |
| uint32 PVID3ParCom::SearchTagV2_4(uint32 aBuffSz, uint32 aFileOffset) |
| { |
| |
| if (iFileSizeInBytes == 0) |
| return 0; |
| |
| uint8 *buff = (uint8 *)oscl_malloc(aBuffSz); |
| if (! buff) // malloc might fail |
| return 0; |
| |
| int remaining_bytes = 0; |
| |
| int num_bytes_read = aBuffSz + aFileOffset; |
| |
| //in case we have almost reached to the begining of file, |
| //and remaining bytes are less than the buffer size, |
| //look for ID3 tag in the remaining bytes only. |
| |
| if (num_bytes_read > iFileSizeInBytes) |
| remaining_bytes = iFileSizeInBytes - (num_bytes_read - aBuffSz); |
| |
| if (remaining_bytes > 0) |
| { |
| |
| if (iInputFile->Seek(0 , Oscl_File::SEEKSET) == -1) |
| { |
| oscl_free(buff); |
| return 0; |
| } |
| |
| if (readByteData(iInputFile, remaining_bytes, buff) == false) |
| { |
| oscl_free(buff); |
| return 0; |
| } |
| |
| for (int i = 0; i < remaining_bytes;i++) |
| { |
| if (oscl_memcmp(buff + i, ID3_V2_4_TAG_FOOTER, ID3V2_TAG_NUM_BYTES_ID) == 0) |
| { |
| oscl_free(buff); |
| return i; |
| } |
| |
| } |
| |
| oscl_free(buff); |
| return 0; |
| } |
| else |
| { |
| |
| if (iInputFile->Seek((iFileSizeInBytes - (aFileOffset + aBuffSz)), Oscl_File::SEEKSET) == -1) |
| { |
| oscl_free(buff); |
| return 0; |
| } |
| |
| if (readByteData(iInputFile, aBuffSz, buff) == false) |
| { |
| oscl_free(buff); |
| return 0; |
| } |
| |
| for (uint i = 0; i < aBuffSz;i++) |
| { |
| if (oscl_memcmp(buff + i, ID3_V2_4_TAG_FOOTER, ID3V2_TAG_NUM_BYTES_ID) == 0) |
| { |
| oscl_free(buff); |
| return ((iFileSizeInBytes - ((aFileOffset + aBuffSz) - i))); |
| } |
| |
| } |
| |
| } |
| |
| oscl_free(buff); |
| return 0; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| void PVID3ParCom::ReadID3V1Tag(bool aTitleOnlyFlag) |
| { |
| PVMFStatus status = PVMFSuccess; |
| bool truncate = false; |
| status = ReadStringValueFrame(PV_ID3_FRAME_TITLE, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_TITLE); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for title")); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| |
| iTitleFoundFlag = true; |
| if (aTitleOnlyFlag) |
| { |
| return; |
| } |
| |
| status = ReadStringValueFrame(PV_ID3_FRAME_ARTIST, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_ARTIST); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for artist")); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| |
| status = ReadStringValueFrame(PV_ID3_FRAME_ALBUM, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_ALBUM); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for album")); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| |
| status = ReadStringValueFrame(PV_ID3_FRAME_YEAR, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_YEAR); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for year")); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| |
| // Read and convert comment & track number |
| uint8* frameData = NULL; |
| uint32 frameDataSize = ID3V1_MAX_NUM_BYTES_FIELD_SIZE + 1; |
| int32 err = 0; |
| OSCL_TRY(err, frameData = (uint8*)iAlloc.ALLOCATE(frameDataSize);); |
| if (err != OsclErrNone || !frameData) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - Out of memory")); |
| OSCL_LEAVE(OsclErrNoMemory); |
| } |
| oscl_memset(frameData, 0, frameDataSize); |
| |
| if (readByteData(iInputFile, ID3V1_MAX_NUM_BYTES_COMMENT, frameData) == false) |
| { |
| iAlloc.deallocate(frameData); |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - readByteData failed")); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| |
| OSCL_StackString<128> keyStr; |
| PvmiKvpSharedPtr kvpPtr; |
| if (frameData[ID3V1_MAX_NUM_BYTES_COMMENT-2] == 0 && |
| frameData[ID3V1_MAX_NUM_BYTES_COMMENT-1] != 0) |
| { |
| // This would mean its an ID3v1.1 tag and hence has the |
| // the track number also, so extract it |
| iVersion = PV_ID3_V1_1; |
| |
| if (ConstructKvpKey(keyStr, PV_ID3_FRAME_TRACK_NUMBER, PV_ID3_CHARSET_INVALID) != PVMFSuccess) |
| { |
| iAlloc.deallocate(frameData); |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - ConstructKvpKey failed for tracknumber")); |
| OSCL_LEAVE(OsclErrNotSupported); |
| } |
| |
| // Allocate key-value pair |
| OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_UINT32, 0, truncate);); |
| |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - AllocateKvp failed. err=%d", err)); |
| iAlloc.deallocate(frameData); |
| OSCL_LEAVE(OsclErrNoMemory); |
| return; |
| ); |
| |
| if (!truncate) |
| kvpPtr->value.uint32_value = (uint32)frameData[ID3V1_MAX_NUM_BYTES_COMMENT - 1]; |
| |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - iFrame.push_back failed")); |
| iAlloc.deallocate(frameData); |
| OSCL_LEAVE(OsclErrNoMemory); |
| return; |
| ); |
| } |
| |
| // Comment frame |
| frameData[ID3V1_MAX_NUM_BYTES_COMMENT] = 0; |
| if (ConstructKvpKey(keyStr, PV_ID3_FRAME_COMMENT, PV_ID3_CHARSET_ISO88591) != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - ConstructKvpKey failed for tracknumber")); |
| iAlloc.deallocate(frameData); |
| OSCL_LEAVE(OsclErrNotSupported); |
| } |
| |
| uint32 dataSize = ID3V1_MAX_NUM_BYTES_COMMENT + 1; |
| // Allocate key-value pair |
| OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, dataSize, truncate);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - AllocateKvp failed. err=%d", err)); |
| iAlloc.deallocate(frameData); |
| OSCL_LEAVE(OsclErrNoMemory); |
| return; |
| ); |
| |
| if (!truncate) |
| oscl_strncpy(kvpPtr->value.pChar_value, (char *)frameData, dataSize) ; |
| |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - iFrame.push_back failed")); |
| iAlloc.deallocate(frameData); |
| return ; |
| ); |
| |
| // Genre frame |
| oscl_memset(frameData, 0, frameDataSize); |
| if (readByteData(iInputFile, ID3V1_MAX_NUM_BYTES_GENRE, frameData) == false) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - readByteData failed")); |
| iAlloc.deallocate(frameData); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| |
| if (ConstructKvpKey(keyStr, PV_ID3_FRAME_GENRE, PV_ID3_CHARSET_INVALID) != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - ConstructKvpKey failed for genre")); |
| iAlloc.deallocate(frameData); |
| OSCL_LEAVE(OsclErrNotSupported); |
| } |
| |
| OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_UINT32, 0, truncate);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - AllocateKvp failed. err=%d", err)); |
| iAlloc.deallocate(frameData); |
| OSCL_LEAVE(OsclErrNoMemory); |
| return; |
| ); |
| |
| if (!truncate) |
| kvpPtr->value.uint32_value = (uint32)(frameData[ID3V1_MAX_NUM_BYTES_GENRE - 1]); |
| |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - iFrame.push_back failed")); |
| iAlloc.deallocate(frameData); |
| OSCL_LEAVE(OsclErrNoMemory); |
| return; |
| ); |
| iAlloc.deallocate(frameData); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| bool PVID3ParCom::ReadHeaderID3V2(bool aReadTags) |
| { |
| bool result = false; |
| |
| // Read and convert tag versions, Major and Minor |
| uint8 ID3V2MajorVer, ID3V2MinorVer; |
| if (read8(iInputFile, ID3V2MajorVer) == false) |
| { |
| return false; |
| } |
| if (read8(iInputFile, ID3V2MinorVer) == false) |
| { |
| return false; |
| } |
| |
| switch (ID3V2MajorVer) |
| { |
| case PV_ID3_V2_2: |
| iVersion = PV_ID3_V2_2; |
| break; |
| case PV_ID3_V2_3: |
| iVersion = PV_ID3_V2_3; |
| break; |
| case PV_ID3_V2_4: |
| iVersion = PV_ID3_V2_4; |
| break; |
| } |
| |
| BEGIN_V2: |
| // Read and convert tag flags |
| if (read8(iInputFile, iID3TagInfo.iID3V2TagFlagsV2) == false) |
| { |
| return false; |
| } |
| |
| uint32 tagsize = 0; |
| |
| // Read and convert tag size |
| if (read32(iInputFile, tagsize) == false) |
| { |
| return false; |
| } |
| |
| // Now check if an extended header exists |
| bool extHeaderFlag = false; |
| if (iID3TagInfo.iID3V2TagFlagsV2 & EXT_FLAGMASK) |
| { |
| if (iVersion == PV_ID3_V2_2) |
| { |
| // Since no compression scheme has been decided yet, just ignore the entire tag |
| LOG_ERR((0, "PVID3ParCom::ReadHeaderID3V2(): Error - cannot process a compressed tag")); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| |
| extHeaderFlag = true; |
| //read extended header data |
| if (!ReadExtendedHeader()) |
| return false; |
| } |
| |
| //check if footer is present. |
| if (iID3TagInfo.iID3V2TagFlagsV2 & FTR_FLAGMASK) |
| { |
| iID3TagInfo.iFooterPresent = true; |
| } |
| |
| // tagSize will store the file's Id3v2 tag size |
| iID3TagInfo.iID3V2TagSize = SafeSynchIntToInt32(tagsize); |
| |
| //calculate start of audio frame. |
| if (iTagAtBof) |
| { |
| // set iByteOffsetToStartOfAudioFrames and it must account for the frame header |
| iByteOffsetToStartOfAudioFrames = |
| iID3TagInfo.iID3V2TagSize + ID3V2_TAG_NUM_BYTES_HEADER; |
| |
| if (iID3TagInfo.iFooterPresent) |
| iByteOffsetToStartOfAudioFrames += ID3V2_TAG_NUM_BYTES_HEADER; //header & footer are of same size. |
| } |
| else |
| { |
| iByteOffsetToStartOfAudioFrames = 0; |
| } |
| |
| // Header read is completed, now check whether we need to read the tags or not |
| if (!aReadTags) |
| { |
| return false; |
| } |
| else |
| { |
| int count = ReadTagID3V2(iVersion); |
| if (count > 0) |
| { |
| // we found some tags |
| result = true; |
| } |
| |
| if (iSeekFrameFound) |
| { |
| //jump to the new tag location skipping 5 bytes of tag ID and version. |
| uint32 seek_size = iID3TagInfo.iID3V2TagSize + ID3V2_TAG_NUM_BYTES_HEADER + (iID3TagInfo.iFooterPresent ? ID3V2_TAG_NUM_BYTES_HEADER : 0); |
| if (iInputFile->Seek(seek_size, Oscl_File::SEEKSET) == -1) |
| { |
| return false; |
| } |
| |
| //skip 5 bytes of tag ID and version. |
| if (iInputFile->Seek(iID3TagInfo.iID3V2SeekOffset, Oscl_File::SEEKCUR) == -1) |
| { |
| return false; |
| } |
| |
| if (!CheckForTagID3V2()) |
| return false; |
| |
| if (read8(iInputFile, ID3V2MajorVer) == false) |
| { |
| return false; |
| } |
| |
| if (read8(iInputFile, ID3V2MinorVer) == false) |
| { |
| return false; |
| } |
| |
| if (ID3V2MajorVer != PV_ID3_V2_4) |
| return false; |
| |
| //parse new tag, located at the seek offset. |
| iSeekFrameFound = false; |
| goto BEGIN_V2; |
| } |
| } |
| return result; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////// |
| bool PVID3ParCom::ReadExtendedHeader() |
| { |
| |
| uint32 extsize = 0; |
| if (read32(iInputFile, extsize) == false) |
| { |
| return false; |
| } |
| |
| // Calculate the length of the extended header. |
| iID3TagInfo.iID3V2ExtendedHeaderSize = SafeSynchIntToInt32(extsize); |
| |
| |
| if (iVersion == PV_ID3_V2_4) |
| { |
| //subtract "ext hdr size" field size from the header size. |
| iID3TagInfo.iID3V2ExtendedHeaderSize = iID3TagInfo.iID3V2ExtendedHeaderSize - ID3V2_TAG_EXTENDED_HEADER_SIZE; |
| |
| //check if this tag is an update of previous tag. |
| uint8 flgsize = 0, exthdrflg = 0; |
| // Read and ext hdr flg size tag flags |
| if (read8(iInputFile, flgsize) == false) |
| { |
| return false; |
| } |
| if (flgsize > 0x01) //flg size should be 1 byte in V2.4 |
| return false ; |
| // Read tag flags |
| if (read8(iInputFile, exthdrflg) == false) |
| { |
| return false; |
| } |
| //if this tag is not an update flag, ignore any tag found before this one |
| if (!(exthdrflg & EXTHDR_UPDMASK) && (iFrames.size() > 0)) |
| { |
| while (iFrames.size() > 0) |
| iFrames.pop_back(); |
| } |
| |
| //subtract 2 bytes for flg size and flg from ext hdr size. |
| iID3TagInfo.iID3V2ExtendedHeaderSize = iID3TagInfo.iID3V2ExtendedHeaderSize - 2; |
| } |
| |
| if (iVersion == PV_ID3_V2_3) |
| { |
| //V2.3 extended hdr size field does not include 6 byte size of the header |
| iID3TagInfo.iID3V2ExtendedHeaderSize += ID3V2_TAG_EXTENDED_HEADER_TOTAL_SIZE; |
| } |
| |
| return true; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////// |
| int PVID3ParCom::ReadTagID3V2(PVID3Version aVersion) |
| { |
| PVID3FrameType frameType; |
| uint32 i = 0; |
| uint32 currFrameLength; |
| uint32 current_file_pos = iInputFile->Tell(); |
| uint32 count = 0; |
| |
| if (iID3TagInfo.iID3V2ExtendedHeaderSize > 0) |
| i += iID3TagInfo.iID3V2ExtendedHeaderSize ; |
| |
| while (i <= (iID3TagInfo.iID3V2TagSize)) |
| { |
| // Read the frame header |
| if (iInputFile->Seek(current_file_pos + i, Oscl_File::SEEKSET) == -1) |
| { |
| return count; |
| } |
| |
| ReadFrameHeaderID3V2(aVersion); |
| |
| currFrameLength = 0; |
| currFrameLength = iID3TagInfo.iID3V2FrameSize; |
| frameType = FrameSupportedID3V2(aVersion); |
| |
| if ((frameType != PV_ID3_FRAME_SEEK) && (currFrameLength > iID3TagInfo.iID3V2TagSize)) |
| { |
| break; |
| } |
| // handle the frame header |
| |
| uint32 frame_header_size = 0; |
| if (aVersion == PV_ID3_V2_2) |
| frame_header_size = ID3V2_2_FRAME_NUM_BYTES_HEADER; |
| else |
| frame_header_size = ID3V2_FRAME_NUM_BYTES_HEADER; |
| |
| |
| if ((currFrameLength == 0) && (frameType != PV_ID3_FRAME_EEND)) |
| { |
| i += frame_header_size; |
| continue; |
| } |
| if (aVersion == PV_ID3_V2_3) |
| { |
| if (iID3TagInfo.iID3V2FrameFlag[1] & ENCR_COMP_3_FLAGMASK) |
| frameType = PV_ID3_FRAME_UNSUPPORTED; |
| |
| |
| } |
| else if (aVersion == PV_ID3_V2_4) |
| { |
| if (iID3TagInfo.iID3V2FrameFlag[1] & ENCR_COMP_4_FLAGMASK) |
| frameType = PV_ID3_FRAME_UNSUPPORTED; |
| } |
| |
| if (frameType == PV_ID3_FRAME_SEEK) |
| { |
| iSeekFrameFound = true; |
| iID3TagInfo.iID3V2SeekOffset = iID3TagInfo.iID3V2FrameSize; |
| return count; |
| } |
| |
| if (((currFrameLength > 1) && (frameType != PV_ID3_FRAME_UNSUPPORTED))) |
| { |
| uint8 unicodeCheck; |
| |
| if (read8(iInputFile, unicodeCheck) == false) |
| { |
| return count; |
| } |
| |
| if ((frameType == PV_ID3_FRAME_LYRICS) || (frameType == PV_ID3_FRAME_COMMENT)) |
| { |
| ReadLyricsCommFrame(unicodeCheck, currFrameLength - 1, frameType); |
| |
| } |
| else if ((frameType == PV_ID3_FRAME_APIC) || (frameType == PV_ID3_FRAME_PIC)) |
| { |
| if (ReadAlbumArtFrame(frameType, unicodeCheck, currFrameLength) != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadTagID3V2: Error - ReadAPICFrame failed")); |
| |
| return count; |
| } |
| |
| } |
| else if (unicodeCheck < PV_ID3_CHARSET_END) |
| { |
| |
| if (!ReadFrameData(unicodeCheck, frameType, |
| current_file_pos + i + frame_header_size + 1 , |
| currFrameLength)) |
| { |
| return count; |
| } |
| } |
| else |
| { |
| // This case is when no text type is defined in the frame. |
| HandleID3V2FrameDataASCII(frameType, i + frame_header_size, |
| currFrameLength); |
| |
| } |
| count++; |
| } |
| else |
| { |
| if (frameType == PV_ID3_FRAME_EEND) |
| { |
| i = iID3TagInfo.iID3V2TagSize + 1; |
| } |
| else if (frameType == PV_ID3_FRAME_UNSUPPORTED) |
| { |
| if (i < iID3TagInfo.iID3V2TagSize) |
| { |
| HandleID3V2FrameUnsupported(frameType, |
| current_file_pos + i, |
| currFrameLength + frame_header_size); |
| } |
| |
| |
| |
| } |
| } |
| |
| i += currFrameLength + frame_header_size; |
| } |
| |
| return count; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////// |
| bool PVID3ParCom::ReadFrameData(uint8 unicodeCheck, PVID3FrameType frameType, uint32 pos, uint32 currFrameLength) |
| { |
| |
| if (unicodeCheck == PV_ID3_CHARSET_ISO88591) |
| { |
| // This frame contains normal ASCII text strings. (ISO-8859-1) |
| iID3TagInfo.iTextType = PV_ID3_CHARSET_ISO88591; |
| HandleID3V2FrameDataASCII(frameType, pos, currFrameLength - 1); |
| } |
| else if (unicodeCheck == PV_ID3_CHARSET_UTF16) |
| { |
| uint16 endianCheck; |
| |
| if (read16(iInputFile, endianCheck) == false) |
| { |
| return false; |
| } |
| |
| // This frame's text strings are Unicode and the frame |
| // does include a BOM value. (UTF-16) |
| iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16; |
| uint32 endianType; |
| if (endianCheck == UNICODE_LITTLE_ENDIAN_INDICATOR_FULL) |
| { |
| endianType = UNICODE_LITTLE_ENDIAN; |
| } |
| else if (endianCheck == UNICODE_BIG_ENDIAN_INDICATOR_FULL) |
| { |
| endianType = UNICODE_BIG_ENDIAN; |
| } |
| else |
| { |
| return false; |
| } |
| |
| // value of 2 is for BOM Character |
| HandleID3V2FrameDataUnicode16(frameType, pos + 2, currFrameLength - 3, endianType); |
| } |
| else if (unicodeCheck == PV_ID3_CHARSET_UTF16BE) |
| { |
| // This frame's text strings are Unicode but the frame |
| // does not contain a BOM(byte order mark) (UTF-16BE) |
| iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16BE; |
| // Default ID3V2 endian type to Big Endian |
| uint32 endianType = UNICODE_BIG_ENDIAN; |
| // Big Endian is assumed since the frame did not specify the endian type. |
| HandleID3V2FrameDataUnicode16(frameType, pos, currFrameLength - 1, endianType); |
| } |
| else if (unicodeCheck == PV_ID3_CHARSET_UTF8) |
| { |
| // This frame's text strings are Unicode (UTF-8) |
| iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF8; |
| HandleID3V2FrameDataUTF8(frameType, pos, currFrameLength - 1); |
| } |
| |
| |
| return true; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| void PVID3ParCom::ReadFrameHeaderID3V2(PVID3Version aVersion) |
| { |
| if (aVersion == PV_ID3_V2_2) |
| { |
| ReadFrameHeaderID3V2_2(); |
| } |
| else |
| { |
| if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_ID, iID3TagInfo.iID3V2FrameID) == false) |
| { |
| return; |
| } |
| iID3TagInfo.iID3V2FrameID[ID3V2_FRAME_NUM_BYTES_ID] = 0; |
| if (read32(iInputFile, iID3TagInfo.iID3V2FrameSize) == false) |
| { |
| return; |
| } |
| if (aVersion == PV_ID3_V2_4) |
| { |
| iID3TagInfo.iID3V2FrameSize = SafeSynchIntToInt32(iID3TagInfo.iID3V2FrameSize); |
| } |
| if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_FLAG, iID3TagInfo.iID3V2FrameFlag) == false) |
| { |
| return; |
| } |
| } |
| return; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| void PVID3ParCom::ReadFrameHeaderID3V2_2() |
| { |
| if (readByteData(iInputFile, ID3V2_2_FRAME_NUM_BYTES_ID, iID3TagInfo.iID3V2FrameID) == false) |
| { |
| return; |
| } |
| iID3TagInfo.iID3V2FrameID[ID3V2_2_FRAME_NUM_BYTES_ID] = 0; |
| if (read24(iInputFile, iID3TagInfo.iID3V2FrameSize) == false) |
| { |
| return; |
| } |
| |
| return; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| void PVID3ParCom::HandleID3V2FrameDataASCII(PVID3FrameType aFrameType, |
| uint32 aPos, |
| uint32 aSize) |
| { |
| OSCL_StackString<128> keyStr; |
| PvmiKvpSharedPtr kvpPtr; |
| PVMFStatus status = PVMFSuccess; |
| if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1) |
| { |
| LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - iInputFile->Seek failed")); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| |
| switch (aFrameType) |
| { |
| case PV_ID3_FRAME_TRACK_LENGTH: |
| status = ReadTrackLengthFrame(aSize); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - ReadTrackLengthFrame failed. status=%d", status)); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| break; |
| case PV_ID3_FRAME_TITLE: |
| case PV_ID3_FRAME_ARTIST: |
| case PV_ID3_FRAME_ALBUM: |
| case PV_ID3_FRAME_YEAR: |
| case PV_ID3_FRAME_TRACK_NUMBER: |
| case PV_ID3_FRAME_GENRE: |
| case PV_ID3_FRAME_COPYRIGHT: |
| case PV_ID3_FRAME_DATE: |
| case PV_ID3_FRAME_RECORDING_TIME: |
| //new frames support |
| case PV_ID3_FRAME_AUTHOR: |
| case PV_ID3_FRAME_COMPOSER: |
| case PV_ID3_FRAME_DESCRIPTION: |
| case PV_ID3_FRAME_VERSION: |
| case PV_ID3_FRAME_PART_OF_SET: |
| |
| status = ReadStringValueFrame(aFrameType, PV_ID3_CHARSET_ISO88591, aSize); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - ReadStringValueFrame failed. status=%d", status)); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| if (aFrameType == PV_ID3_FRAME_TITLE) |
| iTitleFoundFlag = true; |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| void PVID3ParCom::HandleID3V2FrameUnsupported(PVID3FrameType aFrameType, |
| uint32 aPos, |
| uint32 aSize) |
| { |
| OSCL_StackString<128> keyStr; |
| PvmiKvpSharedPtr kvpPtr; |
| PVMFStatus status = PVMFSuccess; |
| if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1) |
| { |
| LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - iInputFile->Seek failed")); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| |
| status = ReadFrame(aFrameType, aSize); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - ReadStringValueFrame failed. status=%d", status)); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| void PVID3ParCom::HandleID3V2FrameDataUnicode16(PVID3FrameType aFrameType, |
| uint32 aPos, |
| uint32 aSize, |
| uint32 aEndianType) |
| { |
| // seek to the beginning of the current frame data |
| if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1) |
| { |
| LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUnicode16: Error - iInputFile->Seek failed")); |
| OSCL_LEAVE(OsclErrGeneral); |
| return; |
| } |
| |
| PVMFStatus status = PVMFSuccess; |
| PVID3CharacterSet charSet; |
| if (aEndianType == UNICODE_BIG_ENDIAN) |
| charSet = PV_ID3_CHARSET_UTF16BE; |
| else |
| charSet = PV_ID3_CHARSET_UTF16; |
| |
| switch (aFrameType) |
| { |
| |
| case PV_ID3_FRAME_TRACK_LENGTH: |
| //is a numeric string and does not depend on text encoding. |
| status = ReadTrackLengthFrame(aSize); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUnicode16: Error - ReadTrackLengthFrame failed. status=%d", status)); |
| OSCL_LEAVE(OsclErrGeneral); |
| return; |
| } |
| break; |
| case PV_ID3_FRAME_TITLE: |
| case PV_ID3_FRAME_ARTIST: |
| case PV_ID3_FRAME_ALBUM: |
| case PV_ID3_FRAME_YEAR: |
| case PV_ID3_FRAME_TRACK_NUMBER: |
| case PV_ID3_FRAME_GENRE: |
| case PV_ID3_FRAME_COPYRIGHT: |
| case PV_ID3_FRAME_DATE: |
| case PV_ID3_FRAME_RECORDING_TIME: |
| //new frames support |
| case PV_ID3_FRAME_AUTHOR: |
| case PV_ID3_FRAME_COMPOSER: |
| case PV_ID3_FRAME_DESCRIPTION: |
| case PV_ID3_FRAME_VERSION: |
| case PV_ID3_FRAME_PART_OF_SET: |
| |
| status = ReadStringValueFrame(aFrameType, charSet, aSize); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUnicode16: Error - ReadStringValueFrame failed. status=%d", status)); |
| OSCL_LEAVE(OsclErrGeneral); |
| return; |
| } |
| if (aFrameType == PV_ID3_FRAME_TITLE) |
| iTitleFoundFlag = true; |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| void PVID3ParCom::HandleID3V2FrameDataUTF8(PVID3FrameType aFrameType, |
| uint32 aPos, |
| uint32 aSize) |
| { |
| if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1) |
| { |
| LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUTF8: Error - iInputFile->Seek failed")); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| |
| PVMFStatus status = PVMFSuccess; |
| switch (aFrameType) |
| { |
| |
| case PV_ID3_FRAME_TRACK_LENGTH: |
| status = ReadTrackLengthFrame(aSize); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUTF8: Error - ReadTrackLengthFrame failed. status=%d", status)); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| break; |
| |
| case PV_ID3_FRAME_TITLE: |
| case PV_ID3_FRAME_ARTIST: |
| case PV_ID3_FRAME_ALBUM: |
| case PV_ID3_FRAME_YEAR: |
| case PV_ID3_FRAME_TRACK_NUMBER: |
| case PV_ID3_FRAME_GENRE: |
| case PV_ID3_FRAME_COPYRIGHT: |
| case PV_ID3_FRAME_DATE: |
| case PV_ID3_FRAME_RECORDING_TIME: |
| //new frames support |
| case PV_ID3_FRAME_AUTHOR: |
| case PV_ID3_FRAME_COMPOSER: |
| case PV_ID3_FRAME_DESCRIPTION: |
| case PV_ID3_FRAME_VERSION: |
| case PV_ID3_FRAME_PART_OF_SET: |
| |
| status = ReadStringValueFrame(aFrameType, PV_ID3_CHARSET_UTF8, aSize); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUTF8: Error - ReadStringValueFrame failed. status=%d", status)); |
| OSCL_LEAVE(OsclErrGeneral); |
| } |
| if (aFrameType == PV_ID3_FRAME_TITLE) |
| iTitleFoundFlag = true; |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| //---------------------------------------------------------------------------- |
| // FUNCTION NAME: PVID3ParCom::FrameSupportedID3V2(PVID3Version) |
| //---------------------------------------------------------------------------- |
| // INPUT AND OUTPUT DEFINITIONS |
| // |
| // Inputs: None |
| // |
| // Outputs: None |
| // |
| // Returns: |
| // ID3V2FrameTypeReturnValue - The value that describes the current frame. |
| // of type enum TID3V2FrameType |
| // |
| // Global Variables Used: |
| // TID3V2FrameType - The enum table containing the supported frame types |
| // |
| //---------------------------------------------------------------------------- |
| // FUNCTION DESCRIPTION |
| // |
| // This function detects the ID3V2FrameType and returns the enum value that |
| // corresponds to the current frame. |
| // |
| //------------------------------------------------------------------------------ |
| |
| PVID3ParCom::PVID3FrameType PVID3ParCom::FrameSupportedID3V2(PVID3Version aVersion) |
| { |
| PVID3FrameType ID3V2FrameTypeReturnValue; |
| |
| if ((iID3TagInfo.iID3V2FrameID[0] == 0xff)) |
| { |
| //possibly start of mp3 frame. Stop further parsing. |
| return PV_ID3_FRAME_EEND; |
| } |
| |
| if (aVersion == PV_ID3_V2_2) |
| { |
| ID3V2FrameTypeReturnValue = FrameSupportedID3V2_2(); |
| } |
| else //for v2.3 & v2.4 |
| { |
| |
| uint8 endTestBuf[ID3V2_FRAME_NUM_BYTES_ID] = {0}; |
| |
| if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_TITLE, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_TITLE; |
| iTitleFoundFlag = true; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_ARTIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_ARTIST; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_PART_OF_SET, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_PART_OF_SET; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_ALBUM, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_ALBUM; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_COPYRIGHT, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_COPYRIGHT; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_GENRE, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_GENRE; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_TRACK_NUMBER, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_NUMBER; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_TRACK_LENGTH, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_LENGTH; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_COMMENT, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_COMMENT; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_YEAR, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_YEAR; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_DATE, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_DATE; |
| } |
| |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_ALBUMART, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_APIC; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_LYRICIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_LYRICS; |
| } |
| |
| // For the seek frame. |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_SEEK, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_SEEK; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_RECORDING_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_RECORDING_TIME; |
| } |
| //new frames support |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_AUTHOR, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_AUTHOR; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_COMPOSER, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_COMPOSER; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_DESCRIPTION, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_DESCRIPTION; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3_FRAME_ID_VERSION, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_VERSION; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, endTestBuf, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_EEND; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, endTestBuf, ID3V2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_EEND; |
| } |
| else |
| { |
| ID3V2FrameTypeReturnValue = PV_ID3_FRAME_UNSUPPORTED; |
| } |
| } |
| return ID3V2FrameTypeReturnValue; |
| } |
| |
| //---------------------------------------------------------------------------- |
| // FUNCTION NAME: PVID3ParCom::FrameSupportedID3V2_2(void) |
| //---------------------------------------------------------------------------- |
| // INPUT AND OUTPUT DEFINITIONS |
| // |
| // Inputs: None |
| // |
| // Outputs: None |
| // |
| // Returns: |
| // ID3V2_2FrameTypeReturnValue - The value that describes the current frame. |
| // of type enum TID3V2FrameType |
| // |
| // Global Variables Used: |
| // TID3V2_2FrameType - The enum table containing the supported frame types |
| // |
| //---------------------------------------------------------------------------- |
| // FUNCTION DESCRIPTION |
| // |
| // This function detects the ID3V2_2FrameType and returns the enum value that |
| // corresponds to the current frame. |
| // |
| //------------------------------------------------------------------------------ |
| |
| PVID3ParCom::PVID3FrameType PVID3ParCom::FrameSupportedID3V2_2(void) |
| { |
| uint8 endTestBuf[ID3V2_2_FRAME_NUM_BYTES_ID] = {0}; |
| PVID3FrameType ID3V2_2FrameTypeReturnValue; |
| |
| if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_TITLE, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_TITLE; |
| iTitleFoundFlag = true; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_ARTIST, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_ARTIST; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_PART_OF_SET, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_PART_OF_SET; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_ALBUM, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_ALBUM; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_COPYRIGHT, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_COPYRIGHT; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_GENRE, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_GENRE; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_TRACK_NUMBER, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_NUMBER; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_TRACK_LENGTH, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_LENGTH; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_COMMENT, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_COMMENT; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_YEAR, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_YEAR; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_DATE, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_DATE; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_ALBUMART, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_PIC; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_LYRICIST, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_LYRICS; |
| } |
| //new frames support |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_AUTHOR, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_AUTHOR; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_COMPOSER, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_COMPOSER; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_DESCRIPTION, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_DESCRIPTION; |
| } |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_VERSION, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_VERSION; |
| } |
| |
| else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, endTestBuf, ID3V2_2_FRAME_NUM_BYTES_ID) == 0) |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_EEND; |
| } |
| |
| else |
| { |
| ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_UNSUPPORTED; |
| } |
| |
| return ID3V2_2FrameTypeReturnValue; |
| } |
| |
| //---------------------------------------------------------------------------- |
| // FUNCTION NAME: PVID3ParCom::EightBitToWideCharBufferTransfer( |
| // const TPtr8& aPtrFrameData8, |
| // uint32 aSize, |
| // uint32 aEndianType, |
| // TPtr16& aPtrFrameData16) |
| //---------------------------------------------------------------------------- |
| // INPUT AND OUTPUT DEFINITIONS |
| // |
| // Inputs: |
| // aPtrFrameData8 - pointer to intput string format of either big |
| // or little endian. |
| // aSize - number of character elements in aPtrFrameData8 |
| // aEndianType - This describes if the encoded Unicode text in the |
| // aPtrFrameData8 buffer is in big or little endian. |
| // Outputs: |
| // aPtrFrameDataWCBase - pointer to the output string in unicode format. |
| // |
| // Returns: size of data in aPtrFrameDataWCBase |
| // |
| // Global Variables Used: None |
| // |
| //---------------------------------------------------------------------------- |
| // FUNCTION DESCRIPTION |
| // |
| // This function moves unicode data sotred in uint8 buffer to wchar buffer. |
| // The endian is taken care of by this function as well. |
| // |
| //------------------------------------------------------------------------------ |
| uint32 PVID3ParCom::EightBitToWideCharBufferTransfer(const uint8 * aPtrFrameData8, |
| uint32 aSize, |
| uint32 aEndianType, |
| oscl_wchar * aPtrFrameDataWCBase) |
| { |
| if (aPtrFrameData8 == NULL || aPtrFrameDataWCBase == NULL) |
| { |
| return 0; |
| } |
| |
| oscl_wchar * aPtrFrameDataWC = aPtrFrameDataWCBase; |
| uint16 tempFrameData16; |
| oscl_wchar tempFrameDataWC = 0; |
| uint32 index = 0; |
| uint32 z = 0, x = 0; |
| uint8 tempByteOne, tempByteTwo; |
| if (aEndianType != UNICODE_BIG_ENDIAN) |
| // Indication check of big-endian vs. little endian |
| { |
| z = 0; |
| for (x = 0; x < (aSize >> 1); x++) |
| { |
| z = x << 1; |
| tempByteOne = aPtrFrameData8[z]; |
| tempByteTwo = aPtrFrameData8[z + 1]; |
| if ((tempByteOne == 0) && (tempByteTwo == 0)) |
| { |
| x++; |
| // End of string here and skip to start of next string. |
| aPtrFrameDataWC[index++] = ((oscl_wchar)'\0'); |
| } |
| else |
| { |
| tempFrameData16 = (uint16)((((uint16)(tempByteTwo << 8)) | tempByteOne)); |
| tempFrameDataWC = tempFrameData16; |
| aPtrFrameDataWC[index++] = tempFrameDataWC; |
| } |
| } |
| } |
| else |
| { |
| z = 0; |
| for (x = 0; x < (aSize >> 1); x++) |
| { |
| z = x << 1; |
| tempByteOne = aPtrFrameData8[z]; |
| tempByteTwo = aPtrFrameData8[z + 1]; |
| if ((tempByteTwo == 0) && (tempByteOne == 0)) |
| { |
| x++; |
| // End of string here and skip to start of next string. |
| aPtrFrameDataWC[index++] = ((oscl_wchar)'\0'); |
| } |
| else |
| { |
| tempFrameData16 = (uint16)((((uint16)(tempByteOne << 8)) | tempByteTwo)); |
| int32 l = sizeof(oscl_wchar); |
| if (l == 4) |
| tempFrameDataWC = (tempFrameData16 << 16) && 0xff00; |
| else if (l == 2) |
| tempFrameDataWC = tempFrameData16; |
| else |
| return 0; |
| aPtrFrameDataWC[index++] = tempFrameDataWC; |
| } |
| } |
| } |
| return (index); |
| } |
| |
| uint32 PVID3ParCom::ConvertToSyncSafeInt(uint32 src) |
| { |
| uint32 dest = (src & 0x0FE00000) << 3; |
| dest |= (src & 0x001FC000) << 2; |
| dest |= (src & 0x00003f80) << 1; |
| dest |= (src & 0x0000007f); |
| |
| return dest; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| uint32 PVID3ParCom::SafeSynchIntToInt32(uint32 aSafeSynchInteger) |
| { |
| uint8 * pBuf = (uint8 *) & (aSafeSynchInteger); |
| uint8 tmpByte = 0; |
| int32 i = 0; |
| uint32 integer = 0; |
| |
| // This loop will calculate the correct size from the bytes designated for size |
| // It is stored as a SynchSafe Integer. This means the 8th bit is reserved in |
| // each byte and not used for integer precision.. The number is effectively 28 |
| // bits in length/precision. |
| // Assumes: sizeof(uint32) = 4 Bytes |
| for (i = 0; i < 4; i++) |
| { |
| #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN) |
| tmpByte = (uint8)(pBuf[i] & MASK127); |
| #elif (OSCL_BYTE_ORDER_BIG_ENDIAN) |
| tmpByte = pBuf[4-i-1] & MASK127; |
| #else |
| #error "Must Specify ENDIANNESS" |
| #endif |
| // now shift the data to it's correct place |
| integer += tmpByte << VALID_BITS_IN_SYNC_SAFE_BYTE * i; |
| } |
| |
| return integer; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| bool PVID3ParCom::readByteData(PVFile* aInputFile, uint32 length, uint8 *aData) |
| { |
| if (length > 0) |
| { |
| uint32 bytesRead; |
| bytesRead = aInputFile->Read(aData, 1, length); |
| |
| if (bytesRead < (uint32)length) // read byte data failed |
| { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| bool PVID3ParCom::read32(PVFile* aInputFile, uint32 &aData) |
| { |
| const int32 N = 4; |
| uint8 bytes[N]; |
| aData = 0; |
| |
| int32 retVal = (int32)(aInputFile->Read((void*)bytes, 1, N)); |
| |
| if (retVal < N) |
| return false; |
| |
| for (int32 i = 0; i < N; i++) |
| aData = (aData << 8) | bytes[i]; |
| |
| return true; |
| } |
| //////////////////////////////////////////////////////////////////////////// |
| bool PVID3ParCom::read16(PVFile* aInputFile, uint16 &aData) |
| { |
| const int32 N = 2; |
| uint8 bytes[N]; |
| aData = 0; |
| |
| int32 retVal = (int32)(aInputFile->Read((void*)bytes, 1, N)); |
| |
| if (retVal < N) |
| return false; |
| |
| for (int32 i = 0; i < N; i++) |
| aData = (uint16)((aData << 8) | bytes[i]); |
| |
| return true; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| bool PVID3ParCom::read24(PVFile* aInputFile, uint32 &aData) |
| { |
| const int32 N = 3; |
| uint8 bytes[N]; |
| aData = 0; |
| |
| int32 retVal = (int32)(aInputFile->Read((void*)bytes, 1, N)); |
| |
| if (retVal < N) |
| return false; |
| |
| for (int32 i = 0; i < N; i++) |
| aData = (aData << 8) | bytes[i]; |
| |
| return true; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| bool PVID3ParCom::read8(PVFile* aInputFile, uint8 &aData) |
| { |
| aData = 0; |
| |
| int32 retVal = (int32)(aInputFile->Read((void*) & aData, 1, 1)); |
| |
| if (retVal < 1) |
| return false; |
| |
| return true; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| |
| PvmiKvpSharedPtr PVID3ParCom::AllocateKvp(OSCL_String& aKey, PvmiKvpValueType aValueType, uint32 aValueSize, bool &truncate) |
| { |
| uint8* myPtr = NULL; |
| OsclRefCounter* refCounter; |
| |
| uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterDA)); |
| uint aligned_cleanup_size = oscl_mem_aligned_size(sizeof(PVID3ParComKvpCleanupDA)); |
| uint aligned_kvp_size = oscl_mem_aligned_size(sizeof(PvmiKvp)); |
| uint32 key_size = oscl_mem_aligned_size(aKey.get_size() + 1); |
| uint32 total_size = aligned_refcnt_size + aligned_cleanup_size + |
| aligned_kvp_size + key_size + aValueSize; |
| |
| int32 error = 0; |
| OSCL_TRY(error, myPtr = (uint8*)iAlloc.ALLOCATE(total_size);); |
| if ((error != OsclErrNone) || (!myPtr) || (total_size < aValueSize)) |
| { |
| if (myPtr) |
| { |
| iAlloc.deallocate(myPtr); |
| } |
| char str_data_len[MAX_RANGE_INT_SIZE + 1] = {0}; |
| oscl_snprintf(str_data_len, MAX_RANGE_INT_SIZE + 1, "%d", aValueSize); |
| aKey += SEMI_COLON; |
| aKey += KVP_VALTYPE_REQSIZE; |
| aKey += _STRLIT_CHAR((char *)str_data_len); |
| uint32 new_key_size = oscl_mem_aligned_size(aKey.get_size() + 1); |
| error = OsclErrNone; |
| total_size = aligned_refcnt_size + aligned_cleanup_size + aligned_kvp_size + new_key_size; |
| myPtr = (uint8*)iAlloc.ALLOCATE(total_size); |
| truncate = true; |
| } |
| oscl_memset(myPtr, 0, total_size); |
| |
| PVID3ParComKvpCleanupDA* kvpCleanup = OSCL_PLACEMENT_NEW(myPtr + aligned_refcnt_size, PVID3ParComKvpCleanupDA(&iAlloc)); |
| refCounter = OSCL_PLACEMENT_NEW(myPtr, OsclRefCounterDA(myPtr, kvpCleanup)); |
| myPtr += aligned_refcnt_size + aligned_cleanup_size; |
| |
| PvmiKvp* kvp = OSCL_STATIC_CAST(PvmiKvp *, myPtr) ; |
| myPtr += aligned_kvp_size; |
| |
| if (!truncate) |
| { |
| kvp->key = OSCL_STATIC_CAST(char* , myPtr); |
| myPtr += key_size; |
| oscl_strncpy(kvp->key, aKey.get_cstr(), key_size); |
| switch (aValueType) |
| { |
| case PVMI_KVPVALTYPE_WCHARPTR: |
| kvp->value.pWChar_value = OSCL_STATIC_CAST(oscl_wchar*, myPtr); |
| break; |
| case PVMI_KVPVALTYPE_CHARPTR: |
| kvp->value.pChar_value = OSCL_STATIC_CAST(char* , myPtr); |
| break; |
| case PVMI_KVPVALTYPE_UINT8PTR: |
| kvp->value.pUint8_value = OSCL_STATIC_CAST(uint8*, myPtr); |
| break; |
| case PVMI_KVPVALTYPE_INT32PTR: |
| kvp->value.pInt32_value = OSCL_STATIC_CAST(int32*, myPtr); |
| break; |
| case PVMI_KVPVALTYPE_UINT32PTR: |
| kvp->value.pUint32_value = OSCL_STATIC_CAST(uint32*, myPtr); |
| break; |
| case PVMI_KVPVALTYPE_INT64PTR: |
| kvp->value.pInt64_value = OSCL_STATIC_CAST(int64* , myPtr); |
| break; |
| case PVMI_KVPVALTYPE_UINT64PTR: |
| kvp->value.pUint64_value = OSCL_STATIC_CAST(uint64* , myPtr); |
| break; |
| case PVMI_KVPVALTYPE_FLOATPTR: |
| kvp->value.pFloat_value = OSCL_STATIC_CAST(float* , myPtr); |
| break; |
| case PVMI_KVPVALTYPE_DOUBLEPTR: |
| kvp->value.pDouble_value = OSCL_STATIC_CAST(double*, myPtr); |
| break; |
| case PVMI_KVPVALTYPE_KSV: |
| kvp->value.key_specific_value = OSCL_STATIC_CAST(OsclAny*, myPtr); |
| default: |
| break; |
| } |
| kvp->length = aValueSize; |
| kvp->capacity = aValueSize; |
| } |
| else |
| { |
| kvp->length = 0; |
| kvp->capacity = 0; |
| |
| } |
| PvmiKvpSharedPtr sharedPtr(kvp, refCounter); |
| return sharedPtr; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| PVMFStatus PVID3ParCom::ConstructKvpKey(OSCL_String& aKey, PVID3FrameType aType, PVID3CharacterSet aCharSet) |
| { |
| aKey = _STRLIT_CHAR(""); |
| |
| switch (aType) |
| { |
| case PV_ID3_FRAME_TITLE: |
| aKey += _STRLIT_CHAR(KVP_KEY_TITLE); |
| break; |
| case PV_ID3_FRAME_ARTIST: |
| aKey += _STRLIT_CHAR(KVP_KEY_ARTIST); |
| break; |
| case PV_ID3_FRAME_PART_OF_SET: |
| aKey += _STRLIT_CHAR(KVP_KEY_PART_OF_SET); |
| break; |
| case PV_ID3_FRAME_ALBUM: |
| aKey += _STRLIT_CHAR(KVP_KEY_ALBUM); |
| break; |
| case PV_ID3_FRAME_COPYRIGHT: |
| aKey += _STRLIT_CHAR(KVP_KEY_COPYRIGHT); |
| break; |
| case PV_ID3_FRAME_GENRE: |
| aKey += _STRLIT_CHAR(KVP_KEY_GENRE); |
| if (aCharSet == PV_ID3_CHARSET_INVALID) |
| { |
| // ID3 V1 genre is a uint32 value |
| aKey += SEMI_COLON; |
| aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_STRING); |
| aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING); |
| aKey += SEMI_COLON; |
| aKey += _STRLIT_CHAR(KVP_FORMAT_ID3V1); |
| return PVMFSuccess; |
| } |
| break; |
| case PV_ID3_FRAME_TRACK_NUMBER: |
| aKey += _STRLIT_CHAR(KVP_KEY_TRACK_NUMBER); |
| if (aCharSet == PV_ID3_CHARSET_INVALID) |
| { |
| // ID3 V1 track number is a uint32 value |
| aKey += SEMI_COLON; |
| aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_STRING); |
| aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING); |
| return PVMFSuccess; |
| } |
| break; |
| case PV_ID3_FRAME_YEAR: |
| aKey += _STRLIT_CHAR(KVP_KEY_YEAR); |
| break; |
| case PV_ID3_FRAME_DATE: |
| aKey += _STRLIT_CHAR(KVP_KEY_DATE); |
| break; |
| case PV_ID3_FRAME_RECORDING_TIME: |
| aKey += _STRLIT_CHAR(KVP_KEY_RECORDING_TIME); |
| break; |
| //new frames support |
| case PV_ID3_FRAME_AUTHOR: |
| aKey += _STRLIT_CHAR(KVP_KEY_AUTHOR); |
| break; |
| case PV_ID3_FRAME_COMPOSER: |
| aKey += _STRLIT_CHAR(KVP_KEY_COMPOSER); |
| break; |
| case PV_ID3_FRAME_DESCRIPTION: |
| aKey += _STRLIT_CHAR(KVP_KEY_DESCRIPTION); |
| break; |
| case PV_ID3_FRAME_VERSION: |
| aKey += _STRLIT_CHAR(KVP_KEY_VERSION); |
| break; |
| case PV_ID3_FRAME_COMMENT: |
| aKey += _STRLIT_CHAR(KVP_KEY_COMMENT); |
| if ((iVersion != PV_ID3_V1_1) && (iVersion != PV_ID3_V1)) |
| { |
| aKey += SEMI_COLON; |
| aKey += KVP_VALTYPE_LYRICS; |
| } |
| break; |
| case PV_ID3_FRAME_TRACK_LENGTH: |
| aKey += _STRLIT_CHAR(KVP_KEY_ID3DURATION); |
| aKey += SEMI_COLON; |
| aKey += _STRLIT_CHAR(KVP_VALTYPE_DURATION); |
| return PVMFSuccess; // No character set for track length |
| case PV_ID3_FRAME_PIC: |
| case PV_ID3_FRAME_APIC: |
| aKey += _STRLIT_CHAR(KVP_KEY_ALBUMART); |
| aKey += SEMI_COLON; |
| return PVMFSuccess; |
| case PV_ID3_FRAME_LYRICS: |
| aKey += _STRLIT_CHAR(KVP_KEY_LYRICS); |
| aKey += SEMI_COLON; |
| aKey += KVP_VALTYPE_LYRICS; |
| break; |
| case PV_ID3_FRAME_UNSUPPORTED: |
| aKey += _STRLIT_CHAR(KVP_ID3V2_VALUE); |
| aKey += FORWARD_SLASH; |
| aKey += _STRLIT_CHAR((char *)iID3TagInfo.iID3V2FrameID); |
| aKey += SEMI_COLON; |
| aKey += _STRLIT_CHAR(KVP_VALTYPE_UINT8PTR_STRING); |
| return PVMFSuccess; |
| break; |
| default: |
| return PVMFErrNotSupported; |
| } |
| |
| |
| //add language code to lyrics key |
| if ((aType == PV_ID3_FRAME_LYRICS) || (aType == PV_ID3_FRAME_COMMENT)) |
| { |
| //not valid for id3 v1 |
| if ((iVersion != PV_ID3_V1_1) && (iVersion != PV_ID3_V1)) |
| { |
| aKey += SEMI_COLON; |
| aKey += _STRLIT_CHAR(KVP_PARAM_LANGUAGE_CODE); |
| aKey += _STRLIT_CHAR((char*)iID3TagInfo.iID3V2LanguageID); |
| return PVMFSuccess; |
| } |
| } |
| aKey += SEMI_COLON; |
| switch (aCharSet) |
| { |
| case PV_ID3_CHARSET_ISO88591: |
| aKey += _STRLIT_CHAR(KVP_VALTYPE_ISO88591_CHAR); |
| break; |
| case PV_ID3_CHARSET_UTF16: |
| aKey += _STRLIT_CHAR(KVP_VALTYPE_UTF16_WCHAR); |
| break; |
| case PV_ID3_CHARSET_UTF16BE: |
| aKey += _STRLIT_CHAR(KVP_VALTYPE_UTF16BE_WCHAR); |
| break; |
| case PV_ID3_CHARSET_UTF8: |
| aKey += _STRLIT_CHAR(KVP_VALTYPE_UTF8_CHAR); |
| break; |
| default: |
| return PVMFErrNotSupported; |
| } |
| |
| aKey += NULL_CHARACTER; |
| |
| return PVMFSuccess; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| PVMFStatus PVID3ParCom::ReadStringValueFrame(PVID3FrameType aFrameType, PVID3CharacterSet aCharSet, uint32 aValueSize) |
| { |
| // Construct key string |
| OSCL_StackString<128> keyStr; |
| if (ConstructKvpKey(keyStr, aFrameType, aCharSet) != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - ConstructKvpKey failed")); |
| return PVMFErrNotSupported; |
| } |
| |
| // Allocate key-value pair |
| int32 err = 0; |
| PvmiKvpSharedPtr kvpPtr; |
| bool truncate = false; |
| switch (aCharSet) |
| { |
| case PV_ID3_CHARSET_ISO88591: |
| case PV_ID3_CHARSET_UTF8: |
| OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, aValueSize + 1, truncate);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - AllocateKvp failed. err=%d", err)); |
| return PVMFErrNoMemory; |
| ); |
| |
| if (truncate) |
| { |
| iInputFile->Seek(aValueSize, Oscl_File::SEEKCUR); |
| kvpPtr->length = 0; |
| } |
| else |
| { |
| if (readByteData(iInputFile, aValueSize, (uint8*)kvpPtr->value.pChar_value) == false) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - readByteData failed")); |
| return PVMFFailure; |
| } |
| kvpPtr->value.pChar_value[aValueSize] = NULL_TERM_CHAR; |
| kvpPtr->length = aValueSize; |
| } |
| // Add to frame vector |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - iFrames.push_back failed. err=%d", err)); |
| return PVMFErrNoMemory; |
| ); |
| break; |
| |
| case PV_ID3_CHARSET_UTF16: |
| case PV_ID3_CHARSET_UTF16BE: |
| { |
| // create buffers to store frame data |
| uint8* ptrFrameData = NULL; |
| OSCL_TRY(err, ptrFrameData = (uint8*)iAlloc.allocate(aValueSize + 2);); |
| if (err != OsclErrNone || !ptrFrameData) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - frameData allocation failed")); |
| return PVMFErrNoMemory; |
| } |
| oscl_memset(ptrFrameData, 0, aValueSize + 2); |
| uint32 wchar_size = sizeof(oscl_wchar); //for platforms where wchar is 4 bytes. |
| // Allocate key-value pair |
| OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_WCHARPTR, (wchar_size / 2) * (aValueSize + 2), truncate);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - AllocateKvp failed. err=%d", err)); |
| return PVMFErrNoMemory; |
| ); |
| |
| if (truncate) |
| { |
| iAlloc.deallocate(ptrFrameData); |
| iInputFile->Seek(aValueSize, Oscl_File::SEEKCUR); |
| kvpPtr->length = 0; |
| } |
| else |
| { |
| if (readByteData(iInputFile, aValueSize, ptrFrameData) == false) |
| { |
| iAlloc.deallocate(ptrFrameData); |
| LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - readByteData failed")); |
| return PVMFFailure; |
| } |
| ptrFrameData[aValueSize] = 0; |
| ptrFrameData[aValueSize+1] = 0; |
| |
| uint32 endianType = UNICODE_LITTLE_ENDIAN; |
| if (aCharSet == PV_ID3_CHARSET_UTF16BE) |
| endianType = UNICODE_BIG_ENDIAN; |
| |
| uint32 wcSize = EightBitToWideCharBufferTransfer(ptrFrameData, aValueSize, endianType, kvpPtr->value.pWChar_value); |
| |
| kvpPtr->value.pWChar_value[wcSize] = NULL_TERM_CHAR; |
| iAlloc.deallocate(ptrFrameData); |
| kvpPtr->length = aValueSize; |
| } |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - iFrame.push_back failed")); |
| return PVMFErrNoMemory; |
| ); |
| } |
| break; |
| default: |
| return PVMFFailure; |
| } |
| |
| return PVMFSuccess; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////// |
| PVMFStatus PVID3ParCom::ReadFrame(PVID3FrameType aFrameType, uint32 aValueSize) |
| { |
| |
| // Construct key string |
| OSCL_StackString<128> keyStr; |
| if (ConstructKvpKey(keyStr, aFrameType, PV_ID3_CHARSET_INVALID) != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - ConstructKvpKey failed")); |
| return PVMFErrNotSupported; |
| } |
| |
| // Allocate key-value pair |
| int32 err = 0; |
| PvmiKvpSharedPtr kvpPtr; |
| bool truncate = false; |
| OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, aValueSize + 1 + VERSION_SIZE, truncate);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - AllocateKvp failed. err=%d", err)); |
| return PVMFErrNoMemory; |
| ); |
| if (truncate) |
| { |
| iInputFile->Seek(aValueSize, Oscl_File::SEEKCUR); |
| kvpPtr->length = 0; |
| } |
| else |
| { |
| |
| kvpPtr->value.pUint8_value[0] = (uint8)iVersion; |
| kvpPtr->value.pUint8_value[1] = 0; |
| |
| if (readByteData(iInputFile, aValueSize, (uint8*)kvpPtr->value.pUint8_value + VERSION_SIZE) == false) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - readByteData failed")); |
| return PVMFFailure; |
| } |
| kvpPtr->value.pUint8_value[aValueSize+VERSION_SIZE] = 0; |
| kvpPtr->length = aValueSize + VERSION_SIZE; |
| |
| } |
| // Add to frame vector |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - iFrames.push_back failed. err=%d", err)); |
| return PVMFErrNoMemory; |
| ); |
| |
| |
| return PVMFSuccess; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////// |
| |
| // Read in a NULL terminated UNICODE string byte by byte and take most significant byte first |
| PVMFStatus |
| PVID3ParCom::readNullTerminatedUnicodeString(PVFile* aInputFile, OSCL_wHeapString<OsclMemAllocator> &aData, uint32 &bomSz) |
| { |
| uint8 buff[ID3_MAX_STRING_FRAME_LEN]; |
| uint32 index = 0; |
| uint16 endianCheck; |
| |
| if (read16(aInputFile, endianCheck) == false) |
| { |
| |
| return PVMFFailure; |
| } |
| |
| iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16; |
| uint32 endianType = 0; |
| |
| //some id3 tools does not add BOM with null strings. |
| if (endianCheck != 0) |
| { |
| |
| bomSz = UNICODE_BOM_SIZE; |
| // This frame's text strings are Unicode and the frame |
| // does include a BOM value. (UTF-16) |
| if (endianCheck == UNICODE_LITTLE_ENDIAN_INDICATOR_FULL) |
| { |
| endianType = UNICODE_LITTLE_ENDIAN; |
| } |
| else if (endianCheck == UNICODE_BIG_ENDIAN_INDICATOR_FULL) |
| { |
| endianType = UNICODE_BIG_ENDIAN; |
| } |
| |
| //read frame data from file |
| bool more = true; |
| while (more && index < ID3_MAX_STRING_FRAME_LEN) |
| { |
| if (read8(iInputFile, buff[index]) == false) |
| return PVMFFailure; |
| |
| if ((index > 0) && (buff[index] == 0) && (buff[index -1] == 0)) |
| more = false; |
| index++; |
| } |
| |
| //read remaining characters if any. |
| if (more) |
| { |
| uint16 temp = 1; |
| while (temp != 0) |
| if (read16(iInputFile, temp) == false) |
| return PVMFFailure; |
| } |
| |
| } |
| else |
| { |
| buff[0] = 0; |
| buff[1] = 0; |
| bomSz = 0; |
| index = 2; |
| } |
| |
| int32 err = 0; |
| oscl_wchar *tmpData = 0; |
| OSCL_TRY(err, tmpData = OSCL_ARRAY_NEW(oscl_wchar, index);); |
| if (err != OsclErrNone || !tmpData) |
| { |
| LOG_ERR((0, "PVID3ParCom::readNullTerminatedUnicodeString: Error - allocation failed")); |
| return PVMFErrNoMemory; |
| } |
| |
| uint32 wcSize = EightBitToWideCharBufferTransfer(buff, index, endianType, tmpData); |
| tmpData[wcSize] = 0; |
| aData = tmpData; |
| OSCL_ARRAY_DELETE(tmpData); |
| |
| return PVMFSuccess; |
| } |
| |
| bool |
| PVID3ParCom::readNullTerminatedAsciiString(PVFile* aInputFile, OSCL_HeapString<OsclMemAllocator> &aData) |
| { |
| uint8 buf[256]; |
| int32 index = 0; |
| |
| if (!read8(aInputFile, buf[index])) |
| return PVMFFailure; |
| |
| bool nextChar = (buf[index] == 0) ? false : true; |
| |
| while (nextChar && (index < 256)) |
| { |
| index++; |
| |
| if (!read8(aInputFile, buf[index])) |
| return PVMFFailure; |
| |
| nextChar = (buf[index] == 0) ? false : true; |
| } |
| |
| OSCL_HeapString<OsclMemAllocator> temp((const char *)buf); |
| aData = temp; |
| return true; |
| } |
| |
| PVMFStatus PVID3ParCom::ReadAlbumArtFrame(PVID3FrameType aFrameType, uint8 unicode, uint32 aFrameSize) |
| { |
| PvmfApicStruct* aApicStruct = NULL; |
| uint8 picType; |
| uint32 dataLen; |
| OSCL_HeapString<OsclMemAllocator> ImageFormat; |
| bool pic_as_url = false; |
| bool truncate = false; |
| int32 err = 0; |
| PvmiKvpSharedPtr kvpPtr; |
| OSCL_StackString<128> keyStr; |
| |
| if (ConstructKvpKey(keyStr, PV_ID3_FRAME_APIC, PV_ID3_CHARSET_INVALID) != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - ConstructKvpKey failed")); |
| return PVMFErrNotSupported; |
| } |
| |
| |
| switch (unicode) |
| { |
| case PV_ID3_CHARSET_ISO88591: |
| case PV_ID3_CHARSET_UTF8: |
| { |
| OSCL_HeapString<OsclMemAllocator> description; |
| |
| if (GetAlbumArtInfo(aFrameType, aFrameSize, ImageFormat, picType, description, dataLen) != PVMFSuccess) |
| return PVMFFailure; |
| |
| if (!oscl_strcmp(ImageFormat.get_cstr(), "-->")) |
| { |
| pic_as_url = true; |
| break; |
| } |
| |
| keyStr += KVP_FORMAT_ALBUMART; |
| keyStr += SEMI_COLON; |
| keyStr += KVP_VALTYPE_ALBUMART; |
| |
| //description and image format are stored as wchar. |
| uint32 rfs = aFrameSize - (ImageFormat.get_size() + description.get_size()); |
| uint32 wchar_size = sizeof(oscl_wchar); //for platforms that store wchar as 4 bytes. |
| uint32 total_size = sizeof(PvmfApicStruct) + rfs + ((wchar_size) * (ImageFormat.get_size() + description.get_size())) + 2 * sizeof(oscl_wchar) ; |
| |
| // Allocate key-value pair |
| OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_KSV, total_size, truncate);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - AllocateKvp failed. err=%d", err)); |
| return PVMFFailure; |
| ); |
| |
| if (truncate) |
| { |
| iInputFile->Seek(dataLen, Oscl_File::SEEKCUR); |
| kvpPtr->capacity = 0; |
| kvpPtr->length = 0; |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed")); |
| return PVMFErrNoMemory;); |
| |
| return PVMFSuccess; |
| |
| } |
| |
| kvpPtr->capacity = total_size; |
| kvpPtr->length = total_size; |
| |
| //convert raw data to struct |
| PVMFStatus status; |
| status = ConvertAsciiDataToApic(ImageFormat.get_str(), description.get_str(), picType, |
| dataLen, kvpPtr->value.key_specific_value, total_size); |
| } |
| break; |
| |
| |
| case PV_ID3_CHARSET_UTF16: |
| case PV_ID3_CHARSET_UTF16BE: |
| { |
| OSCL_wHeapString<OsclMemAllocator> description; |
| if (GetAlbumArtInfo(aFrameType, aFrameSize, ImageFormat, picType, description, dataLen) != PVMFSuccess) |
| return PVMFFailure; |
| |
| if (!oscl_strcmp(ImageFormat.get_cstr(), "-->")) |
| { |
| pic_as_url = true; |
| break; |
| } |
| |
| keyStr += KVP_FORMAT_ALBUMART; |
| keyStr += SEMI_COLON; |
| keyStr += KVP_VALTYPE_ALBUMART; |
| |
| //image format is stored as wchar. |
| uint32 rfs = aFrameSize - (ImageFormat.get_size() - (2 * oscl_strlen(description.get_str()))); |
| uint32 wchar_size = sizeof(oscl_wchar); //for platforms that store wchar as 4 bytes. |
| uint32 total_size = sizeof(PvmfApicStruct) + rfs + (wchar_size * (ImageFormat.get_size() + description.get_size())) + (2 * wchar_size); |
| |
| // Allocate key-value pair |
| OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_KSV, total_size, truncate);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - AllocateKvp failed. err=%d", err)); |
| return PVMFFailure; |
| ); |
| |
| if (truncate) |
| { |
| iInputFile->Seek(dataLen, Oscl_File::SEEKCUR); |
| kvpPtr->capacity = 0; |
| kvpPtr->length = 0; |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed")); |
| return PVMFErrNoMemory;); |
| |
| return PVMFSuccess; |
| |
| } |
| |
| kvpPtr->capacity = total_size; |
| kvpPtr->length = total_size; |
| |
| //convert raw data to struct |
| PVMFStatus status; |
| status = ConvertUnicodeDataToApic(ImageFormat.get_str(), description.get_str(), picType, |
| dataLen , kvpPtr->value.key_specific_value, total_size) ; |
| |
| } |
| break; |
| default: |
| return PVMFFailure; |
| |
| } |
| |
| if (pic_as_url) |
| { |
| |
| keyStr += KVP_VALTYPE_ISO88591_CHAR; |
| bool truncate = false; |
| // Allocate key-value pair |
| OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, dataLen, truncate);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - AllocateKvp failed. err=%d", err)); |
| return PVMFFailure; |
| ); |
| |
| if (truncate) |
| { |
| iInputFile->Seek(dataLen, Oscl_File::SEEKCUR); |
| kvpPtr->length = 0; |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed")); |
| return PVMFErrNoMemory;); |
| |
| return PVMFSuccess; |
| |
| } |
| else |
| { |
| if (readByteData(iInputFile, dataLen, (uint8 *)kvpPtr->value.pChar_value) == false) |
| return PVMFFailure; |
| kvpPtr->length = dataLen; |
| kvpPtr->value.pChar_value[dataLen] = NULL_TERM_CHAR; |
| } |
| } |
| else |
| { |
| aApicStruct = OSCL_STATIC_CAST(PvmfApicStruct *, kvpPtr->value.key_specific_value); |
| if (readByteData(iInputFile, dataLen, aApicStruct->iGraphicData) == false) |
| return PVMFFailure; |
| aApicStruct->iGraphicData[dataLen] = NULL_TERM_CHAR; |
| } |
| |
| |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - iFrame.push_back failed")); |
| return PVMFErrNoMemory; |
| ); |
| |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVID3ParCom::ReadLyricsCommFrame(uint8 unicodeCheck, uint32 aFramesize, PVID3FrameType aFrameType) |
| { |
| |
| uint32 framesize = aFramesize; |
| bool truncate = false; |
| if (readByteData(iInputFile, ID3V2_LANGUAGE_SIZE, iID3TagInfo.iID3V2LanguageID) == false) |
| { |
| return PVMFFailure; |
| } |
| |
| iID3TagInfo.iID3V2LanguageID[3] = 0; |
| |
| //subtract 3 bytes of language from the frame size. |
| framesize = aFramesize - ID3V2_LANGUAGE_SIZE ; |
| if ((framesize == 0) || (framesize > aFramesize)) |
| { |
| return PVMFFailure; |
| } |
| //construct kvp for lyrics frame |
| OSCL_StackString<128> keyStr; |
| if (ConstructKvpKey(keyStr, aFrameType, (PVID3ParCom::PVID3CharacterSet)unicodeCheck) != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - ConstructKvpKey failed")); |
| return PVMFErrNotSupported; |
| } |
| |
| int32 err = 0; |
| PvmiKvpSharedPtr kvpPtr; |
| uint32 wchar_size = sizeof(oscl_wchar); //for platforms where wchar is 4 bytes. |
| uint32 total_size = (wchar_size * framesize) + sizeof(PvmfLyricsCommStruct) + (2 * wchar_size) ; |
| uint32 used_size = 0; |
| // Allocate key-value pair |
| OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_KSV, total_size , truncate);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - AllocateKvp failed. err=%d", err)); |
| return PVMFFailure; |
| ); |
| |
| if (truncate) |
| { |
| iInputFile->Seek(framesize, Oscl_File::SEEKCUR); |
| kvpPtr->capacity = 0; |
| kvpPtr->length = 0; |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed")); |
| return PVMFErrNoMemory;); |
| |
| return PVMFSuccess; |
| |
| } |
| |
| PvmfLyricsCommStruct *lcStruct = OSCL_STATIC_CAST(PvmfLyricsCommStruct *, kvpPtr->value.key_specific_value); |
| uint8 *ptr = (uint8 *)kvpPtr->value.key_specific_value; |
| ptr += sizeof(PvmfLyricsCommStruct); |
| used_size += sizeof(PvmfLyricsCommStruct); |
| |
| switch (unicodeCheck) |
| { |
| case PV_ID3_CHARSET_ISO88591: |
| case PV_ID3_CHARSET_UTF8: |
| { |
| OSCL_HeapString<OsclMemAllocator> descriptor; |
| |
| if (readNullTerminatedAsciiString(iInputFile, descriptor) == false) |
| { |
| iAlloc.deallocate(lcStruct); |
| return PVMFFailure; |
| } |
| |
| uint32 desc_sz = descriptor.get_size(); |
| framesize = framesize - desc_sz - 1 ; //subtract 1 for null character |
| |
| if ((framesize > aFramesize) || (framesize == 0)) |
| { |
| lcStruct->iDescription = NULL; |
| lcStruct->iData = NULL; |
| break; |
| } |
| |
| lcStruct->iDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr); |
| ptr += wchar_size * (desc_sz + 1); //1 for null char |
| |
| used_size += wchar_size * (desc_sz + 1); |
| if (used_size > total_size) |
| return PVMFErrOverflow; |
| if (desc_sz > 0) |
| { |
| uint32 sz = desc_sz + 1; |
| oscl_UTF8ToUnicode((const char *)descriptor.get_cstr(), descriptor.get_size(), lcStruct->iDescription, sz); |
| lcStruct->iDescription[sz] = 0; |
| } |
| else |
| { |
| lcStruct->iDescription[desc_sz] = 0; |
| } |
| |
| uint8 *data = NULL; |
| uint32 datasz = framesize + 1; |
| OSCL_TRY(err, data = (uint8*)iAlloc.allocate(datasz);); |
| |
| if (err != OsclErrNone || !(data)) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - allocation failed")); |
| iInputFile->Seek(framesize, Oscl_File::SEEKCUR); |
| |
| } |
| |
| else |
| { |
| |
| if ((readByteData(iInputFile, framesize, data) == false)) |
| { |
| iAlloc.deallocate(data); |
| return PVMFFailure; |
| } |
| |
| lcStruct->iData = OSCL_STATIC_CAST(oscl_wchar *, ptr); |
| used_size += datasz; |
| if (used_size > total_size) |
| return PVMFErrOverflow; |
| oscl_UTF8ToUnicode((const char *)data, framesize, lcStruct->iData, datasz); |
| lcStruct->iData[datasz] = 0; |
| |
| iAlloc.deallocate(data); |
| } |
| } |
| |
| break; |
| |
| case PV_ID3_CHARSET_UTF16: |
| case PV_ID3_CHARSET_UTF16BE: |
| { |
| |
| uint32 bomSize = 0; |
| OSCL_wHeapString<OsclMemAllocator> description ; |
| |
| if (readNullTerminatedUnicodeString(iInputFile, description, bomSize) == false) |
| { |
| return PVMFFailure; |
| } |
| |
| uint32 desc_len = oscl_strlen(description.get_str()) ; |
| framesize = framesize - (2 * desc_len) - 2 - bomSize; // description(2 byte unicode in id3 tag), null char, bom |
| if ((framesize > aFramesize) || (framesize == 0)) |
| { |
| lcStruct->iDescription = NULL; |
| lcStruct->iData = NULL; |
| break; |
| } |
| |
| lcStruct->iDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr); |
| ptr += wchar_size * (desc_len + 1); //1 for null char |
| used_size += wchar_size * (desc_len + 1); |
| if (used_size > total_size) |
| return PVMFErrOverflow; |
| |
| if (desc_len > 0) |
| { |
| oscl_strncpy(lcStruct->iDescription, description.get_str(), desc_len); |
| lcStruct->iDescription[desc_len + 1] = 0; |
| } |
| else |
| { |
| lcStruct->iDescription[desc_len] = 0; |
| } |
| |
| |
| uint16 endianCheck = 0; |
| //check endian type |
| if (read16(iInputFile, endianCheck) == false) |
| { |
| |
| return PVMFFailure; |
| } |
| |
| // This frame's text strings are Unicode and the frame |
| // does include a BOM value. (UTF-16) |
| iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16; |
| uint32 endianType = 0; |
| |
| if (endianCheck == UNICODE_LITTLE_ENDIAN_INDICATOR_FULL) |
| { |
| endianType = UNICODE_LITTLE_ENDIAN; |
| } |
| else if (endianCheck == UNICODE_BIG_ENDIAN_INDICATOR_FULL) |
| { |
| endianType = UNICODE_BIG_ENDIAN; |
| } |
| |
| framesize -= UNICODE_BOM_SIZE; |
| if ((framesize > aFramesize) || (framesize == 0)) |
| { |
| lcStruct->iDescription = NULL; |
| lcStruct->iData = NULL; |
| break; |
| } |
| |
| uint8 *data = NULL; |
| uint32 datasz = framesize + 2; |
| int32 err = 0; |
| OSCL_TRY(err, data = (uint8*)iAlloc.allocate(datasz);); |
| if (err != OsclErrNone || !(data)) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - allocation failed")); |
| truncate = true; |
| } |
| else |
| { |
| |
| oscl_memset(data, 0, datasz); |
| |
| if ((readByteData(iInputFile, framesize, data) == false)) |
| { |
| iAlloc.deallocate(data); |
| return PVMFFailure; |
| } |
| |
| lcStruct->iData = OSCL_STATIC_CAST(oscl_wchar *, ptr); |
| used_size += wchar_size * (framesize / 2); //UCS-2 unicode |
| if (used_size > total_size) |
| return PVMFErrOverflow; |
| uint32 sz = EightBitToWideCharBufferTransfer(data, framesize, endianType , lcStruct->iData); |
| lcStruct->iData[sz] = 0; |
| |
| iAlloc.deallocate(data); |
| } |
| } |
| break; |
| |
| default: |
| return PVMFFailure; |
| |
| } |
| |
| kvpPtr->capacity = (aFramesize - ID3V2_LANGUAGE_SIZE) + sizeof(PvmfLyricsCommStruct) ; |
| kvpPtr->length = (aFramesize - ID3V2_LANGUAGE_SIZE) + sizeof(PvmfLyricsCommStruct) ; |
| |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed")); |
| return PVMFErrNoMemory; |
| ); |
| |
| |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVID3ParCom::ConvertAsciiDataToApic(char* aMimeTypeID3, char* aDescriptionID3, |
| uint8 aGraphicType, uint32 aGraphicDataLen, |
| void *key_specific_value, uint32 total_size) |
| { |
| uint32 used_size = 0; |
| uint8 *ptr = (uint8 *)key_specific_value; |
| PvmfApicStruct* aAPICStruct = OSCL_STATIC_CAST(PvmfApicStruct*, key_specific_value); |
| uint32 mime_string_size; |
| uint32 description_size; |
| mime_string_size = oscl_strlen(aMimeTypeID3) + 1; |
| description_size = oscl_strlen(aDescriptionID3) + 1; |
| ptr += sizeof(PvmfApicStruct); |
| used_size += sizeof(PvmfApicStruct); |
| if (used_size > total_size) |
| return PVMFErrOverflow; |
| aAPICStruct->iGraphicMimeType = OSCL_STATIC_CAST(oscl_wchar *, ptr); |
| ptr += sizeof(oscl_wchar) * (mime_string_size); |
| used_size += sizeof(oscl_wchar) * (mime_string_size); |
| if (used_size > total_size) |
| return PVMFErrOverflow; |
| aAPICStruct->iGraphicDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr); |
| ptr += sizeof(oscl_wchar) * (description_size); |
| used_size += sizeof(oscl_wchar) * (description_size); |
| if (used_size > total_size) |
| return PVMFErrOverflow; |
| |
| oscl_memset(aAPICStruct->iGraphicDescription, 0 , description_size); |
| oscl_memset(aAPICStruct->iGraphicMimeType , 0 , mime_string_size); |
| oscl_UTF8ToUnicode((const char *)aDescriptionID3, description_size , aAPICStruct->iGraphicDescription, description_size); |
| oscl_UTF8ToUnicode((const char *)aMimeTypeID3, mime_string_size, aAPICStruct->iGraphicMimeType, mime_string_size); |
| |
| //push the data to PvmfApicStruct |
| aAPICStruct->iGraphicType = aGraphicType; |
| |
| aAPICStruct->iGraphicData = OSCL_STATIC_CAST(uint8 *, ptr); |
| |
| aAPICStruct->iGraphicDataLen = aGraphicDataLen; |
| |
| used_size += aGraphicDataLen; |
| if (used_size > total_size) |
| return PVMFErrOverflow; |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVID3ParCom::ConvertUnicodeDataToApic(char* aMimeTypeID3, oscl_wchar* aDescriptionID3, |
| uint8 aGraphicType, uint32 aGraphicDataLen, |
| void *key_specific_value, uint32 total_size) |
| { |
| uint32 used_size = 0; |
| uint8 *ptr = (uint8 *)key_specific_value; |
| PvmfApicStruct* aAPICStruct = OSCL_STATIC_CAST(PvmfApicStruct*, key_specific_value); |
| uint32 mime_string_size; |
| uint32 description_size; |
| |
| mime_string_size = oscl_strlen(aMimeTypeID3) + 1; |
| description_size = oscl_strlen(aDescriptionID3) + 1; |
| |
| ptr += sizeof(PvmfApicStruct); |
| used_size += sizeof(PvmfApicStruct); |
| if (used_size > total_size) |
| return PVMFErrOverflow; |
| |
| aAPICStruct->iGraphicMimeType = OSCL_STATIC_CAST(oscl_wchar *, ptr); |
| ptr += sizeof(oscl_wchar) * mime_string_size; |
| used_size += sizeof(oscl_wchar) * mime_string_size; |
| if (used_size > total_size) |
| return PVMFErrOverflow; |
| aAPICStruct->iGraphicDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr); |
| ptr += sizeof(oscl_wchar) * description_size; |
| used_size += sizeof(oscl_wchar) * description_size; |
| if (used_size > total_size) |
| return PVMFErrOverflow; |
| //push the data to PvmfApicStruct |
| oscl_memset(aAPICStruct->iGraphicDescription, '\0', sizeof(oscl_wchar)*description_size); |
| oscl_memset(aAPICStruct->iGraphicMimeType , '\0', sizeof(oscl_wchar)*mime_string_size); |
| oscl_UTF8ToUnicode((const char *)aMimeTypeID3, mime_string_size - 1, aAPICStruct->iGraphicMimeType, mime_string_size); |
| aAPICStruct->iGraphicMimeType[mime_string_size] = 0; |
| |
| oscl_strncpy(aAPICStruct->iGraphicDescription, aDescriptionID3, description_size); |
| aAPICStruct->iGraphicDescription[description_size] = 0; |
| aAPICStruct->iGraphicType = aGraphicType; |
| aAPICStruct->iGraphicDataLen = aGraphicDataLen; |
| aAPICStruct->iGraphicData = OSCL_STATIC_CAST(uint8 *, ptr); |
| used_size += aGraphicDataLen; |
| if (used_size > total_size) |
| return PVMFErrOverflow; |
| |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVID3ParCom::GetAlbumArtInfo(PVID3FrameType aFrameType, uint32 aFrameSize, OSCL_HeapString<OsclMemAllocator> &aImageFormat, |
| uint8 &aPicType, OSCL_HeapString<OsclMemAllocator> &aDescription, uint32 &aDataLen) |
| { |
| uint8 image_format[4] = {0}; |
| PVMFStatus status = 0; |
| uint32 size = 0; |
| uint32 currentfilepos = 0 ; |
| if (aFrameType == PV_ID3_FRAME_PIC) |
| { |
| if (readByteData(iInputFile, ID3V2_IMAGE_FORMAT_SIZE, image_format) == false) |
| { |
| return PVMFFailure; |
| } |
| else |
| { |
| aImageFormat = (char *)image_format; |
| } |
| if (read8(iInputFile, aPicType) == false) |
| { |
| return PVMFFailure; |
| } |
| |
| currentfilepos = iInputFile->Tell(); |
| //read description from file |
| status = readNullTerminatedAsciiString(iInputFile, aDescription); |
| if (status != PVMFSuccess) |
| { |
| iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET); |
| return PVMFFailure; |
| } |
| //get the graphic data len |
| size = aDescription.get_size() + 1 ; // 1 byte for null char |
| aDataLen = aFrameSize - (ID3V2_PIC_CONST_SIZE + size); |
| if (aDataLen > aFrameSize) |
| { |
| iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET); |
| aDataLen = 0; |
| return PVMFFailure; |
| } |
| |
| |
| |
| } |
| else if (aFrameType == PV_ID3_FRAME_APIC) |
| { |
| uint32 mimeSize; |
| uint32 desSize; |
| |
| currentfilepos = iInputFile->Tell(); |
| status = readNullTerminatedAsciiString(iInputFile, aImageFormat); |
| if (status != PVMFSuccess) |
| { |
| iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET); |
| return PVMFFailure; |
| } |
| if (read8(iInputFile, aPicType) == false) |
| { |
| return PVMFFailure; |
| } |
| currentfilepos = iInputFile->Tell(); |
| status = readNullTerminatedAsciiString(iInputFile, aDescription); |
| if (status != PVMFSuccess) |
| { |
| iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET); |
| return status; |
| } |
| |
| //get the graphic data len |
| mimeSize = aImageFormat.get_size() + 1; //for null string |
| desSize = aDescription.get_size() + 1; //for null string |
| |
| aDataLen = aFrameSize - (ID3V2_APIC_CONST_SIZE + mimeSize + desSize); |
| |
| if (aDataLen > aFrameSize) |
| { |
| iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET); |
| aDataLen = 0; |
| return PVMFFailure; |
| } |
| |
| |
| } |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVID3ParCom::GetAlbumArtInfo(PVID3FrameType aFrameType, uint32 aFrameSize, OSCL_HeapString<OsclMemAllocator> &aImageFormat, |
| uint8 &aPicType, OSCL_wHeapString<OsclMemAllocator> &aDescription, uint32 &aDataLen) |
| { |
| uint8 image_format[4] = {0}; |
| uint32 currentfilepos = 0; |
| uint32 size = 0; |
| if (aFrameType == PV_ID3_FRAME_PIC) |
| { |
| if (readByteData(iInputFile, ID3V2_IMAGE_FORMAT_SIZE, image_format) == false) |
| { |
| return PVMFFailure; |
| } |
| else |
| { |
| aImageFormat = (char *)image_format; |
| } |
| if (read8(iInputFile, aPicType) == false) |
| { |
| return PVMFFailure; |
| } |
| |
| uint32 bomSz = 0; |
| currentfilepos = iInputFile->Tell(); |
| //read description from file |
| if (readNullTerminatedUnicodeString(iInputFile, aDescription, bomSz) == false) |
| { |
| iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET); |
| return PVMFFailure; |
| } |
| |
| //get the graphic data len |
| size = (2 * oscl_strlen(aDescription.get_str())) + bomSz + sizeof(oscl_wchar) * 1; //2 byte null character |
| aDataLen = aFrameSize - (ID3V2_PIC_CONST_SIZE + size); |
| if (aDataLen > aFrameSize) |
| { |
| iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET); |
| aDataLen = 0; |
| return PVMFFailure; |
| } |
| |
| |
| } |
| else if (aFrameType == PV_ID3_FRAME_APIC) |
| { |
| uint32 mimeSize; |
| uint32 desSize; |
| currentfilepos = iInputFile->Tell(); |
| //read the mime type information |
| if (readNullTerminatedAsciiString(iInputFile, aImageFormat) == false) |
| { |
| iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET); |
| return PVMFFailure; |
| } |
| //read the picture type information |
| if (read8(iInputFile, aPicType) == false) |
| { |
| return PVMFFailure; |
| } |
| uint32 bomSz = 0; |
| currentfilepos = iInputFile->Tell(); |
| //read the null terminated description information |
| if (readNullTerminatedUnicodeString(iInputFile, aDescription, bomSz) == false) |
| { |
| iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET); |
| return PVMFFailure; |
| } |
| //get the graphic data len |
| mimeSize = aImageFormat.get_size() + 1; |
| desSize = (2 * oscl_strlen(aDescription.get_str())) + bomSz + sizeof(oscl_wchar) * 1; //2 bytes for null character |
| aDataLen = aFrameSize - (ID3V2_APIC_CONST_SIZE + mimeSize + desSize); |
| if (aDataLen > aFrameSize) |
| { |
| iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET); |
| aDataLen = 0; |
| return PVMFFailure; |
| } |
| |
| |
| |
| } |
| return PVMFSuccess; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////// |
| PVMFStatus PVID3ParCom::ReadTrackLengthFrame(uint32 aValueSize) |
| { |
| OSCL_StackString<128> keyStr; |
| if (ConstructKvpKey(keyStr, PV_ID3_FRAME_TRACK_LENGTH, PV_ID3_CHARSET_INVALID) != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - ConstructKvpKey failed")); |
| return PVMFErrNotSupported; |
| } |
| |
| int32 err = 0; |
| uint8* ptrFrameData = NULL; |
| OSCL_TRY(err, ptrFrameData = (uint8*)iAlloc.ALLOCATE(aValueSize + 1);); |
| if (err != OsclErrNone || !ptrFrameData) |
| { |
| LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - ptrFrameData allocation failed")); |
| return PVMFErrNoMemory; |
| } |
| |
| if (readByteData(iInputFile, aValueSize, ptrFrameData) == false) |
| { |
| iAlloc.deallocate((OsclAny*)ptrFrameData); |
| LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - readByteData failed")); |
| return PVMFFailure; |
| } |
| ptrFrameData[aValueSize] = 0; |
| |
| // The ID3 Track Length is a numeric string in milliseconds. |
| uint32 duration = 0; |
| int32 numericStringLen = oscl_strlen((const char*)ptrFrameData); |
| |
| uint8* ptr = ptrFrameData; |
| if (!PV_atoi((const char *)ptrFrameData, 'd', numericStringLen, duration)) |
| { |
| uint8* ptr = ptrFrameData; |
| bool invalid_frame = false; |
| while (ptr - ptrFrameData < numericStringLen) |
| { |
| // if the charater read is a digit or decimal point |
| // then truncate it to integer value |
| if (!((*ptr >= ZERO_CHARACTER_ASCII_VALUE) && |
| (*ptr <= NINE_CHARACTER_ASCII_VALUE)) || |
| (*ptr == PERIOD_CHARACTER_ASCII_VALUE) || |
| (*ptr == COMMA_CHARACTER_ASCII_VALUE)) |
| { |
| invalid_frame = true; |
| break; |
| } |
| else if (*ptr == PERIOD_CHARACTER_ASCII_VALUE || |
| *ptr == COMMA_CHARACTER_ASCII_VALUE) |
| { |
| numericStringLen = ptr - ptrFrameData; |
| break; |
| } |
| ptr++; |
| } |
| |
| if (!invalid_frame) |
| { |
| numericStringLen = ptr - ptrFrameData; |
| } |
| else |
| { |
| iAlloc.deallocate((OsclAny*)ptrFrameData); |
| numericStringLen = 0; |
| return PVMFSuccess; |
| } |
| } |
| else |
| { |
| numericStringLen = aValueSize; |
| } |
| |
| // Allocate key-value pair |
| bool truncate = false; |
| PvmiKvpSharedPtr kvpPtr; |
| OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_UINT32, 0, truncate);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - AllocateKvp failed. err=%d", err)); |
| return PVMFFailure; |
| ); |
| |
| kvpPtr->value.uint32_value = duration; // Track length in milliseconds |
| kvpPtr->length = numericStringLen; |
| |
| iAlloc.deallocate((OsclAny*)ptrFrameData); |
| |
| OSCL_TRY(err, iFrames.push_back(kvpPtr);); |
| OSCL_FIRST_CATCH_ANY(err, |
| LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - iFrame.push_back failed")); |
| return PVMFErrNoMemory; |
| ); |
| |
| return PVMFSuccess; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////// |
| PVMFStatus PVID3ParCom::GetKvpValueType(PvmiKvpSharedPtr aKvp, |
| PvmiKvpValueType& aValueType, |
| PVID3CharacterSet& aCharSet) |
| { |
| aValueType = GetValTypeFromKeyString(aKvp->key); |
| aCharSet = PV_ID3_CHARSET_INVALID; |
| char* param = NULL; |
| switch (aValueType) |
| { |
| case PVMI_KVPVALTYPE_CHARPTR: |
| aCharSet = PV_ID3_CHARSET_ISO88591; |
| if (pv_mime_string_parse_param(aKvp->key, KVP_PARAM_CHAR_ENCODING_UTF8, param) > 0) |
| aCharSet = PV_ID3_CHARSET_UTF8; |
| break; |
| case PVMI_KVPVALTYPE_WCHARPTR: |
| aCharSet = PV_ID3_CHARSET_UTF16; |
| if (pv_mime_string_parse_param(aKvp->key, KVP_PARAM_CHAR_ENCODING_UTF16BE, param) > 0) |
| aCharSet = PV_ID3_CHARSET_UTF16BE; |
| break; |
| case PVMI_KVPVALTYPE_KSV: |
| // Comment field |
| break; |
| case PVMI_KVPVALTYPE_UNKNOWN: |
| return PVMFFailure; |
| default: |
| break; |
| } |
| |
| return PVMFSuccess; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| PVMFStatus PVID3ParCom::GetFrameTypeFromKvp(PvmiKvpSharedPtr aKvp, |
| OSCL_String& aFrameID, |
| PVID3FrameType& aFrameType) |
| { |
| return GetFrameTypeFromKvp(*aKvp, aFrameID, aFrameType); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| PVMFStatus PVID3ParCom::GetFrameTypeFromKvp(const PvmiKvp& aKvp, |
| OSCL_String& aFrameID, |
| PVID3FrameType& aFrameType) |
| { |
| if (iVersion == PV_ID3_V2_2) |
| { |
| if (pv_mime_strcmp(aKvp.key, KVP_KEY_TITLE) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_TITLE); |
| aFrameType = PV_ID3_FRAME_TITLE; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ARTIST) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_ARTIST); |
| aFrameType = PV_ID3_FRAME_ARTIST; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_PART_OF_SET) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_PART_OF_SET); |
| aFrameType = PV_ID3_FRAME_PART_OF_SET; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUM) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_ALBUM); |
| aFrameType = PV_ID3_FRAME_ALBUM; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_TRACK_NUMBER) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_TRACK_NUMBER); |
| aFrameType = PV_ID3_FRAME_TRACK_NUMBER; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_GENRE) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_GENRE); |
| aFrameType = PV_ID3_FRAME_GENRE; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_YEAR) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_YEAR); |
| aFrameType = PV_ID3_FRAME_YEAR; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COPYRIGHT) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_COPYRIGHT); |
| aFrameType = PV_ID3_FRAME_COPYRIGHT; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMMENT) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_COMMENT); |
| aFrameType = PV_ID3_FRAME_COMMENT; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ID3DURATION) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_TRACK_LENGTH); |
| aFrameType = PV_ID3_FRAME_TRACK_LENGTH; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DATE) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_DATE); |
| aFrameType = PV_ID3_FRAME_DATE; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUMART) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_ALBUMART); |
| aFrameType = PV_ID3_FRAME_PIC; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_LYRICS) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_LYRICIST); |
| aFrameType = PV_ID3_FRAME_LYRICS; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_AUTHOR) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_AUTHOR); |
| aFrameType = PV_ID3_FRAME_AUTHOR; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMPOSER) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_COMPOSER); |
| aFrameType = PV_ID3_FRAME_COMPOSER; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DESCRIPTION) >= 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_DESCRIPTION); |
| aFrameType = PV_ID3_FRAME_DESCRIPTION; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_VERSION) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_VERSION); |
| aFrameType = PV_ID3_FRAME_VERSION; |
| } |
| else |
| { |
| LOG_ERR((0, "PVID3ParCom::GetFrameTypeFromKvp: Error : Frame type not supported for composing")); |
| return PVMFErrNotSupported; |
| } |
| } |
| else |
| { |
| if (pv_mime_strcmp(aKvp.key, KVP_KEY_TITLE) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_TITLE); |
| aFrameType = PV_ID3_FRAME_TITLE; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ARTIST) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_ARTIST); |
| aFrameType = PV_ID3_FRAME_ARTIST; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_PART_OF_SET) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_PART_OF_SET); |
| aFrameType = PV_ID3_FRAME_PART_OF_SET; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUM) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_ALBUM); |
| aFrameType = PV_ID3_FRAME_ALBUM; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_TRACK_NUMBER) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_TRACK_NUMBER); |
| aFrameType = PV_ID3_FRAME_TRACK_NUMBER; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_GENRE) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_GENRE); |
| aFrameType = PV_ID3_FRAME_GENRE; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_YEAR) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_YEAR); |
| aFrameType = PV_ID3_FRAME_YEAR; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COPYRIGHT) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_COPYRIGHT); |
| aFrameType = PV_ID3_FRAME_COPYRIGHT; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMMENT) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_COMMENT); |
| aFrameType = PV_ID3_FRAME_COMMENT; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ID3DURATION) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_TRACK_LENGTH); |
| aFrameType = PV_ID3_FRAME_TRACK_LENGTH; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_RECORDING_TIME) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_RECORDING_TIME); |
| aFrameType = PV_ID3_FRAME_RECORDING_TIME; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_AUTHOR) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_AUTHOR); |
| aFrameType = PV_ID3_FRAME_AUTHOR; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMPOSER) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_COMPOSER); |
| aFrameType = PV_ID3_FRAME_COMPOSER; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DESCRIPTION) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_DESCRIPTION); |
| aFrameType = PV_ID3_FRAME_DESCRIPTION; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_VERSION) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_VERSION); |
| aFrameType = PV_ID3_FRAME_VERSION; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DATE) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_DATE); |
| aFrameType = PV_ID3_FRAME_DATE; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_LYRICS) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_LYRICIST); |
| aFrameType = PV_ID3_FRAME_LYRICS; |
| } |
| else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUMART) == 0) |
| { |
| aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_ALBUMART); |
| aFrameType = PV_ID3_FRAME_APIC; |
| } |
| else |
| { |
| LOG_ERR((0, "PVID3ParCom::GetFrameTypeFromKvp: Error : Frame type not supported for composing")); |
| return PVMFErrNotSupported; |
| } |
| } |
| |
| return PVMFSuccess; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| PVMFStatus PVID3ParCom::GetID3v2FrameDataSize(PvmiKvpSharedPtr aKvp, |
| PvmiKvpValueType aValueType, |
| PVID3CharacterSet aCharSet, |
| uint32& aSize) |
| { |
| aSize = 0; |
| switch (aValueType) |
| { |
| case PVMI_KVPVALTYPE_CHARPTR: |
| aSize += (BYTE_FOR_CHARACTERSET_FORMAT + oscl_strlen(aKvp->value.pChar_value) + 1); |
| break; |
| case PVMI_KVPVALTYPE_WCHARPTR: |
| aSize += (BYTE_FOR_CHARACTERSET_FORMAT + |
| (oscl_strlen(aKvp->value.pWChar_value) + 1) * sizeof(oscl_wchar)); |
| break; |
| case PVMI_KVPVALTYPE_KSV: |
| // Comment field |
| break; |
| case PVMI_KVPVALTYPE_UINT32: |
| uint32 value; |
| value = aKvp->value.uint32_value; |
| if (value == 0) |
| return PVMFSuccess; |
| while (value > 0) |
| { |
| value = value / 10; |
| ++aSize; |
| } |
| break; |
| default: |
| return PVMFErrNotSupported; |
| } |
| |
| // Add 1 byte for BOM value to indicate byte order |
| if (aCharSet == PV_ID3_CHARSET_UTF16) |
| ++aSize; |
| |
| return PVMFSuccess; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| PVMFStatus PVID3ParCom::ComposeID3v2Tag(OsclRefCounterMemFrag& aTag) |
| { |
| uint8* memFragPtr; |
| uint32 index = 0; |
| uint32 composedTagSize = 0; |
| uint32 frameDataSize = 0; |
| uint32 i = 0; |
| char bufTrackLength[16]; |
| oscl_wchar wbufTrackLength[16]; |
| oscl_memset(bufTrackLength, 0, 16); |
| oscl_memset(wbufTrackLength, 0, 16); |
| PvmiKvpValueType kvpValueType; |
| PVID3CharacterSet charSet; |
| PVMFStatus status = PVMFSuccess; |
| |
| // At least one frame should be present for a valid ID3 tag to be composed |
| if (iFrames.empty()) |
| { |
| LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - No Frames are available to add")); |
| return PVMFFailure; |
| } |
| |
| // Calculate the size of composed ID3tag |
| composedTagSize = GetID3TagSize(); |
| if (composedTagSize == 0) |
| { |
| LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetID3TagSize failed")); |
| return PVMFFailure; |
| } |
| |
| //iUseMaxTagSize on but the max tag size set is smaller than the total tag size. |
| if (iUseMaxTagSize && (iMaxTagSize < composedTagSize)) |
| { |
| LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - Max tag size is smaller than size of composed tag")); |
| return PVMFFailure; |
| } |
| |
| //if maxsize is greater than tagsize and padding is ON, allocate memory equal to iMaxTagSize |
| if (iUseMaxTagSize && iUsePadding) |
| composedTagSize = iMaxTagSize; |
| |
| //if the fragment buffer size is not sufficient, allocate memory |
| OsclMemoryFragment& my_memfrag = aTag.getMemFrag(); |
| if (composedTagSize > aTag.getMemFragSize()) |
| { |
| OsclRefCounter* my_refcnt; |
| |
| // Create mem frag for ID3 tag |
| OsclMemAllocDestructDealloc<uint8> my_alloc; |
| uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >)); |
| uint8* myPtr = (uint8*) my_alloc.allocate(aligned_refcnt_size + composedTagSize); |
| my_refcnt = OSCL_PLACEMENT_NEW(myPtr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(myPtr)); |
| myPtr += aligned_refcnt_size; |
| |
| my_memfrag.ptr = myPtr; |
| my_memfrag.len = 0; |
| |
| OsclRefCounterMemFrag mynewRefCntMemFrag(my_memfrag, my_refcnt, composedTagSize); |
| |
| //frees the old memeory and make the RefCounterMemFrag point to newly allocated memory |
| aTag = mynewRefCntMemFrag; |
| } |
| |
| memFragPtr = (uint8*)aTag.getMemFragPtr(); |
| oscl_memset(memFragPtr, 0, composedTagSize); |
| |
| // Form the tag header and place it into the tag buffer |
| oscl_memcpy(memFragPtr, ID3_V2_IDENTIFIER, ID3V2_TAG_NUM_BYTES_ID); |
| index += ID3V2_TAG_NUM_BYTES_ID; |
| |
| // Store ID3 tag version |
| memFragPtr[index++] = (uint8)iVersion; |
| memFragPtr[index++] = 0; |
| |
| // ID3v2 flags |
| memFragPtr[index++] = ID3V2_FLAGS; |
| |
| // Tag size (4 bytes) |
| uint32 syncSafeInt = ConvertToSyncSafeInt(composedTagSize - 10); // Total Size of ID3 tag - 10 bytes for header |
| #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN) |
| memFragPtr[index++] = (uint8)((syncSafeInt & 0xFF000000) >> 24); |
| memFragPtr[index++] = (uint8)((syncSafeInt & 0x00FF0000) >> 16); |
| memFragPtr[index++] = (uint8)((syncSafeInt & 0x0000FF00) >> 8); |
| memFragPtr[index++] = (uint8)(syncSafeInt & 0x000000FF); |
| #elif (OSCL_BYTE_ORDER_BIG_ENDIAN) |
| uint32* sizePtr = (uint32*)(memFragPtr + index); |
| *sizePtr = syncSafeInt; |
| index += 4; |
| #else |
| #error "Byte order is not specified in OSCL" |
| #endif |
| |
| //iterate the frames and write into the tag buffer |
| OSCL_StackString<4> frameID; |
| PVID3FrameType frameType; |
| for (i = 0; i < iFrames.size(); i++) |
| { |
| // 4 character Frame ID |
| status = GetFrameTypeFromKvp(iFrames[i], frameID, frameType); |
| |
| //ignore unsupported frames. |
| if ((status == PVMFErrNotSupported) || (frameType == PV_ID3_FRAME_LYRICS) || |
| (frameType == PV_ID3_FRAME_APIC) || (frameType == PV_ID3_FRAME_PIC) || |
| (frameType == PV_ID3_FRAME_COMMENT)) |
| { |
| continue; |
| } |
| |
| if ((status != PVMFSuccess)) |
| { |
| LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetFrameTypeFromKvp failed. status=%d", status)); |
| return status; |
| } |
| if (iVersion == PV_ID3_V2_2) |
| { |
| oscl_memcpy(memFragPtr + index, frameID.get_cstr(), ID3V2_2_FRAME_NUM_BYTES_ID); |
| index += ID3V2_2_FRAME_NUM_BYTES_ID; |
| } |
| else |
| { |
| oscl_memcpy(memFragPtr + index, frameID.get_cstr(), ID3V2_FRAME_NUM_BYTES_ID); |
| index += ID3V2_FRAME_NUM_BYTES_ID; |
| } |
| status = GetKvpValueType(iFrames[i], kvpValueType, charSet); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetKvpValueType failed. status=%d", status)); |
| return status; |
| } |
| |
| // Size of Frame (4 byte sync safe integer) |
| status = GetID3v2FrameDataSize(iFrames[i], kvpValueType, charSet, frameDataSize); |
| if (status != PVMFSuccess) |
| { |
| LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetID3v2FrameDataSize failed. status=%d", status)); |
| return status; |
| } |
| // syncSafeInt = ConvertToSyncSafeInt(frameDataSize); |
| syncSafeInt = frameDataSize; |
| |
| if (iVersion == PV_ID3_V2_2) |
| { |
| #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN) |
| memFragPtr[index++] = (uint8)((syncSafeInt & 0x00FF0000) >> 16); |
| memFragPtr[index++] = (uint8)((syncSafeInt & 0x0000FF00) >> 8); |
| memFragPtr[index++] = (uint8)(syncSafeInt & 0x000000FF); |
| #elif (OSCL_BYTE_ORDER_BIG_ENDIAN) |
| sizePtr = (uint32*)(memFragPtr + index); |
| *sizePtr = syncSafeInt; |
| index += 3; |
| #else |
| #error "Byte order not specified in OSCL" |
| #endif |
| |
| } |
| else |
| { |
| #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN) |
| memFragPtr[index++] = (uint8)((syncSafeInt & 0xFF000000) >> 24); |
| memFragPtr[index++] = (uint8)((syncSafeInt & 0x00FF0000) >> 16); |
| memFragPtr[index++] = (uint8)((syncSafeInt & 0x0000FF00) >> 8); |
| memFragPtr[index++] = (uint8)(syncSafeInt & 0x000000FF); |
| #elif (OSCL_BYTE_ORDER_BIG_ENDIAN) |
| sizePtr = (uint32*)(memFragPtr + index); |
| *sizePtr = syncSafeInt; |
| index += 4; |
| #else |
| #error "Byte order not specified in OSCL" |
| #endif |
| |
| //frame Flag for status messages |
| memFragPtr[index++] = ID3V2_FLAGS; |
| |
| //frame flag for format description |
| memFragPtr[index++] = ID3V2_FLAGS; |
| } |
| |
| switch (kvpValueType) |
| { |
| case PVMI_KVPVALTYPE_CHARPTR: |
| memFragPtr[index++] = (uint8) charSet; |
| frameDataSize -= 2; // Minus 1 byte for the character set and 1 byte for NULL character |
| oscl_memcpy(memFragPtr + index, iFrames[i]->value.pChar_value, frameDataSize); |
| index += frameDataSize; |
| memFragPtr[index++] = 0; // NULL terminate the string |
| break; |
| case PVMI_KVPVALTYPE_WCHARPTR: |
| memFragPtr[index++] = (uint8)charSet; |
| frameDataSize -= 3; // Minus 1 byte for the character set and 2 bytes for NULL character |
| if (charSet == PV_ID3_CHARSET_UTF16) |
| { |
| #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN) |
| memFragPtr[index++] = UNICODE_LITTLE_ENDIAN_INDICATOR; |
| memFragPtr[index++] = UNICODE_BIG_ENDIAN_INDICATOR; |
| #elif (OSCL_BYTE_ORDER_BIG_ENDIAN) |
| memFragPtr[index++] = UNICODE_BIG_ENDIAN_INDICATOR; |
| memFragPtr[index++] = UNICODE_LITTLE_ENDIAN_INDICATOR; |
| |
| #else |
| #error "Byte order not specified" |
| #endif |
| frameDataSize -= 2; // Minus 1 byte for byte order |
| } |
| oscl_memcpy(memFragPtr + index, iFrames[i]->value.pWChar_value, frameDataSize); |
| index += frameDataSize; |
| memFragPtr[index++] = 0; // NULL terminate the string |
| memFragPtr[index++] = 0; // NULL terminate the string |
| break; |
| case PVMI_KVPVALTYPE_UINT32: |
| // Track length frame |
| oscl_snprintf((char*)(memFragPtr + index), frameDataSize, "%d\0", iFrames[i]->value.uint32_value); |
| break; |
| case PVMI_KVPVALTYPE_KSV: |
| // Comment frame |
| memFragPtr[index++] = (uint8)charSet; |
| frameDataSize -= 1; // Minus 1 byte for the character set |
| break; |
| default: |
| LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - Unsupported key-value pair value type")); |
| return PVMFErrNotSupported; |
| } |
| |
| } |
| |
| //if padding is on and the tag size is less than the maximum tag specified, do the padding |
| if (iUseMaxTagSize && iUsePadding && (index < iMaxTagSize)) |
| { |
| oscl_memset((OsclAny*)(memFragPtr + index), 0, (iMaxTagSize - index)); |
| my_memfrag.len = iMaxTagSize; |
| } |
| else |
| { |
| //save the filesize into the memory fragment |
| my_memfrag.len = index; |
| } |
| |
| return PVMFSuccess; |
| } |
| |