X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fpbd%2Fstateful.cc;h=3fb11a3a509359bf6878a0c63e9849c72b94e81f;hb=b7754af246dd5446828217a636d8a24e751e41d1;hp=8ee587fbc6bb27772a277bdf1f512af868160429;hpb=e178fb2e503245335d00c22949969fa4187250b7;p=ardour.git diff --git a/libs/pbd/stateful.cc b/libs/pbd/stateful.cc index 8ee587fbc6..3fb11a3a50 100644 --- a/libs/pbd/stateful.cc +++ b/libs/pbd/stateful.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2001 Paul Davis + Copyright (C) 2000-2001 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,14 +18,20 @@ $Id: stateful.cc 629 2006-06-21 23:01:03Z paul $ */ +#ifdef COMPILER_MSVC +#include // Microsoft's nearest equivalent to +#else #include +#endif + +#include +#include #include "pbd/debug.h" #include "pbd/stateful.h" #include "pbd/property_list.h" #include "pbd/properties.h" #include "pbd/destructible.h" -#include "pbd/filesystem.h" #include "pbd/xml++.h" #include "pbd/error.h" @@ -38,19 +44,21 @@ namespace PBD { int Stateful::current_state_version = 0; int Stateful::loading_state_version = 0; +Glib::Threads::Private Stateful::_regenerate_xml_or_string_ids; + Stateful::Stateful () - : _frozen (0) - , _properties (new OwnedPropertyList) + : _extra_xml (0) + , _instant_xml (0) + , _properties (new OwnedPropertyList) + , _stateful_frozen (0) { - _extra_xml = 0; - _instant_xml = 0; } Stateful::~Stateful () { - delete _properties; + delete _properties; - // Do not delete _extra_xml. The use of add_child_nocopy() + // Do not delete _extra_xml. The use of add_child_nocopy() // means it needs to live on indefinately. delete _instant_xml; @@ -63,33 +71,53 @@ Stateful::add_extra_xml (XMLNode& node) _extra_xml = new XMLNode ("Extra"); } - _extra_xml->remove_nodes (node.name()); + _extra_xml->remove_nodes_and_delete (node.name()); _extra_xml->add_child_nocopy (node); } XMLNode * -Stateful::extra_xml (const string& str) +Stateful::extra_xml (const string& str, bool add_if_missing) { - if (_extra_xml == 0) { - return 0; - } + XMLNode* node = 0; - const XMLNodeList& nlist = _extra_xml->children(); - XMLNodeConstIterator i; + if (_extra_xml) { + node = _extra_xml->child (str.c_str()); + } - for (i = nlist.begin(); i != nlist.end(); ++i) { - if ((*i)->name() == str) { - return (*i); - } + if (!node && add_if_missing) { + node = new XMLNode (str); + add_extra_xml (*node); } - return 0; + return node; +} + +void +Stateful::save_extra_xml (const XMLNode& node) +{ + /* Looks for the child node called "Extra" and makes _extra_xml + point to a copy of it. Will delete any existing node pointed + to by _extra_xml if a new Extra node is found, but not + otherwise. + */ + + const XMLNode* xtra = node.child ("Extra"); + + if (xtra) { + delete _extra_xml; + _extra_xml = new XMLNode (*xtra); + } } void -Stateful::add_instant_xml (XMLNode& node, const sys::path& directory_path) +Stateful::add_instant_xml (XMLNode& node, const std::string& directory_path) { - sys::create_directories (directory_path); // may throw + if (!Glib::file_test (directory_path, Glib::FILE_TEST_IS_DIR)) { + if (g_mkdir_with_parents (directory_path.c_str(), 0755) != 0) { + error << string_compose(_("Error: could not create directory %1"), directory_path) << endmsg; + return; + } + } if (_instant_xml == 0) { _instant_xml = new XMLNode ("instant"); @@ -98,20 +126,18 @@ Stateful::add_instant_xml (XMLNode& node, const sys::path& directory_path) _instant_xml->remove_nodes_and_delete (node.name()); _instant_xml->add_child_copy (node); - sys::path instant_xml_path(directory_path); + std::string instant_xml_path = Glib::build_filename (directory_path, "instant.xml"); - instant_xml_path /= "instant.xml"; - XMLTree tree; - tree.set_filename(instant_xml_path.to_string()); + tree.set_filename(instant_xml_path); /* Important: the destructor for an XMLTree deletes all of its nodes, starting at _root. We therefore - cannot simply hand it our persistent _instant_xml + cannot simply hand it our persistent _instant_xml node as its _root, because we will lose it whenever the Tree goes out of scope. - So instead, copy the _instant_xml node (which does + So instead, copy the _instant_xml node (which does a deep copy), and hand that to the tree. */ @@ -119,24 +145,23 @@ Stateful::add_instant_xml (XMLNode& node, const sys::path& directory_path) tree.set_root (copy); if (!tree.write()) { - error << string_compose(_("Error: could not write %1"), instant_xml_path.to_string()) << endmsg; + error << string_compose(_("Error: could not write %1"), instant_xml_path) << endmsg; } } XMLNode * -Stateful::instant_xml (const string& str, const sys::path& directory_path) +Stateful::instant_xml (const string& str, const std::string& directory_path) { if (_instant_xml == 0) { - sys::path instant_xml_path(directory_path); - instant_xml_path /= "instant.xml"; + std::string instant_xml_path = Glib::build_filename (directory_path, "instant.xml"); - if (exists(instant_xml_path)) { + if (Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) { XMLTree tree; - if (tree.read(instant_xml_path.to_string())) { + if (tree.read(instant_xml_path)) { _instant_xml = new XMLNode(*(tree.root())); } else { - warning << string_compose(_("Could not understand XML file %1"), instant_xml_path.to_string()) << endmsg; + warning << string_compose(_("Could not understand XML file %1"), instant_xml_path) << endmsg; return 0; } } else { @@ -169,7 +194,7 @@ PropertyList * Stateful::get_changes_as_properties (Command* cmd) const { PropertyList* pl = new PropertyList; - + for (OwnedPropertyList::const_iterator i = _properties->begin(); i != _properties->end(); ++i) { i->second->get_changes_as_properties (*pl, cmd); } @@ -178,7 +203,7 @@ Stateful::get_changes_as_properties (Command* cmd) const } /** Set our property values from an XML node. - * Derived types can call this from ::set_state() (or elsewhere) + * Derived types can call this from set_state() (or elsewhere) * to get basic property setting done. * @return IDs of properties that were changed. */ @@ -186,7 +211,7 @@ PropertyChange Stateful::set_values (XMLNode const & node) { PropertyChange c; - + for (OwnedPropertyList::iterator i = _properties->begin(); i != _properties->end(); ++i) { if (i->second->set_value (node)) { c.add (i->first); @@ -204,29 +229,29 @@ Stateful::apply_changes (const PropertyList& property_list) PropertyChange c; PropertyList::const_iterator p; - DEBUG_TRACE (DEBUG::Stateful, string_compose ("Stateful %1 setting properties from list of %2\n", this, property_list.size())); + DEBUG_TRACE (DEBUG::Stateful, string_compose ("Stateful %1 setting properties from list of %2\n", this, property_list.size())); - for (PropertyList::const_iterator pp = property_list.begin(); pp != property_list.end(); ++pp) { - DEBUG_TRACE (DEBUG::Stateful, string_compose ("in plist: %1\n", pp->second->property_name())); - } - - for (PropertyList::const_iterator i = property_list.begin(); i != property_list.end(); ++i) { - if ((p = _properties->find (i->first)) != _properties->end()) { + for (PropertyList::const_iterator pp = property_list.begin(); pp != property_list.end(); ++pp) { + DEBUG_TRACE (DEBUG::Stateful, string_compose ("in plist: %1\n", pp->second->property_name())); + } + + for (PropertyList::const_iterator i = property_list.begin(); i != property_list.end(); ++i) { + if ((p = _properties->find (i->first)) != _properties->end()) { - DEBUG_TRACE ( + DEBUG_TRACE ( DEBUG::Stateful, string_compose ("actually setting property %1 using %2\n", p->second->property_name(), i->second->property_name()) ); - + if (apply_changes (*i->second)) { c.add (i->first); } } else { - DEBUG_TRACE (DEBUG::Stateful, string_compose ("passed in property %1 not found in own property list\n", - i->second->property_name())); - } + DEBUG_TRACE (DEBUG::Stateful, string_compose ("passed in property %1 not found in own property list\n", + i->second->property_name())); + } } - + post_set (c); send_change (c); @@ -248,7 +273,7 @@ Stateful::add_properties (XMLNode& owner_state) void Stateful::add_property (PropertyBase& s) { - _properties->add (s); + _properties->add (s); } void @@ -259,8 +284,8 @@ Stateful::send_change (const PropertyChange& what_changed) } { - Glib::Mutex::Lock lm (_lock); - if (_frozen) { + Glib::Threads::Mutex::Lock lm (_lock); + if (property_changes_suspended ()) { _pending_changed.add (what_changed); return; } @@ -272,7 +297,7 @@ Stateful::send_change (const PropertyChange& what_changed) void Stateful::suspend_property_changes () { - _frozen++; + g_atomic_int_add (&_stateful_frozen, 1); } void @@ -281,9 +306,9 @@ Stateful::resume_property_changes () PropertyChange what_changed; { - Glib::Mutex::Lock lm (_lock); + Glib::Threads::Mutex::Lock lm (_lock); - if (_frozen && --_frozen > 0) { + if (property_changes_suspended() && g_atomic_int_dec_and_test (&_stateful_frozen) == FALSE) { return; } @@ -293,21 +318,21 @@ Stateful::resume_property_changes () } } - mid_thaw (what_changed); + mid_thaw (what_changed); - send_change (what_changed); + send_change (what_changed); } bool -Stateful::changed() const +Stateful::changed() const { for (OwnedPropertyList::const_iterator i = _properties->begin(); i != _properties->end(); ++i) { - if (i->second->changed()) { - return true; - } - } + if (i->second->changed()) { + return true; + } + } - return false; + return false; } bool @@ -325,17 +350,17 @@ Stateful::apply_changes (const PropertyBase& prop) PropertyList* Stateful::property_factory (const XMLNode& history_node) const { - PropertyList* prop_list = new PropertyList; + PropertyList* prop_list = new PropertyList; - for (OwnedPropertyList::const_iterator i = _properties->begin(); i != _properties->end(); ++i) { - PropertyBase* prop = i->second->clone_from_xml (history_node); + for (OwnedPropertyList::const_iterator i = _properties->begin(); i != _properties->end(); ++i) { + PropertyBase* prop = i->second->clone_from_xml (history_node); - if (prop) { - prop_list->add (prop); - } - } + if (prop) { + prop_list->add (prop); + } + } - return prop_list; + return prop_list; } void @@ -353,6 +378,60 @@ Stateful::clear_owned_changes () i->second->clear_owned_changes (); } } - + +bool +Stateful::set_id (const XMLNode& node) +{ + const XMLProperty* prop; + bool* regen = _regenerate_xml_or_string_ids.get(); + + if (regen && *regen) { + reset_id (); + return true; + } + + if ((prop = node.property ("id")) != 0) { + _id = prop->value (); + return true; + } + + return false; +} + +void +Stateful::reset_id () +{ + _id = ID (); +} + +void +Stateful::set_id (const string& str) +{ + bool* regen = _regenerate_xml_or_string_ids.get(); + + if (regen && *regen) { + reset_id (); + } else { + _id = str; + } +} + +bool +Stateful::regenerate_xml_or_string_ids () const +{ + bool* regen = _regenerate_xml_or_string_ids.get(); + if (regen && *regen) { + return true; + } else { + return false; + } +} + +void +Stateful::set_regenerate_xml_and_string_ids_in_this_thread (bool yn) +{ + bool* val = new bool (yn); + _regenerate_xml_or_string_ids.set (val); +} } // namespace PBD