aboutsummaryrefslogtreecommitdiff
path: root/Src/id3v2/id3_header_frame.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/id3v2/id3_header_frame.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/id3v2/id3_header_frame.cpp')
-rw-r--r--Src/id3v2/id3_header_frame.cpp181
1 files changed, 181 insertions, 0 deletions
diff --git a/Src/id3v2/id3_header_frame.cpp b/Src/id3v2/id3_header_frame.cpp
new file mode 100644
index 00000000..4f7379bc
--- /dev/null
+++ b/Src/id3v2/id3_header_frame.cpp
@@ -0,0 +1,181 @@
+// The authors have released ID3Lib as Public Domain (PD) and claim no copyright,
+// patent or other intellectual property protection in this work. This means that
+// it may be modified, redistributed and used in commercial and non-commercial
+// software and hardware without restrictions. ID3Lib is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+//
+// The ID3Lib authors encourage improvements and optimisations to be sent to the
+// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved
+// submissions may be altered, and will be included and released under these terms.
+//
+// Mon Nov 23 18:34:01 1998
+
+
+#include <string.h>
+#include <memory.h>
+#include "id3_header_frame.h"
+#include "id3_error.h"
+
+bool ID3_FrameAttr::HasDataLength(int version)
+{
+ if (version == 4)
+ return !!(flags & ID3FL_DATA_LENGTH_2_4);
+ else
+ return 0;
+}
+
+bool ID3_FrameAttr::HasCompression(int version)
+{
+ if (version == 4)
+ return !!(flags & ID3FL_COMPRESSION_2_4);
+ else
+ return !!(flags & ID3FL_COMPRESSION_2_3);
+}
+
+bool ID3_FrameAttr::HasEncryption(int version)
+{
+ if (version == 4)
+ return !!(flags & ID3FL_ENCRYPTION_2_4);
+ else
+ return !!(flags & ID3FL_ENCRYPTION_2_3);
+}
+
+bool ID3_FrameAttr::HasGrouping(int version)
+{
+ if (version == 4)
+ return !!(flags & ID3FL_GROUPING_2_4);
+ else
+ return !!(flags & ID3FL_GROUPING_2_3);
+}
+
+bool ID3_FrameAttr::HasUnsync(int version)
+{
+ if (version == 4)
+ return !!(flags & ID3FL_UNSYNC_2_4);
+ else
+ return false;
+}
+
+void ID3_FrameAttr::ClearUnSync(int version)
+{
+ if (version == 4)
+ flags&= ~ID3FL_UNSYNC_2_4;
+}
+
+void ID3_FrameAttr::SetFlags(luint _flags)
+{
+ flags = _flags;
+}
+
+void ID3_FrameHeader::SetFrameID (ID3_FrameID id)
+{
+ frameID = id;
+}
+
+luint ID3_FrameHeader::Size(void)
+{
+ if (!info)
+ return 0;
+ return info->frameIDBytes + info->frameSizeBytes + info->frameFlagsBytes;
+}
+
+// TODO: benski> we should make a return value of 0 mean 'error'
+luint ID3_FrameHeader::GetFrameInfo(ID3_FrameAttr &attr, const uchar *buffer, size_t remSize)
+{
+ luint posn = 0;
+ luint i = 0, bpos = 4;
+
+ // verify that the text is all between A-Z and 0-9 (for TALB and TIT2, etc)
+ for (i = 0; i < 4; i++)
+ {
+ if (!((buffer[i] >= '0' && buffer[i] <= '9') || (buffer[i] >= 'A' && buffer[i] <= 'Z')))
+ {
+ // TODO: benski> return an error here
+ // this helps us to get ID3v2.2 PIC frames without
+ // breaking others since it's not null-terminated!
+ bpos = i;
+ }
+ }
+
+ memcpy(attr.textID, (char *) buffer, (bpos > 0 && bpos <= 4 ? bpos : 4));
+ if (bpos == 3) attr.textID[3] = 0;
+ attr.textID[4] = 0;
+
+ posn += info->frameIDBytes;
+
+ attr.size = 0;
+
+ for (i = 0; i < info->frameSizeBytes; i++)
+ attr.size |= buffer[posn + i] << ((info->frameSizeBytes - 1 - i) * 8);
+
+ if (version == 4) // 2.4 uses syncsafe sizes
+ {
+ // many programs write non-syncsafe sizes anyway (iTunes is the biggest culprit)
+ // so we'll try to detect it. unfortunately this isn't foolproof
+ int mask = attr.size & 0x80808080;
+ if (!quirks.id3v2_4_itunes_bug // make sure we've havn't previously identified that this tag has a problem
+ && mask == 0) // if none of the 'reserved' bits are set
+ {
+ attr.size = int28().setFromFile(attr.size).get(); // convert to syncsafe value
+ }
+ else
+ {
+ // benski> cut for now. this can't be trusted because it applies on subsequent re-parses but not anything before this
+ // quirks.id3v2_4_itunes_bug = true; // mark that the tag has a problem
+ }
+ // TODO: it'd be nice to look ahead into the buffer and make sure that our calculated size
+ // lets us land on the start of a new frame
+ // although that isn't foolproof either (non-standard fields, etc)
+ }
+ posn += info->frameSizeBytes;
+
+ luint flags=0;
+ flags = 0;
+
+ for (i = 0; i < info->frameFlagsBytes; i++)
+ flags |= buffer[ posn + i ] << ((info->frameFlagsBytes - 1 - i) * 8);
+
+ attr.SetFlags(flags);
+
+ posn += info->frameFlagsBytes;
+
+ return posn;
+}
+
+luint ID3_FrameHeader::Render(uchar *buffer)
+{
+ luint bytesUsed = 0;
+ ID3_FrameDef *frameDef = NULL;
+ char *textID = NULL;
+ luint i;
+
+ if (frameDef = ID3_FindFrameDef(frameID))
+ {
+ if (info->frameIDBytes < strlen (frameDef->longTextID))
+ textID = frameDef->shortTextID;
+ else
+ textID = frameDef->longTextID;
+ }
+ else
+ ID3_THROW (ID3E_InvalidFrameID);
+
+ memcpy (&buffer[ bytesUsed ], (uchar *) textID, info->frameIDBytes);
+ bytesUsed += info->frameIDBytes;
+
+ for (i = 0; i < info->frameSizeBytes; i++)
+ {
+ if (version==4) // 2.4 uses syncsafe sizes
+ buffer[ bytesUsed + i ] = (uchar) ((dataSize >> ((info->frameSizeBytes - i - 1) * 7)) & 0x7F);
+ else
+ buffer[ bytesUsed + i ] = (uchar) ((dataSize >> ((info->frameSizeBytes - i - 1) * 8)) & 0xFF);
+ }
+
+ bytesUsed += info->frameSizeBytes;
+
+ for (i = 0; i < info->frameFlagsBytes; i++)
+ buffer[ bytesUsed + i ] = (uchar) ((flags >> ((info->frameFlagsBytes - i - 1) * 8)) & 0xFF);
+
+ bytesUsed += info->frameFlagsBytes;
+
+ return bytesUsed;
+} \ No newline at end of file