~ubuntu-branches/ubuntu/lucid/kmplayer/lucid

« back to all changes in this revision

Viewing changes to src/kmplayerplaylist.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Mercatante
  • Date: 2009-01-31 23:59:43 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090131235943-9py6tgmhb3pmkv3e
Tags: 1:0.11.0a+svn919425-0ubuntu1
* New upstream version released.
* SVN snapshot to fix FTBFS with 4.2
* Rewrite packaging for KDE4

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 *  Boston, MA 02110-1301, USA.
17
17
 **/
18
18
 
19
 
#include <config.h>
 
19
#include "config-kmplayer.h"
20
20
#include <time.h>
21
21
 
22
22
#include <qtextstream.h>
23
23
#include <kdebug.h>
24
24
#include <kurl.h>
25
 
#ifdef HAVE_EXPAT
 
25
#ifdef KMPLAYER_WITH_EXPAT
26
26
#include <expat.h>
27
27
#endif
28
 
#ifdef HAVE_CAIRO
29
 
# include <cairo.h>
30
 
#endif
31
28
#include "kmplayerplaylist.h"
32
29
#include "kmplayer_asx.h"
33
30
#include "kmplayer_atom.h"
35
32
#include "kmplayer_rss.h"
36
33
#include "kmplayer_smil.h"
37
34
#include "kmplayer_xspf.h"
 
35
#include "mediaobject.h"
38
36
 
39
37
#ifdef SHAREDPTR_DEBUG
40
 
int shared_data_count;
 
38
KMPLAYER_EXPORT int shared_data_count;
41
39
#endif
42
40
 
43
41
using namespace KMPlayer;
44
42
 
45
43
//-----------------------------------------------------------------------------
46
44
 
47
 
namespace KMPlayer {
48
 
    Node * fromXMLDocumentTag (NodePtr & d, const QString & tag) {
49
 
        const char * const name = tag.latin1 ();
50
 
        if (!strcmp (name, "smil"))
51
 
            return new SMIL::Smil (d);
52
 
        else if (!strcasecmp (name, "asx"))
53
 
            return new ASX::Asx (d);
54
 
        else if (!strcasecmp (name, "imfl"))
55
 
            return new RP::Imfl (d);
56
 
        else if (!strcasecmp (name, "rss"))
57
 
            return new RSS::Rss (d);
58
 
        else if (!strcasecmp (name, "feed"))
59
 
            return new ATOM::Feed (d);
60
 
        else if (!strcasecmp (name, "playlist"))
61
 
            return new XSPF::Playlist (d);
62
 
        else if (!strcasecmp (name, "url"))
63
 
            return new GenericURL (d, QString ());
64
 
        else if (!strcasecmp (name, "mrl") ||
65
 
                !strcasecmp (name, "document"))
66
 
            return new GenericMrl (d);
67
 
        return 0L;
68
 
    }
 
45
Node *KMPlayer::fromXMLDocumentTag (NodePtr & d, const QString & tag) {
 
46
    const char * const name = tag.latin1 ();
 
47
    if (!strcmp (name, "smil"))
 
48
        return new SMIL::Smil (d);
 
49
    else if (!strcasecmp (name, "asx"))
 
50
        return new ASX::Asx (d);
 
51
    else if (!strcasecmp (name, "imfl"))
 
52
        return new RP::Imfl (d);
 
53
    else if (!strcasecmp (name, "rss"))
 
54
        return new RSS::Rss (d);
 
55
    else if (!strcasecmp (name, "feed"))
 
56
        return new ATOM::Feed (d);
 
57
    else if (!strcasecmp (name, "playlist"))
 
58
        return new XSPF::Playlist (d);
 
59
    else if (!strcasecmp (name, "url"))
 
60
        return new GenericURL (d, QString ());
 
61
    else if (!strcasecmp (name, "mrl") ||
 
62
            !strcasecmp (name, "document"))
 
63
        return new GenericMrl (d);
 
64
    return 0L;
 
65
}
69
66
 
70
67
//-----------------------------------------------------------------------------
71
68
 
72
 
    struct XMLStringlet {
73
 
        const QString str;
74
 
        XMLStringlet (const QString & s) : str (s) {}
75
 
    };
76
 
} // namespace
77
 
 
78
 
QTextStream & operator << (QTextStream & out, const XMLStringlet & txt) {
 
69
QTextStream &KMPlayer::operator << (QTextStream &out, const XMLStringlet &txt) {
79
70
    int len = int (txt.str.length ());
80
71
    for (int i = 0; i < len; ++i) {
81
72
        if (txt.str [i] == QChar ('<')) {
95
86
//-----------------------------------------------------------------------------
96
87
 
97
88
KDE_NO_CDTOR_EXPORT
98
 
Connection::Connection (NodeRefListPtr ls, NodePtr node, NodePtr inv)
 
89
Connection::Connection (NodeRefList *ls, Node *node, Node *inv)
99
90
 : connectee (inv), listeners (ls) {
100
91
    if (listeners) {
101
92
        NodeRefItemPtr nci = new NodeRefItem (node);
102
 
        listeners->append (nci);
 
93
        ls->append (nci);
103
94
        listen_item = nci;
104
95
    }
105
96
}
113
104
 
114
105
//-----------------------------------------------------------------------------
115
106
 
116
 
KDE_NO_CDTOR_EXPORT
117
 
TimerInfo::TimerInfo (NodePtr n, unsigned id, struct timeval & tv, int ms)
118
 
 : node (n), event_id (id), timeout (tv), milli_sec (ms) {}
 
107
KDE_NO_CDTOR_EXPORT TimerPosting::TimerPosting (int ms, unsigned eid)
 
108
 : Posting (NULL, MsgEventTimer),
 
109
   event_id (eid),
 
110
   milli_sec (ms),
 
111
   interval (false) {}
119
112
 
120
113
//-----------------------------------------------------------------------------
121
114
 
132
125
    y = Single (y * d) + ty;
133
126
}
134
127
 
135
 
void Matrix::getXYWH (Single & x, Single & y, Single & w, Single & h) const {
136
 
    getXY (x, y);
 
128
void Matrix::getWH (Single &w, Single &h) const {
137
129
    w *= a;
138
130
    h *= d;
139
131
}
140
132
 
141
 
void Matrix::invXYWH (Single & x, Single & y, Single & w, Single & h) const {
 
133
IRect Matrix::toScreen (const SRect &rect) const {
 
134
    return IRect (
 
135
            (int) (Single (rect.x () * a) + tx),
 
136
            (int) (Single (rect.y () * d) + ty),
 
137
            (int) (rect.width () * a),
 
138
            (int) (rect.height () * d));
 
139
}
 
140
 
 
141
SRect Matrix::toUser (const IRect &rect) const {
142
142
    if (a > 0.00001 && d > 0.00001) {
143
 
        w /= a;
144
 
        h /= d;
145
 
        x = Single ((x - tx) / a);
146
 
        y = Single ((y - ty) / d);
 
143
        return SRect (
 
144
                Single ((Single (rect.x ()) - tx) / a),
 
145
                Single ((Single (rect.y ()) - ty) / d),
 
146
                rect.width () / a,
 
147
                rect.height () / d);
147
148
    } else {
148
 
        kdWarning () << "Not invering " << a << ", " << d << " scale" << endl;
 
149
        kWarning () << "Not invering " << a << ", " << d << " scale";
 
150
        return SRect ();
149
151
    }
150
152
}
151
153
 
173
175
 
174
176
KDE_NO_CDTOR_EXPORT Node::Node (NodePtr & d, short _id)
175
177
 : m_doc (d), state (state_init), id (_id),
176
 
   auxiliary_node (false), editable (true) {}
 
178
   auxiliary_node (false), editable (true), open (false) {}
177
179
 
178
180
Node::~Node () {
179
181
    clear ();
192
194
}
193
195
 
194
196
void Node::setState (State nstate) {
195
 
    if (state != nstate) {
 
197
    if (state != nstate && (state_init == nstate || state != state_resetting)) {
196
198
        State old = state;
197
199
        state = nstate;
198
200
        if (document ()->notify_listener)
204
206
    return true;
205
207
}
206
208
 
 
209
QString Node::caption () const {
 
210
    return QString ();
 
211
}
 
212
 
 
213
void Node::setCaption (const QString &) {
 
214
}
 
215
 
207
216
void Node::activate () {
208
 
    //kdDebug () << nodeName () << " Node::activate" << endl;
 
217
    //kDebug () << nodeName () << " Node::activate";
209
218
    setState (state_activated);
210
219
    if (firstChild ())
211
220
        firstChild ()->activate (); // activate only the first
217
226
    if (active ()) {
218
227
        setState (state_began);
219
228
    } else
220
 
        kdError () << nodeName() << " begin call on not active element" << endl;
 
229
        kError () << nodeName() << " begin call on not active element" << endl;
221
230
}
222
231
 
223
232
void Node::defer () {
224
233
    if (active ()) {
225
234
        setState (state_deferred);
226
235
    } else
227
 
        kdError () << "Node::defer () call on not activated element" << endl;
 
236
        kError () << "Node::defer () call on not activated element" << endl;
228
237
}
229
238
 
230
239
void Node::undefer () {
231
240
    if (state == state_deferred) {
232
 
        setState (state_activated);
233
 
        activate ();
 
241
        if (firstChild () && firstChild ()->state > state_init) {
 
242
            state = state_began;
 
243
        } else {
 
244
            setState (state_activated);
 
245
            activate ();
 
246
        }
234
247
    } else
235
 
        kdWarning () <<"Node::undefer () call on not deferred element"<< endl;
 
248
        kWarning () << nodeName () << " call on not deferred element";
236
249
}
237
250
 
238
251
void Node::finish () {
239
252
    if (active ()) {
240
253
        setState (state_finished);
241
254
        if (m_parent)
242
 
            m_parent->childDone (this);
 
255
            document ()->post (m_parent, new Posting (this, MsgChildFinished));
243
256
        else
244
257
            deactivate (); // document deactivates itself on finish
245
258
    } else
246
 
        kdWarning () <<"Node::finish () call on not active element"<< endl;
 
259
        kWarning () <<"Node::finish () call on not active element";
247
260
}
248
261
 
249
262
void Node::deactivate () {
250
 
    //kdDebug () << nodeName () << " Node::deactivate" << endl;
 
263
    //kDebug () << nodeName () << " Node::deactivate";
251
264
    bool need_finish (unfinished ());
252
 
    setState (state_deactivated);
 
265
    if (state_resetting != state)
 
266
        setState (state_deactivated);
253
267
    for (NodePtr e = firstChild (); e; e = e->nextSibling ()) {
254
268
        if (e->state > state_init && e->state < state_deactivated)
255
269
            e->deactivate ();
256
270
        else
257
271
            break; // remaining not yet activated
258
272
    }
259
 
    if (need_finish && m_parent)
260
 
        m_parent->childDone (this);
 
273
    if (need_finish && m_parent && m_parent->active ())
 
274
        document ()->post (m_parent, new Posting (this, MsgChildFinished));
261
275
}
262
276
 
263
277
void Node::reset () {
264
 
    //kdDebug () << nodeName () << " Node::reset" << endl;
265
 
    if (active ())
 
278
    //kDebug () << nodeName () << " Node::reset";
 
279
    if (active ()) {
 
280
        setState (state_resetting);
266
281
        deactivate ();
 
282
    }
267
283
    setState (state_init);
268
284
    for (NodePtr e = firstChild (); e; e = e->nextSibling ()) {
269
285
        if (e->state != state_init)
273
289
    }
274
290
}
275
291
 
276
 
void Node::childBegan (NodePtr /*child*/) {
277
 
}
278
 
 
279
 
void Node::childDone (NodePtr child) {
280
 
    //kdDebug () << nodeName () << " Node::childDone" << endl;
281
 
    if (unfinished ()) {
282
 
        if (child->state == state_finished)
283
 
            child->deactivate ();
284
 
        if (child->nextSibling ())
285
 
            child->nextSibling ()->activate ();
286
 
        else
287
 
            finish (); // we're done
288
 
    }
289
 
}
290
 
 
291
292
void Node::clear () {
292
293
    clearChildren ();
293
294
}
313
314
}
314
315
 
315
316
void Node::insertBefore (NodePtr c, NodePtr b) {
316
 
    if (!b) {
317
 
        appendChild (c);
318
 
    } else {
319
 
        ASSERT (!c->parentNode ());
320
 
        document()->m_tree_version++;
321
 
        if (b->m_prev) {
322
 
            b->m_prev->m_next = c;
323
 
            c->m_prev = b->m_prev;
324
 
        } else {
325
 
            c->m_prev = 0L;
326
 
            m_first_child = c;
327
 
        }
328
 
        b->m_prev = c;
329
 
        c->m_next = b;
330
 
        c->m_parent = this;
331
 
    }
 
317
    ASSERT (!c->parentNode ());
 
318
    document()->m_tree_version++;
 
319
    TreeNode<Node>::insertBefore (c, b);
332
320
}
333
321
 
334
322
void Node::removeChild (NodePtr c) {
445
433
    return play_type_none;
446
434
}
447
435
 
448
 
void Node::opened () {}
449
 
 
450
 
void Node::closed () {}
451
 
 
452
 
NodeRefListPtr Node::listeners (unsigned int /*event_id*/) {
453
 
    return NodeRefListPtr ();
454
 
}
455
 
 
456
 
bool Node::handleEvent (EventPtr /*event*/) { return false; }
457
 
 
458
 
KDE_NO_EXPORT void Node::propagateEvent (EventPtr event) {
459
 
    NodeRefListPtr nl = listeners (event->id ());
 
436
void Node::opened () {
 
437
    open = true;
 
438
}
 
439
 
 
440
void Node::closed () {
 
441
    open = false;
 
442
}
 
443
 
 
444
void *Node::message (MessageType msg, void *content) {
 
445
    switch (msg) {
 
446
        case MsgQueryReady:
 
447
            return MsgBool (true);
 
448
 
 
449
        case MsgChildFinished: {
 
450
            Posting *post = (Posting *) content;
 
451
            if (unfinished ()) {
 
452
                if (post->source->state == state_finished)
 
453
                    post->source->deactivate ();
 
454
                if (post->source && post->source->nextSibling ())
 
455
                    post->source->nextSibling ()->activate ();
 
456
                else
 
457
                    finish (); // we're done
 
458
            }
 
459
            return NULL;
 
460
        }
 
461
 
 
462
        default:
 
463
            if (MsgStartQueryMessage < msg && MsgEndQueryMessage > msg)
 
464
                return NULL;
 
465
    }
 
466
    return MsgUnhandled;
 
467
}
 
468
 
 
469
KDE_NO_EXPORT void Node::deliver (MessageType msg, void *content) {
 
470
    NodeRefList *nl = nodeMessageReceivers (this, msg);
460
471
    if (nl)
461
472
        for (NodeRefItemPtr c = nl->first(); c; c = c->nextSibling ())
462
473
            if (c->data)
463
 
                c->data->handleEvent (event);
 
474
                c->data->message (msg, content);
464
475
}
465
476
 
466
477
void Node::accept (Visitor * v) {
468
479
}
469
480
 
470
481
KDE_NO_EXPORT
471
 
ConnectionPtr Node::connectTo (NodePtr node, unsigned int evt_id) {
472
 
    NodeRefListPtr nl = listeners (evt_id);
 
482
ConnectionPtr Node::connectTo (Node *node, MessageType msg) {
 
483
    NodeRefList *nl = nodeMessageReceivers (this, msg);
473
484
    if (nl)
474
485
        return ConnectionPtr (new Connection (nl, node, this));
475
486
    return ConnectionPtr ();
479
490
    return QString ();
480
491
}
481
492
 
482
 
SurfacePtr Node::getSurface (NodePtr) {
483
 
    return 0L;
484
 
}
485
 
 
486
 
//-----------------------------------------------------------------------------
487
 
 
488
 
RefNode::RefNode (NodePtr & d, NodePtr ref)
489
 
 : Node (d) {
490
 
    setRefNode (ref);
491
 
}
492
 
 
493
 
void RefNode::setRefNode (const NodePtr ref) {
494
 
    ref_node = ref;
495
 
    if (ref_node)
496
 
        tag_name = QString ("&%1").arg (ref_node->nodeName ());
497
 
}
498
 
 
499
 
//-----------------------------------------------------------------------------
500
 
 
501
 
namespace KMPlayer {
 
493
//-----------------------------------------------------------------------------
 
494
 
 
495
namespace {
502
496
    struct KMPLAYER_NO_EXPORT ParamValue {
503
497
        QString val;
504
498
        QStringList  * modifications;
508
502
        void setValue (const QString & v) { val = v; }
509
503
    };
510
504
    typedef QMap <TrieString, ParamValue *> ParamMap;
 
505
}
 
506
 
 
507
namespace KMPlayer {
511
508
    class KMPLAYER_NO_EXPORT ElementPrivate {
512
509
    public:
513
510
        ~ElementPrivate ();
539
536
    delete d;
540
537
}
541
538
 
542
 
void Element::setParam (const TrieString &param, const QString &val, int *mid) {
543
 
    ParamValue * pv = d->params [param];
 
539
void Element::setParam (const TrieString &name, const QString &val, int *mid) {
 
540
    ParamValue * pv = d->params [name];
544
541
    if (!pv) {
545
 
        pv = new ParamValue (mid ? QString() : val);
546
 
        d->params.insert (param, pv);
 
542
        pv = new ParamValue (mid ? getAttribute (name) : val);
 
543
        d->params.insert (name, pv);
547
544
    }
548
545
    if (mid) {
549
546
        if (!pv->modifications)
554
551
            *mid = pv->modifications->size ();
555
552
            pv->modifications->push_back (val);
556
553
        }
557
 
    } else
 
554
    } else {
558
555
        pv->setValue (val);
559
 
    parseParam (param, val);
 
556
    }
 
557
    parseParam (name, val);
560
558
}
561
559
 
562
560
QString Element::param (const TrieString & name) {
563
561
    ParamValue * pv = d->params [name];
564
562
    if (pv)
565
563
        return pv->value ();
566
 
    return QString ();
 
564
    return getAttribute (name);
567
565
}
568
566
 
569
 
void Element::resetParam (const TrieString & param, int mid) {
570
 
    ParamValue * pv = d->params [param];
 
567
void Element::resetParam (const TrieString &name, int mid) {
 
568
    ParamValue * pv = d->params [name];
571
569
    if (pv && pv->modifications) {
572
570
        if (int (pv->modifications->size ()) > mid && mid > -1) {
573
571
            (*pv->modifications) [mid] = QString ();
579
577
        if (pv->modifications->size () == 0) {
580
578
            delete pv->modifications;
581
579
            pv->modifications = 0L;
582
 
            val = pv->value ();
583
580
            if (val.isNull ()) {
584
581
                delete pv;
585
 
                d->params.remove (param);
 
582
                d->params.remove (name);
586
583
            }
587
584
        }
588
 
        parseParam (param, val);
 
585
        parseParam (name, val);
589
586
    } else
590
 
        kdError () << "resetting " << param.toString() << " that doesn't exists" << endl;
 
587
        kError () << "resetting " << name.toString() << " that doesn't exists" << endl;
591
588
}
592
589
 
593
590
void Element::setAttribute (const TrieString & name, const QString & value) {
594
591
    for (AttributePtr a = m_attributes->first (); a; a = a->nextSibling ())
595
592
        if (name == a->name ()) {
596
 
            a->setValue (value);
 
593
            if (value.isNull ())
 
594
                m_attributes->remove (a);
 
595
            else
 
596
                a->setValue (value);
597
597
            return;
598
598
        }
599
 
    m_attributes->append (new Attribute (name, value));
 
599
    if (!value.isNull ())
 
600
        m_attributes->append (new Attribute (name, value));
600
601
}
601
602
 
602
603
QString Element::getAttribute (const TrieString & name) {
609
610
void Element::init () {
610
611
    d->clear();
611
612
    for (AttributePtr a = attributes ()->first (); a; a = a->nextSibling ())
612
 
        setParam (a->name (), a->value ());
 
613
        parseParam (a->name (), a->value ());
613
614
}
614
615
 
615
616
void Element::reset () {
627
628
    m_attributes = attrs;
628
629
}
629
630
 
 
631
void Element::accept (Visitor * v) {
 
632
    v->visit (this);
 
633
}
 
634
 
630
635
//-----------------------------------------------------------------------------
631
636
 
632
637
Attribute::Attribute (const TrieString & n, const QString & v)
642
647
 
643
648
//-----------------------------------------------------------------------------
644
649
 
 
650
QString Title::caption () const {
 
651
    return title;
 
652
}
 
653
 
 
654
void Title::setCaption (const QString &) {
 
655
}
 
656
 
 
657
//-----------------------------------------------------------------------------
 
658
 
645
659
static bool hasMrlChildren (const NodePtr & e) {
646
660
    for (NodePtr c = e->firstChild (); c; c = c->nextSibling ())
647
661
        if (c->isPlayable () || hasMrlChildren (c))
650
664
}
651
665
 
652
666
Mrl::Mrl (NodePtr & d, short id)
653
 
    : Element (d, id), cached_ismrl_version (~0),
 
667
    : Title (d, id), cached_ismrl_version (~0),
 
668
      media_info (NULL),
654
669
      aspect (0), repeat (0),
655
670
      view_mode (SingleMode),
656
 
      resolved (false), bookmarkable (true) {}
 
671
      resolved (false), bookmarkable (true), access_granted (false) {}
657
672
 
658
 
Mrl::~Mrl () {}
 
673
Mrl::~Mrl () {
 
674
    if (media_info)
 
675
        delete media_info;
 
676
}
659
677
 
660
678
Node::PlayType Mrl::playType () {
661
679
    if (cached_ismrl_version != document()->m_tree_version) {
668
686
 
669
687
QString Mrl::absolutePath () {
670
688
    QString path = src;
671
 
    if (!path.isEmpty()) {
 
689
    if (!path.isEmpty() && !path.startsWith ("tv:/")) {
672
690
        for (NodePtr e = parentNode (); e; e = e->parentNode ()) {
673
691
            Mrl * mrl = e->mrl ();
674
692
            if (mrl && !mrl->src.isEmpty () && mrl->src != src) {
695
713
    return this;
696
714
}
697
715
 
698
 
void Mrl::endOfFile () {
699
 
    if (state == state_deferred &&
700
 
            !isPlayable () && firstChild ()) { // if backend added child links
701
 
        state = state_activated;
702
 
        firstChild ()->activate ();
703
 
    } else
704
 
        finish ();
 
716
void *Mrl::message (MessageType msg, void *content) {
 
717
    switch (msg) {
 
718
    case MsgMediaReady:
 
719
        linkNode ()->resolved = true;
 
720
        if (state == state_deferred) {
 
721
            if (isPlayable ()) {
 
722
                setState (state_activated);
 
723
                begin ();
 
724
            } else {
 
725
                Element::activate ();
 
726
            }
 
727
        }
 
728
        break;
 
729
 
 
730
    case MsgMediaFinished:
 
731
        if (state == state_deferred &&
 
732
                !isPlayable () && firstChild ()) {//if backend added child links
 
733
            state = state_activated;
 
734
            firstChild ()->activate ();
 
735
        } else
 
736
            finish ();
 
737
        return NULL;
 
738
 
 
739
    case MsgQueryRoleChildDisplay:
 
740
        for (NodePtr p = parentNode (); p; p = p->parentNode ())
 
741
            if (p->mrl ())
 
742
                return p->message (msg, content);
 
743
        return NULL;
 
744
 
 
745
    default:
 
746
        break;
 
747
    }
 
748
    return Node::message (msg, content);
705
749
}
706
750
 
707
751
void Mrl::activate () {
708
752
    resolved |= linkNode ()->resolved;
709
 
    if (!resolved && document ()->notify_listener)
710
 
        resolved = document ()->notify_listener->resolveURL (this);
711
 
    if (!resolved) {
 
753
    if (!resolved && linkNode () == this && isPlayable ()) {
712
754
        setState (state_deferred);
713
 
        return;
714
 
    } else
715
 
        linkNode ()->resolved = true;
716
 
    if (!isPlayable ()) {
 
755
        media_info = new MediaInfo (this, MediaManager::AudioVideo);
 
756
        resolved = media_info->wget (absolutePath ());
 
757
    } else if (isPlayable ()) {
 
758
        setState (state_activated);
 
759
        begin ();
 
760
    } else {
717
761
        Element::activate ();
718
 
        return;
719
762
    }
720
 
    setState (state_activated);
721
 
    begin ();
722
763
}
723
764
 
724
765
void Mrl::begin () {
725
 
    kdDebug () << nodeName () << " Mrl::activate" << endl;
726
 
    if (document ()->notify_listener) {
727
 
        if (linkNode () != this) {
728
 
            linkNode ()->activate ();
729
 
            if (linkNode ()->unfinished ())
730
 
                setState (state_began);
731
 
        } else if (!src.isEmpty ()) {
732
 
            if (document ()->notify_listener->requestPlayURL (this))
733
 
                setState (state_began);
734
 
        } else
735
 
            deactivate (); // nothing to activate
736
 
    }
737
 
}
738
 
 
739
 
SurfacePtr Mrl::getSurface (NodePtr node) {
740
 
    for (NodePtr p = parentNode (); p; p = p->parentNode ())
741
 
        if (p->mrl ())
742
 
            return p->getSurface (node);
743
 
    return 0L;
744
 
}
745
 
 
746
 
bool Mrl::handleEvent (EventPtr) {
747
 
    return false;
 
766
    kDebug () << nodeName () << src << this;
 
767
    if (linkNode () != this) {
 
768
        linkNode ()->activate ();
 
769
        if (linkNode ()->unfinished ())
 
770
            setState (state_began);
 
771
    } else if (!src.isEmpty ()) {
 
772
        if (!media_info)
 
773
            media_info = new MediaInfo (this, MediaManager::AudioVideo);
 
774
        if (!media_info->media)
 
775
            media_info->create ();
 
776
        if (media_info->media->play ())
 
777
            setState (state_began);
 
778
        else
 
779
            deactivate ();
 
780
    } else {
 
781
        deactivate (); // nothing to activate
 
782
    }
 
783
}
 
784
 
 
785
void Mrl::defer () {
 
786
    if (media_info && media_info->media)
 
787
        media_info->media->pause ();
 
788
    Node::defer ();
 
789
}
 
790
 
 
791
void Mrl::undefer () {
 
792
    if (media_info && media_info->media) {
 
793
        media_info->media->unpause ();
 
794
        setState (state_began);
 
795
    } else {
 
796
        Node::undefer ();
 
797
    }
 
798
}
 
799
 
 
800
void Mrl::deactivate () {
 
801
    if (media_info) {
 
802
        delete media_info;
 
803
        media_info = NULL;
 
804
    }
 
805
    Node::deactivate ();
748
806
}
749
807
 
750
808
void Mrl::parseParam (const TrieString & para, const QString & val) {
763
821
    }
764
822
}
765
823
 
766
 
Surface::Surface (NodePtr n, const SRect & r)
767
 
  : node (n),
768
 
    bounds (r),
769
 
    xscale (1.0), yscale (1.0),
770
 
    background_color (0),
771
 
    dirty (false)
772
 
#ifdef HAVE_CAIRO
773
 
    , surface (0L)
774
 
#endif
775
 
{}
776
 
 
777
 
Surface::~Surface() {
778
 
#ifdef HAVE_CAIRO
779
 
    if (surface)
780
 
        cairo_surface_destroy (surface);
781
 
#endif
782
 
}
783
 
 
784
 
void Surface::remove () {
785
 
    Surface *sp = parentNode ().ptr ();
786
 
    if (sp) {
787
 
        sp->markDirty ();
788
 
        sp->removeChild (this);
 
824
unsigned int Mrl::parseTimeString (const QString &ts) {
 
825
    QString s (ts);
 
826
    int multiply[] = { 1, 60, 60 * 60, 24 * 60 * 60, 0 };
 
827
    int mpos = 0;
 
828
    double d = 0;
 
829
    while (!s.isEmpty () && multiply[mpos]) {
 
830
        int p = s.lastIndexOf (QChar (':'));
 
831
        QString t = p >= 0 ? s.mid (p + 1) : s;
 
832
        d += multiply[mpos++] * t.toDouble();
 
833
        s = p >= 0 ? s.left (p) : QString ();
789
834
    }
790
 
}
791
 
 
792
 
void Surface::markDirty () {
793
 
    for (Surface *s = this; s; s = s->parentNode ().ptr ())
794
 
        s->dirty = true;
795
 
}
796
 
 
 
835
    if (d > 0.01)
 
836
        return (unsigned int) (d * 100);
 
837
    return 0;
 
838
}
 
839
 
 
840
//----------------------%<-----------------------------------------------------
 
841
 
 
842
EventData::EventData (Node *t, Posting *e, EventData *n)
 
843
 : target (t), event (e), next (n) {}
 
844
 
 
845
EventData::~EventData () {
 
846
    delete event;
 
847
}
797
848
//-----------------------------------------------------------------------------
798
849
 
799
850
Postpone::Postpone (NodePtr doc) : m_doc (doc) {
808
859
 
809
860
//-----------------------------------------------------------------------------
810
861
 
811
 
namespace KMPlayer {
812
 
    static NodePtr dummy_element;
813
 
}
 
862
static NodePtr dummy_element;
814
863
 
815
864
Document::Document (const QString & s, PlayListNotify * n)
816
865
 : Mrl (dummy_element, id_node_document),
817
866
   notify_listener (n),
818
867
   m_tree_version (0),
819
868
   m_PostponedListeners (new NodeRefList),
820
 
   cur_timeout (-1), intimer (false) {
 
869
   event_queue (NULL),
 
870
   paused_queue (NULL),
 
871
   cur_event (NULL),
 
872
   cur_timeout (-1) {
821
873
    m_doc = m_self; // just-in-time setting fragile m_self to m_doc
822
874
    src = s;
823
875
    editable = false;
824
876
}
825
877
 
826
878
Document::~Document () {
827
 
    kdDebug () << "~Document" << endl;
 
879
    kDebug () << "~Document " << src;
828
880
}
829
881
 
830
 
static NodePtr getElementByIdImpl (NodePtr n, const QString & id, bool inter) {
 
882
static Node *getElementByIdImpl (Node *n, const QString & id, bool inter) {
831
883
    NodePtr elm;
832
884
    if (!n->isElementNode ())
833
 
        return elm;
834
 
    Element * e = convertNode <Element> (n);
 
885
        return NULL;
 
886
    Element *e = static_cast <Element *> (n);
835
887
    if (e->getAttribute (StringPool::attr_id) == id)
836
888
        return n;
837
 
    for (NodePtr c = e->firstChild (); c; c = c->nextSibling ()) {
838
 
        if (!inter && c->mrl () && c->mrl ()->opener == n)
 
889
    for (Node *c = e->firstChild ().ptr (); c; c = c->nextSibling ().ptr ()) {
 
890
        if (!inter && c->mrl () && c->mrl ()->opener.ptr () == n)
839
891
            continue;
840
892
        if ((elm = getElementByIdImpl (c, id, inter)))
841
893
            break;
843
895
    return elm;
844
896
}
845
897
 
846
 
NodePtr Document::getElementById (const QString & id) {
 
898
Node *Document::getElementById (const QString & id) {
847
899
    return getElementByIdImpl (this, id, true);
848
900
}
849
901
 
850
 
NodePtr Document::getElementById (NodePtr n, const QString & id, bool inter) {
 
902
Node *Document::getElementById (Node *n, const QString & id, bool inter) {
851
903
    return getElementByIdImpl (n, id, inter);
852
904
}
853
905
 
876
928
}
877
929
 
878
930
void Document::undefer () {
879
 
    if (!postpone_lock) {
880
 
        Mrl::undefer ();
881
 
    } else {
882
 
        setState (state_activated);
883
 
        postpone_lock = 0L;
884
 
    }
 
931
    postpone_lock = 0L;
 
932
    Mrl::undefer ();
885
933
}
886
934
 
887
935
void Document::reset () {
888
936
    Mrl::reset ();
889
 
    if (timers.first ()) {
 
937
    if (event_queue) {
890
938
        if (notify_listener)
891
939
            notify_listener->setTimeout (-1);
892
 
        timers.clear ();
 
940
        while (event_queue) {
 
941
            EventData *ed = event_queue;
 
942
            event_queue = ed->next;
 
943
            delete ed;
 
944
        }
 
945
        cur_timeout = -1;
893
946
    }
894
947
    postpone_lock = 0L;
895
948
}
896
949
 
897
950
static inline
898
951
int diffTime (const struct timeval & tv1, const struct timeval & tv2) {
899
 
    //kdDebug () << "diffTime sec:" << ((tv1.tv_sec - tv2.tv_sec) * 1000) << " usec:" << ((tv1.tv_usec - tv2.tv_usec) /1000) << endl;
 
952
    //kDebug () << "diffTime sec:" << ((tv1.tv_sec - tv2.tv_sec) * 1000) << " usec:" << ((tv1.tv_usec - tv2.tv_usec) /1000);
900
953
    return (tv1.tv_sec - tv2.tv_sec) * 1000 + (tv1.tv_usec - tv2.tv_usec) /1000;
901
954
}
902
955
 
905
958
    tv.tv_usec = (tv.tv_usec + ms*1000) % 1000000;
906
959
}
907
960
 
 
961
KDE_NO_CDTOR_EXPORT UpdateEvent::UpdateEvent (Document *doc, unsigned int skip)
 
962
 : skipped_time (skip) {
 
963
    struct timeval tv;
 
964
    doc->timeOfDay (tv);
 
965
    cur_event_time = doc->last_event_time;
 
966
}
 
967
 
 
968
//-----------------------------------------------------------------------------
 
969
/*static inline void subtractTime (struct timeval & tv, int ms) {
 
970
    int sec = ms / 1000;
 
971
    int msec = ms % 1000;
 
972
    tv.tv_sec -= sec;
 
973
    if (tv.tv_usec / 1000 >= msec) {
 
974
        tv.tv_usec -= msec * 1000;
 
975
    } else {
 
976
        tv.tv_sec--;
 
977
        tv.tv_usec = 1000000 - (msec - tv.tv_usec / 1000 );
 
978
    }
 
979
}*/
 
980
 
908
981
void Document::timeOfDay (struct timeval & tv) {
909
982
    gettimeofday (&tv, 0L);
910
983
    if (!first_event_time.tv_sec) {
911
984
        first_event_time = tv;
912
985
        last_event_time = 0;
913
 
    } else
914
 
        last_event_time = diffTime (tv, first_event_time) / 100;
915
 
}
916
 
 
917
 
TimerInfoPtrW Document::setTimeout (NodePtr n, int ms, unsigned id) {
 
986
    } else {
 
987
        last_event_time = diffTime (tv, first_event_time);
 
988
    }
 
989
}
 
990
 
 
991
static bool postponedSensible (MessageType msg) {
 
992
    return msg == MsgEventTimer ||
 
993
        msg == MsgEventStarted ||
 
994
        msg == MsgEventStopped;
 
995
}
 
996
 
 
997
void Document::insertPosting (Node *n, Posting *e, const struct timeval &tv) {
918
998
    if (!notify_listener)
919
 
        return 0L;
920
 
    TimerInfoPtr ti = timers.first ();
921
 
    int pos = 0;
922
 
    struct timeval tv;
923
 
    timeOfDay (tv);
 
999
        return;
 
1000
    bool postponed_sensible = postponedSensible (e->message);
 
1001
    EventData *prev = NULL;
 
1002
    EventData *ed = event_queue;
 
1003
    for (; ed; ed = ed->next) {
 
1004
        int diff = diffTime (ed->timeout, tv);
 
1005
        bool psens = postponedSensible (ed->event->message);
 
1006
        if ((diff > 0 && postponed_sensible == psens) || (!postponed_sensible && psens))
 
1007
            break;
 
1008
        prev = ed;
 
1009
    }
 
1010
    ed = new EventData (n, e, ed);
 
1011
    ed->timeout = tv;
 
1012
    if (prev)
 
1013
        prev->next = ed;
 
1014
    else
 
1015
        event_queue = ed;
 
1016
    //kDebug () << "setTimeout " << ms << " at:" << pos << " tv:" << tv.tv_sec << "." << tv.tv_usec;
 
1017
}
 
1018
 
 
1019
void Document::setNextTimeout (const struct timeval &now) {
 
1020
    if (!cur_event) {              // if we're not processing events
 
1021
        int timeout = 0x7FFFFFFF;
 
1022
        if (event_queue && active () &&
 
1023
                (!postpone_ref || !postponedSensible (event_queue->event->message)))
 
1024
            timeout = diffTime (event_queue->timeout, now);
 
1025
        timeout = 0x7FFFFFFF != timeout ? (timeout > 0 ? timeout : 0) : -1;
 
1026
        if (timeout != cur_timeout) {
 
1027
            cur_timeout = timeout;
 
1028
            notify_listener->setTimeout (cur_timeout);
 
1029
        }
 
1030
    }
 
1031
}
 
1032
 
 
1033
void Document::updateTimeout () {
 
1034
    if (!postpone_ref && event_queue && notify_listener) {
 
1035
        struct timeval now;
 
1036
        if (cur_event)
 
1037
            now = cur_event->timeout;
 
1038
        else
 
1039
            timeOfDay (now);
 
1040
        setNextTimeout (now);
 
1041
    }
 
1042
}
 
1043
 
 
1044
Posting *Document::post (Node *n, Posting *e) {
 
1045
    int ms = e->message == MsgEventTimer
 
1046
        ? static_cast<TimerPosting *>(e)->milli_sec
 
1047
        : 0;
 
1048
    struct timeval now, tv;
 
1049
    if (cur_event)
 
1050
        now = cur_event->timeout;
 
1051
    else
 
1052
        timeOfDay (now);
 
1053
    tv = now;
924
1054
    addTime (tv, ms);
925
 
    for (; ti && diffTime (ti->timeout, tv) <= 0; ti = ti->nextSibling ()) {
926
 
        pos++;
927
 
        //kdDebug () << "setTimeout tv:" << tv.tv_sec << "." << tv.tv_usec << " "  << ti->timeout.tv_sec << "." << ti->timeout.tv_usec << endl;
928
 
    }
929
 
    TimerInfo * tinfo = new TimerInfo (n, id, tv, ms);
930
 
    timers.insertBefore (tinfo, ti);
931
 
    //kdDebug () << "setTimeout " << ms << " at:" << pos << " tv:" << tv.tv_sec << "." << tv.tv_usec << endl;
932
 
    if (!postpone_ref && pos == 0 && !intimer) { // timer() does that too
933
 
        cur_timeout = ms;
934
 
        notify_listener->setTimeout (ms);
935
 
    }
936
 
    return tinfo;
937
 
}
938
 
 
939
 
void Document::cancelTimer (TimerInfoPtr tinfo) {
940
 
    if (!postpone_ref && !intimer && tinfo == timers.first ()) {
941
 
        //kdDebug () << "cancel first" << endl;
942
 
        TimerInfoPtr second = tinfo->nextSibling ();
943
 
        if (second) {
944
 
            struct timeval now;
945
 
            timeOfDay (now);
946
 
            int diff = diffTime (now, second->timeout);
947
 
            cur_timeout = diff > 0 ? 0 : -diff;
948
 
        } else
949
 
            cur_timeout = -1;
950
 
        notify_listener->setTimeout (cur_timeout);
951
 
    }
952
 
    timers.remove (tinfo);
953
 
}
954
 
 
955
 
bool Document::timer () {
956
 
    struct timeval now = { 0, 0 }; // unset
957
 
    int new_timeout = -1;
958
 
    TimerInfoPtrW tinfo = timers.first (); // keep use_count on 1
959
 
 
960
 
    intimer = true;
961
 
    // handle max 100 timeouts with timeout set to now
962
 
    for (int i = 0; !!tinfo && !postpone_ref && i < 100; ++i) {
963
 
        if (tinfo && !tinfo->node) {
964
 
            // some part of document has gone and didn't remove timer
965
 
            kdError () << "spurious timer" << endl;
966
 
            for (; tinfo && !tinfo->node; tinfo = timers.first ())
967
 
                timers.remove (tinfo);
968
 
            tinfo = timers.first ();
969
 
        }
970
 
        if (!tinfo)
971
 
            break;
972
 
        TimerEvent * te = new TimerEvent (tinfo);
973
 
        EventPtr e (te);
974
 
        tinfo->node->handleEvent (e);
975
 
        if (tinfo) { // may be removed from timers and become 0
976
 
            if (te->interval) {
977
 
                TimerInfoPtr tinfo2 (tinfo); // prevent destruction
978
 
                timers.remove (tinfo);
979
 
                timeOfDay (now);
980
 
                int drift = diffTime (now, tinfo2->timeout);
981
 
                if (drift > tinfo2->milli_sec) {
982
 
                    drift = tinfo2->milli_sec;
983
 
                    //kdWarning() << "time drift" << endl;
984
 
                }
985
 
                tinfo2->timeout = now;
986
 
                addTime (tinfo2->timeout, tinfo2->milli_sec - drift);
987
 
                TimerInfoPtr ti = timers.first ();
988
 
                int pos = 0;
989
 
                for (; ti && diffTime (tinfo2->timeout, ti->timeout) >= 0; ti = ti->nextSibling ()) {
990
 
                    pos++;
991
 
                }
992
 
                timers.insertBefore (tinfo2, ti);
993
 
            } else
994
 
                timers.remove (tinfo);
995
 
        }
996
 
        tinfo = timers.first ();
997
 
        if (!tinfo)
998
 
            break;
999
 
        if (!now.tv_sec)
1000
 
            timeOfDay (now);
1001
 
        int diff = diffTime (now, tinfo->timeout);
1002
 
        new_timeout = diff > 0 ? 0 : -diff;
1003
 
        if (new_timeout > 0)
1004
 
            break;
1005
 
    }
1006
 
    intimer = false;
1007
 
 
1008
 
    // set new timeout to prevent interval timer events
1009
 
    if (notify_listener && !postpone_ref && tinfo) {
1010
 
        if (new_timeout != cur_timeout) {
1011
 
            cur_timeout = new_timeout;
1012
 
            notify_listener->setTimeout (cur_timeout);
1013
 
        }
1014
 
        // else keep the timer, no new setTimeout
1015
 
    } else {
1016
 
        cur_timeout = -1;
1017
 
        notify_listener->setTimeout (-1); // kill timer
1018
 
    }
1019
 
    return false;
 
1055
    insertPosting (n, e, tv);
 
1056
    if (postpone_ref || event_queue->event == e)
 
1057
        setNextTimeout (now);
 
1058
    return e;
 
1059
}
 
1060
 
 
1061
static EventData *findPosting (EventData *queue, EventData **prev, const Posting *e) {
 
1062
    *prev = NULL;
 
1063
    for (EventData *ed = queue; ed; ed = ed->next) {
 
1064
        if (e == ed->event)
 
1065
            return ed;
 
1066
        *prev = ed;
 
1067
    }
 
1068
    return NULL;
 
1069
}
 
1070
 
 
1071
void Document::cancelPosting (Posting *e) {
 
1072
    if (cur_event && cur_event->event == e) {
 
1073
        delete cur_event->event;
 
1074
        cur_event->event = NULL;
 
1075
    } else {
 
1076
        EventData *prev;
 
1077
        EventData **queue = &event_queue;
 
1078
        EventData *ed = findPosting (event_queue, &prev, e);
 
1079
        if (!ed) {
 
1080
            ed = findPosting (paused_queue, &prev, e);
 
1081
            queue = &paused_queue;
 
1082
        }
 
1083
        if (ed) {
 
1084
            if (prev) {
 
1085
                prev->next = ed->next;
 
1086
            } else {
 
1087
                *queue = ed->next;
 
1088
                if (!cur_event && queue == &event_queue) {
 
1089
                    struct timeval now;
 
1090
                    if (event_queue) // save a sys call
 
1091
                        timeOfDay (now);
 
1092
                    setNextTimeout (now);
 
1093
                }
 
1094
            }
 
1095
            delete ed;
 
1096
        } else {
 
1097
            kError () << "Posting not found";
 
1098
        }
 
1099
    }
 
1100
}
 
1101
 
 
1102
void Document::pausePosting (Posting *e) {
 
1103
    if (cur_event && cur_event->event == e) {
 
1104
        paused_queue = new EventData (cur_event->target, cur_event->event, paused_queue);
 
1105
        paused_queue->timeout = cur_event->timeout;
 
1106
        cur_event->event = NULL;
 
1107
    } else {
 
1108
        EventData *prev;
 
1109
        EventData *ed = findPosting (event_queue, &prev, e);
 
1110
        if (ed) {
 
1111
            if (prev)
 
1112
                prev->next = ed->next;
 
1113
            else
 
1114
                event_queue = ed->next;
 
1115
            ed->next = paused_queue;
 
1116
            paused_queue = ed;
 
1117
        } else {
 
1118
            kError () << "pauseEvent not found";
 
1119
        }
 
1120
    }
 
1121
}
 
1122
 
 
1123
void Document::unpausePosting (Posting *e, int ms) {
 
1124
    EventData *prev;
 
1125
    EventData *ed = findPosting (paused_queue, &prev, e);
 
1126
    if (ed) {
 
1127
        if (prev)
 
1128
            prev->next = ed->next;
 
1129
        else
 
1130
            paused_queue = ed->next;
 
1131
        addTime (ed->timeout, ms);
 
1132
        insertPosting (ed->target, ed->event, ed->timeout);
 
1133
        ed->event = NULL;
 
1134
        delete ed;
 
1135
    } else {
 
1136
        kError () << "pausePosting not found";
 
1137
    }
 
1138
}
 
1139
 
 
1140
void Document::timer () {
 
1141
    struct timeval now;
 
1142
    cur_event = event_queue;
 
1143
    if (cur_event) {
 
1144
        NodePtrW guard = this;
 
1145
        struct timeval start = cur_event->timeout;
 
1146
        timeOfDay (now);
 
1147
 
 
1148
        // handle max 100 timeouts with timeout set to now
 
1149
        for (int i = 0; i < 100 && active (); ++i) {
 
1150
            if (postpone_ref && postponedSensible (cur_event->event->message))
 
1151
                break;
 
1152
            // remove from queue
 
1153
            event_queue = cur_event->next;
 
1154
 
 
1155
            if (!cur_event->target) {
 
1156
                // some part of document has gone and didn't remove timer
 
1157
                kError () << "spurious timer" << endl;
 
1158
            } else {
 
1159
                EventData *ed = cur_event;
 
1160
                cur_event->target->message (cur_event->event->message, cur_event->event);
 
1161
                if (!guard) {
 
1162
                    delete ed;
 
1163
                    return;
 
1164
                }
 
1165
                if (cur_event->event && cur_event->event->message == MsgEventTimer) {
 
1166
                    TimerPosting *te = static_cast <TimerPosting *> (cur_event->event);
 
1167
                    if (te->interval) {
 
1168
                        te->interval = false; // reset interval
 
1169
                        addTime (cur_event->timeout, te->milli_sec);
 
1170
                        insertPosting (cur_event->target,
 
1171
                                cur_event->event,
 
1172
                                cur_event->timeout);
 
1173
                        cur_event->event = NULL;
 
1174
                    }
 
1175
                }
 
1176
            }
 
1177
            delete cur_event;
 
1178
            cur_event = event_queue;
 
1179
            if (!cur_event || diffTime (cur_event->timeout, start) > 5)
 
1180
                break;
 
1181
        }
 
1182
        cur_event = NULL;
 
1183
    }
 
1184
    setNextTimeout (now);
1020
1185
}
1021
1186
 
1022
1187
PostponePtr Document::postpone () {
1023
1188
    if (postpone_ref)
1024
1189
        return postpone_ref;
1025
 
    kdDebug () << "postpone" << endl;
1026
 
    if (!intimer && notify_listener) {
1027
 
        cur_timeout = -1;
1028
 
        notify_listener->setTimeout (-1);
1029
 
    }
 
1190
    kDebug () << "postpone";
1030
1191
    PostponePtr p = new Postpone (this);
1031
1192
    postpone_ref = p;
1032
 
    propagateEvent (new PostponedEvent (true));
 
1193
    PostponedEvent event (true);
 
1194
    deliver (MsgEventPostponed, &event);
 
1195
    if (notify_listener)
 
1196
        notify_listener->enableRepaintUpdaters (false, 0);
 
1197
    if (!cur_event) {
 
1198
        struct timeval now;
 
1199
        if (event_queue) // save a sys call
 
1200
            timeOfDay (now);
 
1201
        setNextTimeout (now);
 
1202
    }
1033
1203
    return p;
1034
1204
}
1035
1205
 
1036
 
void Document::proceed (const struct timeval & postponed_time) {
1037
 
    kdDebug () << "proceed" << endl;
1038
 
    if (timers.first () && notify_listener) {
1039
 
        struct timeval now;
1040
 
        timeOfDay (now);
1041
 
        int diff = diffTime (now, postponed_time);
1042
 
        if (diff > 0) {
1043
 
            for (TimerInfoPtr t = timers.first (); t; t = t->nextSibling ())
1044
 
                addTime (t->timeout, diff);
1045
 
        }
1046
 
        if (!intimer) { // eg. postpone() + proceed() in same timer()
1047
 
            diff = diffTime (timers.first ()->timeout, now);
1048
 
            cur_timeout = diff < 0 ? 0 : diff;
1049
 
            notify_listener->setTimeout (cur_timeout);
1050
 
        }
 
1206
void Document::proceed (const struct timeval &postponed_time) {
 
1207
    kDebug () << "proceed";
 
1208
    postpone_ref = NULL;
 
1209
    struct timeval now;
 
1210
    timeOfDay (now);
 
1211
    int diff = diffTime (now, postponed_time);
 
1212
    if (event_queue) {
 
1213
        for (EventData *ed = event_queue; ed; ed = ed->next)
 
1214
            if (ed->event && postponedSensible (ed->event->message))
 
1215
                addTime (ed->timeout, diff);
 
1216
        setNextTimeout (now);
1051
1217
    }
1052
 
    propagateEvent (new PostponedEvent (false));
1053
 
}
1054
 
 
1055
 
SurfacePtr Document::getSurface (NodePtr node) {
1056
1218
    if (notify_listener)
1057
 
        return notify_listener->getSurface (node);
1058
 
    return 0L;
 
1219
        notify_listener->enableRepaintUpdaters (true, diff);
 
1220
    PostponedEvent event (false);
 
1221
    deliver (MsgEventPostponed, &event);
1059
1222
}
1060
1223
 
1061
 
NodeRefListPtr Document::listeners (unsigned int id) {
1062
 
    if (id == event_postponed)
1063
 
        return m_PostponedListeners;
1064
 
    return Mrl::listeners (id);
 
1224
void *Document::message (MessageType msg, void *content) {
 
1225
    if (MsgQueryReceivers == msg) {
 
1226
        MessageType m = (MessageType) (long) content;
 
1227
        if (MsgEventPostponed == m)
 
1228
            return m_PostponedListeners.ptr ();
 
1229
    }
 
1230
    return Mrl::message (msg, content);
1065
1231
}
1066
1232
 
1067
1233
//-----------------------------------------------------------------------------
1088
1254
 
1089
1255
//-----------------------------------------------------------------------------
1090
1256
 
1091
 
DarkNode::DarkNode (NodePtr & d, const QString & n, short id)
 
1257
DarkNode::DarkNode (NodePtr & d, const QByteArray &n, short id)
1092
1258
 : Element (d, id), name (n) {
1093
1259
}
1094
1260
 
1095
1261
NodePtr DarkNode::childFromTag (const QString & tag) {
1096
 
    return new DarkNode (m_doc, tag);
 
1262
    return new DarkNode (m_doc, tag.toUtf8 ());
1097
1263
}
1098
1264
 
1099
1265
KDE_NO_EXPORT bool DarkNode::expose () const {
1107
1273
    src = s;
1108
1274
    if (!src.isEmpty ())
1109
1275
        setAttribute (StringPool::attr_src, src);
1110
 
    pretty_name = name;
 
1276
    title = name;
1111
1277
}
1112
1278
 
1113
1279
KDE_NO_EXPORT void GenericURL::closed () {
1114
1280
    if (src.isEmpty ())
1115
1281
        src = getAttribute (StringPool::attr_src);
 
1282
    Mrl::closed ();
1116
1283
}
1117
1284
 
1118
1285
//-----------------------------------------------------------------------------
1119
1286
 
1120
 
GenericMrl::GenericMrl (NodePtr & d, const QString & s, const QString & name, const QString & tag)
 
1287
GenericMrl::GenericMrl (NodePtr & d, const QString &s, const QString &name, const QByteArray &tag)
1121
1288
 : Mrl (d, id_node_playlist_item), node_name (tag) {
1122
1289
    src = s;
1123
1290
    if (!src.isEmpty ())
1124
1291
        setAttribute (StringPool::attr_src, src);
1125
 
    pretty_name = name;
 
1292
    title = name;
1126
1293
    if (!name.isEmpty ())
1127
1294
        setAttribute (StringPool::attr_name, name);
1128
1295
}
1133
1300
        if (src.isEmpty ())
1134
1301
            src = getAttribute (StringPool::attr_url);
1135
1302
    }
1136
 
    if (pretty_name.isEmpty ())
1137
 
        pretty_name = getAttribute (StringPool::attr_name);
 
1303
    if (title.isEmpty ())
 
1304
        title = getAttribute (StringPool::attr_name);
 
1305
    Mrl::closed ();
1138
1306
}
1139
1307
 
1140
1308
bool GenericMrl::expose () const {
1141
 
    return !pretty_name.isEmpty () || //return false if no title and only one
 
1309
    return !title.isEmpty () || //return false if no title and only one
1142
1310
        previousSibling () || nextSibling ();
1143
1311
}
1144
1312
 
1145
1313
//-----------------------------------------------------------------------------
1146
1314
 
 
1315
void Visitor::visit (Element *elm) {
 
1316
    visit (static_cast <Node *> (elm));
 
1317
}
 
1318
 
 
1319
void Visitor::visit (TextNode *text) {
 
1320
    visit (static_cast <Node *> (text));
 
1321
}
 
1322
 
 
1323
//-----------------------------------------------------------------------------
 
1324
 
1147
1325
namespace KMPlayer {
1148
1326
 
1149
1327
class KMPLAYER_NO_EXPORT DocumentBuilder {
1159
1337
    bool endTag (const QString & tag);
1160
1338
    bool characterData (const QString & data);
1161
1339
    bool cdataData (const QString & data);
1162
 
#ifdef HAVE_EXPAT
 
1340
#ifdef KMPLAYER_WITH_EXPAT
1163
1341
    void cdataStart ();
1164
1342
    void cdataEnd ();
1165
1343
private:
1173
1351
DocumentBuilder::DocumentBuilder (NodePtr d, bool set_opener)
1174
1352
 : m_ignore_depth (0), m_set_opener (set_opener), m_root_is_first (false)
1175
1353
 , m_node (d), m_root (d)
1176
 
#ifdef HAVE_EXPAT
 
1354
#ifdef KMPLAYER_WITH_EXPAT
1177
1355
 , in_cdata (false)
1178
1356
#endif
1179
1357
{}
1181
1359
bool DocumentBuilder::startTag(const QString &tag, AttributeListPtr attr) {
1182
1360
    if (m_ignore_depth) {
1183
1361
        m_ignore_depth++;
1184
 
        //kdDebug () << "Warning: ignored tag " << tag.latin1 () << " ignore depth = " << m_ignore_depth << endl;
 
1362
        //kDebug () << "Warning: ignored tag " << tag.latin1 () << " ignore depth = " << m_ignore_depth;
1185
1363
    } else {
1186
1364
        NodePtr n = m_node->childFromTag (tag);
1187
1365
        if (!n) {
1188
 
            kdDebug () << "Warning: unknown tag " << tag.latin1 () << endl;
 
1366
            kDebug () << "Warning: unknown tag " << tag.latin1 ();
1189
1367
            NodePtr doc = m_root->document ();
1190
 
            n = new DarkNode (doc, tag);
 
1368
            n = new DarkNode (doc, tag.toUtf8 ());
1191
1369
        }
1192
 
        //kdDebug () << "Found tag " << tag << endl;
 
1370
        //kDebug () << "Found tag " << tag;
1193
1371
        if (n->isElementNode ())
1194
1372
            convertNode <Element> (n)->setAttributes (attr);
1195
1373
        if (m_node == n && m_node == m_root)
1210
1388
bool DocumentBuilder::endTag (const QString & tag) {
1211
1389
    if (m_ignore_depth) { // endtag to ignore
1212
1390
        m_ignore_depth--;
1213
 
        kdDebug () << "Warning: ignored end tag " << " ignore depth = " << m_ignore_depth <<  endl;
 
1391
        kDebug () << "Warning: ignored end tag " << " ignore depth = " << m_ignore_depth;
1214
1392
    } else {  // endtag
1215
1393
        NodePtr n = m_node;
1216
1394
        while (n) {
1217
1395
            if (!strcasecmp (n->nodeName (), tag.local8Bit ().data ()) &&
1218
1396
                    (m_root_is_first || n != m_root)) {
1219
1397
                while (n != m_node) {
1220
 
                    kdWarning() << m_node->nodeName () << " not closed" << endl;
 
1398
                    kWarning() << m_node->nodeName () << " not closed";
1221
1399
                    if (m_root == m_node->parentNode ())
1222
1400
                        break;
1223
1401
                    m_node->closed ();
1227
1405
            }
1228
1406
            if (n == m_root) {
1229
1407
                if (n == m_node) {
1230
 
                    kdError () << "m_node == m_doc, stack underflow " << endl;
 
1408
                    kError () << "m_node == m_doc, stack underflow " << endl;
1231
1409
                    return false;
1232
1410
                }
1233
 
                kdWarning () << "endtag: no match " << tag.local8Bit () << endl;
 
1411
                kWarning () << "endtag: no match " << tag.local8Bit ();
1234
1412
                break;
1235
1413
            } else
1236
 
                 kdWarning () << "tag " << tag << " not " << n->nodeName () << endl;
 
1414
                 kWarning () << "tag " << tag << " not " << n->nodeName ();
1237
1415
            n = n ->parentNode ();
1238
1416
        }
1239
 
        //kdDebug () << "end tag " << tag << endl;
 
1417
        //kDebug () << "end tag " << tag;
1240
1418
        m_node->closed ();
1241
1419
        m_node = m_node->parentNode ();
1242
1420
    }
1245
1423
 
1246
1424
bool DocumentBuilder::characterData (const QString & data) {
1247
1425
    if (!m_ignore_depth) {
1248
 
#ifdef HAVE_EXPAT
 
1426
#ifdef KMPLAYER_WITH_EXPAT
1249
1427
        if (in_cdata)
1250
1428
            cdata += data;
1251
1429
        else
1252
1430
#endif
1253
1431
            m_node->characterData (data);
1254
1432
    }
1255
 
    //kdDebug () << "characterData " << d.latin1() << endl;
 
1433
    //kDebug () << "characterData " << d.latin1();
1256
1434
    return true;
1257
1435
}
1258
1436
 
1261
1439
        NodePtr d = m_node->document ();
1262
1440
        m_node->appendChild (new CData (d, data));
1263
1441
    }
1264
 
    //kdDebug () << "cdataData " << d.latin1() << endl;
 
1442
    //kDebug () << "cdataData " << d.latin1();
1265
1443
    return true;
1266
1444
}
1267
1445
 
1268
 
#ifdef HAVE_EXPAT
 
1446
#ifdef KMPLAYER_WITH_EXPAT
1269
1447
 
1270
1448
void DocumentBuilder::cdataStart () {
1271
1449
    cdata.truncate (0);
1312
1490
    builder->cdataEnd ();
1313
1491
}
1314
1492
 
1315
 
namespace KMPlayer {
1316
 
 
1317
1493
KMPLAYER_EXPORT
1318
 
void readXML (NodePtr root, QTextStream & in, const QString & firstline, bool set_opener) {
 
1494
void KMPlayer::readXML (NodePtr root, QTextStream & in, const QString & firstline, bool set_opener) {
1319
1495
    bool ok = true;
1320
1496
    DocumentBuilder builder (root, set_opener);
1321
1497
    XML_Parser parser = XML_ParserCreate (0L);
1325
1501
    XML_SetCdataSectionHandler (parser, cdataStart, cdataEnd);
1326
1502
    if (!firstline.isEmpty ()) {
1327
1503
        QString str (firstline + QChar ('\n'));
1328
 
        QCString buf = str.utf8 ();
 
1504
        QByteArray ba = str.utf8 ();
 
1505
        char *buf = ba.data();
1329
1506
        ok = XML_Parse(parser, buf, strlen (buf), false) != XML_STATUS_ERROR;
1330
1507
        if (!ok)
1331
 
            kdWarning () << XML_ErrorString(XML_GetErrorCode(parser)) << " at " << XML_GetCurrentLineNumber(parser) << " col " << XML_GetCurrentColumnNumber(parser) << endl;
 
1508
            kWarning () << XML_ErrorString(XML_GetErrorCode(parser)) << " at " << XML_GetCurrentLineNumber(parser) << " col " << XML_GetCurrentColumnNumber(parser);
1332
1509
    }
1333
1510
    if (ok && !in.atEnd ()) {
1334
 
        QCString buf = in.read ().utf8 ();
 
1511
        QByteArray ba = in.read ().utf8 ();
 
1512
        char *buf = ba.data();
1335
1513
        ok = XML_Parse(parser, buf, strlen (buf), true) != XML_STATUS_ERROR;
1336
1514
        if (!ok)
1337
 
            kdWarning () << XML_ErrorString(XML_GetErrorCode(parser)) << " at " << XML_GetCurrentLineNumber(parser) << " col " << XML_GetCurrentColumnNumber(parser) << endl;
 
1515
            kWarning () << XML_ErrorString(XML_GetErrorCode(parser)) << " at " << XML_GetCurrentLineNumber(parser) << " col " << XML_GetCurrentColumnNumber(parser);
1338
1516
    }
1339
1517
    XML_ParserFree(parser);
1340
1518
    root->normalize ();
1341
1519
    //return ok;
1342
1520
}
1343
1521
 
1344
 
} // namespace KMPlayer
1345
 
 
1346
1522
//-----------------------------------------------------------------------------
1347
 
#else // HAVE_EXPAT
 
1523
#else // KMPLAYER_WITH_EXPAT
1348
1524
 
1349
1525
namespace {
1350
1526
 
1417
1593
    }
1418
1594
    if (!in.atEnd ())
1419
1595
        parser.parse (in);
1420
 
    for (NodePtr e = root; e; e = e->parentNode ())
 
1596
    for (NodePtr e = root; e; e = e->parentNode ()) {
 
1597
        if (e->open)
 
1598
            break;
1421
1599
        e->closed ();
 
1600
    }
1422
1601
    //doc->normalize ();
1423
 
    //kdDebug () << root->outerXML ();
 
1602
    //kDebug () << root->outerXML ();
1424
1603
}
1425
1604
 
1426
1605
void SimpleSAXParser::push () {
1430
1609
        if (prev_token)
1431
1610
            prev_token->next = token;
1432
1611
        next_token = TokenInfoPtr (new TokenInfo);
1433
 
        //kdDebug () << "push " << token->string << endl;
 
1612
        //kDebug () << "push " << token->string;
1434
1613
    }
1435
1614
}
1436
1615
 
1437
1616
void SimpleSAXParser::push_attribute () {
1438
 
    //kdDebug () << "attribute " << attr_name.latin1 () << "=" << attr_value.latin1 () << endl;
 
1617
    //kDebug () << "attribute " << attr_name.latin1 () << "=" << attr_value.latin1 ();
1439
1618
    m_attributes->append (new Attribute (attr_name, attr_value));
1440
1619
    attr_name.truncate (0);
1441
1620
    attr_value.truncate (0);
1518
1697
                        tmp->next = token;
1519
1698
                        token = tmp;
1520
1699
                    }
1521
 
                    //kdDebug () << "entity found "<<prev_token->string << endl;
 
1700
                    //kDebug () << "entity found "<<prev_token->string;
1522
1701
                } else if (token->token == tok_hash &&
1523
1702
                        nextToken () && token->token == tok_text &&
1524
1703
                        nextToken () && token->token == tok_semi_colon) {
1525
 
                    //kdDebug () << "char entity found " << prev_token->string << prev_token->string.toInt (0L, 16) << endl;
 
1704
                    //kDebug () << "char entity found " << prev_token->string << prev_token->string.toInt (0L, 16);
1526
1705
                    token->token = tok_text;
1527
1706
                    if (!prev_token->string.startsWith (QChar ('x')))
1528
1707
                        token->string = QChar (prev_token->string.toInt ());
1578
1757
    bool closed = false;
1579
1758
    while (true) {
1580
1759
        if (!nextToken ()) return false;
1581
 
        //kdDebug () << "readAttributes " << token->string.latin1() << endl;
 
1760
        //kDebug () << "readAttributes " << token->string.latin1();
1582
1761
        if ((in_dbl_quote && token->token != tok_double_quote) ||
1583
1762
                    (in_sngl_quote && token->token != tok_single_quote)) {
1584
1763
            attr_value += token->string;
1587
1766
                return false;
1588
1767
            if (equal_seen)
1589
1768
                attr_value += token->string; // EQ=a=2c ???
1590
 
            //kdDebug () << "equal_seen"<< endl;
 
1769
            //kDebug () << "equal_seen";
1591
1770
            equal_seen = true;
1592
1771
        } else if (token->token == tok_white_space) {
1593
1772
            if (!attr_value.isEmpty ())
1610
1789
                in_dbl_quote = true;
1611
1790
            else
1612
1791
                attr_value += token->string;
1613
 
            //kdDebug () << "in_dbl_quote:"<< in_dbl_quote << endl;
 
1792
            //kDebug () << "in_dbl_quote:"<< in_dbl_quote;
1614
1793
        } else if (token->token == tok_slash) {
1615
1794
            TokenInfoPtr mark_token = token;
1616
1795
            if (nextToken () &&
1617
1796
                    (token->token != tok_white_space || nextToken()) &&//<e / >
1618
1797
                    token->token == tok_angle_close) {
1619
 
            //kdDebug () << "close mark:"<< endl;
 
1798
            //kDebug () << "close mark:";
1620
1799
                closed = true;
1621
1800
                break;
1622
1801
            } else {
1623
1802
                token = mark_token;
1624
 
            //kdDebug () << "not end mark:"<< equal_seen << endl;
 
1803
            //kDebug () << "not end mark:"<< equal_seen;
1625
1804
                if (equal_seen)
1626
1805
                    attr_value += token->string; // ABBR=w/o ???
1627
1806
                else
1643
1822
            /*const AttributeMap::const_iterator e = attr.end ();
1644
1823
            for (AttributeMap::const_iterator i = attr.begin (); i != e; ++i)
1645
1824
                if (!strcasecmp (i.key ().latin1 (), "encoding"))
1646
 
                  kdDebug () << "encodeing " << i.data().latin1() << endl;*/
 
1825
                  kDebug () << "encodeing " << i.data().latin1();*/
1647
1826
        }
1648
1827
    } else {
1649
1828
        have_error = builder.startTag (tagname, m_attributes);
1650
1829
        if (closed)
1651
1830
            have_error &= builder.endTag (tagname);
1652
 
        //kdDebug () << "readTag " << tagname << " closed:" << closed << " ok:" << have_error << endl;
 
1831
        //kDebug () << "readTag " << tagname << " closed:" << closed << " ok:" << have_error;
1653
1832
    }
1654
1833
    m_state = m_state->next; // pop Node or PI
1655
1834
    return true;
1678
1857
        m_state = new StateInfo (InComment, m_state->next); // note: pop DTD
1679
1858
        return readComment ();
1680
1859
    }
1681
 
    //kdDebug () << "readDTD: " << token->string.latin1 () << endl;
 
1860
    //kDebug () << "readDTD: " << token->string.latin1 ();
1682
1861
    if (token->token == tok_cdata_start) {
1683
1862
        m_state = new StateInfo (InCDATA, m_state->next); // note: pop DTD
1684
1863
        if (token->next) {
1752
1931
    if (!nextToken ()) return false;
1753
1932
    if (token->token == tok_exclamation) {
1754
1933
        m_state = new StateInfo (InDTDTag, m_state->next);
1755
 
    //kdDebug () << "readTag: " << token->string.latin1 () << endl;
 
1934
    //kDebug () << "readTag: " << token->string.latin1 ();
1756
1935
        return readDTD ();
1757
1936
    }
1758
1937
    if (token->token == tok_white_space)
1768
1947
    if (token->token != tok_text)
1769
1948
        return false; // FIXME entities
1770
1949
    tagname = token->string;
1771
 
    //kdDebug () << "readTag " << tagname.latin1() << endl;
 
1950
    //kDebug () << "readTag " << tagname.latin1();
1772
1951
    m_state = new StateInfo (InAttributes, m_state);
1773
1952
    return readAttributes ();
1774
1953
}
1821
2000
                    } else {
1822
2001
                        if (!white_space.isEmpty ()) {
1823
2002
                            if (!in_character_data) {
1824
 
                                int pos = white_space.findRev (QChar ('\n'));
 
2003
                                int pos = white_space.lastIndexOf (QChar ('\n'));
1825
2004
                                if (pos > -1)
1826
2005
                                    white_space = white_space.mid (pos + 1);
1827
2006
                            }
1839
2018
    return false; // need more data
1840
2019
}
1841
2020
 
1842
 
#endif // HAVE_EXPAT
 
2021
#endif // KMPLAYER_WITH_EXPAT