1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 2004 Koos Vriezen <koos.vriezen@xs4all.nl>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  * until boost gets common, a more or less compatable one ..
21  */
22 
23 #ifndef _KMPLAYER_PLAYLIST_H_
24 #define _KMPLAYER_PLAYLIST_H_
25 
26 #include "config-kmplayer.h"
27 #include <sys/time.h>
28 
29 #include <qstring.h>
30 
31 #include "kmplayer_def.h"
32 #include "kmplayertypes.h"
33 #include "kmplayershared.h"
34 
35 typedef struct _cairo_surface cairo_surface_t;
36 
37 class QTextStream;
38 class KUrl;
39 
40 namespace KMPlayer {
41 
42 class Document;
43 class KMPLAYER_EXPORT Node;
44 class TextNode;
45 class Posting;
46 class Mrl;
47 class ElementPrivate;
48 class Visitor;
49 class MediaInfo;
50 
51 template <class T> class KMPLAYER_EXPORT GlobalShared {
52     T **global;
53     int refcount;
54 public:
55     GlobalShared (T **glob);
~GlobalShared()56     virtual ~GlobalShared () {}
57 
ref()58     void ref () { refcount++; }
59     void unref();
60 };
61 
62 template <class T>
GlobalShared(T ** glob)63 inline GlobalShared<T>::GlobalShared (T **glob) : global (glob), refcount (1) {
64     *global = static_cast <T*> (this);
65 }
66 
unref()67 template <class T> inline void GlobalShared<T>::unref() {
68     if (--refcount <= 0) {
69         *global = NULL;
70         delete this;
71     }
72 }
73 
74 /*
75  * Base class for objects that will be used as SharedPtr/WeakPtr pointers.
76  * Item<T> keeps its own copy of the shared SharedData<T> as a weak refence.
77  * \sa: self()
78  */
79 template <class T>
80 class KMPLAYER_EXPORT Item {
81     friend class SharedPtr<T>;
82     friend class WeakPtr<T>;
83 public:
84     typedef SharedPtr <T> SharedType;
85     typedef WeakPtr <T> WeakType;
86 
self()87     SharedType self () const { return m_self; }
88 protected:
89     Item ();
90     WeakType m_self;
91 private:
92     Item (const Item <T> &); // forbidden copy constructor
93 };
94 
95 /**
96  * Because of the m_self member of Item<T>, it's not allowed to assign a
97  * Item<T>* directly to SharedPtr<Item<T>>. Item<T>* will then reside in
98  * two independent SharedData<Item<T>> objects.
99  * So specialize constructor and assignment operators to fetch the
100  * SharedData<Item<T>> from the Item<T>* instead of creating a new one
101  */
102 #define ITEM_AS_POINTER(CLASS)                                         \
103  template <> inline SharedPtr<CLASS>::SharedPtr (CLASS * t)            \
104  : data (t ? t->m_self.data : 0L) {                                    \
105     if (data)                                                          \
106         data->addRef ();                                               \
107  }                                                                     \
108                                                                        \
109  template <>                                                           \
110  inline SharedPtr<CLASS> & SharedPtr<CLASS>::operator = (CLASS * t) {  \
111     if (t) {                                                           \
112         operator = (t->m_self);                                        \
113     } else if (data) {                                                 \
114         data->release ();                                              \
115         data = 0L;                                                     \
116     }                                                                  \
117     return *this;                                                      \
118  }                                                                     \
119                                                                        \
120  template <> inline WeakPtr<CLASS>::WeakPtr (CLASS * t)                \
121  : data (t ? t->m_self.data : 0L) {                                    \
122     if (data)                                                          \
123         data->addWeakRef ();                                           \
124  }                                                                     \
125                                                                        \
126  template <>                                                           \
127  inline WeakPtr<CLASS> & WeakPtr<CLASS>::operator = (CLASS * t) {      \
128     if (t) {                                                           \
129         operator = (t->m_self);                                        \
130     } else if (data) {                                                 \
131         data->releaseWeak ();                                          \
132         data = 0L;                                                     \
133     }                                                                  \
134     return *this;                                                      \
135  }
136 
137 /*
138  * A double linked list of ListNodeBase<T> nodes
139  */
140 template <class T>
141 class KMPLAYER_EXPORT List {
142 public:
List()143     List () {}
List(typename Item<T>::SharedType f,typename Item<T>::SharedType l)144     List (typename Item<T>::SharedType f, typename Item<T>::SharedType l)
145         : m_first (f), m_last (l) {}
~List()146     ~List () { clear (); }
147 
first()148     T* first () const { return m_first.ptr (); }
last()149     T* last () const { return m_last.ptr (); }
150     void append (T *c);
151     void splice (T *pos, List <T> &lst);
152     void insertBefore (T *c, T *b);
153     void remove (T *c);
154     void clear ();
155     unsigned int length () const;
156     T* item (int i) const;
157 
158 protected:
159     typename Item<T>::SharedType m_first;
160     typename Item<T>::WeakType m_last;
161 };
162 
163 /*
164  * Base class for double linked list nodes of SharedPtr/WeakPtr objects.
165  * The linkage is a shared nextSibling and a weak previousSibling.
166  */
167 template <class T>
168 class KMPLAYER_EXPORT ListNodeBase : public Item <T> {
169     friend class List<T>;
170 public:
nextSibling()171     T* nextSibling () const { return m_next.ptr (); }
previousSibling()172     T* previousSibling () const { return m_prev.ptr (); }
173 protected:
ListNodeBase()174     ListNodeBase () {}
175     typename Item<T>::SharedType m_next;
176     typename Item<T>::WeakType m_prev;
177 };
178 
179 /*
180  * ListNode for class T storage
181  */
182 template <class T>
183 class ListNode : public ListNodeBase <ListNode <T> > {
184 public:
ListNode(T d)185     ListNode (T d) : data (d) {}
186     T data;
187 };
188 
189 /*
190  * Base class for double linked tree nodes having parent/siblings/children.
191  * The linkage is a shared firstChild and weak parentNode.
192  */
193 template <class T>
194 class KMPLAYER_EXPORT TreeNode : public ListNodeBase <T> {
195 public:
196     void insertBefore (T *c, T *b);
197     void appendChild (T *c);
198     void removeChild (typename Item<T>::SharedType c);
199 
hasChildNodes()200     bool hasChildNodes () const { return m_first_child != 0L; }
parentNode()201     T* parentNode () const { return m_parent.ptr (); }
firstChild()202     T* firstChild () const { return m_first_child.ptr (); }
lastChild()203     T* lastChild () const { return m_last_child.ptr (); }
204 
205 protected:
TreeNode()206     TreeNode () {}
207     void insertBeforeImpl (T *c, T *b);
208     void appendChildImpl (T *c);
209     void removeChildImpl (typename Item<T>::SharedType c);
210     typename Item<T>::WeakType m_parent;
211     typename Item<T>::SharedType m_first_child;
212     typename Item<T>::WeakType m_last_child;
213 };
214 
215 /**
216  * Attribute having a name/value pair for use with Elements
217  */
218 class KMPLAYER_EXPORT Attribute : public ListNodeBase <Attribute> {
219 public:
Attribute()220     KDE_NO_CDTOR_EXPORT Attribute () {}
221     Attribute (const TrieString &ns, const TrieString &n, const QString &v);
~Attribute()222     KDE_NO_CDTOR_EXPORT ~Attribute () {}
ns()223     TrieString ns () const { return m_namespace; }
name()224     TrieString name () const { return m_name; }
value()225     QString value () const { return m_value; }
226     void setName (const TrieString &);
227     void setValue (const QString &);
228 protected:
229     TrieString m_namespace;
230     TrieString m_name;
231     QString m_value;
232 };
233 
234 ITEM_AS_POINTER(KMPlayer::Attribute)
235 
236 /**
237  * Object should scale according the passed Fit value in SizedEvent
238  */
239 enum Fit {
240     fit_default,   // fill hidden
241     fit_fill,      // fill complete area, no aspect preservation
242     fit_hidden,    // keep aspect and don't scale, cut off what doesn't fit
243     fit_meet,      // keep aspect and scale so that the smallest size just fits
244     fit_slice,     // keep aspect and scale so that the largest size just fits
245     fit_scroll     // keep aspect and don't scale, add scollbars if needed
246 };
247 
248 enum MessageType
249 {
250     MsgEventTimer = 0,
251     MsgEventClicked,
252     MsgEventPointerMoved,
253     MsgEventPointerInBounds,
254     MsgEventPointerOutBounds,
255     MsgEventStarting,
256     MsgEventStarted,
257     MsgEventStopped,
258     MsgMediaFinished,
259     MsgStateChanged,
260     MsgAccessKey,
261     // the above messages are ordered like SMIL timing events
262     MsgMediaPrefetch,
263     MsgMediaReady,
264     MsgMediaUpdated,
265     MsgEventPostponed,
266     MsgSurfaceBoundsUpdate,      // bool parent surface resized
267     MsgSurfaceUpdate,
268     MsgSurfaceAttach,
269     MsgStateFreeze,
270     MsgStateRewind,
271     MsgChildReady,
272     MsgChildTransformedIn,
273     MsgChildFinished,
274 
275     MsgInfoString                // QString*
276 };
277 
278 enum RoleType
279 {
280     RoleReady,
281     RoleMediaManager,
282     RoleTiming,
283     RoleDisplay,
284     RoleChildDisplay,    // Mrl*
285     RoleSizer,
286     RoleReceivers,
287     RolePlaylist
288 };
289 
290 #define MsgUnhandled ((void *) 357L)
291 
292 #define MsgBool(x)                                                          \
293     (void*)(long)(x)
294 
295 #define nodeMessageReceivers(node, msg)                                     \
296     (ConnectionList*)(node)->role (RoleReceivers, (void*)(long)(msg))
297 
298 // convenient types
299 typedef void Role;
300 typedef Item<Node>::SharedType NodePtr;
301 typedef Item<Node>::WeakType NodePtrW;
302 typedef Item<Attribute>::SharedType AttributePtr;
303 typedef Item<Attribute>::WeakType AttributePtrW;
304 typedef List<Node> NodeList;                 // eg. for Node's children
305 typedef List<Attribute> AttributeList;       // eg. for Element's attributes
306 typedef ListNode<NodePtrW> NodeRefItem;      // Node for ref Nodes
307 ITEM_AS_POINTER(KMPlayer::NodeRefItem)
308 typedef ListNode<NodePtr> NodeStoreItem;   // list stores Nodes
309 typedef List<NodeStoreItem> NodeStoreList;
310 typedef NodeRefItem::SharedType NodeRefItemPtr;
311 typedef NodeRefItem::WeakType NodeRefItemPtrW;
312 typedef List<NodeRefItem> NodeRefList;       // ref nodes, eg. event receivers
313 
314 template <> void TreeNode<Node>::appendChild (Node *c);
315 template <> void TreeNode<Node>::insertBefore (Node *c, Node *b);
316 template <> void TreeNode<Node>::removeChild (NodePtr c);
317 
318 /*
319  * Message connection between signaler and the listener node
320  */
321 
322 class ConnectionList;
323 
324 #ifdef KMPLAYER_TEST_CONNECTION
325 extern int connection_counter;
326 #endif
327 
328 struct VirtualVoid {
~VirtualVoidVirtualVoid329     virtual ~VirtualVoid () {}
330 };
331 
332 struct KeyLoad : public VirtualVoid {
KeyLoadKeyLoad333     KeyLoad (int ch) : key (ch) {}
334     int key;
335 };
336 
337 struct Connection {
338     NodePtrW connectee; // the one that will, when ever, trigger the event
339     NodePtrW connecter; // the one that will, when ever, receive the event
340     Connection (Node *invoker, Node*receiver, VirtualVoid *payload);
~ConnectionConnection341     ~Connection () {
342         delete payload;
343 #ifdef KMPLAYER_TEST_CONNECTION
344         connection_counter--;
345 #endif
346     }
347     VirtualVoid *payload;
348     ConnectionList *list;
349     Connection **link;
350     Connection *prev;
351     Connection *next;
352 };
353 
354 class ConnectionLink {
355 #ifdef KMPLAYER_TEST_CONNECTION
356 public:
357 #endif
358     mutable Connection *connection;
359 public:
360     ConnectionLink ();
361     ~ConnectionLink ();
362 
363     bool connect (Node *signaler, MessageType msg, Node *receiver,
364             VirtualVoid *payload=NULL);
365     void disconnect () const;
366     void assign (const ConnectionLink *link) const;
367 
368     Node *signaler () const;
369 private:
370     ConnectionLink (const ConnectionLink &);
371     ConnectionLink &operator = (const ConnectionLink &);
372 };
373 
374 class ConnectionList {
375 #ifdef KMPLAYER_TEST_CONNECTION
376 public:
377 #endif
378     friend class ConnectionLink;
379     Connection *link_first;
380     Connection *link_last;
381     Connection *link_next;
382 public:
383     ConnectionList ();
384     ~ConnectionList () KMPLAYER_EXPORT;
385 
first()386     Connection *first () {
387         link_next = link_first ? link_first->next : NULL;
388         return link_first;
389     }
next()390     Connection *next () {
391         Connection *tmp = link_next;
392         link_next = link_next ? link_next->next : NULL;
393         return tmp;
394     }
395     void clear ();
396 };
397 
398 
399 struct XMLStringlet {
400     const QString str;
XMLStringletXMLStringlet401     XMLStringlet (const QString & s) : str (s) {}
402 };
403 
404 QTextStream & operator << (QTextStream &out, const XMLStringlet &txt);
405 
406 /*
407  * Base class for XML nodes. Provides a w3c's DOM like API
408  *
409  * Most severe traps with using SharedPtr/WeakPtr for tree nodes:
410  * - pointer ends up in two independent shared objects (hopefully with
411  *   template specialization for constructor for T* and assignment of T* should
412  *   be enough of defences ..)
413  * - Node added two times (added ASSERT in appendChild/insertBefore)
414  * - Node is destroyed before being stored in a SharedPtr with kmplayer usage
415  *   of each object having a WeakPtr to itself (eg. be extremely careful with
416  *   using m_self in the constructor, no SharedPtr storage yet)
417  *
418  * Livetime of an element is
419  |-->state_activated<-->state_began<-->state_finished-->state_deactivated-->|
420   In scope            begin event    end event         Out scope
421  */
422 class KMPLAYER_EXPORT Node : public TreeNode <Node> {
423     friend class DocumentBuilder;
424 public:
425     enum State {
426         state_init, state_deferred,
427         state_activated, state_began, state_finished,
428         state_deactivated, state_resetting
429     };
430     enum PlayType {
431         play_type_none, play_type_unknown, play_type_info,
432         play_type_image, play_type_audio, play_type_video
433     };
434     virtual ~Node ();
435     Document * document ();
436     virtual Mrl * mrl ();
437     virtual Node *childFromTag (const QString & tag);
438     void characterData(const QString& s) KDE_NO_EXPORT;
439     QString innerText () const;
440     QString innerXML () const;
441     QString outerXML () const;
442     virtual const char * nodeName () const;
443     virtual QString nodeValue () const;
setNodeName(const QString &)444     virtual void setNodeName (const QString &) {}
445 
446     /**
447      * If this is a derived Mrl object and has a SRC attribute
448      */
449     virtual PlayType playType ();
isPlayable()450     bool isPlayable () { return playType () > play_type_none; }
isElementNode()451     virtual bool isElementNode () const { return false; }
452     /**
453      * If this node purpose is for storing runtime data only,
454      * ie. node doesn't exist in the original document
455      */
auxiliaryNode()456     bool auxiliaryNode () const { return auxiliary_node; }
setAuxiliaryNode(bool b)457     void setAuxiliaryNode (bool b) { auxiliary_node = b; }
458     /*
459      * Message send to this node
460      */
461     virtual void message (MessageType msg, void *content=NULL);
462     /*
463      * Query a role this Node may fulfill
464      */
465     virtual void *role (RoleType msg, void *content=NULL);
466     /*
467      * Dispatch Event to all connectors of MessageType
468      */
469     void deliver(MessageType msg, void *content) KDE_NO_EXPORT;
470     /**
471      * Alternative to event handling is the Visitor pattern
472      */
473     virtual void accept (Visitor *);
474     /**
475      * Activates element, sets state to state_activated. Will call activate() on
476      * firstChild or call deactivate().
477      */
478     virtual void activate ();
479     /**
480      * if state is between state_activated and state_deactivated
481      */
active()482     bool active () const
483         { return state >= state_deferred && state < state_deactivated; }
484     /**
485      * if state is between state_activated and state_finished
486      */
unfinished()487     bool unfinished () const
488         { return state > state_deferred && state < state_finished; }
489     /**
490      * Defers an activated, so possible playlists items can be added.
491      */
492     virtual void defer ();
493     /**
494      * Puts a deferred element in activated again, calls activate() again
495      */
496     virtual void undefer ();
497     /**
498      * Sets state to state_begin when active
499      */
500     virtual void begin ();
501     /**
502      * Sets state to state_finish when >= state_activated.
503      * Notifies parent with a MsgChildFinished message.
504      */
505     virtual void finish ();
506     /**
507      * Stops element, sets state to state_deactivated. Calls deactivate() on
508      * activated/deferred children. May call childDone() when active() and not
509      * finished yet.
510      */
511     virtual void deactivate ();
512     /**
513      * Resets element, calls deactivate() if state is state_activated and sets
514      * state to state_init.
515      */
516     virtual void reset ();
517     virtual void clear ();
518     void clearChildren ();
519     void replaceChild(NodePtr _new, NodePtr old) KDE_NO_EXPORT;
520     /*
521      * Get rid of whitespace only text nodes
522      */
523     void normalize ();
isDocument()524     KDE_NO_EXPORT bool isDocument () const { return m_doc == m_self; }
525 
526     NodeList childNodes() const KDE_NO_EXPORT;
527     void setState (State nstate);
528     /*
529      * Open tag is found by parser, attributes are set
530      */
531     virtual void opened ();
532     /*
533      * Close tag is found by parser, children are appended
534      */
535     virtual void closed ();
536 protected:
537     Node(NodePtr& d, short _id=0) KDE_NO_CDTOR_EXPORT;
538     NodePtr m_doc;
539 public:
540     State state;
541     short id;
542     bool auxiliary_node : 1;
543     bool open : 1;
544 };
545 
546 ITEM_AS_POINTER(KMPlayer::Node)
547 
548 const short id_node_document = 1;
549 const short id_node_record_document = 2;
550 const short id_node_grab_document = 3;
551 const short id_node_text = 5;
552 const short id_node_cdata = 6;
553 
554 const short id_node_group_node = 25;
555 const short id_node_playlist_document = 26;
556 const short id_node_playlist_item = 27;
557 const short id_node_param = 28;
558 const short id_node_html_object = 29;
559 const short id_node_html_embed = 30;
560 const short id_node_svg = 31;
561 
562 /*
563  * Element node, XML node that can have attributes
564  */
565 class KMPLAYER_EXPORT Element : public Node {
566 public:
567     ~Element ();
568     void setAttributes (const AttributeList &attrs);
569     void setAttribute (const TrieString & name, const QString & value);
570     QString getAttribute (const TrieString & name);
attributes()571     KDE_NO_EXPORT AttributeList &attributes () { return m_attributes; }
attributes()572     KDE_NO_EXPORT AttributeList attributes () const { return m_attributes; }
573     virtual void init ();
574     virtual void reset ();
575     virtual void clear ();
isElementNode()576     virtual bool isElementNode () const { return true; }
577     virtual void accept (Visitor * v);
578     /**
579      * Params are like attributes, but meant to be set dynamically. Caller may
580      * pass a modification id, that it can use to restore the old value.
581      * Param will be auto removed on deactivate
582      */
583     void setParam (const TrieString &para, const QString &val, int *mod_id=0L);
584     QString param (const TrieString & para);
585     void resetParam (const TrieString & para, int mod_id);
586     /**
587      * Called from (re)setParam for specialized interpretation of params
588      **/
parseParam(const TrieString &,const QString &)589     virtual void parseParam (const TrieString &, const QString &) {}
590 protected:
591     Element (NodePtr & d, short id=0);
592     AttributeList m_attributes;
593 private:
594     ElementPrivate * d;
595 };
596 
597 template <class T>
convertNode(NodePtr e)598 inline KDE_NO_EXPORT T * convertNode (NodePtr e) {
599     return static_cast <T *> (e.ptr ());
600 }
601 
602 KMPLAYER_NO_EXPORT
findChildWithId(const Node * p,const short id)603 inline Node *findChildWithId (const Node *p, const short id) {
604     for (Node *c = p->firstChild (); c; c = c->nextSibling ())
605         if (id == c->id)
606             return c;
607     return NULL;
608 }
609 
610 class KMPLAYER_EXPORT PlaylistRole {
611 public:
PlaylistRole()612     PlaylistRole () : editable (false) {}
613 
614     QString caption () const;
615     void setCaption (const QString &t);
616 
617     QString title;
618     bool editable;
619 };
620 
621 /**
622  * Element representing a playable link, like URL to a movie or playlist.
623  */
624 class KMPLAYER_EXPORT Mrl : public Element, public PlaylistRole
625 {
626 protected:
627     Mrl (NodePtr & d, short id=0);
628     Node *childFromTag (const QString & tag);
629     void parseParam (const TrieString &, const QString &);
630     unsigned int cached_ismrl_version;
631     PlayType cached_play_type;
632 
633 public:
634     enum { SingleMode = 0, WindowMode };
635 
636     ~Mrl ();
637     PlayType playType ();
638     virtual Mrl * mrl ();
639     QString absolutePath ();
640 
641     virtual void activate ();
642     virtual void begin ();
643     virtual void defer ();
644     virtual void undefer ();
645     virtual void deactivate ();
646     virtual void message (MessageType msg, void *content=NULL);
647     virtual void *role (RoleType msg, void *content=NULL);
648 
649     static unsigned int parseTimeString (const QString &s);
650 
651     /**
652      * If this Mrl is top node of external document, opener has the
653      * location in SCR. Typically that's the parent of this node.
654      */
655     NodePtrW opener; //if this node is top node of external document,
656     MediaInfo *media_info;
657     QString src;
658     QString mimetype;
659     SSize size;
660     float aspect;
661     int repeat;
662     unsigned char view_mode;
663     bool resolved;
664     bool bookmarkable;
665     bool access_granted;
666 };
667 
668 /**
669  * Document listener interface
670  */
671 class KMPLAYER_EXPORT PlayListNotify {
672 public:
~PlayListNotify()673     virtual ~PlayListNotify() { }
674     /**
675      * Element has activated or deactivated notification
676      */
677     virtual void stateElementChanged(Node *n, Node::State os, Node::State ns)=0;
678     /**
679      * Ask for connection bitrates settings
680      */
681     virtual void bitRates (int & preferred, int & maximal) = 0;
682     /**
683      * Sets next call to Document::timer() or -1 to cancel a previous call
684      */
685     virtual void setTimeout (int ms) = 0;
686     /**
687      * Request to open url with mimetype
688      */
689     virtual void openUrl (const KUrl &, const QString &t, const QString &srv)=0;
690     /**
691      * Dis/Enable repaint updaters
692      */
693     virtual void enableRepaintUpdaters (bool enable, unsigned int off_time)=0;
694 };
695 
696 /*
697  *  A generic type for posting messages
698  **/
699 class KMPLAYER_EXPORT Posting {
700 public:
701     KDE_NO_CDTOR_EXPORT Posting (Node *n, MessageType msg, VirtualVoid *p=NULL)
source(n)702         : source (n), message (msg), payload (p) {}
~Posting()703     KDE_NO_CDTOR_EXPORT virtual ~Posting () {}
704     NodePtrW source;
705     MessageType message;
706     VirtualVoid *payload;
707 };
708 
709 /**
710  * Posting signaling a timer event
711  */
712 class KMPLAYER_NO_EXPORT TimerPosting : public Posting {
713 public:
714     TimerPosting (int ms, unsigned eid=0);
715     unsigned event_id;
716     int milli_sec;
717     bool interval; // set to 'true' in 'Node::message()' to make it repeat
718 };
719 
720 class KMPLAYER_NO_EXPORT UpdateEvent {
721 public:
722     UpdateEvent (Document *, unsigned int off_time);
723     unsigned int cur_event_time;
724     unsigned int skipped_time;
725 };
726 
727 /**
728  * Event signaling postponed or proceeded
729  */
730 class KMPLAYER_NO_EXPORT PostponedEvent {
731 public:
732     PostponedEvent (bool postponed);
733     bool is_postponed; // postponed or proceeded
734 };
735 
736 /**
737  * Postpone object representing a postponed document
738  * During its livetime, no TimerEvent's happen
739  */
740 class KMPLAYER_NO_EXPORT Postpone {
741     friend class Document;
742     struct timeval postponed_time;
743     NodePtrW m_doc;
744     Postpone (NodePtr doc);
745 public:
746     ~Postpone ();
747 };
748 
749 typedef SharedPtr <Postpone> PostponePtr;
750 typedef WeakPtr <Postpone> PostponePtrW;
751 
752 struct KMPLAYER_NO_EXPORT EventData {
753     EventData (Node *t, Posting *e, EventData *n);
754     ~EventData ();
755 
756     NodePtrW target;
757     Posting *event;
758     struct timeval timeout;
759 
760     EventData *next;
761 };
762 
763 /**
764  * The root of the DOM tree
765  */
766 class KMPLAYER_EXPORT Document : public Mrl {
767     friend class Postpone;
768 public:
769     Document (const QString &, PlayListNotify * notify = 0L);
770     ~Document ();
771     Node *getElementById (const QString & id);
772     Node *getElementById (Node *start, const QString & id, bool inter_doc);
773     /** All nodes have shared pointers to Document,
774      * so explicitly dispose it (calls clear and set m_doc to 0L)
775      * */
776     void dispose ();
777     virtual Node *childFromTag (const QString & tag);
nodeName()778     KDE_NO_EXPORT const char * nodeName () const { return "document"; }
779     virtual void activate ();
780     virtual void defer ();
781     virtual void undefer ();
782     virtual void reset ();
783 
784     Posting *post (Node *n, Posting *event);
785     void cancelPosting (Posting *event);
786     void pausePosting (Posting *e);
787     void unpausePosting (Posting *e, int ms);
788 
789     void timeOfDay (struct timeval &);
790     PostponePtr postpone ();
postponed()791     bool postponed () const { return !!postpone_ref || !! postpone_lock; }
792     /**
793      * Called by PlayListNotify, processes events in event_queue with timeout set to now
794      */
795     void timer ();
796     void updateTimeout ();
797     /**
798      * Document has list of postponed receivers, eg. for running (gif)movies
799      */
800     virtual void *role (RoleType msg, void *content=NULL);
801 
802     PlayListNotify *notify_listener;
803     unsigned int m_tree_version;
804     unsigned int last_event_time;
805 private:
806     void proceed (const struct timeval & postponed_time);
807     void insertPosting (Node *n, Posting *e, const struct timeval &tv);
808     void setNextTimeout (const struct timeval &now);
809 
810     PostponePtrW postpone_ref;
811     PostponePtr postpone_lock;
812     ConnectionList m_PostponedListeners;
813     EventData *event_queue;
814     EventData *paused_queue;
815     EventData *cur_event;
816     int cur_timeout;
817     struct timeval first_event_time;
818 };
819 
820 namespace SMIL {
821     class Smil;
822     class Layout;
823     class RegionBase;
824     class Seq;
825     class Switch;
826     class Par;
827     class Excl;
828     class Transition;
829     class AnimateBase;
830     class MediaType;
831     class TextMediaType;
832     class RefMediaType;
833     class Brush;
834     class SmilText;
835     class TextFlow;
836     class TemporalMoment;
837     class PriorityClass;
838     class Anchor;
839     class Area;
840 }
841 namespace RP {
842     class Imfl;
843     class Crossfade;
844     class Fadein;
845     class Fadeout;
846     class Fill;
847     class Wipe;
848     class ViewChange;
849     class Animate;
850 }
851 
852 class KMPLAYER_NO_EXPORT Visitor {
853 public:
Visitor()854     KDE_NO_CDTOR_EXPORT Visitor () {}
~Visitor()855     KDE_NO_CDTOR_EXPORT virtual ~Visitor () {}
visit(Node *)856     virtual void visit (Node *) {}
857     virtual void visit (TextNode *);
858     virtual void visit (Element *);
visit(SMIL::Smil *)859     virtual void visit (SMIL::Smil *) {}
860     virtual void visit (SMIL::Layout *);
861     virtual void visit (SMIL::RegionBase *);
862     virtual void visit (SMIL::Seq *);
863     virtual void visit (SMIL::Switch *);
864     virtual void visit (SMIL::Par *);
865     virtual void visit (SMIL::Excl *);
866     virtual void visit (SMIL::Transition *);
867     virtual void visit (SMIL::AnimateBase *);
868     virtual void visit (SMIL::PriorityClass *);
869     virtual void visit (SMIL::MediaType *);
870     virtual void visit (SMIL::TextMediaType *);
871     virtual void visit (SMIL::RefMediaType *);
872     virtual void visit (SMIL::Brush *);
873     virtual void visit (SMIL::SmilText *);
874     virtual void visit (SMIL::TextFlow *);
875     virtual void visit (SMIL::TemporalMoment *);
876     virtual void visit (SMIL::Anchor *);
877     virtual void visit (SMIL::Area *);
visit(RP::Imfl *)878     virtual void visit (RP::Imfl *) {}
visit(RP::Crossfade *)879     virtual void visit (RP::Crossfade *) {}
visit(RP::Fadein *)880     virtual void visit (RP::Fadein *) {}
visit(RP::Fadeout *)881     virtual void visit (RP::Fadeout *) {}
visit(RP::Fill *)882     virtual void visit (RP::Fill *) {}
visit(RP::Wipe *)883     virtual void visit (RP::Wipe *) {}
visit(RP::ViewChange *)884     virtual void visit (RP::ViewChange *) {}
visit(RP::Animate *)885     virtual void visit (RP::Animate *) {}
886 };
887 
888 /**
889  * Represents XML text, like "some text" in '<foo>some text</foo>'
890  */
891 class KMPLAYER_EXPORT TextNode : public Node {
892 public:
893     TextNode(NodePtr& d, const QString& s, short _id = id_node_text) KDE_NO_CDTOR_EXPORT;
~TextNode()894     KDE_NO_CDTOR_EXPORT ~TextNode () {}
895     void appendText (const QString & s);
setText(const QString & txt)896     void setText (const QString & txt) { text = txt; }
nodeName()897     const char * nodeName () const { return "#text"; }
accept(Visitor * v)898     void accept (Visitor *v) { v->visit (this); }
899     QString nodeValue () const;
900 protected:
901     QString text;
902 };
903 
904 /**
905  * Represents cdata sections, like "some text" in '<![CDATA[some text]]>'
906  */
907 class KMPLAYER_EXPORT CData : public TextNode {
908 public:
909     CData(NodePtr& d, const QString& s) KDE_NO_CDTOR_EXPORT;
~CData()910     KDE_NO_CDTOR_EXPORT ~CData () {}
nodeName()911     const char * nodeName () const { return "#cdata"; }
912 };
913 
914 /**
915  * Unrecognized tag by parent element or just some auxiliary node
916  */
917 class KMPLAYER_EXPORT DarkNode : public Element {
918 public:
919     DarkNode (NodePtr & d, const QByteArray &n, short id=0);
~DarkNode()920     KDE_NO_CDTOR_EXPORT ~DarkNode () {}
nodeName()921     const char * nodeName () const { return name.data (); }
922     Node *childFromTag (const QString & tag);
923 protected:
924     QByteArray name;
925 };
926 
927 //-----------------------------------------------------------------------------
928 
929 /**
930  * just some url, can get a SMIL, RSS, or ASX childtree
931  */
932 class KMPLAYER_EXPORT GenericURL : public Mrl {
933 public:
934     GenericURL(NodePtr &d, const QString &s, const QString &n=QString ());
nodeName()935     KDE_NO_EXPORT const char * nodeName () const { return "url"; }
936     void closed() KDE_NO_EXPORT;
937 };
938 
939 /**
940  * Non url mrl
941  */
942 class KMPLAYER_EXPORT GenericMrl : public Mrl {
943 public:
GenericMrl(NodePtr & d)944     KDE_NO_CDTOR_EXPORT GenericMrl (NodePtr & d) : Mrl (d), node_name ("mrl") {}
945     GenericMrl(NodePtr &d, const QString &s, const QString &name=QString (), const QByteArray &tag=QByteArray ("mrl"));
nodeName()946     KDE_NO_EXPORT const char * nodeName () const { return node_name.data (); }
947     void closed ();
948     void *role (RoleType msg, void *content=NULL);
949     QByteArray node_name;
950 };
951 
952 KMPLAYER_EXPORT
953 void readXML (NodePtr root, QTextStream & in, const QString & firstline, bool set_opener=true);
954 KMPLAYER_EXPORT Node * fromXMLDocumentTag (NodePtr & d, const QString & tag);
955 
956 template <class T>
Item()957 inline Item<T>::Item () : m_self (static_cast <T*> (this), true) {}
958 
append(T * c)959 template <class T> inline void List<T>::append (T *c) {
960     if (!m_first) {
961         m_first = c->m_self;
962         m_last = c->m_self;
963     } else {
964         m_last->m_next = c->m_self;
965         c->m_prev = m_last;
966         m_last = c->m_self;
967     }
968 }
969 
splice(T * pos,List<T> & lst)970 template <class T> inline void List<T>::splice (T *pos, List <T> &lst) {
971     if (lst.m_first) {
972         if (!pos) {
973             if (!m_first)
974                 m_first = lst.m_first;
975             else
976                 m_last->m_next = lst.m_first;
977             m_last = lst.m_last;
978         } else {
979             lst.m_last->m_next = pos;
980             if (!pos->m_prev) // pos must be first
981                 m_first = lst.m_first;
982             else
983                 pos->m_prev->m_next = lst.m_first;
984         }
985         lst.m_first = NULL;
986         lst.m_last = NULL;
987     }
988 }
989 
insertBefore(T * c,T * b)990 template <class T> inline void List<T>::insertBefore (T *c, T *b) {
991     if (!b) {
992         append (c);
993     } else {
994         c->m_next = b->m_self;
995         if (b->m_prev) {
996             b->m_prev->m_next = c->m_self;
997             c->m_prev = b->m_prev;
998         } else {
999             c->m_prev = 0L;
1000             m_first = c->m_self;
1001         }
1002         b->m_prev = c->m_self;
1003     }
1004 }
1005 
remove(T * c)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 
length()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 
clear()1028 template <class T> inline void List<T>::clear () {
1029     m_first = m_last = 0L;
1030 }
1031 
1032 template <class T>
item(int i)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>
appendChildImpl(T * c)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>
insertBeforeImpl(T * c,T * b)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>
removeChildImpl(typename Item<T>::SharedType c)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 
childNodes()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_
1093