Pass through TXXX kv pairs from libtags, treated as vorbis comments
mp3 is no good i do not like them at all
This commit is contained in:
parent
b6b62cb8ea
commit
33e89a0672
3 changed files with 47 additions and 22 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue