⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 time_node.cpp

📁 彩信浏览器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// This file is part of Ambulant Player, www.ambulantplayer.org.//// Copyright (C) 2003-2007 Stichting CWI, // Kruislaan 413, 1098 SJ Amsterdam, The Netherlands.//// Ambulant Player is free software; you can redistribute it and/or modify// it under the terms of the GNU Lesser General Public License as published by// the Free Software Foundation; either version 2.1 of the License, or// (at your option) any later version.//// Ambulant Player 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 Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public License// along with Ambulant Player; if not, write to the Free Software// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA/*  * @$Id: time_node.cpp,v 1.76 2007/02/12 14:15:22 jackjansen Exp $  */#include "ambulant/smil2/time_node.h"#include "ambulant/smil2/animate_n.h"#include "ambulant/smil2/animate_e.h"#include "ambulant/smil2/time_calc.h"#include <cmath>#include <stack>#include <set>#include <list>#include "ambulant/lib/logger.h"//#define AM_DBG if(1)#ifndef AM_DBG#define AM_DBG if(0)#endif#ifndef AMBULANT_NO_IOSTREAMS#include <iostream>#endifusing namespace ambulant;using namespace smil2;// static (mem verifier)int time_node::node_counter = 0;time_node::time_node(context_type *ctx, const node *n, 	time_container_type type /* = tc_none */, bool discrete /* = false */) :	m_context(ctx),	m_node(n),	m_attrs(n),	m_type(type),	m_discrete(discrete),	m_timer(0),	m_state(0),	m_interval(interval_type::unresolved),	m_active(false),	m_needs_remove(false),	m_rad(0),	m_precounter(0),	m_priority(0),	m_paused(false), 	m_pad(0),	m_paused_sync_time(0),	m_deferred(false),	m_ffwd_mode(false),	m_update_event(false, qtime_type(0, 0)),	m_transout_sr(0),	m_begin_event_inst(time_type::unresolved),	m_domcall_rule(0),	m_locked(false),	m_want_activate_events(false),	m_want_focusin_events(false),	m_want_focusout_events(false),	m_want_inbounds_events(false),	m_want_outofbounds_events(false),	m_want_accesskey(false),	m_impldur(time_type::unresolved),	m_last_cdur(time_type::unresolved),	m_logger(0),	m_parent(0), m_next(0), m_child(0) {	assert(type <= tc_none);	node_counter++;	m_logger = lib::logger::get_logger();	m_time_calc = new time_calc(this);	create_time_states();	m_state = m_time_states[ts_reset];}	time_node::~time_node() {	node_counter--;		// Delete the timer of this node	delete m_timer;		// Delete begin and end list rules	rule_list::iterator it;	for(it=m_begin_list.begin();it!=m_begin_list.end();it++)		delete (*it);	for(it=m_end_list.begin();it!=m_end_list.end();it++)		delete (*it);	delete m_transout_sr;		// This node owns the lists but not 	// the sync_rules within the lists.	dependency_map::iterator dit;	for(dit=m_dependents.begin();dit!=m_dependents.end();dit++)		delete (*dit).second;		// delete this time states	for(int i=0;i<=ts_dead;i++)		delete m_time_states[i];	delete m_time_calc;	// Delete recursively this branch		node_navigator<time_node>::delete_tree(this); }// A time node can be at any moment in one of the following 5 states:// reset, proactive, active, postactive, dead// So, a node is a FSM.// For the current implementation the engine is// represented by this node whereas the states// by an instance of the time_state class.void time_node::create_time_states() {	m_time_states[ts_reset] = new reset_state(this);	m_time_states[ts_proactive] = new proactive_state(this);	m_time_states[ts_active] = new active_state(this);	m_time_states[ts_postactive] = new postactive_state(this);	m_time_states[ts_dead] = new dead_state(this);}// Helper function that collects time instances from the provided rules. void time_node::get_instance_times(const rule_list& rules, time_mset& set) const {	rule_list::const_iterator it;	for(it=rules.begin();it!=rules.end();it++)		(*it)->get_instance_times(set);}// Helper function that resets time instances of the provided rules. // Resets instance times following the spec rules for a reset.void time_node::reset(rule_list& rules, time_node *src) {	rule_list::iterator it;	for(it=rules.begin();it!=rules.end();it++)		(*it)->reset(src);}// DOM TimeElement::startElement()// Starts a node at t = 0.// Currently supported only for the root.void time_node::start() {	if(!m_domcall_rule) {		m_domcall_rule = new event_rule(this, tn_dom_call);		add_begin_rule(m_domcall_rule);	}		qtime_type timestamp(this, 0);		// Bring node to live	if(!is_alive())		set_state(ts_proactive, timestamp, this);	// Add event instance	m_domcall_rule->add_instance(timestamp, 0);}// DOM TimeElement::stopElement()// Currently supported only for the root.void time_node::stop() {	qtime_type timestamp(this, get_simple_time());	//set_state(ts_postactive, timestamp, this);	reset(timestamp, this);}// DOM TimeElement::pauseElement()void time_node::pause() {	// Pause the local time line	// Pause children	// Pause playable if a media node}// DOM TimeElement::resumeElement()void time_node::resume() {	// Resume the local time line	// Resume children	// Resume playable if a media node}// Adds a sync_rule to the begin list of this node.// This node is not the sync base but the target (e.g. the node that will be affected).// This is similar to how begin and end conditions are specified in the smil doc.// This node is the owner of the sync_rule but not the source of the event. void time_node::add_begin_rule(sync_rule *sr) {	sr->set_target(this, rt_begin);	time_node* tn = sr->get_syncbase();	sync_event se = sr->get_syncbase_event();	assert(tn!=0);	tn->add_dependent(sr, se);	m_begin_list.push_back(sr);}// Adds a sync_rule to the end list of this node.// This node is not the sync base but the target.void time_node::add_end_rule(sync_rule *sr) {	sr->set_target(this, rt_end);	time_node* tn = sr->get_syncbase();	sync_event se = sr->get_syncbase_event();	assert(tn!=0);	tn->add_dependent(sr, se);	m_end_list.push_back(sr);}// Sets a sync_rule for the out transition of this node.// This node is not the sync base but the target.void time_node::set_transout_rule(sync_rule *sr) {	sr->set_target(this, rt_transout);	time_node* tn = sr->get_syncbase();	sync_event se = sr->get_syncbase_event();	assert(tn!=0);	tn->add_dependent(sr, se);	m_transout_sr = sr;}// Adds a sync arc from this node to a targetvoid time_node::add_dependent(sync_rule *sr, sync_event ev) {	dependency_map::iterator it = m_dependents.find(ev);	rule_list *p = 0;	if(it == m_dependents.end() || (*it).second == 0) {		p = new rule_list();		m_dependents[ev] = p;	} else {		p = (*it).second;	}	sr->set_syncbase(this, ev);	p->push_back(sr);}// Retuns the local name of this nodestd::string time_node::to_string() const {	if(get_type() == tc_none)		return dom_node()->get_local_name();	return get_type_as_str();}std::string time_node::get_sig() const {	std::string rv = "time_node(" + to_string() + ", ";	const lib::node *domnode = dom_node();	if (domnode)		rv += domnode->get_sig();	else		rv += "NULL";	rv += ")";	return rv;}// Returns the implicit duration of this node. // This is an implementation for a leaf-node.// e.g. it queries playable for the implicit dur.// The last definite implicit duration returned by the // playable is stored in the variable m_impldur.// This function is called if and only if the implicit// duration of a node is required by the timing model.// See time_container::get_implicit_dur()// See seq::get_implicit_dur()time_node::time_type time_node::get_implicit_dur() {	// This function is not applicable for containers.	// Assert this usage.	assert(!is_time_container());		// If this is a discrete leaf node, we know the answer	if(is_discrete()) {		AM_DBG m_logger->debug("get_implicit_dur(%s[%s]) return 0 for discrete", m_attrs.get_tag().c_str(), 			m_attrs.get_id().c_str());		return time_type(0);	}		// Was the implicit duration calculated before?	// If yes, avoid the overhead of querring	if(m_impldur != time_type::unresolved) {		AM_DBG m_logger->debug("get_implicit_dur(%s[%s]) return cached %s", m_attrs.get_tag().c_str(), 			m_attrs.get_id().c_str(), ::repr(m_impldur).c_str());		return m_impldur;	}		// Can the associated playable provide the implicit duration? 	m_impldur = get_playable_dur();		if(m_ffwd_mode && m_impldur == time_type::unresolved) {		AM_DBG m_logger->debug("get_implicit_dur(%s[%s]) return 1000 for ffwd_mode", m_attrs.get_tag().c_str(), 			m_attrs.get_id().c_str());		return 1000;	}			// Trace the return value of this function	AM_DBG m_logger->debug("%s[%s].get_implicit_dur(): %s", m_attrs.get_tag().c_str(), 		m_attrs.get_id().c_str(), ::repr(m_impldur).c_str());			return m_impldur;}voidtime_node::set_ffwd_mode(bool b){	AM_DBG m_logger->debug("set_ffwd_mode(%d) for %s", (int)b, get_sig().c_str());	m_ffwd_mode = b;	if (m_ffwd_mode && is_playable()) {		AM_DBG m_logger->debug("set_ffwd_mode: stop_playable(%s)", get_sig().c_str());		stop_playable();	}#if 0	std::list<time_node*> children;	get_children(children);	std::list<time_node*>::iterator it;	for(it = children.begin(); it != children.end(); it++) {		(*it)->set_ffwd_mode(b);	}#endif}// This function calculates the simple duration of this node.// See spec: "Defining the simple duration" // The last calculated simple duration is stored in the variable m_last_cdur.// This function will call the function "get_implicit_dur()" if and only if // the implicit duration of a node is required by the timing model.// Delegates the actual work to the associated time_calc instance.time_node::time_type time_node::calc_dur() {	m_last_cdur = m_time_calc->calc_dur();	return m_last_cdur;}// Returns true when the implicit duration is // required by the model for timing calculationsbool time_node::needs_implicit_dur() const {	if(is_time_container() || is_discrete())		return false;	if(!m_attrs.has_dur_specifier() && m_attrs.specified_end()) {		return false;	}	dur_type dt = m_attrs.get_dur_type();	if(dt == dt_unspecified || dt == dt_media)		return true;	return false;}// Calculates and returns the current inteval end.// This uses calc_ad() function.// Delegates the actual work to the associated time_calc instance.time_node::time_type time_node::calc_current_interval_end()  {	time_mset end_list;	get_instance_times(m_end_list, end_list);	return m_time_calc->calc_interval_end(m_interval, end_list);}// Calculates the first valid interval for this node. // Delegates the actual work to the associated time_calc instance.// Calcs are done within the context of a parent simple dur// A valid interval has to overlap with parent's simple durationtime_node::interval_type time_node::calc_first_interval() {	// Get the begin instance list	time_mset begin_list;	get_instance_times(m_begin_list, begin_list);	if(m_begin_event_inst != time_type::unresolved) {		begin_list.insert(m_begin_event_inst);		m_begin_event_inst = time_type::unresolved;	}	// Get the end instance list	time_mset end_list;	get_instance_times(m_end_list, end_list);		// Parent simple duration	time_type parent_simple_dur = up()?up()->get_last_dur():time_type::indefinite;	return m_time_calc->calc_first_interval(begin_list, end_list, parent_simple_dur);}// Calculates the next acceptable interval for this node.// Delegates the actual work to the associated time_calc instance.// Calcs are done within the context of a parent simple dur// An valid interval has to overlap with parent's simple duration// An interval should begin after the previous end// A zero-dur previous interval affects calcs  time_node::interval_type time_node::calc_next_interval(interval_type prev) {	if(prev == interval_type::unresolved) {		if(m_history.empty()) {			// xxx: add warn			return interval_type::unresolved;		}		prev = m_history.back();	}		// Get the begin instance list

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -