Refactor MediaFileInfo::createAppropriateTags()
This commit is contained in:
parent
dabd18102e
commit
b47705ff81
|
@ -64,6 +64,7 @@ set(HEADER_FILES
|
||||||
opus/opusidentificationheader.h
|
opus/opusidentificationheader.h
|
||||||
positioninset.h
|
positioninset.h
|
||||||
progressfeedback.h
|
progressfeedback.h
|
||||||
|
settings.h
|
||||||
signature.h
|
signature.h
|
||||||
size.h
|
size.h
|
||||||
tag.h
|
tag.h
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define TAG_PARSER_ABSTRACTCONTAINER_H
|
#define TAG_PARSER_ABSTRACTCONTAINER_H
|
||||||
|
|
||||||
#include "./exceptions.h"
|
#include "./exceptions.h"
|
||||||
|
#include "./settings.h"
|
||||||
#include "./tagtarget.h"
|
#include "./tagtarget.h"
|
||||||
|
|
||||||
#include <c++utilities/chrono/datetime.h>
|
#include <c++utilities/chrono/datetime.h>
|
||||||
|
@ -25,12 +26,6 @@ class AbstractAttachment;
|
||||||
class Diagnostics;
|
class Diagnostics;
|
||||||
class AbortableProgressFeedback;
|
class AbortableProgressFeedback;
|
||||||
|
|
||||||
enum class ElementPosition {
|
|
||||||
BeforeData, /**< the element is positioned before the actual data */
|
|
||||||
AfterData, /**< the element is positioned after the actual data */
|
|
||||||
Keep /**< the element is placed where it was before */
|
|
||||||
};
|
|
||||||
|
|
||||||
class TAG_PARSER_EXPORT AbstractContainer {
|
class TAG_PARSER_EXPORT AbstractContainer {
|
||||||
public:
|
public:
|
||||||
virtual ~AbstractContainer();
|
virtual ~AbstractContainer();
|
||||||
|
|
|
@ -489,16 +489,7 @@ void MediaFileInfo::parseEverything(Diagnostics &diag)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Ensures appropriate tags are created according the given specifications.
|
* \brief Ensures appropriate tags are created according the given \a settings.
|
||||||
* \param treatUnknownFilesAsMp3Files Specifies whether unknown file formats should be treated as MP3 (might break the file).
|
|
||||||
* \param id3v1usage Specifies the usage of ID3v1 when creating tags for MP3 files (has no effect when the file is no MP3 file or not treated as one).
|
|
||||||
* \param id3v2usage Specifies the usage of ID3v2 when creating tags for MP3 files (has no effect when the file is no MP3 file or not treated as one).
|
|
||||||
* \param id3InitOnCreate Indicates whether to initialize newly created ID3 tags (according to \a id3v1usage and \a id3v2usage) with the values of the already present ID3 tags.
|
|
||||||
* \param id3TransferValuesOnRemoval Indicates whether values of removed ID3 tags (according to \a id3v1usage and \a id3v2usage) should be transfered to remaining ID3 tags (no values will be overwritten).
|
|
||||||
* \param mergeMultipleSuccessiveId3v2Tags Specifies whether multiple successive ID3v2 tags should be merged (see mergeId3v2Tags()).
|
|
||||||
* \param keepExistingId3v2version Specifies whether the version of existing ID3v2 tags should be adjusted to \a id3v2version (otherwise \a id3v2version is only used when creating a new ID3v2 tag).
|
|
||||||
* \param id3v2MajorVersion Specifies the ID3v2 version to be used. Valid values are 2, 3 and 4.
|
|
||||||
* \param requiredTargets Specifies the required targets. If targets are not supported by the container an informal notification is added.
|
|
||||||
* \return Returns whether appropriate tags could be created for the file.
|
* \return Returns whether appropriate tags could be created for the file.
|
||||||
* \remarks
|
* \remarks
|
||||||
* - Tags must have been parsed before invoking this method (otherwise it will just return false).
|
* - Tags must have been parsed before invoking this method (otherwise it will just return false).
|
||||||
|
@ -506,20 +497,20 @@ void MediaFileInfo::parseEverything(Diagnostics &diag)
|
||||||
* - Tags might be removed as well. For example the existing ID3v1 tag of an MP3 file will be removed if \a id3v1Usage is set to TagUsage::Never.
|
* - Tags might be removed as well. For example the existing ID3v1 tag of an MP3 file will be removed if \a id3v1Usage is set to TagUsage::Never.
|
||||||
* - The method might do nothing if present tag(s) already match the given specifications.
|
* - The method might do nothing if present tag(s) already match the given specifications.
|
||||||
* - This is only a convenience method. The task could be done by manually using the methods createId3v1Tag(), createId3v2Tag(), removeId3v1Tag() ... as well.
|
* - This is only a convenience method. The task could be done by manually using the methods createId3v1Tag(), createId3v2Tag(), removeId3v1Tag() ... as well.
|
||||||
* - Some tag information might be discarded. For example when an ID3v2 tag needs to be removed (\a id3v2usage is set to TagUsage::Never) and an ID3v1 tag will be created instead not all fields can be transfered.
|
* - Some tag information might be discarded. For example when an ID3v2 tag needs to be removed (TagSettings::id3v2usage is set to TagUsage::Never) and an ID3v1 tag will be created instead not all fields can be transfered.
|
||||||
* \todo Refactoring required, there are too much params (not sure how to refactor though, since not all of the params are simple flags).
|
|
||||||
*/
|
*/
|
||||||
bool MediaFileInfo::createAppropriateTags(bool treatUnknownFilesAsMp3Files, TagUsage id3v1usage, TagUsage id3v2usage, bool id3InitOnCreate,
|
bool MediaFileInfo::createAppropriateTags(const TagCreationSettings &settings)
|
||||||
bool id3TransferValuesOnRemoval, bool mergeMultipleSuccessiveId3v2Tags, bool keepExistingId3v2version, byte id3v2MajorVersion,
|
|
||||||
const std::vector<TagTarget> &requiredTargets)
|
|
||||||
{
|
{
|
||||||
// check if tags have been parsed yet (tags must have been parsed yet to create appropriate tags)
|
// check if tags have been parsed yet (tags must have been parsed yet to create appropriate tags)
|
||||||
if (tagsParsingStatus() == ParsingStatus::NotParsedYet) {
|
if (tagsParsingStatus() == ParsingStatus::NotParsedYet) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if tags need to be created/adjusted/removed
|
// check if tags need to be created/adjusted/removed
|
||||||
bool targetsRequired = !requiredTargets.empty() && (requiredTargets.size() != 1 || !requiredTargets.front().isEmpty());
|
const auto requiredTargets(settings.requiredTargets);
|
||||||
bool targetsSupported = false;
|
const auto flags(settings.flags);
|
||||||
|
const auto targetsRequired = !requiredTargets.empty() && (requiredTargets.size() != 1 || !requiredTargets.front().isEmpty());
|
||||||
|
auto targetsSupported = false;
|
||||||
if (areTagsSupported() && m_container) {
|
if (areTagsSupported() && m_container) {
|
||||||
// container object takes care of tag management
|
// container object takes care of tag management
|
||||||
if (targetsRequired) {
|
if (targetsRequired) {
|
||||||
|
@ -529,11 +520,9 @@ bool MediaFileInfo::createAppropriateTags(bool treatUnknownFilesAsMp3Files, TagU
|
||||||
targetsSupported = m_container->tag(0)->supportsTarget();
|
targetsSupported = m_container->tag(0)->supportsTarget();
|
||||||
} else {
|
} else {
|
||||||
// try to create a new tag and check whether targets are supported
|
// try to create a new tag and check whether targets are supported
|
||||||
auto *tag = m_container->createTag();
|
auto *const tag = m_container->createTag();
|
||||||
if (tag) {
|
if (tag && (targetsSupported = tag->supportsTarget())) {
|
||||||
if ((targetsSupported = tag->supportsTarget())) {
|
tag->setTarget(requiredTargets.front());
|
||||||
tag->setTarget(requiredTargets.front());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (targetsSupported) {
|
if (targetsSupported) {
|
||||||
|
@ -545,82 +534,74 @@ bool MediaFileInfo::createAppropriateTags(bool treatUnknownFilesAsMp3Files, TagU
|
||||||
// no targets are required -> just ensure that at least one tag is present
|
// no targets are required -> just ensure that at least one tag is present
|
||||||
m_container->createTag();
|
m_container->createTag();
|
||||||
}
|
}
|
||||||
} else {
|
return true;
|
||||||
// no container object present
|
}
|
||||||
if (m_containerFormat == ContainerFormat::Flac) {
|
|
||||||
// creation of Vorbis comment is possible
|
|
||||||
static_cast<FlacStream *>(m_singleTrack.get())->createVorbisComment();
|
|
||||||
} else {
|
|
||||||
// creation of ID3 tag is possible
|
|
||||||
if (!hasAnyTag() && !treatUnknownFilesAsMp3Files) {
|
|
||||||
switch (containerFormat()) {
|
|
||||||
case ContainerFormat::Adts:
|
|
||||||
case ContainerFormat::MpegAudioFrames:
|
|
||||||
case ContainerFormat::WavPack:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// create ID3 tags according to id3v2usage and id3v2usage
|
|
||||||
if (id3v1usage == TagUsage::Always) {
|
|
||||||
// always create ID3v1 tag -> ensure there is one
|
|
||||||
if (!id3v1Tag()) {
|
|
||||||
Id3v1Tag *id3v1Tag = createId3v1Tag();
|
|
||||||
if (id3InitOnCreate) {
|
|
||||||
for (const auto &id3v2Tag : id3v2Tags()) {
|
|
||||||
// overwrite existing values to ensure default ID3v1 genre "Blues" is updated as well
|
|
||||||
id3v1Tag->insertValues(*id3v2Tag, true);
|
|
||||||
// ID3v1 does not support all text encodings which might be used in ID3v2
|
|
||||||
id3v1Tag->ensureTextValuesAreProperlyEncoded();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (id3v2usage == TagUsage::Always) {
|
|
||||||
// always create ID3v2 tag -> ensure there is one and set version
|
|
||||||
if (!hasId3v2Tag()) {
|
|
||||||
Id3v2Tag *id3v2Tag = createId3v2Tag();
|
|
||||||
id3v2Tag->setVersion(id3v2MajorVersion, 0);
|
|
||||||
if (id3InitOnCreate && id3v1Tag()) {
|
|
||||||
id3v2Tag->insertValues(*id3v1Tag(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mergeMultipleSuccessiveId3v2Tags) {
|
// no container object present
|
||||||
mergeId3v2Tags();
|
switch (m_containerFormat) {
|
||||||
}
|
case ContainerFormat::Flac:
|
||||||
// remove ID3 tags according to id3v1usage and id3v2usage
|
static_cast<FlacStream *>(m_singleTrack.get())->createVorbisComment();
|
||||||
if (id3v1usage == TagUsage::Never) {
|
break;
|
||||||
if (hasId3v1Tag()) {
|
default:
|
||||||
// transfer tags to ID3v2 tag before removing
|
// create ID3 tag(s)
|
||||||
if (id3TransferValuesOnRemoval && hasId3v2Tag()) {
|
if (!hasAnyTag() && !(flags & TagCreationFlags::TreatUnknownFilesAsMp3Files)) {
|
||||||
id3v2Tags().front()->insertValues(*id3v1Tag(), false);
|
switch (containerFormat()) {
|
||||||
}
|
case ContainerFormat::Adts:
|
||||||
removeId3v1Tag();
|
case ContainerFormat::MpegAudioFrames:
|
||||||
|
case ContainerFormat::WavPack:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (id3v2usage == TagUsage::Never) {
|
// create ID3 tags according to id3v2usage and id3v2usage
|
||||||
if (id3TransferValuesOnRemoval && hasId3v1Tag()) {
|
// always create ID3v1 tag -> ensure there is one
|
||||||
// transfer tags to ID3v1 tag before removing
|
if (settings.id3v1usage == TagUsage::Always && !id3v1Tag()) {
|
||||||
for (const auto &tag : id3v2Tags()) {
|
auto *const id3v1Tag = createId3v1Tag();
|
||||||
id3v1Tag()->insertValues(*tag, false);
|
if (flags & TagCreationFlags::Id3InitOnCreate) {
|
||||||
|
for (const auto &id3v2Tag : id3v2Tags()) {
|
||||||
|
// overwrite existing values to ensure default ID3v1 genre "Blues" is updated as well
|
||||||
|
id3v1Tag->insertValues(*id3v2Tag, true);
|
||||||
|
// ID3v1 does not support all text encodings which might be used in ID3v2
|
||||||
|
id3v1Tag->ensureTextValuesAreProperlyEncoded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removeAllId3v2Tags();
|
}
|
||||||
} else if (!keepExistingId3v2version) {
|
if (settings.id3v2usage == TagUsage::Always && !hasId3v2Tag()) {
|
||||||
// set version of ID3v2 tag according user preferences
|
// always create ID3v2 tag -> ensure there is one and set version
|
||||||
for (const auto &tag : id3v2Tags()) {
|
auto *const id3v2Tag = createId3v2Tag();
|
||||||
tag->setVersion(id3v2MajorVersion, 0);
|
id3v2Tag->setVersion(settings.id3v2MajorVersion, 0);
|
||||||
|
if ((flags & TagCreationFlags::Id3InitOnCreate) && id3v1Tag()) {
|
||||||
|
id3v2Tag->insertValues(*id3v1Tag(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME
|
|
||||||
//if(targetsRequired && !targetsSupported) {
|
if (flags & TagCreationFlags::MergeMultipleSuccessiveId3v2Tags) {
|
||||||
// diag.emplace_back(DiagLevel::Information, "The container/tags do not support targets. The specified targets are ignored.", "creating tags");
|
mergeId3v2Tags();
|
||||||
//}
|
}
|
||||||
|
// remove ID3 tags according to settings
|
||||||
|
if (settings.id3v1usage == TagUsage::Never && hasId3v1Tag()) {
|
||||||
|
// transfer tags to ID3v2 tag before removing
|
||||||
|
if ((flags & TagCreationFlags::Id3TransferValuesOnRemoval) && hasId3v2Tag()) {
|
||||||
|
id3v2Tags().front()->insertValues(*id3v1Tag(), false);
|
||||||
|
}
|
||||||
|
removeId3v1Tag();
|
||||||
|
}
|
||||||
|
if (settings.id3v2usage == TagUsage::Never) {
|
||||||
|
if ((flags & TagCreationFlags::Id3TransferValuesOnRemoval) && hasId3v1Tag()) {
|
||||||
|
// transfer tags to ID3v1 tag before removing
|
||||||
|
for (const auto &tag : id3v2Tags()) {
|
||||||
|
id3v1Tag()->insertValues(*tag, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removeAllId3v2Tags();
|
||||||
|
} else if (!(flags & TagCreationFlags::KeepExistingId3v2Version)) {
|
||||||
|
// set version of ID3v2 tag according user preferences
|
||||||
|
for (const auto &tag : id3v2Tags()) {
|
||||||
|
tag->setVersion(settings.id3v2MajorVersion, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1307,11 +1288,11 @@ void MediaFileInfo::mergeId3v2Tags()
|
||||||
*/
|
*/
|
||||||
bool MediaFileInfo::id3v1ToId3v2()
|
bool MediaFileInfo::id3v1ToId3v2()
|
||||||
{
|
{
|
||||||
if (tagsParsingStatus() != ParsingStatus::NotParsedYet && areTagsSupported() && hasId3v1Tag()) {
|
if (tagsParsingStatus() == ParsingStatus::NotParsedYet || !areTagsSupported() || !hasId3v1Tag()) {
|
||||||
return createAppropriateTags(false, TagUsage::Never, TagUsage::Always, true, true, 3);
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return createAppropriateTags(TagCreationSettings{
|
||||||
|
{}, TagCreationFlags::MergeMultipleSuccessiveId3v2Tags | TagCreationFlags::KeepExistingId3v2Version, TagUsage::Never, TagUsage::Always, 3 });
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -1326,11 +1307,11 @@ bool MediaFileInfo::id3v1ToId3v2()
|
||||||
*/
|
*/
|
||||||
bool MediaFileInfo::id3v2ToId3v1()
|
bool MediaFileInfo::id3v2ToId3v1()
|
||||||
{
|
{
|
||||||
if (tagsParsingStatus() != ParsingStatus::NotParsedYet && areTagsSupported() && hasId3v2Tag()) {
|
if (tagsParsingStatus() == ParsingStatus::NotParsedYet || !areTagsSupported() || !hasId3v2Tag()) {
|
||||||
return createAppropriateTags(false, TagUsage::Always, TagUsage::Never, true, true, 3);
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return createAppropriateTags(TagCreationSettings{
|
||||||
|
{}, TagCreationFlags::MergeMultipleSuccessiveId3v2Tags | TagCreationFlags::KeepExistingId3v2Version, TagUsage::Always, TagUsage::Never, 3 });
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "./abstractcontainer.h"
|
#include "./abstractcontainer.h"
|
||||||
#include "./basicfileinfo.h"
|
#include "./basicfileinfo.h"
|
||||||
|
#include "./settings.h"
|
||||||
#include "./signature.h"
|
#include "./signature.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -29,15 +30,6 @@ class AbortableProgressFeedback;
|
||||||
enum class MediaType;
|
enum class MediaType;
|
||||||
DECLARE_ENUM_CLASS(TagType, unsigned int);
|
DECLARE_ENUM_CLASS(TagType, unsigned int);
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief The TagUsage enum specifies the usage of a certain tag type.
|
|
||||||
*/
|
|
||||||
enum class TagUsage {
|
|
||||||
Always, /**< a tag of the type is always used; a new tag is created if none exists yet */
|
|
||||||
KeepExisting, /**< existing tags of the type are kept and updated but no new tag is created */
|
|
||||||
Never /**< tags of the type are never used; a possibly existing tag of the type is removed */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The ParsingStatus enum specifies whether a certain part of the file (tracks, tags, ...) has
|
* \brief The ParsingStatus enum specifies whether a certain part of the file (tracks, tags, ...) has
|
||||||
* been parsed yet and if what the parsing result is.
|
* been parsed yet and if what the parsing result is.
|
||||||
|
@ -112,10 +104,7 @@ public:
|
||||||
bool areTagsSupported() const;
|
bool areTagsSupported() const;
|
||||||
|
|
||||||
// methods to create/remove tags
|
// methods to create/remove tags
|
||||||
bool createAppropriateTags(bool treatUnknownFilesAsMp3Files = false, TagUsage id3v1usage = TagUsage::KeepExisting,
|
bool createAppropriateTags(const TagCreationSettings &settings = TagCreationSettings());
|
||||||
TagUsage id3v2usage = TagUsage::Always, bool id3InitOnCreate = false, bool id3TransferValuesOnRemoval = true,
|
|
||||||
bool mergeMultipleSuccessiveId3v2Tags = true, bool keepExistingId3v2version = true, byte id3v2MajorVersion = 3,
|
|
||||||
const std::vector<TagTarget> &requiredTargets = std::vector<TagTarget>());
|
|
||||||
bool removeId3v1Tag();
|
bool removeId3v1Tag();
|
||||||
Id3v1Tag *createId3v1Tag();
|
Id3v1Tag *createId3v1Tag();
|
||||||
bool removeId3v2Tag(Id3v2Tag *tag);
|
bool removeId3v2Tag(Id3v2Tag *tag);
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
#ifndef TAGPARSER_SETTINGS_H
|
||||||
|
#define TAGPARSER_SETTINGS_H
|
||||||
|
|
||||||
|
#include "./tagtarget.h"
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace TagParser {
|
||||||
|
|
||||||
|
enum class ElementPosition {
|
||||||
|
BeforeData, /**< the element is positioned before the actual data */
|
||||||
|
AfterData, /**< the element is positioned after the actual data */
|
||||||
|
Keep, /**< the element is placed where it was before */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The TagUsage enum specifies the usage of a certain tag type.
|
||||||
|
*/
|
||||||
|
enum class TagUsage {
|
||||||
|
Always, /**< a tag of the type is always used; a new tag is created if none exists yet */
|
||||||
|
KeepExisting, /**< existing tags of the type are kept and updated but no new tag is created */
|
||||||
|
Never, /**< tags of the type are never used; a possibly existing tag of the type is removed */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The Flags enum contains options to control the tag creation via MediaFileInfo::createAppropriateTags().
|
||||||
|
*/
|
||||||
|
enum class TagCreationFlags : uint64 {
|
||||||
|
None = 0, /**< no flags present */
|
||||||
|
TreatUnknownFilesAsMp3Files = 1 << 0, /**< treat unknown file formats as MP3 (might make those files unusable) */
|
||||||
|
Id3InitOnCreate = 1 << 1, /**< initialize newly created ID3 tags with the values of the already present ID3 tags */
|
||||||
|
Id3TransferValuesOnRemoval = 1 << 2, /**< transfer values of removed ID3 tags to remaining ID3 tags (no values will be overwritten) */
|
||||||
|
MergeMultipleSuccessiveId3v2Tags = 1 << 3, /**< merge multiple successive ID3v2 tags (see MediaFileInfo::mergeId3v2Tags()) */
|
||||||
|
KeepExistingId3v2Version
|
||||||
|
= 1 << 4, /**< keep version of existing ID3v2 tags so TagSettings::id3v2version is only used when creating a *new* ID3v2 tag */
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr TagCreationFlags operator|(TagCreationFlags lhs, TagCreationFlags rhs)
|
||||||
|
{
|
||||||
|
return static_cast<TagCreationFlags>(
|
||||||
|
static_cast<std::underlying_type<TagCreationFlags>::type>(lhs) | static_cast<std::underlying_type<TagCreationFlags>::type>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator&(TagCreationFlags lhs, TagCreationFlags rhs)
|
||||||
|
{
|
||||||
|
return static_cast<std::underlying_type<TagCreationFlags>::type>(lhs) & static_cast<std::underlying_type<TagCreationFlags>::type>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr TagCreationFlags &operator|=(TagCreationFlags &lhs, TagCreationFlags rhs)
|
||||||
|
{
|
||||||
|
return lhs = static_cast<TagCreationFlags>(
|
||||||
|
static_cast<std::underlying_type<TagCreationFlags>::type>(lhs) | static_cast<std::underlying_type<TagCreationFlags>::type>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr TagCreationFlags &operator+=(TagCreationFlags &lhs, TagCreationFlags rhs)
|
||||||
|
{
|
||||||
|
return lhs = static_cast<TagCreationFlags>(
|
||||||
|
static_cast<std::underlying_type<TagCreationFlags>::type>(lhs) | static_cast<std::underlying_type<TagCreationFlags>::type>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr TagCreationFlags &operator-=(TagCreationFlags &lhs, TagCreationFlags rhs)
|
||||||
|
{
|
||||||
|
return lhs = static_cast<TagCreationFlags>(
|
||||||
|
static_cast<std::underlying_type<TagCreationFlags>::type>(lhs) & (~static_cast<std::underlying_type<TagCreationFlags>::type>(rhs)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The TagSettings struct contains settings which can be passed to MediaFileInfo::createAppropriateTags().
|
||||||
|
*/
|
||||||
|
struct TagCreationSettings {
|
||||||
|
/// \brief Specifies the required targets. If targets are not supported by the container an informal notification is added.
|
||||||
|
std::vector<TagTarget> requiredTargets = std::vector<TagTarget>();
|
||||||
|
/// \brief Specifies options to control the tag creation. See TagSettings::Flags.
|
||||||
|
TagCreationFlags flags = TagCreationFlags::Id3TransferValuesOnRemoval | TagCreationFlags::MergeMultipleSuccessiveId3v2Tags
|
||||||
|
| TagCreationFlags::KeepExistingId3v2Version;
|
||||||
|
/// \brief Specifies the usage of ID3v1 when creating tags for MP3 files (has no effect when the file is no MP3 file or not treated as one).
|
||||||
|
TagUsage id3v1usage = TagUsage::KeepExisting;
|
||||||
|
/// \brief Specifies the usage of ID3v2 when creating tags for MP3 files (has no effect when the file is no MP3 file or not treated as one).
|
||||||
|
TagUsage id3v2usage = TagUsage::Always;
|
||||||
|
/// \brief Specifies the ID3v2 version to be used in case an ID3v2 tag present or will be created. Valid values are 2, 3 and 4.
|
||||||
|
byte id3v2MajorVersion = 3;
|
||||||
|
|
||||||
|
constexpr TagCreationSettings &setFlag(TagCreationFlags flag, bool enabled);
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr TagCreationSettings &TagCreationSettings::setFlag(TagCreationFlags flag, bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled) {
|
||||||
|
flags |= flag;
|
||||||
|
} else {
|
||||||
|
flags -= flag;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace TagParser
|
||||||
|
|
||||||
|
#endif // TAGPARSER_SETTINGS_H
|
|
@ -31,7 +31,7 @@ enum class TagTextEncoding : unsigned int {
|
||||||
* \brief Returns the size of one character for the specified \a encoding in bytes.
|
* \brief Returns the size of one character for the specified \a encoding in bytes.
|
||||||
* \remarks For variable-width encoding the minimum size is returned.
|
* \remarks For variable-width encoding the minimum size is returned.
|
||||||
*/
|
*/
|
||||||
inline int characterSize(TagTextEncoding encoding)
|
constexpr int characterSize(TagTextEncoding encoding)
|
||||||
{
|
{
|
||||||
switch (encoding) {
|
switch (encoding) {
|
||||||
case TagTextEncoding::Latin1:
|
case TagTextEncoding::Latin1:
|
||||||
|
@ -132,7 +132,6 @@ public:
|
||||||
static void ensureHostByteOrder(std::u16string &u16str, TagTextEncoding currentEncoding);
|
static void ensureHostByteOrder(std::u16string &u16str, TagTextEncoding currentEncoding);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::unique_ptr<char[]> m_ptr;
|
std::unique_ptr<char[]> m_ptr;
|
||||||
std::size_t m_size;
|
std::size_t m_size;
|
||||||
std::string m_desc;
|
std::string m_desc;
|
||||||
|
|
Loading…
Reference in New Issue