Support showing unsupported fields when displaying tag info
This commit is contained in:
parent
3148873e09
commit
4edeaa1ab2
|
@ -11,8 +11,8 @@ set(META_APP_DESCRIPTION "A tageditor with Qt GUI and command line interface. Su
|
|||
set(META_GUI_OPTIONAL true)
|
||||
set(META_JS_SRC_DIR renamingutility)
|
||||
set(META_VERSION_MAJOR 3)
|
||||
set(META_VERSION_MINOR 0)
|
||||
set(META_VERSION_PATCH 1)
|
||||
set(META_VERSION_MINOR 1)
|
||||
set(META_VERSION_PATCH 0)
|
||||
|
||||
# add project files
|
||||
set(HEADER_FILES
|
||||
|
|
|
@ -164,8 +164,10 @@ int main(int argc, char *argv[])
|
|||
fieldsArg.setImplicit(true);
|
||||
OperationArgument displayTagInfoArg("get", 'g', "displays the values of all specified tag fields (displays all fields if none specified)",
|
||||
PROJECT_NAME " get title album artist -f /some/dir/*.m4a");
|
||||
displayTagInfoArg.setCallback(std::bind(Cli::displayTagInfo, std::cref(fieldsArg), std::cref(filesArg), std::cref(verboseArg)));
|
||||
displayTagInfoArg.setSubArguments({ &fieldsArg, &filesArg, &verboseArg });
|
||||
ConfigValueArgument showUnsupportedArg("show-unsupported", 'u', "shows unsupported fields (has only effect when no field names specified)");
|
||||
displayTagInfoArg.setCallback(
|
||||
std::bind(Cli::displayTagInfo, std::cref(fieldsArg), std::cref(showUnsupportedArg), std::cref(filesArg), std::cref(verboseArg)));
|
||||
displayTagInfoArg.setSubArguments({ &fieldsArg, &showUnsupportedArg, &filesArg, &verboseArg });
|
||||
// set tag info
|
||||
Cli::SetTagInfoArgs setTagInfoArgs(filesArg, verboseArg);
|
||||
// extract cover
|
||||
|
|
|
@ -213,11 +213,27 @@ void printFieldName(const char *fieldName, size_t fieldNameLen)
|
|||
{
|
||||
cout << " " << fieldName;
|
||||
// also write padding
|
||||
if (fieldNameLen >= 18) {
|
||||
// write at least one space
|
||||
cout << ' ';
|
||||
return;
|
||||
}
|
||||
for (auto i = fieldNameLen; i < 18; ++i) {
|
||||
cout << ' ';
|
||||
}
|
||||
}
|
||||
|
||||
void printTagValue(const TagValue &value)
|
||||
{
|
||||
try {
|
||||
cout << value.toString(TagTextEncoding::Utf8);
|
||||
} catch (const ConversionException &) {
|
||||
// handle case when value can not be displayed as string
|
||||
cout << "can't display as string (see --extract)";
|
||||
}
|
||||
cout << '\n';
|
||||
}
|
||||
|
||||
void printField(const FieldScope &scope, const Tag *tag, TagType tagType, bool skipEmpty)
|
||||
{
|
||||
// write field name
|
||||
|
@ -243,13 +259,7 @@ void printField(const FieldScope &scope, const Tag *tag, TagType tagType, bool s
|
|||
// print values
|
||||
for (const auto &value : values) {
|
||||
printFieldName(fieldName, fieldNameLen);
|
||||
try {
|
||||
cout << value->toString(TagTextEncoding::Utf8);
|
||||
} catch (const ConversionException &) {
|
||||
// handle case when value can not be displayed as string
|
||||
cout << "can't display as string (see --extract)";
|
||||
}
|
||||
cout << '\n';
|
||||
printTagValue(*value);
|
||||
}
|
||||
|
||||
} catch (const ConversionException &e) {
|
||||
|
@ -259,6 +269,41 @@ void printField(const FieldScope &scope, const Tag *tag, TagType tagType, bool s
|
|||
}
|
||||
}
|
||||
|
||||
template <typename ConcreteTag> void printNativeFields(const Tag *tag)
|
||||
{
|
||||
const auto *const concreteTag = static_cast<const ConcreteTag *>(tag);
|
||||
for (const auto &field : concreteTag->fields()) {
|
||||
// skip all fields which are supported anyways
|
||||
if (concreteTag->knownField(field.first) != KnownField::Invalid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto fieldId(ConcreteTag::FieldType::fieldIdToString(field.first));
|
||||
printFieldName(fieldId.data(), fieldId.size());
|
||||
printTagValue(field.second.value());
|
||||
}
|
||||
}
|
||||
|
||||
void printNativeFields(const Tag *tag)
|
||||
{
|
||||
switch (tag->type()) {
|
||||
case TagType::Id3v2Tag:
|
||||
printNativeFields<Id3v2Tag>(tag);
|
||||
break;
|
||||
case TagType::Mp4Tag:
|
||||
printNativeFields<Mp4Tag>(tag);
|
||||
break;
|
||||
case TagType::MatroskaTag:
|
||||
printNativeFields<MatroskaTag>(tag);
|
||||
break;
|
||||
case TagType::VorbisComment:
|
||||
case TagType::OggVorbisComment:
|
||||
printNativeFields<VorbisComment>(tag);
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
TimeSpanOutputFormat parseTimeSpanOutputFormat(const Argument &timeSpanFormatArg, TimeSpanOutputFormat defaultFormat)
|
||||
{
|
||||
if (timeSpanFormatArg.isPresent()) {
|
||||
|
|
|
@ -279,7 +279,7 @@ inline void printProperty(
|
|||
}
|
||||
}
|
||||
|
||||
template <typename NumberType, Traits::EnableIfAny<std::is_integral<NumberType>, std::is_floating_point<NumberType>>* = nullptr>
|
||||
template <typename NumberType, Traits::EnableIfAny<std::is_integral<NumberType>, std::is_floating_point<NumberType>> * = nullptr>
|
||||
inline void printProperty(
|
||||
const char *propName, const NumberType value, const char *suffix = nullptr, bool force = false, ApplicationUtilities::Indentation indentation = 4)
|
||||
{
|
||||
|
@ -289,6 +289,7 @@ inline void printProperty(
|
|||
}
|
||||
|
||||
void printField(const FieldScope &scope, const Tag *tag, TagType tagType, bool skipEmpty);
|
||||
void printNativeFields(const Tag *tag);
|
||||
|
||||
ChronoUtilities::TimeSpanOutputFormat parseTimeSpanOutputFormat(
|
||||
const ApplicationUtilities::Argument &usageArg, ChronoUtilities::TimeSpanOutputFormat defaultFormat);
|
||||
|
|
|
@ -301,7 +301,7 @@ void displayFileInfo(const ArgumentOccurrence &, const Argument &filesArg, const
|
|||
}
|
||||
}
|
||||
|
||||
void displayTagInfo(const Argument &fieldsArg, const Argument &filesArg, const Argument &verboseArg)
|
||||
void displayTagInfo(const Argument &fieldsArg, const Argument &showUnsupportedArg, const Argument &filesArg, const Argument &verboseArg)
|
||||
{
|
||||
CMD_UTILS_START_CONSOLE;
|
||||
|
||||
|
@ -325,29 +325,32 @@ void displayTagInfo(const Argument &fieldsArg, const Argument &filesArg, const A
|
|||
fileInfo.parseTags(diag);
|
||||
cout << "Tag information for \"" << file << "\":\n";
|
||||
const auto tags = fileInfo.tags();
|
||||
if (!tags.empty()) {
|
||||
// iterate through all tags
|
||||
for (const auto *tag : tags) {
|
||||
// determine tag type
|
||||
const TagType tagType = tag->type();
|
||||
// write tag name and target, eg. MP4/iTunes tag
|
||||
cout << " - " << TextAttribute::Bold << tagName(tag) << TextAttribute::Reset << '\n';
|
||||
// iterate through fields specified by the user
|
||||
if (fields.empty()) {
|
||||
for (auto field = firstKnownField; field != KnownField::Invalid; field = nextKnownField(field)) {
|
||||
printField(FieldScope(field), tag, tagType, true);
|
||||
}
|
||||
} else {
|
||||
for (const auto &fieldDenotation : fields) {
|
||||
const FieldScope &denotedScope = fieldDenotation.first;
|
||||
if (denotedScope.tagType == TagType::Unspecified || (denotedScope.tagType | tagType) != TagType::Unspecified) {
|
||||
printField(denotedScope, tag, tagType, false);
|
||||
}
|
||||
if (tags.empty()) {
|
||||
cout << " - File has no (supported) tag information.\n";
|
||||
continue;
|
||||
}
|
||||
// iterate through all tags
|
||||
for (const auto *tag : tags) {
|
||||
// determine tag type
|
||||
const TagType tagType = tag->type();
|
||||
// write tag name and target, eg. MP4/iTunes tag
|
||||
cout << " - " << TextAttribute::Bold << tagName(tag) << TextAttribute::Reset << '\n';
|
||||
// iterate through fields specified by the user
|
||||
if (fields.empty()) {
|
||||
for (auto field = firstKnownField; field != KnownField::Invalid; field = nextKnownField(field)) {
|
||||
printField(FieldScope(field), tag, tagType, true);
|
||||
}
|
||||
if (showUnsupportedArg.isPresent()) {
|
||||
printNativeFields(tag);
|
||||
}
|
||||
} else {
|
||||
for (const auto &fieldDenotation : fields) {
|
||||
const FieldScope &denotedScope = fieldDenotation.first;
|
||||
if (denotedScope.tagType == TagType::Unspecified || (denotedScope.tagType | tagType) != TagType::Unspecified) {
|
||||
printField(denotedScope, tag, tagType, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cout << " - File has no (supported) tag information.\n";
|
||||
}
|
||||
} catch (const TagParser::Failure &) {
|
||||
cerr << Phrases::Error << "A parsing failure occured when reading the file \"" << file << "\"." << Phrases::EndFlush;
|
||||
|
|
|
@ -53,8 +53,8 @@ void displayFileInfo(const ApplicationUtilities::ArgumentOccurrence &, const App
|
|||
const ApplicationUtilities::Argument &verboseArg);
|
||||
void generateFileInfo(const ApplicationUtilities::ArgumentOccurrence &, const ApplicationUtilities::Argument &inputFileArg,
|
||||
const ApplicationUtilities::Argument &outputFileArg, const ApplicationUtilities::Argument &validateArg);
|
||||
void displayTagInfo(const ApplicationUtilities::Argument &fieldsArg, const ApplicationUtilities::Argument &filesArg,
|
||||
const ApplicationUtilities::Argument &verboseArg);
|
||||
void displayTagInfo(const ApplicationUtilities::Argument &fieldsArg, const ApplicationUtilities::Argument &showUnsupportedArg,
|
||||
const ApplicationUtilities::Argument &filesArg, const ApplicationUtilities::Argument &verboseArg);
|
||||
void setTagInfo(const Cli::SetTagInfoArgs &args);
|
||||
void extractField(const ApplicationUtilities::Argument &fieldArg, const ApplicationUtilities::Argument &attachmentArg,
|
||||
const ApplicationUtilities::Argument &inputFilesArg, const ApplicationUtilities::Argument &outputFileArg,
|
||||
|
|
Loading…
Reference in New Issue