From e9f533bb6be978077dc5baa9bb09626209f094d0 Mon Sep 17 00:00:00 2001 From: emeric Date: Sun, 6 Oct 2024 11:37:56 +0200 Subject: [PATCH] lms-metadata: added an option to specify the parser to use --- README.md | 6 +-- src/tools/metadata/LmsMetadata.cpp | 81 +++++++++++++++++++++--------- 2 files changed, 61 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index b82baa57..00820499 100644 --- a/README.md +++ b/README.md @@ -43,15 +43,15 @@ _LMS_ primarily relies on tags to organize your music collection but also suppor ### Filtering It is possible to apply global filters on your collection using `genre`, `mood`, `grouping`, `language`, and by music library. More tags, including custom ones, can be added in the database administration settings. -__Note__: You can use the `lms-metadata` tool to get an idea of the tags parsed by _LMS_ using [TagLib](https://github.com/taglib/taglib). +__Note__: You can use the `lms-metadata` tool to get an idea of the tags parsed by _LMS_. ### Multiple artists -_LMS_ works best when using the default Picard settings, where the `artist` tag contains a single display-friendly value, and the `artists` tag holds the actual artist names. This ensures a cleaner, more organized representation of artist names, when multiple artists are involved. +_LMS_ works best when using the default [Picard](https://picard.musicbrainz.org/) settings, where the `artist` tag contains a single display-friendly value, and the `artists` tag holds the actual artist names. This ensures a cleaner, more organized representation of artist names, when multiple artists are involved. ### Multiple album artists While LMS can manage multiple album artists using the `albumartist` tag, it works better when using the custom `albumartists` and `albumartistssort` tags, similar to how it handles regular artist tags. -__Note__: if you use [Picard](https://picard.musicbrainz.org/), add the following script to include these tags: +__Note__: if you use Picard, add the following script to include these tags: ``` $setmulti(albumartists,%_albumartists%) $setmulti(albumartistssort,%_albumartists_sort%) diff --git a/src/tools/metadata/LmsMetadata.cpp b/src/tools/metadata/LmsMetadata.cpp index a9621c00..0af49eb3 100644 --- a/src/tools/metadata/LmsMetadata.cpp +++ b/src/tools/metadata/LmsMetadata.cpp @@ -27,7 +27,9 @@ #include #include +#include "core/EnumSet.hpp" #include "core/StreamLogger.hpp" +#include "core/String.hpp" #include "metadata/Exception.hpp" #include "metadata/IParser.hpp" @@ -241,7 +243,8 @@ int main(int argc, char* argv[]) options.add_options() ("help,h", "Display this help message") ("tag-delimiter", program_options::value>()->default_value(std::vector{}, "[]"), "Tag delimiters (multiple allowed)") - ("artist-tag-delimiter", program_options::value>()->default_value(std::vector{}, "[]"), "Artist tag delimiters (multiple allowed)"); + ("artist-tag-delimiter", program_options::value>()->default_value(std::vector{}, "[]"), "Artist tag delimiters (multiple allowed)") + ("parser", program_options::value>()->default_value(std::vector{ "taglib" }, "[taglib]"), "Parser to be used (value can be \"taglib\" or \"ffmpeg\")"); // clang-format on program_options::options_description hiddenOptions{ "Hidden options" }; @@ -274,13 +277,39 @@ int main(int argc, char* argv[]) return EXIT_SUCCESS; } - if (!vm.count("file")) + if (vm.count("file") == 0) { - std::cout << "NO INPUT FILE!" << std::endl; + std::cerr << "No input file provided" << std::endl; displayHelp(std::cerr); return EXIT_FAILURE; } + enum class Parser + { + Taglib, + Ffmpeg, + }; + + if (vm.count("parser") == 0) + { + std::cerr << "You must specify at least one parser" << std::endl; + return EXIT_FAILURE; + } + + core::EnumSet parsers; + for (const std::string& strParser : vm["parser"].as>()) + { + if (core::stringUtils::stringCaseInsensitiveEqual(strParser, "taglib")) + parsers.insert(Parser::Taglib); + else if (core::stringUtils::stringCaseInsensitiveEqual(strParser, "ffmpeg")) + parsers.insert(Parser::Ffmpeg); + else + { + std::cerr << "Invalid parser name '" << strParser << "'" << std::endl; + return EXIT_FAILURE; + } + } + const auto& inputFiles{ vm["file"].as>() }; const auto& tagDelimiters{ vm["tag-delimiter"].as>() }; const auto& artistTagDelimiters{ vm["artist-tag-delimiter"].as>() }; @@ -304,34 +333,40 @@ int main(int argc, char* argv[]) std::cout << "Parsing file '" << file << "'" << std::endl; - try + if (parsers.contains(Parser::Ffmpeg)) { - std::cout << "Using av:" << std::endl; + try + { + std::cout << "Using Ffmpeg:" << std::endl; - auto parser{ metadata::createParser(metadata::ParserBackend::AvFormat, metadata::ParserReadStyle::Accurate) }; - parser->setArtistTagDelimiters(artistTagDelimiters); - parser->setDefaultTagDelimiters(tagDelimiters); + auto parser{ metadata::createParser(metadata::ParserBackend::AvFormat, metadata::ParserReadStyle::Accurate) }; + parser->setArtistTagDelimiters(artistTagDelimiters); + parser->setDefaultTagDelimiters(tagDelimiters); - parse(*parser, file); - } - catch (metadata::Exception& e) - { - std::cerr << "Parsing failed: " << e.what() << std::endl; + parse(*parser, file); + } + catch (metadata::Exception& e) + { + std::cerr << "Parsing failed: " << e.what() << std::endl; + } } - try + if (parsers.contains(Parser::Taglib)) { - std::cout << "Using TagLib:" << std::endl; + try + { + std::cout << "Using TagLib:" << std::endl; - auto parser{ metadata::createParser(metadata::ParserBackend::TagLib, metadata::ParserReadStyle::Accurate) }; - parser->setArtistTagDelimiters(artistTagDelimiters); - parser->setDefaultTagDelimiters(tagDelimiters); + auto parser{ metadata::createParser(metadata::ParserBackend::TagLib, metadata::ParserReadStyle::Accurate) }; + parser->setArtistTagDelimiters(artistTagDelimiters); + parser->setDefaultTagDelimiters(tagDelimiters); - parse(*parser, file); - } - catch (metadata::Exception& e) - { - std::cerr << "Parsing failed: " << e.what() << std::endl; + parse(*parser, file); + } + catch (metadata::Exception& e) + { + std::cerr << "Parsing failed: " << e.what() << std::endl; + } } } }