35
32
#include "kmplayer_rss.h"
36
33
#include "kmplayer_smil.h"
37
34
#include "kmplayer_xspf.h"
35
#include "mediaobject.h"
39
37
#ifdef SHAREDPTR_DEBUG
40
int shared_data_count;
38
KMPLAYER_EXPORT int shared_data_count;
43
41
using namespace KMPlayer;
45
43
//-----------------------------------------------------------------------------
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);
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);
70
67
//-----------------------------------------------------------------------------
74
XMLStringlet (const QString & s) : str (s) {}
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 ('<')) {
218
227
setState (state_began);
220
kdError () << nodeName() << " begin call on not active element" << endl;
229
kError () << nodeName() << " begin call on not active element" << endl;
223
232
void Node::defer () {
225
234
setState (state_deferred);
227
kdError () << "Node::defer () call on not activated element" << endl;
236
kError () << "Node::defer () call on not activated element" << endl;
230
239
void Node::undefer () {
231
240
if (state == state_deferred) {
232
setState (state_activated);
241
if (firstChild () && firstChild ()->state > state_init) {
244
setState (state_activated);
235
kdWarning () <<"Node::undefer () call on not deferred element"<< endl;
248
kWarning () << nodeName () << " call on not deferred element";
238
251
void Node::finish () {
240
253
setState (state_finished);
242
m_parent->childDone (this);
255
document ()->post (m_parent, new Posting (this, MsgChildFinished));
244
257
deactivate (); // document deactivates itself on finish
246
kdWarning () <<"Node::finish () call on not active element"<< endl;
259
kWarning () <<"Node::finish () call on not active element";
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 ();
257
271
break; // remaining not yet activated
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));
263
277
void Node::reset () {
264
//kdDebug () << nodeName () << " Node::reset" << endl;
278
//kDebug () << nodeName () << " Node::reset";
280
setState (state_resetting);
267
283
setState (state_init);
268
284
for (NodePtr e = firstChild (); e; e = e->nextSibling ()) {
269
285
if (e->state != state_init)
698
void Mrl::endOfFile () {
699
if (state == state_deferred &&
700
!isPlayable () && firstChild ()) { // if backend added child links
701
state = state_activated;
702
firstChild ()->activate ();
716
void *Mrl::message (MessageType msg, void *content) {
719
linkNode ()->resolved = true;
720
if (state == state_deferred) {
722
setState (state_activated);
725
Element::activate ();
730
case MsgMediaFinished:
731
if (state == state_deferred &&
732
!isPlayable () && firstChild ()) {//if backend added child links
733
state = state_activated;
734
firstChild ()->activate ();
739
case MsgQueryRoleChildDisplay:
740
for (NodePtr p = parentNode (); p; p = p->parentNode ())
742
return p->message (msg, content);
748
return Node::message (msg, content);
707
751
void Mrl::activate () {
708
752
resolved |= linkNode ()->resolved;
709
if (!resolved && document ()->notify_listener)
710
resolved = document ()->notify_listener->resolveURL (this);
753
if (!resolved && linkNode () == this && isPlayable ()) {
712
754
setState (state_deferred);
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);
717
761
Element::activate ();
720
setState (state_activated);
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);
735
deactivate (); // nothing to activate
739
SurfacePtr Mrl::getSurface (NodePtr node) {
740
for (NodePtr p = parentNode (); p; p = p->parentNode ())
742
return p->getSurface (node);
746
bool Mrl::handleEvent (EventPtr) {
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 ()) {
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);
781
deactivate (); // nothing to activate
786
if (media_info && media_info->media)
787
media_info->media->pause ();
791
void Mrl::undefer () {
792
if (media_info && media_info->media) {
793
media_info->media->unpause ();
794
setState (state_began);
800
void Mrl::deactivate () {
750
808
void Mrl::parseParam (const TrieString & para, const QString & val) {
905
958
tv.tv_usec = (tv.tv_usec + ms*1000) % 1000000;
961
KDE_NO_CDTOR_EXPORT UpdateEvent::UpdateEvent (Document *doc, unsigned int skip)
962
: skipped_time (skip) {
965
cur_event_time = doc->last_event_time;
968
//-----------------------------------------------------------------------------
969
/*static inline void subtractTime (struct timeval & tv, int ms) {
971
int msec = ms % 1000;
973
if (tv.tv_usec / 1000 >= msec) {
974
tv.tv_usec -= msec * 1000;
977
tv.tv_usec = 1000000 - (msec - tv.tv_usec / 1000 );
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;
914
last_event_time = diffTime (tv, first_event_time) / 100;
917
TimerInfoPtrW Document::setTimeout (NodePtr n, int ms, unsigned id) {
987
last_event_time = diffTime (tv, first_event_time);
991
static bool postponedSensible (MessageType msg) {
992
return msg == MsgEventTimer ||
993
msg == MsgEventStarted ||
994
msg == MsgEventStopped;
997
void Document::insertPosting (Node *n, Posting *e, const struct timeval &tv) {
918
998
if (!notify_listener)
920
TimerInfoPtr ti = timers.first ();
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))
1010
ed = new EventData (n, e, ed);
1016
//kDebug () << "setTimeout " << ms << " at:" << pos << " tv:" << tv.tv_sec << "." << tv.tv_usec;
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);
1033
void Document::updateTimeout () {
1034
if (!postpone_ref && event_queue && notify_listener) {
1037
now = cur_event->timeout;
1040
setNextTimeout (now);
1044
Posting *Document::post (Node *n, Posting *e) {
1045
int ms = e->message == MsgEventTimer
1046
? static_cast<TimerPosting *>(e)->milli_sec
1048
struct timeval now, tv;
1050
now = cur_event->timeout;
924
1054
addTime (tv, ms);
925
for (; ti && diffTime (ti->timeout, tv) <= 0; ti = ti->nextSibling ()) {
927
//kdDebug () << "setTimeout tv:" << tv.tv_sec << "." << tv.tv_usec << " " << ti->timeout.tv_sec << "." << ti->timeout.tv_usec << endl;
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
934
notify_listener->setTimeout (ms);
939
void Document::cancelTimer (TimerInfoPtr tinfo) {
940
if (!postpone_ref && !intimer && tinfo == timers.first ()) {
941
//kdDebug () << "cancel first" << endl;
942
TimerInfoPtr second = tinfo->nextSibling ();
946
int diff = diffTime (now, second->timeout);
947
cur_timeout = diff > 0 ? 0 : -diff;
950
notify_listener->setTimeout (cur_timeout);
952
timers.remove (tinfo);
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
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 ();
972
TimerEvent * te = new TimerEvent (tinfo);
974
tinfo->node->handleEvent (e);
975
if (tinfo) { // may be removed from timers and become 0
977
TimerInfoPtr tinfo2 (tinfo); // prevent destruction
978
timers.remove (tinfo);
980
int drift = diffTime (now, tinfo2->timeout);
981
if (drift > tinfo2->milli_sec) {
982
drift = tinfo2->milli_sec;
983
//kdWarning() << "time drift" << endl;
985
tinfo2->timeout = now;
986
addTime (tinfo2->timeout, tinfo2->milli_sec - drift);
987
TimerInfoPtr ti = timers.first ();
989
for (; ti && diffTime (tinfo2->timeout, ti->timeout) >= 0; ti = ti->nextSibling ()) {
992
timers.insertBefore (tinfo2, ti);
994
timers.remove (tinfo);
996
tinfo = timers.first ();
1001
int diff = diffTime (now, tinfo->timeout);
1002
new_timeout = diff > 0 ? 0 : -diff;
1003
if (new_timeout > 0)
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);
1014
// else keep the timer, no new setTimeout
1017
notify_listener->setTimeout (-1); // kill timer
1055
insertPosting (n, e, tv);
1056
if (postpone_ref || event_queue->event == e)
1057
setNextTimeout (now);
1061
static EventData *findPosting (EventData *queue, EventData **prev, const Posting *e) {
1063
for (EventData *ed = queue; ed; ed = ed->next) {
1071
void Document::cancelPosting (Posting *e) {
1072
if (cur_event && cur_event->event == e) {
1073
delete cur_event->event;
1074
cur_event->event = NULL;
1077
EventData **queue = &event_queue;
1078
EventData *ed = findPosting (event_queue, &prev, e);
1080
ed = findPosting (paused_queue, &prev, e);
1081
queue = &paused_queue;
1085
prev->next = ed->next;
1088
if (!cur_event && queue == &event_queue) {
1090
if (event_queue) // save a sys call
1092
setNextTimeout (now);
1097
kError () << "Posting not found";
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;
1109
EventData *ed = findPosting (event_queue, &prev, e);
1112
prev->next = ed->next;
1114
event_queue = ed->next;
1115
ed->next = paused_queue;
1118
kError () << "pauseEvent not found";
1123
void Document::unpausePosting (Posting *e, int ms) {
1125
EventData *ed = findPosting (paused_queue, &prev, e);
1128
prev->next = ed->next;
1130
paused_queue = ed->next;
1131
addTime (ed->timeout, ms);
1132
insertPosting (ed->target, ed->event, ed->timeout);
1136
kError () << "pausePosting not found";
1140
void Document::timer () {
1142
cur_event = event_queue;
1144
NodePtrW guard = this;
1145
struct timeval start = cur_event->timeout;
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))
1152
// remove from queue
1153
event_queue = cur_event->next;
1155
if (!cur_event->target) {
1156
// some part of document has gone and didn't remove timer
1157
kError () << "spurious timer" << endl;
1159
EventData *ed = cur_event;
1160
cur_event->target->message (cur_event->event->message, cur_event->event);
1165
if (cur_event->event && cur_event->event->message == MsgEventTimer) {
1166
TimerPosting *te = static_cast <TimerPosting *> (cur_event->event);
1168
te->interval = false; // reset interval
1169
addTime (cur_event->timeout, te->milli_sec);
1170
insertPosting (cur_event->target,
1172
cur_event->timeout);
1173
cur_event->event = NULL;
1178
cur_event = event_queue;
1179
if (!cur_event || diffTime (cur_event->timeout, start) > 5)
1184
setNextTimeout (now);
1022
1187
PostponePtr Document::postpone () {
1023
1188
if (postpone_ref)
1024
1189
return postpone_ref;
1025
kdDebug () << "postpone" << endl;
1026
if (!intimer && notify_listener) {
1028
notify_listener->setTimeout (-1);
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);
1199
if (event_queue) // save a sys call
1201
setNextTimeout (now);
1036
void Document::proceed (const struct timeval & postponed_time) {
1037
kdDebug () << "proceed" << endl;
1038
if (timers.first () && notify_listener) {
1041
int diff = diffTime (now, postponed_time);
1043
for (TimerInfoPtr t = timers.first (); t; t = t->nextSibling ())
1044
addTime (t->timeout, diff);
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);
1206
void Document::proceed (const struct timeval &postponed_time) {
1207
kDebug () << "proceed";
1208
postpone_ref = NULL;
1211
int diff = diffTime (now, postponed_time);
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);
1052
propagateEvent (new PostponedEvent (false));
1055
SurfacePtr Document::getSurface (NodePtr node) {
1056
1218
if (notify_listener)
1057
return notify_listener->getSurface (node);
1219
notify_listener->enableRepaintUpdaters (true, diff);
1220
PostponedEvent event (false);
1221
deliver (MsgEventPostponed, &event);
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 ();
1230
return Mrl::message (msg, content);
1067
1233
//-----------------------------------------------------------------------------