File indexing completed on 2024-04-21 15:38:19

0001 /* This file is part of the KDE project
0002  *
0003  * Copyright (C) 2004 Koos Vriezen <koos.vriezen@xs4all.nl>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Library General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Library General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Library General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  *
0020  * until boost gets common, a more or less compatable one ..
0021  */
0022 
0023 #ifndef _KMPLAYER_PLAYLIST_H_
0024 #define _KMPLAYER_PLAYLIST_H_
0025 
0026 #include "config-kmplayer.h"
0027 #include <sys/time.h>
0028 
0029 #include <qstring.h>
0030 
0031 #include "kmplayer_def.h"
0032 #include "kmplayertypes.h"
0033 #include "kmplayershared.h"
0034 
0035 typedef struct _cairo_surface cairo_surface_t;
0036 
0037 class QTextStream;
0038 class KUrl;
0039 
0040 namespace KMPlayer {
0041 
0042 class Document;
0043 class KMPLAYER_EXPORT Node;
0044 class TextNode;
0045 class Posting;
0046 class Mrl;
0047 class ElementPrivate;
0048 class Visitor;
0049 class MediaInfo;
0050 
0051 template <class T> class KMPLAYER_EXPORT GlobalShared {
0052     T **global;
0053     int refcount;
0054 public:
0055     GlobalShared (T **glob);
0056     virtual ~GlobalShared () {}
0057 
0058     void ref () { refcount++; }
0059     void unref();
0060 };
0061 
0062 template <class T>
0063 inline GlobalShared<T>::GlobalShared (T **glob) : global (glob), refcount (1) {
0064     *global = static_cast <T*> (this);
0065 }
0066 
0067 template <class T> inline void GlobalShared<T>::unref() {
0068     if (--refcount <= 0) {
0069         *global = NULL;
0070         delete this;
0071     }
0072 }
0073 
0074 /*
0075  * Base class for objects that will be used as SharedPtr/WeakPtr pointers.
0076  * Item<T> keeps its own copy of the shared SharedData<T> as a weak refence.
0077  * \sa: self()
0078  */
0079 template <class T>
0080 class KMPLAYER_EXPORT Item {
0081     friend class SharedPtr<T>;
0082     friend class WeakPtr<T>;
0083 public:
0084     typedef SharedPtr <T> SharedType;
0085     typedef WeakPtr <T> WeakType;
0086 
0087     SharedType self () const { return m_self; }
0088 protected:
0089     Item ();
0090     WeakType m_self;
0091 private:
0092     Item (const Item <T> &); // forbidden copy constructor
0093 };
0094 
0095 /**
0096  * Because of the m_self member of Item<T>, it's not allowed to assign a
0097  * Item<T>* directly to SharedPtr<Item<T>>. Item<T>* will then reside in
0098  * two independent SharedData<Item<T>> objects.
0099  * So specialize constructor and assignment operators to fetch the
0100  * SharedData<Item<T>> from the Item<T>* instead of creating a new one
0101  */
0102 #define ITEM_AS_POINTER(CLASS)                                         \
0103  template <> inline SharedPtr<CLASS>::SharedPtr (CLASS * t)            \
0104  : data (t ? t->m_self.data : 0L) {                                    \
0105     if (data)                                                          \
0106         data->addRef ();                                               \
0107  }                                                                     \
0108                                                                        \
0109  template <>                                                           \
0110  inline SharedPtr<CLASS> & SharedPtr<CLASS>::operator = (CLASS * t) {  \
0111     if (t) {                                                           \
0112         operator = (t->m_self);                                        \
0113     } else if (data) {                                                 \
0114         data->release ();                                              \
0115         data = 0L;                                                     \
0116     }                                                                  \
0117     return *this;                                                      \
0118  }                                                                     \
0119                                                                        \
0120  template <> inline WeakPtr<CLASS>::WeakPtr (CLASS * t)                \
0121  : data (t ? t->m_self.data : 0L) {                                    \
0122     if (data)                                                          \
0123         data->addWeakRef ();                                           \
0124  }                                                                     \
0125                                                                        \
0126  template <>                                                           \
0127  inline WeakPtr<CLASS> & WeakPtr<CLASS>::operator = (CLASS * t) {      \
0128     if (t) {                                                           \
0129         operator = (t->m_self);                                        \
0130     } else if (data) {                                                 \
0131         data->releaseWeak ();                                          \
0132         data = 0L;                                                     \
0133     }                                                                  \
0134     return *this;                                                      \
0135  }
0136 
0137 /*
0138  * A double linked list of ListNodeBase<T> nodes
0139  */
0140 template <class T>
0141 class KMPLAYER_EXPORT List {
0142 public:
0143     List () {}
0144     List (typename Item<T>::SharedType f, typename Item<T>::SharedType l)
0145         : m_first (f), m_last (l) {}
0146     ~List () { clear (); }
0147 
0148     T* first () const { return m_first.ptr (); }
0149     T* last () const { return m_last.ptr (); }
0150     void append (T *c);
0151     void splice (T *pos, List <T> &lst);
0152     void insertBefore (T *c, T *b);
0153     void remove (T *c);
0154     void clear ();
0155     unsigned int length () const;
0156     T* item (int i) const;
0157 
0158 protected:
0159     typename Item<T>::SharedType m_first;
0160     typename Item<T>::WeakType m_last;
0161 };
0162 
0163 /*
0164  * Base class for double linked list nodes of SharedPtr/WeakPtr objects.
0165  * The linkage is a shared nextSibling and a weak previousSibling.
0166  */
0167 template <class T>
0168 class KMPLAYER_EXPORT ListNodeBase : public Item <T> {
0169     friend class List<T>;
0170 public:
0171     T* nextSibling () const { return m_next.ptr (); }
0172     T* previousSibling () const { return m_prev.ptr (); }
0173 protected:
0174     ListNodeBase () {}
0175     typename Item<T>::SharedType m_next;
0176     typename Item<T>::WeakType m_prev;
0177 };
0178 
0179 /*
0180  * ListNode for class T storage
0181  */
0182 template <class T>
0183 class ListNode : public ListNodeBase <ListNode <T> > {
0184 public:
0185     ListNode (T d) : data (d) {}
0186     T data;
0187 };
0188 
0189 /*
0190  * Base class for double linked tree nodes having parent/siblings/children.
0191  * The linkage is a shared firstChild and weak parentNode.
0192  */
0193 template <class T>
0194 class KMPLAYER_EXPORT TreeNode : public ListNodeBase <T> {
0195 public:
0196     void insertBefore (T *c, T *b);
0197     void appendChild (T *c);
0198     void removeChild (typename Item<T>::SharedType c);
0199 
0200     bool hasChildNodes () const { return m_first_child != 0L; }
0201     T* parentNode () const { return m_parent.ptr (); }
0202     T* firstChild () const { return m_first_child.ptr (); }
0203     T* lastChild () const { return m_last_child.ptr (); }
0204 
0205 protected:
0206     TreeNode () {}
0207     void insertBeforeImpl (T *c, T *b);
0208     void appendChildImpl (T *c);
0209     void removeChildImpl (typename Item<T>::SharedType c);
0210     typename Item<T>::WeakType m_parent;
0211     typename Item<T>::SharedType m_first_child;
0212     typename Item<T>::WeakType m_last_child;
0213 };
0214 
0215 /**
0216  * Attribute having a name/value pair for use with Elements
0217  */
0218 class KMPLAYER_EXPORT Attribute : public ListNodeBase <Attribute> {
0219 public:
0220     KDE_NO_CDTOR_EXPORT Attribute () {}
0221     Attribute (const TrieString &ns, const TrieString &n, const QString &v);
0222     KDE_NO_CDTOR_EXPORT ~Attribute () {}
0223     TrieString ns () const { return m_namespace; }
0224     TrieString name () const { return m_name; }
0225     QString value () const { return m_value; }
0226     void setName (const TrieString &);
0227     void setValue (const QString &);
0228 protected:
0229     TrieString m_namespace;
0230     TrieString m_name;
0231     QString m_value;
0232 };
0233 
0234 ITEM_AS_POINTER(KMPlayer::Attribute)
0235 
0236 /**
0237  * Object should scale according the passed Fit value in SizedEvent
0238  */
0239 enum Fit {
0240     fit_default,   // fill hidden
0241     fit_fill,      // fill complete area, no aspect preservation
0242     fit_hidden,    // keep aspect and don't scale, cut off what doesn't fit
0243     fit_meet,      // keep aspect and scale so that the smallest size just fits
0244     fit_slice,     // keep aspect and scale so that the largest size just fits
0245     fit_scroll     // keep aspect and don't scale, add scollbars if needed
0246 };
0247 
0248 enum MessageType
0249 {
0250     MsgEventTimer = 0,
0251     MsgEventClicked,
0252     MsgEventPointerMoved,
0253     MsgEventPointerInBounds,
0254     MsgEventPointerOutBounds,
0255     MsgEventStarting,
0256     MsgEventStarted,
0257     MsgEventStopped,
0258     MsgMediaFinished,
0259     MsgStateChanged,
0260     MsgAccessKey,
0261     // the above messages are ordered like SMIL timing events
0262     MsgMediaPrefetch,
0263     MsgMediaReady,
0264     MsgMediaUpdated,
0265     MsgEventPostponed,
0266     MsgSurfaceBoundsUpdate,      // bool parent surface resized
0267     MsgSurfaceUpdate,
0268     MsgSurfaceAttach,
0269     MsgStateFreeze,
0270     MsgStateRewind,
0271     MsgChildReady,
0272     MsgChildTransformedIn,
0273     MsgChildFinished,
0274 
0275     MsgInfoString                // QString*
0276 };
0277 
0278 enum RoleType
0279 {
0280     RoleReady,
0281     RoleMediaManager,
0282     RoleTiming,
0283     RoleDisplay,
0284     RoleChildDisplay,    // Mrl*
0285     RoleSizer,
0286     RoleReceivers,
0287     RolePlaylist
0288 };
0289 
0290 #define MsgUnhandled ((void *) 357L)
0291 
0292 #define MsgBool(x)                                                          \
0293     (void*)(long)(x)
0294 
0295 #define nodeMessageReceivers(node, msg)                                     \
0296     (ConnectionList*)(node)->role (RoleReceivers, (void*)(long)(msg))
0297 
0298 // convenient types
0299 typedef void Role;
0300 typedef Item<Node>::SharedType NodePtr;
0301 typedef Item<Node>::WeakType NodePtrW;
0302 typedef Item<Attribute>::SharedType AttributePtr;
0303 typedef Item<Attribute>::WeakType AttributePtrW;
0304 typedef List<Node> NodeList;                 // eg. for Node's children
0305 typedef List<Attribute> AttributeList;       // eg. for Element's attributes
0306 typedef ListNode<NodePtrW> NodeRefItem;      // Node for ref Nodes
0307 ITEM_AS_POINTER(KMPlayer::NodeRefItem)
0308 typedef ListNode<NodePtr> NodeStoreItem;   // list stores Nodes
0309 typedef List<NodeStoreItem> NodeStoreList;
0310 typedef NodeRefItem::SharedType NodeRefItemPtr;
0311 typedef NodeRefItem::WeakType NodeRefItemPtrW;
0312 typedef List<NodeRefItem> NodeRefList;       // ref nodes, eg. event receivers
0313 
0314 template <> void TreeNode<Node>::appendChild (Node *c);
0315 template <> void TreeNode<Node>::insertBefore (Node *c, Node *b);
0316 template <> void TreeNode<Node>::removeChild (NodePtr c);
0317 
0318 /*
0319  * Message connection between signaler and the listener node
0320  */
0321 
0322 class ConnectionList;
0323 
0324 #ifdef KMPLAYER_TEST_CONNECTION
0325 extern int connection_counter;
0326 #endif
0327 
0328 struct VirtualVoid {
0329     virtual ~VirtualVoid () {}
0330 };
0331 
0332 struct KeyLoad : public VirtualVoid {
0333     KeyLoad (int ch) : key (ch) {}
0334     int key;
0335 };
0336 
0337 struct Connection {
0338     NodePtrW connectee; // the one that will, when ever, trigger the event
0339     NodePtrW connecter; // the one that will, when ever, receive the event
0340     Connection (Node *invoker, Node*receiver, VirtualVoid *payload);
0341     ~Connection () {
0342         delete payload;
0343 #ifdef KMPLAYER_TEST_CONNECTION
0344         connection_counter--;
0345 #endif
0346     }
0347     VirtualVoid *payload;
0348     ConnectionList *list;
0349     Connection **link;
0350     Connection *prev;
0351     Connection *next;
0352 };
0353 
0354 class ConnectionLink {
0355 #ifdef KMPLAYER_TEST_CONNECTION
0356 public:
0357 #endif
0358     mutable Connection *connection;
0359 public:
0360     ConnectionLink ();
0361     ~ConnectionLink ();
0362 
0363     bool connect (Node *signaler, MessageType msg, Node *receiver,
0364             VirtualVoid *payload=NULL);
0365     void disconnect () const;
0366     void assign (const ConnectionLink *link) const;
0367 
0368     Node *signaler () const;
0369 private:
0370     ConnectionLink (const ConnectionLink &);
0371     ConnectionLink &operator = (const ConnectionLink &);
0372 };
0373 
0374 class ConnectionList {
0375 #ifdef KMPLAYER_TEST_CONNECTION
0376 public:
0377 #endif
0378     friend class ConnectionLink;
0379     Connection *link_first;
0380     Connection *link_last;
0381     Connection *link_next;
0382 public:
0383     ConnectionList ();
0384     ~ConnectionList () KMPLAYER_EXPORT;
0385 
0386     Connection *first () {
0387         link_next = link_first ? link_first->next : NULL;
0388         return link_first;
0389     }
0390     Connection *next () {
0391         Connection *tmp = link_next;
0392         link_next = link_next ? link_next->next : NULL;
0393         return tmp;
0394     }
0395     void clear ();
0396 };
0397 
0398 
0399 struct XMLStringlet {
0400     const QString str;
0401     XMLStringlet (const QString & s) : str (s) {}
0402 };
0403 
0404 QTextStream & operator << (QTextStream &out, const XMLStringlet &txt);
0405 
0406 /*
0407  * Base class for XML nodes. Provides a w3c's DOM like API
0408  *
0409  * Most severe traps with using SharedPtr/WeakPtr for tree nodes:
0410  * - pointer ends up in two independent shared objects (hopefully with
0411  *   template specialization for constructor for T* and assignment of T* should
0412  *   be enough of defences ..)
0413  * - Node added two times (added ASSERT in appendChild/insertBefore)
0414  * - Node is destroyed before being stored in a SharedPtr with kmplayer usage
0415  *   of each object having a WeakPtr to itself (eg. be extremely careful with
0416  *   using m_self in the constructor, no SharedPtr storage yet)
0417  *
0418  * Livetime of an element is
0419  |-->state_activated<-->state_began<-->state_finished-->state_deactivated-->|
0420   In scope            begin event    end event         Out scope
0421  */
0422 class KMPLAYER_EXPORT Node : public TreeNode <Node> {
0423     friend class DocumentBuilder;
0424 public:
0425     enum State {
0426         state_init, state_deferred,
0427         state_activated, state_began, state_finished,
0428         state_deactivated, state_resetting
0429     };
0430     enum PlayType {
0431         play_type_none, play_type_unknown, play_type_info,
0432         play_type_image, play_type_audio, play_type_video
0433     };
0434     virtual ~Node ();
0435     Document * document ();
0436     virtual Mrl * mrl ();
0437     virtual Node *childFromTag (const QString & tag);
0438     void characterData(const QString& s) KDE_NO_EXPORT;
0439     QString innerText () const;
0440     QString innerXML () const;
0441     QString outerXML () const;
0442     virtual const char * nodeName () const;
0443     virtual QString nodeValue () const;
0444     virtual void setNodeName (const QString &) {}
0445 
0446     /**
0447      * If this is a derived Mrl object and has a SRC attribute
0448      */
0449     virtual PlayType playType ();
0450     bool isPlayable () { return playType () > play_type_none; }
0451     virtual bool isElementNode () const { return false; }
0452     /**
0453      * If this node purpose is for storing runtime data only,
0454      * ie. node doesn't exist in the original document
0455      */
0456     bool auxiliaryNode () const { return auxiliary_node; }
0457     void setAuxiliaryNode (bool b) { auxiliary_node = b; }
0458     /*
0459      * Message send to this node
0460      */
0461     virtual void message (MessageType msg, void *content=NULL);
0462     /*
0463      * Query a role this Node may fulfill
0464      */
0465     virtual void *role (RoleType msg, void *content=NULL);
0466     /*
0467      * Dispatch Event to all connectors of MessageType
0468      */
0469     void deliver(MessageType msg, void *content) KDE_NO_EXPORT;
0470     /**
0471      * Alternative to event handling is the Visitor pattern
0472      */
0473     virtual void accept (Visitor *);
0474     /**
0475      * Activates element, sets state to state_activated. Will call activate() on
0476      * firstChild or call deactivate().
0477      */
0478     virtual void activate ();
0479     /**
0480      * if state is between state_activated and state_deactivated
0481      */
0482     bool active () const
0483         { return state >= state_deferred && state < state_deactivated; }
0484     /**
0485      * if state is between state_activated and state_finished
0486      */
0487     bool unfinished () const
0488         { return state > state_deferred && state < state_finished; }
0489     /**
0490      * Defers an activated, so possible playlists items can be added.
0491      */
0492     virtual void defer ();
0493     /**
0494      * Puts a deferred element in activated again, calls activate() again
0495      */
0496     virtual void undefer ();
0497     /**
0498      * Sets state to state_begin when active
0499      */
0500     virtual void begin ();
0501     /**
0502      * Sets state to state_finish when >= state_activated.
0503      * Notifies parent with a MsgChildFinished message.
0504      */
0505     virtual void finish ();
0506     /**
0507      * Stops element, sets state to state_deactivated. Calls deactivate() on
0508      * activated/deferred children. May call childDone() when active() and not
0509      * finished yet.
0510      */
0511     virtual void deactivate ();
0512     /**
0513      * Resets element, calls deactivate() if state is state_activated and sets
0514      * state to state_init.
0515      */
0516     virtual void reset ();
0517     virtual void clear ();
0518     void clearChildren ();
0519     void replaceChild(NodePtr _new, NodePtr old) KDE_NO_EXPORT;
0520     /*
0521      * Get rid of whitespace only text nodes
0522      */
0523     void normalize ();
0524     KDE_NO_EXPORT bool isDocument () const { return m_doc == m_self; }
0525 
0526     NodeList childNodes() const KDE_NO_EXPORT;
0527     void setState (State nstate);
0528     /*
0529      * Open tag is found by parser, attributes are set
0530      */
0531     virtual void opened ();
0532     /*
0533      * Close tag is found by parser, children are appended
0534      */
0535     virtual void closed ();
0536 protected:
0537     Node(NodePtr& d, short _id=0) KDE_NO_CDTOR_EXPORT;
0538     NodePtr m_doc;
0539 public:
0540     State state;
0541     short id;
0542     bool auxiliary_node : 1;
0543     bool open : 1;
0544 };
0545 
0546 ITEM_AS_POINTER(KMPlayer::Node)
0547 
0548 const short id_node_document = 1;
0549 const short id_node_record_document = 2;
0550 const short id_node_grab_document = 3;
0551 const short id_node_text = 5;
0552 const short id_node_cdata = 6;
0553 
0554 const short id_node_group_node = 25;
0555 const short id_node_playlist_document = 26;
0556 const short id_node_playlist_item = 27;
0557 const short id_node_param = 28;
0558 const short id_node_html_object = 29;
0559 const short id_node_html_embed = 30;
0560 const short id_node_svg = 31;
0561 
0562 /*
0563  * Element node, XML node that can have attributes
0564  */
0565 class KMPLAYER_EXPORT Element : public Node {
0566 public:
0567     ~Element ();
0568     void setAttributes (const AttributeList &attrs);
0569     void setAttribute (const TrieString & name, const QString & value);
0570     QString getAttribute (const TrieString & name);
0571     KDE_NO_EXPORT AttributeList &attributes () { return m_attributes; }
0572     KDE_NO_EXPORT AttributeList attributes () const { return m_attributes; }
0573     virtual void init ();
0574     virtual void reset ();
0575     virtual void clear ();
0576     virtual bool isElementNode () const { return true; }
0577     virtual void accept (Visitor * v);
0578     /**
0579      * Params are like attributes, but meant to be set dynamically. Caller may
0580      * pass a modification id, that it can use to restore the old value.
0581      * Param will be auto removed on deactivate
0582      */
0583     void setParam (const TrieString &para, const QString &val, int *mod_id=0L);
0584     QString param (const TrieString & para);
0585     void resetParam (const TrieString & para, int mod_id);
0586     /**
0587      * Called from (re)setParam for specialized interpretation of params
0588      **/
0589     virtual void parseParam (const TrieString &, const QString &) {}
0590 protected:
0591     Element (NodePtr & d, short id=0);
0592     AttributeList m_attributes;
0593 private:
0594     ElementPrivate * d;
0595 };
0596 
0597 template <class T>
0598 inline KDE_NO_EXPORT T * convertNode (NodePtr e) {
0599     return static_cast <T *> (e.ptr ());
0600 }
0601 
0602 KMPLAYER_NO_EXPORT
0603 inline Node *findChildWithId (const Node *p, const short id) {
0604     for (Node *c = p->firstChild (); c; c = c->nextSibling ())
0605         if (id == c->id)
0606             return c;
0607     return NULL;
0608 }
0609 
0610 class KMPLAYER_EXPORT PlaylistRole {
0611 public:
0612     PlaylistRole () : editable (false) {}
0613 
0614     QString caption () const;
0615     void setCaption (const QString &t);
0616 
0617     QString title;
0618     bool editable;
0619 };
0620 
0621 /**
0622  * Element representing a playable link, like URL to a movie or playlist.
0623  */
0624 class KMPLAYER_EXPORT Mrl : public Element, public PlaylistRole
0625 {
0626 protected:
0627     Mrl (NodePtr & d, short id=0);
0628     Node *childFromTag (const QString & tag);
0629     void parseParam (const TrieString &, const QString &);
0630     unsigned int cached_ismrl_version;
0631     PlayType cached_play_type;
0632 
0633 public:
0634     enum { SingleMode = 0, WindowMode };
0635 
0636     ~Mrl ();
0637     PlayType playType ();
0638     virtual Mrl * mrl ();
0639     QString absolutePath ();
0640 
0641     virtual void activate ();
0642     virtual void begin ();
0643     virtual void defer ();
0644     virtual void undefer ();
0645     virtual void deactivate ();
0646     virtual void message (MessageType msg, void *content=NULL);
0647     virtual void *role (RoleType msg, void *content=NULL);
0648 
0649     static unsigned int parseTimeString (const QString &s);
0650 
0651     /**
0652      * If this Mrl is top node of external document, opener has the
0653      * location in SCR. Typically that's the parent of this node.
0654      */
0655     NodePtrW opener; //if this node is top node of external document,
0656     MediaInfo *media_info;
0657     QString src;
0658     QString mimetype;
0659     SSize size;
0660     float aspect;
0661     int repeat;
0662     unsigned char view_mode;
0663     bool resolved;
0664     bool bookmarkable;
0665     bool access_granted;
0666 };
0667 
0668 /**
0669  * Document listener interface
0670  */
0671 class KMPLAYER_EXPORT PlayListNotify {
0672 public:
0673     virtual ~PlayListNotify() { }
0674     /**
0675      * Element has activated or deactivated notification
0676      */
0677     virtual void stateElementChanged(Node *n, Node::State os, Node::State ns)=0;
0678     /**
0679      * Ask for connection bitrates settings
0680      */
0681     virtual void bitRates (int & preferred, int & maximal) = 0;
0682     /**
0683      * Sets next call to Document::timer() or -1 to cancel a previous call
0684      */
0685     virtual void setTimeout (int ms) = 0;
0686     /**
0687      * Request to open url with mimetype
0688      */
0689     virtual void openUrl (const KUrl &, const QString &t, const QString &srv)=0;
0690     /**
0691      * Dis/Enable repaint updaters
0692      */
0693     virtual void enableRepaintUpdaters (bool enable, unsigned int off_time)=0;
0694 };
0695 
0696 /*
0697  *  A generic type for posting messages
0698  **/
0699 class KMPLAYER_EXPORT Posting {
0700 public:
0701     KDE_NO_CDTOR_EXPORT Posting (Node *n, MessageType msg, VirtualVoid *p=NULL)
0702         : source (n), message (msg), payload (p) {}
0703     KDE_NO_CDTOR_EXPORT virtual ~Posting () {}
0704     NodePtrW source;
0705     MessageType message;
0706     VirtualVoid *payload;
0707 };
0708 
0709 /**
0710  * Posting signaling a timer event
0711  */
0712 class KMPLAYER_NO_EXPORT TimerPosting : public Posting {
0713 public:
0714     TimerPosting (int ms, unsigned eid=0);
0715     unsigned event_id;
0716     int milli_sec;
0717     bool interval; // set to 'true' in 'Node::message()' to make it repeat
0718 };
0719 
0720 class KMPLAYER_NO_EXPORT UpdateEvent {
0721 public:
0722     UpdateEvent (Document *, unsigned int off_time);
0723     unsigned int cur_event_time;
0724     unsigned int skipped_time;
0725 };
0726 
0727 /**
0728  * Event signaling postponed or proceeded
0729  */
0730 class KMPLAYER_NO_EXPORT PostponedEvent {
0731 public:
0732     PostponedEvent (bool postponed);
0733     bool is_postponed; // postponed or proceeded
0734 };
0735 
0736 /**
0737  * Postpone object representing a postponed document
0738  * During its livetime, no TimerEvent's happen
0739  */
0740 class KMPLAYER_NO_EXPORT Postpone {
0741     friend class Document;
0742     struct timeval postponed_time;
0743     NodePtrW m_doc;
0744     Postpone (NodePtr doc);
0745 public:
0746     ~Postpone ();
0747 };
0748 
0749 typedef SharedPtr <Postpone> PostponePtr;
0750 typedef WeakPtr <Postpone> PostponePtrW;
0751 
0752 struct KMPLAYER_NO_EXPORT EventData {
0753     EventData (Node *t, Posting *e, EventData *n);
0754     ~EventData ();
0755 
0756     NodePtrW target;
0757     Posting *event;
0758     struct timeval timeout;
0759 
0760     EventData *next;
0761 };
0762 
0763 /**
0764  * The root of the DOM tree
0765  */
0766 class KMPLAYER_EXPORT Document : public Mrl {
0767     friend class Postpone;
0768 public:
0769     Document (const QString &, PlayListNotify * notify = 0L);
0770     ~Document ();
0771     Node *getElementById (const QString & id);
0772     Node *getElementById (Node *start, const QString & id, bool inter_doc);
0773     /** All nodes have shared pointers to Document,
0774      * so explicitly dispose it (calls clear and set m_doc to 0L)
0775      * */
0776     void dispose ();
0777     virtual Node *childFromTag (const QString & tag);
0778     KDE_NO_EXPORT const char * nodeName () const { return "document"; }
0779     virtual void activate ();
0780     virtual void defer ();
0781     virtual void undefer ();
0782     virtual void reset ();
0783 
0784     Posting *post (Node *n, Posting *event);
0785     void cancelPosting (Posting *event);
0786     void pausePosting (Posting *e);
0787     void unpausePosting (Posting *e, int ms);
0788 
0789     void timeOfDay (struct timeval &);
0790     PostponePtr postpone ();
0791     bool postponed () const { return !!postpone_ref || !! postpone_lock; }
0792     /**
0793      * Called by PlayListNotify, processes events in event_queue with timeout set to now
0794      */
0795     void timer ();
0796     void updateTimeout ();
0797     /**
0798      * Document has list of postponed receivers, eg. for running (gif)movies
0799      */
0800     virtual void *role (RoleType msg, void *content=NULL);
0801 
0802     PlayListNotify *notify_listener;
0803     unsigned int m_tree_version;
0804     unsigned int last_event_time;
0805 private:
0806     void proceed (const struct timeval & postponed_time);
0807     void insertPosting (Node *n, Posting *e, const struct timeval &tv);
0808     void setNextTimeout (const struct timeval &now);
0809 
0810     PostponePtrW postpone_ref;
0811     PostponePtr postpone_lock;
0812     ConnectionList m_PostponedListeners;
0813     EventData *event_queue;
0814     EventData *paused_queue;
0815     EventData *cur_event;
0816     int cur_timeout;
0817     struct timeval first_event_time;
0818 };
0819 
0820 namespace SMIL {
0821     class Smil;
0822     class Layout;
0823     class RegionBase;
0824     class Seq;
0825     class Switch;
0826     class Par;
0827     class Excl;
0828     class Transition;
0829     class AnimateBase;
0830     class MediaType;
0831     class TextMediaType;
0832     class RefMediaType;
0833     class Brush;
0834     class SmilText;
0835     class TextFlow;
0836     class TemporalMoment;
0837     class PriorityClass;
0838     class Anchor;
0839     class Area;
0840 }
0841 namespace RP {
0842     class Imfl;
0843     class Crossfade;
0844     class Fadein;
0845     class Fadeout;
0846     class Fill;
0847     class Wipe;
0848     class ViewChange;
0849     class Animate;
0850 }
0851 
0852 class KMPLAYER_NO_EXPORT Visitor {
0853 public:
0854     KDE_NO_CDTOR_EXPORT Visitor () {}
0855     KDE_NO_CDTOR_EXPORT virtual ~Visitor () {}
0856     virtual void visit (Node *) {}
0857     virtual void visit (TextNode *);
0858     virtual void visit (Element *);
0859     virtual void visit (SMIL::Smil *) {}
0860     virtual void visit (SMIL::Layout *);
0861     virtual void visit (SMIL::RegionBase *);
0862     virtual void visit (SMIL::Seq *);
0863     virtual void visit (SMIL::Switch *);
0864     virtual void visit (SMIL::Par *);
0865     virtual void visit (SMIL::Excl *);
0866     virtual void visit (SMIL::Transition *);
0867     virtual void visit (SMIL::AnimateBase *);
0868     virtual void visit (SMIL::PriorityClass *);
0869     virtual void visit (SMIL::MediaType *);
0870     virtual void visit (SMIL::TextMediaType *);
0871     virtual void visit (SMIL::RefMediaType *);
0872     virtual void visit (SMIL::Brush *);
0873     virtual void visit (SMIL::SmilText *);
0874     virtual void visit (SMIL::TextFlow *);
0875     virtual void visit (SMIL::TemporalMoment *);
0876     virtual void visit (SMIL::Anchor *);
0877     virtual void visit (SMIL::Area *);
0878     virtual void visit (RP::Imfl *) {}
0879     virtual void visit (RP::Crossfade *) {}
0880     virtual void visit (RP::Fadein *) {}
0881     virtual void visit (RP::Fadeout *) {}
0882     virtual void visit (RP::Fill *) {}
0883     virtual void visit (RP::Wipe *) {}
0884     virtual void visit (RP::ViewChange *) {}
0885     virtual void visit (RP::Animate *) {}
0886 };
0887 
0888 /**
0889  * Represents XML text, like "some text" in '<foo>some text</foo>'
0890  */
0891 class KMPLAYER_EXPORT TextNode : public Node {
0892 public:
0893     TextNode(NodePtr& d, const QString& s, short _id = id_node_text) KDE_NO_CDTOR_EXPORT;
0894     KDE_NO_CDTOR_EXPORT ~TextNode () {}
0895     void appendText (const QString & s);
0896     void setText (const QString & txt) { text = txt; }
0897     const char * nodeName () const { return "#text"; }
0898     void accept (Visitor *v) { v->visit (this); }
0899     QString nodeValue () const;
0900 protected:
0901     QString text;
0902 };
0903 
0904 /**
0905  * Represents cdata sections, like "some text" in '<![CDATA[some text]]>'
0906  */
0907 class KMPLAYER_EXPORT CData : public TextNode {
0908 public:
0909     CData(NodePtr& d, const QString& s) KDE_NO_CDTOR_EXPORT;
0910     KDE_NO_CDTOR_EXPORT ~CData () {}
0911     const char * nodeName () const { return "#cdata"; }
0912 };
0913 
0914 /**
0915  * Unrecognized tag by parent element or just some auxiliary node
0916  */
0917 class KMPLAYER_EXPORT DarkNode : public Element {
0918 public:
0919     DarkNode (NodePtr & d, const QByteArray &n, short id=0);
0920     KDE_NO_CDTOR_EXPORT ~DarkNode () {}
0921     const char * nodeName () const { return name.data (); }
0922     Node *childFromTag (const QString & tag);
0923 protected:
0924     QByteArray name;
0925 };
0926 
0927 //-----------------------------------------------------------------------------
0928 
0929 /**
0930  * just some url, can get a SMIL, RSS, or ASX childtree
0931  */
0932 class KMPLAYER_EXPORT GenericURL : public Mrl {
0933 public:
0934     GenericURL(NodePtr &d, const QString &s, const QString &n=QString ());
0935     KDE_NO_EXPORT const char * nodeName () const { return "url"; }
0936     void closed() KDE_NO_EXPORT;
0937 };
0938 
0939 /**
0940  * Non url mrl
0941  */
0942 class KMPLAYER_EXPORT GenericMrl : public Mrl {
0943 public:
0944     KDE_NO_CDTOR_EXPORT GenericMrl (NodePtr & d) : Mrl (d), node_name ("mrl") {}
0945     GenericMrl(NodePtr &d, const QString &s, const QString &name=QString (), const QByteArray &tag=QByteArray ("mrl"));
0946     KDE_NO_EXPORT const char * nodeName () const { return node_name.data (); }
0947     void closed ();
0948     void *role (RoleType msg, void *content=NULL);
0949     QByteArray node_name;
0950 };
0951 
0952 KMPLAYER_EXPORT
0953 void readXML (NodePtr root, QTextStream & in, const QString & firstline, bool set_opener=true);
0954 KMPLAYER_EXPORT Node * fromXMLDocumentTag (NodePtr & d, const QString & tag);
0955 
0956 template <class T>
0957 inline Item<T>::Item () : m_self (static_cast <T*> (this), true) {}
0958 
0959 template <class T> inline void List<T>::append (T *c) {
0960     if (!m_first) {
0961         m_first = c->m_self;
0962         m_last = c->m_self;
0963     } else {
0964         m_last->m_next = c->m_self;
0965         c->m_prev = m_last;
0966         m_last = c->m_self;
0967     }
0968 }
0969 
0970 template <class T> inline void List<T>::splice (T *pos, List <T> &lst) {
0971     if (lst.m_first) {
0972         if (!pos) {
0973             if (!m_first)
0974                 m_first = lst.m_first;
0975             else
0976                 m_last->m_next = lst.m_first;
0977             m_last = lst.m_last;
0978         } else {
0979             lst.m_last->m_next = pos;
0980             if (!pos->m_prev) // pos must be first
0981                 m_first = lst.m_first;
0982             else
0983                 pos->m_prev->m_next = lst.m_first;
0984         }
0985         lst.m_first = NULL;
0986         lst.m_last = NULL;
0987     }
0988 }
0989 
0990 template <class T> inline void List<T>::insertBefore (T *c, T *b) {
0991     if (!b) {
0992         append (c);
0993     } else {
0994         c->m_next = b->m_self;
0995         if (b->m_prev) {
0996             b->m_prev->m_next = c->m_self;
0997             c->m_prev = b->m_prev;
0998         } else {
0999             c->m_prev = 0L;
1000             m_first = c->m_self;
1001         }
1002         b->m_prev = c->m_self;
1003     }
1004 }
1005 
1006 template <class T> inline void List<T>::remove (T *c) {
1007     typename Item<T>::SharedType s = c->m_self;
1008     if (c->m_prev)
1009         c->m_prev->m_next = c->m_next;
1010     else
1011         m_first = c->m_next;
1012     if (c->m_next) {
1013         c->m_next->m_prev = c->m_prev;
1014         c->m_next = 0L;
1015     } else {
1016         m_last = c->m_prev;
1017     }
1018     c->m_prev = 0L;
1019 }
1020 
1021 template <class T> inline unsigned int List<T>::length () const {
1022     unsigned int count = 0;
1023     for (T *t = m_first.ptr (); t; t = t->nextSibling ())
1024         count++;
1025     return count;
1026 }
1027 
1028 template <class T> inline void List<T>::clear () {
1029     m_first = m_last = 0L;
1030 }
1031 
1032 template <class T>
1033 inline T* List<T>::item (int i) const {
1034     for (T *t = m_first.ptr (); t; t = t->nextSibling(), --i)
1035         if (i == 0)
1036             return t;
1037     return NULL;
1038 }
1039 
1040 template <class T>
1041 inline void TreeNode<T>::appendChildImpl (T *c) {
1042     if (!m_first_child) {
1043         m_first_child = c->m_self;
1044         m_last_child = c->m_self;
1045     } else {
1046         m_last_child->m_next = c->m_self;
1047         c->m_prev = m_last_child;
1048         m_last_child = c->m_self;
1049     }
1050     c->m_parent = Item<T>::m_self;
1051 }
1052 
1053 template <class T>
1054 inline void TreeNode<T>::insertBeforeImpl (T *c, T *b) {
1055     if (!b) {
1056         appendChild (c);
1057     } else {
1058         c->m_next = b->m_self;
1059         if (b->m_prev) {
1060             b->m_prev->m_next = c->m_self;
1061             c->m_prev = b->m_prev;
1062         } else {
1063             c->m_prev = 0L;
1064             m_first_child = c->m_self;
1065         }
1066         b->m_prev = c->m_self;
1067         c->m_parent = Item<T>::m_self;
1068     }
1069 }
1070 
1071 template <class T>
1072 inline void TreeNode<T>::removeChildImpl (typename Item<T>::SharedType c) {
1073     if (c->m_prev) {
1074         c->m_prev->m_next = c->m_next;
1075     } else
1076         m_first_child = c->m_next;
1077     if (c->m_next) {
1078         c->m_next->m_prev = c->m_prev;
1079         c->m_next = 0L;
1080     } else
1081         m_last_child = c->m_prev;
1082     c->m_prev = 0L;
1083     c->m_parent = 0L;
1084 }
1085 
1086 inline KDE_NO_EXPORT NodeList Node::childNodes () const {
1087     return NodeList (m_first_child, m_last_child);
1088 }
1089 
1090 }  // KMPlayer namespace
1091 
1092 #endif //_KMPLAYER_PLAYLIST_H_