diff --git a/approot/messages.xml b/approot/messages.xml
index cc8ba74c..1fcfeea3 100644
--- a/approot/messages.xml
+++ b/approot/messages.xml
@@ -190,12 +190,12 @@
Producers
- Album artists
- Album artist
+ Album artist
+ Album artists
- Remixers
- Remixer
+ Remixer
+ Remixers
@@ -213,6 +213,7 @@
Compilation
Demo
DJ-mix
+Field recording
Interview
Live
Mixtape/Street
diff --git a/approot/messages_fr.xml b/approot/messages_fr.xml
index aca2df14..f396330e 100644
--- a/approot/messages_fr.xml
+++ b/approot/messages_fr.xml
@@ -204,21 +204,22 @@
Disque {1}
Type
Album
-Broadcast
+Diffusion
EP
Other
Single
-Audiobook
-Audio drama
+Livre audio
+Drame audio
Compilation
-Demo
+Démo
DJ-mix
+Enregistrement sur le terrain
Interview
Live
Mixtape/Street
Remix
-Soundtrack
-Spokenword
+Bande son
+Création parlée
Supprimer la liste de lecture ?
diff --git a/approot/messages_it.xml b/approot/messages_it.xml
index 7baa5358..69d30b39 100644
--- a/approot/messages_it.xml
+++ b/approot/messages_it.xml
@@ -220,6 +220,7 @@
+
diff --git a/approot/messages_zh.xml b/approot/messages_zh.xml
index f3e20cea..60853a67 100644
--- a/approot/messages_zh.xml
+++ b/approot/messages_zh.xml
@@ -220,6 +220,7 @@
+
删除播放列表?
diff --git a/src/libs/database/impl/IdTypeTraits.hpp b/src/libs/database/impl/IdTypeTraits.hpp
index bdfa0045..42dd2b2e 100644
--- a/src/libs/database/impl/IdTypeTraits.hpp
+++ b/src/libs/database/impl/IdTypeTraits.hpp
@@ -26,35 +26,34 @@
namespace Wt::Dbo
{
+ template
+ struct sql_value_traits::value>::type>
+ {
+ static_assert(!std::is_same_v, "Cannot use IdType, use derived types");
+ static const bool specialized = true;
- template
- struct sql_value_traits::value>::type>
- {
- static_assert(!std::is_same_v, "Cannot use IdType, use derived types");
- static const bool specialized = true;
+ static std::string type(SqlConnection* conn, int size)
+ {
+ return sql_value_traits::type(conn, size);
+ }
- static std::string type(SqlConnection *conn, int size)
- {
- return sql_value_traits::type(conn, size);
- }
+ static void bind(const T& v, SqlStatement* statement, int column, int size)
+ {
+ sql_value_traits::bind(v.getValue(), statement, column, size);
+ }
- static void bind(const T& v, SqlStatement *statement, int column, int size)
- {
- sql_value_traits::bind(v.getValue(), statement, column, size);
- }
+ static bool read(T& v, SqlStatement* statement, int column, int size)
+ {
+ typename T::ValueType value;
+ if (sql_value_traits::read(value, statement, column, size))
+ {
+ v = value;
+ return true;
+ }
- static bool read(T& v, SqlStatement *statement, int column, int size)
- {
- typename T::ValueType value;
- if (sql_value_traits::read(value, statement, column, size))
- {
- v = value;
- return true;
- }
-
- v = {};
- return false;
- }
- };
+ v = {};
+ return false;
+ }
+ };
}
diff --git a/src/libs/database/impl/Migration.cpp b/src/libs/database/impl/Migration.cpp
index 6cff6ac2..59d20694 100644
--- a/src/libs/database/impl/Migration.cpp
+++ b/src/libs/database/impl/Migration.cpp
@@ -267,6 +267,31 @@ CREATE TABLE IF NOT EXISTS "track_backup" (
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
}
+ void migrateFromV47(Session& session)
+ {
+ // release type, new way
+ session.getDboSession().execute("ALTER TABLE release DROP primary_type");
+ session.getDboSession().execute("ALTER TABLE release DROP secondary_types");
+
+ session.getDboSession().execute(R"(CREATE TABLE IF NOT EXISTS "release_type" (
+ "id" integer primary key autoincrement,
+ "version" integer not null,
+ "name" text not null))");
+
+ session.getDboSession().execute(R"(CREATE TABLE IF NOT EXISTS "release_release_type" (
+ "release_type_id" bigint,
+ "release_id" bigint,
+ primary key ("release_type_id", "release_id"),
+ constraint "fk_release_release_type_key1" foreign key ("release_type_id") references "release_type" ("id") on delete cascade deferrable initially deferred,
+ constraint "fk_release_release_type_key2" foreign key ("release_id") references "release" ("id") on delete cascade deferrable initially deferred
+))");
+ session.getDboSession().execute(R"(CREATE INDEX "release_release_type_release_type" on "release_release_type" ("release_type_id"))");
+ session.getDboSession().execute(R"(CREATE INDEX "release_release_type_release" on "release_release_type" ("release_id"))");
+
+ // Just increment the scan version of the settings to make the next scheduled scan rescan everything
+ session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
+ }
+
void doDbMigration(Session& session)
{
static const std::string outdatedMsg{ "Outdated database, please rebuild it (delete the .db file and restart)" };
@@ -292,6 +317,7 @@ CREATE TABLE IF NOT EXISTS "track_backup" (
{44, migrateFromV44},
{45, migrateFromV45},
{46, migrateFromV46},
+ {47, migrateFromV47},
};
{
diff --git a/src/libs/database/impl/Migration.hpp b/src/libs/database/impl/Migration.hpp
index 3c351bad..5717b96d 100644
--- a/src/libs/database/impl/Migration.hpp
+++ b/src/libs/database/impl/Migration.hpp
@@ -26,7 +26,7 @@ namespace Database
class Session;
using Version = std::size_t;
- static constexpr Version LMS_DATABASE_VERSION{ 47 };
+ static constexpr Version LMS_DATABASE_VERSION{ 48 };
class VersionInfo
{
public:
diff --git a/src/libs/database/impl/Release.cpp b/src/libs/database/impl/Release.cpp
index 9dcda60e..f56b028e 100644
--- a/src/libs/database/impl/Release.cpp
+++ b/src/libs/database/impl/Release.cpp
@@ -30,6 +30,7 @@
#include "SqlQuery.hpp"
#include "EnumSetTraits.hpp"
#include "IdTypeTraits.hpp"
+#include "StringViewTraits.hpp"
#include "Utils.hpp"
namespace Database
@@ -53,6 +54,13 @@ namespace Database
query.join("track t ON t.release_id = r.id");
}
+ if (!params.releaseType.empty())
+ {
+ query.join("release_release_type r_r_t ON r_r_t.release_id = r.id");
+ query.join("release_type r_t ON r_t.id = r_r_t.release_type_id")
+ .where("r_t.name = ?").bind(params.releaseType);
+ }
+
if (params.writtenAfter.isValid())
query.where("t.file_last_write > ?").bind(params.writtenAfter);
@@ -148,11 +156,6 @@ namespace Database
query.where(oss.str());
}
- if (params.primaryType)
- query.where("primary_type = ?").bind(*params.primaryType);
- if (!params.secondaryTypes.empty())
- query.where("secondary_type = ?").bind(params.secondaryTypes);
-
switch (params.sortMethod)
{
case ReleaseSortMethod::None:
@@ -185,6 +188,36 @@ namespace Database
}
}
+ ReleaseType::ReleaseType(std::string_view name)
+ : _name{ std::string(name, 0 , _maxNameLength) }
+ {
+ }
+
+ ReleaseType::pointer ReleaseType::create(Session& session, std::string_view name)
+ {
+ return session.getDboSession().add(std::unique_ptr {new ReleaseType{ name }});
+ }
+
+ ReleaseType::pointer ReleaseType::find(Session& session, ReleaseTypeId id)
+ {
+ session.checkReadTransaction();
+
+ return session.getDboSession()
+ .find()
+ .where("id = ?").bind(id)
+ .resultValue();
+ }
+
+ ReleaseType::pointer ReleaseType::find(Session& session, std::string_view name)
+ {
+ session.checkReadTransaction();
+
+ return session.getDboSession()
+ .find()
+ .where("name = ?").bind(name)
+ .resultValue();
+ }
+
Release::Release(const std::string& name, const std::optional& MBID)
: _name{ std::string(name, 0 , _maxNameLength) },
_MBID{ MBID ? MBID->getAsString() : "" }
@@ -448,6 +481,16 @@ namespace Database
return std::vector(res.begin(), res.end());
}
+ void Release::clearReleaseTypes()
+ {
+ _releaseTypes.clear();
+ }
+
+ void Release::addReleaseType(ObjectPtr releaseType)
+ {
+ _releaseTypes.insert(getDboPtr(releaseType));
+ }
+
bool Release::hasVariousArtists() const
{
// TODO optimize
@@ -459,6 +502,21 @@ namespace Database
return _tracks.size();
}
+ std::vector> Release::getReleaseTypes() const
+ {
+ return std::vector>(_releaseTypes.begin(), _releaseTypes.end());
+ }
+
+ std::vector Release::getReleaseTypeNames() const
+ {
+ std::vector res;
+
+ for (const auto& releaseType : _releaseTypes)
+ res.push_back(std::string{ releaseType->getName() });
+
+ return res;
+ }
+
std::chrono::milliseconds Release::getDuration() const
{
assert(session());
diff --git a/src/libs/database/impl/Session.cpp b/src/libs/database/impl/Session.cpp
index 06ce0151..9079c664 100644
--- a/src/libs/database/impl/Session.cpp
+++ b/src/libs/database/impl/Session.cpp
@@ -82,6 +82,7 @@ namespace Database
_session.mapClass("cluster_type");
_session.mapClass("listen");
_session.mapClass("release");
+ _session.mapClass("release_type");
_session.mapClass("scan_settings");
_session.mapClass("starred_artist");
_session.mapClass("starred_release");
@@ -142,6 +143,7 @@ namespace Database
_session.execute("CREATE INDEX IF NOT EXISTS release_name_idx ON release(name)");
_session.execute("CREATE INDEX IF NOT EXISTS release_name_nocase_idx ON release(name COLLATE NOCASE)");
_session.execute("CREATE INDEX IF NOT EXISTS release_mbid_idx ON release(mbid)");
+ _session.execute("CREATE INDEX IF NOT EXISTS release_type_name_idx ON release_type(name)");
_session.execute("CREATE INDEX IF NOT EXISTS track_path_idx ON track(file_path)");
_session.execute("CREATE INDEX IF NOT EXISTS track_name_idx ON track(name)");
_session.execute("CREATE INDEX IF NOT EXISTS track_name_nocase_idx ON track(name COLLATE NOCASE)");
diff --git a/src/libs/database/impl/Track.cpp b/src/libs/database/impl/Track.cpp
index 4811dc95..68124631 100644
--- a/src/libs/database/impl/Track.cpp
+++ b/src/libs/database/impl/Track.cpp
@@ -197,8 +197,7 @@ namespace Database
return session.getDboSession().add(std::unique_ptr