mirror of
https://github.com/taglib/taglib.git
synced 2026-02-08 00:10:15 -05:00
Fix and simplify Matroska simple tag
Avoid use of raw pointers, fix property interface.
This commit is contained in:
@ -30,23 +30,21 @@ int main(int argc, char *argv[])
|
||||
const TagLib::Matroska::SimpleTagsList &list = tag->simpleTagsList();
|
||||
printf("Found %u tag(s):\n", list.size());
|
||||
|
||||
for(TagLib::Matroska::SimpleTag *t : list) {
|
||||
PRINT_PRETTY("Tag Name", t->name().toCString(true));
|
||||
for(const TagLib::Matroska::SimpleTag &t : list) {
|
||||
PRINT_PRETTY("Tag Name", t.name().toCString(true));
|
||||
|
||||
TagLib::Matroska::SimpleTagString *tString = nullptr;
|
||||
TagLib::Matroska::SimpleTagBinary *tBinary = nullptr;
|
||||
if((tString = dynamic_cast<TagLib::Matroska::SimpleTagString*>(t)))
|
||||
PRINT_PRETTY("Tag Value", tString->value().toCString(true));
|
||||
else if((tBinary = dynamic_cast<TagLib::Matroska::SimpleTagBinary*>(t)))
|
||||
if(t.type() == TagLib::Matroska::SimpleTag::StringType)
|
||||
PRINT_PRETTY("Tag Value", t.toString().toCString(true));
|
||||
else if(t.type() == TagLib::Matroska::SimpleTag::BinaryType)
|
||||
PRINT_PRETTY("Tag Value",
|
||||
TagLib::Utils::formatString("Binary with size %i", tBinary->value().size()).toCString(false)
|
||||
TagLib::Utils::formatString("Binary with size %i", t.toByteVector().size()).toCString(false)
|
||||
);
|
||||
|
||||
auto targetTypeValue = static_cast<unsigned int>(t->targetTypeValue());
|
||||
auto targetTypeValue = static_cast<unsigned int>(t.targetTypeValue());
|
||||
PRINT_PRETTY("Target Type Value",
|
||||
targetTypeValue == 0 ? "None" : TagLib::Utils::formatString("%i", targetTypeValue).toCString(false)
|
||||
);
|
||||
const TagLib::String &language = t->language();
|
||||
const TagLib::String &language = t.language();
|
||||
PRINT_PRETTY("Language", !language.isEmpty() ? language.toCString(false) : "Not set");
|
||||
|
||||
printf("\n");
|
||||
|
||||
@ -22,18 +22,13 @@ int main(int argc, char *argv[])
|
||||
auto tag = file.tag(true);
|
||||
tag->clearSimpleTags();
|
||||
|
||||
auto simpleTag = new TagLib::Matroska::SimpleTagString();
|
||||
simpleTag->setName("Test Name 1");
|
||||
simpleTag->setTargetTypeValue(TagLib::Matroska::SimpleTag::TargetTypeValue::Track);
|
||||
simpleTag->setValue("Test Value 1");
|
||||
simpleTag->setLanguage("en");
|
||||
tag->addSimpleTag(simpleTag);
|
||||
tag->addSimpleTag(TagLib::Matroska::SimpleTag(
|
||||
"Test Name 1", TagLib::String("Test Value 1"),
|
||||
TagLib::Matroska::SimpleTag::TargetTypeValue::Track, "en"));
|
||||
|
||||
simpleTag = new TagLib::Matroska::SimpleTagString();
|
||||
simpleTag->setName("Test Name 2");
|
||||
simpleTag->setTargetTypeValue(TagLib::Matroska::SimpleTag::TargetTypeValue::Album);
|
||||
simpleTag->setValue("Test Value 2");
|
||||
tag->addSimpleTag(simpleTag);
|
||||
tag->addSimpleTag(TagLib::Matroska::SimpleTag(
|
||||
"Test Name 2", TagLib::String("Test Value 2"),
|
||||
TagLib::Matroska::SimpleTag::TargetTypeValue::Album));
|
||||
tag->setTitle("Test title");
|
||||
tag->setArtist("Test artist");
|
||||
tag->setYear(1969);
|
||||
|
||||
@ -68,47 +68,33 @@ std::unique_ptr<Matroska::Tag> EBML::MkTags::parse()
|
||||
|
||||
// Parse each <SimpleTag>
|
||||
for(auto simpleTag : simpleTags) {
|
||||
const String *tagName = nullptr;
|
||||
const String *tagValueString = nullptr;
|
||||
const ByteVector *tagValueBinary = nullptr;
|
||||
const String *language = nullptr;
|
||||
String tagName;
|
||||
String language;
|
||||
bool defaultLanguageFlag = true;
|
||||
|
||||
for(const auto &simpleTagChild : *simpleTag) {
|
||||
Id id = simpleTagChild->getId();
|
||||
if(id == Id::MkTagName && !tagName)
|
||||
tagName = &(element_cast<Id::MkTagName>(simpleTagChild)->getValue());
|
||||
if(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());
|
||||
else if(id == Id::MkTagBinary && !tagValueBinary)
|
||||
tagValueBinary = &(element_cast<Id::MkTagBinary>(simpleTagChild)->getValue());
|
||||
else if(id == Id::MkTagsTagLanguage && !language)
|
||||
language = &(element_cast<Id::MkTagsTagLanguage>(simpleTagChild)->getValue());
|
||||
else if(id == Id::MkTagsTagLanguage && language.isEmpty())
|
||||
language = element_cast<Id::MkTagsTagLanguage>(simpleTagChild)->getValue();
|
||||
else if(id == Id::MkTagsLanguageDefault)
|
||||
defaultLanguageFlag = element_cast<Id::MkTagsLanguageDefault>(simpleTagChild)->getValue() ? true : false;
|
||||
}
|
||||
if(!tagName || (tagValueString && tagValueBinary) || (!tagValueString && !tagValueBinary))
|
||||
if(tagName.isEmpty() || (tagValueString && tagValueBinary) || (!tagValueString && !tagValueBinary))
|
||||
continue;
|
||||
|
||||
// Create a Simple Tag object and add it to the Tag object
|
||||
Matroska::SimpleTag *sTag = nullptr;
|
||||
if(tagValueString) {
|
||||
auto sTagString = new Matroska::SimpleTagString();
|
||||
sTagString->setTargetTypeValue(targetTypeValue);
|
||||
sTagString->setValue(*tagValueString);
|
||||
sTag = sTagString;
|
||||
}
|
||||
else { // tagValueBinary must be non null
|
||||
auto sTagBinary = new Matroska::SimpleTagBinary();
|
||||
sTagBinary->setTargetTypeValue(targetTypeValue);
|
||||
sTagBinary->setValue(*tagValueBinary);
|
||||
sTag = sTagBinary;
|
||||
}
|
||||
sTag->setName(*tagName);
|
||||
if(language)
|
||||
sTag->setLanguage(*language);
|
||||
sTag->setDefaultLanguageFlag(defaultLanguageFlag);
|
||||
mTag->addSimpleTag(sTag);
|
||||
mTag->addSimpleTag(tagValueString
|
||||
? Matroska::SimpleTag(tagName, *tagValueString,
|
||||
targetTypeValue, language, defaultLanguageFlag)
|
||||
: Matroska::SimpleTag(tagName, *tagValueBinary,
|
||||
targetTypeValue, language, defaultLanguageFlag));
|
||||
}
|
||||
}
|
||||
return mTag;
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "matroskasimpletag.h"
|
||||
#include <variant>
|
||||
#include "matroskatag.h"
|
||||
#include "tstring.h"
|
||||
#include "tbytevector.h"
|
||||
@ -28,43 +29,68 @@ using namespace TagLib;
|
||||
class Matroska::SimpleTag::SimpleTagPrivate
|
||||
{
|
||||
public:
|
||||
SimpleTagPrivate() = default;
|
||||
TargetTypeValue targetTypeValue = None;
|
||||
String name;
|
||||
String language;
|
||||
bool defaultLanguageFlag = true;
|
||||
explicit SimpleTagPrivate(const String &name, const String& value,
|
||||
TargetTypeValue targetTypeValue, const String &language, bool defaultLanguage) :
|
||||
value(value), name(name), language(language),
|
||||
targetTypeValue(targetTypeValue), defaultLanguageFlag(defaultLanguage) {}
|
||||
explicit SimpleTagPrivate(const String &name, const ByteVector& value,
|
||||
TargetTypeValue targetTypeValue, const String &language, bool defaultLanguage) :
|
||||
value(value), name(name), language(language),
|
||||
targetTypeValue(targetTypeValue), defaultLanguageFlag(defaultLanguage) {}
|
||||
const std::variant<String, ByteVector> value;
|
||||
const String name;
|
||||
const String language;
|
||||
const TargetTypeValue targetTypeValue;
|
||||
const bool defaultLanguageFlag;
|
||||
};
|
||||
|
||||
class Matroska::SimpleTagString::SimpleTagStringPrivate
|
||||
{
|
||||
public:
|
||||
SimpleTagStringPrivate() = default;
|
||||
String value;
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Matroska::SimpleTagBinary::SimpleTagBinaryPrivate
|
||||
{
|
||||
public:
|
||||
SimpleTagBinaryPrivate() = default;
|
||||
ByteVector value;
|
||||
};
|
||||
|
||||
Matroska::SimpleTag::SimpleTag() :
|
||||
d(std::make_unique<SimpleTagPrivate>())
|
||||
Matroska::SimpleTag::SimpleTag(const String &name, const String &value,
|
||||
TargetTypeValue targetTypeValue, const String &language, bool defaultLanguage) :
|
||||
d(std::make_unique<SimpleTagPrivate>(name, value, targetTypeValue,
|
||||
language, defaultLanguage))
|
||||
{
|
||||
}
|
||||
|
||||
Matroska::SimpleTag::SimpleTag(const String &name, const ByteVector &value,
|
||||
TargetTypeValue targetTypeValue, const String &language, bool defaultLanguage) :
|
||||
d(std::make_unique<SimpleTagPrivate>(name, value, targetTypeValue,
|
||||
language, defaultLanguage))
|
||||
{
|
||||
}
|
||||
|
||||
Matroska::SimpleTag::SimpleTag(const SimpleTag &other) :
|
||||
d(std::make_unique<SimpleTagPrivate>(*other.d))
|
||||
{
|
||||
}
|
||||
|
||||
Matroska::SimpleTag::SimpleTag(SimpleTag&& other) noexcept = default;
|
||||
|
||||
Matroska::SimpleTag::~SimpleTag() = default;
|
||||
|
||||
Matroska::SimpleTag &Matroska::SimpleTag::operator=(SimpleTag &&other) = default;
|
||||
|
||||
Matroska::SimpleTag &Matroska::SimpleTag::operator=(const SimpleTag &other)
|
||||
{
|
||||
SimpleTag(other).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Matroska::SimpleTag::swap(SimpleTag &other) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
swap(d, other.d);
|
||||
}
|
||||
|
||||
Matroska::SimpleTag::TargetTypeValue Matroska::SimpleTag::targetTypeValue() const
|
||||
{
|
||||
return d->targetTypeValue;
|
||||
}
|
||||
|
||||
void Matroska::SimpleTag::setTargetTypeValue(TargetTypeValue targetTypeValue)
|
||||
{
|
||||
d->targetTypeValue = targetTypeValue;
|
||||
}
|
||||
|
||||
const String &Matroska::SimpleTag::name() const
|
||||
{
|
||||
return d->name;
|
||||
@ -75,54 +101,28 @@ const String &Matroska::SimpleTag::language() const
|
||||
return d->language;
|
||||
}
|
||||
|
||||
void Matroska::SimpleTag::setLanguage(const String &language)
|
||||
{
|
||||
d->language = language;
|
||||
}
|
||||
|
||||
bool Matroska::SimpleTag::defaultLanguageFlag() const
|
||||
{
|
||||
return d->defaultLanguageFlag;
|
||||
}
|
||||
|
||||
void Matroska::SimpleTag::setDefaultLanguageFlag(bool flag)
|
||||
Matroska::SimpleTag::ValueType Matroska::SimpleTag::type() const
|
||||
{
|
||||
d->defaultLanguageFlag = flag;
|
||||
return std::holds_alternative<ByteVector>(d->value) ? BinaryType : StringType;
|
||||
}
|
||||
|
||||
void Matroska::SimpleTag::setName(const String &name)
|
||||
String Matroska::SimpleTag::toString() const
|
||||
{
|
||||
d->name = name;
|
||||
if(std::holds_alternative<String>(d->value)) {
|
||||
return std::get<String>(d->value);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Matroska::SimpleTagString::SimpleTagString() :
|
||||
dd(std::make_unique<SimpleTagStringPrivate>())
|
||||
ByteVector Matroska::SimpleTag::toByteVector() const
|
||||
{
|
||||
}
|
||||
Matroska::SimpleTagString::~SimpleTagString() = default;
|
||||
|
||||
const String &Matroska::SimpleTagString::value() const
|
||||
{
|
||||
return dd->value;
|
||||
}
|
||||
|
||||
void Matroska::SimpleTagString::setValue(const String &value)
|
||||
{
|
||||
dd->value = value;
|
||||
}
|
||||
|
||||
Matroska::SimpleTagBinary::SimpleTagBinary() :
|
||||
dd(std::make_unique<SimpleTagBinaryPrivate>())
|
||||
{
|
||||
}
|
||||
Matroska::SimpleTagBinary::~SimpleTagBinary() = default;
|
||||
|
||||
const ByteVector &Matroska::SimpleTagBinary::value() const
|
||||
{
|
||||
return dd->value;
|
||||
}
|
||||
|
||||
void Matroska::SimpleTagBinary::setValue(const ByteVector &value)
|
||||
{
|
||||
dd->value = value;
|
||||
if(std::holds_alternative<ByteVector>(d->value)) {
|
||||
return std::get<ByteVector>(d->value);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -23,70 +23,116 @@
|
||||
|
||||
#include <memory>
|
||||
#include "tag.h"
|
||||
//#include "matroskatag.h"
|
||||
|
||||
namespace TagLib {
|
||||
class String;
|
||||
class ByteVector;
|
||||
namespace Matroska {
|
||||
//! Attribute of Matroska metadata.
|
||||
class TAGLIB_EXPORT SimpleTag
|
||||
{
|
||||
public:
|
||||
//! Specifies the level of other elements the tag value applies to.
|
||||
enum TargetTypeValue {
|
||||
None = 0,
|
||||
Shot = 10,
|
||||
Subtrack = 20,
|
||||
Track = 30,
|
||||
Part = 40,
|
||||
Album = 50,
|
||||
Edition = 60,
|
||||
Collection = 70
|
||||
None = 0, //!< Empty or omitted, everything in the segment
|
||||
Shot = 10, //!< Shot
|
||||
Subtrack = 20, //!< Subtrack / movement / scene
|
||||
Track = 30, //!< Track / song / chapter
|
||||
Part = 40, //!< Part / session
|
||||
Album = 50, //!< Album / opera / concert / movie / episode
|
||||
Edition = 60, //!< Edition / issue / volume / opus / season / sequel
|
||||
Collection = 70 //!< Collection
|
||||
};
|
||||
|
||||
//! The types the value can have.
|
||||
enum ValueType {
|
||||
StringType = 0, //!< Item contains text information coded in UTF-8
|
||||
BinaryType = 1 //!< Item contains binary information
|
||||
};
|
||||
|
||||
/*!
|
||||
* Construct a string simple tag.
|
||||
*/
|
||||
SimpleTag(const String &name, const String &value,
|
||||
TargetTypeValue targetTypeValue = None,
|
||||
const String &language = String(), bool defaultLanguage = true);
|
||||
|
||||
/*!
|
||||
* Construct a binary simple tag.
|
||||
*/
|
||||
SimpleTag(const String &name, const ByteVector &value,
|
||||
TargetTypeValue targetTypeValue = None,
|
||||
const String &language = String(), bool defaultLanguage = true);
|
||||
|
||||
/*!
|
||||
* Construct a simple tag as a copy of \a other.
|
||||
*/
|
||||
SimpleTag(const SimpleTag &other);
|
||||
|
||||
/*!
|
||||
* Construct a simple tag moving from \a other.
|
||||
*/
|
||||
SimpleTag(SimpleTag &&other) noexcept;
|
||||
|
||||
/*!
|
||||
* Destroys this simple tag.
|
||||
*/
|
||||
~SimpleTag();
|
||||
|
||||
/*!
|
||||
* Copies the contents of \a other into this item.
|
||||
*/
|
||||
SimpleTag &operator=(const SimpleTag &other);
|
||||
|
||||
/*!
|
||||
* Moves the contents of \a other into this item.
|
||||
*/
|
||||
SimpleTag &operator=(SimpleTag &&other);
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the simple tag with the content of \a other.
|
||||
*/
|
||||
void swap(SimpleTag &other) noexcept;
|
||||
|
||||
/*!
|
||||
* Returns the name of the simple tag.
|
||||
*/
|
||||
const String &name() const;
|
||||
|
||||
/*!
|
||||
* Returns the logical level of the target.
|
||||
*/
|
||||
TargetTypeValue targetTypeValue() const;
|
||||
|
||||
/*!
|
||||
* Returns the language of the tag.
|
||||
*/
|
||||
const String &language() const;
|
||||
|
||||
/*!
|
||||
* Returns if this is the default/original language to use for the tag.
|
||||
*/
|
||||
bool defaultLanguageFlag() const;
|
||||
void setName(const String &name);
|
||||
void setTargetTypeValue(TargetTypeValue targetTypeValue);
|
||||
void setLanguage(const String &language);
|
||||
void setDefaultLanguageFlag(bool flag);
|
||||
virtual ~SimpleTag();
|
||||
|
||||
/*!
|
||||
* Returns the type of the value.
|
||||
*/
|
||||
ValueType type() const;
|
||||
|
||||
/*!
|
||||
* Returns the StringType value.
|
||||
*/
|
||||
String toString() const;
|
||||
|
||||
/*!
|
||||
* Returns the BinaryType value.
|
||||
*/
|
||||
ByteVector toByteVector() const;
|
||||
|
||||
private:
|
||||
class SimpleTagPrivate;
|
||||
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
|
||||
std::unique_ptr<SimpleTagPrivate> d;
|
||||
|
||||
protected:
|
||||
SimpleTag();
|
||||
};
|
||||
|
||||
class TAGLIB_EXPORT SimpleTagString : public SimpleTag
|
||||
{
|
||||
public:
|
||||
SimpleTagString();
|
||||
~SimpleTagString() override;
|
||||
const String &value() const;
|
||||
void setValue(const String &value);
|
||||
|
||||
private:
|
||||
class SimpleTagStringPrivate;
|
||||
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
|
||||
std::unique_ptr<SimpleTagStringPrivate> dd;
|
||||
};
|
||||
|
||||
class TAGLIB_EXPORT SimpleTagBinary : public SimpleTag
|
||||
{
|
||||
public:
|
||||
SimpleTagBinary();
|
||||
~SimpleTagBinary() override;
|
||||
const ByteVector &value() const;
|
||||
void setValue(const ByteVector &value);
|
||||
|
||||
private:
|
||||
class SimpleTagBinaryPrivate;
|
||||
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
|
||||
std::unique_ptr<SimpleTagBinaryPrivate> dd;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ public:
|
||||
~TagPrivate() = default;
|
||||
|
||||
bool setTag(const String &key, const String &value);
|
||||
const String *getTag(const String &key) const;
|
||||
String getTag(const String &key) const;
|
||||
|
||||
template <typename T>
|
||||
int removeSimpleTags(T &&p)
|
||||
@ -51,8 +51,6 @@ public:
|
||||
for(auto it = list.begin(); it != list.end();) {
|
||||
it = std::find_if(it, list.end(), std::forward<T>(p));
|
||||
if(it != list.end()) {
|
||||
delete *it;
|
||||
*it = nullptr;
|
||||
it = list.erase(it);
|
||||
numRemoved++;
|
||||
}
|
||||
@ -74,23 +72,7 @@ public:
|
||||
return list;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const SimpleTag *findSimpleTag(T &&p) const
|
||||
{
|
||||
auto &list = tags;
|
||||
auto it = std::find_if(list.begin(), list.end(), std::forward<T>(p));
|
||||
return it != list.end() ? *it : nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SimpleTag *findSimpleTag(T &&p)
|
||||
{
|
||||
return const_cast<SimpleTag *>(
|
||||
const_cast<const TagPrivate *>(this)->findSimpleTag(std::forward<T>(p))
|
||||
);
|
||||
}
|
||||
|
||||
List<SimpleTag *> tags;
|
||||
SimpleTagsList tags;
|
||||
ByteVector data;
|
||||
};
|
||||
|
||||
@ -98,20 +80,24 @@ Matroska::Tag::Tag() :
|
||||
Element(static_cast<ID>(EBML::Element::Id::MkTags)),
|
||||
d(std::make_unique<TagPrivate>())
|
||||
{
|
||||
d->tags.setAutoDelete(true);
|
||||
}
|
||||
|
||||
Matroska::Tag::~Tag() = default;
|
||||
|
||||
void Matroska::Tag::addSimpleTag(SimpleTag *tag)
|
||||
void Matroska::Tag::addSimpleTag(const SimpleTag &tag)
|
||||
{
|
||||
d->tags.append(tag);
|
||||
}
|
||||
|
||||
void Matroska::Tag::removeSimpleTag(SimpleTag *tag)
|
||||
void Matroska::Tag::removeSimpleTag(const String &name,
|
||||
SimpleTag::TargetTypeValue targetTypeValue)
|
||||
{
|
||||
auto it = d->tags.find(tag);
|
||||
auto it = std::find_if(d->tags.begin(), d->tags.end(),
|
||||
[&name, targetTypeValue](const SimpleTag &t) {
|
||||
return t.name() == name && t.targetTypeValue() == targetTypeValue;
|
||||
}
|
||||
);
|
||||
if(it != d->tags.end()) {
|
||||
delete *it;
|
||||
d->tags.erase(it);
|
||||
}
|
||||
}
|
||||
@ -163,49 +149,44 @@ void Matroska::Tag::setTrack(unsigned int i)
|
||||
|
||||
String Matroska::Tag::title() const
|
||||
{
|
||||
const auto value = d->getTag("TITLE");
|
||||
return value ? *value : String();
|
||||
return d->getTag("TITLE");
|
||||
}
|
||||
|
||||
String Matroska::Tag::artist() const
|
||||
{
|
||||
const auto value = d->getTag("ARTIST");
|
||||
return value ? *value : String();
|
||||
return d->getTag("ARTIST");
|
||||
}
|
||||
|
||||
String Matroska::Tag::album() const
|
||||
{
|
||||
const auto value = d->getTag("ALBUM");
|
||||
return value ? *value : String();
|
||||
return d->getTag("ALBUM");
|
||||
}
|
||||
|
||||
String Matroska::Tag::comment() const
|
||||
{
|
||||
const auto value = d->getTag("COMMENT");
|
||||
return value ? *value : String();
|
||||
return d->getTag("COMMENT");
|
||||
}
|
||||
|
||||
String Matroska::Tag::genre() const
|
||||
{
|
||||
const auto value = d->getTag("GENRE");
|
||||
return value ? *value : String();
|
||||
return d->getTag("GENRE");
|
||||
}
|
||||
|
||||
unsigned int Matroska::Tag::year() const
|
||||
{
|
||||
auto value = d->getTag("DATE");
|
||||
if(!value)
|
||||
if(value.isEmpty())
|
||||
return 0;
|
||||
auto list = value->split("-");
|
||||
auto list = value.split("-");
|
||||
return static_cast<unsigned int>(list.front().toInt());
|
||||
}
|
||||
|
||||
unsigned int Matroska::Tag::track() const
|
||||
{
|
||||
auto value = d->getTag("TRACKNUMBER");
|
||||
if(!value)
|
||||
if(value.isEmpty())
|
||||
return 0;
|
||||
auto list = value->split("-");
|
||||
auto list = value.split("-");
|
||||
return static_cast<unsigned int>(list.front().toInt());
|
||||
}
|
||||
|
||||
@ -217,30 +198,29 @@ bool Matroska::Tag::isEmpty() const
|
||||
bool Matroska::Tag::render()
|
||||
{
|
||||
EBML::MkTags tags;
|
||||
List<List<SimpleTag *> *> targetList;
|
||||
targetList.setAutoDelete(true);
|
||||
List<SimpleTagsList> targetList;
|
||||
|
||||
// Build target-based list
|
||||
for(auto tag : d->tags) {
|
||||
auto targetTypeValue = tag->targetTypeValue();
|
||||
for(const auto &tag : std::as_const(d->tags)) {
|
||||
auto targetTypeValue = tag.targetTypeValue();
|
||||
auto it = std::find_if(targetList.begin(),
|
||||
targetList.end(),
|
||||
[&](auto list) {
|
||||
const auto *simpleTag = list->front();
|
||||
return simpleTag->targetTypeValue() == targetTypeValue;
|
||||
[&](const auto &list) {
|
||||
const auto &simpleTag = list.front();
|
||||
return simpleTag.targetTypeValue() == targetTypeValue;
|
||||
}
|
||||
);
|
||||
if(it == targetList.end()) {
|
||||
auto list = new List<SimpleTag *>();
|
||||
list->append(tag);
|
||||
SimpleTagsList list;
|
||||
list.append(tag);
|
||||
targetList.append(list);
|
||||
}
|
||||
else
|
||||
(*it)->append(tag);
|
||||
it->append(tag);
|
||||
}
|
||||
for(auto list : targetList) {
|
||||
auto frontTag = list->front();
|
||||
auto targetTypeValue = frontTag->targetTypeValue();
|
||||
for(const auto &list : targetList) {
|
||||
const auto &frontTag = list.front();
|
||||
auto targetTypeValue = frontTag.targetTypeValue();
|
||||
auto tag = EBML::make_unique_element<EBML::Element::Id::MkTag>();
|
||||
|
||||
// Build <Tag Targets> element
|
||||
@ -253,35 +233,33 @@ bool Matroska::Tag::render()
|
||||
tag->appendElement(std::move(targets));
|
||||
|
||||
// Build <Simple Tag> element
|
||||
for(auto simpleTag : *list) {
|
||||
for(const auto &simpleTag : list) {
|
||||
auto t = EBML::make_unique_element<EBML::Element::Id::MkSimpleTag>();
|
||||
auto tagName = EBML::make_unique_element<EBML::Element::Id::MkTagName>();
|
||||
tagName->setValue(simpleTag->name());
|
||||
tagName->setValue(simpleTag.name());
|
||||
t->appendElement(std::move(tagName));
|
||||
|
||||
// Tag Value
|
||||
SimpleTagString *tStr = nullptr;
|
||||
SimpleTagBinary *tBin = nullptr;
|
||||
if((tStr = dynamic_cast<SimpleTagString *>(simpleTag))) {
|
||||
if(simpleTag.type() == SimpleTag::StringType) {
|
||||
auto tagValue = EBML::make_unique_element<EBML::Element::Id::MkTagString>();
|
||||
tagValue->setValue(tStr->value());
|
||||
tagValue->setValue(simpleTag.toString());
|
||||
t->appendElement(std::move(tagValue));
|
||||
}
|
||||
else if((tBin = dynamic_cast<SimpleTagBinary *>(simpleTag))) {
|
||||
else if(simpleTag.type() == SimpleTag::BinaryType) {
|
||||
auto tagValue = EBML::make_unique_element<EBML::Element::Id::MkTagBinary>();
|
||||
tagValue->setValue(tBin->value());
|
||||
tagValue->setValue(simpleTag.toByteVector());
|
||||
t->appendElement(std::move(tagValue));
|
||||
}
|
||||
|
||||
// Language
|
||||
auto language = EBML::make_unique_element<EBML::Element::Id::MkTagsTagLanguage>();
|
||||
const String &lang = simpleTag->language();
|
||||
const String &lang = simpleTag.language();
|
||||
language->setValue(!lang.isEmpty() ? lang : "und");
|
||||
t->appendElement(std::move(language));
|
||||
|
||||
// Default language flag
|
||||
auto dlf = EBML::make_unique_element<EBML::Element::Id::MkTagsLanguageDefault>();
|
||||
dlf->setValue(simpleTag->defaultLanguageFlag() ? 1 : 0);
|
||||
dlf->setValue(simpleTag.defaultLanguageFlag() ? 1 : 0);
|
||||
t->appendElement(std::move(dlf));
|
||||
|
||||
tag->appendElement(std::move(t));
|
||||
@ -302,51 +280,62 @@ bool Matroska::Tag::render()
|
||||
|
||||
namespace
|
||||
{
|
||||
// PropertyMap key, Tag name, Target type value
|
||||
// PropertyMap key, Tag name, Target type value, strict
|
||||
// If the key is the same as the name and the target type value is Track,
|
||||
// no translation is needed because this is the default mapping.
|
||||
// Therefore, keys like TITLE, ARTIST, GENRE, COMMENT, etc. are omitted.
|
||||
// Therefore, keys like TITLE, ARTIST, GENRE, COMMENT, etc. are omitted
|
||||
// unless they shall have priority over higher level tags with the same name
|
||||
// when no target type value is given. The strict boolean marks
|
||||
// entries which shall not be mapped without correct target type value.
|
||||
// For offical tags, see https://www.matroska.org/technical/tagging.html
|
||||
constexpr std::array simpleTagsTranslation {
|
||||
std::tuple("ALBUM", "TITLE", Matroska::SimpleTag::TargetTypeValue::Album),
|
||||
std::tuple("ALBUMARTIST", "ARTIST", Matroska::SimpleTag::TargetTypeValue::Album),
|
||||
std::tuple("TRACKNUMBER", "PART_NUMBER", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("TRACKTOTAL", "TOTAL_PARTS", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("DISCNUMBER", "PART_NUMBER", Matroska::SimpleTag::TargetTypeValue::Part),
|
||||
std::tuple("DISCTOTAL", "TOTAL_PARTS", Matroska::SimpleTag::TargetTypeValue::Part),
|
||||
std::tuple("DATE", "DATE_RELEASED", Matroska::SimpleTag::TargetTypeValue::Album),
|
||||
std::tuple("TITLE", "TITLE", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("ALBUM", "TITLE", Matroska::SimpleTag::TargetTypeValue::Album, true),
|
||||
std::tuple("ARTIST", "ARTIST", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("ALBUMARTIST", "ARTIST", Matroska::SimpleTag::TargetTypeValue::Album, true),
|
||||
std::tuple("TRACKNUMBER", "PART_NUMBER", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("DISCNUMBER", "PART_NUMBER", Matroska::SimpleTag::TargetTypeValue::Album, true),
|
||||
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("ALBUMSORT", "TITLESORT", Matroska::SimpleTag::TargetTypeValue::Album),
|
||||
std::tuple("ALBUMARTISTSORT", "ARTISTSORT", Matroska::SimpleTag::TargetTypeValue::Album),
|
||||
std::tuple("ENCODEDBY", "ENCODED_BY", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("MEDIA", "ORIGINAL_MEDIA_TYPE", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("LABEL", "LABEL_CODE", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("CATALOGNUMBER", "CATALOG_NUMBER", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("DJMIXER", "MIXED_BY", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("REMIXER", "REMIXED_BY", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("INITIALKEY", "INITIAL_KEY", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("RELEASEDATE", "DATE_RELEASED", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("ENCODINGTIME", "DATE_ENCODED", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("TAGGINGDATE", "DATE_TAGGED", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("ENCODEDBY", "ENCODER", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("ENCODING", "ENCODER_SETTINGS", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("OWNER", "PURCHASE_OWNER", Matroska::SimpleTag::TargetTypeValue::Track),
|
||||
std::tuple("MUSICBRAINZ_ALBUMARTISTID", "MUSICBRAINZ_ALBUMARTISTID", Matroska::SimpleTag::TargetTypeValue::Album),
|
||||
std::tuple("MUSICBRAINZ_ALBUMID", "MUSICBRAINZ_ALBUMID", Matroska::SimpleTag::TargetTypeValue::Album),
|
||||
std::tuple("MUSICBRAINZ_RELEASEGROUPID", "MUSICBRAINZ_RELEASEGROUPID", Matroska::SimpleTag::TargetTypeValue::Album),
|
||||
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),
|
||||
std::tuple("ALBUMARTISTSORT", "ARTISTSORT", Matroska::SimpleTag::TargetTypeValue::Album, true),
|
||||
std::tuple("ENCODEDBY", "ENCODED_BY", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("MEDIA", "ORIGINAL_MEDIA_TYPE", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("LABEL", "LABEL_CODE", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("CATALOGNUMBER", "CATALOG_NUMBER", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("DJMIXER", "MIXED_BY", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("REMIXER", "REMIXED_BY", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("INITIALKEY", "INITIAL_KEY", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("RELEASEDATE", "DATE_RELEASED", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("ENCODINGTIME", "DATE_ENCODED", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("TAGGINGDATE", "DATE_TAGGED", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("ENCODEDBY", "ENCODER", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("ENCODING", "ENCODER_SETTINGS", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("OWNER", "PURCHASE_OWNER", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("REPLAYGAIN_TRACK_GAIN", "REPLAYGAIN_GAIN", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("REPLAYGAIN_ALBUM_GAIN", "REPLAYGAIN_GAIN", Matroska::SimpleTag::TargetTypeValue::Album, true),
|
||||
std::tuple("REPLAYGAIN_TRACK_PEAK", "REPLAYGAIN_PEAK", Matroska::SimpleTag::TargetTypeValue::Track, false),
|
||||
std::tuple("REPLAYGAIN_ALBUM_PEAK", "REPLAYGAIN_PEAK", Matroska::SimpleTag::TargetTypeValue::Album, true),
|
||||
std::tuple("MUSICBRAINZ_ALBUMARTISTID", "MUSICBRAINZ_ALBUMARTISTID", Matroska::SimpleTag::TargetTypeValue::Album, false),
|
||||
std::tuple("MUSICBRAINZ_ALBUMID", "MUSICBRAINZ_ALBUMID", Matroska::SimpleTag::TargetTypeValue::Album, false),
|
||||
std::tuple("MUSICBRAINZ_RELEASEGROUPID", "MUSICBRAINZ_RELEASEGROUPID", Matroska::SimpleTag::TargetTypeValue::Album, false),
|
||||
};
|
||||
|
||||
std::pair<String, Matroska::SimpleTag::TargetTypeValue> translateKey(const String &key)
|
||||
std::tuple<String, Matroska::SimpleTag::TargetTypeValue, bool> translateKey(const String &key)
|
||||
{
|
||||
auto it = std::find_if(simpleTagsTranslation.cbegin(),
|
||||
simpleTagsTranslation.cend(),
|
||||
[&key](const auto &t) { return key == std::get<0>(t); }
|
||||
);
|
||||
if(it != simpleTagsTranslation.end())
|
||||
return { std::get<1>(*it), std::get<2>(*it) };
|
||||
return { std::get<1>(*it), std::get<2>(*it), std::get<3>(*it) };
|
||||
if (!key.isEmpty() && !key.startsWith("_"))
|
||||
return { key, Matroska::SimpleTag::TargetTypeValue::Track };
|
||||
return { String(), Matroska::SimpleTag::TargetTypeValue::None };
|
||||
return { key, Matroska::SimpleTag::TargetTypeValue::Track, false };
|
||||
return { String(), Matroska::SimpleTag::TargetTypeValue::None, false };
|
||||
}
|
||||
|
||||
String translateTag(const String &name, Matroska::SimpleTag::TargetTypeValue targetTypeValue)
|
||||
@ -355,12 +344,16 @@ namespace
|
||||
simpleTagsTranslation.cend(),
|
||||
[&name, targetTypeValue](const auto &t) {
|
||||
return name == std::get<1>(t)
|
||||
&& targetTypeValue == std::get<2>(t);
|
||||
&& (targetTypeValue == std::get<2>(t) ||
|
||||
(targetTypeValue == Matroska::SimpleTag::TargetTypeValue::None
|
||||
&& !std::get<3>(t)));
|
||||
}
|
||||
);
|
||||
return it != simpleTagsTranslation.end()
|
||||
? String(std::get<0>(*it), String::UTF8)
|
||||
: targetTypeValue == Matroska::SimpleTag::TargetTypeValue::Track && !name.startsWith("_")
|
||||
: (targetTypeValue == Matroska::SimpleTag::TargetTypeValue::Track ||
|
||||
targetTypeValue == Matroska::SimpleTag::TargetTypeValue::None) &&
|
||||
!name.startsWith("_")
|
||||
? name
|
||||
: String();
|
||||
}
|
||||
@ -368,59 +361,65 @@ namespace
|
||||
|
||||
bool Matroska::Tag::TagPrivate::setTag(const String &key, const String &value)
|
||||
{
|
||||
const auto pair = translateKey(key);
|
||||
const auto tpl = translateKey(key);
|
||||
// Workaround Clang issue - no lambda capture of structured bindings
|
||||
const String &name = pair.first;
|
||||
auto targetTypeValue = pair.second;
|
||||
const String &name = std::get<0>(tpl);
|
||||
auto targetTypeValue = std::get<1>(tpl);
|
||||
if(name.isEmpty())
|
||||
return false;
|
||||
removeSimpleTags(
|
||||
[&name, targetTypeValue] (auto t) {
|
||||
return t->name() == name
|
||||
&& t->targetTypeValue() == targetTypeValue;
|
||||
[&name, targetTypeValue] (const auto &t) {
|
||||
return t.name() == name
|
||||
&& t.targetTypeValue() == targetTypeValue;
|
||||
}
|
||||
);
|
||||
if(!value.isEmpty()) {
|
||||
auto t = new SimpleTagString();
|
||||
t->setTargetTypeValue(targetTypeValue);
|
||||
t->setName(name);
|
||||
t->setValue(value);
|
||||
tags.append(t);
|
||||
tags.append(SimpleTag(name, value, targetTypeValue));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const String *Matroska::Tag::TagPrivate::getTag(const String &key) const
|
||||
String Matroska::Tag::TagPrivate::getTag(const String &key) const
|
||||
{
|
||||
const auto pair = translateKey(key);
|
||||
const auto tpl = translateKey(key);
|
||||
// Workaround Clang issue - no lambda capture of structured bindings
|
||||
const String &name = pair.first;
|
||||
auto targetTypeValue = pair.second;
|
||||
const String &name = std::get<0>(tpl);
|
||||
auto targetTypeValue = std::get<1>(tpl);
|
||||
bool strict = std::get<2>(tpl);
|
||||
if(name.isEmpty())
|
||||
return nullptr;
|
||||
auto tag = dynamic_cast<const SimpleTagString *>(
|
||||
findSimpleTag(
|
||||
[&name, targetTypeValue] (auto t) {
|
||||
return t->name() == name
|
||||
&& t->targetTypeValue() == targetTypeValue;
|
||||
}
|
||||
)
|
||||
return {};
|
||||
auto it = std::find_if(tags.begin(), tags.end(),
|
||||
[&name, targetTypeValue, strict] (const SimpleTag &t) {
|
||||
return t.name() == name
|
||||
&& t.type() == SimpleTag::StringType
|
||||
&& (t.targetTypeValue() == targetTypeValue ||
|
||||
(t.targetTypeValue() == SimpleTag::TargetTypeValue::None && !strict));
|
||||
}
|
||||
);
|
||||
return tag ? &tag->value() : nullptr;
|
||||
return it != tags.end() ? it->toString() : String();
|
||||
}
|
||||
|
||||
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 &&
|
||||
!(key = translateTag(it->name(), it->targetTypeValue())).isEmpty()) {
|
||||
it = d->tags.erase(it);
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new properties
|
||||
PropertyMap unsupportedProperties;
|
||||
for(const auto &[key, values] : propertyMap) {
|
||||
for(const auto &value : values) {
|
||||
if(auto [name, targetTypeValue] = translateKey(key);
|
||||
if(auto [name, targetTypeValue, _] = translateKey(key);
|
||||
!name.isEmpty()) {
|
||||
auto t = new SimpleTagString();
|
||||
t->setTargetTypeValue(targetTypeValue);
|
||||
t->setName(name);
|
||||
t->setValue(value);
|
||||
d->tags.append(t);
|
||||
d->tags.append(SimpleTag(name, value, targetTypeValue));
|
||||
}
|
||||
else {
|
||||
unsupportedProperties[key] = values;
|
||||
@ -433,8 +432,8 @@ PropertyMap Matroska::Tag::setProperties(const PropertyMap &propertyMap)
|
||||
void Matroska::Tag::removeUnsupportedProperties(const StringList& properties)
|
||||
{
|
||||
d->removeSimpleTags(
|
||||
[&properties](const SimpleTag* t) {
|
||||
return properties.contains(t->name());
|
||||
[&properties](const SimpleTag &t) {
|
||||
return properties.contains(t.name());
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -442,9 +441,9 @@ void Matroska::Tag::removeUnsupportedProperties(const StringList& properties)
|
||||
StringList Matroska::Tag::complexPropertyKeys() const
|
||||
{
|
||||
StringList keys;
|
||||
for(const SimpleTag *t : std::as_const(d->tags)) {
|
||||
if(auto tBinary = dynamic_cast<const SimpleTagBinary*>(t)) {
|
||||
keys.append(tBinary->name());
|
||||
for(const SimpleTag &t : std::as_const(d->tags)) {
|
||||
if(t.type() == SimpleTag::BinaryType) {
|
||||
keys.append(t.name());
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
@ -454,19 +453,19 @@ List<VariantMap> Matroska::Tag::complexProperties(const String& key) const
|
||||
{
|
||||
List<VariantMap> props;
|
||||
if(key.upper() != "PICTURE") { // Pictures are handled at the file level
|
||||
for(const SimpleTag *t : std::as_const(d->tags)) {
|
||||
if(auto tBinary = dynamic_cast<const SimpleTagBinary*>(t)) {
|
||||
for(const SimpleTag &t : std::as_const(d->tags)) {
|
||||
if(t.type() == SimpleTag::BinaryType) {
|
||||
VariantMap property;
|
||||
property.insert("data", tBinary->value());
|
||||
property.insert("name", tBinary->name());
|
||||
property.insert("targetTypeValue", tBinary->targetTypeValue());
|
||||
property.insert("language", tBinary->language());
|
||||
property.insert("defaultLanguage", tBinary->defaultLanguageFlag());
|
||||
property.insert("data", t.toByteVector());
|
||||
property.insert("name", t.name());
|
||||
property.insert("targetTypeValue", t.targetTypeValue());
|
||||
property.insert("language", t.language());
|
||||
property.insert("defaultLanguage", t.defaultLanguageFlag());
|
||||
props.append(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TagLib::Tag::complexProperties(key);
|
||||
return props;
|
||||
}
|
||||
|
||||
bool Matroska::Tag::setComplexProperties(const String& key, const List<VariantMap>& value)
|
||||
@ -476,21 +475,20 @@ bool Matroska::Tag::setComplexProperties(const String& key, const List<VariantMa
|
||||
return false;
|
||||
}
|
||||
d->removeSimpleTags(
|
||||
[&key](const SimpleTag* t) {
|
||||
return t->name() == key && dynamic_cast<const SimpleTagBinary*>(t) != nullptr;
|
||||
[&key](const SimpleTag &t) {
|
||||
return t.name() == key && t.type() == SimpleTag::BinaryType;
|
||||
}
|
||||
);
|
||||
bool result = false;
|
||||
for(const auto &property : value) {
|
||||
if(property.value("name").value<String>() == key && property.contains("data")) {
|
||||
auto *t = new SimpleTagBinary;
|
||||
t->setTargetTypeValue(static_cast<SimpleTag::TargetTypeValue>(
|
||||
property.value("targetTypeValue", 0).value<int>()));
|
||||
t->setName(key);
|
||||
t->setValue(property.value("data").value<ByteVector>());
|
||||
t->setLanguage(property.value("language").value<String>());
|
||||
t->setDefaultLanguageFlag(property.value("defaultLanguage", true).value<bool>());
|
||||
d->tags.append(t);
|
||||
d->tags.append(SimpleTag(
|
||||
key,
|
||||
property.value("data").value<ByteVector>(),
|
||||
static_cast<SimpleTag::TargetTypeValue>(
|
||||
property.value("targetTypeValue", 0).value<int>()),
|
||||
property.value("language").value<String>(),
|
||||
property.value("defaultLanguage", true).value<bool>()));
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
@ -500,12 +498,13 @@ bool Matroska::Tag::setComplexProperties(const String& key, const List<VariantMa
|
||||
PropertyMap Matroska::Tag::properties() const
|
||||
{
|
||||
PropertyMap properties;
|
||||
SimpleTagString *tStr = nullptr;
|
||||
for(auto simpleTag : std::as_const(d->tags)) {
|
||||
if((tStr = dynamic_cast<SimpleTagString *>(simpleTag))) {
|
||||
String key = translateTag(tStr->name(), tStr->targetTypeValue());
|
||||
for(const auto &simpleTag : std::as_const(d->tags)) {
|
||||
if(simpleTag.type() == SimpleTag::StringType) {
|
||||
String key = translateTag(simpleTag.name(), simpleTag.targetTypeValue());
|
||||
if(!key.isEmpty())
|
||||
properties[key].append(tStr->value());
|
||||
properties[key].append(simpleTag.toString());
|
||||
else
|
||||
properties.addUnsupportedData(simpleTag.name());
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
|
||||
@ -37,7 +37,7 @@ namespace TagLib {
|
||||
}
|
||||
|
||||
namespace Matroska {
|
||||
using SimpleTagsList = List<SimpleTag *>;
|
||||
using SimpleTagsList = List<SimpleTag>;
|
||||
class TAGLIB_EXPORT Tag : public TagLib::Tag
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
, private Element
|
||||
@ -76,7 +76,7 @@ namespace TagLib {
|
||||
* The attached files such as pictures with key "PICTURE" are available
|
||||
* with Matroska::File::complexProperties().
|
||||
*/
|
||||
List<VariantMap> complexProperties(const String& key) const override;
|
||||
List<VariantMap> complexProperties(const String &key) const override;
|
||||
|
||||
/*!
|
||||
* Set the binary simple tags as maps with keys "data", "name",
|
||||
@ -88,8 +88,8 @@ namespace TagLib {
|
||||
*/
|
||||
bool setComplexProperties(const String& key, const List<VariantMap>& value) override;
|
||||
|
||||
void addSimpleTag(SimpleTag *tag);
|
||||
void removeSimpleTag(SimpleTag *tag);
|
||||
void addSimpleTag(const SimpleTag &tag);
|
||||
void removeSimpleTag(const String &name, SimpleTag::TargetTypeValue targetTypeValue);
|
||||
void clearSimpleTags();
|
||||
const SimpleTagsList &simpleTagsList() const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user