mirror of
https://github.com/taglib/taglib.git
synced 2026-06-17 11:49:21 -04:00
Matroska: Fix issues reported by static analysis, formatting, docs
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "ebmlbinaryelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "tfile.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlelement.h"
|
||||
#include "tbytevector.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
@@ -31,20 +32,14 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
BinaryElement(Id id, int sizeLength, offset_t dataSize) :
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
Element(id, sizeLength, dataSize) {}
|
||||
BinaryElement(Id id, int sizeLength, offset_t dataSize, offset_t) :
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
Element(id, sizeLength, dataSize) {}
|
||||
explicit BinaryElement(Id id) :
|
||||
Element(id, 0, 0)
|
||||
{
|
||||
}
|
||||
Element(id, 0, 0) {}
|
||||
|
||||
const ByteVector &getValue() const { return value; }
|
||||
void setValue(const ByteVector &value) { this->value = value; }
|
||||
void setValue(const ByteVector &val) { value = val; }
|
||||
bool read(File &file) override;
|
||||
ByteVector render() override;
|
||||
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
#include "tdebug.h"
|
||||
#include "tutils.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
#define RETURN_ELEMENT_FOR_CASE(eid) \
|
||||
@@ -46,7 +44,7 @@ using namespace TagLib;
|
||||
std::unique_ptr<EBML::Element> EBML::Element::factory(File &file)
|
||||
{
|
||||
// Get the element ID
|
||||
offset_t offset = file.tell();
|
||||
const offset_t offset = file.tell();
|
||||
unsigned int uintId = readId(file);
|
||||
if(!uintId) {
|
||||
debug("Failed to parse EMBL ElementID");
|
||||
@@ -138,12 +136,12 @@ unsigned int EBML::Element::readId(File &file)
|
||||
debug("Failed to read VINT size");
|
||||
return 0;
|
||||
}
|
||||
unsigned int nb_bytes = VINTSizeLength<4>(*buffer.begin());
|
||||
if(!nb_bytes)
|
||||
const unsigned int numBytes = VINTSizeLength<4>(*buffer.begin());
|
||||
if(!numBytes)
|
||||
return 0;
|
||||
if(nb_bytes > 1)
|
||||
buffer.append(file.readBlock(nb_bytes - 1));
|
||||
if(buffer.size() != nb_bytes) {
|
||||
if(numBytes > 1)
|
||||
buffer.append(file.readBlock(numBytes - 1));
|
||||
if(buffer.size() != numBytes) {
|
||||
debug("Failed to read VINT data");
|
||||
return 0;
|
||||
}
|
||||
@@ -169,9 +167,9 @@ ByteVector EBML::Element::render()
|
||||
|
||||
ByteVector EBML::Element::renderId() const
|
||||
{
|
||||
int numBytes = idSize(id);
|
||||
const int numBytes = idSize(id);
|
||||
static const auto byteOrder = Utils::systemByteOrder();
|
||||
auto uintId = static_cast<uint32_t>(id);
|
||||
const auto uintId = static_cast<uint32_t>(id);
|
||||
uint32_t data = byteOrder == Utils::LittleEndian ? Utils::byteSwap(uintId) : uintId;
|
||||
return ByteVector(reinterpret_cast<char *>(&data) + (4 - numBytes), numBytes);
|
||||
}
|
||||
|
||||
@@ -22,233 +22,232 @@
|
||||
#define TAGLIB_EBMLELEMENT_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include "tfile.h"
|
||||
#include "tutils.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib::EBML {
|
||||
class Element
|
||||
{
|
||||
public:
|
||||
enum class Id : unsigned int
|
||||
namespace TagLib
|
||||
{
|
||||
class File;
|
||||
class ByteVector;
|
||||
|
||||
namespace EBML {
|
||||
|
||||
class Element
|
||||
{
|
||||
EBMLHeader = 0x1A45DFA3,
|
||||
DocType = 0x4282,
|
||||
DocTypeVersion = 0x4287,
|
||||
VoidElement = 0xEC,
|
||||
MkSegment = 0x18538067,
|
||||
MkTags = 0x1254C367,
|
||||
MkTag = 0x7373,
|
||||
MkTagTargets = 0x63C0,
|
||||
MkTagTargetTypeValue = 0x68CA,
|
||||
MkTagTrackUID = 0x63C5,
|
||||
MkSimpleTag = 0x67C8,
|
||||
MkTagName = 0x45A3,
|
||||
MkTagLanguage = 0x447A,
|
||||
MkTagBinary = 0x4485,
|
||||
MkTagString = 0x4487,
|
||||
MkTagsTagLanguage = 0x447A,
|
||||
MkTagsLanguageDefault = 0x4484,
|
||||
MkAttachments = 0x1941A469,
|
||||
MkAttachedFile = 0x61A7,
|
||||
MkAttachedFileDescription = 0x467E,
|
||||
MkAttachedFileName = 0x466E,
|
||||
MkAttachedFileMediaType = 0x4660,
|
||||
MkAttachedFileData = 0x465C,
|
||||
MkAttachedFileUID = 0x46AE,
|
||||
MkSeekHead = 0x114D9B74,
|
||||
MkSeek = 0x4DBB,
|
||||
MkSeekID = 0x53AB,
|
||||
MkSeekPosition = 0x53AC,
|
||||
MkCluster = 0x1F43B675,
|
||||
MkCodecState = 0xA4,
|
||||
MkCues = 0x1C53BB6B,
|
||||
MkCuePoint = 0xBB,
|
||||
MkCueTime = 0xB3,
|
||||
MkCueTrackPositions = 0xB7,
|
||||
MkCueTrack = 0xF7,
|
||||
MkCueClusterPosition = 0xF1,
|
||||
MkCueRelativePosition = 0xF0,
|
||||
MkCueDuration = 0xB2,
|
||||
MkCueBlockNumber = 0x5378,
|
||||
MkCueCodecState = 0xEA,
|
||||
MkCueReference = 0xDB,
|
||||
MkCueRefTime = 0x96,
|
||||
MkInfo = 0x1549A966,
|
||||
MkTimestampScale = 0x2AD7B1,
|
||||
MkDuration = 0x4489,
|
||||
MkTitle = 0x7BA9,
|
||||
MkTracks = 0x1654AE6B,
|
||||
MkTrackEntry = 0xAE,
|
||||
MkCodecID = 0x86,
|
||||
MkAudio = 0xE1,
|
||||
MkSamplingFrequency = 0xB5,
|
||||
MkBitDepth = 0x6264,
|
||||
MkChannels = 0x9F,
|
||||
MkChapters = 0x1043A770,
|
||||
MkEditionEntry = 0x45B9,
|
||||
MkEditionUID = 0x45BC,
|
||||
MkEditionFlagDefault = 0x45DB,
|
||||
MkEditionFlagOrdered = 0x45DD,
|
||||
MkChapterAtom = 0xB6,
|
||||
MkChapterUID = 0x73C4,
|
||||
MkChapterTimeStart = 0x91,
|
||||
MkChapterTimeEnd = 0x92,
|
||||
MkChapterFlagHidden = 0x98,
|
||||
MkChapterDisplay = 0x80,
|
||||
MkChapString = 0x85,
|
||||
MkChapLanguage = 0x437C,
|
||||
public:
|
||||
enum class Id : unsigned int
|
||||
{
|
||||
EBMLHeader = 0x1A45DFA3,
|
||||
DocType = 0x4282,
|
||||
DocTypeVersion = 0x4287,
|
||||
VoidElement = 0xEC,
|
||||
MkSegment = 0x18538067,
|
||||
MkTags = 0x1254C367,
|
||||
MkTag = 0x7373,
|
||||
MkTagTargets = 0x63C0,
|
||||
MkTagTargetTypeValue = 0x68CA,
|
||||
MkTagTrackUID = 0x63C5,
|
||||
MkSimpleTag = 0x67C8,
|
||||
MkTagName = 0x45A3,
|
||||
MkTagLanguage = 0x447A,
|
||||
MkTagBinary = 0x4485,
|
||||
MkTagString = 0x4487,
|
||||
MkTagsTagLanguage = 0x447A,
|
||||
MkTagsLanguageDefault = 0x4484,
|
||||
MkAttachments = 0x1941A469,
|
||||
MkAttachedFile = 0x61A7,
|
||||
MkAttachedFileDescription = 0x467E,
|
||||
MkAttachedFileName = 0x466E,
|
||||
MkAttachedFileMediaType = 0x4660,
|
||||
MkAttachedFileData = 0x465C,
|
||||
MkAttachedFileUID = 0x46AE,
|
||||
MkSeekHead = 0x114D9B74,
|
||||
MkSeek = 0x4DBB,
|
||||
MkSeekID = 0x53AB,
|
||||
MkSeekPosition = 0x53AC,
|
||||
MkCluster = 0x1F43B675,
|
||||
MkCodecState = 0xA4,
|
||||
MkCues = 0x1C53BB6B,
|
||||
MkCuePoint = 0xBB,
|
||||
MkCueTime = 0xB3,
|
||||
MkCueTrackPositions = 0xB7,
|
||||
MkCueTrack = 0xF7,
|
||||
MkCueClusterPosition = 0xF1,
|
||||
MkCueRelativePosition = 0xF0,
|
||||
MkCueDuration = 0xB2,
|
||||
MkCueBlockNumber = 0x5378,
|
||||
MkCueCodecState = 0xEA,
|
||||
MkCueReference = 0xDB,
|
||||
MkCueRefTime = 0x96,
|
||||
MkInfo = 0x1549A966,
|
||||
MkTimestampScale = 0x2AD7B1,
|
||||
MkDuration = 0x4489,
|
||||
MkTitle = 0x7BA9,
|
||||
MkTracks = 0x1654AE6B,
|
||||
MkTrackEntry = 0xAE,
|
||||
MkCodecID = 0x86,
|
||||
MkAudio = 0xE1,
|
||||
MkSamplingFrequency = 0xB5,
|
||||
MkBitDepth = 0x6264,
|
||||
MkChannels = 0x9F,
|
||||
MkChapters = 0x1043A770,
|
||||
MkEditionEntry = 0x45B9,
|
||||
MkEditionUID = 0x45BC,
|
||||
MkEditionFlagDefault = 0x45DB,
|
||||
MkEditionFlagOrdered = 0x45DD,
|
||||
MkChapterAtom = 0xB6,
|
||||
MkChapterUID = 0x73C4,
|
||||
MkChapterTimeStart = 0x91,
|
||||
MkChapterTimeEnd = 0x92,
|
||||
MkChapterFlagHidden = 0x98,
|
||||
MkChapterDisplay = 0x80,
|
||||
MkChapString = 0x85,
|
||||
MkChapLanguage = 0x437C,
|
||||
};
|
||||
|
||||
Element(Id id, int sizeLength, offset_t dataSize) :
|
||||
id(id), sizeLength(sizeLength), dataSize(dataSize) {}
|
||||
Element(Id id, int sizeLength, offset_t dataSize, offset_t) :
|
||||
id(id), sizeLength(sizeLength), dataSize(dataSize) {}
|
||||
virtual ~Element() = default;
|
||||
virtual bool read(File &file)
|
||||
{
|
||||
skipData(file);
|
||||
return true;
|
||||
}
|
||||
void skipData(File &file);
|
||||
Id getId() const { return id; }
|
||||
offset_t headSize() const;
|
||||
offset_t getSize() const { return headSize() + dataSize; }
|
||||
int getSizeLength() const { return sizeLength; }
|
||||
int64_t getDataSize() const { return dataSize; }
|
||||
ByteVector renderId() const;
|
||||
virtual ByteVector render();
|
||||
static std::unique_ptr<Element> factory(File &file);
|
||||
static unsigned int readId(File &file);
|
||||
|
||||
protected:
|
||||
Id id;
|
||||
int sizeLength;
|
||||
offset_t dataSize;
|
||||
};
|
||||
|
||||
Element(Id id, int sizeLength, offset_t dataSize) :
|
||||
id(id), sizeLength(sizeLength), dataSize(dataSize)
|
||||
// Template specializations to ensure that elements for the different IDs
|
||||
// are consistently created and cast. They provide a mapping between IDs
|
||||
// and Element subclasses. The switch in factory() makes sure that the
|
||||
// template for all IDs are instantiated, i.e. that every ID has its Element
|
||||
// subclass mapped.
|
||||
class MasterElement;
|
||||
class UIntElement;
|
||||
class BinaryElement;
|
||||
class FloatElement;
|
||||
class MkSegment;
|
||||
class MkInfo;
|
||||
class MkTracks;
|
||||
class MkTags;
|
||||
class MkAttachments;
|
||||
class MkSeekHead;
|
||||
class MkChapters;
|
||||
class MkCues;
|
||||
class VoidElement;
|
||||
class UTF8StringElement;
|
||||
class Latin1StringElement;
|
||||
|
||||
template <Element::Id ID>
|
||||
struct GetElementTypeById;
|
||||
|
||||
template <> struct GetElementTypeById<Element::Id::EBMLHeader> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::DocType> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::DocTypeVersion> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSegment> { using type = MkSegment; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkInfo> { using type = MkInfo; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTracks> { using type = MkTracks; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTags> { using type = MkTags; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachments> { using type = MkAttachments; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTag> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagTargets> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSimpleTag> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFile> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeek> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTrackEntry> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAudio> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCuePoint> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueTrackPositions> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueReference> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCluster> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCues> { using type = MkCues; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagName> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagString> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileName> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileDescription> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagLanguage> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileMediaType> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCodecID> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagTargetTypeValue> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagTrackUID> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileUID> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeekPosition> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTimestampScale> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkBitDepth> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChannels> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueTime> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueTrack> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueClusterPosition> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueRelativePosition> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueDuration> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueBlockNumber> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueCodecState> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueRefTime> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagsLanguageDefault> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileData> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeekID> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagBinary> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCodecState> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkDuration> { using type = FloatElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTitle> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSamplingFrequency> { using type = FloatElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeekHead> { using type = MkSeekHead; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapters> { using type = MkChapters; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkEditionEntry> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkEditionUID> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkEditionFlagDefault> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkEditionFlagOrdered> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterAtom> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterUID> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterTimeStart> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterTimeEnd> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterFlagHidden> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterDisplay> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapString> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapLanguage> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::VoidElement> { using type = VoidElement; };
|
||||
|
||||
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
|
||||
const T *element_cast(const std::unique_ptr<Element> &ptr)
|
||||
{
|
||||
return static_cast<const T *>(ptr.get());
|
||||
}
|
||||
Element(Id id, int sizeLength, offset_t dataSize, offset_t) :
|
||||
id(id), sizeLength(sizeLength), dataSize(dataSize)
|
||||
|
||||
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
|
||||
std::unique_ptr<T> element_cast(std::unique_ptr<Element> &&ptr)
|
||||
{
|
||||
return std::unique_ptr<T>(static_cast<T *>(ptr.release()));
|
||||
}
|
||||
virtual ~Element() = default;
|
||||
virtual bool read(File &file)
|
||||
|
||||
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
|
||||
std::unique_ptr<T> make_unique_element(Element::Id id, int sizeLength, offset_t dataSize, offset_t offset)
|
||||
{
|
||||
skipData(file);
|
||||
return true;
|
||||
return std::make_unique<T>(id, sizeLength, dataSize, offset);
|
||||
}
|
||||
void skipData(File &file);
|
||||
Id getId() const { return id; }
|
||||
offset_t headSize() const;
|
||||
offset_t getSize() const { return headSize() + dataSize; }
|
||||
int getSizeLength() const { return sizeLength; }
|
||||
int64_t getDataSize() const { return dataSize; }
|
||||
ByteVector renderId() const;
|
||||
virtual ByteVector render();
|
||||
static std::unique_ptr<Element> factory(File &file);
|
||||
static unsigned int readId(File &file);
|
||||
|
||||
protected:
|
||||
Id id;
|
||||
int sizeLength;
|
||||
offset_t dataSize;
|
||||
};
|
||||
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
|
||||
std::unique_ptr<T> make_unique_element()
|
||||
{
|
||||
return std::make_unique<T>(ID, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Template specializations to ensure that elements for the different IDs
|
||||
// are consistently created and cast. They provide a mapping between IDs
|
||||
// and Element subclasses. The switch in factory() makes sure that the
|
||||
// template for all IDs are instantiated, i.e. that every ID has its Element
|
||||
// subclass mapped.
|
||||
class MasterElement;
|
||||
class UIntElement;
|
||||
class BinaryElement;
|
||||
class FloatElement;
|
||||
class MkSegment;
|
||||
class MkInfo;
|
||||
class MkTracks;
|
||||
class MkTags;
|
||||
class MkAttachments;
|
||||
class MkSeekHead;
|
||||
class MkChapters;
|
||||
class MkCues;
|
||||
class VoidElement;
|
||||
|
||||
template <String::Type t>
|
||||
class StringElement;
|
||||
using UTF8StringElement = StringElement<String::UTF8>;
|
||||
using Latin1StringElement = StringElement<String::Latin1>;
|
||||
|
||||
template <Element::Id ID>
|
||||
struct GetElementTypeById;
|
||||
|
||||
template <> struct GetElementTypeById<Element::Id::EBMLHeader> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::DocType> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::DocTypeVersion> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSegment> { using type = MkSegment; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkInfo> { using type = MkInfo; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTracks> { using type = MkTracks; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTags> { using type = MkTags; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachments> { using type = MkAttachments; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTag> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagTargets> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSimpleTag> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFile> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeek> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTrackEntry> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAudio> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCuePoint> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueTrackPositions> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueReference> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCluster> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCues> { using type = MkCues; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagName> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagString> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileName> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileDescription> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagLanguage> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileMediaType> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCodecID> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagTargetTypeValue> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagTrackUID> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileUID> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeekPosition> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTimestampScale> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkBitDepth> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChannels> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueTime> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueTrack> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueClusterPosition> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueRelativePosition> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueDuration> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueBlockNumber> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueCodecState> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueRefTime> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagsLanguageDefault> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileData> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeekID> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagBinary> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCodecState> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkDuration> { using type = FloatElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTitle> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSamplingFrequency> { using type = FloatElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeekHead> { using type = MkSeekHead; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapters> { using type = MkChapters; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkEditionEntry> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkEditionUID> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkEditionFlagDefault> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkEditionFlagOrdered> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterAtom> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterUID> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterTimeStart> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterTimeEnd> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterFlagHidden> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterDisplay> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapString> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapLanguage> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::VoidElement> { using type = VoidElement; };
|
||||
|
||||
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
|
||||
const T *element_cast(const std::unique_ptr<Element> &ptr)
|
||||
{
|
||||
return static_cast<const T *>(ptr.get());
|
||||
}
|
||||
|
||||
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
|
||||
std::unique_ptr<T> element_cast(std::unique_ptr<Element> &&ptr)
|
||||
{
|
||||
return std::unique_ptr<T>(static_cast<T *>(ptr.release()));
|
||||
}
|
||||
|
||||
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
|
||||
std::unique_ptr<T> make_unique_element(Element::Id id, int sizeLength, offset_t dataSize, offset_t offset)
|
||||
{
|
||||
return std::make_unique<T>(id, sizeLength, dataSize, offset);
|
||||
}
|
||||
|
||||
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
|
||||
std::unique_ptr<T> make_unique_element()
|
||||
{
|
||||
return std::make_unique<T>(ID, 0, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -44,7 +44,7 @@ double EBML::FloatElement::getValueAsDouble(double defaultValue) const
|
||||
|
||||
bool EBML::FloatElement::read(File &file)
|
||||
{
|
||||
ByteVector buffer = file.readBlock(dataSize);
|
||||
const ByteVector buffer = file.readBlock(dataSize);
|
||||
if(buffer.size() != dataSize) {
|
||||
debug("Failed to read EBML Float element");
|
||||
return false;
|
||||
|
||||
@@ -40,18 +40,12 @@ namespace TagLib {
|
||||
using FloatVariantType = std::variant<std::monostate, float, double>;
|
||||
|
||||
FloatElement(Id id, int sizeLength, offset_t dataSize) :
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
Element(id, sizeLength, dataSize) {}
|
||||
FloatElement(Id id, int sizeLength, offset_t dataSize, offset_t) :
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
Element(id, sizeLength, dataSize) {}
|
||||
explicit FloatElement(Id id) :
|
||||
FloatElement(id, 0, 0)
|
||||
{
|
||||
}
|
||||
FloatElement(id, 0, 0) {}
|
||||
|
||||
FloatVariantType getValue() const { return value; }
|
||||
double getValueAsDouble(double defaultValue = 0.0) const;
|
||||
void setValue(FloatVariantType val) { value = val; }
|
||||
|
||||
@@ -27,14 +27,14 @@ using namespace TagLib;
|
||||
|
||||
EBML::MasterElement::~MasterElement() = default;
|
||||
|
||||
void EBML::MasterElement::appendElement(std::unique_ptr<Element>&& element)
|
||||
void EBML::MasterElement::appendElement(std::unique_ptr<Element> &&element)
|
||||
{
|
||||
elements.push_back(std::move(element));
|
||||
}
|
||||
|
||||
bool EBML::MasterElement::read(File &file)
|
||||
{
|
||||
offset_t maxOffset = file.tell() + dataSize;
|
||||
const offset_t maxOffset = file.tell() + dataSize;
|
||||
std::unique_ptr<Element> element;
|
||||
while((element = findNextElement(file, maxOffset))) {
|
||||
if(!element->read(file))
|
||||
@@ -54,8 +54,8 @@ ByteVector EBML::MasterElement::render()
|
||||
buffer.append(renderVINT(dataSize, 0));
|
||||
buffer.append(data);
|
||||
if(minRenderSize) {
|
||||
auto bufferSize = buffer.size();
|
||||
if(minRenderSize >= bufferSize + MIN_VOID_ELEMENT_SIZE)
|
||||
if(const auto bufferSize = buffer.size();
|
||||
minRenderSize >= bufferSize + MIN_VOID_ELEMENT_SIZE)
|
||||
buffer.append(VoidElement::renderSize(minRenderSize - bufferSize));
|
||||
}
|
||||
return buffer;
|
||||
|
||||
@@ -23,46 +23,46 @@
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlelement.h"
|
||||
#include "tbytevector.h"
|
||||
#include "tlist.h"
|
||||
#include "taglib.h"
|
||||
#include "tlist.h"
|
||||
|
||||
namespace TagLib::EBML {
|
||||
class MasterElement : public Element
|
||||
{
|
||||
public:
|
||||
MasterElement(Id id, int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
Element(id, sizeLength, dataSize), offset(offset)
|
||||
namespace TagLib
|
||||
{
|
||||
class ByteVector;
|
||||
|
||||
namespace EBML {
|
||||
class MasterElement : public Element
|
||||
{
|
||||
}
|
||||
public:
|
||||
MasterElement(Id id, int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
Element(id, sizeLength, dataSize), offset(offset) {}
|
||||
explicit MasterElement(Id id) :
|
||||
Element(id, 0, 0), offset(0) {}
|
||||
~MasterElement() override;
|
||||
|
||||
explicit MasterElement(Id id) :
|
||||
Element(id, 0, 0), offset(0)
|
||||
{
|
||||
}
|
||||
~MasterElement() override;
|
||||
offset_t getOffset() const { return offset; }
|
||||
bool read(File &file) override;
|
||||
ByteVector render() override;
|
||||
void appendElement(std::unique_ptr<Element> &&element);
|
||||
std::list<std::unique_ptr<Element>>::iterator begin() { return elements.begin(); }
|
||||
std::list<std::unique_ptr<Element>>::iterator end() { return elements.end(); }
|
||||
std::list<std::unique_ptr<Element>>::const_iterator begin() const { return elements.begin(); }
|
||||
std::list<std::unique_ptr<Element>>::const_iterator end() const { return elements.end(); }
|
||||
std::list<std::unique_ptr<Element>>::const_iterator cbegin() const { return elements.cbegin(); }
|
||||
std::list<std::unique_ptr<Element>>::const_iterator cend() const { return elements.cend(); }
|
||||
offset_t getPadding() const { return padding; }
|
||||
void setPadding(offset_t padding) { this->padding = padding; }
|
||||
offset_t getMinRenderSize() const { return minRenderSize; }
|
||||
void setMinRenderSize(offset_t minRenderSize) { this->minRenderSize = minRenderSize; }
|
||||
offset_t getOffset() const { return offset; }
|
||||
bool read(File &file) override;
|
||||
ByteVector render() override;
|
||||
void appendElement(std::unique_ptr<Element> &&element);
|
||||
std::list<std::unique_ptr<Element>>::iterator begin() { return elements.begin(); }
|
||||
std::list<std::unique_ptr<Element>>::iterator end() { return elements.end(); }
|
||||
std::list<std::unique_ptr<Element>>::const_iterator begin() const { return elements.begin(); }
|
||||
std::list<std::unique_ptr<Element>>::const_iterator end() const { return elements.end(); }
|
||||
std::list<std::unique_ptr<Element>>::const_iterator cbegin() const { return elements.cbegin(); }
|
||||
std::list<std::unique_ptr<Element>>::const_iterator cend() const { return elements.cend(); }
|
||||
offset_t getPadding() const { return padding; }
|
||||
void setPadding(offset_t numBytes) { padding = numBytes; }
|
||||
offset_t getMinRenderSize() const { return minRenderSize; }
|
||||
void setMinRenderSize(offset_t minimumSize) { minRenderSize = minimumSize; }
|
||||
|
||||
protected:
|
||||
offset_t offset;
|
||||
offset_t padding = 0;
|
||||
offset_t minRenderSize = 0;
|
||||
std::list<std::unique_ptr<Element>> elements;
|
||||
};
|
||||
protected:
|
||||
offset_t offset;
|
||||
offset_t padding = 0;
|
||||
offset_t minRenderSize = 0;
|
||||
std::list<std::unique_ptr<Element>> elements;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
std::unique_ptr<Matroska::Attachments> EBML::MkAttachments::parse()
|
||||
std::unique_ptr<Matroska::Attachments> EBML::MkAttachments::parse() const
|
||||
{
|
||||
auto attachments = std::make_unique<Matroska::Attachments>();
|
||||
attachments->setOffset(offset);
|
||||
@@ -42,17 +42,16 @@ std::unique_ptr<Matroska::Attachments> EBML::MkAttachments::parse()
|
||||
const String *mediaType = nullptr;
|
||||
const ByteVector *data = nullptr;
|
||||
Matroska::AttachedFile::UID uid = 0;
|
||||
auto attachedFile = element_cast<Id::MkAttachedFile>(element);
|
||||
const auto attachedFile = element_cast<Id::MkAttachedFile>(element);
|
||||
for(const auto &attachedFileChild : *attachedFile) {
|
||||
Id id = attachedFileChild->getId();
|
||||
if(id == Id::MkAttachedFileName)
|
||||
filename = &(element_cast<Id::MkAttachedFileName>(attachedFileChild)->getValue());
|
||||
if(const Id id = attachedFileChild->getId(); id == Id::MkAttachedFileName)
|
||||
filename = &element_cast<Id::MkAttachedFileName>(attachedFileChild)->getValue();
|
||||
else if(id == Id::MkAttachedFileData)
|
||||
data = &(element_cast<Id::MkAttachedFileData>(attachedFileChild)->getValue());
|
||||
data = &element_cast<Id::MkAttachedFileData>(attachedFileChild)->getValue();
|
||||
else if(id == Id::MkAttachedFileDescription)
|
||||
description = &(element_cast<Id::MkAttachedFileDescription>(attachedFileChild)->getValue());
|
||||
description = &element_cast<Id::MkAttachedFileDescription>(attachedFileChild)->getValue();
|
||||
else if(id == Id::MkAttachedFileMediaType)
|
||||
mediaType = &(element_cast<Id::MkAttachedFileMediaType>(attachedFileChild)->getValue());
|
||||
mediaType = &element_cast<Id::MkAttachedFileMediaType>(attachedFileChild)->getValue();
|
||||
else if(id == Id::MkAttachedFileUID)
|
||||
uid = element_cast<Id::MkAttachedFileUID>(attachedFileChild)->getValue();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
@@ -35,18 +34,13 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
MkAttachments(int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkAttachments, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkAttachments, sizeLength, dataSize, offset) {}
|
||||
MkAttachments(Id, int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkAttachments, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkAttachments, sizeLength, dataSize, offset) {}
|
||||
MkAttachments() :
|
||||
MasterElement(Id::MkAttachments, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
std::unique_ptr<Matroska::Attachments> parse();
|
||||
MasterElement(Id::MkAttachments, 0, 0, 0) {}
|
||||
|
||||
std::unique_ptr<Matroska::Attachments> parse() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
std::unique_ptr<Matroska::Chapters> EBML::MkChapters::parse()
|
||||
std::unique_ptr<Matroska::Chapters> EBML::MkChapters::parse() const
|
||||
{
|
||||
auto chapters = std::make_unique<Matroska::Chapters>();
|
||||
chapters->setOffset(offset);
|
||||
@@ -45,10 +45,9 @@ std::unique_ptr<Matroska::Chapters> EBML::MkChapters::parse()
|
||||
Matroska::ChapterEdition::UID editionUid = 0;
|
||||
bool editionIsDefault = false;
|
||||
bool editionIsOrdered = false;
|
||||
auto edition = element_cast<Id::MkEditionEntry>(element);
|
||||
const auto edition = element_cast<Id::MkEditionEntry>(element);
|
||||
for(const auto &editionChild : *edition) {
|
||||
Id id = editionChild->getId();
|
||||
if(id == Id::MkEditionUID)
|
||||
if(const Id id = editionChild->getId(); id == Id::MkEditionUID)
|
||||
editionUid = element_cast<Id::MkEditionUID>(editionChild)->getValue();
|
||||
else if(id == Id::MkEditionFlagDefault)
|
||||
editionIsDefault = element_cast<Id::MkEditionFlagDefault>(editionChild)->getValue() != 0;
|
||||
@@ -60,10 +59,9 @@ std::unique_ptr<Matroska::Chapters> EBML::MkChapters::parse()
|
||||
Matroska::Chapter::Time chapterTimeEnd = 0;
|
||||
List<Matroska::Chapter::Display> chapterDisplays;
|
||||
bool chapterHidden = false;
|
||||
auto chapterAtom = element_cast<Id::MkChapterAtom>(editionChild);
|
||||
const auto chapterAtom = element_cast<Id::MkChapterAtom>(editionChild);
|
||||
for(const auto &chapterChild : *chapterAtom) {
|
||||
Id cid = chapterChild->getId();
|
||||
if(cid == Id::MkChapterUID)
|
||||
if(const Id cid = chapterChild->getId(); cid == Id::MkChapterUID)
|
||||
chapterUid = element_cast<Id::MkChapterUID>(chapterChild)->getValue();
|
||||
else if(cid == Id::MkChapterTimeStart)
|
||||
chapterTimeStart = element_cast<Id::MkChapterTimeStart>(chapterChild)->getValue();
|
||||
@@ -72,12 +70,11 @@ std::unique_ptr<Matroska::Chapters> EBML::MkChapters::parse()
|
||||
else if(cid == Id::MkChapterFlagHidden)
|
||||
chapterHidden = element_cast<Id::MkChapterFlagHidden>(chapterChild)->getValue() != 0;
|
||||
else if(cid == Id::MkChapterDisplay) {
|
||||
auto display = element_cast<Id::MkChapterDisplay>(chapterChild);
|
||||
const auto display = element_cast<Id::MkChapterDisplay>(chapterChild);
|
||||
String displayString;
|
||||
String displayLanguage;
|
||||
for(const auto &displayChild : *display) {
|
||||
Id did = displayChild->getId();
|
||||
if(did == Id::MkChapString)
|
||||
if(const Id did = displayChild->getId(); did == Id::MkChapString)
|
||||
displayString = element_cast<Id::MkChapString>(displayChild)->getValue();
|
||||
else if(did == Id::MkChapLanguage)
|
||||
displayLanguage = element_cast<Id::MkChapLanguage>(displayChild)->getValue();
|
||||
|
||||
@@ -39,18 +39,13 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
MkChapters(int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkChapters, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkChapters, sizeLength, dataSize, offset) {}
|
||||
MkChapters(Id, int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkChapters, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkChapters, sizeLength, dataSize, offset) {}
|
||||
MkChapters() :
|
||||
MasterElement(Id::MkChapters, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
std::unique_ptr<Matroska::Chapters> parse();
|
||||
MasterElement(Id::MkChapters, 0, 0, 0) {}
|
||||
|
||||
std::unique_ptr<Matroska::Chapters> parse() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
std::unique_ptr<Matroska::Cues> EBML::MkCues::parse(offset_t segmentDataOffset)
|
||||
std::unique_ptr<Matroska::Cues> EBML::MkCues::parse(offset_t segmentDataOffset) const
|
||||
{
|
||||
auto cues = std::make_unique<Matroska::Cues>(segmentDataOffset);
|
||||
cues->setOffset(offset);
|
||||
@@ -34,19 +34,17 @@ std::unique_ptr<Matroska::Cues> EBML::MkCues::parse(offset_t segmentDataOffset)
|
||||
for(const auto &cuesChild : elements) {
|
||||
if(cuesChild->getId() != Id::MkCuePoint)
|
||||
continue;
|
||||
auto cuePointElement = element_cast<Id::MkCuePoint>(cuesChild);
|
||||
const auto cuePointElement = element_cast<Id::MkCuePoint>(cuesChild);
|
||||
auto cuePoint = std::make_unique<Matroska::CuePoint>();
|
||||
|
||||
for(const auto &cuePointChild : *cuePointElement) {
|
||||
Id id = cuePointChild->getId();
|
||||
if(id == Id::MkCueTime)
|
||||
if(const Id id = cuePointChild->getId(); id == Id::MkCueTime)
|
||||
cuePoint->setTime(element_cast<Id::MkCueTime>(cuePointChild)->getValue());
|
||||
else if(id == Id::MkCueTrackPositions) {
|
||||
auto cueTrack = std::make_unique<Matroska::CueTrack>();
|
||||
auto cueTrackElement = element_cast<Id::MkCueTrackPositions>(cuePointChild);
|
||||
const auto cueTrackElement = element_cast<Id::MkCueTrackPositions>(cuePointChild);
|
||||
for(const auto &cueTrackChild : *cueTrackElement) {
|
||||
Id trackId = cueTrackChild->getId();
|
||||
if(trackId == Id::MkCueTrack)
|
||||
if(const Id trackId = cueTrackChild->getId(); trackId == Id::MkCueTrack)
|
||||
cueTrack->setTrackNumber(element_cast<Id::MkCueTrack>(cueTrackChild)->getValue());
|
||||
else if(trackId == Id::MkCueClusterPosition)
|
||||
cueTrack->setClusterPosition(element_cast<Id::MkCueClusterPosition>(cueTrackChild)->getValue());
|
||||
@@ -59,7 +57,7 @@ std::unique_ptr<Matroska::Cues> EBML::MkCues::parse(offset_t segmentDataOffset)
|
||||
else if(trackId == Id::MkCueCodecState)
|
||||
cueTrack->setCodecState(element_cast<Id::MkCueCodecState>(cueTrackChild)->getValue());
|
||||
else if(trackId == Id::MkCueReference) {
|
||||
auto cueReference = element_cast<Id::MkCueReference>(cueTrackChild);
|
||||
const auto cueReference = element_cast<Id::MkCueReference>(cueTrackChild);
|
||||
for(const auto &cueReferenceChild : *cueReference) {
|
||||
if(cueReferenceChild->getId() != Id::MkCueRefTime)
|
||||
continue;
|
||||
|
||||
@@ -23,32 +23,25 @@
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace Matroska {
|
||||
class Cues;
|
||||
}
|
||||
//class Matroska::Tag;
|
||||
|
||||
namespace EBML {
|
||||
class MkCues : public MasterElement
|
||||
{
|
||||
public:
|
||||
MkCues(int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkCues, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkCues, sizeLength, dataSize, offset) {}
|
||||
MkCues(Id, int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkCues, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkCues, sizeLength, dataSize, offset) {}
|
||||
MkCues() :
|
||||
MasterElement(Id::MkCues, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkCues, 0, 0, 0) {}
|
||||
|
||||
std::unique_ptr<Matroska::Cues> parse(offset_t segmentDataOffset);
|
||||
std::unique_ptr<Matroska::Cues> parse(offset_t segmentDataOffset) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
void EBML::MkInfo::parse(Matroska::Properties *properties)
|
||||
void EBML::MkInfo::parse(Matroska::Properties *properties) const
|
||||
{
|
||||
if(!properties)
|
||||
return;
|
||||
@@ -40,14 +40,13 @@ void EBML::MkInfo::parse(Matroska::Properties *properties)
|
||||
double duration = 0.0;
|
||||
String title;
|
||||
for(const auto &element : elements) {
|
||||
Id id = element->getId();
|
||||
if (id == Id::MkTimestampScale) {
|
||||
if(const Id id = element->getId(); id == Id::MkTimestampScale) {
|
||||
timestampScale = element_cast<Id::MkTimestampScale>(element)->getValue();
|
||||
}
|
||||
else if (id == Id::MkDuration) {
|
||||
else if(id == Id::MkDuration) {
|
||||
duration = element_cast<Id::MkDuration>(element)->getValueAsDouble();
|
||||
}
|
||||
else if (id == Id::MkTitle) {
|
||||
else if(id == Id::MkTitle) {
|
||||
title = element_cast<Id::MkTitle>(element)->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
@@ -40,18 +39,13 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
MkInfo(int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkInfo, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkInfo, sizeLength, dataSize, offset) {}
|
||||
MkInfo(Id, int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkInfo, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkInfo, sizeLength, dataSize, offset) {}
|
||||
MkInfo() :
|
||||
MasterElement(Id::MkInfo, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
void parse(Matroska::Properties * properties);
|
||||
MasterElement(Id::MkInfo, 0, 0, 0) {}
|
||||
|
||||
void parse(Matroska::Properties * properties) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
std::unique_ptr<Matroska::SeekHead> EBML::MkSeekHead::parse(offset_t segmentDataOffset)
|
||||
std::unique_ptr<Matroska::SeekHead> EBML::MkSeekHead::parse(offset_t segmentDataOffset) const
|
||||
{
|
||||
auto seekHead = std::make_unique<Matroska::SeekHead>(segmentDataOffset);
|
||||
seekHead->setOffset(offset);
|
||||
@@ -34,14 +34,13 @@ std::unique_ptr<Matroska::SeekHead> EBML::MkSeekHead::parse(offset_t segmentData
|
||||
for(const auto &element : elements) {
|
||||
if(element->getId() != Id::MkSeek)
|
||||
continue;
|
||||
auto seekElement = element_cast<Id::MkSeek>(element);
|
||||
const auto seekElement = element_cast<Id::MkSeek>(element);
|
||||
Matroska::Element::ID entryId = 0;
|
||||
offset_t offset = 0;
|
||||
for(const auto &seekElementChild : *seekElement) {
|
||||
Id id = seekElementChild->getId();
|
||||
if(id == Id::MkSeekID && !entryId) {
|
||||
auto data = element_cast<Id::MkSeekID>(seekElementChild)->getValue();
|
||||
if(data.size() == 4)
|
||||
if(const Id id = seekElementChild->getId(); id == Id::MkSeekID && !entryId) {
|
||||
if(auto data = element_cast<Id::MkSeekID>(seekElementChild)->getValue();
|
||||
data.size() == 4)
|
||||
entryId = data.toUInt(true);
|
||||
}
|
||||
else if(id == Id::MkSeekPosition && !offset)
|
||||
|
||||
@@ -34,19 +34,13 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
MkSeekHead(int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset) {}
|
||||
MkSeekHead(Id, int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset) {}
|
||||
MkSeekHead() :
|
||||
MasterElement(Id::MkSeekHead, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkSeekHead, 0, 0, 0) {}
|
||||
|
||||
std::unique_ptr<Matroska::SeekHead> parse(offset_t segmentDataOffset);
|
||||
std::unique_ptr<Matroska::SeekHead> parse(offset_t segmentDataOffset) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,13 +39,12 @@ offset_t EBML::MkSegment::segmentDataOffset() const
|
||||
|
||||
bool EBML::MkSegment::read(File &file)
|
||||
{
|
||||
offset_t maxOffset = file.tell() + dataSize;
|
||||
const offset_t maxOffset = file.tell() + dataSize;
|
||||
std::unique_ptr<Element> element;
|
||||
int i = 0;
|
||||
int seekHeadIndex = -1;
|
||||
while((element = findNextElement(file, maxOffset))) {
|
||||
Id id = element->getId();
|
||||
if(id == Id::MkSeekHead) {
|
||||
if(const Id id = element->getId(); id == Id::MkSeekHead) {
|
||||
seekHeadIndex = i;
|
||||
seekHead = element_cast<Id::MkSeekHead>(std::move(element));
|
||||
if(!seekHead->read(file))
|
||||
@@ -94,46 +93,46 @@ bool EBML::MkSegment::read(File &file)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Tag> EBML::MkSegment::parseTag()
|
||||
std::unique_ptr<Matroska::Tag> EBML::MkSegment::parseTag() const
|
||||
{
|
||||
return tags ? tags->parse() : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Attachments> EBML::MkSegment::parseAttachments()
|
||||
std::unique_ptr<Matroska::Attachments> EBML::MkSegment::parseAttachments() const
|
||||
{
|
||||
return attachments ? attachments->parse() : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Chapters> EBML::MkSegment::parseChapters()
|
||||
std::unique_ptr<Matroska::Chapters> EBML::MkSegment::parseChapters() const
|
||||
{
|
||||
return chapters ? chapters->parse() : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::SeekHead> EBML::MkSegment::parseSeekHead()
|
||||
std::unique_ptr<Matroska::SeekHead> EBML::MkSegment::parseSeekHead() const
|
||||
{
|
||||
return seekHead ? seekHead->parse(segmentDataOffset()) : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Cues> EBML::MkSegment::parseCues()
|
||||
std::unique_ptr<Matroska::Cues> EBML::MkSegment::parseCues() const
|
||||
{
|
||||
return cues ? cues->parse(segmentDataOffset()) : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Segment> EBML::MkSegment::parseSegment()
|
||||
std::unique_ptr<Matroska::Segment> EBML::MkSegment::parseSegment() const
|
||||
{
|
||||
return std::make_unique<Matroska::Segment>(sizeLength, dataSize, offset + idSize(id));
|
||||
}
|
||||
|
||||
void EBML::MkSegment::parseInfo(Matroska::Properties *properties)
|
||||
void EBML::MkSegment::parseInfo(Matroska::Properties *properties) const
|
||||
{
|
||||
if(info) {
|
||||
info->parse(properties);
|
||||
}
|
||||
}
|
||||
|
||||
void EBML::MkSegment::parseTracks(Matroska::Properties *properties)
|
||||
void EBML::MkSegment::parseTracks(Matroska::Properties *properties) const
|
||||
{
|
||||
if (tracks) {
|
||||
if(tracks) {
|
||||
tracks->parse(properties);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,20 +49,19 @@ namespace TagLib {
|
||||
{
|
||||
}
|
||||
MkSegment(Id, int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkSegment, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkSegment, sizeLength, dataSize, offset) {}
|
||||
~MkSegment() override;
|
||||
|
||||
offset_t segmentDataOffset() const;
|
||||
bool read(File &file) override;
|
||||
std::unique_ptr<Matroska::Tag> parseTag();
|
||||
std::unique_ptr<Matroska::Attachments> parseAttachments();
|
||||
std::unique_ptr<Matroska::Chapters> parseChapters();
|
||||
std::unique_ptr<Matroska::SeekHead> parseSeekHead();
|
||||
std::unique_ptr<Matroska::Cues> parseCues();
|
||||
std::unique_ptr<Matroska::Segment> parseSegment();
|
||||
void parseInfo(Matroska::Properties *properties);
|
||||
void parseTracks(Matroska::Properties *properties);
|
||||
std::unique_ptr<Matroska::Tag> parseTag() const;
|
||||
std::unique_ptr<Matroska::Attachments> parseAttachments() const;
|
||||
std::unique_ptr<Matroska::Chapters> parseChapters() const;
|
||||
std::unique_ptr<Matroska::SeekHead> parseSeekHead() const;
|
||||
std::unique_ptr<Matroska::Cues> parseCues() const;
|
||||
std::unique_ptr<Matroska::Segment> parseSegment() const;
|
||||
void parseInfo(Matroska::Properties *properties) const;
|
||||
void parseTracks(Matroska::Properties *properties) const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<MkTags> tags;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
std::unique_ptr<Matroska::Tag> EBML::MkTags::parse()
|
||||
std::unique_ptr<Matroska::Tag> EBML::MkTags::parse() const
|
||||
{
|
||||
auto mTag = std::make_unique<Matroska::Tag>();
|
||||
mTag->setOffset(offset);
|
||||
@@ -39,14 +39,13 @@ std::unique_ptr<Matroska::Tag> EBML::MkTags::parse()
|
||||
for(const auto &tagsChild : elements) {
|
||||
if(tagsChild->getId() != Id::MkTag)
|
||||
continue;
|
||||
auto tag = element_cast<Id::MkTag>(tagsChild);
|
||||
const auto tag = element_cast<Id::MkTag>(tagsChild);
|
||||
List<const MasterElement *> simpleTags;
|
||||
const MasterElement *targets = nullptr;
|
||||
|
||||
// Identify the <Targets> element and the <SimpleTag> elements
|
||||
for(const auto &tagChild : *tag) {
|
||||
Id tagChildId = tagChild->getId();
|
||||
if(!targets && tagChildId == Id::MkTagTargets)
|
||||
if(const Id tagChildId = tagChild->getId(); !targets && tagChildId == Id::MkTagTargets)
|
||||
targets = element_cast<Id::MkTagTargets>(tagChild);
|
||||
else if(tagChildId == Id::MkSimpleTag)
|
||||
simpleTags.append(element_cast<Id::MkSimpleTag>(tagChild));
|
||||
@@ -57,8 +56,7 @@ std::unique_ptr<Matroska::Tag> EBML::MkTags::parse()
|
||||
unsigned long long trackUid = 0;
|
||||
if(targets) {
|
||||
for(const auto &targetsChild : *targets) {
|
||||
Id id = targetsChild->getId();
|
||||
if(id == Id::MkTagTargetTypeValue
|
||||
if(const Id id = targetsChild->getId(); id == Id::MkTagTargetTypeValue
|
||||
&& targetTypeValue == Matroska::SimpleTag::TargetTypeValue::None) {
|
||||
targetTypeValue = static_cast<Matroska::SimpleTag::TargetTypeValue>(
|
||||
element_cast<Id::MkTagTargetTypeValue>(targetsChild)->getValue()
|
||||
@@ -71,7 +69,7 @@ std::unique_ptr<Matroska::Tag> EBML::MkTags::parse()
|
||||
}
|
||||
|
||||
// Parse each <SimpleTag>
|
||||
for(auto simpleTag : simpleTags) {
|
||||
for(const auto simpleTag : simpleTags) {
|
||||
const String *tagValueString = nullptr;
|
||||
const ByteVector *tagValueBinary = nullptr;
|
||||
String tagName;
|
||||
@@ -79,13 +77,12 @@ std::unique_ptr<Matroska::Tag> EBML::MkTags::parse()
|
||||
bool defaultLanguageFlag = true;
|
||||
|
||||
for(const auto &simpleTagChild : *simpleTag) {
|
||||
Id id = simpleTagChild->getId();
|
||||
if(id == Id::MkTagName && tagName.isEmpty())
|
||||
if(const Id id = simpleTagChild->getId(); id == Id::MkTagName && tagName.isEmpty())
|
||||
tagName = element_cast<Id::MkTagName>(simpleTagChild)->getValue();
|
||||
else if(id == Id::MkTagString && !tagValueString)
|
||||
tagValueString = &(element_cast<Id::MkTagString>(simpleTagChild)->getValue());
|
||||
tagValueString = &element_cast<Id::MkTagString>(simpleTagChild)->getValue();
|
||||
else if(id == Id::MkTagBinary && !tagValueBinary)
|
||||
tagValueBinary = &(element_cast<Id::MkTagBinary>(simpleTagChild)->getValue());
|
||||
tagValueBinary = &element_cast<Id::MkTagBinary>(simpleTagChild)->getValue();
|
||||
else if(id == Id::MkTagsTagLanguage && language.isEmpty())
|
||||
language = element_cast<Id::MkTagsTagLanguage>(simpleTagChild)->getValue();
|
||||
else if(id == Id::MkTagsLanguageDefault)
|
||||
|
||||
@@ -23,32 +23,25 @@
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace Matroska {
|
||||
class Tag;
|
||||
}
|
||||
//class Matroska::Tag;
|
||||
|
||||
namespace EBML {
|
||||
class MkTags : public MasterElement
|
||||
{
|
||||
public:
|
||||
MkTags(int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkTags, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkTags, sizeLength, dataSize, offset) {}
|
||||
MkTags(Id, int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkTags, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkTags, sizeLength, dataSize, offset) {}
|
||||
MkTags() :
|
||||
MasterElement(Id::MkTags, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkTags, 0, 0, 0) {}
|
||||
|
||||
std::unique_ptr<Matroska::Tag> parse();
|
||||
std::unique_ptr<Matroska::Tag> parse() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
void EBML::MkTracks::parse(Matroska::Properties *properties)
|
||||
void EBML::MkTracks::parse(Matroska::Properties *properties) const
|
||||
{
|
||||
if(!properties)
|
||||
return;
|
||||
@@ -44,16 +44,14 @@ void EBML::MkTracks::parse(Matroska::Properties *properties)
|
||||
double samplingFrequency = 0.0;
|
||||
unsigned long long bitDepth = 0;
|
||||
unsigned long long channels = 0;
|
||||
auto trackEntry = element_cast<Id::MkTrackEntry>(element);
|
||||
const auto trackEntry = element_cast<Id::MkTrackEntry>(element);
|
||||
for(const auto &trackEntryChild : *trackEntry) {
|
||||
Id trackEntryChildId = trackEntryChild->getId();
|
||||
if(trackEntryChildId == Id::MkCodecID)
|
||||
if(const Id trackEntryChildId = trackEntryChild->getId(); trackEntryChildId == Id::MkCodecID)
|
||||
codecId = element_cast<Id::MkCodecID>(trackEntryChild)->getValue();
|
||||
else if(trackEntryChildId == Id::MkAudio) {
|
||||
auto audio = element_cast<Id::MkAudio>(trackEntryChild);
|
||||
const auto audio = element_cast<Id::MkAudio>(trackEntryChild);
|
||||
for(const auto &audioChild : *audio) {
|
||||
Id audioChildId = audioChild->getId();
|
||||
if(audioChildId == Id::MkSamplingFrequency)
|
||||
if(const Id audioChildId = audioChild->getId(); audioChildId == Id::MkSamplingFrequency)
|
||||
samplingFrequency = element_cast<Id::MkSamplingFrequency>(audioChild)->getValueAsDouble();
|
||||
else if(audioChildId == Id::MkBitDepth)
|
||||
bitDepth = element_cast<Id::MkBitDepth>(audioChild)->getValue();
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
@@ -40,18 +39,13 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
MkTracks(int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkTracks, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkTracks, sizeLength, dataSize, offset) {}
|
||||
MkTracks(Id, int sizeLength, offset_t dataSize, offset_t offset) :
|
||||
MasterElement(Id::MkTracks, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
MasterElement(Id::MkTracks, sizeLength, dataSize, offset) {}
|
||||
MkTracks() :
|
||||
MasterElement(Id::MkTracks, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
void parse(Matroska::Properties *properties);
|
||||
MasterElement(Id::MkTracks, 0, 0, 0) {}
|
||||
|
||||
void parse(Matroska::Properties *properties) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,15 +21,13 @@
|
||||
#include "ebmlstringelement.h"
|
||||
#include <string>
|
||||
#include "tfile.h"
|
||||
#include "tstring.h"
|
||||
#include "tbytevector.h"
|
||||
#include "tdebug.h"
|
||||
#include "ebmlutils.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
template <String::Type t>
|
||||
bool EBML::StringElement<t>::read(File &file)
|
||||
bool EBML::StringElement::read(File &file)
|
||||
{
|
||||
ByteVector buffer = file.readBlock(dataSize);
|
||||
if(buffer.size() != dataSize) {
|
||||
@@ -39,24 +37,18 @@ bool EBML::StringElement<t>::read(File &file)
|
||||
|
||||
// The EBML strings aren't supposed to be null-terminated,
|
||||
// but we'll check for it and strip the null terminator if found
|
||||
int nullByte = buffer.find('\0');
|
||||
if(nullByte >= 0)
|
||||
if(const int nullByte = buffer.find('\0'); nullByte >= 0)
|
||||
buffer = ByteVector(buffer.data(), nullByte);
|
||||
value = String(buffer, t);
|
||||
value = String(buffer, encoding);
|
||||
return true;
|
||||
}
|
||||
template bool EBML::StringElement<String::UTF8>::read(File &file);
|
||||
template bool EBML::StringElement<String::Latin1>::read(File &file);
|
||||
|
||||
template <String::Type t>
|
||||
ByteVector EBML::StringElement<t>::render()
|
||||
ByteVector EBML::StringElement::render()
|
||||
{
|
||||
ByteVector buffer = renderId();
|
||||
std::string string = value.to8Bit(t == String::UTF8);
|
||||
const std::string string = value.to8Bit(encoding == String::UTF8);
|
||||
dataSize = string.size();
|
||||
buffer.append(renderVINT(dataSize, 0));
|
||||
buffer.append(ByteVector(string.data(), static_cast<unsigned int>(dataSize)));
|
||||
return buffer;
|
||||
}
|
||||
template ByteVector EBML::StringElement<String::UTF8>::render();
|
||||
template ByteVector EBML::StringElement<String::Latin1>::render();
|
||||
|
||||
@@ -23,40 +23,48 @@
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlelement.h"
|
||||
#include "tbytevector.h"
|
||||
#include "tstring.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
class ByteVector;
|
||||
|
||||
namespace EBML {
|
||||
template <String::Type t>
|
||||
class StringElement : public Element
|
||||
{
|
||||
public:
|
||||
StringElement(Id id, int sizeLength, offset_t dataSize) :
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
StringElement(Id id, int sizeLength, offset_t dataSize, offset_t) :
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
StringElement(String::Type stringEncoding, Id id, int sizeLength, offset_t dataSize) :
|
||||
Element(id, sizeLength, dataSize), encoding(stringEncoding) {}
|
||||
|
||||
explicit StringElement(Id id) :
|
||||
Element(id, 0, 0)
|
||||
{
|
||||
}
|
||||
const String &getValue() const { return value; }
|
||||
void setValue(const String &value) { this->value = value; }
|
||||
void setValue(const String &val) { value = val; }
|
||||
bool read(File &file) override;
|
||||
ByteVector render() override;
|
||||
|
||||
private:
|
||||
String value;
|
||||
String::Type encoding;
|
||||
};
|
||||
|
||||
using UTF8StringElement = StringElement<String::UTF8>;
|
||||
using Latin1StringElement = StringElement<String::Latin1>;
|
||||
class UTF8StringElement : public StringElement {
|
||||
public:
|
||||
UTF8StringElement(Id id, int sizeLength, offset_t dataSize) :
|
||||
StringElement(String::UTF8, id, sizeLength, dataSize) {}
|
||||
UTF8StringElement(Id id, int sizeLength, offset_t dataSize, offset_t) :
|
||||
UTF8StringElement(id, sizeLength, dataSize) {}
|
||||
explicit UTF8StringElement(Id id) :
|
||||
UTF8StringElement(id, 0, 0) {}
|
||||
};
|
||||
|
||||
class Latin1StringElement : public StringElement {
|
||||
public:
|
||||
Latin1StringElement(Id id, int sizeLength, offset_t dataSize) :
|
||||
StringElement(String::Latin1, id, sizeLength, dataSize) {}
|
||||
Latin1StringElement(Id id, int sizeLength, offset_t dataSize, offset_t) :
|
||||
Latin1StringElement(id, sizeLength, dataSize) {}
|
||||
explicit Latin1StringElement(Id id) :
|
||||
Latin1StringElement(id, 0, 0) {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ using namespace TagLib;
|
||||
|
||||
bool EBML::UIntElement::read(File &file)
|
||||
{
|
||||
ByteVector buffer = file.readBlock(dataSize);
|
||||
const ByteVector buffer = file.readBlock(dataSize);
|
||||
if(buffer.size() != dataSize) {
|
||||
debug("Failed to read EBML Uint element");
|
||||
return false;
|
||||
@@ -59,11 +59,11 @@ ByteVector EBML::UIntElement::render()
|
||||
|
||||
ByteVector buffer = renderId();
|
||||
buffer.append(renderVINT(dataSize, 0));
|
||||
uint64_t value = this->value;
|
||||
uint64_t val = value;
|
||||
static const auto byteOrder = Utils::systemByteOrder();
|
||||
if(byteOrder == Utils::LittleEndian)
|
||||
value = Utils::byteSwap(value);
|
||||
val = Utils::byteSwap(val);
|
||||
|
||||
buffer.append(ByteVector(reinterpret_cast<char *>(&value) + (sizeof(value) - dataSize), dataSize));
|
||||
buffer.append(ByteVector(reinterpret_cast<char *>(&val) + (sizeof(val) - dataSize), dataSize));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -32,20 +32,14 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
UIntElement(Id id, int sizeLength, offset_t dataSize) :
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
Element(id, sizeLength, dataSize) {}
|
||||
UIntElement(Id id, int sizeLength, offset_t dataSize, offset_t) :
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
Element(id, sizeLength, dataSize) {}
|
||||
explicit UIntElement(Id id) :
|
||||
UIntElement(id, 0, 0)
|
||||
{
|
||||
}
|
||||
UIntElement(id, 0, 0) {}
|
||||
|
||||
unsigned long long getValue() const { return value; }
|
||||
void setValue(unsigned long long value) { this->value = value; }
|
||||
void setValue(unsigned long long val) { value = val; }
|
||||
bool read(File &file) override;
|
||||
ByteVector render() override;
|
||||
|
||||
|
||||
@@ -18,16 +18,11 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include <random>
|
||||
#include "ebmlutils.h"
|
||||
#include "ebmlelement.h"
|
||||
#include <random>
|
||||
#include "tbytevector.h"
|
||||
#include "matroskafile.h"
|
||||
|
||||
#include "tdebug.h"
|
||||
#include "tutils.h"
|
||||
#include "taglib.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
std::unique_ptr<EBML::Element> EBML::findElement(File &file, Element::Id id, offset_t maxOffset)
|
||||
@@ -63,8 +58,8 @@ std::pair<int, T> EBML::readVINT(File &file)
|
||||
|
||||
if(nb_bytes > 1)
|
||||
buffer.append(file.readBlock(nb_bytes - 1));
|
||||
int bits_to_shift = static_cast<int>(sizeof(T) * 8) - 7 * nb_bytes;
|
||||
offset_t mask = 0xFFFFFFFFFFFFFFFF >> bits_to_shift;
|
||||
const int bitsToShift = static_cast<int>(sizeof(T) * 8) - 7 * nb_bytes;
|
||||
offset_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift;
|
||||
return { nb_bytes, static_cast<T>(buffer.toLongLong(true)) & mask };
|
||||
}
|
||||
namespace TagLib::EBML {
|
||||
@@ -82,8 +77,8 @@ std::pair<int, T> EBML::parseVINT(const ByteVector &buffer)
|
||||
if(!numBytes)
|
||||
return {0, 0};
|
||||
|
||||
int bits_to_shift = static_cast<int>(sizeof(T) * 8) - 7 * numBytes;
|
||||
offset_t mask = 0xFFFFFFFFFFFFFFFF >> bits_to_shift;
|
||||
const int bitsToShift = static_cast<int>(sizeof(T) * 8) - 7 * numBytes;
|
||||
offset_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift;
|
||||
return { numBytes, static_cast<T>(buffer.toLongLong(true)) & mask };
|
||||
}
|
||||
namespace TagLib::EBML {
|
||||
@@ -93,7 +88,7 @@ namespace TagLib::EBML {
|
||||
|
||||
ByteVector EBML::renderVINT(uint64_t number, int minSizeLength)
|
||||
{
|
||||
int numBytes = std::max(minSizeLength, minSize(number));
|
||||
const int numBytes = std::max(minSizeLength, minSize(number));
|
||||
number |= 1ULL << (numBytes * 7);
|
||||
static const auto byteOrder = Utils::systemByteOrder();
|
||||
if(byteOrder == Utils::LittleEndian)
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "tutils.h"
|
||||
#include "tdebug.h"
|
||||
#include "ebmlelement.h"
|
||||
#include "tbytevector.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
@@ -68,29 +67,27 @@ namespace TagLib {
|
||||
{
|
||||
if(data <= 0x7Fu)
|
||||
return 1;
|
||||
else if(data <= 0x3FFFu)
|
||||
if(data <= 0x3FFFu)
|
||||
return 2;
|
||||
else if(data <= 0x1FFFFFu)
|
||||
if(data <= 0x1FFFFFu)
|
||||
return 3;
|
||||
else if(data <= 0xFFFFFFFu)
|
||||
if(data <= 0xFFFFFFFu)
|
||||
return 4;
|
||||
else if(data <= 0x7FFFFFFFFu)
|
||||
if(data <= 0x7FFFFFFFFu)
|
||||
return 5;
|
||||
else
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
constexpr int idSize(Element::Id id)
|
||||
{
|
||||
auto uintId = static_cast<unsigned int>(id);
|
||||
const auto uintId = static_cast<unsigned int>(id);
|
||||
if(uintId <= 0xFF)
|
||||
return 1;
|
||||
else if(uintId <= 0xFFFF)
|
||||
if(uintId <= 0xFFFF)
|
||||
return 2;
|
||||
else if(uintId <= 0xFFFFFF)
|
||||
if(uintId <= 0xFFFFFF)
|
||||
return 3;
|
||||
else
|
||||
return 4;
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,10 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlvoidelement.h"
|
||||
#include <algorithm>
|
||||
#include "ebmlutils.h"
|
||||
#include "tbytevector.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
ByteVector EBML::VoidElement::render()
|
||||
@@ -46,9 +45,9 @@ offset_t EBML::VoidElement::getTargetSize() const
|
||||
return targetSize;
|
||||
}
|
||||
|
||||
void EBML::VoidElement::setTargetSize(offset_t targetSize)
|
||||
void EBML::VoidElement::setTargetSize(offset_t size)
|
||||
{
|
||||
this->targetSize = std::max(targetSize, MIN_VOID_ELEMENT_SIZE);
|
||||
this->targetSize = std::max(size, MIN_VOID_ELEMENT_SIZE);
|
||||
}
|
||||
|
||||
ByteVector EBML::VoidElement::renderSize(offset_t targetSize)
|
||||
|
||||
@@ -33,17 +33,15 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
VoidElement(int sizeLength, offset_t dataSize) :
|
||||
Element(Id::VoidElement, sizeLength, dataSize)
|
||||
{}
|
||||
Element(Id::VoidElement, sizeLength, dataSize) {}
|
||||
VoidElement(Id, int sizeLength, offset_t dataSize, offset_t) :
|
||||
Element(Id::VoidElement, sizeLength, dataSize)
|
||||
{}
|
||||
Element(Id::VoidElement, sizeLength, dataSize) {}
|
||||
VoidElement() :
|
||||
Element(Id::VoidElement, 0, 0)
|
||||
{}
|
||||
Element(Id::VoidElement, 0, 0) {}
|
||||
|
||||
ByteVector render() override;
|
||||
offset_t getTargetSize() const;
|
||||
void setTargetSize(offset_t targetSize);
|
||||
void setTargetSize(offset_t size);
|
||||
static ByteVector renderSize(offset_t targetSize);
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
@@ -50,11 +50,11 @@ Matroska::AttachedFile::AttachedFile(const AttachedFile &other) :
|
||||
{
|
||||
}
|
||||
|
||||
Matroska::AttachedFile::AttachedFile(AttachedFile&& other) noexcept = default;
|
||||
Matroska::AttachedFile::AttachedFile(AttachedFile &&other) noexcept = default;
|
||||
|
||||
Matroska::AttachedFile::~AttachedFile() = default;
|
||||
|
||||
Matroska::AttachedFile &Matroska::AttachedFile::operator=(AttachedFile &&other) = default;
|
||||
Matroska::AttachedFile &Matroska::AttachedFile::operator=(AttachedFile &&other) noexcept = default;
|
||||
|
||||
Matroska::AttachedFile &Matroska::AttachedFile::operator=(const AttachedFile &other)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,12 @@ namespace TagLib {
|
||||
class TAGLIB_EXPORT AttachedFile
|
||||
{
|
||||
public:
|
||||
//! Unique identifier.
|
||||
using UID = unsigned long long;
|
||||
|
||||
/*!
|
||||
* Construct an attached file.
|
||||
*/
|
||||
AttachedFile();
|
||||
|
||||
/*!
|
||||
@@ -58,7 +63,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Moves the contents of \a other into this object.
|
||||
*/
|
||||
AttachedFile &operator=(AttachedFile &&other);
|
||||
AttachedFile &operator=(AttachedFile &&other) noexcept;
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the object with the content of \a other.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
@@ -19,13 +19,13 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "matroskaattachments.h"
|
||||
#include <memory>
|
||||
#include "matroskaattachedfile.h"
|
||||
#include "ebmlmkattachments.h"
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmlstringelement.h"
|
||||
#include "ebmlbinaryelement.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "tlist.h"
|
||||
#include "tbytevector.h"
|
||||
|
||||
@@ -53,7 +53,7 @@ Matroska::Attachments::Attachments() :
|
||||
|
||||
Matroska::Attachments::~Attachments() = default;
|
||||
|
||||
void Matroska::Attachments::addAttachedFile(const AttachedFile& file)
|
||||
void Matroska::Attachments::addAttachedFile(const AttachedFile &file)
|
||||
{
|
||||
d->files.append(file);
|
||||
setNeedsRender(true);
|
||||
@@ -61,8 +61,8 @@ void Matroska::Attachments::addAttachedFile(const AttachedFile& file)
|
||||
|
||||
void Matroska::Attachments::removeAttachedFile(unsigned long long uid)
|
||||
{
|
||||
auto it = std::find_if(d->files.begin(), d->files.end(),
|
||||
[uid](const AttachedFile& file) {
|
||||
const auto it = std::find_if(d->files.begin(), d->files.end(),
|
||||
[uid](const AttachedFile &file) {
|
||||
return file.uid() == uid;
|
||||
});
|
||||
if(it != d->files.end()) {
|
||||
@@ -109,14 +109,15 @@ ByteVector Matroska::Attachments::renderInternal()
|
||||
attachedFileElement->appendElement(std::move(fileNameElement));
|
||||
|
||||
// Media/MIME type
|
||||
auto mediaTypeElement = EBML::make_unique_element<EBML::Element::Id::MkAttachedFileMediaType>();
|
||||
auto mediaTypeElement =
|
||||
EBML::make_unique_element<EBML::Element::Id::MkAttachedFileMediaType>();
|
||||
mediaTypeElement->setValue(attachedFile.mediaType());
|
||||
attachedFileElement->appendElement(std::move(mediaTypeElement));
|
||||
|
||||
// Description
|
||||
const String &description = attachedFile.description();
|
||||
if(!description.isEmpty()) {
|
||||
auto descriptionElement = EBML::make_unique_element<EBML::Element::Id::MkAttachedFileDescription>();
|
||||
if(const String &description = attachedFile.description(); !description.isEmpty()) {
|
||||
auto descriptionElement =
|
||||
EBML::make_unique_element<EBML::Element::Id::MkAttachedFileDescription>();
|
||||
descriptionElement->setValue(description);
|
||||
attachedFileElement->appendElement(std::move(descriptionElement));
|
||||
}
|
||||
|
||||
@@ -42,11 +42,13 @@ namespace TagLib {
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
//! List of attached files.
|
||||
using AttachedFileList = List<AttachedFile>;
|
||||
|
||||
//! Construct attachments.
|
||||
Attachments();
|
||||
|
||||
//! Destroy attachements.
|
||||
//! Destroy attachments.
|
||||
virtual ~Attachments();
|
||||
|
||||
//! Add an attached file.
|
||||
@@ -55,7 +57,7 @@ namespace TagLib {
|
||||
//! Remove an attached file.
|
||||
void removeAttachedFile(unsigned long long uid);
|
||||
|
||||
//! Remove an attached file.
|
||||
//! Remove all attached files.
|
||||
void clear();
|
||||
|
||||
//! Get list of all attached files.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
@@ -109,7 +109,7 @@ bool Matroska::Chapter::isHidden() const
|
||||
return d->hidden;
|
||||
}
|
||||
|
||||
const List<Matroska::Chapter::Display>& Matroska::Chapter::displayList() const
|
||||
const List<Matroska::Chapter::Display> &Matroska::Chapter::displayList() const
|
||||
{
|
||||
return d->displayList;
|
||||
}
|
||||
@@ -130,13 +130,14 @@ Matroska::Chapter::Display::Display(Display &&other) noexcept = default;
|
||||
|
||||
Matroska::Chapter::Display::~Display() = default;
|
||||
|
||||
Matroska::Chapter::Display& Matroska::Chapter::Display::operator=(const Display &other)
|
||||
Matroska::Chapter::Display &Matroska::Chapter::Display::operator=(const Display &other)
|
||||
{
|
||||
Display(other).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Matroska::Chapter::Display& Matroska::Chapter::Display::operator=(Display &&other) noexcept = default;
|
||||
Matroska::Chapter::Display &Matroska::Chapter::Display::operator=(
|
||||
Display &&other) noexcept = default;
|
||||
|
||||
void Matroska::Chapter::Display::swap(Display &other) noexcept
|
||||
{
|
||||
@@ -145,12 +146,12 @@ void Matroska::Chapter::Display::swap(Display &other) noexcept
|
||||
swap(d, other.d);
|
||||
}
|
||||
|
||||
const String& Matroska::Chapter::Display::string() const
|
||||
const String &Matroska::Chapter::Display::string() const
|
||||
{
|
||||
return d->string;
|
||||
}
|
||||
|
||||
const String& Matroska::Chapter::Display::language() const
|
||||
const String &Matroska::Chapter::Display::language() const
|
||||
{
|
||||
return d->language;
|
||||
}
|
||||
|
||||
@@ -31,18 +31,22 @@
|
||||
#include "tlist.h"
|
||||
|
||||
namespace TagLib {
|
||||
class String;
|
||||
class ByteVector;
|
||||
|
||||
namespace EBML {
|
||||
class MkChapters;
|
||||
}
|
||||
|
||||
class String;
|
||||
class ByteVector;
|
||||
namespace Matroska {
|
||||
//! Matroska chapter.
|
||||
class TAGLIB_EXPORT Chapter
|
||||
{
|
||||
public:
|
||||
//! Unique identifier.
|
||||
using UID = unsigned long long;
|
||||
|
||||
//! Timestamp in nanoseconds.
|
||||
using Time = unsigned long long;
|
||||
|
||||
/*!
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
@@ -61,11 +61,12 @@ Matroska::ChapterEdition::ChapterEdition(const ChapterEdition &other) :
|
||||
{
|
||||
}
|
||||
|
||||
Matroska::ChapterEdition::ChapterEdition(ChapterEdition&& other) noexcept = default;
|
||||
Matroska::ChapterEdition::ChapterEdition(ChapterEdition &&other) noexcept = default;
|
||||
|
||||
Matroska::ChapterEdition::~ChapterEdition() = default;
|
||||
|
||||
Matroska::ChapterEdition &Matroska::ChapterEdition::operator=(ChapterEdition &&other) = default;
|
||||
Matroska::ChapterEdition &Matroska::ChapterEdition::operator=(
|
||||
ChapterEdition &&other) noexcept = default;
|
||||
|
||||
Matroska::ChapterEdition &Matroska::ChapterEdition::operator=(const ChapterEdition &other)
|
||||
{
|
||||
|
||||
@@ -31,11 +31,13 @@
|
||||
namespace TagLib {
|
||||
class String;
|
||||
class ByteVector;
|
||||
|
||||
namespace Matroska {
|
||||
//! Edition of chapters.
|
||||
class TAGLIB_EXPORT ChapterEdition
|
||||
{
|
||||
public:
|
||||
//! Unique identifier.
|
||||
using UID = unsigned long long;
|
||||
|
||||
/*!
|
||||
@@ -67,7 +69,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Moves the contents of \a other into this object.
|
||||
*/
|
||||
ChapterEdition &operator=(ChapterEdition &&other);
|
||||
ChapterEdition &operator=(ChapterEdition &&other) noexcept;
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the object with the content of \a other.
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "matroskachapters.h"
|
||||
#include <memory>
|
||||
#include "matroskachapteredition.h"
|
||||
#include "ebmlstringelement.h"
|
||||
#include "ebmlbinaryelement.h"
|
||||
@@ -58,7 +57,7 @@ Matroska::Chapters::Chapters() :
|
||||
|
||||
Matroska::Chapters::~Chapters() = default;
|
||||
|
||||
void Matroska::Chapters::addChapterEdition(const ChapterEdition& edition)
|
||||
void Matroska::Chapters::addChapterEdition(const ChapterEdition &edition)
|
||||
{
|
||||
d->editions.append(edition);
|
||||
setNeedsRender(true);
|
||||
@@ -66,8 +65,8 @@ void Matroska::Chapters::addChapterEdition(const ChapterEdition& edition)
|
||||
|
||||
void Matroska::Chapters::removeChapterEdition(unsigned long long uid)
|
||||
{
|
||||
auto it = std::find_if(d->editions.begin(), d->editions.end(),
|
||||
[uid](const ChapterEdition& file) {
|
||||
const auto it = std::find_if(d->editions.begin(), d->editions.end(),
|
||||
[uid](const ChapterEdition &file) {
|
||||
return file.uid() == uid;
|
||||
});
|
||||
if(it != d->editions.end()) {
|
||||
@@ -101,7 +100,7 @@ ByteVector Matroska::Chapters::renderInternal()
|
||||
for(const auto &chapterEdition : std::as_const(d->editions)) {
|
||||
auto chapterEditionElement = EBML::make_unique_element<EBML::Element::Id::MkEditionEntry>();
|
||||
|
||||
if(auto uid = chapterEdition.uid()) {
|
||||
if(const auto uid = chapterEdition.uid()) {
|
||||
auto uidElement = EBML::make_unique_element<EBML::Element::Id::MkEditionUID>();
|
||||
uidElement->setValue(uid);
|
||||
chapterEditionElement->appendElement(std::move(uidElement));
|
||||
@@ -117,7 +116,7 @@ ByteVector Matroska::Chapters::renderInternal()
|
||||
auto chapterElement = EBML::make_unique_element<EBML::Element::Id::MkChapterAtom>();
|
||||
|
||||
auto cuidElement = EBML::make_unique_element<EBML::Element::Id::MkChapterUID>();
|
||||
auto cuid = chapter.uid();
|
||||
const auto cuid = chapter.uid();
|
||||
cuidElement->setValue(cuid ? cuid : EBML::randomUID());
|
||||
chapterElement->appendElement(std::move(cuidElement));
|
||||
auto timeStartElement = EBML::make_unique_element<EBML::Element::Id::MkChapterTimeStart>();
|
||||
@@ -130,7 +129,7 @@ ByteVector Matroska::Chapters::renderInternal()
|
||||
hiddenElement->setValue(chapter.isHidden());
|
||||
chapterElement->appendElement(std::move(hiddenElement));
|
||||
|
||||
for(const auto& display : chapter.displayList()) {
|
||||
for(const auto &display : chapter.displayList()) {
|
||||
auto displayElement = EBML::make_unique_element<EBML::Element::Id::MkChapterDisplay>();
|
||||
|
||||
auto stringElement = EBML::make_unique_element<EBML::Element::Id::MkChapString>();
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
|
||||
namespace EBML {
|
||||
class MkChapters;
|
||||
}
|
||||
@@ -47,7 +48,9 @@ namespace TagLib {
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
//! List of chapter editions.
|
||||
using ChapterEditionList = List<ChapterEdition>;
|
||||
|
||||
//! Construct chapters.
|
||||
Chapters();
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ Matroska::Cues::Cues(offset_t segmentDataOffset) :
|
||||
|
||||
ByteVector Matroska::Cues::renderInternal()
|
||||
{
|
||||
auto beforeSize = sizeRenderedOrWritten();
|
||||
const auto beforeSize = sizeRenderedOrWritten();
|
||||
EBML::MkCues cues;
|
||||
cues.setMinRenderSize(beforeSize);
|
||||
for(const auto &cuePoint : cuePoints) {
|
||||
@@ -90,10 +90,9 @@ ByteVector Matroska::Cues::renderInternal()
|
||||
}
|
||||
|
||||
// Reference times
|
||||
auto referenceTimes = cueTrack->referenceTimes();
|
||||
if(!referenceTimes.isEmpty()) {
|
||||
if(auto referenceTimes = cueTrack->referenceTimes(); !referenceTimes.isEmpty()) {
|
||||
auto cueReference = EBML::make_unique_element<EBML::Element::Id::MkCueReference>();
|
||||
for(auto reference : referenceTimes) {
|
||||
for(const auto reference : referenceTimes) {
|
||||
auto refTime = EBML::make_unique_element<EBML::Element::Id::MkCueRefTime>();
|
||||
refTime->setValue(reference);
|
||||
cueReference->appendElement(std::move(refTime));
|
||||
@@ -107,7 +106,7 @@ ByteVector Matroska::Cues::renderInternal()
|
||||
return cues.render();
|
||||
}
|
||||
|
||||
void Matroska::Cues::write(TagLib::File& file)
|
||||
void Matroska::Cues::write(TagLib::File &file)
|
||||
{
|
||||
if(!data().isEmpty())
|
||||
Element::write(file);
|
||||
@@ -119,8 +118,8 @@ bool Matroska::Cues::sizeChanged(Element &caller, offset_t delta)
|
||||
if(!Element::sizeChanged(caller, delta))
|
||||
return false;
|
||||
|
||||
offset_t offset = caller.offset() - segmentDataOffset;
|
||||
for(auto &cuePoint : cuePoints) {
|
||||
const offset_t offset = caller.offset() - segmentDataOffset;
|
||||
for(const auto &cuePoint : cuePoints) {
|
||||
if(cuePoint->adjustOffset(offset, delta)) {
|
||||
setNeedsRender(true);
|
||||
}
|
||||
@@ -142,9 +141,7 @@ void Matroska::Cues::addCuePoint(std::unique_ptr<CuePoint> &&cuePoint)
|
||||
cuePoints.push_back(std::move(cuePoint));
|
||||
}
|
||||
|
||||
Matroska::CuePoint::CuePoint()
|
||||
{
|
||||
}
|
||||
Matroska::CuePoint::CuePoint() = default;
|
||||
|
||||
bool Matroska::CuePoint::isValid(TagLib::File &file, offset_t segmentDataOffset) const
|
||||
{
|
||||
@@ -163,7 +160,7 @@ void Matroska::CuePoint::addCueTrack(std::unique_ptr<CueTrack> &&cueTrack)
|
||||
bool Matroska::CuePoint::adjustOffset(offset_t offset, offset_t delta)
|
||||
{
|
||||
bool ret = false;
|
||||
for(auto &cueTrack : cueTracks)
|
||||
for(const auto &cueTrack : cueTracks)
|
||||
ret |= cueTrack->adjustOffset(offset, delta);
|
||||
|
||||
return ret;
|
||||
@@ -201,8 +198,8 @@ bool Matroska::CueTrack::adjustOffset(offset_t offset, offset_t delta)
|
||||
clusterPosition += delta;
|
||||
ret = true;
|
||||
}
|
||||
offset_t codecStateValue;
|
||||
if(codecState.has_value() && (codecStateValue = codecState.value()) != 0 &&
|
||||
if(offset_t codecStateValue;
|
||||
codecState.has_value() && (codecStateValue = codecState.value()) != 0 &&
|
||||
codecStateValue > offset) {
|
||||
codecState = codecStateValue + delta;
|
||||
ret = true;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
|
||||
namespace EBML {
|
||||
class MkCues;
|
||||
}
|
||||
@@ -36,6 +37,7 @@ namespace TagLib {
|
||||
namespace Matroska {
|
||||
class CuePoint;
|
||||
class CueTrack;
|
||||
|
||||
class Cues : public Element
|
||||
{
|
||||
public:
|
||||
@@ -66,7 +68,7 @@ namespace TagLib {
|
||||
bool isValid(TagLib::File &file, offset_t segmentDataOffset) const;
|
||||
void addCueTrack(std::unique_ptr<CueTrack> &&cueTrack);
|
||||
const CueTrackList &cueTrackList() const { return cueTracks; }
|
||||
void setTime(Time time) { this->time = time; }
|
||||
void setTime(Time timestamp) { time = timestamp; }
|
||||
Time getTime() const { return time; }
|
||||
bool adjustOffset(offset_t offset, offset_t delta);
|
||||
|
||||
@@ -82,17 +84,17 @@ namespace TagLib {
|
||||
CueTrack() = default;
|
||||
~CueTrack() = default;
|
||||
bool isValid(TagLib::File &file, offset_t segmentDataOffset) const;
|
||||
void setTrackNumber(unsigned long long trackNumber) { this->trackNumber = trackNumber; }
|
||||
void setTrackNumber(unsigned long long trackNr) { trackNumber = trackNr; }
|
||||
unsigned long long getTrackNumber() const { return trackNumber; }
|
||||
void setClusterPosition(offset_t clusterPosition) { this->clusterPosition = clusterPosition; }
|
||||
void setClusterPosition(offset_t clusterPos) { clusterPosition = clusterPos; }
|
||||
offset_t getClusterPosition() const { return clusterPosition; }
|
||||
void setRelativePosition(std::optional<offset_t> relativePosition) { this->relativePosition = relativePosition; }
|
||||
void setRelativePosition(std::optional<offset_t> relativePos) { relativePosition = relativePos; }
|
||||
std::optional<offset_t> getRelativePosition() const { return relativePosition; }
|
||||
void setCodecState(std::optional<offset_t> codecState) { this->codecState = codecState; }
|
||||
void setCodecState(std::optional<offset_t> codecStatePos) { codecState = codecStatePos; }
|
||||
std::optional<offset_t> getCodecState() const { return codecState; }
|
||||
void setBlockNumber(std::optional<unsigned long long> blockNumber) { this->blockNumber = blockNumber; }
|
||||
void setBlockNumber(std::optional<unsigned long long> blockNr) { blockNumber = blockNr; }
|
||||
std::optional<unsigned long long> getBlockNumber() const { return blockNumber; }
|
||||
void setDuration(std::optional<unsigned long long> duration) { this->duration = duration; }
|
||||
void setDuration(std::optional<unsigned long long> segmentTicks) { duration = segmentTicks; }
|
||||
std::optional<unsigned long long> getDuration() const { return duration; }
|
||||
void addReferenceTime(unsigned long long refTime) { refTimes.append(refTime); }
|
||||
const ReferenceTimeList &referenceTimes() const { return refTimes; }
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
#include <memory>
|
||||
|
||||
#include "matroskaelement.h"
|
||||
#include <memory>
|
||||
#include "tlist.h"
|
||||
#include "tfile.h"
|
||||
#include "tbytevector.h"
|
||||
@@ -48,6 +49,7 @@ Matroska::Element::Element(ID id) :
|
||||
{
|
||||
e->id = id;
|
||||
}
|
||||
|
||||
Matroska::Element::~Element() = default;
|
||||
|
||||
offset_t Matroska::Element::size() const
|
||||
@@ -110,11 +112,10 @@ bool Matroska::Element::render()
|
||||
if(!needsRender())
|
||||
return true;
|
||||
|
||||
auto beforeSize = sizeRenderedOrWritten();
|
||||
auto data = renderInternal();
|
||||
const auto beforeSize = sizeRenderedOrWritten();
|
||||
const auto data = renderInternal();
|
||||
setNeedsRender(false);
|
||||
auto afterSize = data.size();
|
||||
if(afterSize != beforeSize) {
|
||||
if(const auto afterSize = data.size(); afterSize != beforeSize) {
|
||||
if(!emitSizeChanged(afterSize - beforeSize)) {
|
||||
return false;
|
||||
}
|
||||
@@ -136,7 +137,7 @@ bool Matroska::Element::needsRender() const
|
||||
|
||||
bool Matroska::Element::emitSizeChanged(offset_t delta)
|
||||
{
|
||||
for(auto element : e->sizeListeners) {
|
||||
for(const auto element : e->sizeListeners) {
|
||||
if(!element->sizeChanged(*this, delta))
|
||||
return false;
|
||||
}
|
||||
@@ -156,7 +157,7 @@ bool Matroska::Element::sizeChanged(Element &caller, offset_t delta)
|
||||
|
||||
offset_t Matroska::Element::sizeRenderedOrWritten() const
|
||||
{
|
||||
offset_t dataSize = e->data.size();
|
||||
const offset_t dataSize = e->data.size();
|
||||
return dataSize != 0 ? dataSize : e->size;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,11 +25,12 @@
|
||||
#include <memory>
|
||||
#include "taglib_export.h"
|
||||
#include "taglib.h"
|
||||
#include "tbytevector.h"
|
||||
#include "tlist.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
class ByteVector;
|
||||
|
||||
namespace Matroska {
|
||||
class TAGLIB_EXPORT Element
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "matroskafile.h"
|
||||
#include <memory>
|
||||
#include "matroskatag.h"
|
||||
#include "matroskaattachments.h"
|
||||
#include "matroskaattachedfile.h"
|
||||
@@ -38,8 +39,6 @@
|
||||
#include "tagutils.h"
|
||||
#include "tpropertymap.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
class Matroska::File::FilePrivate
|
||||
@@ -177,8 +176,8 @@ StringList Matroska::File::complexPropertyKeys() const
|
||||
if(d->attachments) {
|
||||
const auto &attachedFiles = d->attachments->attachedFileList();
|
||||
for(const auto &attachedFile : attachedFiles) {
|
||||
String key = keyForAttachedFile(attachedFile);
|
||||
if(!key.isEmpty() && !keys.contains(key)) {
|
||||
if(String key = keyForAttachedFile(attachedFile);
|
||||
!key.isEmpty() && !keys.contains(key)) {
|
||||
keys.append(key);
|
||||
}
|
||||
}
|
||||
@@ -196,27 +195,27 @@ List<VariantMap> Matroska::File::complexProperties(const String &key) const
|
||||
if(d->chapters) {
|
||||
for(const auto &edition : d->chapters->chapterEditionList()) {
|
||||
VariantMap property;
|
||||
if(auto uid = edition.uid()) {
|
||||
if(const auto uid = edition.uid()) {
|
||||
property.insert("uid", uid);
|
||||
}
|
||||
if(auto isDefault = edition.isDefault()) {
|
||||
if(const auto isDefault = edition.isDefault()) {
|
||||
property.insert("isDefault", isDefault);
|
||||
}
|
||||
if(auto isOrdered = edition.isOrdered()) {
|
||||
if(const auto isOrdered = edition.isOrdered()) {
|
||||
property.insert("isOrdered", isOrdered);
|
||||
}
|
||||
if(auto chapters = edition.chapterList(); !chapters.isEmpty()) {
|
||||
VariantList chaps;
|
||||
for(const auto &chapter : chapters) {
|
||||
VariantMap chap;
|
||||
if(auto uid = chapter.uid()) {
|
||||
if(const auto uid = chapter.uid()) {
|
||||
chap.insert("uid", uid);
|
||||
}
|
||||
if(auto isHidden = chapter.isHidden()) {
|
||||
if(const auto isHidden = chapter.isHidden()) {
|
||||
chap.insert("isHidden", isHidden);
|
||||
}
|
||||
chap.insert("timeStart", chapter.timeStart());
|
||||
if(auto timeEnd = chapter.timeEnd()) {
|
||||
if(const auto timeEnd = chapter.timeEnd()) {
|
||||
chap.insert("timeEnd", timeEnd);
|
||||
}
|
||||
if(auto displays = chapter.displayList(); !displays.isEmpty()) {
|
||||
@@ -313,7 +312,6 @@ bool Matroska::File::setComplexProperties(const String &key, const List<VariantM
|
||||
auto fileName = property.value("fileName").value<String>();
|
||||
auto uid = property.value("uid").value<unsigned long long>();
|
||||
bool ok;
|
||||
unsigned long long uidKey;
|
||||
if(key.upper() == "PICTURE" && !mimeType.startsWith("image/")) {
|
||||
mimeType = data.startsWith("\x89PNG\x0d\x0a\x1a\x0a")
|
||||
? "image/png" : "image/jpeg";
|
||||
@@ -324,11 +322,12 @@ bool Matroska::File::setComplexProperties(const String &key, const List<VariantM
|
||||
else if(fileName.isEmpty() && key.find(".") != -1) {
|
||||
fileName = key;
|
||||
}
|
||||
else if(!uid && ((uidKey = key.toULongLong(&ok))) && ok) {
|
||||
else if(unsigned long long uidKey;
|
||||
!uid && ((uidKey = key.toULongLong(&ok))) && ok) {
|
||||
uid = uidKey;
|
||||
}
|
||||
if(fileName.isEmpty() && !mimeType.isEmpty()) {
|
||||
int slashPos = mimeType.rfind('/');
|
||||
const int slashPos = mimeType.rfind('/');
|
||||
String ext = mimeType.substr(slashPos + 1);
|
||||
if(ext == "jpeg") {
|
||||
ext = "jpg";
|
||||
@@ -364,10 +363,10 @@ Matroska::Chapters *Matroska::File::chapters(bool create) const
|
||||
|
||||
void Matroska::File::read(bool readProperties, Properties::ReadStyle readStyle)
|
||||
{
|
||||
offset_t fileLength = length();
|
||||
const offset_t fileLength = length();
|
||||
|
||||
// Find the EBML Header
|
||||
auto head = EBML::element_cast<EBML::Element::Id::EBMLHeader>(
|
||||
const auto head = EBML::element_cast<EBML::Element::Id::EBMLHeader>(
|
||||
EBML::Element::factory(*this));
|
||||
if(!head || head->getId() != EBML::Element::Id::EBMLHeader) {
|
||||
debug("Failed to find EBML head");
|
||||
@@ -382,7 +381,7 @@ void Matroska::File::read(bool readProperties, Properties::ReadStyle readStyle)
|
||||
}
|
||||
|
||||
// Find the Matroska segment in the file
|
||||
std::unique_ptr<EBML::MkSegment> segment(
|
||||
const std::unique_ptr<EBML::MkSegment> segment(
|
||||
EBML::element_cast<EBML::Element::Id::MkSegment>(
|
||||
EBML::findElement(*this, EBML::Element::Id::MkSegment, fileLength - tell())
|
||||
)
|
||||
@@ -412,12 +411,11 @@ void Matroska::File::read(bool readProperties, Properties::ReadStyle readStyle)
|
||||
d->properties = std::make_unique<Properties>(this);
|
||||
|
||||
for(const auto &element : *head) {
|
||||
auto id = element->getId();
|
||||
if (id == EBML::Element::Id::DocType) {
|
||||
if(const auto id = element->getId(); id == EBML::Element::Id::DocType) {
|
||||
d->properties->setDocType(
|
||||
EBML::element_cast<EBML::Element::Id::DocType>(element)->getValue());
|
||||
}
|
||||
else if (id == EBML::Element::Id::DocTypeVersion) {
|
||||
else if(id == EBML::Element::Id::DocTypeVersion) {
|
||||
d->properties->setDocTypeVersion(static_cast<int>(
|
||||
EBML::element_cast<EBML::Element::Id::DocTypeVersion>(element)->getValue()));
|
||||
}
|
||||
@@ -505,8 +503,8 @@ bool Matroska::File::save()
|
||||
|
||||
// Add our new elements to the Seek Head (if the file has one)
|
||||
if(d->seekHead) {
|
||||
auto segmentDataOffset = d->segment->dataOffset();
|
||||
for(auto element : newElements)
|
||||
const auto segmentDataOffset = d->segment->dataOffset();
|
||||
for(const auto element : newElements)
|
||||
d->seekHead->addEntry(element->id(), element->offset() - segmentDataOffset);
|
||||
d->seekHead->sort();
|
||||
}
|
||||
@@ -545,7 +543,7 @@ bool Matroska::File::save()
|
||||
bool rendering = true;
|
||||
while(rendering && renderRound < 5) {
|
||||
rendering = false;
|
||||
for(auto element : renderList) {
|
||||
for(const auto element : renderList) {
|
||||
if(element->needsRender()) {
|
||||
rendering = true;
|
||||
if(!element->render()) {
|
||||
@@ -558,7 +556,7 @@ bool Matroska::File::save()
|
||||
|
||||
// Write out to file
|
||||
renderList.sort(sortAscending);
|
||||
for(auto element : renderList)
|
||||
for(const auto element : renderList)
|
||||
element->write(*this);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -23,11 +23,9 @@
|
||||
|
||||
#include "taglib_export.h"
|
||||
#include "tfile.h"
|
||||
#include "tag.h"
|
||||
#include "matroskaproperties.h"
|
||||
|
||||
namespace TagLib::Matroska {
|
||||
class Properties;
|
||||
class Tag;
|
||||
class Attachments;
|
||||
class Chapters;
|
||||
|
||||
@@ -69,7 +69,7 @@ int Matroska::Properties::lengthInMilliseconds() const
|
||||
|
||||
int Matroska::Properties::bitrate() const
|
||||
{
|
||||
if (d->bitrate == -1) {
|
||||
if(d->bitrate == -1) {
|
||||
d->bitrate = d->length != 0 ? static_cast<int>(d->file->length() * 8 / d->length) : 0;
|
||||
}
|
||||
return d->bitrate;
|
||||
@@ -149,7 +149,7 @@ void Matroska::Properties::setCodecName(const String &codecName)
|
||||
d->codecName = codecName;
|
||||
}
|
||||
|
||||
void Matroska::Properties::setTitle(const String& title)
|
||||
void Matroska::Properties::setTitle(const String &title)
|
||||
{
|
||||
d->title = title;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "ebmlbinaryelement.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "tfile.h"
|
||||
#include "tutils.h"
|
||||
#include "tdebug.h"
|
||||
|
||||
using namespace TagLib;
|
||||
@@ -34,7 +36,7 @@ Matroska::SeekHead::SeekHead(offset_t segmentDataOffset) :
|
||||
setNeedsRender(false);
|
||||
}
|
||||
|
||||
bool Matroska::SeekHead::isValid(TagLib::File& file) const
|
||||
bool Matroska::SeekHead::isValid(TagLib::File &file) const
|
||||
{
|
||||
bool result = true;
|
||||
for(const auto &[id, offset] : entries) {
|
||||
@@ -62,7 +64,7 @@ void Matroska::SeekHead::addEntry(ID id, offset_t offset)
|
||||
|
||||
ByteVector Matroska::SeekHead::renderInternal()
|
||||
{
|
||||
auto beforeSize = sizeRenderedOrWritten();
|
||||
const auto beforeSize = sizeRenderedOrWritten();
|
||||
EBML::MkSeekHead seekHead;
|
||||
seekHead.setMinRenderSize(beforeSize);
|
||||
for(const auto &[id, position] : entries) {
|
||||
@@ -98,34 +100,32 @@ bool Matroska::SeekHead::sizeChanged(Element &caller, offset_t delta)
|
||||
adjustOffset(delta);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// The equal case is needed when multiple new elements are added
|
||||
// (e.g. Attachments and Tags), they will start with the same offset
|
||||
// and are updated via size change handling.
|
||||
offset_t offset = caller.offset() - segmentDataOffset;
|
||||
auto it = entries.begin();
|
||||
while(it != entries.end()) {
|
||||
it = std::find_if(it,
|
||||
entries.end(),
|
||||
[offset, callerID](const auto &a) {
|
||||
return a.second >= offset && a.first != callerID;
|
||||
}
|
||||
);
|
||||
if(it != entries.end()) {
|
||||
it->second += delta;
|
||||
setNeedsRender(true);
|
||||
++it;
|
||||
// The equal case is needed when multiple new elements are added
|
||||
// (e.g. Attachments and Tags), they will start with the same offset
|
||||
// and are updated via size change handling.
|
||||
offset_t offset = caller.offset() - segmentDataOffset;
|
||||
auto it = entries.begin();
|
||||
while(it != entries.end()) {
|
||||
it = std::find_if(it,
|
||||
entries.end(),
|
||||
[offset, callerID](const auto &a) {
|
||||
return a.second >= offset && a.first != callerID;
|
||||
}
|
||||
);
|
||||
if(it != entries.end()) {
|
||||
it->second += delta;
|
||||
setNeedsRender(true);
|
||||
++it;
|
||||
}
|
||||
|
||||
if(caller.data().isEmpty() && caller.size() + delta == 0) {
|
||||
// The caller element is removed, remove it from the seek head.
|
||||
it = std::find_if(entries.begin(), entries.end(),
|
||||
[callerID](const auto &a){ return a.first == callerID; });
|
||||
if(it != entries.end()) {
|
||||
entries.erase(it);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(caller.data().isEmpty() && caller.size() + delta == 0) {
|
||||
// The caller element is removed, remove it from the seek head.
|
||||
it = std::find_if(entries.begin(), entries.end(),
|
||||
[callerID](const auto &a){ return a.first == callerID; });
|
||||
if(it != entries.end()) {
|
||||
entries.erase(it);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -23,17 +23,19 @@
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "matroskaelement.h"
|
||||
#include "tbytevector.h"
|
||||
#include "tlist.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
class ByteVector;
|
||||
|
||||
namespace Matroska {
|
||||
class SeekHead : public Element
|
||||
{
|
||||
public:
|
||||
explicit SeekHead(offset_t segmentDataOffset);
|
||||
~SeekHead() override = default;
|
||||
|
||||
bool isValid(TagLib::File &file) const;
|
||||
void addEntry(const Element &element);
|
||||
void addEntry(ID id, offset_t offset);
|
||||
|
||||
@@ -38,11 +38,10 @@ ByteVector Matroska::Segment::renderInternal()
|
||||
|
||||
bool Matroska::Segment::render()
|
||||
{
|
||||
auto beforeSize = sizeLength;
|
||||
const auto beforeSize = sizeLength;
|
||||
auto data = renderInternal();
|
||||
setNeedsRender(false);
|
||||
auto afterSize = data.size();
|
||||
if(afterSize != beforeSize) {
|
||||
if(auto afterSize = data.size(); afterSize != beforeSize) {
|
||||
sizeLength = 8;
|
||||
data = renderInternal();
|
||||
setNeedsRender(false);
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "matroskasimpletag.h"
|
||||
#include <variant>
|
||||
#include "matroskatag.h"
|
||||
#include "tstring.h"
|
||||
#include "tbytevector.h"
|
||||
|
||||
using namespace TagLib;
|
||||
@@ -29,16 +28,17 @@ using namespace TagLib;
|
||||
class Matroska::SimpleTag::SimpleTagPrivate
|
||||
{
|
||||
public:
|
||||
explicit SimpleTagPrivate(const String &name, const String& value,
|
||||
explicit SimpleTagPrivate(const String &name, const String &value,
|
||||
TargetTypeValue targetTypeValue, const String &language, bool defaultLanguage,
|
||||
unsigned long long trackUid) :
|
||||
value(value), name(name), language(language), trackUid(trackUid),
|
||||
targetTypeValue(targetTypeValue), defaultLanguageFlag(defaultLanguage) {}
|
||||
explicit SimpleTagPrivate(const String &name, const ByteVector& value,
|
||||
explicit SimpleTagPrivate(const String &name, const ByteVector &value,
|
||||
TargetTypeValue targetTypeValue, const String &language, bool defaultLanguage,
|
||||
unsigned long long trackUid) :
|
||||
value(value), name(name), language(language), trackUid(trackUid),
|
||||
targetTypeValue(targetTypeValue), defaultLanguageFlag(defaultLanguage) {}
|
||||
|
||||
const std::variant<String, ByteVector> value;
|
||||
const String name;
|
||||
const String language;
|
||||
@@ -74,11 +74,11 @@ Matroska::SimpleTag::SimpleTag(const SimpleTag &other) :
|
||||
{
|
||||
}
|
||||
|
||||
Matroska::SimpleTag::SimpleTag(SimpleTag&& other) noexcept = default;
|
||||
Matroska::SimpleTag::SimpleTag(SimpleTag &&other) noexcept = default;
|
||||
|
||||
Matroska::SimpleTag::~SimpleTag() = default;
|
||||
|
||||
Matroska::SimpleTag &Matroska::SimpleTag::operator=(SimpleTag &&other) = default;
|
||||
Matroska::SimpleTag &Matroska::SimpleTag::operator=(SimpleTag &&other) noexcept = default;
|
||||
|
||||
Matroska::SimpleTag &Matroska::SimpleTag::operator=(const SimpleTag &other)
|
||||
{
|
||||
|
||||
@@ -22,11 +22,13 @@
|
||||
#define TAGLIB_MATROSKASIMPLETAG_H
|
||||
|
||||
#include <memory>
|
||||
#include "tag.h"
|
||||
|
||||
#include "tstring.h"
|
||||
|
||||
namespace TagLib {
|
||||
class String;
|
||||
class ByteVector;
|
||||
|
||||
namespace Matroska {
|
||||
//! Attribute of Matroska metadata.
|
||||
class TAGLIB_EXPORT SimpleTag
|
||||
@@ -89,7 +91,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Moves the contents of \a other into this item.
|
||||
*/
|
||||
SimpleTag &operator=(SimpleTag &&other);
|
||||
SimpleTag &operator=(SimpleTag &&other) noexcept;
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the simple tag with the content of \a other.
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <tuple>
|
||||
#include "matroskasimpletag.h"
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmlstringelement.h"
|
||||
#include "ebmlbinaryelement.h"
|
||||
@@ -30,7 +29,6 @@
|
||||
#include "ebmluintelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "tpropertymap.h"
|
||||
#include "tlist.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
@@ -95,7 +93,7 @@ void Matroska::Tag::removeSimpleTag(const String &name,
|
||||
SimpleTag::TargetTypeValue targetTypeValue,
|
||||
unsigned long long trackUid)
|
||||
{
|
||||
auto it = std::find_if(d->tags.begin(), d->tags.end(),
|
||||
const auto it = std::find_if(d->tags.begin(), d->tags.end(),
|
||||
[&name, targetTypeValue, trackUid](const SimpleTag &t) {
|
||||
return t.name() == name && t.targetTypeValue() == targetTypeValue &&
|
||||
t.trackUid() == trackUid;
|
||||
@@ -118,14 +116,14 @@ const Matroska::SimpleTagsList &Matroska::Tag::simpleTagsList() const
|
||||
return d->tags;
|
||||
}
|
||||
|
||||
void Matroska::Tag::setSegmentTitle(const String& title)
|
||||
void Matroska::Tag::setSegmentTitle(const String &title)
|
||||
{
|
||||
d->segmentTitle = title;
|
||||
}
|
||||
|
||||
bool Matroska::Tag::setTag(const String &key, const String &value)
|
||||
{
|
||||
bool found = d->setTag(key, value);
|
||||
const bool found = d->setTag(key, value);
|
||||
if(found) {
|
||||
setNeedsRender(true);
|
||||
}
|
||||
@@ -198,7 +196,7 @@ String Matroska::Tag::genre() const
|
||||
|
||||
unsigned int Matroska::Tag::year() const
|
||||
{
|
||||
auto value = d->getTag("DATE");
|
||||
const auto value = d->getTag("DATE");
|
||||
if(value.isEmpty())
|
||||
return 0;
|
||||
auto list = value.split("-");
|
||||
@@ -207,7 +205,7 @@ unsigned int Matroska::Tag::year() const
|
||||
|
||||
unsigned int Matroska::Tag::track() const
|
||||
{
|
||||
auto value = d->getTag("TRACKNUMBER");
|
||||
const auto value = d->getTag("TRACKNUMBER");
|
||||
if(value.isEmpty())
|
||||
return 0;
|
||||
auto list = value.split("-");
|
||||
@@ -251,8 +249,8 @@ ByteVector Matroska::Tag::renderInternal()
|
||||
}
|
||||
for(const auto &list : targetList) {
|
||||
const auto &frontTag = list.front();
|
||||
auto targetTypeValue = frontTag.targetTypeValue();
|
||||
auto trackUid = frontTag.trackUid();
|
||||
const auto targetTypeValue = frontTag.targetTypeValue();
|
||||
const auto trackUid = frontTag.trackUid();
|
||||
auto tag = EBML::make_unique_element<EBML::Element::Id::MkTag>();
|
||||
|
||||
// Build <Tag Targets> element
|
||||
@@ -326,7 +324,6 @@ namespace
|
||||
std::tuple("TRACKTOTAL", "TOTAL_PARTS", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("DISCTOTAL", "TOTAL_PARTS", Matroska::SimpleTag::TargetTypeValue::Album, true),
|
||||
std::tuple("DATE", "DATE_RELEASED", Matroska::SimpleTag::TargetTypeValue::Album, false),
|
||||
// Todo - original date
|
||||
std::tuple("TITLESORT", "TITLESORT", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("ALBUMSORT", "TITLESORT", Matroska::SimpleTag::TargetTypeValue::Album, true),
|
||||
std::tuple("ARTISTSORT", "ARTISTSORT", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
@@ -360,14 +357,14 @@ namespace
|
||||
);
|
||||
if(it != simpleTagsTranslation.end())
|
||||
return { std::get<1>(*it), std::get<2>(*it), std::get<3>(*it) };
|
||||
if (!key.isEmpty())
|
||||
if(!key.isEmpty())
|
||||
return { key, Matroska::SimpleTag::TargetTypeValue::Track, false };
|
||||
return { String(), Matroska::SimpleTag::TargetTypeValue::None, false };
|
||||
}
|
||||
|
||||
String translateTag(const String &name, Matroska::SimpleTag::TargetTypeValue targetTypeValue)
|
||||
{
|
||||
auto it = std::find_if(simpleTagsTranslation.cbegin(),
|
||||
const auto it = std::find_if(simpleTagsTranslation.cbegin(),
|
||||
simpleTagsTranslation.cend(),
|
||||
[&name, targetTypeValue](const auto &t) {
|
||||
return name == std::get<1>(t)
|
||||
@@ -378,8 +375,8 @@ namespace
|
||||
);
|
||||
return it != simpleTagsTranslation.end()
|
||||
? String(std::get<0>(*it), String::UTF8)
|
||||
: (targetTypeValue == Matroska::SimpleTag::TargetTypeValue::Track ||
|
||||
targetTypeValue == Matroska::SimpleTag::TargetTypeValue::None)
|
||||
: targetTypeValue == Matroska::SimpleTag::TargetTypeValue::Track ||
|
||||
targetTypeValue == Matroska::SimpleTag::TargetTypeValue::None
|
||||
? name
|
||||
: String();
|
||||
}
|
||||
@@ -414,7 +411,7 @@ String Matroska::Tag::TagPrivate::getTag(const String &key) const
|
||||
bool strict = std::get<2>(tpl);
|
||||
if(name.isEmpty())
|
||||
return {};
|
||||
auto it = std::find_if(tags.begin(), tags.end(),
|
||||
const auto it = std::find_if(tags.begin(), tags.end(),
|
||||
[&name, targetTypeValue, strict] (const SimpleTag &t) {
|
||||
return t.name() == name
|
||||
&& t.type() == SimpleTag::StringType
|
||||
@@ -431,8 +428,8 @@ PropertyMap Matroska::Tag::properties() const
|
||||
PropertyMap properties;
|
||||
for(const auto &simpleTag : std::as_const(d->tags)) {
|
||||
if(simpleTag.type() == SimpleTag::StringType && simpleTag.trackUid() == 0) {
|
||||
String key = translateTag(simpleTag.name(), simpleTag.targetTypeValue());
|
||||
if(!key.isEmpty())
|
||||
if(String key = translateTag(simpleTag.name(), simpleTag.targetTypeValue());
|
||||
!key.isEmpty())
|
||||
properties[key].append(simpleTag.toString());
|
||||
else
|
||||
properties.addUnsupportedData(simpleTag.name());
|
||||
@@ -445,10 +442,9 @@ PropertyMap Matroska::Tag::setProperties(const PropertyMap &propertyMap)
|
||||
{
|
||||
// Remove all simple tags which would be returned in properties()
|
||||
for(auto it = d->tags.begin(); it != d->tags.end();) {
|
||||
String key;
|
||||
if(it->type() == SimpleTag::StringType &&
|
||||
it->trackUid() == 0 &&
|
||||
!(key = translateTag(it->name(), it->targetTypeValue())).isEmpty()) {
|
||||
!translateTag(it->name(), it->targetTypeValue()).isEmpty()) {
|
||||
it = d->tags.erase(it);
|
||||
setNeedsRender(true);
|
||||
}
|
||||
@@ -474,10 +470,10 @@ PropertyMap Matroska::Tag::setProperties(const PropertyMap &propertyMap)
|
||||
return unsupportedProperties;
|
||||
}
|
||||
|
||||
void Matroska::Tag::removeUnsupportedProperties(const StringList& properties)
|
||||
void Matroska::Tag::removeUnsupportedProperties(const StringList &properties)
|
||||
{
|
||||
if(d->removeSimpleTags(
|
||||
[&properties](const SimpleTag& t) {
|
||||
[&properties](const SimpleTag &t) {
|
||||
return properties.contains(t.name());
|
||||
}) > 0) {
|
||||
setNeedsRender(true);
|
||||
@@ -497,7 +493,7 @@ StringList Matroska::Tag::complexPropertyKeys() const
|
||||
return keys;
|
||||
}
|
||||
|
||||
List<VariantMap> Matroska::Tag::complexProperties(const String& key) const
|
||||
List<VariantMap> Matroska::Tag::complexProperties(const String &key) const
|
||||
{
|
||||
List<VariantMap> props;
|
||||
if(key.upper() != "PICTURE") { // Pictures are handled at the file level
|
||||
@@ -529,7 +525,7 @@ List<VariantMap> Matroska::Tag::complexProperties(const String& key) const
|
||||
return props;
|
||||
}
|
||||
|
||||
bool Matroska::Tag::setComplexProperties(const String& key, const List<VariantMap>& value)
|
||||
bool Matroska::Tag::setComplexProperties(const String &key, const List<VariantMap> &value)
|
||||
{
|
||||
if(key.upper() == "PICTURE") {
|
||||
// Pictures are handled at the file level
|
||||
@@ -549,8 +545,8 @@ bool Matroska::Tag::setComplexProperties(const String& key, const List<VariantMa
|
||||
if(property.value("name").value<String>() == key &&
|
||||
(property.contains("data") || property.contains("value") )) {
|
||||
SimpleTag::TargetTypeValue targetTypeValue;
|
||||
Variant targetTypeValueVar = property.value("targetTypeValue", 0);
|
||||
switch(targetTypeValueVar.type()) {
|
||||
switch(Variant targetTypeValueVar = property.value("targetTypeValue", 0);
|
||||
targetTypeValueVar.type()) {
|
||||
case Variant::UInt:
|
||||
targetTypeValue = static_cast<SimpleTag::TargetTypeValue>(targetTypeValueVar.value<unsigned int>());
|
||||
break;
|
||||
@@ -564,8 +560,8 @@ bool Matroska::Tag::setComplexProperties(const String& key, const List<VariantMa
|
||||
targetTypeValue = static_cast<SimpleTag::TargetTypeValue>(targetTypeValueVar.value<int>());
|
||||
}
|
||||
auto language = property.value("language").value<String>();
|
||||
bool defaultLanguage = property.value("defaultLanguage", true).value<bool>();
|
||||
auto trackUid = property.value("trackUid", 0ULL).value<unsigned long long>();
|
||||
const bool defaultLanguage = property.value("defaultLanguage", true).value<bool>();
|
||||
const auto trackUid = property.value("trackUid", 0ULL).value<unsigned long long>();
|
||||
d->tags.append(property.contains("data")
|
||||
? SimpleTag(key, property.value("data").value<ByteVector>(),
|
||||
targetTypeValue, language, defaultLanguage, trackUid)
|
||||
|
||||
@@ -24,27 +24,33 @@
|
||||
#include <memory>
|
||||
|
||||
#include "tag.h"
|
||||
#include "tstring.h"
|
||||
#include "tlist.h"
|
||||
#include "matroskafile.h"
|
||||
#include "matroskaelement.h"
|
||||
#include "matroskasimpletag.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
|
||||
namespace EBML {
|
||||
class MkTags;
|
||||
}
|
||||
|
||||
namespace Matroska {
|
||||
//! List of tag attributes.
|
||||
using SimpleTagsList = List<SimpleTag>;
|
||||
|
||||
//! Matroska tag implementation.
|
||||
class TAGLIB_EXPORT Tag : public TagLib::Tag
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
, private Element
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Constructs a Matroska tag.
|
||||
*/
|
||||
Tag();
|
||||
|
||||
~Tag() override;
|
||||
String title() const override;
|
||||
String artist() const override;
|
||||
@@ -63,7 +69,7 @@ namespace TagLib {
|
||||
bool isEmpty() const override;
|
||||
PropertyMap properties() const override;
|
||||
PropertyMap setProperties(const PropertyMap &propertyMap) override;
|
||||
void removeUnsupportedProperties(const StringList& properties) override;
|
||||
void removeUnsupportedProperties(const StringList &properties) override;
|
||||
|
||||
/*!
|
||||
* Returns the names of the binary simple tags.
|
||||
@@ -86,12 +92,27 @@ namespace TagLib {
|
||||
*
|
||||
* Returns \c true if \c key can be stored as binary simple tags.
|
||||
*/
|
||||
bool setComplexProperties(const String& key, const List<VariantMap>& value) override;
|
||||
bool setComplexProperties(const String &key, const List<VariantMap> &value) override;
|
||||
|
||||
/*!
|
||||
* Add a tag attribute.
|
||||
*/
|
||||
void addSimpleTag(const SimpleTag &tag);
|
||||
|
||||
/*!
|
||||
* Remove a tag attribute.
|
||||
*/
|
||||
void removeSimpleTag(const String &name, SimpleTag::TargetTypeValue targetTypeValue,
|
||||
unsigned long long trackUid = 0);
|
||||
|
||||
/*!
|
||||
* Remove all tag attributes.
|
||||
*/
|
||||
void clearSimpleTags();
|
||||
|
||||
/*!
|
||||
* Get list of all tag attributes.
|
||||
*/
|
||||
const SimpleTagsList &simpleTagsList() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -1002,7 +1002,7 @@ public:
|
||||
void testChapters()
|
||||
{
|
||||
const Matroska::ChapterEdition edition1(
|
||||
List{
|
||||
List<Matroska::Chapter>{
|
||||
Matroska::Chapter(
|
||||
0, 40000,
|
||||
List{
|
||||
|
||||
Reference in New Issue
Block a user