mirror of
https://github.com/clangen/musikcube.git
synced 2025-03-29 19:20:28 +00:00
Added the ability to create playlists via ISimpleDataProvider using both
stable (external) ids, and non-stable ids.
This commit is contained in:
parent
acd5a94c10
commit
41c4f9bbf1
@ -49,7 +49,6 @@
|
||||
#include <core/library/track/RetainedTrack.h>
|
||||
#include <core/library/LocalLibraryConstants.h>
|
||||
|
||||
|
||||
#define TAG "LocalSimpleDataProvider"
|
||||
|
||||
using namespace musik::core;
|
||||
@ -58,6 +57,59 @@ using namespace musik::core::db::local;
|
||||
using namespace musik::core::library;
|
||||
using namespace musik::core::sdk;
|
||||
|
||||
class ExternalIdListToTrackListQuery : public LocalQueryBase {
|
||||
public:
|
||||
ExternalIdListToTrackListQuery(
|
||||
ILibraryPtr library,
|
||||
const char** externalIds,
|
||||
size_t externalIdCount)
|
||||
{
|
||||
this->library = library;
|
||||
this->externalIds = externalIds;
|
||||
this->externalIdCount = externalIdCount;
|
||||
}
|
||||
|
||||
virtual ~ExternalIdListToTrackListQuery() {
|
||||
}
|
||||
|
||||
std::shared_ptr<TrackList> Result() {
|
||||
return this->result;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool OnRun(musik::core::db::Connection& db) {
|
||||
std::string sql = "SELECT id FROM tracks WHERE external_id IN(";
|
||||
for (size_t i = 0; i < externalIdCount; i++) {
|
||||
sql += (i == 0) ? "?" : ",?";
|
||||
}
|
||||
sql += ");";
|
||||
|
||||
Statement query(sql.c_str(), db);
|
||||
|
||||
for (size_t i = 0; i < externalIdCount; i++) {
|
||||
query.BindText(i, externalIds[i]);
|
||||
}
|
||||
|
||||
this->result = std::make_shared<TrackList>(this->library);
|
||||
|
||||
while (query.Step() == Row) {
|
||||
result->Add(query.ColumnInt64(0));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual std::string Name() {
|
||||
return "ExternalIdListToTrackListQuery";
|
||||
}
|
||||
|
||||
private:
|
||||
ILibraryPtr library;
|
||||
const char** externalIds;
|
||||
size_t externalIdCount;
|
||||
std::shared_ptr<TrackList> result;
|
||||
};
|
||||
|
||||
LocalSimpleDataProvider::LocalSimpleDataProvider(musik::core::ILibraryPtr library)
|
||||
: library(library) {
|
||||
|
||||
@ -213,32 +265,25 @@ IMetadataMapList* LocalSimpleDataProvider::QueryAlbums(const char* filter) {
|
||||
return this->QueryAlbums(nullptr, -1, filter);
|
||||
}
|
||||
|
||||
uint64_t LocalSimpleDataProvider::SavePlaylist(
|
||||
int64_t trackIds[],
|
||||
size_t trackIdCount,
|
||||
const char* name,
|
||||
static uint64_t savePlaylist(
|
||||
ILibraryPtr library,
|
||||
std::shared_ptr<TrackList> trackList,
|
||||
const char* playlistName,
|
||||
const uint64_t playlistId)
|
||||
{
|
||||
if (playlistId == 0 && (!name || !strlen(name))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
std::shared_ptr<TrackList> sharedTrackList =
|
||||
std::make_shared<TrackList>(this->library, trackIds, trackIdCount);
|
||||
|
||||
/* replacing (and optionally renaming) an existing playlist */
|
||||
if (playlistId != 0) {
|
||||
std::shared_ptr<SavePlaylistQuery> query =
|
||||
SavePlaylistQuery::Replace(playlistId, sharedTrackList);
|
||||
SavePlaylistQuery::Replace(playlistId, trackList);
|
||||
|
||||
this->library->Enqueue(query, ILibrary::QuerySynchronous);
|
||||
library->Enqueue(query, ILibrary::QuerySynchronous);
|
||||
|
||||
if (query->GetStatus() == IQuery::Finished) {
|
||||
if (strlen(name)) {
|
||||
query = SavePlaylistQuery::Rename(playlistId, name);
|
||||
if (strlen(playlistName)) {
|
||||
query = SavePlaylistQuery::Rename(playlistId, playlistName);
|
||||
|
||||
this->library->Enqueue(query, ILibrary::QuerySynchronous);
|
||||
library->Enqueue(query, ILibrary::QuerySynchronous);
|
||||
|
||||
if (query->GetStatus() == IQuery::Finished) {
|
||||
return playlistId;
|
||||
@ -251,9 +296,9 @@ uint64_t LocalSimpleDataProvider::SavePlaylist(
|
||||
}
|
||||
else {
|
||||
std::shared_ptr<SavePlaylistQuery> query =
|
||||
SavePlaylistQuery::Save(name, sharedTrackList);
|
||||
SavePlaylistQuery::Save(playlistName, trackList);
|
||||
|
||||
this->library->Enqueue(query, ILibrary::QuerySynchronous);
|
||||
library->Enqueue(query, ILibrary::QuerySynchronous);
|
||||
|
||||
if (query->GetStatus() == IQuery::Finished) {
|
||||
return query->GetPlaylistId();
|
||||
@ -267,6 +312,46 @@ uint64_t LocalSimpleDataProvider::SavePlaylist(
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t LocalSimpleDataProvider::SavePlaylistWithIds(
|
||||
int64_t* trackIds,
|
||||
size_t trackIdCount,
|
||||
const char* playlistName,
|
||||
const uint64_t playlistId)
|
||||
{
|
||||
if (playlistId == 0 && (!playlistName || !strlen(playlistName))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<TrackList> trackList =
|
||||
std::make_shared<TrackList>(this->library, trackIds, trackIdCount);
|
||||
|
||||
return savePlaylist(this->library, trackList, playlistName, playlistId);
|
||||
}
|
||||
|
||||
uint64_t LocalSimpleDataProvider::SavePlaylistWithExternalIds(
|
||||
const char** externalIds,
|
||||
size_t externalIdCount,
|
||||
const char* playlistName,
|
||||
const uint64_t playlistId)
|
||||
{
|
||||
if (playlistId == 0 && (!playlistName || !strlen(playlistName))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
using Query = ExternalIdListToTrackListQuery;
|
||||
|
||||
std::shared_ptr<Query> query =
|
||||
std::make_shared<Query> (this->library, externalIds, externalIdCount);
|
||||
|
||||
library->Enqueue(query, ILibrary::QuerySynchronous);
|
||||
|
||||
if (query->GetStatus() == IQuery::Finished) {
|
||||
return savePlaylist(this->library, query->Result(), playlistName, playlistId);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool LocalSimpleDataProvider::RenamePlaylist(const uint64_t playlistId, const char* name)
|
||||
{
|
||||
try {
|
||||
|
@ -78,12 +78,18 @@ namespace musik { namespace core { namespace db { namespace local {
|
||||
int64_t categoryIdValue,
|
||||
const char* filter = "") override;
|
||||
|
||||
virtual uint64_t SavePlaylist(
|
||||
int64_t trackIds[],
|
||||
virtual uint64_t SavePlaylistWithIds(
|
||||
int64_t* trackIds,
|
||||
size_t trackIdCount,
|
||||
const char* name,
|
||||
const uint64_t playlistId = 0) override;
|
||||
|
||||
virtual uint64_t SavePlaylistWithExternalIds(
|
||||
const char** externalIds,
|
||||
size_t externalIdCount,
|
||||
const char* playlistName,
|
||||
const uint64_t playlistId = 0) override;
|
||||
|
||||
virtual bool RenamePlaylist(
|
||||
const uint64_t playlistId,
|
||||
const char* name) override;
|
||||
|
@ -70,12 +70,18 @@ namespace musik { namespace core { namespace sdk {
|
||||
int64_t categoryIdValue,
|
||||
const char* filter = "") = 0;
|
||||
|
||||
virtual uint64_t SavePlaylist(
|
||||
int64_t trackIds[],
|
||||
virtual uint64_t SavePlaylistWithIds(
|
||||
int64_t* trackIds,
|
||||
size_t trackIdCount,
|
||||
const char* playlistName,
|
||||
const uint64_t playlistId = 0) = 0;
|
||||
|
||||
virtual uint64_t SavePlaylistWithExternalIds(
|
||||
const char** externalIds,
|
||||
size_t externalIdCount,
|
||||
const char* playlistName,
|
||||
const uint64_t playlistId = 0) = 0;
|
||||
|
||||
virtual bool RenamePlaylist(
|
||||
const uint64_t playlistId,
|
||||
const char* playlistName) = 0;
|
||||
|
@ -80,6 +80,7 @@ namespace key {
|
||||
static const std::string playing_track = "playing_track";
|
||||
static const std::string title = "title";
|
||||
static const std::string external_id = "external_id";
|
||||
static const std::string external_ids = "external_ids";
|
||||
static const std::string filename = "filename";
|
||||
static const std::string duration = "duration";
|
||||
static const std::string artist = "artist";
|
||||
|
@ -785,32 +785,79 @@ void WebSocketServer::RespondWithCurrentTime(connection_hdl connection, json& re
|
||||
void WebSocketServer::RespondWithSavePlaylist(connection_hdl connection, json& request) {
|
||||
auto& options = request[message::options];
|
||||
|
||||
json& ids = options[key::ids];
|
||||
if (ids.is_array()) {
|
||||
int64_t id = options.value(key::playlist_id, 0);
|
||||
std::string name = options.value(key::playlist_name, "");
|
||||
/* by int64 id (faster, but less reliable) */
|
||||
if (options.find(key::ids) != options.end()) {
|
||||
json& ids = options[key::ids];
|
||||
|
||||
size_t count = ids.size();
|
||||
int64_t* idArray = new int64_t[count];
|
||||
if (ids.is_array()) {
|
||||
int64_t id = options.value(key::playlist_id, 0);
|
||||
std::string name = options.value(key::playlist_name, "");
|
||||
|
||||
if (count > 0) {
|
||||
std::copy(ids.begin(), ids.end(), idArray);
|
||||
}
|
||||
size_t count = ids.size();
|
||||
int64_t* idArray = new int64_t[count];
|
||||
|
||||
uint64_t newPlaylistId = this->context.dataProvider
|
||||
->SavePlaylist(idArray, count, name.c_str(), id);
|
||||
if (count > 0) {
|
||||
std::copy(ids.begin(), ids.end(), idArray);
|
||||
}
|
||||
|
||||
delete[] idArray;
|
||||
uint64_t newPlaylistId = this->context.dataProvider
|
||||
->SavePlaylistWithIds(idArray, count, name.c_str(), id);
|
||||
|
||||
if (newPlaylistId != 0) {
|
||||
this->RespondWithOptions(connection, request, {
|
||||
{ key::playlist_id, newPlaylistId }
|
||||
});
|
||||
}
|
||||
else {
|
||||
this->RespondWithFailure(connection, request);
|
||||
delete[] idArray;
|
||||
|
||||
if (newPlaylistId != 0) {
|
||||
this->RespondWithOptions(connection, request, {
|
||||
{ key::playlist_id, newPlaylistId }
|
||||
});
|
||||
}
|
||||
else {
|
||||
this->RespondWithFailure(connection, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* by external id (slower, more reliable) */
|
||||
else if (options.find(key::external_ids) != options.end()) {
|
||||
json& externalIds = options[key::external_ids];
|
||||
|
||||
if (externalIds.is_array()) {
|
||||
int64_t id = options.value(key::playlist_id, 0);
|
||||
std::string name = options.value(key::playlist_name, "");
|
||||
|
||||
size_t count = externalIds.size();
|
||||
char** externalIdArray = (char**) malloc(count * sizeof(char*));
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
std::string externalId = externalIds[i];
|
||||
size_t size = externalId.size();
|
||||
externalIdArray[i] = (char*) malloc(size + 1);
|
||||
strncpy(externalIdArray[i], externalId.c_str(), size);
|
||||
externalIdArray[i][size] = 0;
|
||||
}
|
||||
|
||||
uint64_t newPlaylistId = this->context.dataProvider
|
||||
->SavePlaylistWithExternalIds(
|
||||
(const char**) externalIdArray,
|
||||
count,
|
||||
name.c_str(),
|
||||
id);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
free(externalIdArray[i]);
|
||||
}
|
||||
|
||||
free(externalIdArray);
|
||||
|
||||
if (newPlaylistId != 0) {
|
||||
this->RespondWithOptions(connection, request, {
|
||||
{ key::playlist_id, newPlaylistId }
|
||||
});
|
||||
}
|
||||
else {
|
||||
this->RespondWithFailure(connection, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* no id list or external id list */
|
||||
else {
|
||||
this->RespondWithInvalidRequest(
|
||||
connection, request[message::name], request[message::id]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user