Warning, file /multimedia/amarok/src/core/playlists/Playlist.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /**************************************************************************************** 0002 * Copyright (c) 2007 Bart Cerneels <bart.cerneels@kde.org> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 #ifndef AMAROK_META_PLAYLIST_H 0018 #define AMAROK_META_PLAYLIST_H 0019 0020 #include "core/amarokcore_export.h" 0021 #include "core/meta/forward_declarations.h" 0022 0023 #include <QList> 0024 #include <QMetaType> 0025 #include <QMutex> 0026 #include <QPixmap> 0027 #include <QSet> 0028 #include <QSharedData> 0029 #include <QString> 0030 #include <QTextStream> 0031 0032 #include "AmarokSharedPointer.h" 0033 #include <QUrl> 0034 0035 class QTextStream; 0036 0037 class QAction; 0038 typedef QList<QAction *> QActionList; 0039 0040 namespace Playlists 0041 { 0042 class Playlist; 0043 class PlaylistProvider; 0044 0045 typedef AmarokSharedPointer<Playlist> PlaylistPtr; 0046 typedef QList<PlaylistPtr> PlaylistList; 0047 0048 enum PlaylistCategory 0049 { 0050 UserPlaylist = 1, 0051 PodcastChannelPlaylist 0052 }; 0053 0054 /** 0055 * Subclass this class in order to be able to watch playlists as their metadata and 0056 * track list changes. 0057 */ 0058 class AMAROKCORE_EXPORT PlaylistObserver 0059 { 0060 public: 0061 PlaylistObserver(); 0062 virtual ~PlaylistObserver(); 0063 0064 /** 0065 * Subscribe to changes made by @p playlist. Does nothing if playlist is 0066 * null or if already subscribed. 0067 * 0068 * @param playlist the playlist 0069 * 0070 * This method is thread-safe. 0071 */ 0072 void subscribeTo( PlaylistPtr playlist ); 0073 0074 /** 0075 * Unsubscribe from changes made by @p playlist. Does nothing if not yet 0076 * subscribed to playlist. 0077 * 0078 * @param playlist the playlist 0079 * 0080 * This method is thread-safe. 0081 */ 0082 void unsubscribeFrom( PlaylistPtr playlist ); 0083 0084 /** 0085 * This method is called when playlist metadata (such as title) has changed. 0086 * This isn't called when just a list of tracks changes. 0087 * 0088 * @param playlist playlist whose metadata were changed 0089 * 0090 * @note this method may get called from non-main thread and must be 0091 * implemented in a thread-safe manner 0092 */ 0093 virtual void metadataChanged( const PlaylistPtr &playlist ); 0094 0095 /** 0096 * This method is called when a track has been added to the playlist. 0097 * 0098 * @param playlist playlist whose track list was changed 0099 * @param track track that was added 0100 * @param position position where the track was inserted to, beginning from 0 0101 * 0102 * @note this method may get called from non-main thread and must be 0103 * implemented in a thread-safe manner 0104 */ 0105 virtual void trackAdded( const PlaylistPtr &playlist, const Meta::TrackPtr &track, int position ); 0106 0107 /** 0108 * This method is called after a track is removed from to the playlist. 0109 * 0110 * @param playlist playlist whose track list was changed 0111 * @param position position occupied by the track right before it was removed 0112 * 0113 * @note this method may get called from non-main thread and must be 0114 * implemented in a thread-safe manner 0115 */ 0116 virtual void trackRemoved( const PlaylistPtr &playlist, int position ); 0117 0118 /** 0119 * This method is called after loading of playlist is finished 0120 * (which was started by triggerTrackLoad()) and all tracks are already added. 0121 * 0122 * @param playlist playlist loading of which has finished 0123 * 0124 * @note this method may get called from non-main thread and must be 0125 * implemented in a thread-safe manner 0126 */ 0127 virtual void tracksLoaded( PlaylistPtr playlist ); 0128 0129 private: 0130 QSet<PlaylistPtr> m_playlistSubscriptions; 0131 QMutex m_playlistSubscriptionsMutex; // guards access to m_playlistSubscriptions 0132 }; 0133 0134 class AMAROKCORE_EXPORT Playlist : public virtual QSharedData 0135 { 0136 public: 0137 Playlist(); 0138 virtual ~Playlist(); 0139 0140 /** 0141 * @returns a unique identifier for a playlist. Should be similar to 0142 * Meta::Track::uidUrl 0143 */ 0144 virtual QUrl uidUrl() const = 0; 0145 0146 virtual QString name() const = 0; 0147 virtual QString prettyName() const { return name(); } 0148 0149 virtual PlaylistProvider *provider() const { return nullptr; } 0150 0151 virtual void setName( const QString &name ); 0152 0153 /** 0154 * Returns the number of tracks this playlist contains. -1 if tracks are not 0155 * yet loaded (call triggerTrackLoad() in this case). If you get non-negative 0156 * number, all tracks have been already loaded. 0157 */ 0158 virtual int trackCount() const = 0; 0159 0160 /** 0161 * Returns loaded tracks in this playlist. Note that the list may be incomplete, 0162 * to be sure, check that trackCount() is non-negative. Otherwise you have to 0163 * become playlist observer, watch for trackAdded() methods and call 0164 * triggerTrackLoad(). If you want to immediately play or 0165 * extract metadata of the tracks, be aware that many playlist implementations 0166 * initially return MetaProxy::Tracks that are resolved asynchronously. 0167 * 0168 * Convenient way to overcome the first and optionally the second 0169 * inconvenience is to use TrackLoader helper class. 0170 */ 0171 virtual Meta::TrackList tracks() = 0; 0172 0173 /** 0174 * Trigger full background loading of this playlist. Observer's trackAdded() 0175 * and metadataChanged() will be called as appropriate. This may even change 0176 * playlist metadata; 0177 * 0178 * Implementors, you should start a background job in this method to 0179 * actually load tracks, calling notifyObservers[Something]Added/Changed() 0180 * as appropriate. 0181 * It is guaranteed that tracksLoaded() observer method will be called 0182 * exactly once, either sooner (before returning from this method) or 0183 * later (asynchronously perhaps from a different thread). 0184 * 0185 * Implementors should also use MetaProxy::Track as a second-level 0186 * lazy-loading. 0187 * 0188 * Default implementation just calls notifyObserversTracksLoaded(). 0189 */ 0190 virtual void triggerTrackLoad(); 0191 0192 /** 0193 * Add the track to a certain position in the playlist 0194 * 0195 * @param track the track to add 0196 * @param position place to add this track. The default value -1 appends to 0197 * the end. 0198 * 0199 * @note if the position is larger then the size of the playlist append to the 0200 * end without generating an error. 0201 */ 0202 virtual void addTrack( const Meta::TrackPtr &track, int position = -1 ); 0203 0204 /** 0205 * Remove track at the specified position 0206 */ 0207 virtual void removeTrack( int position ); 0208 0209 /** 0210 * Sync track status between two tracks. This is only 0211 * useful for podcasts providers and some other exotic 0212 * playlist providers. 0213 */ 0214 virtual void syncTrackStatus( int position, const Meta::TrackPtr &otherTrack ); 0215 0216 /** 0217 * A list of groups or labels this playlist belongs to. 0218 * 0219 * Can be used for grouping in folders (use ex. '/' as separator) or for 0220 * labels. Default implementation returns empty list. 0221 */ 0222 virtual QStringList groups(); 0223 0224 /** 0225 * Labels the playlist as part of a group. 0226 * 0227 * In a folder-like hierarchy this means adding the playlist to the folder with 0228 * name groups.first(). If groups is empty that means removing all groups from 0229 * the playlist. Default implementation does nothing. 0230 */ 0231 virtual void setGroups( const QStringList &groups ); 0232 0233 // FIXME: two methods below are a temporary solution 0234 // and should be removed after support of async loading will 0235 // added everywhere 0236 /** 0237 * Call this method to assure synchronously loading. 0238 * @note not all playlist implementations support asynchronous loading 0239 */ 0240 QT_DEPRECATED void makeLoadingSync() { m_async = false; } 0241 /** 0242 * Allows to check if asynchronously loading is deactivated 0243 */ 0244 bool isLoadingAsync() const { return m_async; } 0245 0246 protected: 0247 /** 0248 * Implementations must call this when metadata such as title has changed. Do 0249 * not call this when just a list of track changes. 0250 * 0251 * @note calling this from (code called by) Playlist constructor is FORBIDDEN. 0252 * 0253 * TODO: find all occurrences where this should be called in Playlist subclasses 0254 * and add the call! 0255 */ 0256 void notifyObserversMetadataChanged(); 0257 0258 /** 0259 * Implementations must call this when playlist loading started 0260 * by trriggerTrackLoad() is finished and all tracks are added. 0261 * 0262 * @note calling this from (code called by) Playlist constructor is FORBIDDEN. 0263 */ 0264 void notifyObserversTracksLoaded(); 0265 0266 /** 0267 * Implementations must call this when a track is added to playlist 0268 * 0269 * @param track the track that was added 0270 * @param position is the actual new position of the added track, never negative 0271 * @note calling this from (code called by) Playlist constructor is FORBIDDEN. 0272 */ 0273 void notifyObserversTrackAdded( const Meta::TrackPtr &track, int position ); 0274 0275 /** 0276 * Implementations must call this when a track is added to playlist 0277 * 0278 * @param position is the position where the track was before removal 0279 * @note calling this from (code called by) Playlist constructor is FORBIDDEN. 0280 */ 0281 void notifyObserversTrackRemoved( int position ); 0282 0283 private: 0284 friend class PlaylistObserver; // so that it can call (un)subscribe() 0285 void subscribe( PlaylistObserver *observer ); 0286 void unsubscribe( PlaylistObserver *observer ); 0287 0288 QSet<PlaylistObserver *> m_observers; 0289 /** 0290 * Guards access to m_observers. It would seem that QReadWriteLock would be 0291 * more efficient, but when it is locked for read, it cannot be relocked for 0292 * write, even if it is recursive. This can cause deadlocks, so it would be 0293 * never safe to lock it just for read. 0294 */ 0295 QMutex m_observersMutex; 0296 bool m_async; 0297 }; 0298 } 0299 0300 Q_DECLARE_METATYPE( Playlists::PlaylistPtr ) 0301 Q_DECLARE_METATYPE( Playlists::PlaylistList ) 0302 0303 #endif