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;
|
return 0;
|
||||||
}else if(strcmp(k-1, "COM") == 0 || strcmp(k-1, "COMM") == 0){
|
}else if(strcmp(k-1, "COM") == 0 || strcmp(k-1, "COMM") == 0){
|
||||||
txtcb(ctx, Tcomment, k-1, v);
|
txtcb(ctx, Tcomment, k-1, v);
|
||||||
|
}else if(strcmp(k, "XXX") == 0){
|
||||||
|
k = v;
|
||||||
|
v += strlen(v) + 1;
|
||||||
|
txtcb(ctx, Tunknown, k, v);
|
||||||
}else{
|
}else{
|
||||||
txtcb(ctx, Tunknown, k-1, v);
|
txtcb(ctx, Tunknown, k-1, v);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "database/track.hpp"
|
#include "database/track.hpp"
|
||||||
#include "debug.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 {
|
namespace libtags {
|
||||||
|
|
||||||
struct Aux {
|
struct Aux {
|
||||||
|
@ -96,7 +120,14 @@ static void tag(Tagctx* ctx,
|
||||||
int size,
|
int size,
|
||||||
Tagread f) {
|
Tagread f) {
|
||||||
Aux* aux = reinterpret_cast<Aux*>(ctx->aux);
|
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) {
|
if (!tag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -168,18 +199,7 @@ auto TagParserImpl::ReadAndParseTags(std::string_view path)
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
OggTagParser::OggTagParser() {
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto OggTagParser::ReadAndParseTags(std::string_view p)
|
auto OggTagParser::ReadAndParseTags(std::string_view p)
|
||||||
-> std::shared_ptr<TrackTags> {
|
-> std::shared_ptr<TrackTags> {
|
||||||
|
@ -295,8 +315,9 @@ auto OggTagParser::parseComments(TrackTags& res, std::span<unsigned char> data)
|
||||||
std::string key_upper{key};
|
std::string key_upper{key};
|
||||||
std::transform(key.begin(), key.end(), key_upper.begin(), ::toupper);
|
std::transform(key.begin(), key.end(), key_upper.begin(), ::toupper);
|
||||||
|
|
||||||
if (nameToTag_.contains(key_upper) && !val.empty()) {
|
auto tag = convert_vorbis_tag(key);
|
||||||
res.set(nameToTag_[key_upper], val);
|
if (tag && !val.empty()) {
|
||||||
|
res.set(*tag, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,14 +337,16 @@ auto GenericTagParser::ReadAndParseTags(std::string_view p)
|
||||||
std::string path{p};
|
std::string path{p};
|
||||||
libtags::Aux aux;
|
libtags::Aux aux;
|
||||||
|
|
||||||
// Fail fast if trying to parse a file that doesn't appear to be a supported audio format
|
// Fail fast if trying to parse a file that doesn't appear to be a supported
|
||||||
// For context, see: https://codeberg.org/cool-tech-zone/tangara-fw/issues/149
|
// audio format For context, see:
|
||||||
|
// https://codeberg.org/cool-tech-zone/tangara-fw/issues/149
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (const auto& ext : supported_exts) {
|
for (const auto& ext : supported_exts) {
|
||||||
// Case-insensitive file extension check
|
// Case-insensitive file extension check
|
||||||
if (std::equal(ext.rbegin(), ext.rend(), path.rbegin(),
|
if (std::equal(ext.rbegin(), ext.rend(), path.rbegin(), [](char a, char b) {
|
||||||
[](char a, char b) { return std::tolower(a) == std::tolower(b); })) {
|
return std::tolower(a) == std::tolower(b);
|
||||||
found=true;
|
})) {
|
||||||
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,6 @@ class OggTagParser : public ITagParser {
|
||||||
private:
|
private:
|
||||||
auto parseComments(TrackTags&, std::span<unsigned char> data) -> void;
|
auto parseComments(TrackTags&, std::span<unsigned char> data) -> void;
|
||||||
auto parseLength(std::span<unsigned char> data) -> uint64_t;
|
auto parseLength(std::span<unsigned char> data) -> uint64_t;
|
||||||
|
|
||||||
std::unordered_map<std::string, Tag> nameToTag_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GenericTagParser : public ITagParser {
|
class GenericTagParser : public ITagParser {
|
||||||
|
|
Loading…
Add table
Reference in a new issue