summaryrefslogtreecommitdiff
path: root/src/database/include
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-06-15 10:42:28 +1000
committerjacqueline <me@jacqueline.id.au>2023-06-15 10:42:28 +1000
commitc6bb42cdd21b63accd20012373a8a0e41d8566f5 (patch)
tree7fdbab3c5f1e285b54ea4949a31db41602b93b83 /src/database/include
parent0024bb1dbe0df319bc7bf022f0c4614cc9c8e0ed (diff)
downloadtangara-fw-c6bb42cdd21b63accd20012373a8a0e41d8566f5.tar.gz
song -> track
Diffstat (limited to 'src/database/include')
-rw-r--r--src/database/include/database.hpp24
-rw-r--r--src/database/include/records.hpp36
-rw-r--r--src/database/include/song.hpp166
-rw-r--r--src/database/include/tag_parser.hpp6
-rw-r--r--src/database/include/track.hpp169
5 files changed, 202 insertions, 199 deletions
diff --git a/src/database/include/database.hpp b/src/database/include/database.hpp
index 5214b8df..1a8388e8 100644
--- a/src/database/include/database.hpp
+++ b/src/database/include/database.hpp
@@ -23,9 +23,9 @@
#include "leveldb/slice.h"
#include "records.hpp"
#include "result.hpp"
-#include "song.hpp"
#include "tag_parser.hpp"
#include "tasks.hpp"
+#include "track.hpp"
namespace database {
@@ -82,7 +82,7 @@ class Database {
auto Update() -> std::future<void>;
- auto GetSongs(std::size_t page_size) -> std::future<Result<Song>*>;
+ auto GetTracks(std::size_t page_size) -> std::future<Result<Track>*>;
auto GetDump(std::size_t page_size) -> std::future<Result<std::string>*>;
template <typename T>
@@ -109,14 +109,14 @@ class Database {
ITagParser* tag_parser,
std::shared_ptr<tasks::Worker> worker);
- auto dbMintNewSongId() -> SongId;
- auto dbEntomb(SongId song, uint64_t hash) -> void;
+ auto dbMintNewTrackId() -> TrackId;
+ auto dbEntomb(TrackId track, uint64_t hash) -> void;
- auto dbPutSongData(const SongData& s) -> void;
- auto dbGetSongData(SongId id) -> std::optional<SongData>;
- auto dbPutHash(const uint64_t& hash, SongId i) -> void;
- auto dbGetHash(const uint64_t& hash) -> std::optional<SongId>;
- auto dbPutSong(SongId id, const std::string& path, const uint64_t& hash)
+ auto dbPutTrackData(const TrackData& s) -> void;
+ auto dbGetTrackData(TrackId id) -> std::optional<TrackData>;
+ auto dbPutHash(const uint64_t& hash, TrackId i) -> void;
+ auto dbGetHash(const uint64_t& hash) -> std::optional<TrackId>;
+ auto dbPutTrack(TrackId id, const std::string& path, const uint64_t& hash)
-> void;
template <typename T>
@@ -128,9 +128,9 @@ class Database {
};
template <>
-auto Database::ParseRecord<Song>(const leveldb::Slice& key,
- const leveldb::Slice& val)
- -> std::optional<Song>;
+auto Database::ParseRecord<Track>(const leveldb::Slice& key,
+ const leveldb::Slice& val)
+ -> std::optional<Track>;
template <>
auto Database::ParseRecord<std::string>(const leveldb::Slice& key,
const leveldb::Slice& val)
diff --git a/src/database/include/records.hpp b/src/database/include/records.hpp
index 1b66ad42..95a1a1e8 100644
--- a/src/database/include/records.hpp
+++ b/src/database/include/records.hpp
@@ -13,7 +13,7 @@
#include "leveldb/db.h"
#include "leveldb/slice.h"
-#include "song.hpp"
+#include "track.hpp"
namespace database {
@@ -31,49 +31,49 @@ class OwningSlice {
};
/*
- * Returns the prefix added to every SongData key. This can be used to iterate
+ * Returns the prefix added to every TrackData key. This can be used to iterate
* over every data record in the database.
*/
auto CreateDataPrefix() -> OwningSlice;
-/* Creates a data key for a song with the specified id. */
-auto CreateDataKey(const SongId& id) -> OwningSlice;
+/* Creates a data key for a track with the specified id. */
+auto CreateDataKey(const TrackId& id) -> OwningSlice;
/*
- * Encodes a SongData instance into bytes, in preparation for storing it within
+ * Encodes a TrackData instance into bytes, in preparation for storing it within
* the database. This encoding is consistent, and will remain stable over time.
*/
-auto CreateDataValue(const SongData& song) -> OwningSlice;
+auto CreateDataValue(const TrackData& track) -> OwningSlice;
/*
- * Parses bytes previously encoded via CreateDataValue back into a SongData. May
- * return nullopt if parsing fails.
+ * Parses bytes previously encoded via CreateDataValue back into a TrackData.
+ * May return nullopt if parsing fails.
*/
-auto ParseDataValue(const leveldb::Slice& slice) -> std::optional<SongData>;
+auto ParseDataValue(const leveldb::Slice& slice) -> std::optional<TrackData>;
/* Creates a hash key for the specified hash. */
auto CreateHashKey(const uint64_t& hash) -> OwningSlice;
/*
- * Encodes a hash value (at this point just a song id) into bytes, in
+ * Encodes a hash value (at this point just a track id) into bytes, in
* preparation for storing within the database. This encoding is consistent, and
* will remain stable over time.
*/
-auto CreateHashValue(SongId id) -> OwningSlice;
+auto CreateHashValue(TrackId id) -> OwningSlice;
/*
- * Parses bytes previously encoded via CreateHashValue back into a song id. May
+ * Parses bytes previously encoded via CreateHashValue back into a track id. May
* return nullopt if parsing fails.
*/
-auto ParseHashValue(const leveldb::Slice&) -> std::optional<SongId>;
+auto ParseHashValue(const leveldb::Slice&) -> std::optional<TrackId>;
-/* Encodes a SongId as bytes. */
-auto SongIdToBytes(SongId id) -> OwningSlice;
+/* Encodes a TrackId as bytes. */
+auto TrackIdToBytes(TrackId id) -> OwningSlice;
/*
- * Converts a song id encoded via SongIdToBytes back into a SongId. May return
- * nullopt if parsing fails.
+ * Converts a track id encoded via TrackIdToBytes back into a TrackId. May
+ * return nullopt if parsing fails.
*/
-auto BytesToSongId(const std::string& bytes) -> std::optional<SongId>;
+auto BytesToTrackId(const std::string& bytes) -> std::optional<TrackId>;
} // namespace database
diff --git a/src/database/include/song.hpp b/src/database/include/song.hpp
deleted file mode 100644
index d03660dc..00000000
--- a/src/database/include/song.hpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright 2023 jacqueline <me@jacqueline.id.au>
- *
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-#pragma once
-
-#include <stdint.h>
-
-#include <optional>
-#include <string>
-#include <utility>
-
-#include "leveldb/db.h"
-#include "span.hpp"
-
-namespace database {
-
-/*
- * Uniquely describes a single song within the database. This value will be
- * consistent across database updates, and should ideally (but is not guaranteed
- * to) endure even across a song being removed and re-added.
- *
- * Four billion songs should be enough for anybody.
- */
-typedef uint32_t SongId;
-
-/*
- * Audio file encodings that we are aware of. Used to select an appropriate
- * decoder at play time.
- *
- * Values of this enum are persisted in this database, so it is probably never a
- * good idea to change the int representation of an existing value.
- */
-enum class Encoding {
- kUnsupported = 0,
- kMp3 = 1,
- kWav = 2,
- kOgg = 3,
- kFlac = 4,
-};
-
-/*
- * Owning container for tag-related song metadata that was extracted from a
- * file.
- */
-struct SongTags {
- Encoding encoding;
- std::optional<std::string> title;
-
- // TODO(jacqueline): It would be nice to use shared_ptr's for the artist and
- // album, since there's likely a fair number of duplicates for each
- // (especially the former).
-
- std::optional<std::string> artist;
- std::optional<std::string> album;
-
- std::optional<int> channels;
- std::optional<int> sample_rate;
- std::optional<int> bits_per_sample;
-
- /*
- * Returns a hash of the 'identifying' tags of this song. That is, a hash that
- * can be used to determine if one song is likely the same as another, across
- * things like re-encoding, re-mastering, or moving the underlying file.
- */
- auto Hash() const -> uint64_t;
-
- bool operator==(const SongTags&) const = default;
-};
-
-/*
- * Immutable owning container for all of the metadata we store for a particular
- * song. This includes two main kinds of metadata:
- * 1. static(ish) attributes, such as the id, path on disk, hash of the tags
- * 2. dynamic attributes, such as the number of times this song has been
- * played.
- *
- * Because a SongData is immutable, it is thread safe but will not reflect any
- * changes to the dynamic attributes that may happen after it was obtained.
- *
- * Songs may be 'tombstoned'; this indicates that the song is no longer present
- * at its previous location on disk, and we do not have any existing files with
- * a matching tags_hash. When this is the case, we ignore this SongData for most
- * purposes. We keep the entry in our database so that we can properly restore
- * dynamic attributes (such as play count) if the song later re-appears on disk.
- */
-class SongData {
- private:
- const SongId id_;
- const std::string filepath_;
- const uint64_t tags_hash_;
- const uint32_t play_count_;
- const bool is_tombstoned_;
-
- public:
- /* Constructor used when adding new songs to the database. */
- SongData(SongId id, const std::string& path, uint64_t hash)
- : id_(id),
- filepath_(path),
- tags_hash_(hash),
- play_count_(0),
- is_tombstoned_(false) {}
-
- SongData(SongId id,
- const std::string& path,
- uint64_t hash,
- uint32_t play_count,
- bool is_tombstoned)
- : id_(id),
- filepath_(path),
- tags_hash_(hash),
- play_count_(play_count),
- is_tombstoned_(is_tombstoned) {}
-
- auto id() const -> SongId { return id_; }
- auto filepath() const -> std::string { return filepath_; }
- auto play_count() const -> uint32_t { return play_count_; }
- auto tags_hash() const -> uint64_t { return tags_hash_; }
- auto is_tombstoned() const -> bool { return is_tombstoned_; }
-
- auto UpdateHash(uint64_t new_hash) const -> SongData;
-
- /*
- * Marks this song data as a 'tombstone'. Tombstoned songs are not playable,
- * and should not generally be shown to users.
- */
- auto Entomb() const -> SongData;
-
- /*
- * Clears the tombstone bit of this song, and updates the path to reflect its
- * new location.
- */
- auto Exhume(const std::string& new_path) const -> SongData;
-
- bool operator==(const SongData&) const = default;
-};
-
-/*
- * Immutable and owning combination of a song's tags and metadata.
- *
- * Note that instances of this class may have a fairly large memory impact, due
- * to the large number of strings they own. Prefer to query the database again
- * (which has its own caching layer), rather than retaining Song instances for a
- * long time.
- */
-class Song {
- public:
- Song(const SongData& data, const SongTags& tags) : data_(data), tags_(tags) {}
- Song(const Song& other) = default;
-
- auto data() const -> const SongData& { return data_; }
- auto tags() const -> const SongTags& { return tags_; }
-
- bool operator==(const Song&) const = default;
- Song operator=(const Song& other) const { return Song(other); }
-
- private:
- const SongData data_;
- const SongTags tags_;
-};
-
-void swap(Song& first, Song& second);
-
-} // namespace database
diff --git a/src/database/include/tag_parser.hpp b/src/database/include/tag_parser.hpp
index 7dab93a1..4be5ad16 100644
--- a/src/database/include/tag_parser.hpp
+++ b/src/database/include/tag_parser.hpp
@@ -8,20 +8,20 @@
#include <string>
-#include "song.hpp"
+#include "track.hpp"
namespace database {
class ITagParser {
public:
virtual ~ITagParser() {}
- virtual auto ReadAndParseTags(const std::string& path, SongTags* out)
+ virtual auto ReadAndParseTags(const std::string& path, TrackTags* out)
-> bool = 0;
};
class TagParserImpl : public ITagParser {
public:
- virtual auto ReadAndParseTags(const std::string& path, SongTags* out)
+ virtual auto ReadAndParseTags(const std::string& path, TrackTags* out)
-> bool override;
};
diff --git a/src/database/include/track.hpp b/src/database/include/track.hpp
new file mode 100644
index 00000000..5a0c0ca8
--- /dev/null
+++ b/src/database/include/track.hpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <optional>
+#include <string>
+#include <utility>
+
+#include "leveldb/db.h"
+#include "span.hpp"
+
+namespace database {
+
+/*
+ * Uniquely describes a single track within the database. This value will be
+ * consistent across database updates, and should ideally (but is not guaranteed
+ * to) endure even across a track being removed and re-added.
+ *
+ * Four billion tracks should be enough for anybody.
+ */
+typedef uint32_t TrackId;
+
+/*
+ * Audio file encodings that we are aware of. Used to select an appropriate
+ * decoder at play time.
+ *
+ * Values of this enum are persisted in this database, so it is probably never a
+ * good idea to change the int representation of an existing value.
+ */
+enum class Encoding {
+ kUnsupported = 0,
+ kMp3 = 1,
+ kWav = 2,
+ kOgg = 3,
+ kFlac = 4,
+};
+
+/*
+ * Owning container for tag-related track metadata that was extracted from a
+ * file.
+ */
+struct TrackTags {
+ Encoding encoding;
+ std::optional<std::string> title;
+
+ // TODO(jacqueline): It would be nice to use shared_ptr's for the artist and
+ // album, since there's likely a fair number of duplicates for each
+ // (especially the former).
+
+ std::optional<std::string> artist;
+ std::optional<std::string> album;
+
+ std::optional<int> channels;
+ std::optional<int> sample_rate;
+ std::optional<int> bits_per_sample;
+
+ /*
+ * Returns a hash of the 'identifying' tags of this track. That is, a hash
+ * that can be used to determine if one track is likely the same as another,
+ * across things like re-encoding, re-mastering, or moving the underlying
+ * file.
+ */
+ auto Hash() const -> uint64_t;
+
+ bool operator==(const TrackTags&) const = default;
+};
+
+/*
+ * Immutable owning container for all of the metadata we store for a particular
+ * track. This includes two main kinds of metadata:
+ * 1. static(ish) attributes, such as the id, path on disk, hash of the tags
+ * 2. dynamic attributes, such as the number of times this track has been
+ * played.
+ *
+ * Because a TrackData is immutable, it is thread safe but will not reflect any
+ * changes to the dynamic attributes that may happen after it was obtained.
+ *
+ * Tracks may be 'tombstoned'; this indicates that the track is no longer
+ * present at its previous location on disk, and we do not have any existing
+ * files with a matching tags_hash. When this is the case, we ignore this
+ * TrackData for most purposes. We keep the entry in our database so that we can
+ * properly restore dynamic attributes (such as play count) if the track later
+ * re-appears on disk.
+ */
+class TrackData {
+ private:
+ const TrackId id_;
+ const std::string filepath_;
+ const uint64_t tags_hash_;
+ const uint32_t play_count_;
+ const bool is_tombstoned_;
+
+ public:
+ /* Constructor used when adding new tracks to the database. */
+ TrackData(TrackId id, const std::string& path, uint64_t hash)
+ : id_(id),
+ filepath_(path),
+ tags_hash_(hash),
+ play_count_(0),
+ is_tombstoned_(false) {}
+
+ TrackData(TrackId id,
+ const std::string& path,
+ uint64_t hash,
+ uint32_t play_count,
+ bool is_tombstoned)
+ : id_(id),
+ filepath_(path),
+ tags_hash_(hash),
+ play_count_(play_count),
+ is_tombstoned_(is_tombstoned) {}
+
+ auto id() const -> TrackId { return id_; }
+ auto filepath() const -> std::string { return filepath_; }
+ auto play_count() const -> uint32_t { return play_count_; }
+ auto tags_hash() const -> uint64_t { return tags_hash_; }
+ auto is_tombstoned() const -> bool { return is_tombstoned_; }
+
+ auto UpdateHash(uint64_t new_hash) const -> TrackData;
+
+ /*
+ * Marks this track data as a 'tombstone'. Tombstoned tracks are not playable,
+ * and should not generally be shown to users.
+ */
+ auto Entomb() const -> TrackData;
+
+ /*
+ * Clears the tombstone bit of this track, and updates the path to reflect its
+ * new location.
+ */
+ auto Exhume(const std::string& new_path) const -> TrackData;
+
+ bool operator==(const TrackData&) const = default;
+};
+
+/*
+ * Immutable and owning combination of a track's tags and metadata.
+ *
+ * Note that instances of this class may have a fairly large memory impact, due
+ * to the large number of strings they own. Prefer to query the database again
+ * (which has its own caching layer), rather than retaining Track instances for
+ * a long time.
+ */
+class Track {
+ public:
+ Track(const TrackData& data, const TrackTags& tags)
+ : data_(data), tags_(tags) {}
+ Track(const Track& other) = default;
+
+ auto data() const -> const TrackData& { return data_; }
+ auto tags() const -> const TrackTags& { return tags_; }
+
+ bool operator==(const Track&) const = default;
+ Track operator=(const Track& other) const { return Track(other); }
+
+ private:
+ const TrackData data_;
+ const TrackTags tags_;
+};
+
+void swap(Track& first, Track& second);
+
+} // namespace database