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_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

View File

@ -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

View File

@ -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()) {

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(
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);

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;
@ -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;

View File

@ -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,