2010-03-24 00:11:46 +01:00
|
|
|
/* This file is part of Clementine.
|
2010-11-20 14:27:10 +01:00
|
|
|
Copyright 2010, David Sansome <me@davidsansome.com>
|
2010-03-24 00:11:46 +01:00
|
|
|
|
|
|
|
Clementine is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Clementine is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
#ifndef PLAYLIST_H
|
|
|
|
#define PLAYLIST_H
|
|
|
|
|
|
|
|
#include <QAbstractItemModel>
|
|
|
|
#include <QList>
|
|
|
|
|
2020-09-18 16:15:19 +02:00
|
|
|
#include "core/song.h"
|
|
|
|
#include "core/tagreaderclient.h"
|
2009-12-24 20:16:07 +01:00
|
|
|
#include "playlistitem.h"
|
2010-03-08 19:05:41 +01:00
|
|
|
#include "playlistsequence.h"
|
2010-11-18 21:19:33 +01:00
|
|
|
#include "smartplaylists/generator_fwd.h"
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2010-08-31 21:45:33 +02:00
|
|
|
class LibraryBackend;
|
2010-05-09 02:10:26 +02:00
|
|
|
class PlaylistBackend;
|
2010-05-22 18:36:13 +02:00
|
|
|
class PlaylistFilter;
|
2010-07-11 17:37:40 +02:00
|
|
|
class Queue;
|
2011-07-15 15:27:50 +02:00
|
|
|
class InternetModel;
|
2011-11-06 16:12:44 +01:00
|
|
|
class InternetService;
|
2010-06-23 15:21:30 +02:00
|
|
|
class TaskManager;
|
2009-12-26 22:35:45 +01:00
|
|
|
|
2010-05-22 18:36:13 +02:00
|
|
|
class QSortFilterProxyModel;
|
2010-04-19 20:44:35 +02:00
|
|
|
class QUndoStack;
|
2018-10-08 17:24:36 +02:00
|
|
|
class QStringList;
|
2010-04-19 20:44:35 +02:00
|
|
|
|
|
|
|
namespace PlaylistUndoCommands {
|
2014-02-07 16:34:20 +01:00
|
|
|
class InsertItems;
|
|
|
|
class RemoveItems;
|
|
|
|
class MoveItems;
|
|
|
|
class ReOrderItems;
|
|
|
|
class SortItems;
|
|
|
|
class ShuffleItems;
|
2020-09-18 16:15:19 +02:00
|
|
|
} // namespace PlaylistUndoCommands
|
2010-04-19 20:44:35 +02:00
|
|
|
|
2010-12-22 11:45:14 +01:00
|
|
|
typedef QMap<int, Qt::Alignment> ColumnAlignmentMap;
|
2019-11-10 00:30:18 +01:00
|
|
|
Q_DECLARE_METATYPE(Qt::Alignment)
|
|
|
|
Q_DECLARE_METATYPE(ColumnAlignmentMap)
|
2010-12-22 11:45:14 +01:00
|
|
|
|
2011-01-17 00:46:58 +01:00
|
|
|
// Objects that may prevent a song being added to the playlist. When there
|
|
|
|
// is something about to be inserted into it, Playlist notifies all of it's
|
|
|
|
// listeners about the fact and every one of them picks 'invalid' songs.
|
|
|
|
class SongInsertVetoListener : public QObject {
|
|
|
|
Q_OBJECT
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
public:
|
2011-01-17 00:46:58 +01:00
|
|
|
// Listener returns a list of 'invalid' songs. 'old_songs' are songs that are
|
2014-02-07 16:34:20 +01:00
|
|
|
// currently in the playlist and 'new_songs' are the songs about to be added
|
|
|
|
// if
|
2011-01-17 00:46:58 +01:00
|
|
|
// nobody exercises a veto.
|
2014-02-07 16:34:20 +01:00
|
|
|
virtual SongList AboutToInsertSongs(const SongList& old_songs,
|
|
|
|
const SongList& new_songs) = 0;
|
2011-01-17 00:46:58 +01:00
|
|
|
};
|
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
class Playlist : public QAbstractListModel {
|
|
|
|
Q_OBJECT
|
|
|
|
|
2010-04-19 20:44:35 +02:00
|
|
|
friend class PlaylistUndoCommands::InsertItems;
|
|
|
|
friend class PlaylistUndoCommands::RemoveItems;
|
|
|
|
friend class PlaylistUndoCommands::MoveItems;
|
2012-06-09 15:24:15 +02:00
|
|
|
friend class PlaylistUndoCommands::ReOrderItems;
|
2010-04-19 20:44:35 +02:00
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
public:
|
2014-02-07 16:34:20 +01:00
|
|
|
Playlist(PlaylistBackend* backend, TaskManager* task_manager,
|
|
|
|
LibraryBackend* library, int id,
|
|
|
|
const QString& special_type = QString(), bool favorite = false,
|
2014-02-10 16:03:54 +01:00
|
|
|
QObject* parent = nullptr);
|
2009-12-24 20:16:07 +01:00
|
|
|
~Playlist();
|
|
|
|
|
2014-02-10 14:29:07 +01:00
|
|
|
void SkipTracks(const QModelIndexList& source_indexes);
|
2014-01-17 07:01:31 +01:00
|
|
|
|
2010-10-17 19:10:19 +02:00
|
|
|
// Always add new columns to the end of this enum - the values are persisted
|
2009-12-24 20:16:07 +01:00
|
|
|
enum Column {
|
|
|
|
Column_Title = 0,
|
|
|
|
Column_Artist,
|
|
|
|
Column_Album,
|
2010-03-07 23:46:41 +01:00
|
|
|
Column_AlbumArtist,
|
|
|
|
Column_Composer,
|
2009-12-24 20:16:07 +01:00
|
|
|
Column_Length,
|
|
|
|
Column_Track,
|
2009-12-30 05:05:33 +01:00
|
|
|
Column_Disc,
|
|
|
|
Column_Year,
|
|
|
|
Column_Genre,
|
|
|
|
Column_BPM,
|
|
|
|
Column_Bitrate,
|
|
|
|
Column_Samplerate,
|
|
|
|
Column_Filename,
|
2010-03-19 11:39:22 +01:00
|
|
|
Column_BaseFilename,
|
2009-12-30 05:05:33 +01:00
|
|
|
Column_Filesize,
|
2010-03-07 23:46:41 +01:00
|
|
|
Column_Filetype,
|
|
|
|
Column_DateCreated,
|
|
|
|
Column_DateModified,
|
2010-10-17 19:10:19 +02:00
|
|
|
Column_Rating,
|
|
|
|
Column_PlayCount,
|
2010-10-17 20:21:30 +02:00
|
|
|
Column_SkipCount,
|
|
|
|
Column_LastPlayed,
|
2010-11-01 22:15:52 +01:00
|
|
|
Column_Score,
|
2010-11-28 16:22:48 +01:00
|
|
|
Column_Comment,
|
2012-01-04 12:50:19 +01:00
|
|
|
Column_Source,
|
2012-05-27 17:46:16 +02:00
|
|
|
Column_Mood,
|
2013-03-10 07:58:09 +01:00
|
|
|
Column_Performer,
|
|
|
|
Column_Grouping,
|
2015-06-30 19:25:38 +02:00
|
|
|
Column_OriginalYear,
|
2009-12-24 20:16:07 +01:00
|
|
|
ColumnCount
|
|
|
|
};
|
|
|
|
|
|
|
|
enum Role {
|
|
|
|
Role_IsCurrent = Qt::UserRole + 1,
|
|
|
|
Role_IsPaused,
|
|
|
|
Role_StopAfter,
|
2010-07-11 18:17:38 +02:00
|
|
|
Role_QueuePosition,
|
2010-10-17 23:56:19 +02:00
|
|
|
Role_CanSetRating,
|
2009-12-24 20:16:07 +01:00
|
|
|
};
|
|
|
|
|
2011-04-07 18:25:52 +02:00
|
|
|
enum LastFMStatus {
|
2014-02-07 16:34:20 +01:00
|
|
|
LastFM_New = 0, // Haven't scrobbled yet, but we want to later
|
|
|
|
LastFM_Scrobbled, // Scrobbled ok
|
|
|
|
LastFM_Seeked, // The user seeked so don't scrobble
|
|
|
|
LastFM_Error, // Tried to scrobble but got an error
|
|
|
|
LastFM_Invalid, // The song isn't suitable for scrobbling
|
|
|
|
LastFM_Queued, // Track added to the queue for scrobbling
|
2011-04-07 18:25:52 +02:00
|
|
|
};
|
|
|
|
|
2014-08-13 04:48:18 +02:00
|
|
|
enum Path {
|
|
|
|
Path_Automatic = 0, // Automatically select path type
|
|
|
|
Path_Absolute, // Always use absolute paths
|
|
|
|
Path_Relative, // Always use relative paths
|
2014-10-07 00:23:28 +02:00
|
|
|
Path_Ask_User, // Only used in preferences: to ask user which of the
|
|
|
|
// previous values he wants to use.
|
2014-08-13 04:48:18 +02:00
|
|
|
};
|
|
|
|
|
2011-06-10 01:08:43 +02:00
|
|
|
static const char* kCddaMimeType;
|
2009-12-24 20:16:07 +01:00
|
|
|
static const char* kRowsMimetype;
|
2010-06-18 17:31:49 +02:00
|
|
|
static const char* kPlayNowMimetype;
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2011-03-19 10:41:00 +01:00
|
|
|
static const int kInvalidSongPriority;
|
|
|
|
static const QRgb kInvalidSongColor;
|
|
|
|
|
|
|
|
static const int kDynamicHistoryPriority;
|
|
|
|
static const QRgb kDynamicHistoryColor;
|
|
|
|
|
|
|
|
static const char* kSettingsGroup;
|
|
|
|
|
2014-10-05 01:22:19 +02:00
|
|
|
static const char* kPathType;
|
|
|
|
static const char* kWriteMetadata;
|
2018-10-08 17:24:36 +02:00
|
|
|
static const char* kSortIgnorePrefix;
|
|
|
|
static const char* kSortIgnorePrefixList;
|
2014-10-05 01:22:19 +02:00
|
|
|
|
2011-04-16 15:31:57 +02:00
|
|
|
static const int kUndoStackSize;
|
|
|
|
static const int kUndoItemLimit;
|
|
|
|
|
2015-05-18 19:22:55 +02:00
|
|
|
static const qint64 kMinScrobblePointNsecs;
|
|
|
|
static const qint64 kMaxScrobblePointNsecs;
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
static bool CompareItems(int column, Qt::SortOrder order, PlaylistItemPtr a,
|
2018-10-08 17:24:36 +02:00
|
|
|
PlaylistItemPtr b, const QStringList& prefixes = {});
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2010-03-24 01:12:52 +01:00
|
|
|
static QString column_name(Column column);
|
2011-07-06 15:22:42 +02:00
|
|
|
static QString abbreviated_column_name(Column column);
|
|
|
|
|
2010-03-26 00:48:58 +01:00
|
|
|
static bool column_is_editable(Playlist::Column column);
|
2014-02-07 16:34:20 +01:00
|
|
|
static bool set_column_value(Song& song, Column column,
|
|
|
|
const QVariant& value);
|
2010-03-24 01:12:52 +01:00
|
|
|
|
2010-03-10 01:04:04 +01:00
|
|
|
// Persistence
|
|
|
|
void Save() const;
|
|
|
|
void Restore();
|
2009-12-24 20:16:07 +01:00
|
|
|
|
|
|
|
// Accessors
|
2010-05-22 18:36:13 +02:00
|
|
|
QSortFilterProxyModel* proxy() const;
|
2010-07-11 17:37:40 +02:00
|
|
|
Queue* queue() const { return queue_; }
|
2010-05-22 18:36:13 +02:00
|
|
|
|
2010-05-20 23:21:55 +02:00
|
|
|
int id() const { return id_; }
|
2012-10-31 07:04:22 +01:00
|
|
|
const QString& ui_path() const { return ui_path_; }
|
|
|
|
void set_ui_path(const QString& path) { ui_path_ = path; }
|
2013-05-11 23:17:54 +02:00
|
|
|
bool is_favorite() const { return favorite_; }
|
|
|
|
void set_favorite(bool favorite) { favorite_ = favorite; }
|
2010-12-17 01:21:20 +01:00
|
|
|
|
|
|
|
int current_row() const;
|
|
|
|
int last_played_row() const;
|
2011-11-27 22:02:37 +01:00
|
|
|
int next_row(bool ignore_repeat_track = false) const;
|
2012-08-26 14:10:38 +02:00
|
|
|
int previous_row(bool ignore_repeat_track = false) const;
|
2010-12-17 01:21:20 +01:00
|
|
|
|
|
|
|
const QModelIndex current_index() const;
|
|
|
|
|
2009-12-27 00:43:38 +01:00
|
|
|
bool stop_after_current() const;
|
2013-04-15 12:58:16 +02:00
|
|
|
bool is_dynamic() const { return static_cast<bool>(dynamic_playlist_); }
|
2012-06-09 15:24:15 +02:00
|
|
|
int dynamic_history_length() const;
|
2009-12-29 20:57:33 +01:00
|
|
|
|
2011-04-28 19:50:45 +02:00
|
|
|
QString special_type() const { return special_type_; }
|
|
|
|
void set_special_type(const QString& v) { special_type_ = v; }
|
|
|
|
|
2010-10-16 17:22:14 +02:00
|
|
|
const PlaylistItemPtr& item_at(int index) const { return items_[index]; }
|
2014-02-07 16:34:20 +01:00
|
|
|
const bool has_item_at(int index) const {
|
|
|
|
return index >= 0 && index < rowCount();
|
|
|
|
}
|
2010-12-18 18:41:03 +01:00
|
|
|
|
2012-06-09 15:24:15 +02:00
|
|
|
PlaylistItemPtr current_item() const;
|
2009-12-29 20:57:33 +01:00
|
|
|
|
2009-12-29 17:15:21 +01:00
|
|
|
PlaylistItem::Options current_item_options() const;
|
2009-12-29 20:57:33 +01:00
|
|
|
Song current_item_metadata() const;
|
2010-03-06 16:33:57 +01:00
|
|
|
|
2010-06-18 16:26:46 +02:00
|
|
|
PlaylistItemList library_items_by_id(int id) const;
|
|
|
|
|
2010-05-23 00:20:00 +02:00
|
|
|
SongList GetAllSongs() const;
|
2011-03-13 12:43:44 +01:00
|
|
|
PlaylistItemList GetAllItems() const;
|
2014-02-07 16:34:20 +01:00
|
|
|
quint64 GetTotalLength() const; // in seconds
|
2010-05-23 00:20:00 +02:00
|
|
|
|
2010-03-08 19:05:41 +01:00
|
|
|
void set_sequence(PlaylistSequence* v);
|
|
|
|
PlaylistSequence* sequence() const { return playlist_sequence_; }
|
2009-12-29 20:57:33 +01:00
|
|
|
|
2010-04-19 20:44:35 +02:00
|
|
|
QUndoStack* undo_stack() const { return undo_stack_; }
|
|
|
|
|
2009-12-29 20:57:33 +01:00
|
|
|
// Scrobbling
|
2011-03-20 23:19:38 +01:00
|
|
|
qint64 scrobble_point_nanosec() const { return scrobble_point_; }
|
2011-04-07 18:25:52 +02:00
|
|
|
LastFMStatus get_lastfm_status() const { return lastfm_status_; }
|
2014-02-07 16:34:20 +01:00
|
|
|
bool have_incremented_playcount() const {
|
|
|
|
return have_incremented_playcount_;
|
|
|
|
}
|
|
|
|
void set_lastfm_status(LastFMStatus status) { lastfm_status_ = status; }
|
2011-04-17 16:11:37 +02:00
|
|
|
void set_have_incremented_playcount() { have_incremented_playcount_ = true; }
|
2015-05-18 19:22:55 +02:00
|
|
|
void UpdateScrobblePoint(qint64 seek_point_nanosec = 0);
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2018-10-20 13:57:49 +02:00
|
|
|
// play count tracking
|
|
|
|
qint64 play_count_point_nanosec() const { return play_count_point_; }
|
|
|
|
void set_max_play_count_point_nsecs(qint64 max_play_count_point_nsecs) {
|
|
|
|
max_play_count_point_nsecs_ = max_play_count_point_nsecs;
|
|
|
|
}
|
|
|
|
qint64 get_max_play_count_point_nsecs() const {
|
|
|
|
return max_play_count_point_nsecs_;
|
|
|
|
}
|
|
|
|
void UpdatePlayCountPoint(qint64 seek_point_nanosec = 0);
|
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
// Changing the playlist
|
2014-02-07 16:34:20 +01:00
|
|
|
void InsertItems(const PlaylistItemList& items, int pos = -1,
|
2018-04-14 22:57:06 +02:00
|
|
|
bool play_now = false, bool enqueue = false,
|
|
|
|
bool enqueue_next = false);
|
2014-02-07 16:34:20 +01:00
|
|
|
void InsertLibraryItems(const SongList& items, int pos = -1,
|
2018-04-14 22:57:06 +02:00
|
|
|
bool play_now = false, bool enqueue = false,
|
|
|
|
bool enqueue_next = false);
|
2014-02-07 16:34:20 +01:00
|
|
|
void InsertSongs(const SongList& items, int pos = -1, bool play_now = false,
|
2018-03-19 03:44:00 +01:00
|
|
|
bool enqueue = false, bool enqueue_next = false);
|
2014-02-07 16:34:20 +01:00
|
|
|
void InsertSongsOrLibraryItems(const SongList& items, int pos = -1,
|
2018-04-14 22:57:06 +02:00
|
|
|
bool play_now = false, bool enqueue = false,
|
|
|
|
bool enqueue_next = false);
|
2014-02-07 16:34:20 +01:00
|
|
|
void InsertSmartPlaylist(smart_playlists::GeneratorPtr gen, int pos = -1,
|
2018-04-14 22:57:06 +02:00
|
|
|
bool play_now = false, bool enqueue = false,
|
|
|
|
bool enqueue_next = false);
|
2014-02-07 16:34:20 +01:00
|
|
|
void InsertInternetItems(InternetService* service, const SongList& songs,
|
|
|
|
int pos = -1, bool play_now = false,
|
2018-03-19 03:44:00 +01:00
|
|
|
bool enqueue = false, bool enqueue_next = false);
|
2012-06-09 15:24:15 +02:00
|
|
|
void ReshuffleIndices();
|
2014-02-07 16:34:20 +01:00
|
|
|
|
|
|
|
// If this playlist contains the current item, this method will apply the
|
|
|
|
// "valid" flag on it.
|
|
|
|
// If the "valid" flag is false, the song will be greyed out. Otherwise the
|
|
|
|
// grey color will
|
2011-03-19 10:41:00 +01:00
|
|
|
// be undone.
|
2014-02-07 16:34:20 +01:00
|
|
|
// If the song is a local file and it's valid but non existent or invalid but
|
|
|
|
// exists, the
|
|
|
|
// song will be reloaded to even out the situation because obviously something
|
|
|
|
// has changed.
|
|
|
|
// This returns true if this playlist had current item when the method was
|
|
|
|
// invoked.
|
2011-03-19 10:41:00 +01:00
|
|
|
bool ApplyValidityOnCurrentSong(const QUrl& url, bool valid);
|
2014-02-07 16:34:20 +01:00
|
|
|
// Grays out and reloads all deleted songs in all playlists. Also, "ungreys"
|
|
|
|
// those songs
|
2011-03-19 11:43:50 +01:00
|
|
|
// which were once deleted but now got restored somehow.
|
2011-03-19 10:41:00 +01:00
|
|
|
void InvalidateDeletedSongs();
|
2011-04-21 23:56:37 +02:00
|
|
|
// Removes from the playlist all local files that don't exist anymore.
|
|
|
|
void RemoveDeletedSongs();
|
2011-03-19 10:41:00 +01:00
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
void StopAfter(int row);
|
2010-01-16 17:12:47 +01:00
|
|
|
void ReloadItems(const QList<int>& rows);
|
2011-11-11 02:42:48 +01:00
|
|
|
void InformOfCurrentSongChange();
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2010-12-17 01:21:20 +01:00
|
|
|
// Changes rating of a song to the given value asynchronously
|
|
|
|
void RateSong(const QModelIndex& index, double rating);
|
2014-04-20 03:07:44 +02:00
|
|
|
void RateSongs(const QModelIndexList& index_list, double rating);
|
2010-12-17 01:21:20 +01:00
|
|
|
|
2011-01-17 00:46:58 +01:00
|
|
|
// Registers an object which will get notifications when new songs
|
|
|
|
// are about to be inserted into this playlist.
|
|
|
|
void AddSongInsertVetoListener(SongInsertVetoListener* listener);
|
|
|
|
// Unregisters a SongInsertVetoListener object.
|
|
|
|
void RemoveSongInsertVetoListener(SongInsertVetoListener* listener);
|
|
|
|
|
2012-05-27 19:53:57 +02:00
|
|
|
// Just emits the dataChanged() signal so the mood column is repainted.
|
|
|
|
void MoodbarUpdated(const QModelIndex& index);
|
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
// QAbstractListModel
|
2014-02-07 16:34:20 +01:00
|
|
|
int rowCount(const QModelIndex& = QModelIndex()) const {
|
|
|
|
return items_.count();
|
|
|
|
}
|
|
|
|
int columnCount(const QModelIndex& = QModelIndex()) const {
|
|
|
|
return ColumnCount;
|
|
|
|
}
|
2009-12-24 20:16:07 +01:00
|
|
|
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
2014-02-07 16:34:20 +01:00
|
|
|
bool setData(const QModelIndex& index, const QVariant& value, int role);
|
|
|
|
QVariant headerData(int section, Qt::Orientation orientation,
|
|
|
|
int role = Qt::DisplayRole) const;
|
|
|
|
Qt::ItemFlags flags(const QModelIndex& index) const;
|
2009-12-24 20:16:07 +01:00
|
|
|
QStringList mimeTypes() const;
|
|
|
|
Qt::DropActions supportedDropActions() const;
|
|
|
|
QMimeData* mimeData(const QModelIndexList& indexes) const;
|
2014-02-07 16:34:20 +01:00
|
|
|
bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row,
|
|
|
|
int column, const QModelIndex& parent);
|
2009-12-24 20:16:07 +01:00
|
|
|
void sort(int column, Qt::SortOrder order);
|
2014-02-07 16:34:20 +01:00
|
|
|
bool removeRows(int row, int count,
|
|
|
|
const QModelIndex& parent = QModelIndex());
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2016-12-31 14:22:10 +01:00
|
|
|
static bool ComparePathDepths(Qt::SortOrder, PlaylistItemPtr,
|
|
|
|
PlaylistItemPtr);
|
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
public slots:
|
2014-04-26 04:45:25 +02:00
|
|
|
void set_current_row(int index, bool is_stopping = false);
|
2009-12-24 20:16:07 +01:00
|
|
|
void Paused();
|
|
|
|
void Playing();
|
|
|
|
void Stopped();
|
2009-12-26 16:21:36 +01:00
|
|
|
void IgnoreSorting(bool value) { ignore_sorting_ = value; }
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2009-12-26 23:15:57 +01:00
|
|
|
void ClearStreamMetadata();
|
|
|
|
void SetStreamMetadata(const QUrl& url, const Song& song);
|
2010-10-23 22:58:20 +02:00
|
|
|
void ItemChanged(PlaylistItemPtr item);
|
2011-11-18 21:55:54 +01:00
|
|
|
void UpdateItems(const SongList& songs);
|
2009-12-26 23:15:57 +01:00
|
|
|
|
2010-01-14 13:27:50 +01:00
|
|
|
void Clear();
|
2012-07-06 00:00:33 +02:00
|
|
|
void RemoveDuplicateSongs();
|
2014-08-24 10:44:27 +02:00
|
|
|
void RemoveUnavailableSongs();
|
2010-02-04 00:56:41 +01:00
|
|
|
void Shuffle();
|
2010-01-14 13:27:50 +01:00
|
|
|
|
2010-03-08 19:05:41 +01:00
|
|
|
void ShuffleModeChanged(PlaylistSequence::ShuffleMode mode);
|
2010-03-08 18:55:40 +01:00
|
|
|
|
2011-11-10 12:21:41 +01:00
|
|
|
void ExpandDynamicPlaylist();
|
2010-11-20 21:00:40 +01:00
|
|
|
void RepopulateDynamicPlaylist();
|
2010-11-20 19:49:54 +01:00
|
|
|
void TurnOffDynamicPlaylist();
|
|
|
|
|
2011-11-12 17:12:03 +01:00
|
|
|
void SetColumnAlignment(const ColumnAlignmentMap& alignment);
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
void InsertUrls(const QList<QUrl>& urls, int pos = -1, bool play_now = false,
|
2018-03-19 03:44:00 +01:00
|
|
|
bool enqueue = false, bool enqueue_next = false);
|
2014-02-07 16:34:20 +01:00
|
|
|
// Removes items with given indices from the playlist. This operation is not
|
|
|
|
// undoable.
|
2013-04-13 11:57:05 +02:00
|
|
|
void RemoveItemsWithoutUndo(const QList<int>& indices);
|
|
|
|
|
2020-09-18 16:15:19 +02:00
|
|
|
signals:
|
2011-02-10 21:55:19 +01:00
|
|
|
void RestoreFinished();
|
2010-01-08 15:52:05 +01:00
|
|
|
void CurrentSongChanged(const Song& metadata);
|
2010-04-11 19:58:58 +02:00
|
|
|
void EditingFinished(const QModelIndex& index);
|
2010-06-15 20:24:08 +02:00
|
|
|
void PlayRequested(const QModelIndex& index);
|
2010-01-08 15:52:05 +01:00
|
|
|
|
2010-12-09 21:43:06 +01:00
|
|
|
// Signals that the underlying list of items was changed, meaning that
|
|
|
|
// something was added to it, removed from it or the ordering changed.
|
2010-03-24 21:58:17 +01:00
|
|
|
void PlaylistChanged();
|
2010-11-20 21:00:40 +01:00
|
|
|
void DynamicModeChanged(bool dynamic);
|
2010-03-24 21:58:17 +01:00
|
|
|
|
2015-12-20 18:25:45 +01:00
|
|
|
void Error(const QString& message);
|
2010-06-15 20:24:08 +02:00
|
|
|
|
2014-07-23 01:15:06 +02:00
|
|
|
// Signals that the queue has changed, meaning that the remaining queued
|
|
|
|
// items should update their position.
|
|
|
|
void QueueChanged();
|
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
private:
|
|
|
|
void SetCurrentIsPaused(bool paused);
|
2011-11-27 22:02:37 +01:00
|
|
|
int NextVirtualIndex(int i, bool ignore_repeat_track) const;
|
2012-08-26 14:10:38 +02:00
|
|
|
int PreviousVirtualIndex(int i, bool ignore_repeat_track) const;
|
2010-05-22 18:36:13 +02:00
|
|
|
bool FilterContainsVirtualIndex(int i) const;
|
2010-11-20 21:30:21 +01:00
|
|
|
void TurnOnDynamicPlaylist(smart_playlists::GeneratorPtr gen);
|
2010-03-24 13:07:37 +01:00
|
|
|
|
2011-07-15 15:27:50 +02:00
|
|
|
void InsertInternetItems(const InternetModel* model,
|
2014-02-07 16:34:20 +01:00
|
|
|
const QModelIndexList& items, int pos, bool play_now,
|
2018-03-19 03:44:00 +01:00
|
|
|
bool enqueue, bool enqueue_next = false);
|
2014-02-07 16:34:20 +01:00
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void InsertSongItems(const SongList& songs, int pos, bool play_now,
|
2018-03-19 03:44:00 +01:00
|
|
|
bool enqueue, bool enqueue_next = false);
|
2011-01-09 19:27:41 +01:00
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
void InsertDynamicItems(int count);
|
2011-01-17 00:46:58 +01:00
|
|
|
|
2010-04-19 20:44:35 +02:00
|
|
|
// Modify the playlist without changing the undo stack. These are used by
|
|
|
|
// our friends in PlaylistUndoCommands
|
2011-01-10 23:26:13 +01:00
|
|
|
void InsertItemsWithoutUndo(const PlaylistItemList& items, int pos,
|
2018-03-19 03:44:00 +01:00
|
|
|
bool enqueue = false, bool enqueue_next = false);
|
2010-04-19 20:44:35 +02:00
|
|
|
PlaylistItemList RemoveItemsWithoutUndo(int pos, int count);
|
|
|
|
void MoveItemsWithoutUndo(const QList<int>& source_rows, int pos);
|
2012-06-09 15:24:15 +02:00
|
|
|
void MoveItemWithoutUndo(int source, int dest);
|
2010-04-19 20:44:35 +02:00
|
|
|
void MoveItemsWithoutUndo(int start, const QList<int>& dest_rows);
|
2012-06-09 15:24:15 +02:00
|
|
|
void ReOrderWithoutUndo(const PlaylistItemList& new_items);
|
2010-04-19 20:44:35 +02:00
|
|
|
|
2010-11-21 18:48:58 +01:00
|
|
|
void RemoveItemsNotInQueue();
|
|
|
|
|
2011-04-21 23:56:37 +02:00
|
|
|
// Removes rows with given indices from this playlist.
|
|
|
|
bool removeRows(QList<int>& rows);
|
|
|
|
|
2010-07-11 18:58:22 +02:00
|
|
|
private slots:
|
|
|
|
void TracksAboutToBeDequeued(const QModelIndex&, int begin, int end);
|
|
|
|
void TracksDequeued();
|
2010-07-26 17:53:06 +02:00
|
|
|
void TracksEnqueued(const QModelIndex&, int begin, int end);
|
2010-07-11 19:39:11 +02:00
|
|
|
void QueueLayoutChanged();
|
2014-02-07 16:34:20 +01:00
|
|
|
void SongSaveComplete(TagReaderReply* reply,
|
|
|
|
const QPersistentModelIndex& index);
|
2015-11-26 19:59:44 +01:00
|
|
|
void ItemReloadComplete(const QPersistentModelIndex& index);
|
2015-11-27 15:22:59 +01:00
|
|
|
void ItemsLoaded(QFuture<PlaylistItemList> future);
|
2011-01-17 00:46:58 +01:00
|
|
|
void SongInsertVetoListenerDestroyed();
|
2010-07-11 18:58:22 +02:00
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
private:
|
2010-11-27 20:11:36 +01:00
|
|
|
bool is_loading_;
|
2010-05-22 18:36:13 +02:00
|
|
|
PlaylistFilter* proxy_;
|
2010-07-11 17:37:40 +02:00
|
|
|
Queue* queue_;
|
2010-05-22 18:36:13 +02:00
|
|
|
|
2010-07-26 17:53:06 +02:00
|
|
|
QList<QModelIndex> temp_dequeue_change_indexes_;
|
2010-07-11 18:58:22 +02:00
|
|
|
|
2010-05-09 02:10:26 +02:00
|
|
|
PlaylistBackend* backend_;
|
2010-06-23 15:21:30 +02:00
|
|
|
TaskManager* task_manager_;
|
2010-08-31 21:45:33 +02:00
|
|
|
LibraryBackend* library_;
|
2010-05-20 23:21:55 +02:00
|
|
|
int id_;
|
2012-10-31 07:04:22 +01:00
|
|
|
QString ui_path_;
|
2013-05-11 23:17:54 +02:00
|
|
|
bool favorite_;
|
2010-04-14 23:03:00 +02:00
|
|
|
|
|
|
|
PlaylistItemList items_;
|
2014-02-07 16:34:20 +01:00
|
|
|
QList<int> virtual_items_; // Contains the indices into items_ in the order
|
|
|
|
// that they will be played.
|
2010-06-18 16:26:46 +02:00
|
|
|
// A map of library ID to playlist item - for fast lookups when library
|
|
|
|
// items change.
|
2010-10-16 17:22:14 +02:00
|
|
|
QMultiMap<int, PlaylistItemPtr> library_items_by_id_;
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2010-04-20 21:08:12 +02:00
|
|
|
QPersistentModelIndex current_item_index_;
|
|
|
|
QPersistentModelIndex last_played_item_index_;
|
2009-12-24 20:16:07 +01:00
|
|
|
QPersistentModelIndex stop_after_;
|
|
|
|
bool current_is_paused_;
|
2010-03-08 18:55:40 +01:00
|
|
|
int current_virtual_index_;
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2010-03-24 13:07:37 +01:00
|
|
|
bool is_shuffled_;
|
|
|
|
|
2011-03-20 23:19:38 +01:00
|
|
|
qint64 scrobble_point_;
|
2011-04-07 18:25:52 +02:00
|
|
|
LastFMStatus lastfm_status_;
|
2011-04-17 16:11:37 +02:00
|
|
|
bool have_incremented_playcount_;
|
2009-12-29 20:57:33 +01:00
|
|
|
|
2018-10-20 13:57:49 +02:00
|
|
|
qint64 play_count_point_;
|
|
|
|
|
2010-03-24 13:07:37 +01:00
|
|
|
PlaylistSequence* playlist_sequence_;
|
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
// Hack to stop QTreeView::setModel sorting the playlist
|
2009-12-26 16:21:36 +01:00
|
|
|
bool ignore_sorting_;
|
2010-04-19 20:44:35 +02:00
|
|
|
|
|
|
|
QUndoStack* undo_stack_;
|
2010-11-20 19:49:54 +01:00
|
|
|
|
|
|
|
smart_playlists::GeneratorPtr dynamic_playlist_;
|
2010-12-22 11:45:14 +01:00
|
|
|
ColumnAlignmentMap column_alignments_;
|
2011-01-17 00:46:58 +01:00
|
|
|
|
|
|
|
QList<SongInsertVetoListener*> veto_listeners_;
|
2011-04-28 19:50:45 +02:00
|
|
|
|
|
|
|
QString special_type_;
|
2016-04-12 16:53:43 +02:00
|
|
|
|
2018-10-20 13:57:49 +02:00
|
|
|
qint64 min_play_count_point_nsecs_;
|
|
|
|
qint64 max_play_count_point_nsecs_;
|
|
|
|
|
2016-04-12 16:53:43 +02:00
|
|
|
// Cancel async restore if songs are already replaced
|
|
|
|
bool cancel_restore_;
|
2009-12-24 20:16:07 +01:00
|
|
|
};
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
// QDataStream& operator <<(QDataStream&, const Playlist*);
|
|
|
|
// QDataStream& operator >>(QDataStream&, Playlist*&);
|
2010-07-17 14:47:59 +02:00
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
#endif // PLAYLIST_H
|