Finished initial round of query serialization.

This commit is contained in:
casey langen 2020-10-05 18:44:16 -07:00
parent 9af8844a29
commit fc8279968e
25 changed files with 428 additions and 97 deletions

View File

@ -37,16 +37,17 @@
#include "QueryRegistry.h" #include "QueryRegistry.h"
#include <core/library/query/AlbumListQuery.h> #include <core/library/query/AlbumListQuery.h>
#include <core/library/query/AllCategoriesQuery.h> #include <core/library/query/AllCategoriesQuery.h>
//#include <core/library/query/AppendPlaylistQuery.h> #include <core/library/query/AppendPlaylistQuery.h>
#include <core/library/query/GetPlaylistQuery.h> #include <core/library/query/GetPlaylistQuery.h>
#include <core/library/query/CategoryListQuery.h> #include <core/library/query/CategoryListQuery.h>
#include <core/library/query/CategoryTrackListQuery.h> #include <core/library/query/CategoryTrackListQuery.h>
//#include <core/library/query/DeletePlaylistQuery.h> #include <core/library/query/DeletePlaylistQuery.h>
//#include <core/library/query/DirectoryTrackListQuery.h> #include <core/library/query/DirectoryTrackListQuery.h>
#include <core/library/query/LyricsQuery.h> #include <core/library/query/LyricsQuery.h>
// #include <core/library/query/MarkTrackPlayedQuery.h> #include <core/library/query/MarkTrackPlayedQuery.h>
// #include <core/library/query/NowPlayingTrackListQuery.h> #include <core/library/query/NowPlayingTrackListQuery.h>
// #include <core/library/query/SavePlaylistQuery.h> #include <core/library/query/PersistedPlayQueueQuery.h>
#include <core/library/query/SavePlaylistQuery.h>
#include <core/library/query/SearchTrackListQuery.h> #include <core/library/query/SearchTrackListQuery.h>
#include <core/library/query/SetTrackRatingQuery.h> #include <core/library/query/SetTrackRatingQuery.h>
#include <core/library/query/TrackMetadataQuery.h> #include <core/library/query/TrackMetadataQuery.h>
@ -67,8 +68,9 @@ namespace musik { namespace core { namespace library {
if (name == AllCategoriesQuery::kQueryName) { if (name == AllCategoriesQuery::kQueryName) {
return AllCategoriesQuery::DeserializeQuery(data); return AllCategoriesQuery::DeserializeQuery(data);
} }
//if (name == AppendPlaylistQuery::kQueryName) { if (name == AppendPlaylistQuery::kQueryName) {
//} return AppendPlaylistQuery::DeserializeQuery(library, data);
}
if (name == GetPlaylistQuery::kQueryName) { if (name == GetPlaylistQuery::kQueryName) {
return GetPlaylistQuery::DeserializeQuery(library, data); return GetPlaylistQuery::DeserializeQuery(library, data);
} }
@ -78,19 +80,21 @@ namespace musik { namespace core { namespace library {
if (name == CategoryTrackListQuery::kQueryName) { if (name == CategoryTrackListQuery::kQueryName) {
return CategoryTrackListQuery::DeserializeQuery(library, data); return CategoryTrackListQuery::DeserializeQuery(library, data);
} }
//if (name == DeletePlaylistQuery::kQueryName) { if (name == DeletePlaylistQuery::kQueryName) {
//} return DeletePlaylistQuery::DeserializeQuery(library, data);
//if (name == DirectoryTrackListQuery::kQueryName) { }
//} if (name == DirectoryTrackListQuery::kQueryName) {
return DirectoryTrackListQuery::DeserializeQuery(library, data);
}
if (name == LyricsQuery::kQueryName) { if (name == LyricsQuery::kQueryName) {
return LyricsQuery::DeserializeQuery(data); return LyricsQuery::DeserializeQuery(data);
} }
//if (name == MarkTrackPlayedQuery::kQueryName) { if (name == MarkTrackPlayedQuery::kQueryName) {
//} return MarkTrackPlayedQuery::DeserializeQuery(data);
//if (name == NowPlayingTrackListQuery::kQueryName) { }
//} if (name == SavePlaylistQuery::kQueryName) {
//if (name == SavePlaylistQuery::kQueryName) { return SavePlaylistQuery::DeserializeQuery(library, data);
//} }
if (name == SearchTrackListQuery::kQueryName) { if (name == SearchTrackListQuery::kQueryName) {
return SearchTrackListQuery::DeserializeQuery(library, data); return SearchTrackListQuery::DeserializeQuery(library, data);
} }
@ -102,6 +106,15 @@ namespace musik { namespace core { namespace library {
} }
return std::shared_ptr<ISerializableQuery>(); return std::shared_ptr<ISerializableQuery>();
} }
bool IsLocalOnlyQuery(const std::string& queryName) {
static const std::set<std::string> sLocalOnlyQuerys = {
NowPlayingTrackListQuery::kQueryName,
PersistedPlayQueueQuery::kQueryName
};
return sLocalOnlyQuerys.find(queryName) != sLocalOnlyQuerys.end();
}
} }
} } } } } }

View File

@ -44,6 +44,8 @@ namespace musik { namespace core { namespace library {
namespace QueryRegistry { namespace QueryRegistry {
std::shared_ptr<musik::core::db::ISerializableQuery> CreateLocalQueryFor( std::shared_ptr<musik::core::db::ISerializableQuery> CreateLocalQueryFor(
const std::string& name, const std::string& data, musik::core::ILibraryPtr library); const std::string& name, const std::string& data, musik::core::ILibraryPtr library);
bool IsLocalOnlyQuery(const std::string& queryName);
} }
} } } } } }

View File

@ -131,6 +131,11 @@ void RemoteLibrary::Close() {
} }
int RemoteLibrary::Enqueue(QueryPtr query, unsigned int options, Callback callback) { int RemoteLibrary::Enqueue(QueryPtr query, unsigned int options, Callback callback) {
if (QueryRegistry::IsLocalOnlyQuery(query->Name())) {
auto defaultLocalLibrary = LibraryFactory::Instance().Default();
return defaultLocalLibrary->Enqueue(query, options, callback);
}
auto serializableQuery = std::dynamic_pointer_cast<ISerializableQuery>(query); auto serializableQuery = std::dynamic_pointer_cast<ISerializableQuery>(query);
if (serializableQuery) { if (serializableQuery) {
@ -206,7 +211,7 @@ void RemoteLibrary::RunQuery(QueryContextPtr context, bool notify) {
this->QueryCompleted(localQuery.get()); this->QueryCompleted(localQuery.get());
} }
} }
if (context->callback) { else if (context->callback) {
context->callback(context->query); context->callback(context->query);
} }
}; };

View File

@ -36,10 +36,12 @@
#include "AppendPlaylistQuery.h" #include "AppendPlaylistQuery.h"
#include <core/library/track/LibraryTrack.h> #include <core/library/track/LibraryTrack.h>
#include <core/library/query/TrackMetadataQuery.h> #include <core/library/query/TrackMetadataQuery.h>
#include <core/library/query/util/Serialization.h>
#include <core/library/LocalLibraryConstants.h> #include <core/library/LocalLibraryConstants.h>
#include <core/runtime/Message.h> #include <core/runtime/Message.h>
#include <core/support/Messages.h> #include <core/support/Messages.h>
#include <core/db/Statement.h> #include <core/db/Statement.h>
#include <json.hpp>
using musik::core::db::Statement; using musik::core::db::Statement;
using musik::core::db::Row; using musik::core::db::Row;
@ -47,10 +49,13 @@ using musik::core::db::Row;
using namespace musik::core; using namespace musik::core;
using namespace musik::core::db; using namespace musik::core::db;
using namespace musik::core::library::query; using namespace musik::core::library::query;
using namespace musik::core::library::query::serialization;
using namespace musik::core::library::constants; using namespace musik::core::library::constants;
using namespace musik::core::sdk; using namespace musik::core::sdk;
using namespace musik::core::runtime; using namespace musik::core::runtime;
const std::string AppendPlaylistQuery::kQueryName = "AppendPlaylistQuery";
static std::string INSERT_PLAYLIST_TRACK_QUERY = static std::string INSERT_PLAYLIST_TRACK_QUERY =
"INSERT INTO playlist_tracks (track_external_id, source_id, playlist_id, sort_order) " "INSERT INTO playlist_tracks (track_external_id, source_id, playlist_id, sort_order) "
"VALUES (?, ?, ?, ?)"; "VALUES (?, ?, ?, ?)";
@ -87,9 +92,12 @@ AppendPlaylistQuery::AppendPlaylistQuery(
} }
bool AppendPlaylistQuery::OnRun(musik::core::db::Connection &db) { bool AppendPlaylistQuery::OnRun(musik::core::db::Connection &db) {
this->result = false;
ITrackList* tracks = sharedTracks ? sharedTracks.get() : rawTracks; ITrackList* tracks = sharedTracks ? sharedTracks.get() : rawTracks;
if (!tracks || !tracks->Count() || playlistId == 0) { if (!tracks || !tracks->Count() || playlistId == 0) {
this->result = true;
return true; return true;
} }
@ -148,5 +156,45 @@ bool AppendPlaylistQuery::OnRun(musik::core::db::Connection &db) {
this->library->GetMessageQueue().Broadcast( this->library->GetMessageQueue().Broadcast(
Message::Create(nullptr, message::PlaylistModified, playlistId)); Message::Create(nullptr, message::PlaylistModified, playlistId));
this->result = true;
return true; return true;
}
/* ISerializableQuery */
std::string AppendPlaylistQuery::SerializeQuery() {
ITrackList* tracks = rawTracks ? rawTracks : sharedTracks.get();
nlohmann::json output = {
{ "name", kQueryName },
{ "options", {
{ "playlistId", this->playlistId },
{ "offset", this->offset },
{ "tracks", ITrackListToJsonIdList(*tracks) }
}}
};
return output.dump();
}
std::string AppendPlaylistQuery::SerializeResult() {
nlohmann::json output = { { "result", this->result } };
return output.dump();
}
void AppendPlaylistQuery::DeserializeResult(const std::string& data) {
auto input = nlohmann::json::parse(data);
this->SetStatus(input["result"].get<bool>() == true
? IQuery::Finished : IQuery::Failed);
}
std::shared_ptr<AppendPlaylistQuery> AppendPlaylistQuery::DeserializeQuery(
musik::core::ILibraryPtr library, const std::string& data)
{
auto options = nlohmann::json::parse(data)["options"];
auto trackList = std::make_shared<TrackList>(library);
TrackListFromJson(options["tracks"], *trackList, library, true);
return std::make_shared<AppendPlaylistQuery>(
library,
options["playlistId"].get<int64_t>(),
trackList,
options["offset"].get<int>());
} }

View File

@ -43,6 +43,8 @@ namespace musik { namespace core { namespace library { namespace query {
class AppendPlaylistQuery : public musik::core::library::query::QueryBase { class AppendPlaylistQuery : public musik::core::library::query::QueryBase {
public: public:
static const std::string kQueryName;
AppendPlaylistQuery( AppendPlaylistQuery(
musik::core::ILibraryPtr library, musik::core::ILibraryPtr library,
const int64_t playlistId, const int64_t playlistId,
@ -57,17 +59,24 @@ namespace musik { namespace core { namespace library { namespace query {
virtual ~AppendPlaylistQuery() { } virtual ~AppendPlaylistQuery() { }
std::string Name() { return "AppendPlaylistQuery"; } std::string Name() { return kQueryName; }
/* ISerializableQuery */
virtual std::string SerializeQuery();
virtual std::string SerializeResult();
virtual void DeserializeResult(const std::string& data);
static std::shared_ptr<AppendPlaylistQuery> DeserializeQuery(
musik::core::ILibraryPtr library, const std::string& data);
protected: protected:
virtual bool OnRun(musik::core::db::Connection &db); virtual bool OnRun(musik::core::db::Connection &db);
int64_t playlistId;
musik::core::ILibraryPtr library; musik::core::ILibraryPtr library;
std::shared_ptr<musik::core::TrackList> sharedTracks; std::shared_ptr<musik::core::TrackList> sharedTracks;
musik::core::sdk::ITrackList* rawTracks; musik::core::sdk::ITrackList* rawTracks;
int64_t playlistId;
int offset; int offset;
bool result{ false };
}; };
} } } } } } } }

View File

@ -214,25 +214,17 @@ std::string CategoryTrackListQuery::SerializeQuery() {
{ "sortType", sortType } { "sortType", sortType }
}} }}
}; };
return output.dump(); return FinalizeSerializedQueryWithLimitAndOffset(output);
} }
std::string CategoryTrackListQuery::SerializeResult() { std::string CategoryTrackListQuery::SerializeResult() {
nlohmann::json output = { return InitializeSerializedResultWithHeadersAndTrackList().dump();
{ "result", {
{ "headers", *this->headers },
{ "trackList", TrackListToJson(*this->result, true) }
}}
};
return output.dump();
} }
void CategoryTrackListQuery::DeserializeResult(const std::string& data) { void CategoryTrackListQuery::DeserializeResult(const std::string& data) {
this->SetStatus(IQuery::Failed); this->SetStatus(IQuery::Failed);
nlohmann::json result = nlohmann::json::parse(data)["result"]; nlohmann::json result = nlohmann::json::parse(data)["result"];
this->result = std::make_shared<TrackList>(this->library); this->DeserializeTrackListAndHeaders(result, this->library, this->result, this->headers);
TrackListFromJson(result["trackList"], *this->result, this->library, true);
JsonArrayToSet<std::set<size_t>, size_t>(result["headers"], *this->headers);
this->SetStatus(IQuery::Finished); this->SetStatus(IQuery::Finished);
} }
@ -244,6 +236,7 @@ std::shared_ptr<CategoryTrackListQuery> CategoryTrackListQuery::DeserializeQuery
library, library,
options["filter"].get<std::string>(), options["filter"].get<std::string>(),
options["sortType"].get<TrackSortType>()); options["sortType"].get<TrackSortType>());
result->ExtractLimitAndOffsetFromDeserializedQuery(options);
PredicateListFromJson(options["regularPredicateList"], result->regular); PredicateListFromJson(options["regularPredicateList"], result->regular);
PredicateListFromJson(options["extendedPredicateList"], result->extended); PredicateListFromJson(options["extendedPredicateList"], result->extended);
result->ScanPredicateListsForQueryType(); result->ScanPredicateListsForQueryType();

View File

@ -40,11 +40,15 @@
#include <core/support/Messages.h> #include <core/support/Messages.h>
#include <core/runtime/Message.h> #include <core/runtime/Message.h>
#include <json.hpp>
using namespace musik::core; using namespace musik::core;
using namespace musik::core::db; using namespace musik::core::db;
using namespace musik::core::library::query; using namespace musik::core::library::query;
using namespace musik::core::runtime; using namespace musik::core::runtime;
const std::string DeletePlaylistQuery::kQueryName = "DeletePlaylistQuery";
static std::string DELETE_PLAYLIST_TRACKS_QUERY = static std::string DELETE_PLAYLIST_TRACKS_QUERY =
"DELETE FROM playlist_tracks WHERE playlist_id=?;"; "DELETE FROM playlist_tracks WHERE playlist_id=?;";
@ -68,20 +72,53 @@ bool DeletePlaylistQuery::OnRun(musik::core::db::Connection &db) {
if (deleteTracks.Step() == db::Error) { if (deleteTracks.Step() == db::Error) {
transaction.Cancel(); transaction.Cancel();
return false; this->result = false;
} }
else {
/* delete the container */
Statement deletePlaylist(DELETE_PLAYLIST_QUERY.c_str(), db);
deletePlaylist.BindInt64(0, this->playlistId);
/* delete the container */ if (deletePlaylist.Step() == db::Error) {
Statement deletePlaylist(DELETE_PLAYLIST_QUERY.c_str(), db); transaction.Cancel();
deletePlaylist.BindInt64(0, this->playlistId); this->result = false;
}
if (deletePlaylist.Step() == db::Error) { else {
transaction.Cancel(); this->library->GetMessageQueue().Broadcast(
return false; Message::Create(nullptr, message::PlaylistDeleted, playlistId));
this->result = true;
}
} }
return this->result;
}
this->library->GetMessageQueue().Broadcast(
Message::Create(nullptr, message::PlaylistDeleted, playlistId));
return true; /* ISerializableQuery */
std::string DeletePlaylistQuery::SerializeQuery() {
nlohmann::json output = {
{ "name", kQueryName },
{ "options", {
{ "playlistId", this->playlistId },
}}
};
return output.dump();
}
std::string DeletePlaylistQuery::SerializeResult() {
nlohmann::json output = { { "result", this->result } };
return output.dump();
}
void DeletePlaylistQuery::DeserializeResult(const std::string& data) {
auto input = nlohmann::json::parse(data);
this->SetStatus(input["result"].get<bool>() == true
? IQuery::Finished : IQuery::Failed);
}
std::shared_ptr<DeletePlaylistQuery> DeletePlaylistQuery::DeserializeQuery(
musik::core::ILibraryPtr library, const std::string& data)
{
auto options = nlohmann::json::parse(data)["options"];
return std::make_shared<DeletePlaylistQuery>(library, options["playlistId"].get<int64_t>());
} }

View File

@ -42,13 +42,22 @@ namespace musik { namespace core { namespace library { namespace query {
class DeletePlaylistQuery : public musik::core::library::query::QueryBase { class DeletePlaylistQuery : public musik::core::library::query::QueryBase {
public: public:
static const std::string kQueryName;
DeletePlaylistQuery( DeletePlaylistQuery(
musik::core::ILibraryPtr library, musik::core::ILibraryPtr library,
const int64_t playlistId); const int64_t playlistId);
virtual ~DeletePlaylistQuery(); virtual ~DeletePlaylistQuery();
virtual std::string Name() { return "DeletePlaylistQuery"; } virtual std::string Name() { return kQueryName; }
/* ISerializableQuery */
virtual std::string SerializeQuery();
virtual std::string SerializeResult();
virtual void DeserializeResult(const std::string& data);
static std::shared_ptr<DeletePlaylistQuery> DeserializeQuery(
musik::core::ILibraryPtr library, const std::string& data);
protected: protected:
virtual bool OnRun(musik::core::db::Connection &db); virtual bool OnRun(musik::core::db::Connection &db);
@ -56,6 +65,7 @@ namespace musik { namespace core { namespace library { namespace query {
private: private:
int64_t playlistId; int64_t playlistId;
musik::core::ILibraryPtr library; musik::core::ILibraryPtr library;
bool result{ false };
}; };
} } } } } } } }

View File

@ -34,6 +34,7 @@
#include "pch.hpp" #include "pch.hpp"
#include <core/library/LocalLibraryConstants.h> #include <core/library/LocalLibraryConstants.h>
#include <core/library/query/util/Serialization.h>
#include <core/i18n/Locale.h> #include <core/i18n/Locale.h>
#include "DirectoryTrackListQuery.h" #include "DirectoryTrackListQuery.h"
#include "CategoryTrackListQuery.h" #include "CategoryTrackListQuery.h"
@ -44,8 +45,11 @@ using musik::core::ILibraryPtr;
using namespace musik::core::db; using namespace musik::core::db;
using namespace musik::core::library::query; using namespace musik::core::library::query;
using namespace musik::core::library::query::serialization;
using namespace musik::core::library; using namespace musik::core::library;
const std::string DirectoryTrackListQuery::kQueryName = "DirectoryTrackListQuery";
DirectoryTrackListQuery::DirectoryTrackListQuery( DirectoryTrackListQuery::DirectoryTrackListQuery(
ILibraryPtr library, ILibraryPtr library,
const std::string& directory, const std::string& directory,
@ -101,3 +105,39 @@ bool DirectoryTrackListQuery::OnRun(Connection& db) {
return true; return true;
} }
/* ISerializableQuery */
std::string DirectoryTrackListQuery::SerializeQuery() {
nlohmann::json output = {
{ "name", kQueryName },
{ "options", {
{ "directory", directory },
{ "filter", filter },
}}
};
return FinalizeSerializedQueryWithLimitAndOffset(output);
}
std::string DirectoryTrackListQuery::SerializeResult() {
return InitializeSerializedResultWithHeadersAndTrackList().dump();
}
void DirectoryTrackListQuery::DeserializeResult(const std::string& data) {
this->SetStatus(IQuery::Failed);
nlohmann::json result = nlohmann::json::parse(data)["result"];
this->DeserializeTrackListAndHeaders(result, this->library, this->result, this->headers);
this->SetStatus(IQuery::Finished);
}
std::shared_ptr<DirectoryTrackListQuery> DirectoryTrackListQuery::DeserializeQuery(
ILibraryPtr library, const std::string& data)
{
auto options = nlohmann::json::parse(data)["options"];
auto result = std::make_shared<DirectoryTrackListQuery>(
library,
options["directory"].get<std::string>(),
options["filter"].get<std::string>());
result->ExtractLimitAndOffsetFromDeserializedQuery(options);
return result;
}

View File

@ -41,6 +41,8 @@ namespace musik { namespace core { namespace library { namespace query {
class DirectoryTrackListQuery : public TrackListQueryBase { class DirectoryTrackListQuery : public TrackListQueryBase {
public: public:
static const std::string kQueryName;
DirectoryTrackListQuery( DirectoryTrackListQuery(
musik::core::ILibraryPtr library, musik::core::ILibraryPtr library,
const std::string& directory, const std::string& directory,
@ -48,11 +50,18 @@ namespace musik { namespace core { namespace library { namespace query {
virtual ~DirectoryTrackListQuery(); virtual ~DirectoryTrackListQuery();
virtual std::string Name() { return "DirectoryTrackListQuery"; } virtual std::string Name() { return kQueryName; }
virtual Result GetResult() { return this->result; } virtual Result GetResult() { return this->result; }
virtual Headers GetHeaders() { return this->headers; } virtual Headers GetHeaders() { return this->headers; }
virtual size_t GetQueryHash() { return this->hash; } virtual size_t GetQueryHash() { return this->hash; }
/* ISerializableQuery */
virtual std::string SerializeQuery();
virtual std::string SerializeResult();
virtual void DeserializeResult(const std::string& data);
static std::shared_ptr<DirectoryTrackListQuery> DeserializeQuery(
musik::core::ILibraryPtr library, const std::string& data);
protected: protected:
virtual bool OnRun(musik::core::db::Connection &db); virtual bool OnRun(musik::core::db::Connection &db);

View File

@ -111,25 +111,17 @@ std::string GetPlaylistQuery::SerializeQuery() {
{ "playlistId", playlistId }, { "playlistId", playlistId },
}} }}
}; };
return output.dump(); return FinalizeSerializedQueryWithLimitAndOffset(output);
} }
std::string GetPlaylistQuery::SerializeResult() { std::string GetPlaylistQuery::SerializeResult() {
nlohmann::json output = { return InitializeSerializedResultWithHeadersAndTrackList().dump();
{ "result", {
{ "headers", *this->headers },
{ "trackList", TrackListToJson(*this->result, true) }
}}
};
return output.dump();
} }
void GetPlaylistQuery::DeserializeResult(const std::string& data) { void GetPlaylistQuery::DeserializeResult(const std::string& data) {
this->SetStatus(IQuery::Failed); this->SetStatus(IQuery::Failed);
nlohmann::json result = nlohmann::json::parse(data)["result"]; nlohmann::json result = nlohmann::json::parse(data)["result"];
this->result = std::make_shared<TrackList>(this->library); this->DeserializeTrackListAndHeaders(result, this->library, this->result, this->headers);
TrackListFromJson(result["trackList"], *this->result, this->library, true);
JsonArrayToSet<std::set<size_t>, size_t>(result["headers"], *this->headers);
this->SetStatus(IQuery::Finished); this->SetStatus(IQuery::Finished);
} }
@ -137,6 +129,8 @@ std::shared_ptr<GetPlaylistQuery> GetPlaylistQuery::DeserializeQuery(
musik::core::ILibraryPtr library, const std::string& data) musik::core::ILibraryPtr library, const std::string& data)
{ {
auto options = nlohmann::json::parse(data)["options"]; auto options = nlohmann::json::parse(data)["options"];
return std::make_shared<GetPlaylistQuery>( auto result = std::make_shared<GetPlaylistQuery>(
library, options["playlistId"].get<int64_t>()); library, options["playlistId"].get<int64_t>());
result->ExtractLimitAndOffsetFromDeserializedQuery(options);
return result;
} }

View File

@ -34,11 +34,14 @@
#include "pch.hpp" #include "pch.hpp"
#include "MarkTrackPlayedQuery.h" #include "MarkTrackPlayedQuery.h"
#include <json.hpp>
using namespace musik::core::db; using namespace musik::core::db;
using namespace musik::core::library::query; using namespace musik::core::library::query;
using namespace musik::core::sdk; using namespace musik::core::sdk;
const std::string MarkTrackPlayedQuery::kQueryName = "MarkTrackPlayedQuery";
MarkTrackPlayedQuery::MarkTrackPlayedQuery(const int64_t trackId) { MarkTrackPlayedQuery::MarkTrackPlayedQuery(const int64_t trackId) {
this->trackId = trackId; this->trackId = trackId;
} }
@ -55,9 +58,34 @@ bool MarkTrackPlayedQuery::OnRun(musik::core::db::Connection &db) {
stmt.BindInt64(0, this->trackId); stmt.BindInt64(0, this->trackId);
if (stmt.Step() == db::Done) { this->result = stmt.Step() == db::Done;
return true; return this->result;
} }
return false; /* ISerializableQuery */
std::string MarkTrackPlayedQuery::SerializeQuery() {
nlohmann::json output = {
{ "name", kQueryName },
{ "options", {
{ "trackId", this->trackId },
}}
};
return output.dump();
}
std::string MarkTrackPlayedQuery::SerializeResult() {
nlohmann::json output = { { "result", this->result } };
return output.dump();
}
void MarkTrackPlayedQuery::DeserializeResult(const std::string& data) {
auto input = nlohmann::json::parse(data);
this->SetStatus(input["result"].get<bool>() == true
? IQuery::Finished : IQuery::Failed);
}
std::shared_ptr<MarkTrackPlayedQuery> MarkTrackPlayedQuery::DeserializeQuery(const std::string& data) {
auto options = nlohmann::json::parse(data)["options"];
return std::make_shared<MarkTrackPlayedQuery>(options["trackId"].get<int64_t>());
} }

View File

@ -40,13 +40,22 @@ namespace musik { namespace core { namespace library { namespace query {
class MarkTrackPlayedQuery: public QueryBase { class MarkTrackPlayedQuery: public QueryBase {
public: public:
static const std::string kQueryName;
MarkTrackPlayedQuery(const int64_t trackId); MarkTrackPlayedQuery(const int64_t trackId);
virtual ~MarkTrackPlayedQuery(); virtual ~MarkTrackPlayedQuery();
std::string Name() { return "MarkTrackPlayedQuery"; } std::string Name() { return "MarkTrackPlayedQuery"; }
/* ISerializableQuery */
virtual std::string SerializeQuery();
virtual std::string SerializeResult();
virtual void DeserializeResult(const std::string& data);
static std::shared_ptr<MarkTrackPlayedQuery> DeserializeQuery(const std::string& data);
protected: protected:
virtual bool OnRun(musik::core::db::Connection &db); virtual bool OnRun(musik::core::db::Connection &db);
int64_t trackId; int64_t trackId;
bool result{ false };
}; };
} } } } } } } }

View File

@ -49,6 +49,8 @@ using namespace musik::core::db;
using namespace musik::core::library::constants; using namespace musik::core::library::constants;
using namespace musik::core::library::query; using namespace musik::core::library::query;
const std::string NowPlayingTrackListQuery::kQueryName = "NowPlayingTrackListQuery";
NowPlayingTrackListQuery::NowPlayingTrackListQuery( NowPlayingTrackListQuery::NowPlayingTrackListQuery(
ILibraryPtr library, musik::core::audio::PlaybackService& playback) ILibraryPtr library, musik::core::audio::PlaybackService& playback)
: library(library) : library(library)

View File

@ -43,13 +43,15 @@ namespace musik { namespace core { namespace library { namespace query {
class NowPlayingTrackListQuery : public TrackListQueryBase { class NowPlayingTrackListQuery : public TrackListQueryBase {
public: public:
static const std::string kQueryName;
NowPlayingTrackListQuery( NowPlayingTrackListQuery(
musik::core::ILibraryPtr library, musik::core::ILibraryPtr library,
musik::core::audio::PlaybackService& playback); musik::core::audio::PlaybackService& playback);
virtual ~NowPlayingTrackListQuery(); virtual ~NowPlayingTrackListQuery();
virtual std::string Name() { return "NowPlayingTrackListQuery"; } virtual std::string Name() { return kQueryName; }
virtual Result GetResult(); virtual Result GetResult();
virtual Headers GetHeaders(); virtual Headers GetHeaders();
virtual size_t GetQueryHash(); virtual size_t GetQueryHash();

View File

@ -42,6 +42,8 @@ using namespace musik::core;
using namespace musik::core::db; using namespace musik::core::db;
using namespace musik::core::library::query; using namespace musik::core::library::query;
const std::string PersistedPlayQueueQuery::kQueryName = "PersistedPlayQueueQuery";
PersistedPlayQueueQuery::PersistedPlayQueueQuery( PersistedPlayQueueQuery::PersistedPlayQueueQuery(
musik::core::ILibraryPtr library, musik::core::ILibraryPtr library,
musik::core::audio::PlaybackService& playback, musik::core::audio::PlaybackService& playback,

View File

@ -41,6 +41,8 @@ namespace musik { namespace core { namespace library { namespace query {
class PersistedPlayQueueQuery : public musik::core::library::query::QueryBase { class PersistedPlayQueueQuery : public musik::core::library::query::QueryBase {
public: public:
static const std::string kQueryName;
static PersistedPlayQueueQuery* Save( static PersistedPlayQueueQuery* Save(
musik::core::ILibraryPtr library, musik::core::ILibraryPtr library,
musik::core::audio::PlaybackService& playback) musik::core::audio::PlaybackService& playback)
@ -57,7 +59,7 @@ namespace musik { namespace core { namespace library { namespace query {
virtual ~PersistedPlayQueueQuery(); virtual ~PersistedPlayQueueQuery();
virtual std::string Name() { return "PersistedPlayQueueQuery"; } virtual std::string Name() { return kQueryName; }
protected: protected:
virtual bool OnRun(musik::core::db::Connection &db); virtual bool OnRun(musik::core::db::Connection &db);

View File

@ -38,18 +38,25 @@
#include <core/library/track/LibraryTrack.h> #include <core/library/track/LibraryTrack.h>
#include <core/library/query/TrackMetadataQuery.h> #include <core/library/query/TrackMetadataQuery.h>
#include <core/library/query/util/Serialization.h>
#include <core/library/LocalLibraryConstants.h>
#include <core/db/ScopedTransaction.h> #include <core/db/ScopedTransaction.h>
#include <core/db/Statement.h> #include <core/db/Statement.h>
#include <core/runtime/Message.h> #include <core/runtime/Message.h>
#include <core/support/Messages.h> #include <core/support/Messages.h>
using namespace musik::core; using namespace musik::core;
using namespace musik::core::sdk;
using namespace musik::core::db; using namespace musik::core::db;
using namespace musik::core::library;
using namespace musik::core::library::query; using namespace musik::core::library::query;
using namespace musik::core::library::query::serialization;
using namespace musik::core::runtime; using namespace musik::core::runtime;
/* CONSTANTS */ /* CONSTANTS */
const std::string SavePlaylistQuery::kQueryName = "SavePlaylistQuery";
static std::string CREATE_PLAYLIST_QUERY = static std::string CREATE_PLAYLIST_QUERY =
"INSERT INTO playlists (name) VALUES (?);"; "INSERT INTO playlists (name) VALUES (?);";
@ -130,7 +137,7 @@ std::shared_ptr<SavePlaylistQuery> SavePlaylistQuery::Append(
auto result = std::shared_ptr<SavePlaylistQuery>( auto result = std::shared_ptr<SavePlaylistQuery>(
new SavePlaylistQuery(library, playlistId, tracks)); new SavePlaylistQuery(library, playlistId, tracks));
result->op = AppendOp; result->op = Operation::Append;
return result; return result;
} }
@ -146,7 +153,7 @@ std::shared_ptr<SavePlaylistQuery> SavePlaylistQuery::Append(
auto result = std::shared_ptr<SavePlaylistQuery>( auto result = std::shared_ptr<SavePlaylistQuery>(
new SavePlaylistQuery(library, playlistId, categoryType, categoryId)); new SavePlaylistQuery(library, playlistId, categoryType, categoryId));
result->op = AppendOp; result->op = Operation::Append;
return result; return result;
} }
@ -162,7 +169,7 @@ SavePlaylistQuery::SavePlaylistQuery(
this->playlistName = playlistName; this->playlistName = playlistName;
this->tracks.rawTracks = nullptr; this->tracks.rawTracks = nullptr;
this->tracks.sharedTracks = tracks; this->tracks.sharedTracks = tracks;
this->op = CreateOp; this->op = Operation::Create;
} }
SavePlaylistQuery::SavePlaylistQuery( SavePlaylistQuery::SavePlaylistQuery(
@ -175,7 +182,7 @@ SavePlaylistQuery::SavePlaylistQuery(
this->categoryId = -1; this->categoryId = -1;
this->playlistName = playlistName; this->playlistName = playlistName;
this->tracks.rawTracks = tracks; this->tracks.rawTracks = tracks;
this->op = CreateOp; this->op = Operation::Create;
} }
SavePlaylistQuery::SavePlaylistQuery( SavePlaylistQuery::SavePlaylistQuery(
@ -189,7 +196,7 @@ SavePlaylistQuery::SavePlaylistQuery(
this->categoryId = categoryId; this->categoryId = categoryId;
this->categoryType = categoryType; this->categoryType = categoryType;
this->playlistName = playlistName; this->playlistName = playlistName;
this->op = CreateOp; this->op = Operation::Create;
} }
SavePlaylistQuery::SavePlaylistQuery( SavePlaylistQuery::SavePlaylistQuery(
@ -200,7 +207,7 @@ SavePlaylistQuery::SavePlaylistQuery(
this->library = library; this->library = library;
this->playlistId = playlistId; this->playlistId = playlistId;
this->tracks.sharedTracks = tracks; this->tracks.sharedTracks = tracks;
this->op = ReplaceOp; this->op = Operation::Replace;
} }
SavePlaylistQuery::SavePlaylistQuery( SavePlaylistQuery::SavePlaylistQuery(
@ -211,7 +218,7 @@ SavePlaylistQuery::SavePlaylistQuery(
this->library = library; this->library = library;
this->playlistId = playlistId; this->playlistId = playlistId;
this->tracks.rawTracks = tracks; this->tracks.rawTracks = tracks;
this->op = ReplaceOp; this->op = Operation::Replace;
} }
SavePlaylistQuery::SavePlaylistQuery( SavePlaylistQuery::SavePlaylistQuery(
@ -224,7 +231,7 @@ SavePlaylistQuery::SavePlaylistQuery(
this->playlistId = playlistId; this->playlistId = playlistId;
this->categoryId = categoryId; this->categoryId = categoryId;
this->categoryType = categoryType; this->categoryType = categoryType;
this->op = AppendOp; this->op = Operation::Append;
} }
SavePlaylistQuery::SavePlaylistQuery( SavePlaylistQuery::SavePlaylistQuery(
@ -236,7 +243,12 @@ SavePlaylistQuery::SavePlaylistQuery(
this->categoryId = -1; this->categoryId = -1;
this->playlistId = playlistId; this->playlistId = playlistId;
this->playlistName = playlistName; this->playlistName = playlistName;
this->op = RenameOp; this->op = Operation::Rename;
}
SavePlaylistQuery::SavePlaylistQuery(musik::core::ILibraryPtr library) {
this->library = library;
this->categoryId = -1;
} }
SavePlaylistQuery::~SavePlaylistQuery() { SavePlaylistQuery::~SavePlaylistQuery() {
@ -394,13 +406,14 @@ bool SavePlaylistQuery::AppendToPlaylist(musik::core::db::Connection& db) {
} }
bool SavePlaylistQuery::OnRun(musik::core::db::Connection &db) { bool SavePlaylistQuery::OnRun(musik::core::db::Connection &db) {
this->result = false;
switch (this->op) { switch (this->op) {
case RenameOp: return this->RenamePlaylist(db); case Operation::Rename: this->result = this->RenamePlaylist(db); break;
case ReplaceOp: return this->ReplacePlaylist(db); case Operation::Replace: this->result = this->ReplacePlaylist(db); break;
case CreateOp: return this->CreatePlaylist(db); case Operation::Create: this->result = this->CreatePlaylist(db); break;
case AppendOp: return this->AppendToPlaylist(db); case Operation::Append: this->result = this->AppendToPlaylist(db); break;
} }
return false; return this->result;
} }
/* SUPPORTING TYPES */ /* SUPPORTING TYPES */
@ -445,3 +458,53 @@ TrackPtr SavePlaylistQuery::TrackListWrapper::Get(
return result; return result;
} }
ITrackList* SavePlaylistQuery::TrackListWrapper::Get() {
if (sharedTracks) {
return sharedTracks.get();
}
return rawTracks;
}
/* ISerializableQuery */
std::string SavePlaylistQuery::SerializeQuery() {
nlohmann::json output = {
{ "name", kQueryName },
{ "options", {
{ "op", this->op },
{ "playlistName", this->playlistName },
{ "categoryType", this->categoryType },
{ "playlistId", this->playlistId },
{ "categoryId", this->categoryId },
{ "tracks", ITrackListToJsonIdList(*tracks.Get()) }
}}
};
return output.dump();
}
std::string SavePlaylistQuery::SerializeResult() {
nlohmann::json output = { { "result", this->result } };
return output.dump();
}
void SavePlaylistQuery::DeserializeResult(const std::string& data) {
auto input = nlohmann::json::parse(data);
this->SetStatus(input["result"].get<bool>() == true
? IQuery::Finished : IQuery::Failed);
}
std::shared_ptr<SavePlaylistQuery> SavePlaylistQuery::DeserializeQuery(
musik::core::ILibraryPtr library, const std::string& data)
{
auto options = nlohmann::json::parse(data)["options"];
auto output = std::shared_ptr<SavePlaylistQuery>(new SavePlaylistQuery(library));
output->op = options["op"].get<Operation>();
output->playlistName = options["playlistName"].get<std::string>();
output->categoryType = options["categoryType"].get<std::string>();
output->playlistId = options["playlistId"].get<int64_t>();
output->categoryId = options["categoryId"].get<int64_t>();
output->tracks.sharedTracks = std::make_shared<TrackList>(library);
TrackListFromJson(options["tracks"], *output->tracks.sharedTracks, library, true);
return output;
}

View File

@ -44,6 +44,8 @@ namespace musik { namespace core { namespace library { namespace query {
class SavePlaylistQuery : public musik::core::library::query::QueryBase { class SavePlaylistQuery : public musik::core::library::query::QueryBase {
public: public:
static const std::string kQueryName;
static std::shared_ptr<SavePlaylistQuery> Save( static std::shared_ptr<SavePlaylistQuery> Save(
musik::core::ILibraryPtr library, musik::core::ILibraryPtr library,
const std::string& playlistName, const std::string& playlistName,
@ -86,12 +88,19 @@ namespace musik { namespace core { namespace library { namespace query {
const std::string& categoryType, const std::string& categoryType,
int64_t categoryId); int64_t categoryId);
virtual std::string Name() { return "SavePlaylistQuery"; } virtual std::string Name() { return kQueryName; }
virtual ~SavePlaylistQuery(); virtual ~SavePlaylistQuery();
int64_t GetPlaylistId() const; int64_t GetPlaylistId() const;
/* ISerializableQuery */
virtual std::string SerializeQuery();
virtual std::string SerializeResult();
virtual void DeserializeResult(const std::string& data);
static std::shared_ptr<SavePlaylistQuery> DeserializeQuery(
musik::core::ILibraryPtr library, const std::string& data);
protected: protected:
virtual bool OnRun(musik::core::db::Connection &db); virtual bool OnRun(musik::core::db::Connection &db);
@ -133,6 +142,8 @@ namespace musik { namespace core { namespace library { namespace query {
const int64_t playlistId, const int64_t playlistId,
const std::string& newName); const std::string& newName);
SavePlaylistQuery(musik::core::ILibraryPtr library); /* for query (de)serialization */
struct TrackListWrapper { struct TrackListWrapper {
TrackListWrapper(); TrackListWrapper();
TrackListWrapper(std::shared_ptr<musik::core::TrackList> shared); TrackListWrapper(std::shared_ptr<musik::core::TrackList> shared);
@ -140,12 +151,18 @@ namespace musik { namespace core { namespace library { namespace query {
bool Exists(); bool Exists();
size_t Count(); size_t Count();
TrackPtr Get(musik::core::ILibraryPtr library, size_t index); TrackPtr Get(musik::core::ILibraryPtr library, size_t index);
musik::core::sdk::ITrackList* Get();
std::shared_ptr<musik::core::TrackList> sharedTracks; std::shared_ptr<musik::core::TrackList> sharedTracks;
musik::core::sdk::ITrackList* rawTracks; musik::core::sdk::ITrackList* rawTracks;
}; };
enum Operation { CreateOp, RenameOp, ReplaceOp, AppendOp }; enum class Operation: int {
Create = 1,
Rename = 2,
Replace = 3,
Append = 4
};
bool CreatePlaylist(musik::core::db::Connection &db); bool CreatePlaylist(musik::core::db::Connection &db);
bool RenamePlaylist(musik::core::db::Connection &db); bool RenamePlaylist(musik::core::db::Connection &db);
@ -159,6 +176,7 @@ namespace musik { namespace core { namespace library { namespace query {
int64_t playlistId, int64_t playlistId,
TrackListWrapper& tracks); TrackListWrapper& tracks);
bool result{ false };
Operation op; Operation op;
musik::core::ILibraryPtr library; musik::core::ILibraryPtr library;
std::string playlistName, categoryType; std::string playlistName, categoryType;

View File

@ -176,32 +176,26 @@ std::string SearchTrackListQuery::SerializeQuery() {
{ "sortType", sortType} { "sortType", sortType}
}} }}
}; };
return output.dump(); return FinalizeSerializedQueryWithLimitAndOffset(output);
} }
std::string SearchTrackListQuery::SerializeResult() { std::string SearchTrackListQuery::SerializeResult() {
nlohmann::json output = { return InitializeSerializedResultWithHeadersAndTrackList().dump();
{ "result", {
{ "headers", *this->headers },
{ "trackList", TrackListToJson(*this->result, true) }
}}
};
return output.dump();
} }
void SearchTrackListQuery::DeserializeResult(const std::string& data) { void SearchTrackListQuery::DeserializeResult(const std::string& data) {
this->SetStatus(IQuery::Failed); this->SetStatus(IQuery::Failed);
nlohmann::json result = nlohmann::json::parse(data)["result"]; nlohmann::json result = nlohmann::json::parse(data)["result"];
this->result = std::make_shared<TrackList>(this->library); this->DeserializeTrackListAndHeaders(result, this->library, this->result, this->headers);
TrackListFromJson(result["trackList"], *this->result, this->library, true);
JsonArrayToSet<std::set<size_t>, size_t>(result["headers"], *this->headers);
this->SetStatus(IQuery::Finished); this->SetStatus(IQuery::Finished);
} }
std::shared_ptr<SearchTrackListQuery> SearchTrackListQuery::DeserializeQuery(musik::core::ILibraryPtr library, const std::string& data) { std::shared_ptr<SearchTrackListQuery> SearchTrackListQuery::DeserializeQuery(musik::core::ILibraryPtr library, const std::string& data) {
auto options = nlohmann::json::parse(data)["options"]; auto options = nlohmann::json::parse(data)["options"];
return std::make_shared<SearchTrackListQuery>( auto result = std::make_shared<SearchTrackListQuery>(
library, library,
options["filter"].get<std::string>(), options["filter"].get<std::string>(),
options["sortType"].get<TrackSortType>()); options["sortType"].get<TrackSortType>());
result->ExtractLimitAndOffsetFromDeserializedQuery(options);
return result;
} }

View File

@ -54,13 +54,12 @@ bool SetTrackRatingQuery::OnRun(musik::core::db::Connection &db) {
Statement stmt("UPDATE tracks SET rating=? WHERE id=?", db); Statement stmt("UPDATE tracks SET rating=? WHERE id=?", db);
stmt.BindInt32(0, this->rating); stmt.BindInt32(0, this->rating);
stmt.BindInt64(1, this->trackId); stmt.BindInt64(1, this->trackId);
if (stmt.Step() == db::Done) { this->result = stmt.Step() == db::Done;
return true; return this->result;
}
return false;
} }
/* ISerializableQuery */ /* ISerializableQuery */
std::string SetTrackRatingQuery::SerializeQuery() { std::string SetTrackRatingQuery::SerializeQuery() {
nlohmann::json output = { nlohmann::json output = {
{ "name", kQueryName }, { "name", kQueryName },
@ -73,7 +72,7 @@ std::string SetTrackRatingQuery::SerializeQuery() {
} }
std::string SetTrackRatingQuery::SerializeResult() { std::string SetTrackRatingQuery::SerializeResult() {
nlohmann::json output = { { "result", true } }; nlohmann::json output = { { "result", this->result } };
return output.dump(); return output.dump();
} }

View File

@ -57,6 +57,7 @@ namespace musik { namespace core { namespace library { namespace query {
int64_t trackId; int64_t trackId;
int rating; int rating;
bool result{ false };
}; };
} } } } } } } }

View File

@ -38,6 +38,9 @@
#include <core/db/Connection.h> #include <core/db/Connection.h>
#include <core/library/track/Track.h> #include <core/library/track/Track.h>
#include <core/library/track/TrackList.h> #include <core/library/track/TrackList.h>
#include <core/library/query/util/Serialization.h>
#include <json.hpp>
namespace musik { namespace core { namespace library { namespace query { namespace musik { namespace core { namespace library { namespace query {
@ -67,6 +70,9 @@ namespace musik { namespace core { namespace library { namespace query {
} }
protected: protected:
/* for IMetadataProxy */
std::string GetLimitAndOffset() { std::string GetLimitAndOffset() {
if (this->limit > 0 && this->offset >= 0) { if (this->limit > 0 && this->offset >= 0) {
return u8fmt("LIMIT %d OFFSET %d", this->limit, this->offset); return u8fmt("LIMIT %d OFFSET %d", this->limit, this->offset);
@ -74,6 +80,40 @@ namespace musik { namespace core { namespace library { namespace query {
return ""; return "";
} }
/* for ISerialization */
const std::string FinalizeSerializedQueryWithLimitAndOffset(nlohmann::json &output) {
auto& options = output["options"];
options["limit"] = this->limit;
options["offset"] = this->offset;
return output.dump();
}
void ExtractLimitAndOffsetFromDeserializedQuery(nlohmann::json& options) {
this->limit = options.value("limit", -1);
this->offset = options.value("offset", 0);
}
nlohmann::json InitializeSerializedResultWithHeadersAndTrackList() {
nlohmann::json output = {
{ "result", {
{ "headers", *this->GetHeaders() },
{ "trackList", serialization::TrackListToJson(*this->GetResult(), true) }
}}
};
return output;
}
void DeserializeTrackListAndHeaders(
nlohmann::json &result,
ILibraryPtr library,
Result tracks,
Headers headers)
{
serialization::TrackListFromJson(result["trackList"], *tracks, library, true);
serialization::JsonArrayToSet<std::set<size_t>, size_t>(result["headers"], *headers);
}
private: private:
int limit, offset; int limit, offset;

View File

@ -231,6 +231,14 @@ namespace musik { namespace core { namespace library { namespace query {
} }
} }
nlohmann::json ITrackListToJsonIdList(const ITrackList& input) {
nlohmann::json output;
for (size_t i = 0; i < input.Count(); i++) {
output.push_back(input.GetId(i));
}
return output;
}
} }
} } } } } } } }

View File

@ -86,6 +86,9 @@ namespace musik { namespace core { namespace library { namespace query {
musik::core::ILibraryPtr library, musik::core::ILibraryPtr library,
bool onlyIds); bool onlyIds);
nlohmann::json ITrackListToJsonIdList(
const musik::core::sdk::ITrackList& input);
template <typename SetType, typename DataType> template <typename SetType, typename DataType>
void JsonArrayToSet(const nlohmann::json& input, SetType& output) { void JsonArrayToSet(const nlohmann::json& input, SetType& output) {
for (auto& value : input) { for (auto& value : input) {