You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/noatun/library/noatun/playlist.h

533 lines
12 KiB

#ifndef NOATUNPLAYLIST_H
#define NOATUNPLAYLIST_H
#include <tqobject.h>
#include <kurl.h>
#include <tqdict.h>
#include <tqstringlist.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 TQMap<TQString,TQString>
* 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 TQString property(const TQString &key, const TQString &def=0) const=0;
/**
* This sets the property with the given key and value.
*
* Important: If you use a TQMap, you'll have to remove the current
* item before adding a new one
**/
virtual void setProperty(const TQString &key, const TQString &property)=0;
/**
* remove the item with given key
**/
virtual void clearProperty(const TQString &key)=0;
/**
* return a list of property keys
**/
virtual TQStringList properties() const=0;
/**
* return whether if the given key exists
**/
virtual bool isProperty(const TQString &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 TQString 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 TQCString mimetype() const;
/**
* first, checks for the property "playObject", else,
* it'l ask aRts
**/
virtual TQCString playObject() const;
/**
* return the filename to send to the playobject
**/
virtual TQString 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
**/
TQString 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); }
TQString property(const TQString &key, const TQString &def=0) const
{
assert(mData);
return mData->property(key, def);
}
void setProperty(const TQString &key, const TQString &property)
{
assert(mData);
const_cast<PlaylistItemData*>(mData)->setProperty(key, property);
}
void clearProperty(const TQString &key)
{
assert(mData);
const_cast<PlaylistItemData*>(mData)->clearProperty(key);
}
TQStringList properties() const
{
assert(mData);
return mData->properties();
}
bool isProperty(const TQString &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);
}
TQCString mimetype() const { assert(mData); return mData->mimetype(); }
TQCString playObject() const { assert(mData); return mData->playObject(); }
TQString file() const { assert(mData); return mData->file(); }
TQString 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);
}
TQString 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 TQObject
{
TQ_OBJECT
friend class PlaylistItemData;
public:
Playlist(TQObject *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 TDECmdLineArgs 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 TQValueList<PlaylistItem> select(
const TQStringList &keys, const TQStringList &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 TQValueList<PlaylistItem> select(
const TQString &key, const TQString &value,
int limit=-1, bool exact=false, bool caseSensitive=false
);
/**
* exactly the same as the above, except converts
* the const char* to TQString (utf8)
**/
inline TQValueList<PlaylistItem> select(
const char *key, const char *value,
int limit=-1, bool exact=false, bool caseSensitive=false
)
{
return select(
TQString(key), TQString(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