Support showing unsupported fields when displaying tag info

This commit is contained in:
Martchus 2018-05-13 00:27:42 +02:00
parent 3148873e09
commit 4edeaa1ab2
6 changed files with 86 additions and 35 deletions

View File

@ -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_GUI_OPTIONAL true)
set(META_JS_SRC_DIR renamingutility) set(META_JS_SRC_DIR renamingutility)
set(META_VERSION_MAJOR 3) set(META_VERSION_MAJOR 3)
set(META_VERSION_MINOR 0) set(META_VERSION_MINOR 1)
set(META_VERSION_PATCH 1) set(META_VERSION_PATCH 0)
# add project files # add project files
set(HEADER_FILES set(HEADER_FILES

View File

@ -164,8 +164,10 @@ int main(int argc, char *argv[])
fieldsArg.setImplicit(true); fieldsArg.setImplicit(true);
OperationArgument displayTagInfoArg("get", 'g', "displays the values of all specified tag fields (displays all fields if none specified)", 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"); 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))); ConfigValueArgument showUnsupportedArg("show-unsupported", 'u', "shows unsupported fields (has only effect when no field names specified)");
displayTagInfoArg.setSubArguments({ &fieldsArg, &filesArg, &verboseArg }); 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 // set tag info
Cli::SetTagInfoArgs setTagInfoArgs(filesArg, verboseArg); Cli::SetTagInfoArgs setTagInfoArgs(filesArg, verboseArg);
// extract cover // extract cover

View File

@ -213,11 +213,27 @@ void printFieldName(const char *fieldName, size_t fieldNameLen)
{ {
cout << " " << fieldName; cout << " " << fieldName;
// also write padding // also write padding
if (fieldNameLen >= 18) {
// write at least one space
cout << ' ';
return;
}
for (auto i = fieldNameLen; i < 18; ++i) { for (auto i = fieldNameLen; i < 18; ++i) {
cout << ' '; 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) void printField(const FieldScope &scope, const Tag *tag, TagType tagType, bool skipEmpty)
{ {
// write field name // write field name
@ -243,13 +259,7 @@ void printField(const FieldScope &scope, const Tag *tag, TagType tagType, bool s
// print values // print values
for (const auto &value : values) { for (const auto &value : values) {
printFieldName(fieldName, fieldNameLen); printFieldName(fieldName, fieldNameLen);
try { printTagValue(*value);
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';
} }
} catch (const ConversionException &e) { } 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) TimeSpanOutputFormat parseTimeSpanOutputFormat(const Argument &timeSpanFormatArg, TimeSpanOutputFormat defaultFormat)
{ {
if (timeSpanFormatArg.isPresent()) { if (timeSpanFormatArg.isPresent()) {

View File

@ -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( inline void printProperty(
const char *propName, const NumberType value, const char *suffix = nullptr, bool force = false, ApplicationUtilities::Indentation indentation = 4) 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 printField(const FieldScope &scope, const Tag *tag, TagType tagType, bool skipEmpty);
void printNativeFields(const Tag *tag);
ChronoUtilities::TimeSpanOutputFormat parseTimeSpanOutputFormat( ChronoUtilities::TimeSpanOutputFormat parseTimeSpanOutputFormat(
const ApplicationUtilities::Argument &usageArg, ChronoUtilities::TimeSpanOutputFormat defaultFormat); const ApplicationUtilities::Argument &usageArg, ChronoUtilities::TimeSpanOutputFormat defaultFormat);

View File

@ -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; CMD_UTILS_START_CONSOLE;
@ -325,29 +325,32 @@ void displayTagInfo(const Argument &fieldsArg, const Argument &filesArg, const A
fileInfo.parseTags(diag); fileInfo.parseTags(diag);
cout << "Tag information for \"" << file << "\":\n"; cout << "Tag information for \"" << file << "\":\n";
const auto tags = fileInfo.tags(); const auto tags = fileInfo.tags();
if (!tags.empty()) { if (tags.empty()) {
// iterate through all tags cout << " - File has no (supported) tag information.\n";
for (const auto *tag : tags) { continue;
// determine tag type }
const TagType tagType = tag->type(); // iterate through all tags
// write tag name and target, eg. MP4/iTunes tag for (const auto *tag : tags) {
cout << " - " << TextAttribute::Bold << tagName(tag) << TextAttribute::Reset << '\n'; // determine tag type
// iterate through fields specified by the user const TagType tagType = tag->type();
if (fields.empty()) { // write tag name and target, eg. MP4/iTunes tag
for (auto field = firstKnownField; field != KnownField::Invalid; field = nextKnownField(field)) { cout << " - " << TextAttribute::Bold << tagName(tag) << TextAttribute::Reset << '\n';
printField(FieldScope(field), tag, tagType, true); // iterate through fields specified by the user
} if (fields.empty()) {
} else { for (auto field = firstKnownField; field != KnownField::Invalid; field = nextKnownField(field)) {
for (const auto &fieldDenotation : fields) { printField(FieldScope(field), tag, tagType, true);
const FieldScope &denotedScope = fieldDenotation.first; }
if (denotedScope.tagType == TagType::Unspecified || (denotedScope.tagType | tagType) != TagType::Unspecified) { if (showUnsupportedArg.isPresent()) {
printField(denotedScope, tag, tagType, false); 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 &) { } catch (const TagParser::Failure &) {
cerr << Phrases::Error << "A parsing failure occured when reading the file \"" << file << "\"." << Phrases::EndFlush; cerr << Phrases::Error << "A parsing failure occured when reading the file \"" << file << "\"." << Phrases::EndFlush;

View File

@ -53,8 +53,8 @@ void displayFileInfo(const ApplicationUtilities::ArgumentOccurrence &, const App
const ApplicationUtilities::Argument &verboseArg); const ApplicationUtilities::Argument &verboseArg);
void generateFileInfo(const ApplicationUtilities::ArgumentOccurrence &, const ApplicationUtilities::Argument &inputFileArg, void generateFileInfo(const ApplicationUtilities::ArgumentOccurrence &, const ApplicationUtilities::Argument &inputFileArg,
const ApplicationUtilities::Argument &outputFileArg, const ApplicationUtilities::Argument &validateArg); const ApplicationUtilities::Argument &outputFileArg, const ApplicationUtilities::Argument &validateArg);
void displayTagInfo(const ApplicationUtilities::Argument &fieldsArg, const ApplicationUtilities::Argument &filesArg, void displayTagInfo(const ApplicationUtilities::Argument &fieldsArg, const ApplicationUtilities::Argument &showUnsupportedArg,
const ApplicationUtilities::Argument &verboseArg); const ApplicationUtilities::Argument &filesArg, const ApplicationUtilities::Argument &verboseArg);
void setTagInfo(const Cli::SetTagInfoArgs &args); void setTagInfo(const Cli::SetTagInfoArgs &args);
void extractField(const ApplicationUtilities::Argument &fieldArg, const ApplicationUtilities::Argument &attachmentArg, void extractField(const ApplicationUtilities::Argument &fieldArg, const ApplicationUtilities::Argument &attachmentArg,
const ApplicationUtilities::Argument &inputFilesArg, const ApplicationUtilities::Argument &outputFileArg, const ApplicationUtilities::Argument &inputFilesArg, const ApplicationUtilities::Argument &outputFileArg,