📄 smil_player.cpp
字号:
int n = *i; // If the node can't be found we're done. std::map<int, time_node*>::iterator it = m_dom2tn->find(n); if (it == m_dom2tn->end()) continue; // If the node is interested in activate events (clicks) we tell // it that the mouse is over it (it may want to show visual feedback) time_node *tn = (*it).second; if(tn->wants_activate_event()) { m_cursorid = 1; node_focussed(tn->dom_node()); m_pointed_node = tn; } // If the node was also in the old focus we're done. if (m_focussed_nodes->count(n) > 0) continue; AM_DBG m_logger->debug("after_mousemove: focus acquired by %d, 0x%x", n, tn); // Send it the focusin and inbounds event, if it wants them. if (tn->wants_inbounds_event()) { AM_DBG m_logger->debug("smil_player::pointed: schedule 0x%x.inBoundsEvent", (void*)tn); time_node::value_type root_time = m_root->get_simple_time(); m_scheduler->update_horizon(root_time); q_smil_time timestamp(m_root, root_time); dom_event_cb *cb = new dom_event_cb(tn, &time_node::raise_inbounds_event, timestamp); schedule_event(cb, 0, ep_high); } if (tn->wants_focusin_event()) { AM_DBG m_logger->debug("smil_player::pointed: schedule 0x%x.focusInEvent", (void*)tn); time_node::value_type root_time = m_root->get_simple_time(); m_scheduler->update_horizon(root_time); q_smil_time timestamp(m_root, root_time); dom_event_cb *cb = new dom_event_cb(tn, &time_node::raise_focusin_event, timestamp); schedule_event(cb, 0, ep_high); } } // Finally juggle the old and new focussed nodes set delete m_focussed_nodes; m_focussed_nodes = m_new_focussed_nodes; m_new_focussed_nodes = NULL; // And if nothing has focus anymore signal that to the embedding app. if (m_cursorid == 0) node_focussed(NULL); return m_cursorid;}// Playable notification for a point (mouse over) event.void smil_player::pointed(int n, double t) {#if 1 AM_DBG m_logger->debug("smil_player(0x%x)::pointed(%d, %f) m_new_focussed_nodes=0x%x", this, n, t, m_new_focussed_nodes); assert(m_new_focussed_nodes); m_new_focussed_nodes->insert(n);#else typedef lib::scalar_arg_callback_event<time_node, q_smil_time> dom_event_cb; std::map<int, time_node*>::iterator it = m_dom2tn->find(n); if(it != m_dom2tn->end()) { bool changed_focus = m_pointed_node != (*it).second; if (m_pointed_node && changed_focus) { // XXX We treat outOfBounds and focusOut identical, which is // not 100% correct. if (m_pointed_node->wants_outofbounds_event()) { AM_DBG m_logger->debug("smil_player::pointed: schedule 0x%x.outOfBoundsEvent", (void*)m_pointed_node); time_node::value_type root_time = m_root->get_simple_time(); m_scheduler->update_horizon(root_time); q_smil_time timestamp(m_root, root_time); dom_event_cb *cb = new dom_event_cb((*it).second, &time_node::raise_outofbounds_event, timestamp); schedule_event(cb, 0, ep_high); } if (m_pointed_node->wants_focusout_event()) { AM_DBG m_logger->debug("smil_player::pointed: schedule 0x%x.focusOutEvent", (void*)m_pointed_node); time_node::value_type root_time = m_root->get_simple_time(); m_scheduler->update_horizon(root_time); q_smil_time timestamp(m_root, root_time); dom_event_cb *cb = new dom_event_cb((*it).second, &time_node::raise_focusout_event, timestamp); schedule_event(cb, 0, ep_high); } m_pointed_node = NULL; } m_pointed_node = (*it).second; if((*it).second->wants_activate_event()) { m_cursorid = 1; node_focussed(m_pointed_node->dom_node()); } if (changed_focus) { AM_DBG m_logger->debug("smil_player::pointed: m_pointed_node is now 0x%x %s[%s]", m_pointed_node, m_pointed_node->get_time_attrs()->get_tag().c_str(), m_pointed_node->get_time_attrs()->get_id().c_str()); } // XXX We treat inBounds and focusIn identical, which is // not 100% correct. if (changed_focus && m_pointed_node->wants_inbounds_event()) { AM_DBG m_logger->debug("smil_player::pointed: schedule 0x%x.inBoundsEvent", (void*)m_pointed_node); time_node::value_type root_time = m_root->get_simple_time(); m_scheduler->update_horizon(root_time); q_smil_time timestamp(m_root, root_time); dom_event_cb *cb = new dom_event_cb((*it).second, &time_node::raise_inbounds_event, timestamp); schedule_event(cb, 0, ep_high); } if (changed_focus && m_pointed_node->wants_focusin_event()) { AM_DBG m_logger->debug("smil_player::pointed: schedule 0x%x.focusInEvent", (void*)m_pointed_node); time_node::value_type root_time = m_root->get_simple_time(); m_scheduler->update_horizon(root_time); q_smil_time timestamp(m_root, root_time); dom_event_cb *cb = new dom_event_cb((*it).second, &time_node::raise_focusin_event, timestamp); schedule_event(cb, 0, ep_high); } } else { if (m_pointed_node) { // XXX We treat outOfBounds and focusOut identical, which is // not 100% correct. if (m_pointed_node->wants_outofbounds_event()) { AM_DBG m_logger->debug("smil_player::pointed: schedule 0x%x.outOfBoundsEvent", (void*)m_pointed_node); time_node::value_type root_time = m_root->get_simple_time(); m_scheduler->update_horizon(root_time); q_smil_time timestamp(m_root, root_time); dom_event_cb *cb = new dom_event_cb((*it).second, &time_node::raise_outofbounds_event, timestamp); schedule_event(cb, 0, ep_high); } if (m_pointed_node->wants_focusout_event()) { AM_DBG m_logger->debug("smil_player::pointed: schedule 0x%x.focusOutEvent", (void*)m_pointed_node); time_node::value_type root_time = m_root->get_simple_time(); m_scheduler->update_horizon(root_time); q_smil_time timestamp(m_root, root_time); dom_event_cb *cb = new dom_event_cb((*it).second, &time_node::raise_focusout_event, timestamp); schedule_event(cb, 0, ep_high); } m_pointed_node = NULL; node_focussed(NULL); } } AM_DBG m_logger->debug("smil_player::pointed: now m_pointed_node=0x%x", m_pointed_node);#endif}// Playable notification for a start event.void smil_player::started(int n, double t) { AM_DBG m_logger->debug("smil_player::started(%d, %f)", n, t); typedef lib::scalar_arg_callback_event<time_node, q_smil_time> bom_event_cb; std::map<int, time_node*>::iterator it = m_dom2tn->find(n); if(it != m_dom2tn->end() && !(*it).second->is_discrete()) { time_node::value_type root_time = m_root->get_simple_time(); m_scheduler->update_horizon(root_time); q_smil_time timestamp(m_root, root_time); bom_event_cb *cb = new bom_event_cb((*it).second, &time_node::on_bom, timestamp); schedule_event(cb, 0, ep_high); }}// Playable notification for a stop event.void smil_player::stopped(int n, double t) { AM_DBG m_logger->debug("smil_player::stopped(%d, %f) roottime=%d", n, t, m_root->get_simple_time()); typedef lib::scalar_arg_callback_event<time_node, q_smil_time> eom_event_cb; std::map<int, time_node*>::iterator it = m_dom2tn->find(n); if(it != m_dom2tn->end() && !(*it).second->is_discrete()) { time_node::value_type root_time = m_root->get_simple_time(); // XXXJACK m_scheduler->update_horizon(root_time); q_smil_time timestamp(m_root, root_time); time_node* tn = (*it).second; AM_DBG m_logger->debug("smil_player::stopped(%d), want_on_eom()=%d", n, tn->want_on_eom()); if (tn->want_on_eom()) { eom_event_cb *cb = new eom_event_cb(tn, &time_node::on_eom, timestamp); schedule_event(cb, 0, ep_high); } }}// Playable notification for a transition stop event.void smil_player::transitioned(int n, double t) { // remove fill effect for nodes specifing fill="transition" // and overlap with n AM_DBG m_logger->debug("smil_player::transitioned(%d, %f)", n, t); typedef lib::scalar_arg_callback_event<time_node, q_smil_time> transitioned_event_cb; std::map<int, time_node*>::iterator it = m_dom2tn->find(n); if(it != m_dom2tn->end()) { time_node::value_type root_time = m_root->get_simple_time(); m_scheduler->update_horizon(root_time); q_smil_time timestamp(m_root, root_time); transitioned_event_cb *cb = new transitioned_event_cb((*it).second, &time_node::on_transitioned, timestamp); schedule_event(cb, 0, ep_high); }}// Playable notification for a stall event.void smil_player::stalled(int n, double t) { AM_DBG m_logger->debug("smil_player::stalled(%d, %f)", n, t);}// Playable notification for an unstall event.void smil_player::unstalled(int n, double t) { AM_DBG m_logger->debug("smil_player::unstalled(%d, %f)", n, t);}// UI notification for a char event.void smil_player::on_char(int ch) { // First check for an anchor node with accesskey attribute std::map<int, int>::iterator p = m_accesskey_map.find(ch); if (p != m_accesskey_map.end()) { // The character was registered, at some point in time. int nid = (*p).second; std::map<int, time_node*>::iterator it = m_dom2tn->find(nid); if(it != m_dom2tn->end() && (*it).second->wants_activate_event()) { // And the node is alive and still wants the event. Use clicked() // to do the hard work. AM_DBG m_logger->debug("smil_player::on_char() convert to clicked(%d): '%c' [%d]", nid, (char)ch, ch); clicked(nid, 0); return; } } typedef std::pair<q_smil_time, int> accesskey; typedef scalar_arg_callback_event<time_node, accesskey> accesskey_cb; time_node::value_type root_time = m_root->get_simple_time(); m_scheduler->update_horizon(root_time); q_smil_time timestamp(m_root, root_time); AM_DBG m_logger->debug("smil_player::on_char(): '%c' [%d] at %ld", char(ch), ch, timestamp.second()); accesskey ak(timestamp, ch); accesskey_cb *cb = new accesskey_cb(m_root, &time_node::raise_accesskey, ak); schedule_event(cb, 0, ep_high); m_scheduler->exec();}void smil_player::on_focus_advance() { AM_DBG m_logger->debug("smil_player::on_focus_advance");AM_DBG lib::logger::get_logger()->debug("smil_player:::on_focus_advance(0x%x)cs.enter", (void*)this); m_playables_cs.enter(); std::map<const lib::node*, common::playable *>::iterator it = m_playables.begin(); // First find the current focus if (m_focus != NULL) { while (it != m_playables.end() && (*it).first != m_focus) it++; if (it == m_playables.end()) { m_logger->debug("smil_player::on_focus_advance: current focus unknown"); it = m_playables.begin(); } else { it++; } } // Now find the next playable that is interested in focus while (it != m_playables.end()) { std::map<int, time_node*>::iterator tit = m_dom2tn->find((*it).first->get_numid()); if (tit != m_dom2tn->end()) { time_node *tn = (*tit).second; if (tn && tn->wants_activate_event()) break; } it++; } if (m_focus) highlight(m_focus, false); m_focus = NULL; if (it != m_playables.end()) m_focus = (*it).first; if (m_focus) { highlight(m_focus); } else { m_logger->trace("on_focus_advance: Nothing to focus on"); } m_playables_cs.leave();AM_DBG lib::logger::get_logger()->debug("smil_player:::on_focus_advance(0x%x)cs.leave", (void*)this); node_focussed(m_focus); }void smil_player::on_focus_activate() { AM_DBG m_logger->debug("smil_player::on_focus_activate"); if (m_focus) { clicked(m_focus->get_numid(), 0); } else { m_logger->trace("on_focus_activate: No current focus"); }}// Creates and returns a playable for the node.common::playable *smil_player::new_playable(const lib::node *n) { int nid = n->get_numid(); std::string tag = n->get_local_name(); const char *pid = n->get_attribute("id"); surface *surf = m_layout_manager->get_surface(n); AM_DBG m_logger->debug("%s[%s].new_playable 0x%x cookie=%d rect%s at %s", tag.c_str(), (pid?pid:"no-id"), (void*)n, nid, ::repr(surf->get_rect()).c_str(), ::repr(surf->get_global_topleft()).c_str()); common::playable_factory *pf = m_factory->get_playable_factory(); common::playable *np = pf->new_playable(this, nid, n, m_event_processor); // And connect it to the rendering surface if (np) { common::renderer *rend = np->get_renderer(); if (rend) { AM_DBG m_logger->debug("smil_player::new_playable: surface set,rend = 0x%x, np = 0x%x", (void*) rend, (void*) np); rend->set_surface(surf); const alignment *align = m_layout_manager->get_alignment(n); rend->set_alignment(align); } else { AM_DBG m_logger->debug("smil_player::new_playable: surface not set because rend == NULL"); } } return np;}// Destroys the playable of the node (checkpoint).void smil_player::destroy_playable(common::playable *np, const lib::node *n) { AM_DBG { std::string tag = n->get_local_name(); const char *pid = n->get_attribute("id"); m_logger->debug("%s[%s].destroy_playable 0x%x", tag.c_str(), (pid?pid:"no-id"), np); } np->stop(); int rem = np->release(); if (rem) m_logger->debug("smil_player::destroy_playable: playable 0x%x still has refcount of %d", np, rem);}void smil_player::show_link(const lib::node *n, const net::url& href, src_playstate srcstate, dst_playstate dststate) { AM_DBG lib::logger::get_logger()->debug("show_link(\"%s\"), srcplaystate=%d, dstplaystate=%d", href.get_url().c_str(), (int)srcstate, (int)dststate); net::url our_url(m_doc->get_src_url()); if(srcstate == src_replace && href.same_document(our_url)) { // This is an internal hyperjump std::string anchor = href.get_ref(); const lib::node *target = m_doc->get_node(anchor); if(target) { goto_node(target); } else { m_logger->error(gettext("Link destination not found: %s"), href.get_url().c_str()); } return; } if(!m_system) { lib::logger::get_logger()->error(gettext("This implementation cannot open <%s> in new window"), href.get_url().c_str()); return; } if (srcstate == src_pause) { AM_DBG lib::logger::get_logger()->debug("show_link: pausing source document"); pause(); } smil_player *to_replace = NULL; if (srcstate == src_replace) { AM_DBG lib::logger::get_logger()->debug("show_link: replacing source document"); to_replace = this; } if ( dststate == dst_external ) { AM_DBG lib::logger::get_logger()->debug("show_link: open externally: \"%s\"", href.get_url().c_str()); if (to_replace) m_system->close(to_replace); m_system->show_file(href); } else { m_system->open(href, dststate == dst_play, to_replace); }}bool smil_player::goto_node(const lib::node *target){ std::map<int, time_node*>::iterator it = m_dom2tn->find(target->get_numid()); if(it != m_dom2tn->end()) { bool already_running = m_root->is_active(); m_scheduler->start((*it).second); if (!already_running) update(); return true; } return false;}boolsmil_player::highlight(const lib::node *n, bool on){ std::map<const lib::node*, common::playable *>::iterator it = m_playables.find(n); common::playable *np = (it != m_playables.end())?(*it).second:0; if (np == NULL) return false; common::renderer *rend = np->get_renderer(); if (rend == NULL) return false; common::surface *surf = rend->get_surface(); if (surf == NULL) return false; surf->highlight(on); return true;}std::string smil_player::get_pointed_node_str() const { if(m_pointed_node == 0) return ""; const time_node *tn = m_pointed_node; const lib::node *n = tn->dom_node(); const char *pid = n->get_attribute("id"); const char *reg = 0; if(n->get_local_name() == "area" && n->up()) { reg = n->up()->get_attribute("region"); } else { reg = n->get_attribute("region"); } const char *href = n->get_attribute("href"); char buf[256]; if(href) sprintf(buf, "%.32s - %.32s : %.32s", (pid?pid:"no-id"), (reg?reg:"no-reg"), href); else sprintf(buf, "%.32s - %.32s", (pid?pid:"no-id"), (reg?reg:"no-reg")); return buf;}void smil_player::update() { if(m_scheduler && m_root && m_root->is_active()) { lib::timer::time_type dt = m_scheduler->exec(); if(m_root->is_active()) { lib::event *update_event = new lib::no_arg_callback_event<smil_player>(this, &smil_player::update); m_event_processor->add_event(update_event, dt, lib::ep_high); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -