aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/nsid3v2/header.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/replicant/nsid3v2/header.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/replicant/nsid3v2/header.cpp')
-rw-r--r--Src/replicant/nsid3v2/header.cpp186
1 files changed, 186 insertions, 0 deletions
diff --git a/Src/replicant/nsid3v2/header.cpp b/Src/replicant/nsid3v2/header.cpp
new file mode 100644
index 00000000..f006b238
--- /dev/null
+++ b/Src/replicant/nsid3v2/header.cpp
@@ -0,0 +1,186 @@
+#include "header.h"
+#include "values.h"
+#include "util.h"
+#include <assert.h>
+#include "nu/ByteReader.h"
+#include "nu/ByteWriter.h"
+#include <string.h>
+#include "foundation/error.h"
+
+ID3v2::Header::Header()
+{
+ marker[0]=0;
+ marker[1]=0;
+ marker[2]=0;
+ version=0;
+ revision=0;
+ flags=0;
+ size=0;
+}
+
+ID3v2::Header::Header(uint8_t version, uint8_t revision)
+{
+ marker[0]='I';
+ marker[1]='D';
+ marker[2]='3';
+ this->version=version;
+ this->revision=revision;
+ this->flags=0;
+ this->size=0;
+}
+
+ID3v2::Header::Header(const void *data)
+{
+ Parse(data);
+}
+
+
+ID3v2::Header::Header(const ID3v2::Header *copy, uint32_t new_size)
+{
+ marker[0]=copy->marker[0];
+ marker[1]=copy->marker[1];
+ marker[2]=copy->marker[2];
+ version=copy->version;
+ revision=copy->revision;
+ flags=copy->flags;
+ size = Util::Int32To28(new_size);
+}
+
+void ID3v2::Header::Parse(const void *data)
+{
+ bytereader_value_t byte_reader;
+ bytereader_init(&byte_reader, data, Header::SIZE);
+ bytereader_read_n(&byte_reader, &marker, 3);
+ version = bytereader_read_u8(&byte_reader);
+ revision = bytereader_read_u8(&byte_reader);
+ flags = bytereader_read_u8(&byte_reader);
+ size = bytereader_read_u32_be(&byte_reader);
+}
+
+int ID3v2::Header::Serialize(void *data)
+{
+ bytewriter_s byte_writer;
+ bytewriter_init(&byte_writer, data, 10);
+ bytewriter_write_n(&byte_writer, marker, 3);
+ bytewriter_write_u8(&byte_writer, version);
+ bytewriter_write_u8(&byte_writer, revision);
+ bytewriter_write_u8(&byte_writer, flags);
+ bytewriter_write_u32_be(&byte_writer, size);
+ return NErr_Success;
+}
+
+int ID3v2::Header::SerializeAsHeader(void *data)
+{
+ bytewriter_s byte_writer;
+ bytewriter_init(&byte_writer, data, 10);
+ bytewriter_write_n(&byte_writer, "ID3", 3);
+ bytewriter_write_u8(&byte_writer, version);
+ bytewriter_write_u8(&byte_writer, revision);
+ bytewriter_write_u8(&byte_writer, flags);
+ bytewriter_write_u32_be(&byte_writer, size);
+ return NErr_Success;
+}
+
+int ID3v2::Header::SerializeAsFooter(void *data)
+{
+ bytewriter_s byte_writer;
+ bytewriter_init(&byte_writer, data, 10);
+ bytewriter_write_n(&byte_writer, "3DI", 3);
+ bytewriter_write_u8(&byte_writer, version);
+ bytewriter_write_u8(&byte_writer, revision);
+ bytewriter_write_u8(&byte_writer, flags);
+ bytewriter_write_u32_be(&byte_writer, size);
+ return NErr_Success;
+}
+
+bool ID3v2::Header::Valid() const
+{
+ if (marker[0] != 'I'
+ || marker[1] != 'D'
+ || marker[2] != '3')
+ return false;
+
+ if (!Values::KnownVersion(version, revision))
+ return false;
+
+ if (flags & ~Values::ValidHeaderMask(version, revision))
+ return false;
+
+ if (size & 0x80808080)
+ return false;
+
+ return true;
+}
+
+bool ID3v2::Header::FooterValid() const
+{
+ if (marker[0] != '3'
+ || marker[1] != 'D'
+ || marker[2] != 'I')
+ return false;
+
+ if (!Values::KnownVersion(version, revision))
+ return false;
+
+ if (flags & ~Values::ValidHeaderMask(version, revision))
+ return false;
+
+ if (size & 0x80808080)
+ return false;
+
+ return true;
+}
+
+uint32_t ID3v2::Header::TagSize() const
+{
+ uint32_t size = Util::Int28To32(this->size);
+ return size;
+}
+
+bool ID3v2::Header::HasExtendedHeader() const
+{
+ return !!(flags & ID3v2::Values::ExtendedHeaderFlag(version, revision));
+}
+
+uint8_t ID3v2::Header::GetVersion() const
+{
+ return version;
+}
+
+uint8_t ID3v2::Header::GetRevision() const
+{
+ return revision;
+}
+
+bool ID3v2::Header::Unsynchronised() const
+{
+ return !!(flags & (1 << 7));
+}
+
+bool ID3v2::Header::HasFooter() const
+{
+ if (version < 4)
+ return false;
+ return !!(flags & 0x10);
+}
+
+void ID3v2::Header::ClearExtendedHeader()
+{
+ flags &= ~ID3v2::Values::ExtendedHeaderFlag(version, revision);
+}
+
+void ID3v2::Header::ClearUnsynchronized()
+{
+ flags &= ~(1 << 7);
+}
+
+void ID3v2::Header::SetFooter(bool footer)
+{
+ if (version >= 4)
+ {
+ if (footer)
+ flags |= 0x10;
+ else
+ flags &= 0x10;
+ }
+}