Fix missing track number issues

custom
jacqueline 2 years ago
parent dad14baa73
commit 63215ccf16
  1. 6
      src/database/index.cpp
  2. 9
      src/database/records.cpp
  3. 57
      src/database/tag_parser.cpp
  4. 1
      src/database/track.cpp

@ -5,10 +5,13 @@
*/ */
#include "index.hpp" #include "index.hpp"
#include <stdint.h>
#include <cstdint>
#include <variant> #include <variant>
#include "komihash.h" #include "komihash.h"
#include "leveldb/write_batch.h" #include "leveldb/write_batch.h"
#include "records.hpp" #include "records.hpp"
namespace database { namespace database {
@ -49,6 +52,7 @@ static auto missing_component_text(const Track& track, Tag tag)
case Tag::kTitle: case Tag::kTitle:
return track.TitleOrFilename(); return track.TitleOrFilename();
case Tag::kAlbumTrack: case Tag::kAlbumTrack:
return "0000";
case Tag::kDuration: case Tag::kDuration:
default: default:
return {}; return {};

@ -309,7 +309,8 @@ auto EncodeIndexKey(const IndexKey& key) -> OwningSlice {
// Construct the footer. // Construct the footer.
out << kFieldSeparator; out << kFieldSeparator;
if (key.track) { if (key.track) {
out << TrackIdToBytes(*key.track).data; auto encoded = TrackIdToBytes(*key.track);
out << encoded.data;
} }
return OwningSlice(out.str()); return OwningSlice(out.str());
} }
@ -394,9 +395,9 @@ auto ParseIndexKey(const leveldb::Slice& slice) -> std::optional<IndexKey> {
buffer = {}; buffer = {};
in.get(buffer); in.get(buffer);
if (buffer.str().size() > 1) { std::string id_str = buffer.str();
std::string raw_id = buffer.str().substr(1); if (id_str.size() > 1) {
result.track = BytesToTrackId(raw_id); result.track = BytesToTrackId(id_str.substr(1));
} }
return result; return result;

@ -17,7 +17,26 @@
namespace database { namespace database {
auto convert_tag(int tag) -> std::optional<Tag> { const static std::array<std::pair<const char*, Tag>, 5> kVorbisIdToTag = {{
{"TITLE", Tag::kTitle},
{"ARTIST", Tag::kArtist},
{"ALBUM", Tag::kAlbum},
{"TRACKNUMBER", Tag::kAlbumTrack},
{"GENRE", Tag::kGenre},
}};
static auto convert_track_number(int number) -> std::string {
std::ostringstream oss;
oss << std::setw(4) << std::setfill('0') << number;
return oss.str();
}
static auto convert_track_number(const std::string& raw) -> std::string {
uint32_t as_int = std::atoi(raw.c_str());
return convert_track_number(as_int);
}
static auto convert_tag(int tag) -> std::optional<Tag> {
switch (tag) { switch (tag) {
case Ttitle: case Ttitle:
return Tag::kTitle; return Tag::kTitle;
@ -92,10 +111,6 @@ static void tag(Tagctx* ctx,
return; return;
} }
if (*tag == Tag::kAlbumTrack) { if (*tag == Tag::kAlbumTrack) {
uint32_t as_int = std::atoi(v);
std::ostringstream oss;
oss << std::setw(4) << std::setfill('0') << as_int;
value = oss.str();
} }
aux->tags->set(*tag, value); aux->tags->set(*tag, value);
} }
@ -137,6 +152,21 @@ auto TagParserImpl::ReadAndParseTags(const std::string& path, TrackTags* out)
return false; return false;
} }
// There wasn't a track number found in the track's tags. Try to synthesize
// one from the filename, which will sometimes have a track number at the
// start.
if (!out->at(Tag::kAlbumTrack)) {
auto slash_pos = path.find_last_of("/");
if (slash_pos != std::string::npos && path.size() - slash_pos > 1) {
out->set(Tag::kAlbumTrack, path.substr(slash_pos + 1));
}
}
// Normalise track numbers; they're usually treated as strings, but we would
// like to sort them lexicographically.
out->set(Tag::kAlbumTrack,
convert_track_number(out->at(Tag::kAlbumTrack).value_or("0")));
{ {
std::lock_guard<std::mutex> lock{cache_mutex_}; std::lock_guard<std::mutex> lock{cache_mutex_};
cache_.Put(path, *out); cache_.Put(path, *out);
@ -226,18 +256,11 @@ auto OpusTagParser::ReadAndParseTags(const std::string& path, TrackTags* out)
} }
out->encoding(Container::kOpus); out->encoding(Container::kOpus);
const char* tag = NULL; for (const auto& pair : kVorbisIdToTag) {
tag = opus_tags_query(tags, "TITLE", 0); const char* tag = opus_tags_query(tags, pair.first, 0);
if (tag != NULL) { if (tag != NULL) {
out->set(Tag::kTitle, tag); out->set(pair.second, tag);
} }
tag = opus_tags_query(tags, "ARTIST", 0);
if (tag != NULL) {
out->set(Tag::kArtist, tag);
}
tag = opus_tags_query(tags, "ALBUM", 0);
if (tag != NULL) {
out->set(Tag::kAlbum, tag);
} }
op_free(f); op_free(f);

@ -45,6 +45,7 @@ auto TrackTags::Hash() const -> uint64_t {
HashString(&stream, at(Tag::kTitle).value_or("")); HashString(&stream, at(Tag::kTitle).value_or(""));
HashString(&stream, at(Tag::kArtist).value_or("")); HashString(&stream, at(Tag::kArtist).value_or(""));
HashString(&stream, at(Tag::kAlbum).value_or("")); HashString(&stream, at(Tag::kAlbum).value_or(""));
HashString(&stream, at(Tag::kAlbumTrack).value_or(""));
return komihash_stream_final(&stream); return komihash_stream_final(&stream);
} }

Loading…
Cancel
Save