1 /* 2 * Copyright (C) 2000-2015 Paul Davis <paul@linuxaudiosystems.com> 3 * Copyright (C) 2006 Hans Fugal <hans@fugal.net> 4 * Copyright (C) 2007-2015 Tim Mayberry <mojofunk@gmail.com> 5 * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net> 6 * Copyright (C) 2015 Robin Gareus <robin@gareus.org> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License along 19 * with this program; if not, write to the Free Software Foundation, Inc., 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21 */ 22 23 #ifndef __pbd_stateful_h__ 24 #define __pbd_stateful_h__ 25 26 #include <string> 27 #include <list> 28 #include <cassert> 29 30 #include "pbd/libpbd_visibility.h" 31 #include "pbd/id.h" 32 #include "pbd/xml++.h" 33 #include "pbd/property_basics.h" 34 #include "pbd/signals.h" 35 #include "pbd/g_atomic_compat.h" 36 37 class XMLNode; 38 39 namespace PBD { 40 41 namespace sys { 42 class path; 43 } 44 45 class PropertyList; 46 class OwnedPropertyList; 47 48 /** Base class for objects with saveable and undoable state */ 49 class LIBPBD_API Stateful { 50 public: 51 Stateful (); 52 virtual ~Stateful(); 53 54 virtual XMLNode& get_state (void) = 0; 55 virtual int set_state (const XMLNode&, int version) = 0; 56 57 virtual bool apply_changes (PropertyBase const &); 58 PropertyChange apply_changes (PropertyList const &); 59 properties()60 const OwnedPropertyList& properties() const { return *_properties; } 61 62 void add_property (PropertyBase& s); 63 64 /* Extra XML node: so that 3rd parties can attach state to the XMLNode 65 representing the state of this object. 66 */ 67 68 void add_extra_xml (XMLNode&); 69 XMLNode *extra_xml (const std::string& str, bool add_if_missing = false); 70 void save_extra_xml (const XMLNode&); 71 id()72 const PBD::ID& id() const { return _id; } 73 bool set_id (const XMLNode&); 74 void set_id (const std::string&); 75 void reset_id (); 76 77 /* RAII structure to manage thread-local ID regeneration. 78 */ 79 struct ForceIDRegeneration { ForceIDRegenerationForceIDRegeneration80 ForceIDRegeneration () { 81 set_regenerate_xml_and_string_ids_in_this_thread (true); 82 } ~ForceIDRegenerationForceIDRegeneration83 ~ForceIDRegeneration () { 84 set_regenerate_xml_and_string_ids_in_this_thread (false); 85 } 86 }; 87 88 /* history management */ 89 90 void clear_changes (); 91 virtual void clear_owned_changes (); 92 PropertyList* get_changes_as_properties (Command *) const; 93 virtual void rdiff (std::vector<Command*> &) const; 94 bool changed() const; 95 96 /* create a property list from an XMLNode */ 97 virtual PropertyList* property_factory (const XMLNode&) const; 98 99 /* How stateful's notify of changes to their properties */ 100 PBD::Signal1<void,const PropertyChange&> PropertyChanged; 101 102 static int current_state_version; 103 static int loading_state_version; 104 105 virtual void suspend_property_changes (); 106 virtual void resume_property_changes (); 107 property_changes_suspended()108 bool property_changes_suspended() const { return g_atomic_int_get (&_stateful_frozen) > 0; } 109 110 protected: 111 112 void add_instant_xml (XMLNode&, const std::string& directory_path); 113 XMLNode *instant_xml (const std::string& str, const std::string& directory_path); 114 void add_properties (XMLNode &); 115 116 PropertyChange set_values (XMLNode const &); 117 118 /* derived classes can implement this to do cross-checking 119 of property values after either a PropertyList or XML 120 driven property change. 121 */ post_set(const PropertyChange &)122 virtual void post_set (const PropertyChange&) { }; 123 124 XMLNode *_extra_xml; 125 XMLNode *_instant_xml; 126 PBD::PropertyChange _pending_changed; 127 Glib::Threads::Mutex _lock; 128 129 std::string _xml_node_name; ///< name of node to use for this object in XML 130 OwnedPropertyList* _properties; 131 132 virtual void send_change (const PropertyChange&); 133 /** derived classes can implement this in order to process a property change 134 within thaw() just before send_change() is called. 135 */ mid_thaw(const PropertyChange &)136 virtual void mid_thaw (const PropertyChange&) { } 137 138 bool regenerate_xml_or_string_ids () const; 139 140 private: 141 friend struct ForceIDRegeneration; 142 static Glib::Threads::Private<bool> _regenerate_xml_or_string_ids; 143 144 PBD::ID _id; 145 GATOMIC_QUAL gint _stateful_frozen; 146 147 static void set_regenerate_xml_and_string_ids_in_this_thread (bool yn); 148 }; 149 150 } // namespace PBD 151 152 #endif /* __pbd_stateful_h__ */ 153