summaryrefslogtreecommitdiffstats
path: root/noatun/library/noatun/playlist.h
diff options
context:
space:
mode:
Diffstat (limited to 'noatun/library/noatun/playlist.h')
-rw-r--r--noatun/library/noatun/playlist.h531
1 files changed, 531 insertions, 0 deletions
diff --git a/noatun/library/noatun/playlist.h b/noatun/library/noatun/playlist.h
new file mode 100644
index 00000000..37eabb0b
--- /dev/null
+++ b/noatun/library/noatun/playlist.h
@@ -0,0 +1,531 @@
+#ifndef NOATUNPLAYLIST_H
+#define NOATUNPLAYLIST_H
+
+#include <qobject.h>
+#include <kurl.h>
+#include <qdict.h>
+#include <qstringlist.h>
+#include <cassert>
+#include <kdemacros.h>
+
+class PlaylistItem;
+
+/**
+ * If you're not coding a playlist, ignore this class.
+ *
+ * The backend. Since PlaylistItemData is refcounted,
+ * this contains the data, the PlaylistItem is the "reference"
+ * <pre>
+ * PlaylistItem m=new PlaylistItemData;
+ * </pre>
+ * Of course, you're supposed to inherit from PlaylistItemData
+ * in your Playlist, since there are pure virtuals.
+ *
+ * You can create these objects on demand.
+ *
+ * @short Playlist item data
+ * @author Charles Samuels
+ * @version 2.3
+ **/
+class KDE_EXPORT PlaylistItemData
+{
+public:
+ PlaylistItemData();
+ virtual ~PlaylistItemData();
+
+ /**
+ * Noatun asks your playlist for properties. It is your
+ * responsiblity to store the information. But usually a QMap<QString,QString>
+ * is enough.
+ *
+ * If you return the default value, the default should not
+ * be written.
+ *
+ * This returns the property, or def if such a property doesn't exist
+ **/
+ virtual QString property(const QString &key, const QString &def=0) const=0;
+
+ /**
+ * This sets the property with the given key and value.
+ *
+ * Important: If you use a QMap, you'll have to remove the current
+ * item before adding a new one
+ **/
+ virtual void setProperty(const QString &key, const QString &property)=0;
+
+ /**
+ * remove the item with given key
+ **/
+ virtual void clearProperty(const QString &key)=0;
+
+ /**
+ * return a list of property keys
+ **/
+ virtual QStringList properties() const=0;
+
+ /**
+ * return whether if the given key exists
+ **/
+ virtual bool isProperty(const QString &key) const=0;
+
+ /**
+ * return the title of the song. By default, this will
+ * use the following by default, in order of priority
+ *
+ * property("realtitle")
+ * property("title")
+ * url().filename()
+ *
+ * you shouldn't need to override this.
+ **/
+ virtual QString title() const;
+
+ /**
+ * the true filename of the song, remote or local
+ **/
+ virtual KURL url() const { return KURL(property("url")); }
+ /**
+ * set the true filename of the song, remote or local
+ **/
+ virtual void setUrl(const KURL &url) { setProperty("url", url.url()); }
+
+ /**
+ * first, this checks for the property "mimetype", else
+ * it'l ask KMimeType based on file()
+ **/
+ virtual QCString mimetype() const;
+
+ /**
+ * first, checks for the property "playObject", else,
+ * it'l ask aRts
+ **/
+ virtual QCString playObject() const;
+
+ /**
+ * return the filename to send to the playobject
+ **/
+ virtual QString file() const { return url().path(); }
+
+ /**
+ * what's the length of the song, in milliseconds?
+ **/
+ virtual int length() const;
+
+ /**
+ * sets the length of the song, in milliseconds
+ **/
+ virtual void setLength(int ms);
+
+ /**
+ * returns a friendly representation of the length
+ * of this file
+ **/
+ QString lengthString() const;
+
+ /**
+ * compare yourself with the given PlaylistItemData
+ * This is implemented in the slow fashion of
+ * comparing all the properties. You may
+ * have a much faster way of implementing this
+ * if this==&d, this will not be called, normally
+ **/
+ virtual bool operator == (const PlaylistItemData &d) const;
+
+ /**
+ * this is implemented as !(*this==d), you may have a
+ * faster way to implement this
+ **/
+ virtual bool operator != (const PlaylistItemData &d) const;
+
+ /**
+ * remove this item from the list
+ **/
+ virtual void remove() = 0;
+
+
+ /**
+ * Playlists should not download files if this is true
+ **/
+ bool streamable() const { return isProperty("stream_"); }
+
+public:
+ /**
+ * Call this when you want to signal
+ * the given item has been added to the list
+ **/
+ void added();
+
+ /**
+ * Your playlist must call this when the file
+ * is removed from the playlist
+ **/
+ void removed();
+
+ /**
+ * Your playlist must call this when the file
+ * is modified
+ **/
+ void modified();
+
+
+public: // reference counting
+ /**
+ * Have the reference counter never delete this
+ *
+ * This is useful for when you want to keep all
+ * your items hanging around
+ **/
+ void addRef() { mRefs++; }
+ void removeRef()
+ {
+ mRefs--;
+ if (!mRefs)
+ delete this;
+ }
+
+private:
+ mutable int mRefs;
+};
+
+
+/**
+ * a reference to a PlaylistItem(Data)
+ *
+ * All methods here should have the same behavior
+ * as they do for PlaylistItemData
+ *
+ * If you're a playlist, you should inherit
+ * from PlaylistItemData
+ *
+ * It's client code's responsibility to ensure that
+ * PlaylistItem is not null by using either the boolean
+ * conversion or isNull()
+ *
+ * @short Playlist items
+ * @author Charles Samuels
+ * @version 2.3
+ **/
+class KDE_EXPORT PlaylistItem
+{
+public:
+ PlaylistItem(const PlaylistItem &source);
+ PlaylistItem(PlaylistItemData *source);
+ PlaylistItem() : mData(0) {}
+ ~PlaylistItem();
+
+ PlaylistItem &operator =(const PlaylistItem &source);
+ PlaylistItem &operator =(PlaylistItemData *source);
+
+ PlaylistItemData *data() { return mData; }
+ const PlaylistItemData *data() const { return mData; }
+
+ const PlaylistItem &operator =(const PlaylistItem &source) const;
+ const PlaylistItem &operator =(const PlaylistItemData *source) const;
+
+ operator bool() const { return (bool)mData; }
+ bool isNull() const { return !(bool)mData; }
+
+ bool operator ==(const PlaylistItem &i) const
+ {
+ if (data()==i.data()) return true;
+ if (!data() || !i.data()) return false;
+ return *i.data()==*data();
+ }
+ bool operator ==(const PlaylistItemData *i) const
+ {
+ if (data()==i) return true;
+ if (!data() || !i) return false;
+ return *i==*data();
+ }
+
+ bool operator !=(const PlaylistItem &i) const
+ { return ! (*this==i); }
+ bool operator !=(const PlaylistItemData *i) const
+ { return ! (*this->data()==*i); }
+
+ QString property(const QString &key, const QString &def=0) const
+ {
+ assert(mData);
+ return mData->property(key, def);
+ }
+
+ void setProperty(const QString &key, const QString &property)
+ {
+ assert(mData);
+ const_cast<PlaylistItemData*>(mData)->setProperty(key, property);
+ }
+
+ void clearProperty(const QString &key)
+ {
+ assert(mData);
+ const_cast<PlaylistItemData*>(mData)->clearProperty(key);
+ }
+
+ QStringList properties() const
+ {
+ assert(mData);
+ return mData->properties();
+ }
+
+ bool isProperty(const QString &key) const
+ {
+ assert(mData);
+ return mData->isProperty(key);
+ }
+
+ KURL url() const { assert(mData); return mData->url(); }
+ void setUrl(const KURL &url)
+ {
+ assert(mData);
+ const_cast<PlaylistItemData*>(mData)->setUrl(url);
+ }
+
+ QCString mimetype() const { assert(mData); return mData->mimetype(); }
+ QCString playObject() const { assert(mData); return mData->playObject(); }
+ QString file() const { assert(mData); return mData->file(); }
+
+ QString title() const
+ {
+ assert(mData);
+ return mData->title();
+ }
+
+ int length() const
+ {
+ assert(mData);
+ return mData->length();
+ }
+
+ void setLength(int ms) const
+ {
+ assert(mData);
+ mData->setLength(ms);
+ }
+
+ QString lengthString() const { assert(mData); return mData->lengthString(); }
+
+ void remove() { assert(mData); mData->remove(); }
+
+ bool streamable() const { assert(mData); return mData->streamable(); }
+
+private:
+ // reference counting
+ void removeRef() const;
+ void addRef() const; // requires mData already has item
+
+private:
+ mutable PlaylistItemData *mData;
+ void *_bc1, *_bc2;
+};
+
+/**
+ * The playlist, which you derive from when creating
+ * your own playlist.
+ *
+ * Do not, under any circumstances, call a Playlist method
+ * when you can call a Player method, unless, of course, you
+ * ARE the playlist.
+ **/
+class Playlist : public QObject
+{
+Q_OBJECT
+ friend class PlaylistItemData;
+public:
+ Playlist(QObject *parent, const char *name);
+ /**
+ * on playlist unload, your playlist must
+ * have current()==0 and emit playCurrent
+ **/
+ virtual ~Playlist();
+
+ /**
+ * go to the front
+ **/
+ virtual void reset()=0;
+
+ /**
+ * empty the list
+ **/
+ virtual void clear()=0;
+
+ /**
+ * add a file
+ */
+ virtual void addFile(const KURL&, bool play=false)=0;
+
+ /**
+ * cycle forward, return that
+ **/
+ virtual PlaylistItem next()=0;
+
+ /**
+ * cycle to next section, return that
+ * defaults to return next()
+ */
+ virtual PlaylistItem nextSection();
+
+ /**
+ * cycle back, return that
+ **/
+ virtual PlaylistItem previous()=0;
+
+ /**
+ * cycle to previous section, return that
+ * defaults to return previous()
+ */
+ virtual PlaylistItem previousSection();
+
+ /**
+ * current item
+ **/
+ virtual PlaylistItem current()=0;
+ /**
+ * set the current item
+ **/
+ virtual void setCurrent(const PlaylistItem &)=0;
+
+ /**
+ * get the first item
+ **/
+ virtual PlaylistItem getFirst() const =0;
+
+ /**
+ * get the item after item, note that getFirst and getAfter do not
+ * have to follow play order since they are used solely to iterate
+ * over the entire collection in some order. Duplicating the play
+ * order (by looking into the future) is not necessary.
+ **/
+ virtual PlaylistItem getAfter(const PlaylistItem &item) const =0;
+
+ /**
+ * is the view visible?
+ **/
+
+ virtual bool listVisible() const =0;
+
+ /**
+ * do the KCmdLineArgs stuff
+ **/
+ int handleArguments();
+
+ /**
+ * return a list of songs in which at least one
+ * of the keys matches at least one of the values
+ *
+ * the default implementation will call getFirst()
+ * and getAfter() which could be potentially slow,
+ * depending how your playlist is designed. So
+ * you're free to reimplement this if you could
+ * do better
+ *
+ * A value of "" is equal to an unset value
+ *
+ * limit is the maximum amount of items to return,
+ * or -1 if you want as many as possible
+ *
+ * if exact is true, a match is only made if
+ * the string is identical to a value. if false
+ * a match is made if the string contains a value
+ *
+ * caseSensitive, if false, means that the given
+ * values are compared case insensitively to
+ * to the items in the playlist. The keys
+ * are always compared with case sensitivity
+ **/
+ virtual QValueList<PlaylistItem> select(
+ const QStringList &keys, const QStringList &values,
+ int limit=-1, bool exact=false, bool caseSensitive=false
+ );
+
+ /**
+ * The default implementation will just call
+ * the above select. Of course, you're free to implement
+ * both of these (with different mechanisms if need be)
+ * for speed
+ **/
+ virtual QValueList<PlaylistItem> select(
+ const QString &key, const QString &value,
+ int limit=-1, bool exact=false, bool caseSensitive=false
+ );
+ /**
+ * exactly the same as the above, except converts
+ * the const char* to QString (utf8)
+ **/
+ inline QValueList<PlaylistItem> select(
+ const char *key, const char *value,
+ int limit=-1, bool exact=false, bool caseSensitive=false
+ )
+ {
+ return select(
+ QString(key), QString(value),
+ limit, exact, caseSensitive
+ );
+ }
+
+public slots:
+ /**
+ * show the list!
+ **/
+ virtual void showList()=0;
+ /**
+ * hide it
+ **/
+ virtual void hideList()=0;
+ /**
+ * toggle visibility
+ **/
+ virtual void toggleList();
+
+signals:
+ /**
+ * when you want the engine to reload current()
+ * This is how your playlist forces noatun to
+ * play a new song
+ **/
+ void playCurrent();
+
+ /**
+ * when the list is hidden
+ **/
+ void listHidden();
+
+ /**
+ * when the list is shown
+ **/
+ void listShown();
+};
+
+/**
+ * this class's methods will be called whenever
+ * something happens to the playlist or its
+ * items.
+ *
+ * If the playlist plugin changes, you don't have to do
+ * anything.
+ **/
+class PlaylistNotifier
+{
+public:
+ PlaylistNotifier();
+ virtual ~PlaylistNotifier();
+
+ /**
+ * a new item is added to the list
+ **/
+ virtual void added(PlaylistItem &) {}
+
+ /**
+ * an item is removed from the list
+ **/
+ virtual void removed(PlaylistItem &) {}
+
+ /**
+ * this item was modified (via a changed
+ * or added property
+ **/
+ virtual void modified(PlaylistItem &) {}
+};
+
+
+#endif
+