added --remove-targets and --remove-existing-attachments
This commit is contained in:
parent
c692795a9d
commit
53330c7d2c
|
@ -68,7 +68,7 @@ int main(int argc, char *argv[])
|
|||
displayTagInfoArg.setValueNames({"title", "album", "artist", "trackpos"});
|
||||
displayTagInfoArg.setSecondaryArguments({&filesArg, &verboseArg});
|
||||
// set tag info
|
||||
Argument removeOtherFieldsArg("remove-other-fields", string(), "if present ALL unspecified tag fields will be removed; otherwise use eg. \"album=\" to remove a specific field");
|
||||
Argument removeOtherFieldsArg("remove-other-fields", string(), "if present ALL unspecified tag fields will be removed (to remove a specific field use eg. \"album=\")");
|
||||
removeOtherFieldsArg.setCombinable(true);
|
||||
Argument treatUnknownFilesAsMp3FilesArg("treat-unknown-as-mp3", string(), "if present unknown files will be treatet as MP3 files");
|
||||
treatUnknownFilesAsMp3FilesArg.setCombinable(true);
|
||||
|
@ -90,16 +90,22 @@ int main(int argc, char *argv[])
|
|||
encodingArg.setRequiredValueCount(1);
|
||||
encodingArg.setValueNames({"latin1/utf8/utf16le/utf16be"});
|
||||
encodingArg.setCombinable(true);
|
||||
Argument attachmentsArg("attachments", string(), "specifies attachments to be added/updated/removed");
|
||||
Argument removeTargetsArg("remove-targets", string(), "removes all tags with the specified targets (which must be separated by \",\")");
|
||||
removeTargetsArg.setRequiredValueCount(-1);
|
||||
removeTargetsArg.setValueNames({""});
|
||||
removeTargetsArg.setCombinable(true);
|
||||
Argument attachmentsArg("attachments", string(), "specifies attachments to be added/updated/removed (multiple attachments must be separated by \",\"");
|
||||
attachmentsArg.setRequiredValueCount(-1);
|
||||
attachmentsArg.setValueNames({"path=some/file", "name=Some name", "desc=Some desc", "mime=mime/type", ",", "path=another/file"});
|
||||
attachmentsArg.setCombinable(true);
|
||||
Argument removeExistingAttachmentsArg("remove-existing-attachments", "ra", "specifies names/IDs of existing attachments to be removed");
|
||||
removeExistingAttachmentsArg.setCombinable(true);
|
||||
Argument setTagInfoArg("set-tag-info", "set", "sets the values of all specified tag fields");
|
||||
setTagInfoArg.setDenotesOperation(true);
|
||||
setTagInfoArg.setCallback(std::bind(Cli::setTagInfo, _1, std::cref(filesArg), std::cref(removeOtherFieldsArg), std::cref(treatUnknownFilesAsMp3FilesArg), std::cref(id3v1UsageArg), std::cref(id3v2UsageArg), std::cref(mergeMultipleSuccessiveTagsArg), std::cref(id3v2VersionArg), std::cref(encodingArg), std::cref(attachmentsArg), std::cref(verboseArg)));
|
||||
setTagInfoArg.setCallback(std::bind(Cli::setTagInfo, _1, std::cref(filesArg), std::cref(removeOtherFieldsArg), std::cref(treatUnknownFilesAsMp3FilesArg), std::cref(id3v1UsageArg), std::cref(id3v2UsageArg), std::cref(mergeMultipleSuccessiveTagsArg), std::cref(id3v2VersionArg), std::cref(encodingArg), std::cref(removeTargetsArg), std::cref(attachmentsArg), std::cref(removeExistingAttachmentsArg), std::cref(verboseArg)));
|
||||
setTagInfoArg.setRequiredValueCount(-1);
|
||||
setTagInfoArg.setValueNames({"title=foo", "album=bar", "cover=/path/to/file"});
|
||||
setTagInfoArg.setSecondaryArguments({&filesArg, &removeOtherFieldsArg, &treatUnknownFilesAsMp3FilesArg, &id3v1UsageArg, &id3v2UsageArg, &mergeMultipleSuccessiveTagsArg, &id3v2VersionArg, &encodingArg, &attachmentsArg, &verboseArg});
|
||||
setTagInfoArg.setSecondaryArguments({&filesArg, &removeOtherFieldsArg, &treatUnknownFilesAsMp3FilesArg, &id3v1UsageArg, &id3v2UsageArg, &mergeMultipleSuccessiveTagsArg, &id3v2VersionArg, &encodingArg, &removeTargetsArg, &attachmentsArg, &removeExistingAttachmentsArg, &verboseArg});
|
||||
// extract cover
|
||||
Argument extractFieldArg("extract", "ext", "extracts the specified field from the specified file");
|
||||
extractFieldArg.setRequiredValueCount(1);
|
||||
|
|
|
@ -52,16 +52,16 @@ inline TagType &operator|= (TagType &lhs, TagType rhs)
|
|||
|
||||
struct FieldDenotation
|
||||
{
|
||||
FieldDenotation();
|
||||
bool present;
|
||||
FieldDenotation(KnownField field);
|
||||
KnownField field;
|
||||
DenotationType type;
|
||||
TagType tagType;
|
||||
TagTarget tagTarget;
|
||||
std::vector<std::pair<unsigned int, QString> > values;
|
||||
};
|
||||
|
||||
FieldDenotation::FieldDenotation() :
|
||||
present(false),
|
||||
FieldDenotation::FieldDenotation(KnownField field) :
|
||||
field(field),
|
||||
type(DenotationType::Normal),
|
||||
tagType(TagType::Unspecified)
|
||||
{}
|
||||
|
@ -224,33 +224,38 @@ TagTarget::IdContainerType parseIds(const std::string &concatenatedIds)
|
|||
|
||||
bool applyTargetConfiguration(TagTarget &target, const std::string &configStr)
|
||||
{
|
||||
if(strncmp(configStr.c_str(), "target-level:", 13) == 0) {
|
||||
try {
|
||||
target.setLevel(stringToNumber<uint64>(configStr.substr(13)));
|
||||
} catch (ConversionException &) {
|
||||
cout << "Warning: The specified target level \"" << configStr.substr(13) << "\" is invalid and will be ignored." << endl;
|
||||
if(!configStr.empty()) {
|
||||
if(configStr.compare(0, 13, "target-level=") == 0) {
|
||||
try {
|
||||
target.setLevel(stringToNumber<uint64>(configStr.substr(13)));
|
||||
} catch (ConversionException &) {
|
||||
cout << "Warning: The specified target level \"" << configStr.substr(13) << "\" is invalid and will be ignored." << endl;
|
||||
}
|
||||
} else if(configStr.compare(0, 17, "target-levelname=") == 0) {
|
||||
target.setLevelName(configStr.substr(17));
|
||||
} else if(configStr.compare(0, 14, "target-tracks=") == 0) {
|
||||
target.tracks() = parseIds(configStr.substr(14));
|
||||
} else if(configStr.compare(0, 16, "target-chapters=") == 0) {
|
||||
target.chapters() = parseIds(configStr.substr(16));
|
||||
} else if(configStr.compare(0, 16, "target-editions=") == 0) {
|
||||
target.editions() = parseIds(configStr.substr(16));
|
||||
} else if(configStr.compare(0, 17, "target-attachments=") == 0) {
|
||||
target.attachments() = parseIds(configStr.substr(17));
|
||||
} else if(configStr == "target-reset") {
|
||||
target.clear();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if(configStr.compare(0, 17, "target-levelname:") == 0) {
|
||||
target.setLevelName(configStr.substr(17));
|
||||
} else if(configStr.compare(0, 14, "target-tracks:") == 0) {
|
||||
target.tracks() = parseIds(configStr.substr(14));
|
||||
} else if(configStr.compare(0, 16, "target-chapters:") == 0) {
|
||||
target.chapters() = parseIds(configStr.substr(16));
|
||||
} else if(configStr.compare(0, 16, "target-editions:") == 0) {
|
||||
target.editions() = parseIds(configStr.substr(16));
|
||||
} else if(configStr.compare(0, 17, "target-attachments:") == 0) {
|
||||
target.attachments() = parseIds(configStr.substr(17));
|
||||
} else if(configStr == "target-reset") {
|
||||
target.clear();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int parseFieldDenotations(const StringVector &fieldDenotations, bool readOnly, FieldDenotation *fields)
|
||||
vector<FieldDenotation> parseFieldDenotations(const StringVector &fieldDenotations, bool readOnly)
|
||||
{
|
||||
unsigned int validDenotations = 0;
|
||||
vector<FieldDenotation> fields;
|
||||
fields.reserve(fieldDenotations.size());
|
||||
TagType currentTagType = TagType::Unspecified;
|
||||
TagTarget currentTagTarget;
|
||||
for(const string &fieldDenotationString : fieldDenotations) {
|
||||
|
@ -382,8 +387,8 @@ unsigned int parseFieldDenotations(const StringVector &fieldDenotations, bool re
|
|||
continue;
|
||||
}
|
||||
// add field denotation with parsed values
|
||||
FieldDenotation &fieldDenotation = fields[static_cast<unsigned int>(field)];
|
||||
fieldDenotation.present = true;
|
||||
fields.emplace_back(field);
|
||||
FieldDenotation &fieldDenotation = fields.back();
|
||||
fieldDenotation.type = type;
|
||||
fieldDenotation.tagType = currentTagType;
|
||||
fieldDenotation.tagTarget = currentTagTarget;
|
||||
|
@ -391,12 +396,11 @@ unsigned int parseFieldDenotations(const StringVector &fieldDenotations, bool re
|
|||
if(readOnly) {
|
||||
cout << "Warning: Specified value for \"" << fieldName << "\" will be ignored." << endl;
|
||||
} else {
|
||||
fieldDenotation.values.emplace_back(make_pair(mult == 1 ? fieldDenotation.values.size() : fileIndex, QString::fromLocal8Bit(fieldDenotationString.c_str() + equationPos + 1)));
|
||||
fieldDenotation.values.emplace_back(make_pair(mult == 1 ? fieldDenotation.values.size() : fileIndex, QString::fromLocal8Bit(fieldDenotationString.data() + equationPos + 1)));
|
||||
}
|
||||
}
|
||||
++validDenotations;
|
||||
}
|
||||
return validDenotations;
|
||||
return fields;
|
||||
}
|
||||
|
||||
enum class AttachmentAction {
|
||||
|
@ -699,8 +703,7 @@ void displayTagInfo(const StringVector ¶meterValues, const Argument &filesAr
|
|||
cout << "Error: No files have been specified." << endl;
|
||||
return;
|
||||
}
|
||||
FieldDenotation fields[knownFieldArraySize];
|
||||
unsigned int validDenotations = parseFieldDenotations(parameterValues, true, fields);
|
||||
const auto fields = parseFieldDenotations(parameterValues, true);
|
||||
MediaFileInfo fileInfo;
|
||||
for(const auto &file : filesArg.values()) {
|
||||
try {
|
||||
|
@ -722,24 +725,18 @@ void displayTagInfo(const StringVector ¶meterValues, const Argument &filesAr
|
|||
}
|
||||
cout << endl;
|
||||
// iterate through fields specified by the user
|
||||
KnownField field = firstKnownField;
|
||||
for(const FieldDenotation &fieldDenotation : fields) {
|
||||
const auto &value = tag->value(field);
|
||||
if((!validDenotations && !value.isEmpty())
|
||||
|| (fieldDenotation.present
|
||||
&& (fieldDenotation.tagType == TagType::Unspecified
|
||||
|| (fieldDenotation.tagType | tagType) != TagType::Unspecified))) {
|
||||
// write field name
|
||||
const char *fieldName = KnownFieldModel::fieldName(field);
|
||||
cout << ' ' << fieldName;
|
||||
// write padding
|
||||
for(auto i = strlen(fieldName); i < 18; ++i) {
|
||||
cout << ' ';
|
||||
}
|
||||
// write value
|
||||
if(value.isEmpty()) {
|
||||
cout << "none";
|
||||
} else {
|
||||
if(fields.empty()) {
|
||||
for(auto field = firstKnownField; field != KnownField::Invalid; field = nextKnownField(field)) {
|
||||
const auto &value = tag->value(field);
|
||||
if(!value.isEmpty()) {
|
||||
// write field name
|
||||
const char *fieldName = KnownFieldModel::fieldName(field);
|
||||
cout << ' ' << fieldName;
|
||||
// write padding
|
||||
for(auto i = strlen(fieldName); i < 18; ++i) {
|
||||
cout << ' ';
|
||||
}
|
||||
// write value
|
||||
try {
|
||||
const auto textValue = tagValueToQString(value);
|
||||
if(textValue.isEmpty()) {
|
||||
|
@ -750,10 +747,38 @@ void displayTagInfo(const StringVector ¶meterValues, const Argument &filesAr
|
|||
} catch(ConversionException &) {
|
||||
cout << "conversion error";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(const FieldDenotation &fieldDenotation : fields) {
|
||||
const auto &value = tag->value(fieldDenotation.field);
|
||||
if(fieldDenotation.tagType == TagType::Unspecified || (fieldDenotation.tagType | tagType) != TagType::Unspecified) {
|
||||
// write field name
|
||||
const char *fieldName = KnownFieldModel::fieldName(fieldDenotation.field);
|
||||
cout << ' ' << fieldName;
|
||||
// write padding
|
||||
for(auto i = strlen(fieldName); i < 18; ++i) {
|
||||
cout << ' ';
|
||||
}
|
||||
// write value
|
||||
if(value.isEmpty()) {
|
||||
cout << "none";
|
||||
} else {
|
||||
try {
|
||||
const auto textValue = tagValueToQString(value);
|
||||
if(textValue.isEmpty()) {
|
||||
cout << "can't display here (see --extract)";
|
||||
} else {
|
||||
cout << textValue.toLocal8Bit().data();
|
||||
}
|
||||
} catch(ConversionException &) {
|
||||
cout << "conversion error";
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
field = nextKnownField(field);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -772,19 +797,42 @@ void displayTagInfo(const StringVector ¶meterValues, const Argument &filesAr
|
|||
void setTagInfo(const StringVector ¶meterValues, const Argument &filesArg, const Argument &removeOtherFieldsArg,
|
||||
const Argument &treatUnknownFilesAsMp3FilesArg, const Argument &id3v1UsageArg, const Argument &id3v2UsageArg,
|
||||
const Argument &mergeMultipleSuccessiveTagsArg, const Argument &id3v2VersionArg, const Argument &encodingArg,
|
||||
const Argument &attachmentsArg, const Argument &verboseArg)
|
||||
const Argument &removeTargetsArg,
|
||||
const Argument &attachmentsArg, const Argument &removeExistingAttachmentsArg, const Argument &verboseArg)
|
||||
{
|
||||
CMD_UTILS_START_CONSOLE;
|
||||
if(!filesArg.valueCount()) {
|
||||
cout << "Error: No files have been specified." << endl;
|
||||
return;
|
||||
}
|
||||
FieldDenotation fields[knownFieldArraySize];
|
||||
unsigned int validDenotations = parseFieldDenotations(parameterValues, false, fields);
|
||||
if(!validDenotations && !attachmentsArg.valueCount()) {
|
||||
auto fields = parseFieldDenotations(parameterValues, false);
|
||||
if(fields.empty() && !attachmentsArg.valueCount()) {
|
||||
cout << "Error: No fields/attachments have been specified." << endl;
|
||||
return;
|
||||
}
|
||||
// determine required targets
|
||||
vector<TagTarget> requiredTargets;
|
||||
for(const FieldDenotation &fieldDenotation : fields) {
|
||||
if(find(requiredTargets.cbegin(), requiredTargets.cend(), fieldDenotation.tagTarget) == requiredTargets.cend()) {
|
||||
requiredTargets.push_back(fieldDenotation.tagTarget);
|
||||
}
|
||||
}
|
||||
// determine targets to remove
|
||||
vector<TagTarget> targetsToRemove;
|
||||
targetsToRemove.emplace_back();
|
||||
bool validRemoveTargetsSpecified = false;
|
||||
for(const auto &targetDenotation : removeTargetsArg.values()) {
|
||||
if(targetDenotation == ",") {
|
||||
if(validRemoveTargetsSpecified) {
|
||||
targetsToRemove.emplace_back();
|
||||
}
|
||||
} else if(applyTargetConfiguration(targetsToRemove.back(), targetDenotation)) {
|
||||
validRemoveTargetsSpecified = true;
|
||||
} else {
|
||||
cout << "Warning: The given target specification \"" << targetDenotation << "\" is invalid and will be ignored." << endl;
|
||||
}
|
||||
}
|
||||
// parse other settings
|
||||
uint32 id3v2Version = 3;
|
||||
if(id3v2VersionArg.isPresent()) {
|
||||
try {
|
||||
|
@ -800,6 +848,7 @@ void setTagInfo(const StringVector ¶meterValues, const Argument &filesArg, c
|
|||
TagTextEncoding denotedEncoding = parseEncodingDenotation(encodingArg, TagTextEncoding::Utf8);
|
||||
TagUsage id3v1Usage = parseUsageDenotation(id3v1UsageArg, TagUsage::KeepExisting);
|
||||
TagUsage id3v2Usage = parseUsageDenotation(id3v2UsageArg, TagUsage::Always);
|
||||
// iterate through all specified files
|
||||
unsigned int fileIndex = 0;
|
||||
static const string context("setting tags");
|
||||
MediaFileInfo fileInfo;
|
||||
|
@ -812,24 +861,34 @@ void setTagInfo(const StringVector ¶meterValues, const Argument &filesArg, c
|
|||
fileInfo.setPath(file);
|
||||
fileInfo.parseTags();
|
||||
fileInfo.parseTracks();
|
||||
fileInfo.createAppropriateTags(treatUnknownFilesAsMp3FilesArg.isPresent(), id3v1Usage, id3v2Usage, mergeMultipleSuccessiveTagsArg.isPresent(), !id3v2VersionArg.isPresent(), id3v2Version);
|
||||
vector<Tag *> tags;
|
||||
// remove tags with the specified targets
|
||||
if(validRemoveTargetsSpecified) {
|
||||
fileInfo.tags(tags);
|
||||
for(auto *tag : tags) {
|
||||
if(find(targetsToRemove.cbegin(), targetsToRemove.cend(), tag->target()) != targetsToRemove.cend()) {
|
||||
fileInfo.removeTag(tag);
|
||||
}
|
||||
}
|
||||
tags.clear();
|
||||
}
|
||||
// create new tags according to settings
|
||||
fileInfo.createAppropriateTags(treatUnknownFilesAsMp3FilesArg.isPresent(), id3v1Usage, id3v2Usage, mergeMultipleSuccessiveTagsArg.isPresent(), !id3v2VersionArg.isPresent(), id3v2Version, requiredTargets);
|
||||
auto container = fileInfo.container();
|
||||
auto tags = fileInfo.tags();
|
||||
fileInfo.tags(tags);
|
||||
if(!tags.empty()) {
|
||||
// iterate through all tags
|
||||
for(auto *tag : tags) {
|
||||
if(removeOtherFieldsArg.isPresent()) {
|
||||
tag->removeAllFields();
|
||||
}
|
||||
TagType tagType = tag->type();
|
||||
auto tagType = tag->type();
|
||||
bool targetSupported = tag->supportsTarget();
|
||||
TagTarget tagTarget = tag->target();
|
||||
KnownField field = firstKnownField;
|
||||
auto tagTarget = tag->target();
|
||||
for(FieldDenotation &fieldDenotation : fields) {
|
||||
if(fieldDenotation.present
|
||||
&& (fieldDenotation.tagType == TagType::Unspecified
|
||||
|| (fieldDenotation.tagType | tagType) != TagType::Unspecified)
|
||||
&& (!targetSupported || fieldDenotation.tagTarget.isEmpty() || fieldDenotation.tagTarget == tagTarget)) {
|
||||
if((fieldDenotation.tagType == TagType::Unspecified
|
||||
|| (fieldDenotation.tagType | tagType) != TagType::Unspecified)
|
||||
&& (!targetSupported || fieldDenotation.tagTarget == tagTarget)) {
|
||||
pair<unsigned int, QString> *selectedDenotatedValue = nullptr;
|
||||
for(auto &someDenotatedValue : fieldDenotation.values) {
|
||||
if(someDenotatedValue.first <= fileIndex) {
|
||||
|
@ -841,7 +900,7 @@ void setTagInfo(const StringVector ¶meterValues, const Argument &filesArg, c
|
|||
if(selectedDenotatedValue) {
|
||||
if(fieldDenotation.type == DenotationType::File) {
|
||||
if(selectedDenotatedValue->second.isEmpty()) {
|
||||
tag->setValue(field, TagValue());
|
||||
tag->setValue(fieldDenotation.field, TagValue());
|
||||
} else {
|
||||
try {
|
||||
MediaFileInfo fileInfo(selectedDenotatedValue->second.toLocal8Bit().constData());
|
||||
|
@ -852,7 +911,7 @@ void setTagInfo(const StringVector ¶meterValues, const Argument &filesArg, c
|
|||
fileInfo.stream().read(buff.get(), fileInfo.size());
|
||||
TagValue value(move(buff), fileInfo.size(), TagDataType::Picture);
|
||||
value.setMimeType(fileInfo.mimeType());
|
||||
tag->setValue(field, move(value));
|
||||
tag->setValue(fieldDenotation.field, move(value));
|
||||
} catch (ios_base::failure &) {
|
||||
fileInfo.addNotification(NotificationType::Critical, "An IO error occured when parsing the specified cover file.", context);
|
||||
} catch (Media::Failure &) {
|
||||
|
@ -864,25 +923,32 @@ void setTagInfo(const StringVector ¶meterValues, const Argument &filesArg, c
|
|||
if(!tag->canEncodingBeUsed(denotedEncoding)) {
|
||||
usedEncoding = tag->proposedTextEncoding();
|
||||
}
|
||||
tag->setValue(field, qstringToTagValue(selectedDenotatedValue->second, usedEncoding));
|
||||
tag->setValue(fieldDenotation.field, qstringToTagValue(selectedDenotatedValue->second, usedEncoding));
|
||||
if(fieldDenotation.type == DenotationType::Increment && tag == tags.back()) {
|
||||
selectedDenotatedValue->second = incremented(selectedDenotatedValue->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
field = nextKnownField(field);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fileInfo.addNotification(NotificationType::Critical, "Can not create appropriate tags for file.", context);
|
||||
}
|
||||
bool attachmentsModified = false;
|
||||
if(attachmentsArg.isPresent()) {
|
||||
if(attachmentsArg.isPresent() || removeExistingAttachmentsArg.isPresent()) {
|
||||
static const string context("setting attachments");
|
||||
fileInfo.parseAttachments();
|
||||
if(fileInfo.attachmentsParsingStatus() == ParsingStatus::Ok) {
|
||||
if(container) {
|
||||
// ignore all existing attachments if argument is specified
|
||||
if(removeExistingAttachmentsArg.isPresent()) {
|
||||
for(size_t i = 0, count = container->attachmentCount(); i < count; ++i) {
|
||||
container->attachment(i)->setIgnored(false);
|
||||
}
|
||||
attachmentsModified = true;
|
||||
}
|
||||
// add/update/remove attachments explicitely
|
||||
AttachmentInfo currentInfo;
|
||||
for(const auto &value : attachmentsArg.values()) {
|
||||
const auto *data = value.data();
|
||||
|
@ -949,9 +1015,8 @@ void setTagInfo(const StringVector ¶meterValues, const Argument &filesArg, c
|
|||
void extractField(const StringVector ¶meterValues, const Argument &inputFileArg, const Argument &outputFileArg, const Argument &verboseArg)
|
||||
{
|
||||
CMD_UTILS_START_CONSOLE;
|
||||
FieldDenotation fields[knownFieldArraySize];
|
||||
unsigned int validDenotations = parseFieldDenotations(parameterValues, true, fields);
|
||||
if(validDenotations != 1) {
|
||||
const auto fields = parseFieldDenotations(parameterValues, true);
|
||||
if(fields.size() != 1) {
|
||||
cout << "Error: Excactly one field needs to be specified." << endl;
|
||||
return;
|
||||
}
|
||||
|
@ -966,15 +1031,11 @@ void extractField(const StringVector ¶meterValues, const Argument &inputFile
|
|||
vector<pair<const TagValue *, string> > values;
|
||||
// iterate through all tags
|
||||
for(const Tag *tag : tags) {
|
||||
auto field = firstKnownField;
|
||||
for(const auto &fieldDenotation : fields) {
|
||||
if(fieldDenotation.present) {
|
||||
const auto &value = tag->value(field);
|
||||
if(!value.isEmpty()) {
|
||||
values.emplace_back(&value, joinStrings({tag->typeName(), numberToString(values.size())}, "-"));
|
||||
}
|
||||
const auto &value = tag->value(fieldDenotation.field);
|
||||
if(!value.isEmpty()) {
|
||||
values.emplace_back(&value, joinStrings({tag->typeName(), numberToString(values.size())}, "-"));
|
||||
}
|
||||
field = nextKnownField(field);
|
||||
}
|
||||
}
|
||||
if(values.empty()) {
|
||||
|
|
|
@ -18,7 +18,7 @@ void printFieldNames(const ApplicationUtilities::StringVector ¶meterValues);
|
|||
void displayFileInfo(const ApplicationUtilities::StringVector &, const ApplicationUtilities::Argument &filesArg, const ApplicationUtilities::Argument &verboseArg);
|
||||
void generateFileInfo(const ApplicationUtilities::StringVector ¶meterValues, const ApplicationUtilities::Argument &inputFileArg, const ApplicationUtilities::Argument &outputFileArg, const ApplicationUtilities::Argument &validateArg);
|
||||
void displayTagInfo(const ApplicationUtilities::StringVector ¶meterValues, const ApplicationUtilities::Argument &filesArg, const ApplicationUtilities::Argument &verboseArg);
|
||||
void setTagInfo(const ApplicationUtilities::StringVector ¶meterValues, const ApplicationUtilities::Argument &filesArg, const ApplicationUtilities::Argument &removeOtherFieldsArg, const ApplicationUtilities::Argument &treatUnknownFilesAsMp3FilesArg, const ApplicationUtilities::Argument &id3v1UsageArg, const ApplicationUtilities::Argument &id3v2UsageArg, const ApplicationUtilities::Argument &mergeMultipleSuccessiveTagsArg, const ApplicationUtilities::Argument &id3v2VersionArg, const ApplicationUtilities::Argument &encodingArg, const ApplicationUtilities::Argument &attachmentsArg, const ApplicationUtilities::Argument &verboseArg);
|
||||
void setTagInfo(const ApplicationUtilities::StringVector ¶meterValues, const ApplicationUtilities::Argument &filesArg, const ApplicationUtilities::Argument &removeOtherFieldsArg, const ApplicationUtilities::Argument &treatUnknownFilesAsMp3FilesArg, const ApplicationUtilities::Argument &id3v1UsageArg, const ApplicationUtilities::Argument &id3v2UsageArg, const ApplicationUtilities::Argument &mergeMultipleSuccessiveTagsArg, const ApplicationUtilities::Argument &id3v2VersionArg, const ApplicationUtilities::Argument &encodingArg, const ApplicationUtilities::Argument &removeTargetsArg, const ApplicationUtilities::Argument &attachmentsArg, const ApplicationUtilities::Argument &removeExistingAttachmentsArg, const ApplicationUtilities::Argument &verboseArg);
|
||||
void extractField(const ApplicationUtilities::StringVector ¶meterValues, const ApplicationUtilities::Argument &inputFileArg, const ApplicationUtilities::Argument &outputFileArg, const ApplicationUtilities::Argument &verboseArg);
|
||||
void removeBackupFiles(const ApplicationUtilities::StringVector ¶meterValues, const ApplicationUtilities::Argument &recursiveArg);
|
||||
|
||||
|
|
Loading…
Reference in New Issue