File indexing completed on 2024-04-21 15:38:09
0001 /** 0002 * Copyright (C) 2006 by Koos Vriezen <koos.vriezen@gmail.com> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Library General Public 0006 * License version 2 as published by the Free Software Foundation. 0007 * 0008 * This library is distributed in the hope that it will be useful, 0009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0011 * Library General Public License for more details. 0012 * 0013 * You should have received a copy of the GNU Library General Public License 0014 * along with this library; see the file COPYING.LIB. If not, write to 0015 * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 0016 * Boston, MA 02110-1301, USA. 0017 **/ 0018 0019 #include "config-kmplayer.h" 0020 0021 #include <qcolor.h> 0022 #include <qtimer.h> 0023 0024 #include <kdebug.h> 0025 0026 #include "kmplayer_rp.h" 0027 #include "kmplayer_smil.h" 0028 #include "mediaobject.h" 0029 0030 using namespace KMPlayer; 0031 0032 0033 KDE_NO_CDTOR_EXPORT RP::Imfl::Imfl (NodePtr & d) 0034 : Mrl (d, id_node_imfl), 0035 fit (fit_hidden), 0036 duration (0), 0037 duration_timer (NULL), 0038 needs_scene_img (0) {} 0039 0040 KDE_NO_CDTOR_EXPORT RP::Imfl::~Imfl () { 0041 } 0042 0043 KDE_NO_EXPORT void RP::Imfl::closed () { 0044 for (Node *n = firstChild (); n; n = n->nextSibling ()) 0045 if (RP::id_node_head == n->id) { 0046 Attribute *a = static_cast <Element *> (n)->attributes ().first (); 0047 for (; a; a = a->nextSibling ()) { 0048 if (Ids::attr_width == a->name ()) { 0049 size.width = a->value ().toInt (); 0050 } else if (Ids::attr_height == a->name ()) { 0051 size.height = a->value ().toInt (); 0052 } else if (a->name () == "duration") { 0053 int dur; 0054 parseTime (a->value ().toLower (), dur); 0055 duration = dur; 0056 } 0057 } 0058 } 0059 Mrl::closed (); 0060 } 0061 0062 KDE_NO_EXPORT void RP::Imfl::defer () { 0063 kDebug () << "RP::Imfl::defer "; 0064 setState (state_deferred); 0065 for (Node *n = firstChild (); n; n = n->nextSibling ()) 0066 if (n->id == RP::id_node_image && !n->active ()) 0067 n->activate (); 0068 } 0069 0070 KDE_NO_EXPORT void RP::Imfl::activate () { 0071 kDebug () << "RP::Imfl::activate "; 0072 resolved = true; 0073 setState (state_activated); 0074 int timings_count = 0; 0075 for (Node *n = firstChild (); n; n = n->nextSibling ()) 0076 switch (n->id) { 0077 case RP::id_node_crossfade: 0078 case RP::id_node_fadein: 0079 case RP::id_node_fadeout: 0080 case RP::id_node_fill: 0081 case RP::id_node_wipe: 0082 case RP::id_node_viewchange: 0083 n->activate (); // set their start timers 0084 timings_count++; 0085 break; 0086 case RP::id_node_image: 0087 if (!n->active ()) 0088 n->activate (); 0089 break; 0090 } 0091 if (duration > 0) 0092 duration_timer = document ()->post (this, 0093 new TimerPosting (duration * 10)); 0094 else if (!timings_count) 0095 finish (); 0096 } 0097 0098 KDE_NO_EXPORT void RP::Imfl::finish () { 0099 kDebug () << "RP::Imfl::finish "; 0100 Mrl::finish (); 0101 if (duration_timer) { 0102 document ()->cancelPosting (duration_timer); 0103 duration_timer = 0; 0104 } 0105 for (NodePtr n = firstChild (); n; n = n->nextSibling ()) 0106 if (n->unfinished ()) 0107 n->finish (); 0108 } 0109 0110 KDE_NO_EXPORT void RP::Imfl::deactivate () { 0111 kDebug () << "RP::Imfl::deactivate "; 0112 if (unfinished ()) 0113 finish (); 0114 else if (duration_timer) { 0115 document ()->cancelPosting (duration_timer); 0116 duration_timer = 0; 0117 } 0118 if (!active ()) 0119 return; // calling finish might call deactivate() as well 0120 setState (state_deactivated); 0121 for (NodePtr n = firstChild (); n; n = n->nextSibling ()) 0122 if (n->active ()) 0123 n->deactivate (); 0124 rp_surface = (Surface *) role (RoleChildDisplay, NULL); 0125 } 0126 0127 KDE_NO_EXPORT void RP::Imfl::message (MessageType msg, void *content) { 0128 switch (msg) { 0129 case MsgEventTimer: 0130 duration_timer = 0; 0131 if (unfinished ()) 0132 finish (); 0133 return; 0134 case MsgChildFinished: 0135 if (unfinished () && !duration_timer) { 0136 for (Node *n = firstChild (); n; n = n->nextSibling ()) 0137 switch (n->id) { 0138 case RP::id_node_crossfade: 0139 case RP::id_node_fadein: 0140 case RP::id_node_fadeout: 0141 case RP::id_node_fill: 0142 if (n->unfinished ()) 0143 return; 0144 } 0145 finish (); 0146 } 0147 return; 0148 default: 0149 break; 0150 } 0151 Mrl::message (msg, content); 0152 } 0153 0154 KDE_NO_EXPORT void RP::Imfl::accept (Visitor * v) { 0155 v->visit (this); 0156 } 0157 0158 KDE_NO_EXPORT Surface *RP::Imfl::surface () { 0159 if (!rp_surface) { 0160 rp_surface = (Surface *) Mrl::role (RoleChildDisplay, this); 0161 if (rp_surface && size.isEmpty ()) 0162 size = rp_surface->bounds.size; 0163 } 0164 return rp_surface.ptr (); 0165 } 0166 0167 KDE_NO_EXPORT Node *RP::Imfl::childFromTag (const QString & tag) { 0168 QByteArray ba = tag.toLatin1 (); 0169 const char *ctag = ba.constData (); 0170 if (!strcmp (ctag, "head")) 0171 return new DarkNode (m_doc, "head", RP::id_node_head); 0172 else if (!strcmp (ctag, "image")) 0173 return new RP::Image (m_doc); 0174 else if (!strcmp (ctag, "fill")) 0175 return new RP::Fill (m_doc); 0176 else if (!strcmp (ctag, "wipe")) 0177 return new RP::Wipe (m_doc); 0178 else if (!strcmp (ctag, "viewchange")) 0179 return new RP::ViewChange (m_doc); 0180 else if (!strcmp (ctag, "crossfade")) 0181 return new RP::Crossfade (m_doc); 0182 else if (!strcmp (ctag, "fadein")) 0183 return new RP::Fadein (m_doc); 0184 else if (!strcmp (ctag, "fadeout")) 0185 return new RP::Fadeout (m_doc); 0186 return NULL; 0187 } 0188 0189 KDE_NO_EXPORT void RP::Imfl::repaint () { 0190 if (!active ()) { 0191 kWarning () << "Spurious Imfl repaint"; 0192 } else if (surface () && !size.isEmpty ()) { 0193 rp_surface->markDirty (); 0194 rp_surface->repaint (SRect (0, 0, size)); 0195 } 0196 } 0197 0198 KDE_NO_CDTOR_EXPORT RP::Image::Image (NodePtr & doc) 0199 : Mrl (doc, id_node_image) { 0200 view_mode = WindowMode; 0201 } 0202 0203 KDE_NO_CDTOR_EXPORT RP::Image::~Image () { 0204 } 0205 0206 KDE_NO_EXPORT void RP::Image::closed () { 0207 src = getAttribute (Ids::attr_name); 0208 Mrl::closed (); 0209 } 0210 0211 KDE_NO_EXPORT void RP::Image::activate () { 0212 kDebug () << "RP::Image::activate"; 0213 setState (state_activated); 0214 isPlayable (); // update src attribute 0215 if (!media_info) 0216 media_info = new MediaInfo (this, MediaManager::Image); 0217 media_info->wget (absolutePath ()); 0218 } 0219 0220 KDE_NO_EXPORT void RP::Image::begin () { 0221 Node::begin (); 0222 } 0223 0224 KDE_NO_EXPORT void RP::Image::deactivate () { 0225 if (img_surface) { 0226 img_surface->remove (); 0227 img_surface = NULL; 0228 } 0229 setState (state_deactivated); 0230 postpone_lock = 0L; 0231 delete media_info; 0232 media_info = NULL; 0233 } 0234 0235 KDE_NO_EXPORT void RP::Image::message (MessageType msg, void *content) { 0236 if (msg == MsgMediaReady) { 0237 if (media_info) 0238 dataArrived (); 0239 } else { 0240 Mrl::message (msg, content); 0241 } 0242 } 0243 0244 KDE_NO_EXPORT void RP::Image::dataArrived () { 0245 kDebug () << "RP::Image::remoteReady"; 0246 ImageMedia *im = media_info->media ? (ImageMedia *)media_info->media : NULL; 0247 if (im && !im->isEmpty ()) { 0248 size.width = im->cached_img->width; 0249 size.height = im->cached_img->height; 0250 } 0251 postpone_lock = 0L; 0252 } 0253 0254 KDE_NO_EXPORT bool RP::Image::isReady (bool postpone_if_not) { 0255 if (media_info->downloading () && postpone_if_not) 0256 postpone_lock = document ()->postpone (); 0257 return !media_info->downloading (); 0258 } 0259 0260 KDE_NO_EXPORT Surface *RP::Image::surface () { 0261 ImageMedia *im = media_info && media_info->media 0262 ? (ImageMedia *)media_info->media : NULL; 0263 if (im && !img_surface && !im->isEmpty ()) { 0264 Node * p = parentNode (); 0265 if (p && p->id == RP::id_node_imfl) { 0266 Surface *ps = static_cast <RP::Imfl *> (p)->surface (); 0267 if (ps) 0268 img_surface = ps->createSurface (this, 0269 SRect (0, 0, size)); 0270 } 0271 } 0272 return img_surface; 0273 } 0274 0275 KDE_NO_CDTOR_EXPORT RP::TimingsBase::TimingsBase (NodePtr & d, const short i) 0276 : Element (d, i), x (0), y (0), w (0), h (0), start (0), duration (0), 0277 start_timer (NULL), duration_timer (NULL), update_timer (NULL) {} 0278 0279 KDE_NO_EXPORT void RP::TimingsBase::activate () { 0280 setState (state_activated); 0281 x = y = w = h = 0; 0282 srcx = srcy = srcw = srch = 0; 0283 for (Attribute *a = attributes ().first (); a; a = a->nextSibling ()) { 0284 if (a->name () == Ids::attr_target) { 0285 for (Node *n = parentNode()->firstChild(); n; n= n->nextSibling()) 0286 if (static_cast <Element *> (n)-> 0287 getAttribute ("handle") == a->value ()) 0288 target = n; 0289 } else if (a->name () == "start") { 0290 int dur; 0291 parseTime (a->value ().toLower (), dur); 0292 start = dur; 0293 } else if (a->name () == "duration") { 0294 int dur; 0295 parseTime (a->value ().toLower (), dur); 0296 duration = dur; 0297 } else if (a->name () == "dstx") { 0298 x = a->value ().toInt (); 0299 } else if (a->name () == "dsty") { 0300 y = a->value ().toInt (); 0301 } else if (a->name () == "dstw") { 0302 w = a->value ().toInt (); 0303 } else if (a->name () == "dsth") { 0304 h = a->value ().toInt (); 0305 } else if (a->name () == "srcx") { 0306 srcx = a->value ().toInt (); 0307 } else if (a->name () == "srcy") { 0308 srcy = a->value ().toInt (); 0309 } else if (a->name () == "srcw") { 0310 srcw = a->value ().toInt (); 0311 } else if (a->name () == "srch") { 0312 srch = a->value ().toInt (); 0313 } 0314 } 0315 start_timer = document ()->post (this, new TimerPosting (start *10)); 0316 } 0317 0318 KDE_NO_EXPORT void RP::TimingsBase::deactivate () { 0319 if (unfinished ()) 0320 finish (); 0321 else 0322 cancelTimers (); 0323 setState (state_deactivated); 0324 } 0325 0326 KDE_NO_EXPORT void RP::TimingsBase::message (MessageType msg, void *content) { 0327 switch (msg) { 0328 case MsgEventTimer: { 0329 TimerPosting *te = static_cast <TimerPosting *> (content); 0330 if (te == update_timer && duration > 0) { 0331 update (100 * 10 * ++curr_step / duration); 0332 te->interval = true; 0333 } else if (te == start_timer) { 0334 start_timer = 0; 0335 duration_timer = document()->post (this, 0336 new TimerPosting (duration * 10)); 0337 begin (); 0338 } else if (te == duration_timer) { 0339 duration_timer = 0; 0340 update (100); 0341 finish (); 0342 } 0343 break; 0344 } 0345 case MsgEventPostponed: { 0346 PostponedEvent *pe = static_cast <PostponedEvent *> (content); 0347 if (!pe->is_postponed) { 0348 document_postponed.disconnect (); 0349 update (duration > 0 ? 0 : 100); 0350 } 0351 break; 0352 } 0353 default: 0354 Element::message (msg, content); 0355 } 0356 } 0357 0358 KDE_NO_EXPORT void RP::TimingsBase::begin () { 0359 progress = 0; 0360 setState (state_began); 0361 if (target) 0362 target->begin (); 0363 if (duration > 0) { 0364 steps = duration / 10; // 10/s updates 0365 update_timer = document ()->post (this, new TimerPosting (100)); // 50ms 0366 curr_step = 1; 0367 } 0368 } 0369 0370 KDE_NO_EXPORT void RP::TimingsBase::update (int percentage) { 0371 progress = percentage; 0372 Node *p = parentNode (); 0373 if (p->id == RP::id_node_imfl) 0374 static_cast <RP::Imfl *> (p)->repaint (); 0375 } 0376 0377 KDE_NO_EXPORT void RP::TimingsBase::finish () { 0378 progress = 100; 0379 cancelTimers (); 0380 document_postponed.disconnect (); 0381 Element::finish (); 0382 } 0383 0384 KDE_NO_EXPORT void RP::TimingsBase::cancelTimers () { 0385 if (start_timer) { 0386 document ()->cancelPosting (start_timer); 0387 start_timer = 0; 0388 } else if (duration_timer) { 0389 document ()->cancelPosting (duration_timer); 0390 duration_timer = 0; 0391 } 0392 if (update_timer) { 0393 document ()->cancelPosting (update_timer); 0394 update_timer = 0; 0395 } 0396 } 0397 0398 KDE_NO_EXPORT void RP::Crossfade::activate () { 0399 TimingsBase::activate (); 0400 } 0401 0402 KDE_NO_EXPORT void RP::Crossfade::begin () { 0403 //kDebug () << "RP::Crossfade::begin"; 0404 TimingsBase::begin (); 0405 if (target && target->id == id_node_image) { 0406 RP::Image * img = static_cast <RP::Image *> (target.ptr ()); 0407 if (!img->isReady (true)) 0408 document_postponed.connect (document(), MsgEventPostponed, this); 0409 else 0410 update (duration > 0 ? 0 : 100); 0411 } 0412 } 0413 0414 KDE_NO_EXPORT void RP::Crossfade::accept (Visitor * v) { 0415 v->visit (this); 0416 } 0417 0418 KDE_NO_EXPORT void RP::Fadein::activate () { 0419 // pickup color from Fill that should be declared before this node 0420 from_color = 0; 0421 TimingsBase::activate (); 0422 } 0423 0424 KDE_NO_EXPORT void RP::Fadein::begin () { 0425 //kDebug () << "RP::Fadein::begin"; 0426 TimingsBase::begin (); 0427 if (target && target->id == id_node_image) { 0428 RP::Image * img = static_cast <RP::Image *> (target.ptr ()); 0429 if (!img->isReady (true)) 0430 document_postponed.connect (document(), MsgEventPostponed, this); 0431 else 0432 update (duration > 0 ? 0 : 100); 0433 } 0434 } 0435 0436 KDE_NO_EXPORT void RP::Fadein::accept (Visitor * v) { 0437 v->visit (this); 0438 } 0439 0440 KDE_NO_EXPORT void RP::Fadeout::activate () { 0441 to_color = QColor (getAttribute ("color")).rgb (); 0442 TimingsBase::activate (); 0443 } 0444 0445 KDE_NO_EXPORT void RP::Fadeout::begin () { 0446 //kDebug () << "RP::Fadeout::begin"; 0447 TimingsBase::begin (); 0448 } 0449 0450 KDE_NO_EXPORT void RP::Fadeout::accept (Visitor * v) { 0451 v->visit (this); 0452 } 0453 0454 KDE_NO_EXPORT void RP::Fill::activate () { 0455 color = QColor (getAttribute ("color")).rgb (); 0456 TimingsBase::activate (); 0457 } 0458 0459 KDE_NO_EXPORT void RP::Fill::begin () { 0460 setState (state_began); 0461 update (0); 0462 } 0463 0464 KDE_NO_EXPORT void RP::Fill::accept (Visitor * v) { 0465 v->visit (this); 0466 } 0467 0468 KDE_NO_EXPORT void RP::Wipe::activate () { 0469 //TODO implement 'type="push"' 0470 QString dir = getAttribute ("direction").toLower (); 0471 direction = dir_right; 0472 if (dir == QString::fromLatin1 ("left")) 0473 direction = dir_left; 0474 else if (dir == QString::fromLatin1 ("up")) 0475 direction = dir_up; 0476 else if (dir == QString::fromLatin1 ("down")) 0477 direction = dir_down; 0478 TimingsBase::activate (); 0479 } 0480 0481 KDE_NO_EXPORT void RP::Wipe::begin () { 0482 //kDebug () << "RP::Wipe::begin"; 0483 TimingsBase::begin (); 0484 if (target && target->id == id_node_image) { 0485 RP::Image * img = static_cast <RP::Image *> (target.ptr ()); 0486 if (!img->isReady (true)) 0487 document_postponed.connect (document(), MsgEventPostponed, this); 0488 else 0489 update (duration > 0 ? 0 : 100); 0490 } 0491 } 0492 0493 KDE_NO_EXPORT void RP::Wipe::accept (Visitor * v) { 0494 v->visit (this); 0495 } 0496 0497 KDE_NO_EXPORT void RP::ViewChange::activate () { 0498 TimingsBase::activate (); 0499 } 0500 0501 KDE_NO_EXPORT void RP::ViewChange::begin () { 0502 kDebug () << "RP::ViewChange::begin"; 0503 setState (state_began); 0504 Node *p = parentNode (); 0505 if (p->id == RP::id_node_imfl) 0506 static_cast <RP::Imfl *> (p)->needs_scene_img++; 0507 update (0); 0508 } 0509 0510 KDE_NO_EXPORT void RP::ViewChange::finish () { 0511 Node *p = parentNode (); 0512 if (p && p->id == RP::id_node_imfl) 0513 static_cast <RP::Imfl *> (p)->needs_scene_img--; 0514 TimingsBase::finish (); 0515 } 0516 0517 KDE_NO_EXPORT void RP::ViewChange::accept (Visitor * v) { 0518 v->visit (this); 0519 }