📄 time_node.cpp
字号:
}}// Resumes this node.// Excl element handling.void time_node::resume(qtime_type timestamp) { if(!is_active()) { // gone inactive while paused AM_DBG m_logger->debug("%s[%s].resume(): gone inactive while paused", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str()); return; } m_time_calc->set_paused_mode(false); set_paused(false); AM_DBG m_logger->debug("%s[%s].resume()", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str()); time_type self_simple_time = timestamp.as_time_down_to(this); qtime_type qt(this, self_simple_time); // re-establish sync time_type iend = calc_current_interval_end(); time_type resumed_sync_time = timestamp.as_time_down_to(sync_node()); time_type pauseoffset = resumed_sync_time - m_paused_sync_time; m_pad += pauseoffset; if(iend != m_interval.end) { update_interval_end(timestamp, iend); } AM_DBG m_logger->debug("%s[%s].resume(): %s", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), ::repr(m_interval).c_str()); if(is_playable()) resume_playable(); if(m_timer) m_timer->resume(); // Resume playable active children time_node::iterator nit; time_node::iterator end_nit = end(); for(nit=begin(); nit != end_nit; nit++) { if(!(*nit).first && (*nit).second->is_playable() && (*nit).second->is_active()) { (*nit).second->resume_playable(); } }}// Defers the interval of this node.// Excl element handling.void time_node::defer_interval(qtime_type timestamp) { // Mark this node as deferred. set_deferred(true); // Cancel notifications interval_type i = m_interval; if(!i.is_valid()) return; m_interval = interval_type::unresolved; on_cancel_instance(timestamp, tn_begin, i.begin); on_cancel_instance(timestamp, tn_end, i.end); // Remember interval m_interval = i;}// Excl element handling.// When an element is deferred, the begin time is deferred as wellvoid time_node::set_deferred_interval(qtime_type timestamp) { if(!deferred()) return; // Remove deferred marker set_deferred(false); if(!m_interval.is_valid()) return; // Translate the defered interval to timestamp interval_type i = m_interval; i.translate(timestamp.second-m_interval.begin); // Schedule interval set_interval(timestamp, i);}// This function is called always when a node exits the active state.// Applies the appropriate fill behavior for this node.//// For containers the current implementation calls first kill_children().// Therefore this function will be called first for the children and// then for their parent.//// Pause or stop peer playable based on the fill semantics.// Results to peer.pause() (m_needs_remove = true) or peer.stop() (m_needs_remove = true).//void time_node::fill(qtime_type timestamp) { // Does this node have shown anything? if(!m_needs_remove) return; fill_behavior fb = m_attrs.get_fill();// fill_behavior pfb = sync_node()->get_time_attrs()->get_fill(); bool keep = (fb != fill_remove); if(keep) { // this node should be freezed AM_DBG m_logger->debug("%s[%s].pause() ST:%ld, PT:%ld, DT:%ld", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), timestamp.as_time_value_down_to(this), timestamp.second(), timestamp.as_doc_time_value()); if(down()) { std::list<time_node*> cl; get_children(cl); std::list<time_node*>::iterator it; time_type self_simple_time = timestamp.as_time_down_to(this); qtime_type qt(this, self_simple_time); for(it = cl.begin(); it != cl.end(); it++) (*it)->fill(qt); } if(is_playable()) pause_playable(); if(m_timer) { m_timer->pause(); m_timer->set_time(m_interval.end()); } } else { // this node should be removed remove(timestamp); }}// Removes any fill effects// This is called always by reset.// This maybe called when the element is deactivated// or when the next is activated.void time_node::remove(qtime_type timestamp) { if(!m_needs_remove) return; AM_DBG m_logger->debug("%s[%s].stop() ST:%ld, PT:%ld, DT:%ld", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), timestamp.as_time_value_down_to(this), timestamp.second(), timestamp.as_doc_time_value()); if(down()) { // Is this correct for a container? std::list<time_node*> children; get_children(children); std::list<time_node*>::iterator it; time_type self_simple_time = timestamp.as_time_down_to(this); qtime_type qt(this, self_simple_time); for(it = children.begin(); it != children.end(); it++) (*it)->remove(qt); } if(is_animation()) stop_animation(); else if(is_playable()) stop_playable(); if(m_timer) m_timer->stop(); m_needs_remove = false;}///////////////////////////////// Dependents updatesvoid time_node::on_new_instance(qtime_type timestamp, sync_event ev, time_type instance, time_node *filter) { dependency_map::iterator dit = m_dependents.find(ev); if(dit != m_dependents.end() && (*dit).second != 0) { rule_list *p = (*dit).second; for(rule_list::iterator it=p->begin();it!=p->end();it++) { time_node* owner = (*it)->get_target(); if(!filter || !nnhelper::is_descendent(owner, filter)) (*it)->new_instance(timestamp, instance); } }}void time_node::on_update_instance(qtime_type timestamp, sync_event ev, time_type instance, time_type old_instance, time_node *filter) { dependency_map::iterator dit = m_dependents.find(ev); if(dit != m_dependents.end() && (*dit).second != 0) { rule_list *p = (*dit).second; for(rule_list::iterator it=p->begin();it!=p->end();it++) { time_node* owner = (*it)->get_target(); if(!filter || !nnhelper::is_descendent(owner, filter)) (*it)->update_instance(timestamp, instance, old_instance); } }}void time_node::on_cancel_instance(qtime_type timestamp, sync_event ev, time_type instance, time_node *filter) { dependency_map::iterator dit = m_dependents.find(ev); if(dit != m_dependents.end() && (*dit).second != 0) { rule_list *p = (*dit).second; for(rule_list::iterator it=p->begin();it!=p->end();it++) { time_node* owner = (*it)->get_target(); if(!filter || !nnhelper::is_descendent(owner, filter)) (*it)->cancel_instance(timestamp, instance); } }}// Update dependents for an event instance// Asserts that the same event is not used to update the same element twice.void time_node::on_add_instance(qtime_type timestamp, smil2::sync_event ev, time_node::time_type instance, int data, time_node *filter) { dependency_map::iterator dit = m_dependents.find(ev); if(dit == m_dependents.end() || (*dit).second == 0) { // no dependents return; } // List of rules to update rule_list *p = (*dit).second; // Set of dependents std::set<time_node*> dset; // 1. add event to not active // 1.1 begin rule_list::iterator it; for(it=p->begin();it!=p->end();it++) { time_node* owner = (*it)->get_target(); AM_DBG m_logger->debug("%s[%s].on_add_instance() --> %s[%s]", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), owner->get_time_attrs()->get_tag().c_str(), owner->get_time_attrs()->get_id().c_str()); rule_type rt = (*it)->get_target_attr(); if(!owner->is_active() && rt == rt_begin && dset.find(owner) == dset.end()) { if(!filter || !nnhelper::is_descendent(owner, filter)) { (*it)->add_instance(timestamp, instance, data); dset.insert(owner); } } } // 1.2 end for(it=p->begin();it!=p->end();it++) { time_node* owner = (*it)->get_target(); rule_type rt = (*it)->get_target_attr(); if(!owner->is_active() && rt == rt_end && dset.find(owner) == dset.end()) { if(!filter || !nnhelper::is_descendent(owner, filter)) { (*it)->add_instance(timestamp, instance, data); dset.insert(owner); } } } // 2. add event to active // 2.1 end for(it=p->begin();it!=p->end();it++) { time_node* owner = (*it)->get_target(); rule_type rt = (*it)->get_target_attr(); if(owner->is_active() && rt == rt_end && dset.find(owner) == dset.end()) { if(!filter || !nnhelper::is_descendent(owner, filter)) { (*it)->add_instance(timestamp, instance, data); dset.insert(owner); } } } // 2.2 begin for(it=p->begin();it!=p->end();it++) { time_node* owner = (*it)->get_target(); rule_type rt = (*it)->get_target_attr(); if(owner->is_active() && rt == rt_begin && dset.find(owner) == dset.end()) { if(!filter || !nnhelper::is_descendent(owner, filter)) { (*it)->add_instance(timestamp, instance, data); dset.insert(owner); } } }}////////////////////// Raising events: // beginEvent, repeat event, endEvent// Called when this node transitions to active.// (active_state::enter() activity)// Containers have to reset children, bring them to life // and notify dependents.// Leaf nodes have to notify dependents and start their peer playable.void time_node::raise_begin_event(qtime_type timestamp) { AM_DBG m_logger->debug("%s[%s].raise_begin_event() ST:%ld, PT:%ld, DT:%ld", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), timestamp.as_time_value_down_to(this), timestamp.second(), timestamp.as_doc_time_value()); assert(timestamp.first == sync_node()); on_add_instance(timestamp, tn_begin_event, timestamp.second); // Simulate a timegraph-sampling implementation // For a time container we know that more info will be available // immediately after it starts. if(down() && m_interval.end == time_type::indefinite) raise_update_event(timestamp);}// Send feedback to the upper layers about what we're doingvoid time_node::node_started(){ if(is_root()) m_context->started_playback(); if(!m_ffwd_mode) m_context->node_started(m_node);}// Called when this node repeats.// Containers have to reset children, bring them to life // and notify dependents.// Leaf nodes have to notify dependents and start their peer playable at 0.// timestamp is parent's simple time when this event occurs.void time_node::raise_repeat_event(qtime_type timestamp) { AM_DBG m_logger->debug("%s[%s].raise_repeat_event(%d) ST:%ld, PT:%ld, DT:%ld", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), m_precounter, timestamp.as_time_value_down_to(this), timestamp.second(), timestamp.as_doc_time_value()); assert(timestamp.first == sync_node()); on_add_instance(timestamp, tn_repeat_event, timestamp.second, m_precounter);}// Called when this node exits active.// On end, containers have to kill their children // and notify dependents.// Leaf nodes have to notify dependents and pause playablevoid time_node::raise_end_event(qtime_type timestamp, time_node *oproot) { AM_DBG m_logger->debug("%s[%s].raise_end_event() ST:%ld, PT:%ld, DT:%ld", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), timestamp.as_time_value_down_to(this), timestamp.second(), timestamp.as_doc_time_value()); if(timestamp.first != sync_node()) { timestamp.to_node(sync_node()); } if(m_interval.end != timestamp.second) { on_update_instance(timestamp, tn_end, timestamp.second, m_interval.end, oproot); m_interval.end = timestamp.second; } on_add_instance(timestamp, tn_end_event, timestamp.second, 0, oproot); if(sync_node()->is_excl() && (paused() || deferred())) { excl* p = qualify<excl*>(sync_node()); p->remove(this); set_paused(false); set_deferred(false); m_time_calc->set_paused_mode(false); } // Check parent end_sync conditions // call schedule_sync_update(timestamp) if needed time_node *p = up(); if(p && (p->is_par() || p->is_excl() || (p->is_seq() && !next()))) p->raise_update_event(timestamp); if(p && p->is_seq()) { time_node *n = next(); if(n) n->raise_update_event(timestamp); } if(is_root()) m_context->done_playback(); m_context->node_stopped(m_node);}void time_node::raise_activate_event(qtime_type timestamp) { timestamp.to_descendent(sync_node()); AM_DBG m_logger->debug("%s[%s].raise_activate_event() ST:%ld, PT:%ld, DT:%ld", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), timestamp.as_time_value_down_to(this), timestamp.second(), timestamp.as_doc_time_value()); on_add_instance(timestamp, tn_activate_event, timestamp.second); if(is_link()) { follow_link(timestamp); }}void time_node::raise_inbounds_event(qtime_type timestamp) { timestamp.to_descendent(sync_node()); AM_DBG m_logger->debug("%s[%s].raise_inbounds_event() ST:%ld, PT:%ld, DT:%ld", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), timestamp.as_time_value_down_to(this), timestamp.second(), timestamp.as_doc_time_value()); on_add_instance(timestamp, tn_inbounds_event, timestamp.second);}void time_node::raise_outofbounds_event(qtime_type timestamp) { timestamp.to_descendent(sync_node()); AM_DBG m_logger->debug("%s[%s].raise_outofbounds_event() ST:%ld, PT:%ld, DT:%ld", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), timestamp.as_time_value_down_to(this), timestamp.second(), timestamp.as_doc_time_value()); on_add_instance(timestamp, tn_outofbounds_event, timestamp.second);}void time_node::raise_focusin_event(qtime_type timestamp) { timestamp.to_descendent(sync_node()); AM_DBG m_logger->debug("%s[%s].raise_focusin_event() ST:%ld, PT:%ld, DT:%ld", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), timestamp.as_time_value_down_to(this), timestamp.second(), timestamp.as_doc_time_value()); on_add_instance(timestamp, tn_focusin_event, timestamp.second);}void time_node::raise_focusout_event(qtime_type timestamp) { timestamp.to_descendent(sync_node()); AM_DBG m_logger->debug("%s[%s].raise_focusout_event() ST:%ld, PT:%ld, DT:%ld", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -