Move ARDOUR::Change into PBD so that Stateful can be aware of

what Change a State reflects.  Hence allow Stateful to do some
of the work of set/get_state in Region.


git-svn-id: svn://localhost/ardour2/branches/3.0@6671 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington
2010-02-10 01:38:20 +00:00
parent c9d433d9b3
commit 3c00a7ca2a
30 changed files with 202 additions and 170 deletions

View File

@@ -33,13 +33,20 @@ namespace sys {
class path;
}
enum Change {
range_guarantee = ~0
};
Change new_change ();
/** Base (non template) part of State */
class StateBase
{
public:
StateBase (std::string const & p)
StateBase (std::string const & p, Change c)
: _have_old (false)
, _xml_property_name (p)
, _change (c)
{
}
@@ -47,6 +54,7 @@ public:
StateBase (StateBase const & s)
: _have_old (s._have_old)
, _xml_property_name (s._xml_property_name)
, _change (s._change)
{
}
@@ -57,10 +65,13 @@ public:
}
virtual void diff (XMLNode *, XMLNode *) const = 0;
virtual Change set_state (XMLNode const &) = 0;
virtual void add_state (XMLNode &) const = 0;
protected:
bool _have_old;
std::string _xml_property_name;
Change _change;
};
/** Class to represent a single piece of state in a Stateful object */
@@ -68,8 +79,8 @@ template <class T>
class State : public StateBase
{
public:
State (std::string const & p, T const & v)
: StateBase (p)
State (std::string const & p, Change c, T const & v)
: StateBase (p, c)
, _current (v)
{
@@ -86,6 +97,7 @@ public:
/* XXX: isn't there a nicer place to do this? */
_have_old = s._have_old;
_xml_property_name = s._xml_property_name;
_change = s._change;
_current = s._current;
_old = s._old;
@@ -112,21 +124,50 @@ public:
void diff (XMLNode* old, XMLNode* current) const {
if (_have_old) {
std::stringstream o;
o << _old;
old->add_property (_xml_property_name.c_str(), o.str().c_str());
std::stringstream c;
c << _current;
current->add_property (_xml_property_name.c_str(), c.str().c_str());
old->add_property (_xml_property_name.c_str(), to_string (_old));
current->add_property (_xml_property_name.c_str(), to_string (_current));
}
}
/** Try to set state from the property of an XML node.
* @param node XML node.
* @return Change effected, or 0.
*/
Change set_state (XMLNode const & node) {
XMLProperty const * p = node.property (_xml_property_name.c_str());
if (p) {
std::stringstream s (p->value ());
T v;
s >> v;
if (v == _current) {
return Change (0);
}
set (v);
return _change;
}
return Change (0);
}
void add_state (XMLNode & node) const {
node.add_property (_xml_property_name.c_str(), to_string (_current));
}
private:
void set (T const & v) {
_old = _current;
_have_old = true;
_current = v;
}
std::string to_string (T const & v) const {
std::stringstream s;
s << v;
return s.str ();
}
T _current;
T _old;
@@ -163,6 +204,8 @@ class Stateful {
void add_instant_xml (XMLNode&, const sys::path& directory_path);
XMLNode *instant_xml (const std::string& str, const sys::path& directory_path);
Change set_state_using_states (XMLNode const &);
void add_states (XMLNode &);
XMLNode *_extra_xml;
XMLNode *_instant_xml;

View File

@@ -35,6 +35,27 @@ namespace PBD {
int Stateful::current_state_version = 0;
int Stateful::loading_state_version = 0;
PBD::Change
new_change ()
{
Change c;
static uint32_t change_bit = 1;
/* catch out-of-range */
if (!change_bit)
{
fatal << _("programming error: ")
<< "change_bit out of range in ARDOUR::new_change()"
<< endmsg;
/*NOTREACHED*/
}
c = Change (change_bit);
change_bit <<= 1; // if it shifts too far, change_bit == 0
return c;
}
Stateful::Stateful ()
{
_extra_xml = 0;
@@ -175,5 +196,32 @@ Stateful::diff ()
return make_pair (old, current);
}
/** Set state of _states from an XML node.
* @param node Node.
* @return Changes made.
*/
Change
Stateful::set_state_using_states (XMLNode const & node)
{
Change c = Change (0);
for (list<StateBase*>::iterator i = _states.begin(); i != _states.end(); ++i) {
c = Change (c | (*i)->set_state (node));
}
return c;
}
/** Add state of _states to an XML node.
* @param node Node.
*/
void
Stateful::add_states (XMLNode & node)
{
for (list<StateBase*>::iterator i = _states.begin(); i != _states.end(); ++i) {
(*i)->add_state (node);
}
}
} // namespace PBD