1 /* 2 * Strawberry Music Player 3 * This file was part of Clementine. 4 * Copyright 2010, David Sansome <me@davidsansome.com> 5 * Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net> 6 * 7 * Strawberry is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * Strawberry is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with Strawberry. If not, see <http://www.gnu.org/licenses/>. 19 * 20 */ 21 22 #ifndef PLAYLISTMANAGER_H 23 #define PLAYLISTMANAGER_H 24 25 #include "config.h" 26 27 #include <QtGlobal> 28 #include <QObject> 29 #include <QItemSelectionModel> 30 #include <QFuture> 31 #include <QList> 32 #include <QMap> 33 #include <QString> 34 #include <QUrl> 35 36 #include "core/song.h" 37 #include "playlist.h" 38 #include "smartplaylists/playlistgenerator.h" 39 40 class QModelIndex; 41 42 class Application; 43 class CollectionBackend; 44 class PlaylistBackend; 45 class PlaylistContainer; 46 class PlaylistParser; 47 class PlaylistSequence; 48 49 class PlaylistManagerInterface : public QObject { 50 Q_OBJECT 51 52 public: 53 explicit PlaylistManagerInterface(Application *app, QObject *parent) : QObject(parent) { Q_UNUSED(app); } 54 55 virtual int current_id() const = 0; 56 virtual int active_id() const = 0; 57 58 virtual Playlist *playlist(const int id) const = 0; 59 virtual Playlist *current() const = 0; 60 virtual Playlist *active() const = 0; 61 62 // Returns the collection of playlists managed by this PlaylistManager. 63 virtual QList<Playlist*> GetAllPlaylists() const = 0; 64 // Grays out and reloads all deleted songs in all playlists. 65 virtual void InvalidateDeletedSongs() = 0; 66 // Removes all deleted songs from all playlists. 67 virtual void RemoveDeletedSongs() = 0; 68 69 virtual QItemSelection selection(const int id) const = 0; 70 virtual QItemSelection current_selection() const = 0; 71 virtual QItemSelection active_selection() const = 0; 72 73 virtual QString GetPlaylistName(const int index) const = 0; 74 75 virtual CollectionBackend *collection_backend() const = 0; 76 virtual PlaylistBackend *playlist_backend() const = 0; 77 virtual PlaylistSequence *sequence() const = 0; 78 virtual PlaylistParser *parser() const = 0; 79 virtual PlaylistContainer *playlist_container() const = 0; 80 81 virtual void PlaySmartPlaylist(PlaylistGeneratorPtr generator, const bool as_new, const bool clear) = 0; 82 83 public slots: 84 virtual void New(const QString &name, const SongList &songs = SongList(), const QString &special_type = QString()) = 0; 85 virtual void Load(const QString &filename) = 0; 86 virtual void Save(const int id, const QString &filename, const Playlist::Path path_type) = 0; 87 virtual void Rename(const int id, const QString &new_name) = 0; 88 virtual void Delete(const int id) = 0; 89 virtual bool Close(const int id) = 0; 90 virtual void Open(const int id) = 0; 91 virtual void ChangePlaylistOrder(const QList<int> &ids) = 0; 92 93 virtual void SongChangeRequestProcessed(const QUrl &url, const bool valid) = 0; 94 95 virtual void SetCurrentPlaylist(const int id) = 0; 96 virtual void SetActivePlaylist(const int id) = 0; 97 virtual void SetActiveToCurrent() = 0; 98 99 virtual void SelectionChanged(const QItemSelection &selection) = 0; 100 101 // Convenience slots that defer to either current() or active() 102 virtual void ClearCurrent() = 0; 103 virtual void ShuffleCurrent() = 0; 104 virtual void RemoveDuplicatesCurrent() = 0; 105 virtual void RemoveUnavailableCurrent() = 0; 106 virtual void SetActivePlaying() = 0; 107 virtual void SetActivePaused() = 0; 108 virtual void SetActiveStopped() = 0; 109 110 // Rate current song using 0.0 - 1.0 scale. 111 virtual void RateCurrentSong(const double rating) = 0; 112 // Rate current song using 0 - 5 scale. 113 virtual void RateCurrentSong(const int rating) = 0; 114 115 signals: 116 void PlaylistManagerInitialized(); 117 void AllPlaylistsLoaded(); 118 119 void PlaylistAdded(int id, QString name, bool favorite); 120 void PlaylistDeleted(int id); 121 void PlaylistClosed(int id); 122 void PlaylistRenamed(int id, QString new_name); 123 void PlaylistFavorited(int id, bool favorite); 124 void CurrentChanged(Playlist *new_playlist, int scroll_position = 0); 125 void ActiveChanged(Playlist *new_playlist); 126 127 void Error(QString message); 128 void SummaryTextChanged(QString summary); 129 130 // Forwarded from individual playlists 131 void CurrentSongChanged(Song song); 132 void SongMetadataChanged(Song song); 133 134 // Signals that one of manager's playlists has changed (new items, new ordering etc.) - the argument shows which. 135 void PlaylistChanged(Playlist *playlist); 136 void EditingFinished(int playlist_id, QModelIndex idx); 137 void PlayRequested(QModelIndex idx, Playlist::AutoScroll autoscroll); 138 }; 139 140 class PlaylistManager : public PlaylistManagerInterface { 141 Q_OBJECT 142 143 public: 144 explicit PlaylistManager(Application *app, QObject *parent = nullptr); 145 ~PlaylistManager() override; 146 147 int current_id() const override { return current_; } 148 int active_id() const override { return active_; } 149 150 Playlist *playlist(const int id) const override { return playlists_[id].p; } 151 Playlist *current() const override { return playlist(current_id()); } 152 Playlist *active() const override { return playlist(active_id()); } 153 154 // Returns the collection of playlists managed by this PlaylistManager. 155 QList<Playlist*> GetAllPlaylists() const override; 156 // Grays out and reloads all deleted songs in all playlists. 157 void InvalidateDeletedSongs() override; 158 // Removes all deleted songs from all playlists. 159 void RemoveDeletedSongs() override; 160 // Returns true if the playlist is open 161 bool IsPlaylistOpen(const int id); 162 163 // Returns a pretty automatic name for playlist created from the given list of songs. 164 static QString GetNameForNewPlaylist(const SongList &songs); 165 166 QItemSelection selection(const int id) const override; 167 QItemSelection current_selection() const override { return selection(current_id()); } 168 QItemSelection active_selection() const override { return selection(active_id()); } 169 170 QString GetPlaylistName(const int index) const override { return playlists_[index].name; } 171 bool IsPlaylistFavorite(const int index) const { return playlists_[index].p->is_favorite(); } 172 173 void Init(CollectionBackend *collection_backend, PlaylistBackend *playlist_backend, PlaylistSequence *sequence, PlaylistContainer *playlist_container); 174 175 CollectionBackend *collection_backend() const override { return collection_backend_; } 176 PlaylistBackend *playlist_backend() const override { return playlist_backend_; } 177 PlaylistSequence *sequence() const override { return sequence_; } 178 PlaylistParser *parser() const override { return parser_; } 179 PlaylistContainer *playlist_container() const override { return playlist_container_; } 180 181 public slots: 182 void New(const QString &name, const SongList &songs = SongList(), const QString &special_type = QString()) override; 183 void Load(const QString &filename) override; 184 void Save(const int id, const QString &filename, const Playlist::Path path_type) override; 185 // Display a file dialog to let user choose a file before saving the file 186 void SaveWithUI(const int id, const QString &playlist_name); 187 void Rename(const int id, const QString &new_name) override; 188 void Favorite(const int id, bool favorite); 189 void Delete(const int id) override; 190 bool Close(const int id) override; 191 void Open(const int id) override; 192 void ChangePlaylistOrder(const QList<int> &ids) override; 193 194 void SetCurrentPlaylist(const int id) override; 195 void SetActivePlaylist(const int id) override; 196 void SetActiveToCurrent() override; 197 198 void SelectionChanged(const QItemSelection &selection) override; 199 200 // Makes a playlist current if it's open already, or opens it and makes it current if it is hidden. 201 void SetCurrentOrOpen(const int id); 202 203 // Convenience slots that defer to either current() or active() 204 void ClearCurrent() override; 205 void ShuffleCurrent() override; 206 void RemoveDuplicatesCurrent() override; 207 void RemoveUnavailableCurrent() override; 208 209 void SongChangeRequestProcessed(const QUrl &url, const bool valid) override; 210 211 void InsertUrls(const int id, const QList<QUrl> &urls, const int pos = -1, const bool play_now = false, const bool enqueue = false); 212 void InsertSongs(const int id, const SongList &songs, const int pos = -1, const bool play_now = false, const bool enqueue = false); 213 // Removes items with given indices from the playlist. This operation is not undoable. 214 void RemoveItemsWithoutUndo(const int id, const QList<int> &indices); 215 // Remove the current playing song 216 void RemoveCurrentSong() const; 217 218 void PlaySmartPlaylist(PlaylistGeneratorPtr generator, const bool as_new, const bool clear) override; 219 220 // Rate current song using 0.0 - 1.0 scale. 221 void RateCurrentSong(const double rating) override; 222 // Rate current song using 0 - 5 scale. 223 void RateCurrentSong(const int rating) override; 224 225 private slots: 226 void SetActivePlaying() override; 227 void SetActivePaused() override; 228 void SetActiveStopped() override; 229 230 void OneOfPlaylistsChanged(); 231 void UpdateSummaryText(); 232 void SongsDiscovered(const SongList &songs); 233 void ItemsLoadedForSavePlaylist(const SongList &songs, const QString &filename, const Playlist::Path path_type); 234 void PlaylistLoaded(); 235 236 private: 237 Playlist *AddPlaylist(const int id, const QString &name, const QString &special_type, const QString &ui_path, const bool favorite); 238 239 private: 240 struct Data { 241 explicit Data(Playlist *_p = nullptr, const QString &_name = QString()) : p(_p), name(_name), scroll_position(0) {} 242 Playlist *p; 243 QString name; 244 QItemSelection selection; 245 int scroll_position; 246 }; 247 248 Application *app_; 249 PlaylistBackend *playlist_backend_; 250 CollectionBackend *collection_backend_; 251 PlaylistSequence *sequence_; 252 PlaylistParser *parser_; 253 PlaylistContainer *playlist_container_; 254 255 // key = id 256 QMap<int, Data> playlists_; 257 258 int current_; 259 int active_; 260 int playlists_loading_; 261 }; 262 263 #endif // PLAYLISTMANAGER_H 264