winamp/Src/replicant/nsid3v2/header.cpp
2024-09-24 14:54:57 +02:00

187 lines
3.7 KiB
C++

#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;
}
}