From 33e89a0672079bf30151a9353cb0fbf165afaae5 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Tue, 31 Dec 2024 11:32:51 +1100 Subject: [PATCH] Pass through TXXX kv pairs from libtags, treated as vorbis comments mp3 is no good i do not like them at all --- lib/libtags/id3v2.c | 4 ++ src/tangara/database/tag_parser.cpp | 63 ++++++++++++++++++++--------- src/tangara/database/tag_parser.hpp | 2 - 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/lib/libtags/id3v2.c b/lib/libtags/id3v2.c index 78a0a5fe..69c76aaa 100644 --- a/lib/libtags/id3v2.c +++ b/lib/libtags/id3v2.c @@ -68,6 +68,10 @@ v2cb(Tagctx *ctx, char *k, char *v) return 0; }else if(strcmp(k-1, "COM") == 0 || strcmp(k-1, "COMM") == 0){ txtcb(ctx, Tcomment, k-1, v); + }else if(strcmp(k, "XXX") == 0){ + k = v; + v += strlen(v) + 1; + txtcb(ctx, Tunknown, k, v); }else{ txtcb(ctx, Tunknown, k-1, v); } diff --git a/src/tangara/database/tag_parser.cpp b/src/tangara/database/tag_parser.cpp index 1756fa0a..6cdf6175 100644 --- a/src/tangara/database/tag_parser.cpp +++ b/src/tangara/database/tag_parser.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "database/track.hpp" #include "debug.hpp" @@ -47,6 +48,29 @@ static auto convert_tag(int tag) -> std::optional { } } +static std::unordered_map sVorbisNameToTag{ + {"TITLE", Tag::kTitle}, + {"ALBUM", Tag::kAlbum}, + {"ARTIST", Tag::kArtist}, + {"ARTISTS", Tag::kAllArtists}, + {"ALBUMARTIST", Tag::kAlbumArtist}, + {"TRACK", Tag::kTrack}, + {"TRACKNUMBER", Tag::kTrack}, + {"GENRE", Tag::kGenres}, + {"DISC", Tag::kDisc}, + {"DISCNUMBER", Tag::kDisc}, +}; + +static auto convert_vorbis_tag(const std::string_view name) + -> std::optional { + std::string name_upper{name}; + std::transform(name.begin(), name.end(), name_upper.begin(), ::toupper); + if (sVorbisNameToTag.contains(name_upper)) { + return sVorbisNameToTag[name_upper]; + } + return {}; +} + namespace libtags { struct Aux { @@ -96,7 +120,14 @@ static void tag(Tagctx* ctx, int size, Tagread f) { Aux* aux = reinterpret_cast(ctx->aux); - auto tag = convert_tag(t); + std::optional tag; + if (t == Tunknown && k && v) { + // Sometimes 'unknown' tags are vorbis comments shoved into a generic tag + // name in other containers. + tag = convert_vorbis_tag(k); + } else { + tag = convert_tag(t); + } if (!tag) { return; } @@ -168,18 +199,7 @@ auto TagParserImpl::ReadAndParseTags(std::string_view path) return tags; } -OggTagParser::OggTagParser() { - nameToTag_["TITLE"] = Tag::kTitle; - nameToTag_["ALBUM"] = Tag::kAlbum; - nameToTag_["ARTIST"] = Tag::kArtist; - nameToTag_["ARTISTS"] = Tag::kAllArtists; - nameToTag_["ALBUMARTIST"] = Tag::kAlbumArtist; - nameToTag_["TRACK"] = Tag::kTrack; - nameToTag_["TRACKNUMBER"] = Tag::kTrack; - nameToTag_["GENRE"] = Tag::kGenres; - nameToTag_["DISC"] = Tag::kDisc; - nameToTag_["DISCNUMBER"] = Tag::kDisc; -} +OggTagParser::OggTagParser() {} auto OggTagParser::ReadAndParseTags(std::string_view p) -> std::shared_ptr { @@ -295,8 +315,9 @@ auto OggTagParser::parseComments(TrackTags& res, std::span data) std::string key_upper{key}; std::transform(key.begin(), key.end(), key_upper.begin(), ::toupper); - if (nameToTag_.contains(key_upper) && !val.empty()) { - res.set(nameToTag_[key_upper], val); + auto tag = convert_vorbis_tag(key); + if (tag && !val.empty()) { + res.set(*tag, val); } } @@ -316,14 +337,16 @@ auto GenericTagParser::ReadAndParseTags(std::string_view p) std::string path{p}; libtags::Aux aux; - // Fail fast if trying to parse a file that doesn't appear to be a supported audio format - // For context, see: https://codeberg.org/cool-tech-zone/tangara-fw/issues/149 + // Fail fast if trying to parse a file that doesn't appear to be a supported + // audio format For context, see: + // https://codeberg.org/cool-tech-zone/tangara-fw/issues/149 bool found = false; for (const auto& ext : supported_exts) { // Case-insensitive file extension check - if (std::equal(ext.rbegin(), ext.rend(), path.rbegin(), - [](char a, char b) { return std::tolower(a) == std::tolower(b); })) { - found=true; + if (std::equal(ext.rbegin(), ext.rend(), path.rbegin(), [](char a, char b) { + return std::tolower(a) == std::tolower(b); + })) { + found = true; break; } } diff --git a/src/tangara/database/tag_parser.hpp b/src/tangara/database/tag_parser.hpp index 9130b306..69b71940 100644 --- a/src/tangara/database/tag_parser.hpp +++ b/src/tangara/database/tag_parser.hpp @@ -47,8 +47,6 @@ class OggTagParser : public ITagParser { private: auto parseComments(TrackTags&, std::span data) -> void; auto parseLength(std::span data) -> uint64_t; - - std::unordered_map nameToTag_; }; class GenericTagParser : public ITagParser {