summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libtags/id3v2.c4
-rw-r--r--src/tangara/database/tag_parser.cpp63
-rw-r--r--src/tangara/database/tag_parser.hpp2
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 <iomanip>
#include <memory>
#include <mutex>
+#include <optional>
#include "database/track.hpp"
#include "debug.hpp"
@@ -47,6 +48,29 @@ static auto convert_tag(int tag) -> std::optional<Tag> {
}
}
+static std::unordered_map<std::string, Tag> 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<Tag> {
+ 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<Aux*>(ctx->aux);
- auto tag = convert_tag(t);
+ std::optional<Tag> 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<TrackTags> {
@@ -295,8 +315,9 @@ auto OggTagParser::parseComments(TrackTags& res, std::span<unsigned char> 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<unsigned char> data) -> void;
auto parseLength(std::span<unsigned char> data) -> uint64_t;
-
- std::unordered_map<std::string, Tag> nameToTag_;
};
class GenericTagParser : public ITagParser {