mirror of
https://github.com/clangen/musikcube.git
synced 2025-03-14 04:18:36 +00:00
Added proper playlist creation and replacing.
This commit is contained in:
parent
1f0139c5cd
commit
de859a7f7a
@ -48,19 +48,66 @@ static std::string CREATE_PLAYLIST_QUERY =
|
||||
static std::string INSERT_PLAYLIST_TRACK_QUERY =
|
||||
"INSERT INTO playlist_tracks (track_id, playlist_id, sort_order) VALUES (?, ?, ?);";
|
||||
|
||||
static std::string DELETE_PLAYLIST_TRACKS_QUERY =
|
||||
"DELETE FROM playlist_tracks WHERE playlist_id=?;";
|
||||
|
||||
std::shared_ptr<SavePlaylistQuery> SavePlaylistQuery::Save(
|
||||
const std::string& playlistName,
|
||||
std::shared_ptr<musik::core::TrackList> tracks)
|
||||
{
|
||||
return std::shared_ptr<SavePlaylistQuery>(
|
||||
new SavePlaylistQuery(playlistName, tracks));
|
||||
}
|
||||
|
||||
std::shared_ptr<SavePlaylistQuery> SavePlaylistQuery::Replace(
|
||||
const DBID playlistId,
|
||||
std::shared_ptr<musik::core::TrackList> tracks)
|
||||
{
|
||||
return std::shared_ptr<SavePlaylistQuery>(
|
||||
new SavePlaylistQuery(playlistId, tracks));
|
||||
}
|
||||
|
||||
SavePlaylistQuery::SavePlaylistQuery(
|
||||
const std::string& playlistName,
|
||||
std::shared_ptr<musik::core::TrackList> tracks)
|
||||
{
|
||||
this->playlistId = -1;
|
||||
this->playlistName = playlistName;
|
||||
this->tracks = tracks;
|
||||
}
|
||||
|
||||
SavePlaylistQuery::~SavePlaylistQuery() {
|
||||
|
||||
SavePlaylistQuery::SavePlaylistQuery(
|
||||
DBID playlistId,
|
||||
std::shared_ptr<musik::core::TrackList> tracks)
|
||||
{
|
||||
this->playlistId = playlistId;
|
||||
this->tracks = tracks;
|
||||
}
|
||||
|
||||
bool SavePlaylistQuery::OnRun(musik::core::db::Connection &db) {
|
||||
SavePlaylistQuery::~SavePlaylistQuery() {
|
||||
}
|
||||
|
||||
bool SavePlaylistQuery::AddTracksToPlaylist(musik::core::db::Connection &db, DBID playlistId) {
|
||||
Statement insertTrack(INSERT_PLAYLIST_TRACK_QUERY.c_str(), db);
|
||||
|
||||
TrackPtr track;
|
||||
TrackList& tracks = *this->tracks;
|
||||
for (size_t i = 0; i < tracks.Count(); i++) {
|
||||
track = tracks.Get(i);
|
||||
insertTrack.Reset();
|
||||
insertTrack.BindInt(0, track->Id());
|
||||
insertTrack.BindInt(1, playlistId);
|
||||
insertTrack.BindInt(2, (int) i);
|
||||
|
||||
if (insertTrack.Step() == db::Error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SavePlaylistQuery::CreatePlaylist(musik::core::db::Connection &db) {
|
||||
ScopedTransaction transaction(db);
|
||||
|
||||
/* create playlist */
|
||||
@ -75,21 +122,39 @@ bool SavePlaylistQuery::OnRun(musik::core::db::Connection &db) {
|
||||
DBID playlistId = db.LastInsertedId();
|
||||
|
||||
/* add tracks to playlist */
|
||||
Statement insertTrack(INSERT_PLAYLIST_TRACK_QUERY.c_str(), db);
|
||||
TrackList& tracks = *this->tracks;
|
||||
TrackPtr track;
|
||||
for (size_t i = 0; i < tracks.Count(); i++) {
|
||||
track = tracks.Get(i);
|
||||
insertTrack.Reset();
|
||||
insertTrack.BindInt(0, track->Id());
|
||||
insertTrack.BindInt(1, playlistId);
|
||||
insertTrack.BindInt(2, (int) i);
|
||||
|
||||
if (insertTrack.Step() == db::Error) {
|
||||
transaction.Cancel();
|
||||
return false;
|
||||
}
|
||||
if (!this->AddTracksToPlaylist(db, playlistId)) {
|
||||
transaction.Cancel();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SavePlaylistQuery::ReplacePlaylist(musik::core::db::Connection &db) {
|
||||
ScopedTransaction transaction(db);
|
||||
|
||||
/* delete existing tracks, we'll replace 'em */
|
||||
Statement createPlaylist(DELETE_PLAYLIST_TRACKS_QUERY.c_str(), db);
|
||||
createPlaylist.BindInt(0, this->playlistId);
|
||||
|
||||
if (createPlaylist.Step() == db::Error) {
|
||||
transaction.Cancel();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* add tracks to playlist */
|
||||
if (!this->AddTracksToPlaylist(db, playlistId)) {
|
||||
transaction.Cancel();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SavePlaylistQuery::OnRun(musik::core::db::Connection &db) {
|
||||
if (playlistId != -1) {
|
||||
return this->ReplacePlaylist(db);
|
||||
}
|
||||
|
||||
return this->CreatePlaylist(db);
|
||||
}
|
@ -43,10 +43,14 @@ namespace musik {
|
||||
namespace glue {
|
||||
class SavePlaylistQuery : public musik::core::query::QueryBase {
|
||||
public:
|
||||
SavePlaylistQuery(
|
||||
static std::shared_ptr<SavePlaylistQuery> Save(
|
||||
const std::string& playlistName,
|
||||
std::shared_ptr<musik::core::TrackList> tracks);
|
||||
|
||||
static std::shared_ptr<SavePlaylistQuery> Replace(
|
||||
const DBID playlistId,
|
||||
std::shared_ptr<musik::core::TrackList> tracks);
|
||||
|
||||
virtual std::string Name() { return "SavePlaylistQuery"; }
|
||||
|
||||
virtual ~SavePlaylistQuery();
|
||||
@ -54,7 +58,21 @@ namespace musik {
|
||||
protected:
|
||||
virtual bool OnRun(musik::core::db::Connection &db);
|
||||
|
||||
private:
|
||||
SavePlaylistQuery(
|
||||
const std::string& playlistName,
|
||||
std::shared_ptr<musik::core::TrackList> tracks);
|
||||
|
||||
SavePlaylistQuery(
|
||||
DBID playlistId,
|
||||
std::shared_ptr<musik::core::TrackList> tracks);
|
||||
|
||||
bool CreatePlaylist(musik::core::db::Connection &db);
|
||||
bool ReplacePlaylist(musik::core::db::Connection &db);
|
||||
bool AddTracksToPlaylist(musik::core::db::Connection &db, DBID playlistId);
|
||||
|
||||
std::string playlistName;
|
||||
DBID playlistId;
|
||||
std::shared_ptr<musik::core::TrackList> tracks;
|
||||
};
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <app/util/Hotkeys.h>
|
||||
#include <app/overlay/PlayQueueOverlays.h>
|
||||
#include <glue/query/NowPlayingTrackListQuery.h>
|
||||
#include <glue/query/GetPlaylistQuery.h>
|
||||
#include <glue/util/Duration.h>
|
||||
#include "NowPlayingLayout.h"
|
||||
|
||||
@ -67,7 +68,7 @@ NowPlayingLayout::NowPlayingLayout(
|
||||
, playback(playback)
|
||||
, library(library)
|
||||
, reselectIndex(-1)
|
||||
, lastPlaylistId(-1) {
|
||||
, lastPlaylistQueryId(-1) {
|
||||
this->InitializeWindows();
|
||||
this->playback.Shuffled.connect(this, &NowPlayingLayout::OnPlaybackShuffled);
|
||||
|
||||
@ -146,9 +147,9 @@ void NowPlayingLayout::OnTrackListRequeried(musik::glue::TrackListQueryBase* que
|
||||
/* if the requery just finished for a regular playlist, we need to
|
||||
make sure we load it into the PlaybackService. generally we just read
|
||||
FROM the playback service */
|
||||
if (query && query->GetId() == this->lastPlaylistId) {
|
||||
if (query && query->GetId() == this->lastPlaylistQueryId) {
|
||||
this->playback.CopyFrom(*query->GetResult());
|
||||
this->lastPlaylistId = -1;
|
||||
this->lastPlaylistQueryId = -1;
|
||||
}
|
||||
|
||||
if (playback.Count()) {
|
||||
@ -197,8 +198,11 @@ void NowPlayingLayout::RequeryTrackList() {
|
||||
new NowPlayingTrackListQuery(this->library, this->playback)));
|
||||
}
|
||||
|
||||
void NowPlayingLayout::OnPlaylistQueryStart(std::shared_ptr<musik::glue::TrackListQueryBase> query) {
|
||||
this->lastPlaylistId = query->GetId();
|
||||
void NowPlayingLayout::OnPlaylistSelected(DBID playlistId) {
|
||||
auto query = std::shared_ptr<GetPlaylistQuery>(
|
||||
new GetPlaylistQuery(library, playlistId));
|
||||
|
||||
this->lastPlaylistQueryId = query->GetId();
|
||||
this->trackListView->Requery(query);
|
||||
}
|
||||
|
||||
@ -214,7 +218,7 @@ bool NowPlayingLayout::KeyPress(const std::string& key) {
|
||||
PlayQueueOverlays::ShowLoadPlaylistOverlay(
|
||||
this->playback,
|
||||
this->library,
|
||||
std::bind(&NowPlayingLayout::OnPlaylistQueryStart, this, std::placeholders::_1));
|
||||
std::bind(&NowPlayingLayout::OnPlaylistSelected, this, std::placeholders::_1));
|
||||
return true;
|
||||
}
|
||||
else if (key == "M-s") {
|
||||
|
@ -76,13 +76,13 @@ namespace musik {
|
||||
void OnTrackListRequeried(musik::glue::TrackListQueryBase* query);
|
||||
void OnPlaybackShuffled(bool shuffled);
|
||||
int64 RowDecorator(musik::core::TrackPtr track, size_t index);
|
||||
void OnPlaylistQueryStart(std::shared_ptr<musik::glue::TrackListQueryBase> query);
|
||||
void OnPlaylistSelected(DBID playlistId);
|
||||
|
||||
musik::core::audio::PlaybackService& playback;
|
||||
musik::core::ILibraryPtr library;
|
||||
std::shared_ptr<TrackListView> trackListView;
|
||||
int reselectIndex; /* gross... */
|
||||
int lastPlaylistId;
|
||||
int lastPlaylistQueryId;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -67,6 +67,44 @@ static std::shared_ptr<Adapter> createAddToAdapter() {
|
||||
return adapter;
|
||||
}
|
||||
|
||||
static std::shared_ptr<CategoryListQuery> queryPlaylists(musik::core::ILibraryPtr library) {
|
||||
std::shared_ptr<CategoryListQuery> query(
|
||||
new CategoryListQuery(Playlists::TABLE_NAME, ""));
|
||||
|
||||
library->Enqueue(query, ILibrary::QuerySynchronous);
|
||||
if (query->GetStatus() != IQuery::Finished) {
|
||||
query.reset();
|
||||
return query;
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
static void addPlaylistsToAdapter(
|
||||
std::shared_ptr<Adapter> adapter, CategoryListQuery::ResultList result)
|
||||
{
|
||||
auto it = result->begin();
|
||||
while (it != result->end()) {
|
||||
adapter->AddEntry((*it)->displayValue);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
static void showPlaylistListOverlay(
|
||||
const std::string& title,
|
||||
std::shared_ptr<Adapter> adapter,
|
||||
ListOverlay::ItemSelectedCallback callback)
|
||||
{
|
||||
std::shared_ptr<ListOverlay> dialog(new ListOverlay());
|
||||
|
||||
dialog->SetAdapter(adapter)
|
||||
.SetTitle(title)
|
||||
.SetSelectedIndex(0)
|
||||
.SetItemSelectedCallback(callback);
|
||||
|
||||
cursespp::App::Overlays().Push(dialog);
|
||||
}
|
||||
|
||||
PlayQueueOverlays::PlayQueueOverlays() {
|
||||
}
|
||||
|
||||
@ -161,40 +199,40 @@ void PlayQueueOverlays::ShowAddCategoryOverlay(
|
||||
void PlayQueueOverlays::ShowLoadPlaylistOverlay(
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
musik::core::ILibraryPtr library,
|
||||
TrackListQueryCallback callback)
|
||||
PlaylistSelectedCallback callback)
|
||||
{
|
||||
std::shared_ptr<CategoryListQuery> query(
|
||||
new CategoryListQuery(Playlists::TABLE_NAME, ""));
|
||||
|
||||
library->Enqueue(query, ILibrary::QuerySynchronous);
|
||||
if (query->GetStatus() != IQuery::Finished) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<CategoryListQuery> query = queryPlaylists(library);
|
||||
auto result = query->GetResult();
|
||||
|
||||
std::shared_ptr<Adapter> adapter(new Adapter());
|
||||
adapter->SetSelectable(true);
|
||||
addPlaylistsToAdapter(adapter, result);
|
||||
|
||||
auto it = result->begin();
|
||||
while (it != result->end()) {
|
||||
adapter->AddEntry((*it)->displayValue);
|
||||
++it;
|
||||
}
|
||||
showPlaylistListOverlay(
|
||||
"load playlist",
|
||||
adapter,
|
||||
[library, result, callback]
|
||||
(cursespp::IScrollAdapterPtr adapter, size_t index) {
|
||||
if (index != ListWindow::NO_SELECTION && callback) {
|
||||
DBID playlistId = (*result)[index]->id;
|
||||
callback(playlistId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<ListOverlay> dialog(new ListOverlay());
|
||||
static void createNewPlaylist(
|
||||
std::shared_ptr<TrackList> tracks,
|
||||
musik::core::ILibraryPtr library)
|
||||
{
|
||||
std::shared_ptr<InputOverlay> dialog(new InputOverlay());
|
||||
|
||||
dialog->SetAdapter(adapter)
|
||||
.SetTitle("load playlist")
|
||||
.SetSelectedIndex(0)
|
||||
.SetItemSelectedCallback(
|
||||
[&playback, library, result, callback]
|
||||
(cursespp::IScrollAdapterPtr adapter, size_t index) {
|
||||
if (index != ListWindow::NO_SELECTION && callback) {
|
||||
DBID playlistId = (*result)[index]->id;
|
||||
|
||||
callback(std::shared_ptr<GetPlaylistQuery>(
|
||||
new GetPlaylistQuery(library, playlistId)));
|
||||
dialog->SetTitle("playlist name")
|
||||
.SetWidth(36)
|
||||
.SetText("")
|
||||
.SetInputAcceptedCallback(
|
||||
[tracks, library](const std::string& name) {
|
||||
if (name.size()) {
|
||||
library->Enqueue(SavePlaylistQuery::Save(name, tracks));
|
||||
}
|
||||
});
|
||||
|
||||
@ -205,23 +243,29 @@ void PlayQueueOverlays::ShowSavePlaylistOverlay(
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
musik::core::ILibraryPtr library)
|
||||
{
|
||||
std::shared_ptr<InputOverlay> dialog(new InputOverlay());
|
||||
std::shared_ptr<CategoryListQuery> query = queryPlaylists(library);
|
||||
auto result = query->GetResult();
|
||||
|
||||
dialog->SetTitle("playlist name")
|
||||
.SetWidth(36)
|
||||
.SetText("")
|
||||
.SetInputAcceptedCallback(
|
||||
[&playback, library](const std::string& name) {
|
||||
if (name.size()) {
|
||||
std::shared_ptr<TrackList> tracks(new TrackList(library));
|
||||
playback.CopyTo(*tracks);
|
||||
std::shared_ptr<Adapter> adapter(new Adapter());
|
||||
adapter->SetSelectable(true);
|
||||
adapter->AddEntry("new...");
|
||||
addPlaylistsToAdapter(adapter, result);
|
||||
|
||||
std::shared_ptr<SavePlaylistQuery>
|
||||
saveQuery(new SavePlaylistQuery(name, tracks));
|
||||
showPlaylistListOverlay(
|
||||
"save playlist",
|
||||
adapter,
|
||||
[&playback, library, result]
|
||||
(cursespp::IScrollAdapterPtr adapter, size_t index) {
|
||||
std::shared_ptr<TrackList> tracks(new TrackList(library));
|
||||
playback.CopyTo(*tracks);
|
||||
|
||||
library->Enqueue(saveQuery);
|
||||
}
|
||||
});
|
||||
|
||||
cursespp::App::Overlays().Push(dialog);
|
||||
if (index == 0) { /* create new */
|
||||
createNewPlaylist(tracks, library);
|
||||
}
|
||||
else { /* replace existing */
|
||||
--index;
|
||||
DBID playlistId = (*result)[index]->id;
|
||||
library->Enqueue(SavePlaylistQuery::Replace(playlistId, tracks));
|
||||
}
|
||||
});
|
||||
}
|
@ -43,8 +43,7 @@ namespace musik {
|
||||
namespace box {
|
||||
class PlayQueueOverlays {
|
||||
public:
|
||||
using TrackListQueryCallback =
|
||||
std::function<void(std::shared_ptr<musik::glue::TrackListQueryBase>)>;
|
||||
using PlaylistSelectedCallback = std::function<void(DBID)>;
|
||||
|
||||
static void ShowAddTrackOverlay(
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
@ -59,7 +58,7 @@ namespace musik {
|
||||
static void ShowLoadPlaylistOverlay(
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
musik::core::ILibraryPtr library,
|
||||
TrackListQueryCallback callback);
|
||||
PlaylistSelectedCallback callback);
|
||||
|
||||
static void ShowSavePlaylistOverlay(
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
|
Loading…
x
Reference in New Issue
Block a user