📄 id3_support.cpp
字号:
// Move the audio data if the ID3 frame is new or has to grow. XMP_Assert ( dwNewID3ContentSize >= dwOldID3ContentSize ); if ( dwNewID3ContentSize > dwOldID3ContentSize ) { unsigned long audioOffset = dwNewID3ContentSize - dwOldID3ContentSize; unsigned long oldAudioBase = k_dwTagHeaderSize + dwOldID3ContentSize; if ( ! fFoundID3 ) { // We're injecting an entire ID3 section. audioOffset = k_dwTagHeaderSize + dwNewID3ContentSize; oldAudioBase = 0; } OffsetAudioData ( inFileRef, audioOffset, oldAudioBase ); } // Set the new size for the ID3 content. This always uses the 4x7 format. dwFormattedTemp = CalculateSize ( 4, dwNewID3ContentSize ); szID3Buffer[6] = (char)(dwFormattedTemp >> 24); szID3Buffer[7] = (char)((dwFormattedTemp >> 16) & 0xFF); szID3Buffer[8] = (char)((dwFormattedTemp >> 8) & 0xFF); szID3Buffer[9] = (char)(dwFormattedTemp & 0xFF); // Write the partial ID3 buffer (ID3 header plus unknown tags) LFA_Seek ( inFileRef, 0, SEEK_SET ); LFA_Write ( inFileRef, szID3Buffer, id3BufferLen ); // Append the new legacy metadata frames if ( dwFullLegacySize > 0 ) { LFA_Write ( inFileRef, strLegacyFrames, dwFullLegacySize ); } // Append the XMP frame prefix LFA_Write ( inFileRef, szXMPPrefix, k_XMPPrefixSize ); // Append the XMP packet LFA_Write ( inFileRef, strXMPPacket, dwXMPPacketSize ); // Append the padding. if ( newPadSize > 0 ) { std::string szPad; szPad.reserve ( newPadSize ); szPad.assign ( newPadSize, '\0' ); LFA_Write ( inFileRef, const_cast<char *>(szPad.data()), newPadSize ); } LFA_Flush ( inFileRef ); return true;}// =================================================================================================bool LoadTagHeaderAndUnknownFrames ( LFA_FileRef inFileRef, char * strBuffer, bool fRecon, unsigned long & posPad ){ LFA_Seek ( inFileRef, 3ULL, SEEK_SET ); // Point after the "ID3" // Get the tag info unsigned long dwOffset = 0; XMP_Uns8 v1 = 0, v2 = 0, flags = 0; unsigned long dwTagSize = 0; GetTagInfo ( inFileRef, v1, v2, flags, dwTagSize ); unsigned long dwExtendedTag = SkipExtendedHeader ( inFileRef, v1, flags ); LFA_Seek ( inFileRef, 0ULL, SEEK_SET ); LFA_Read ( inFileRef, strBuffer, k_dwTagHeaderSize ); dwOffset += k_dwTagHeaderSize; // Completely ignore the Extended Header if ( ((flags & flagExt) == flagExt) && (dwExtendedTag > 0) ) { strBuffer[5] = strBuffer[5] & 0xBF; // If the flag has been set, let's reset it LFA_Seek ( inFileRef, dwExtendedTag, SEEK_CUR ); // And let's seek up to after the extended header } // Enumerate through the frames XMP_Int64 posCur = 0ULL; posCur = GetFilePosition ( inFileRef ); XMP_Int64 posEnd = posCur + dwTagSize; while ( posCur < posEnd ) { char szFrameID[5] = {"xxxx"}; unsigned long dwFrameSize = 0; XMP_Uns8 cflag1 = 0, cflag2 = 0; // Get the next frame if ( ! GetFrameInfo ( inFileRef, v1, szFrameID, cflag1, cflag2, dwFrameSize ) ) break; // Are we in a padding frame? if ( dwFrameSize == 0 ) break; // We just hit a padding frame bool fIgnore = false; bool knownID = (strcmp ( szFrameID, "TIT2" ) == 0) || (strcmp ( szFrameID, "TYER" ) == 0) || (strcmp ( szFrameID, "TDRV" ) == 0) || (strcmp ( szFrameID, "TPE1" ) == 0) || (strcmp ( szFrameID, "TALB" ) == 0) || (strcmp ( szFrameID, "TCON" ) == 0) || (strcmp ( szFrameID, "COMM" ) == 0) || (strcmp ( szFrameID, "TRCK" ) == 0); // If a known frame, just ignore // Note: If recon is turned off, let's consider all known frames as unknown if ( knownID && fRecon ) { fIgnore = true; } else if ( strcmp ( szFrameID, "PRIV" ) == 0 ) { // Read the "PRIV" frame // <Header for "PRIV"> // Short content descrip. <text string according to encoding> $00 (00) // The actual data <full text string according to encoding> // Get the PRIV descriptor char szXMPTag[4] = {"xxx"}; if ( LFA_Read ( inFileRef, &szXMPTag, k_dwXMPLabelSize ) != 0 ) { // Is it a XMP "PRIV" if ( (szXMPTag[3] == 0) && (strcmp ( szXMPTag, "XMP" ) == 0) ) fIgnore = true; LFA_Seek ( inFileRef, -(long)k_dwXMPLabelSize, SEEK_CUR ); } } if ( fIgnore ) { LFA_Seek ( inFileRef, dwFrameSize, SEEK_CUR ); } else { // Unknown frame, let's copy it LFA_Seek ( inFileRef, -(long)k_dwFrameHeaderSize, SEEK_CUR ); LFA_Read ( inFileRef, strBuffer+dwOffset, dwFrameSize+k_dwFrameHeaderSize ); dwOffset += dwFrameSize+k_dwFrameHeaderSize; } posCur = GetFilePosition ( inFileRef ); } posPad = dwOffset; return true;}// =================================================================================================bool FindID3Tag ( LFA_FileRef inFileRef, unsigned long & dwLen, XMP_Uns8 & bMajorVer ){ // id3v2 tag: // ID3v2/file identifier "ID3" // ID3v2 version $04 00 // ID3v2 flags %abcd0000 // ID3v2 size 4 * %0xxxxxxx // Taking into account that the first Tag is the ID3 tag LFA_Seek ( inFileRef, 0ULL, SEEK_SET ); // Read the tag name char szID[4] = {"xxx"}; long bytesRead = LFA_Read ( inFileRef, szID, 3 ); if ( bytesRead == 0 ) return false; // Check for "ID3" if ( strcmp ( szID, "ID3" ) != 0 ) return false; // Read the version, flag and size XMP_Uns8 v2 = 0, flags = 0; if ( ! GetTagInfo ( inFileRef, bMajorVer, v2, flags, dwLen ) ) return false; return true;}// =================================================================================================bool GetTagInfo ( LFA_FileRef inFileRef, XMP_Uns8 & v1, XMP_Uns8 & v2, XMP_Uns8 & flags, unsigned long & dwTagSize ){ if ((LFA_Read(inFileRef, &v1, 1)) == 0) return false; if ((LFA_Read(inFileRef, &v2, 1)) == 0) return false; if ((LFA_Read(inFileRef, &flags, 1)) == 0) return false; if (!ReadSize(inFileRef, 4, dwTagSize)) return false; // Tag size is always using the size reading method. return true;}// =================================================================================================static bool FindXMPFrame ( LFA_FileRef inFileRef, XMP_Int64 & posXMP, XMP_Int64 & posPAD, unsigned long & dwExtendedTag, unsigned long & dwLen ){ // Taking into account that the first Tag is the ID3 tag bool fReturn = false; dwExtendedTag = 0; posPAD = 0; LFA_Seek ( inFileRef, 0ULL, SEEK_SET ); // Read the tag name char szID[4] = {"xxx"}; long bytesRead = LFA_Read ( inFileRef, szID, 3 ); if ( bytesRead == 0 ) return fReturn; // Check for "ID3" if ( strcmp ( szID, "ID3") != 0 ) return fReturn; // Read the version, flag and size XMP_Uns8 v1 = 0, v2 = 0, flags = 0; unsigned long dwTagSize = 0; if ( ! GetTagInfo ( inFileRef, v1, v2, flags, dwTagSize ) ) return fReturn; if ( dwTagSize == 0 ) return fReturn; if ( v1 > 4 ) return fReturn; // We don't support anything newer than id3v2 4.0 // If there's an extended header, ignore it dwExtendedTag = SkipExtendedHeader(inFileRef, v1, flags); dwTagSize -= dwExtendedTag; // Enumerate through the frames XMP_Int64 posCur = 0ULL; posCur = GetFilePosition ( inFileRef ); XMP_Int64 posEnd = posCur + dwTagSize; while ( posCur < posEnd ) { char szFrameID[5] = {"xxxx"}; unsigned long dwFrameSize = 0; XMP_Uns8 cflag1 = 0, cflag2 = 0; // Get the next frame if ( ! GetFrameInfo ( inFileRef, v1, szFrameID, cflag1, cflag2, dwFrameSize ) ) { // Set the file pointer to the XMP or the start LFA_Seek ( inFileRef, fReturn ? posXMP : 0ULL, SEEK_SET ); break; } // Are we in a padding frame? if ( dwFrameSize == 0 ) { // We just hit a padding frame LFA_Seek ( inFileRef, -(long)k_dwFrameHeaderSize, SEEK_CUR ); posPAD = GetFilePosition ( inFileRef ); // Set the file pointer to the XMP or the start LFA_Seek ( inFileRef, fReturn ? posXMP : 0ULL, SEEK_SET ); break; } // Is it a "PRIV"? if ( strcmp(szFrameID, "PRIV") != 0 ) { // Jump to the next frame LFA_Seek ( inFileRef, dwFrameSize, SEEK_CUR ); } else { // Read the "PRIV" frame // <Header for "PRIV"> // Short content descrip. <text string according to encoding> $00 (00) // The actual data <full text string according to encoding> unsigned long dwBytesRead = 0; // Get the PRIV descriptor char szXMPTag[4] = {"xxx"}; if (LFA_Read(inFileRef, &szXMPTag, k_dwXMPLabelSize) == 0) return fReturn; dwBytesRead += k_dwXMPLabelSize; // Is it a XMP "PRIV" if ( (szXMPTag[3] == 0) && (strcmp ( szXMPTag, "XMP" ) == 0) ) { dwLen = dwFrameSize; LFA_Seek ( inFileRef, -(long)k_dwXMPLabelSize, SEEK_CUR ); posXMP = GetFilePosition ( inFileRef ); fReturn = true; dwBytesRead -= k_dwXMPLabelSize; } // Didn't find it, let skip the rest of the frame and continue LFA_Seek ( inFileRef, dwFrameSize - dwBytesRead, SEEK_CUR ); } posCur = GetFilePosition ( inFileRef ); } return fReturn;}// =================================================================================================// Returns the size of the extended headerstatic unsigned long SkipExtendedHeader ( LFA_FileRef inFileRef, XMP_Uns8 bVersion, XMP_Uns8 flags ){ if ( flags & flagExt ) { unsigned long dwExtSize = 0; // <-- This will include the size (full extended header size) if ( ReadSize ( inFileRef, bVersion, dwExtSize ) ) { if ( bVersion < 4 ) dwExtSize += 4; // v3 doesn't include the size, while v4 does. LFA_Seek ( inFileRef, (size_t)(dwExtSize - 4), SEEK_CUR ); } return dwExtSize; } return 0;}// =================================================================================================static bool GetFrameInfo ( LFA_FileRef inFileRef, XMP_Uns8 bVersion, char * strFrameID, XMP_Uns8 & cflag1, XMP_Uns8 & cflag2, unsigned long & dwSize){ // Frame ID $xx xx xx xx (four characters) // Size 4 * %0xxxxxxx <<--- IMPORTANT NOTE: This is true only in v4.0 (v3.0 uses a XMP_Int32) // Flags $xx xx if ( strFrameID == 0 ) return false; if ( LFA_Read ( inFileRef, strFrameID, 4 ) == 0 ) return false; if ( ! ReadSize ( inFileRef, bVersion, dwSize ) ) return false; if ( LFA_Read ( inFileRef, &cflag1, 1 ) == 0 ) return false; if ( LFA_Read ( inFileRef, &cflag2, 1 ) == 0 ) return false; return true;}// =================================================================================================static bool ReadSize ( LFA_FileRef inFileRef, XMP_Uns8 bVersion, unsigned long & dwSize ){ char s4 = 0, s3 = 0, s2 = 0, s1 = 0; if ( LFA_Read ( inFileRef, &s4, 1 ) == 0 ) return false; if ( LFA_Read ( inFileRef, &s3, 1 ) == 0 ) return false; if ( LFA_Read ( inFileRef, &s2, 1 ) == 0 ) return false; if ( LFA_Read ( inFileRef, &s1, 1 ) == 0 ) return false; if ( bVersion > 3 ) { dwSize = ((s4 & 0x7f) << 21) | ((s3 & 0x7f) << 14) | ((s2 & 0x7f) << 7) | (s1 & 0x7f); } else { dwSize = ((s4 << 24) | (s3 << 16) | (s2 << 8) | s1); } return true;}// =================================================================================================static unsigned long CalculateSize ( XMP_Uns8 bVersion, unsigned long dwSizeIn ){ unsigned long dwReturn; if ( bVersion <= 3 ) { dwReturn = dwSizeIn; } else { dwReturn = dwSizeIn & 0x7f; // Expand to 7 bits per byte. dwSizeIn = dwSizeIn >> 7; dwReturn |= ((dwSizeIn & 0x7f) << 8); dwSizeIn = dwSizeIn >> 7; dwReturn |= ((dwSizeIn & 0x7f) << 16); dwSizeIn = dwSizeIn >> 7; dwReturn |= ((dwSizeIn & 0x7f) << 24); } return dwReturn;}} // namespace ID3_Support
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -