diff --git a/data/data.qrc b/data/data.qrc index 549ebafd9..39cac4902 100644 --- a/data/data.qrc +++ b/data/data.qrc @@ -286,5 +286,6 @@ icons/48x48/folder.png smartplaylistsearchterm.css schema/schema-19.sql + schema/schema-20.sql diff --git a/src/core/database.cpp b/src/core/database.cpp index 033c74cb3..20b8c682f 100644 --- a/src/core/database.cpp +++ b/src/core/database.cpp @@ -30,7 +30,7 @@ #include const char* Database::kDatabaseFilename = "clementine.db"; -const int Database::kSchemaVersion = 19; +const int Database::kSchemaVersion = 20; const char* Database::kMagicAllSongsTables = "%allsongstables"; int Database::sNextConnectionId = 1; diff --git a/src/main.cpp b/src/main.cpp index 0721d1e1b..99971f3c6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,6 +32,7 @@ #include "engines/enginebase.h" #include "library/directory.h" #include "radio/lastfmservice.h" +#include "smartplaylists/generator.h" #include "ui/equalizer.h" #include "ui/iconloader.h" #include "ui/mainwindow.h" @@ -126,6 +127,7 @@ int main(int argc, char *argv[]) { qRegisterMetaType("const char*"); qRegisterMetaType("QNetworkReply*"); qRegisterMetaType("QNetworkReply**"); + qRegisterMetaType("smart_playlists::GeneratorPtr"); #ifdef HAVE_GSTREAMER qRegisterMetaType("GstBuffer*"); diff --git a/src/playlist/playlist.cpp b/src/playlist/playlist.cpp index c77390910..ddddca1cd 100644 --- a/src/playlist/playlist.cpp +++ b/src/playlist/playlist.cpp @@ -52,6 +52,7 @@ #include +using smart_playlists::Generator; using smart_playlists::GeneratorInserter; using smart_playlists::GeneratorPtr; @@ -640,13 +641,18 @@ void Playlist::InsertSmartPlaylist(GeneratorPtr generator, int pos, bool play_no inserter->Load(this, pos, play_now, generator); if (generator->is_dynamic()) { - dynamic_playlist_ = generator; - playlist_sequence_->SetUsingDynamicPlaylist(true); - ShuffleModeChanged(PlaylistSequence::Shuffle_Off); - emit DynamicModeChanged(true); + TurnOnDynamicPlaylist(generator); } } +void Playlist::TurnOnDynamicPlaylist(GeneratorPtr gen) { + dynamic_playlist_ = gen; + playlist_sequence_->SetUsingDynamicPlaylist(true); + ShuffleModeChanged(PlaylistSequence::Shuffle_Off); + emit DynamicModeChanged(true); + Save(); +} + void Playlist::MoveItemsWithoutUndo(const QList &source_rows, int pos) { layoutAboutToBeChanged(); PlaylistItemList moved_items; @@ -991,7 +997,7 @@ void Playlist::Save() const { if (!backend_) return; - backend_->SavePlaylistAsync(id_, items_, last_played_index()); + backend_->SavePlaylistAsync(id_, items_, last_played_index(), dynamic_playlist_); } namespace { @@ -1023,6 +1029,15 @@ void Playlist::ItemsLoaded() { last_played_item_index_ = p.last_played == -1 ? QModelIndex() : index(p.last_played); + + if (!p.dynamic_type.isEmpty()) { + GeneratorPtr gen = Generator::Create(p.dynamic_type); + if (gen) { + gen->set_library(library_); + gen->Load(p.dynamic_data); + TurnOnDynamicPlaylist(gen); + } + } } bool Playlist::removeRows(int row, int count, const QModelIndex& parent) { @@ -1161,6 +1176,7 @@ void Playlist::TurnOffDynamicPlaylist() { ShuffleModeChanged(playlist_sequence_->shuffle_mode()); } emit DynamicModeChanged(false); + Save(); } void Playlist::RepopulateDynamicPlaylist() { diff --git a/src/playlist/playlist.h b/src/playlist/playlist.h index 7cd7fa2d6..1e44fc085 100644 --- a/src/playlist/playlist.h +++ b/src/playlist/playlist.h @@ -208,6 +208,7 @@ class Playlist : public QAbstractListModel { int NextVirtualIndex(int i) const; int PreviousVirtualIndex(int i) const; bool FilterContainsVirtualIndex(int i) const; + void TurnOnDynamicPlaylist(smart_playlists::GeneratorPtr gen); // Modify the playlist without changing the undo stack. These are used by // our friends in PlaylistUndoCommands diff --git a/src/playlist/playlistbackend.cpp b/src/playlist/playlistbackend.cpp index e5e20eb0b..52b981ae7 100644 --- a/src/playlist/playlistbackend.cpp +++ b/src/playlist/playlistbackend.cpp @@ -20,11 +20,14 @@ #include "core/scopedtransaction.h" #include "core/song.h" #include "library/sqlrow.h" +#include "smartplaylists/generator.h" #include #include #include +using smart_playlists::GeneratorPtr; + using boost::shared_ptr; PlaylistBackend::PlaylistBackend(QObject* parent) @@ -58,7 +61,9 @@ PlaylistBackend::Playlist PlaylistBackend::GetPlaylist(int id) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("SELECT ROWID, name, last_played FROM playlists" + QSqlQuery q("SELECT ROWID, name, last_played, dynamic_playlist_type," + " dynamic_playlist_data" + " FROM playlists" " WHERE ROWID=:id", db); q.bindValue(":id", id); q.exec(); @@ -71,6 +76,8 @@ PlaylistBackend::Playlist PlaylistBackend::GetPlaylist(int id) { p.id = q.value(0).toInt(); p.name = q.value(1).toString(); p.last_played = q.value(2).toInt(); + p.dynamic_type = q.value(3).toString(); + p.dynamic_data = q.value(4).toByteArray(); return p; } @@ -118,15 +125,16 @@ PlaylistItemPtr PlaylistBackend::NewSongFromQuery(const SqlRow& row) { } void PlaylistBackend::SavePlaylistAsync(int playlist, const PlaylistItemList &items, - int last_played) { + int last_played, GeneratorPtr dynamic) { metaObject()->invokeMethod(this, "SavePlaylist", Qt::QueuedConnection, Q_ARG(int, playlist), Q_ARG(PlaylistItemList, items), - Q_ARG(int, last_played)); + Q_ARG(int, last_played), + Q_ARG(smart_playlists::GeneratorPtr, dynamic)); } void PlaylistBackend::SavePlaylist(int playlist, const PlaylistItemList& items, - int last_played) { + int last_played, GeneratorPtr dynamic) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); @@ -135,7 +143,10 @@ void PlaylistBackend::SavePlaylist(int playlist, const PlaylistItemList& items, " (playlist, type, library_id, url, title, artist, album," " length, radio_service)" " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", db); - QSqlQuery update("UPDATE playlists SET last_played=:last_played" + QSqlQuery update("UPDATE playlists SET " + " last_played=:last_played," + " dynamic_playlist_type=:dynamic_type," + " dynamic_playlist_data=:dynamic_data" " WHERE ROWID=:playlist", db); ScopedTransaction transaction(&db); @@ -157,7 +168,14 @@ void PlaylistBackend::SavePlaylist(int playlist, const PlaylistItemList& items, // Update the last played track number update.bindValue(":last_played", last_played); - update.bindValue(":id", playlist); + if (dynamic) { + update.bindValue(":dynamic_type", dynamic->type()); + update.bindValue(":dynamic_data", dynamic->Save()); + } else { + update.bindValue(":dynamic_type", QString()); + update.bindValue(":dynamic_data", QByteArray()); + } + update.bindValue(":playlist", playlist); update.exec(); if (db_->CheckErrors(update.lastError())) return; diff --git a/src/playlist/playlistbackend.h b/src/playlist/playlistbackend.h index b0fb27f30..c82b8ac17 100644 --- a/src/playlist/playlistbackend.h +++ b/src/playlist/playlistbackend.h @@ -23,6 +23,7 @@ #include #include "playlistitem.h" +#include "smartplaylists/generator_fwd.h" #include @@ -39,6 +40,8 @@ class PlaylistBackend : public QObject { int id; QString name; int last_played; + QString dynamic_type; + QByteArray dynamic_data; }; typedef QList PlaylistList; typedef QFuture PlaylistItemFuture; @@ -47,7 +50,7 @@ class PlaylistBackend : public QObject { Playlist GetPlaylist(int id); PlaylistItemFuture GetPlaylistItems(int playlist); void SavePlaylistAsync(int playlist, const PlaylistItemList& items, - int last_played); + int last_played, smart_playlists::GeneratorPtr dynamic); void SetPlaylistOrder(const QList& ids); int CreatePlaylist(const QString& name); @@ -55,7 +58,8 @@ class PlaylistBackend : public QObject { void RenamePlaylist(int id, const QString& new_name); public slots: - void SavePlaylist(int playlist, const PlaylistItemList& items, int last_played); + void SavePlaylist(int playlist, const PlaylistItemList& items, + int last_played, smart_playlists::GeneratorPtr dynamic); private: static PlaylistItemPtr NewSongFromQuery(const SqlRow& row);