/** * Copyright (C) 2006 by Koos Vriezen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, * Boston, MA 02110-1301, USA. **/ #include #include #include #include #include #include "kmplayer_rp.h" #include "kmplayer_smil.h" using namespace KMPlayer; KDE_NO_CDTOR_EXPORT RP::Imfl::Imfl (NodePtr & d) : Mrl (d, id_node_imfl), fit (fit_hidden), duration (0), needs_scene_img (0) {} KDE_NO_CDTOR_EXPORT RP::Imfl::~Imfl () { } TDE_NO_EXPORT void RP::Imfl::closed () { for (NodePtr n = firstChild (); n; n = n->nextSibling ()) if (RP::id_node_head == n->id) { AttributePtr a = convertNode (n)->attributes ()->first (); for (; a; a = a->nextSibling ()) { if (StringPool::attr_width == a->name ()) { width = a->value ().toInt (); } else if (StringPool::attr_height == a->name ()) { height = a->value ().toInt (); } else if (a->name () == "duration") { int dur; parseTime (a->value ().lower (), dur); duration = dur; } } } } TDE_NO_EXPORT void RP::Imfl::defer () { kdDebug () << "RP::Imfl::defer " << endl; setState (state_deferred); for (Node * n = firstChild ().ptr (); n; n = n->nextSibling ().ptr ()) if (n->id == RP::id_node_image && !n->active ()) n->activate (); } TDE_NO_EXPORT void RP::Imfl::activate () { kdDebug () << "RP::Imfl::activate " << endl; resolved = true; setState (state_activated); int timings_count = 0; for (NodePtr n = firstChild (); n; n = n->nextSibling ()) switch (n->id) { case RP::id_node_crossfade: case RP::id_node_fadein: case RP::id_node_fadeout: case RP::id_node_fill: case RP::id_node_wipe: case RP::id_node_viewchange: n->activate (); // set their start timers timings_count++; break; case RP::id_node_image: if (!n->active ()) n->activate (); break; } if (duration > 0) duration_timer = document ()->setTimeout (this, duration * 100); else if (!timings_count) finish (); } TDE_NO_EXPORT void RP::Imfl::finish () { kdDebug () << "RP::Imfl::finish " << endl; Mrl::finish (); if (duration_timer) { document ()->cancelTimer (duration_timer); duration_timer = 0; } for (NodePtr n = firstChild (); n; n = n->nextSibling ()) if (n->unfinished ()) n->finish (); } TDE_NO_EXPORT void RP::Imfl::childDone (NodePtr) { if (unfinished () && !duration_timer) { for (NodePtr n = firstChild (); n; n = n->nextSibling ()) switch (n->id) { case RP::id_node_crossfade: case RP::id_node_fadein: case RP::id_node_fadeout: case RP::id_node_fill: if (n->unfinished ()) return; } finish (); } } TDE_NO_EXPORT void RP::Imfl::deactivate () { kdDebug () << "RP::Imfl::deactivate " << endl; if (unfinished ()) finish (); if (!active ()) return; // calling finish might call deactivate() as well setState (state_deactivated); for (NodePtr n = firstChild (); n; n = n->nextSibling ()) if (n->active ()) n->deactivate (); rp_surface = Mrl::getSurface (0L); } TDE_NO_EXPORT bool RP::Imfl::handleEvent (EventPtr event) { if (event->id () == event_timer) { TimerEvent * te = static_cast (event.ptr ()); if (te->timer_info == duration_timer) { kdDebug () << "RP::Imfl timer " << duration << endl; duration_timer = 0; if (unfinished ()) finish (); } } return true; } TDE_NO_EXPORT void RP::Imfl::accept (Visitor * v) { v->visit (this); } TDE_NO_EXPORT Surface *RP::Imfl::surface () { if (!rp_surface) { rp_surface = Mrl::getSurface (this); if (rp_surface) { if (width <= 0 || width > 32000) width = rp_surface->bounds.width (); if (height <= 0 || height > 32000) height = rp_surface->bounds.height (); } } return rp_surface.ptr (); } TDE_NO_EXPORT NodePtr RP::Imfl::childFromTag (const TQString & tag) { const char * ctag = tag.latin1 (); if (!strcmp (ctag, "head")) return new DarkNode (m_doc, "head", RP::id_node_head); else if (!strcmp (ctag, "image")) return new RP::Image (m_doc); else if (!strcmp (ctag, "fill")) return new RP::Fill (m_doc); else if (!strcmp (ctag, "wipe")) return new RP::Wipe (m_doc); else if (!strcmp (ctag, "viewchange")) return new RP::ViewChange (m_doc); else if (!strcmp (ctag, "crossfade")) return new RP::Crossfade (m_doc); else if (!strcmp (ctag, "fadein")) return new RP::Fadein (m_doc); else if (!strcmp (ctag, "fadeout")) return new RP::Fadeout (m_doc); return 0L; } TDE_NO_EXPORT void RP::Imfl::repaint () { if (!active ()) kdWarning () << "Spurious Imfl repaint" << endl; else if (surface () && width > 0 && height > 0) rp_surface->repaint (SRect (0, 0, width, height)); } KDE_NO_CDTOR_EXPORT RP::Image::Image (NodePtr & doc) : Mrl (doc, id_node_image) {} KDE_NO_CDTOR_EXPORT RP::Image::~Image () { } TDE_NO_EXPORT void RP::Image::closed () { src = getAttribute (StringPool::attr_name); } TDE_NO_EXPORT void RP::Image::activate () { kdDebug () << "RP::Image::activate" << endl; setState (state_activated); isPlayable (); // update src attribute cached_img.setUrl (absolutePath ()); if (cached_img.isEmpty ()) { wget (absolutePath ()); } else { width = cached_img.data->image->width (); height = cached_img.data->image->height (); } } TDE_NO_EXPORT void RP::Image::begin () { Node::begin (); } TDE_NO_EXPORT void RP::Image::deactivate () { cached_img.setUrl (TQString ()); if (img_surface) { img_surface->remove (); img_surface = NULL; } setState (state_deactivated); postpone_lock = 0L; } TDE_NO_EXPORT void RP::Image::remoteReady (TQByteArray & data) { kdDebug () << "RP::Image::remoteReady" << endl; if (!data.isEmpty () && cached_img.isEmpty ()) { TQImage * img = new TQImage (data); if (!img->isNull ()) { cached_img.data->image = img; width = img->width (); height = img->height (); } else { delete img; } } postpone_lock = 0L; } TDE_NO_EXPORT bool RP::Image::isReady (bool postpone_if_not) { if (downloading () && postpone_if_not) postpone_lock = document ()->postpone (); return !downloading (); } TDE_NO_EXPORT Surface *RP::Image::surface () { if (!img_surface && !cached_img.isEmpty ()) { Node * p = parentNode ().ptr (); if (p && p->id == RP::id_node_imfl) { Surface *ps = static_cast (p)->surface (); if (ps) img_surface = ps->createSurface (this, SRect (0, 0, width, height)); } } return img_surface; } KDE_NO_CDTOR_EXPORT RP::TimingsBase::TimingsBase (NodePtr & d, const short i) : Element (d, i), x (0), y (0), w (0), h (0), start (0), duration (0) {} TDE_NO_EXPORT void RP::TimingsBase::activate () { setState (state_activated); x = y = w = h = 0; srcx = srcy = srcw = srch = 0; for (Attribute * a= attributes ()->first ().ptr (); a; a = a->nextSibling ().ptr ()) { if (a->name () == StringPool::attr_target) { for (NodePtr n = parentNode()->firstChild(); n; n= n->nextSibling()) if (convertNode (n)-> getAttribute ("handle") == a->value ()) target = n; } else if (a->name () == "start") { int dur; parseTime (a->value ().lower (), dur); start = dur; } else if (a->name () == "duration") { int dur; parseTime (a->value ().lower (), dur); duration = dur; } else if (a->name () == "dstx") { x = a->value ().toInt (); } else if (a->name () == "dsty") { y = a->value ().toInt (); } else if (a->name () == "dstw") { w = a->value ().toInt (); } else if (a->name () == "dsth") { h = a->value ().toInt (); } else if (a->name () == "srcx") { srcx = a->value ().toInt (); } else if (a->name () == "srcy") { srcy = a->value ().toInt (); } else if (a->name () == "srcw") { srcw = a->value ().toInt (); } else if (a->name () == "srch") { srch = a->value ().toInt (); } } start_timer = document ()->setTimeout (this, start *100); } TDE_NO_EXPORT void RP::TimingsBase::deactivate () { if (unfinished ()) finish (); setState (state_deactivated); } TDE_NO_EXPORT bool RP::TimingsBase::handleEvent (EventPtr event) { if (event->id () == event_timer) { TimerEvent * te = static_cast (event.ptr ()); if (te->timer_info == update_timer && duration > 0) { update (100 * ++curr_step / duration); te->interval = true; } else if (te->timer_info == start_timer) { start_timer = 0; duration_timer = document ()->setTimeout (this, duration * 100); begin (); } else if (te->timer_info == duration_timer) { duration_timer = 0; update (100); finish (); } else return false; return true; } else if (event->id () == event_postponed) { if (!static_cast (event.ptr ())->is_postponed) { document_postponed = 0L; // disconnect update (duration > 0 ? 0 : 100); } } return false; } TDE_NO_EXPORT void RP::TimingsBase::begin () { progress = 0; setState (state_began); if (target) target->begin (); if (duration > 0) { steps = duration; // 10/s updates update_timer = document ()->setTimeout (this, 100); // 50ms curr_step = 1; } } TDE_NO_EXPORT void RP::TimingsBase::update (int percentage) { progress = percentage; Node * p = parentNode ().ptr (); if (p->id == RP::id_node_imfl) static_cast (p)->repaint (); } TDE_NO_EXPORT void RP::TimingsBase::finish () { progress = 100; if (start_timer) { document ()->cancelTimer (start_timer); start_timer = 0; } else if (duration_timer) { document ()->cancelTimer (duration_timer); duration_timer = 0; } if (update_timer) { document ()->cancelTimer (update_timer); update_timer = 0; } document_postponed = 0L; // disconnect Element::finish (); } TDE_NO_EXPORT void RP::Crossfade::activate () { TimingsBase::activate (); } TDE_NO_EXPORT void RP::Crossfade::begin () { //kdDebug () << "RP::Crossfade::begin" << endl; TimingsBase::begin (); if (target && target->id == id_node_image) { RP::Image * img = static_cast (target.ptr ()); if (!img->isReady (true)) document_postponed = document()->connectTo (this, event_postponed); else update (duration > 0 ? 0 : 100); } } TDE_NO_EXPORT void RP::Crossfade::accept (Visitor * v) { v->visit (this); } TDE_NO_EXPORT void RP::Fadein::activate () { // pickup color from Fill that should be declared before this node from_color = 0; TimingsBase::activate (); } TDE_NO_EXPORT void RP::Fadein::begin () { //kdDebug () << "RP::Fadein::begin" << endl; TimingsBase::begin (); if (target && target->id == id_node_image) { RP::Image * img = static_cast (target.ptr ()); if (!img->isReady (true)) document_postponed = document()->connectTo (this, event_postponed); else update (duration > 0 ? 0 : 100); } } TDE_NO_EXPORT void RP::Fadein::accept (Visitor * v) { v->visit (this); } TDE_NO_EXPORT void RP::Fadeout::activate () { to_color = TQColor (getAttribute ("color")).rgb (); TimingsBase::activate (); } TDE_NO_EXPORT void RP::Fadeout::begin () { //kdDebug () << "RP::Fadeout::begin" << endl; TimingsBase::begin (); } TDE_NO_EXPORT void RP::Fadeout::accept (Visitor * v) { v->visit (this); } TDE_NO_EXPORT void RP::Fill::activate () { color = TQColor (getAttribute ("color")).rgb (); TimingsBase::activate (); } TDE_NO_EXPORT void RP::Fill::begin () { setState (state_began); update (0); } TDE_NO_EXPORT void RP::Fill::accept (Visitor * v) { v->visit (this); } TDE_NO_EXPORT void RP::Wipe::activate () { //TODO implement 'type="push"' TQString dir = getAttribute ("direction").lower (); direction = dir_right; if (dir == TQString::fromLatin1 ("left")) direction = dir_left; else if (dir == TQString::fromLatin1 ("up")) direction = dir_up; else if (dir == TQString::fromLatin1 ("down")) direction = dir_down; TimingsBase::activate (); } TDE_NO_EXPORT void RP::Wipe::begin () { //kdDebug () << "RP::Wipe::begin" << endl; TimingsBase::begin (); if (target && target->id == id_node_image) { RP::Image * img = static_cast (target.ptr ()); if (!img->isReady (true)) document_postponed = document()->connectTo (this, event_postponed); else update (duration > 0 ? 0 : 100); } } TDE_NO_EXPORT void RP::Wipe::accept (Visitor * v) { v->visit (this); } TDE_NO_EXPORT void RP::ViewChange::activate () { TimingsBase::activate (); } TDE_NO_EXPORT void RP::ViewChange::begin () { kdDebug () << "RP::ViewChange::begin" << endl; setState (state_began); Node * p = parentNode ().ptr (); if (p->id == RP::id_node_imfl) static_cast (p)->needs_scene_img++; update (0); } TDE_NO_EXPORT void RP::ViewChange::finish () { Node * p = parentNode ().ptr (); if (p && p->id == RP::id_node_imfl) static_cast (p)->needs_scene_img--; TimingsBase::finish (); } TDE_NO_EXPORT void RP::ViewChange::accept (Visitor * v) { v->visit (this); }