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 ¶, 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