diff options
author | Hans Fugal <hans@fugal.net> | 2006-08-12 21:49:20 +0000 |
---|---|---|
committer | Hans Fugal <hans@fugal.net> | 2006-08-12 21:49:20 +0000 |
commit | 57f7f71ce3c1acae5a50e903d2dd472743df8043 (patch) | |
tree | 6bb6ea6e16a17bbc5e96ecdc70d839ef7b3a955c /libs | |
parent | f995ac37860140c513e29c3bc58701474a7ed336 (diff) |
r316@gandalf: fugalh | 2006-08-11 17:06:48 -0600
Reconstitution. Comiples, untested.
git-svn-id: svn://localhost/ardour2/branches/undo@797 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r-- | libs/ardour/ardour/automation_event.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/curve.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/location.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 11 | ||||
-rw-r--r-- | libs/ardour/audio_diskstream.cc | 2 | ||||
-rw-r--r-- | libs/ardour/automation_event.cc | 4 | ||||
-rw-r--r-- | libs/ardour/curve.cc | 3 | ||||
-rw-r--r-- | libs/ardour/session.cc | 25 | ||||
-rw-r--r-- | libs/ardour/session_command.cc | 79 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 62 | ||||
-rw-r--r-- | libs/ardour/session_transport.cc | 2 | ||||
-rw-r--r-- | libs/pbd/pbd/memento_command.h | 82 | ||||
-rw-r--r-- | libs/pbd/pbd/stateful.h | 3 | ||||
-rw-r--r-- | libs/pbd/undo.cc | 8 |
14 files changed, 221 insertions, 65 deletions
diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h index 5864de73c6..dad94161d0 100644 --- a/libs/ardour/ardour/automation_event.h +++ b/libs/ardour/ardour/automation_event.h @@ -183,6 +183,8 @@ class AutomationList : public StateManager, public Stateful } }; + static sigc::signal<void, AutomationList*> AutomationListCreated; + protected: PBD::ID _id; struct State : public ARDOUR::StateManager::State { diff --git a/libs/ardour/ardour/curve.h b/libs/ardour/ardour/curve.h index 7f8a43cfe1..7ba6b5fa6c 100644 --- a/libs/ardour/ardour/curve.h +++ b/libs/ardour/ardour/curve.h @@ -59,6 +59,8 @@ class Curve : public AutomationList AutomationEventList::iterator closest_control_point_after (double xval); void solve (); + + static sigc::signal<void, Curve*> CurveCreated; protected: ControlEvent* point_factory (double,double) const; diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h index ff953d1d78..beae4a6e07 100644 --- a/libs/ardour/ardour/location.h +++ b/libs/ardour/ardour/location.h @@ -149,6 +149,7 @@ class Locations : public Stateful, public StateManager XMLNode& get_state (void); int set_state (const XMLNode&); PBD::ID id() { return _id; } + Location *get_location_by_id(PBD::ID); Location* auto_loop_location () const; Location* auto_punch_location () const; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index e2b14eccfa..d067de4e68 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -302,6 +302,7 @@ class Session : public sigc::trackable, public Stateful template<class T, class A> void foreach_route (T *obj, void (T::*func)(Route&, A), A arg); boost::shared_ptr<Route> route_by_name (string); + boost::shared_ptr<Route> route_by_id (PBD::ID); boost::shared_ptr<Route> route_by_remote_id (uint32_t id); bool route_name_unique (string) const; @@ -478,6 +479,7 @@ class Session : public sigc::trackable, public Stateful int restore_state (string snapshot_name); int save_template (string template_name); int save_history (string snapshot_name = ""); + int restore_history (string snapshot_name); static int rename_template (string old_name, string new_name); @@ -713,6 +715,10 @@ class Session : public sigc::trackable, public Stateful sigc::signal<void> NamedSelectionAdded; sigc::signal<void> NamedSelectionRemoved; + /* Curves and AutomationLists (TODO when they go away) */ + void add_curve(Curve*); + void add_automation_list(AutomationList*); + /* fade curves */ float get_default_fade_length () const { return default_fade_msecs; } @@ -840,6 +846,7 @@ class Session : public sigc::trackable, public Stateful // these commands are implemented in libs/ardour/session_command.cc Command *memento_command_factory(XMLNode *n); + void register_with_memento_command_factory(PBD::ID, Stateful *); class GlobalSoloStateCommand : public Command { GlobalRouteBooleanState before, after; @@ -1586,6 +1593,10 @@ class Session : public sigc::trackable, public Stateful NamedSelection *named_selection_factory (string name); NamedSelection *XMLNamedSelectionFactory (const XMLNode&); + /* CURVES and AUTOMATION LISTS */ + std::map<PBD::ID, Curve*> curves; + std::map<PBD::ID, AutomationList*> automation_lists; + /* DEFAULT FADE CURVES */ float default_fade_steepness; diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 9619f404fa..d3e64104a0 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -1614,7 +1614,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca _playlist->thaw (); XMLNode &after = _playlist->get_state(); - _session.add_command (new MementoCommand<Playlist>(*_playlist, before, after)); + _session.add_command (new MementoCommand<Playlist>(*_playlist, &before, &after)); } mark_write_completed = true; diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc index dc1767d1e7..cf69c634b1 100644 --- a/libs/ardour/automation_event.cc +++ b/libs/ardour/automation_event.cc @@ -64,6 +64,8 @@ AutomationList::AutomationList (double defval, bool with_state) if (!no_state) { save_state (_("initial")); } + + AutomationListCreated(this); } AutomationList::AutomationList (const AutomationList& other) @@ -91,6 +93,7 @@ AutomationList::AutomationList (const AutomationList& other) } mark_dirty (); + AutomationListCreated(this); } AutomationList::AutomationList (const AutomationList& other, double start, double end) @@ -123,6 +126,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl delete section; mark_dirty (); + AutomationListCreated(this); } AutomationList::~AutomationList() diff --git a/libs/ardour/curve.cc b/libs/ardour/curve.cc index 977b6dfd7b..5879cb5988 100644 --- a/libs/ardour/curve.cc +++ b/libs/ardour/curve.cc @@ -45,6 +45,7 @@ Curve::Curve (double minv, double maxv, double canv, bool nostate) { min_yval = minv; max_yval = maxv; + CurveCreated(this); } Curve::Curve (const Curve& other) @@ -52,6 +53,7 @@ Curve::Curve (const Curve& other) { min_yval = other.min_yval; max_yval = other.max_yval; + CurveCreated(this); } Curve::Curve (const Curve& other, double start, double end) @@ -59,6 +61,7 @@ Curve::Curve (const Curve& other, double start, double end) { min_yval = other.min_yval; max_yval = other.max_yval; + CurveCreated(this); } Curve::~Curve () diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 4a0d820381..1bd11cacc0 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -2227,6 +2227,20 @@ Session::route_by_name (string name) } shared_ptr<Route> +Session::route_by_id (PBD::ID id) +{ + shared_ptr<RouteList> r = routes.reader (); + + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + if ((*i)->id() == id) { + return *i; + } + } + + return shared_ptr<Route> ((Route*) 0); +} + +shared_ptr<Route> Session::route_by_remote_id (uint32_t id) { shared_ptr<RouteList> r = routes.reader (); @@ -3794,3 +3808,14 @@ Session::set_xfade_model (CrossfadeModel xm) } } +void +Session::add_curve(Curve *curve) +{ + curves[curve->id()] = curve; +} + +void +Session::add_automation_list(AutomationList *al) +{ + automation_lists[al->id()] = al; +} diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc index 556c6ea9a3..4021fae573 100644 --- a/libs/ardour/session_command.cc +++ b/libs/ardour/session_command.cc @@ -2,24 +2,85 @@ #include <ardour/route.h> #include <pbd/memento_command.h> #include <ardour/diskstream.h> +#include <ardour/playlist.h> +#include <ardour/tempo.h> +#include <ardour/audiosource.h> +#include <ardour/audioregion.h> +#include <pbd/error.h> +using namespace PBD; +#include "i18n.h" + namespace ARDOUR { +static map<PBD::ID, Stateful*> registry; + +void Session::register_with_memento_command_factory(PBD::ID id, Stateful *ptr) +{ + registry[id] = ptr; +} + Command *Session::memento_command_factory(XMLNode *n) { PBD::ID id; - XMLNode *before, *after; + XMLNode *before = 0, *after = 0; + + /* get id */ + id = PBD::ID(n->property("obj_id")->value()); + + /* get before/after */ + if (n->name() == "MementoCommand") + { + before = n->children().front(); + after = n->children().back(); + } else if (n->name() == "MementoUndoCommand") + before = n->children().front(); + else if (n->name() == "MementoRedoCommand") + after = n->children().front(); - /* get obj_id */ - /* get before and/or after */ + /* create command */ + string obj_T = n->children().front()->name(); + if (obj_T == "AudioRegion" || obj_T == "Region") + { + if (audio_regions.count(id)) + return new MementoCommand<AudioRegion>(*audio_regions[id], before, after); + } + else if (obj_T == "AudioSource") + { + if (audio_sources.count(id)) + return new MementoCommand<AudioSource>(*audio_sources[id], before, after); + } + else if (obj_T == "Location") + return new MementoCommand<Location>(*_locations.get_location_by_id(id), before, after); + else if (obj_T == "Locations") + return new MementoCommand<Locations>(_locations, before, after); + else if (obj_T == "TempoMap") + return new MementoCommand<TempoMap>(*_tempo_map, before, after); + else if (obj_T == "Playlist" || obj_T == "AudioPlaylist") + { + if (Playlist *pl = playlist_by_name(before->property("name")->value())) + return new MementoCommand<Playlist>(*pl, before, after); + } + else if (obj_T == "Route") // inlcudes AudioTrack + return new MementoCommand<Route>(*route_by_id(id), before, after); + // For Editor and AutomationLine which are off-limits here + else if (registry.count(id)) + return new MementoCommand<Stateful>(*registry[id], before, after); + else if (obj_T == "Curve") + { + if (curves.count(id)) + return new MementoCommand<Curve>(*curves[id], before, after); + } + else if (obj_T == "AutomationList") + { + if (automation_lists.count(id)) + return new MementoCommand<AutomationList>(*automation_lists[id], before, after); + } - /* get an object by id by trial and error, and use it to construct an - * appropriate memento command */ - // e.g. - if (Diskstream *obj = diskstream_by_id(id)) - return new MementoCommand<Diskstream>(*obj, *before, *after); - // etc. + /* we failed */ + error << _("could not reconstitute MementoCommand from XMLNode. id=") << id.to_s() << endmsg; + return 0; } // solo diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index ebf2b6efd5..903d6f558a 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -266,6 +266,8 @@ Session::first_stage_init (string fullpath, string snapshot_name) Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect)); AudioDiskstream::DiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream)); NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection)); + Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve)); + AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list)); Controllable::Created.connect (mem_fun (*this, &Session::add_controllable)); Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable)); @@ -3328,3 +3330,63 @@ Session::save_history (string snapshot_name) return 0; } + +int +Session::restore_history (string snapshot_name) +{ + XMLTree tree; + string xmlpath; + + /* read xml */ + xmlpath = _path + snapshot_name + ".history"; + + if (access (xmlpath.c_str(), F_OK)) { + error << string_compose(_("%1: session history file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg; + return 1; + } + + if (!tree.read (xmlpath)) { + error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg; + return -1; + } + + /* replace history */ + history.clear(); + for (XMLNodeConstIterator it = tree.root()->children().begin(); + it != tree.root()->children().end(); + it++) + { + XMLNode *t = *it; + UndoTransaction ut; + struct timeval tv; + + ut.set_name(t->property("name")->value()); + stringstream ss(t->property("tv_sec")->value()); + ss >> tv.tv_sec; + ss.str(t->property("tv_usec")->value()); + ss >> tv.tv_usec; + ut.set_timestamp(tv); + + for (XMLNodeConstIterator child_it = t->children().begin(); + child_it != t->children().end(); + child_it++) + { + XMLNode *n = *child_it; + Command *c; + if (n->name() == "MementoCommand" || + n->name() == "MementoUndoCommand" || + n->name() == "MementoRedoCommand") + { + c = memento_command_factory(n); + if (c) + ut.add_command(c); + } + else + { + error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg; + } + } + history.add(ut); + } + return 0; +} diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 1f70a9ebb8..0e3895caf1 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -324,7 +324,7 @@ Session::non_realtime_stop (bool abort) XMLNode &before = loc->get_state(); loc->set_end(_transport_frame); XMLNode &after = loc->get_state(); - add_command (new MementoCommand<Location>(*loc, before, after)); + add_command (new MementoCommand<Location>(*loc, &before, &after)); } _end_location_is_free = false; diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h index 122dcb4c86..3a72fc9841 100644 --- a/libs/pbd/pbd/memento_command.h +++ b/libs/pbd/pbd/memento_command.h @@ -36,70 +36,44 @@ class MementoCommand : public Command public: MementoCommand(XMLNode &state); MementoCommand(obj_T &obj, - XMLNode &before, - XMLNode &after + XMLNode *before, + XMLNode *after ) : obj(obj), before(before), after(after) {} - void operator() () { obj.set_state(after); } - void undo() { obj.set_state(before); } + void operator() () + { + if (after) + obj.set_state(*after); + } + void undo() + { + if (before) + obj.set_state(*before); + } virtual XMLNode &get_state() { - XMLNode *node = new XMLNode("MementoCommand"); + string name; + if (before && after) + name = "MementoCommand"; + else if (before) + name = "MementoUndoCommand"; + else + name = "MementoRedoCommand"; + + XMLNode *node = new XMLNode(name); node->add_property("obj_id", obj.id().to_s()); node->add_property("type_name", typeid(obj).name()); - node->add_child_copy(before); - node->add_child_copy(after); + + if (before) + node->add_child_copy(*before); + if (after) + node->add_child_copy(*after); + return *node; } protected: obj_T &obj; - XMLNode &before, &after; -}; - -template <class obj_T> -class MementoUndoCommand : public Command -{ -public: - MementoUndoCommand(XMLNode &state); - MementoUndoCommand(obj_T &obj, - XMLNode &before) - : obj(obj), before(before) {} - void operator() () { /* noop */ } - void undo() { obj.set_state(before); } - virtual XMLNode &get_state() - { - XMLNode *node = new XMLNode("MementoUndoCommand"); - node->add_property("obj_id", obj.id().to_s()); - node->add_property("type_name", typeid(obj).name()); - node->add_child_copy(before); - return *node; - } -protected: - obj_T &obj; - XMLNode &before; -}; - -template <class obj_T> -class MementoRedoCommand : public Command -{ -public: - MementoRedoCommand(XMLNode &state); - MementoRedoCommand(obj_T &obj, - XMLNode &after) - : obj(obj), after(after) {} - void operator() () { obj.set_state(after); } - void undo() { /* noop */ } - virtual XMLNode &get_state() - { - XMLNode *node = new XMLNode("MementoRedoCommand"); - node->add_property("obj_id", obj.id().to_s()); - node->add_property("type_name", typeid(obj).name()); - node->add_child_copy(after); - return *node; - } -protected: - obj_T &obj; - XMLNode &after; + XMLNode *before, *after; }; #endif // __lib_pbd_memento_h__ diff --git a/libs/pbd/pbd/stateful.h b/libs/pbd/pbd/stateful.h index 3038f16b4f..5adddfc1c0 100644 --- a/libs/pbd/pbd/stateful.h +++ b/libs/pbd/pbd/stateful.h @@ -22,6 +22,7 @@ #define __pbd_stateful_h__ #include <string> +#include <pbd/id.h> class XMLNode; @@ -41,10 +42,12 @@ class Stateful { virtual void add_instant_xml (XMLNode&, const std::string& dir); XMLNode *instant_xml (const std::string& str, const std::string& dir); + PBD::ID id() { return _id; } protected: XMLNode *_extra_xml; XMLNode *_instant_xml; + PBD::ID _id; }; #endif /* __pbd_stateful_h__ */ diff --git a/libs/pbd/undo.cc b/libs/pbd/undo.cc index 8d1b416c16..6f421de84e 100644 --- a/libs/pbd/undo.cc +++ b/libs/pbd/undo.cc @@ -23,6 +23,7 @@ #include <pbd/undo.h> #include <pbd/xml++.h> #include <string> +#include <sstream> using namespace std; using namespace sigc; @@ -87,6 +88,13 @@ UndoTransaction::redo () XMLNode &UndoTransaction::get_state() { XMLNode *node = new XMLNode ("UndoTransaction"); + stringstream ss; + ss << _timestamp.tv_sec; + node->add_property("tv_sec", ss.str()); + ss.str(""); + ss << _timestamp.tv_usec; + node->add_property("tv_usec", ss.str()); + node->add_property("name", _name); list<Command*>::iterator it; for (it=actions.begin(); it!=actions.end(); it++) |