File indexing completed on 2024-04-21 04:54:08

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