summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2010-02-08 19:39:17 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2010-02-08 19:39:17 +0000
commite2baff4f7d00c97dc4192c5ac573aeee8950b2ae (patch)
treed099f62d821f86980b062d2fc93aa6e8c9203ba2 /libs/ardour
parent1afb1cfea4f2ea66962faef01d729014bdc9eb56 (diff)
new RegionCommand object; remove unused string argument from Region::thaw(); add map<ID,Region> in RegionFactory so that we can look up regions by ID
git-svn-id: svn://localhost/ardour2/branches/3.0@6652 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/region.h2
-rw-r--r--libs/ardour/ardour/region_command.h104
-rw-r--r--libs/ardour/ardour/region_factory.h12
-rw-r--r--libs/ardour/audioregion.cc2
-rw-r--r--libs/ardour/enums.cc27
-rw-r--r--libs/ardour/export_graph_builder.cc2
-rw-r--r--libs/ardour/mute_master.cc2
-rw-r--r--libs/ardour/playlist.cc8
-rw-r--r--libs/ardour/region.cc2
-rw-r--r--libs/ardour/region_command.cc274
-rw-r--r--libs/ardour/region_factory.cc40
-rw-r--r--libs/ardour/session.cc4
-rw-r--r--libs/ardour/session_command.cc8
-rw-r--r--libs/ardour/session_state.cc11
-rw-r--r--libs/ardour/wscript1
15 files changed, 490 insertions, 9 deletions
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index 4cae00c532..310bd582cd 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -162,7 +162,7 @@ class Region
void recompute_position_from_lock_style ();
void freeze ();
- void thaw (const std::string& why);
+ void thaw ();
bool covers (nframes_t frame) const {
return first_frame() <= frame && frame <= last_frame();
diff --git a/libs/ardour/ardour/region_command.h b/libs/ardour/ardour/region_command.h
new file mode 100644
index 0000000000..07589b70c7
--- /dev/null
+++ b/libs/ardour/ardour/region_command.h
@@ -0,0 +1,104 @@
+#ifndef __libardour_region_command_h__
+#define __libardour_region_command_h__
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "pbd/command.h"
+
+namespace ARDOUR {
+
+class Region;
+
+class RegionCommand : public Command {
+ public:
+ enum Property {
+ Name,
+ PositionLockStyle,
+ Length,
+ Start,
+ Position,
+ PositionOnTop,
+ Layer,
+ SyncPosition,
+ Hidden,
+ Muted,
+ Opaque,
+ Locked,
+ PositionLocked,
+
+ /* audio */
+ ScaleAmplitude,
+ FadeInActive,
+ FadeInShape,
+ FadeInLength,
+ FadeIn,
+ FadeOutActive,
+ FadeOutShape,
+ FadeOutLength,
+ FadeOut,
+ EnvelopActive,
+ DefaultEnvelope
+ };
+
+ RegionCommand (boost::shared_ptr<Region>);
+ RegionCommand (boost::shared_ptr<Region>, const XMLNode&);
+ RegionCommand (boost::shared_ptr<Region>, Property, const std::string& target_value);
+
+
+ /* this is mildly type-unsafe, in that we could pass in the wrong types for before&after
+ given the value of `property'. however, its just as safe as a variant that accepts
+ strings, and makes this whole class much easier to use.
+ */
+
+ template<typename T> void add_property_change (Property property, const T& before, const T& after) {
+ std::stringstream sb, sa;
+
+ /* in case T is a floating point value ...
+ */
+
+ sb.precision (15);
+ sa.precision (15);
+
+ /* format */
+
+ sb << before;
+ sa << after;
+
+ /* and stash it away */
+
+ _add_property_change (property, sb.str(), sa.str());
+ }
+
+ void set_name (const std::string& str) { _name = str; }
+ const std::string& name() const { return _name; }
+
+ void operator() ();
+ void undo();
+ void redo() { (*this)(); }
+
+ XMLNode &get_state();
+ int set_state (const XMLNode&, int /*version*/);
+
+ private:
+ struct PropertyTriple {
+ Property property;
+ std::string before;
+ std::string after;
+
+ PropertyTriple (Property p, const std::string& b, const std::string& a)
+ : property (p), before (b), after (a) {}
+ };
+
+ boost::shared_ptr<Region> region;
+ typedef std::vector<PropertyTriple> PropertyTriples;
+ PropertyTriples property_changes;
+
+ void do_property_change (Property prop, const std::string& value);
+ void _add_property_change (Property, const std::string& before_value, const std::string& after_value);
+};
+
+}
+
+#endif /* __libardour_region_command_h__ */
diff --git a/libs/ardour/ardour/region_factory.h b/libs/ardour/ardour/region_factory.h
index b53e9490de..64d3417287 100644
--- a/libs/ardour/ardour/region_factory.h
+++ b/libs/ardour/ardour/region_factory.h
@@ -20,6 +20,10 @@
#ifndef __ardour_region_factory_h__
#define __ardour_region_factory_h__
+#include <map>
+
+#include "pbd/id.h"
+
#include "ardour/types.h"
#include "ardour/region.h"
@@ -33,6 +37,10 @@ class AudioRegion;
class RegionFactory {
public:
+
+ static boost::shared_ptr<Region> region_by_id (const PBD::ID&);
+ static void clear_map ();
+
/** This is emitted only when a new id is assigned. Therefore,
in a pure Region copy, it will not be emitted.
@@ -59,6 +67,10 @@ class RegionFactory {
static boost::shared_ptr<Region> create (const SourceList &, nframes_t start, nframes_t length, const std::string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
static boost::shared_ptr<Region> create (Session&, XMLNode&, bool);
static boost::shared_ptr<Region> create (SourceList &, const XMLNode&);
+
+ private:
+ static std::map<PBD::ID,boost::weak_ptr<Region> > region_map;
+ static void map_add (boost::shared_ptr<Region>);
};
}
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index 729398cf21..e904541ac4 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -767,7 +767,7 @@ AudioRegion::set_live_state (const XMLNode& node, int version, Change& what_chan
}
_envelope->thaw ();
- thaw ("");
+ thaw ();
if (send) {
cerr << _name << ": audio final change: " << hex << what_changed << dec << endl;
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 7d07a5a95f..9a512fe708 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -33,6 +33,7 @@
#include "ardour/midi_track.h"
#include "ardour/mute_master.h"
#include "ardour/panner.h"
+#include "ardour/region_command.h"
#include "ardour/route_group.h"
#include "ardour/session.h"
#include "ardour/track.h"
@@ -121,6 +122,7 @@ setup_enum_writer ()
Session::PostTransportWork _Session_PostTransportWork;
Session::SlaveState _Session_SlaveState;
MTC_Status _MIDI_MTC_Status;
+ RegionCommand::Property _RegionCommandProperty;
#define REGISTER(e) enum_writer.register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
#define REGISTER_BITS(e) enum_writer.register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
@@ -583,6 +585,31 @@ setup_enum_writer ()
REGISTER_ENUM(Groove);
REGISTER(_QuantizeType);
+ REGISTER_CLASS_ENUM (RegionCommand, Name);
+ REGISTER_CLASS_ENUM (RegionCommand, PositionLockStyle);
+ REGISTER_CLASS_ENUM (RegionCommand, Length);
+ REGISTER_CLASS_ENUM (RegionCommand, Start);
+ REGISTER_CLASS_ENUM (RegionCommand, Position);
+ REGISTER_CLASS_ENUM (RegionCommand, PositionOnTop);
+ REGISTER_CLASS_ENUM (RegionCommand, Layer);
+ REGISTER_CLASS_ENUM (RegionCommand, SyncPosition);
+ REGISTER_CLASS_ENUM (RegionCommand, Hidden);
+ REGISTER_CLASS_ENUM (RegionCommand, Muted);
+ REGISTER_CLASS_ENUM (RegionCommand, Opaque);
+ REGISTER_CLASS_ENUM (RegionCommand, Locked);
+ REGISTER_CLASS_ENUM (RegionCommand, PositionLocked);
+ REGISTER_CLASS_ENUM (RegionCommand, ScaleAmplitude);
+ REGISTER_CLASS_ENUM (RegionCommand, FadeInActive);
+ REGISTER_CLASS_ENUM (RegionCommand, FadeInShape);
+ REGISTER_CLASS_ENUM (RegionCommand, FadeInLength);
+ REGISTER_CLASS_ENUM (RegionCommand, FadeIn);
+ REGISTER_CLASS_ENUM (RegionCommand, FadeOutActive);
+ REGISTER_CLASS_ENUM (RegionCommand, FadeOutShape);
+ REGISTER_CLASS_ENUM (RegionCommand, FadeOutLength);
+ REGISTER_CLASS_ENUM (RegionCommand, FadeOut);
+ REGISTER_CLASS_ENUM (RegionCommand, EnvelopActive);
+ REGISTER_CLASS_ENUM (RegionCommand, DefaultEnvelope);
+ REGISTER(_RegionCommandProperty);
}
} /* namespace ARDOUR */
diff --git a/libs/ardour/export_graph_builder.cc b/libs/ardour/export_graph_builder.cc
index 3b1d1e3838..01c2934555 100644
--- a/libs/ardour/export_graph_builder.cc
+++ b/libs/ardour/export_graph_builder.cc
@@ -44,7 +44,7 @@ ExportGraphBuilder::~ExportGraphBuilder ()
}
int
-ExportGraphBuilder::process (nframes_t frames, bool last_cycle)
+ExportGraphBuilder::process (nframes_t /* frames */, bool last_cycle)
{
for (ChannelMap::iterator it = channels.begin(); it != channels.end(); ++it) {
it->first->read (process_buffer, process_buffer_frames);
diff --git a/libs/ardour/mute_master.cc b/libs/ardour/mute_master.cc
index 14411580fd..e7810b27fd 100644
--- a/libs/ardour/mute_master.cc
+++ b/libs/ardour/mute_master.cc
@@ -34,7 +34,7 @@ const MuteMaster::MutePoint MuteMaster::AllPoints = MutePoint (MuteMaster::PreFa
MuteMaster::Listen|
MuteMaster::Main);
-MuteMaster::MuteMaster (Session& s, const std::string& name)
+MuteMaster::MuteMaster (Session&, const std::string&)
: _mute_point (MutePoint (0))
{
}
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index 689c1fe35b..39bd5695b4 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -762,7 +762,7 @@ Playlist::partition (nframes_t start, nframes_t end, bool cut)
partition_internal (start, end, cut, thawlist);
for (RegionList::iterator i = thawlist.begin(); i != thawlist.end(); ++i) {
- (*i)->thaw ("separation");
+ (*i)->thaw ();
}
}
@@ -1027,7 +1027,7 @@ Playlist::cut (nframes_t start, nframes_t cnt, bool result_is_hidden)
partition_internal (start, start+cnt-1, true, thawlist);
for (RegionList::iterator i = thawlist.begin(); i != thawlist.end(); ++i) {
- (*i)->thaw ("playlist cut");
+ (*i)->thaw ();
}
return the_copy;
@@ -1900,7 +1900,7 @@ Playlist::set_state (const XMLNode& node, int version)
region->freeze ();
if (region->set_live_state (*child, version, what_changed, false)) {
- region->thaw ("");
+ region->thaw ();
continue;
}
@@ -1915,7 +1915,7 @@ Playlist::set_state (const XMLNode& node, int version)
// So that layer_op ordering doesn't get screwed up
region->set_last_layer_op( region->layer());
- region->thaw ("");
+ region->thaw ();
}
}
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index 1f4d6f0f91..f1dd92abe5 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -1324,7 +1324,7 @@ Region::freeze ()
}
void
-Region::thaw (const string& /*why*/)
+Region::thaw ()
{
Change what_changed = Change (0);
diff --git a/libs/ardour/region_command.cc b/libs/ardour/region_command.cc
new file mode 100644
index 0000000000..02a542e6c7
--- /dev/null
+++ b/libs/ardour/region_command.cc
@@ -0,0 +1,274 @@
+#include "pbd/convert.h"
+#include "pbd/xml++.h"
+#include "pbd/locale_guard.h"
+#include "pbd/enumwriter.h"
+
+#include "ardour/region.h"
+#include "ardour/region_command.h"
+#include "ardour/utils.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+using namespace std;
+
+RegionCommand::RegionCommand (boost::shared_ptr<Region> r, const XMLNode& node)
+ : region (r)
+{
+ if (set_state (node, 0)) {
+ throw failed_constructor();
+ }
+}
+
+RegionCommand::RegionCommand (boost::shared_ptr<Region> r)
+ : region (r)
+{
+}
+
+RegionCommand::RegionCommand (boost::shared_ptr<Region> r, Property prop, const std::string& target_value)
+ : region (r)
+{
+ LocaleGuard lg ("POSIX");
+ string before;
+ char buf[128];
+
+ /* get current value as a string */
+
+ switch (prop) {
+ case Name:
+ before = r->name();
+ break;
+ case PositionLockStyle:
+ before = enum_2_string (r->positional_lock_style());
+ break;
+ case Length:
+ snprintf (buf, sizeof (buf), "%" PRId32, r->length());
+ before = buf;
+ break;
+ case Start:
+ snprintf (buf, sizeof (buf), "%" PRId32, r->start());
+ before = buf;
+ break;
+ case Position:
+ snprintf (buf, sizeof (buf), "%" PRId32, r->position());
+ before = buf;
+ break;
+ case PositionOnTop:
+ snprintf (buf, sizeof (buf), "%" PRId32, r->position());
+ before = buf;
+ break;
+ case Layer:
+ snprintf (buf, sizeof (buf), "%" PRId32, r->layer());
+ before = buf;
+ break;
+ case SyncPosition:
+ snprintf (buf, sizeof (buf), "%" PRId32, r->sync_position());
+ before = buf;
+ break;
+ case Hidden:
+ before = (r->hidden() ? "yes" : "no");
+ break;
+ case Muted:
+ before = (r->muted() ? "yes" : "no");
+ break;
+ case Opaque:
+ before = (r->opaque() ? "yes" : "no");
+ break;
+ case Locked:
+ before = (r->locked() ? "yes" : "no");
+ break;
+ case PositionLocked:
+ before = (r->position_locked() ? "yes" : "no");
+ break;
+
+ /* audio */
+
+ case ScaleAmplitude:
+ break;
+ case FadeInActive:
+ break;
+ case FadeInShape:
+ break;
+ case FadeInLength:
+ break;
+ case FadeIn:
+ break;
+ case FadeOutActive:
+ break;
+ case FadeOutShape:
+ break;
+ case FadeOutLength:
+ break;
+ case FadeOut:
+ break;
+ case EnvelopActive:
+ break;
+ case DefaultEnvelope:
+ break;
+
+ }
+
+ add_property_change (prop, before, target_value);
+}
+
+void
+RegionCommand::_add_property_change (Property prop, const std::string& before, const std::string& after)
+{
+ property_changes.push_back (PropertyTriple (prop, before, after));
+}
+
+void
+RegionCommand::operator() ()
+{
+ region->freeze ();
+ for (PropertyTriples::iterator i= property_changes.begin(); i != property_changes.end(); ++i) {
+ do_property_change (i->property, i->after);
+ }
+ region->thaw ();
+}
+
+void
+RegionCommand::undo ()
+{
+ region->freeze ();
+ for (PropertyTriples::iterator i= property_changes.begin(); i != property_changes.end(); ++i) {
+ do_property_change (i->property, i->before);
+ }
+ region->thaw ();
+}
+
+void
+RegionCommand::do_property_change (Property prop, const std::string& value)
+{
+ Region::PositionLockStyle pls;
+
+ switch (prop) {
+ case Name:
+ region->set_name (value);
+ break;
+ case PositionLockStyle:
+ region->set_position_lock_style ((Region::PositionLockStyle) string_2_enum (value, pls));
+ break;
+ case Length:
+ region->set_length (atoll (value), this);
+ break;
+ case Start:
+ region->set_start (atoll (value), this);
+ break;
+ case Position:
+ region->set_position (atoll (value), this);
+ break;
+ case PositionOnTop:
+ region->set_position_on_top (atoll (value), this);
+ break;
+ case Layer:
+ region->set_layer (atoi (value));
+ break;
+ case SyncPosition:
+ region->set_sync_position (atoi (value));
+ break;
+ case Hidden:
+ region->set_hidden (string_is_affirmative (value));
+ break;
+ case Muted:
+ region->set_muted (string_is_affirmative (value));
+ break;
+ case Opaque:
+ region->set_opaque (string_is_affirmative (value));
+ break;
+ case Locked:
+ region->set_locked (string_is_affirmative (value));
+ break;
+ case PositionLocked:
+ region->set_position_locked (string_is_affirmative (value));
+ break;
+
+ /* audio */
+
+ case ScaleAmplitude:
+ break;
+ case FadeInActive:
+ break;
+ case FadeInShape:
+ break;
+ case FadeInLength:
+ break;
+ case FadeIn:
+ break;
+ case FadeOutActive:
+ break;
+ case FadeOutShape:
+ break;
+ case FadeOutLength:
+ break;
+ case FadeOut:
+ break;
+ case EnvelopActive:
+ break;
+ case DefaultEnvelope:
+ break;
+
+ }
+}
+
+XMLNode&
+RegionCommand::get_state ()
+{
+ XMLNode* node = new XMLNode (X_("RegionCommand"));
+ XMLNode* child;
+
+ node->add_property (X_("region"), region->id().to_s());
+
+ for (PropertyTriples::iterator i = property_changes.begin(); i != property_changes.end(); ++i) {
+
+ child = new XMLNode (X_("Op"));
+
+ child->add_property (X_("property"), enum_2_string (i->property));
+ child->add_property (X_("before"), i->before);
+ child->add_property (X_("after"), i->after);
+
+ node->add_child_nocopy (*child);
+ }
+
+ return *node;
+}
+
+int
+RegionCommand::set_state (const XMLNode& node, int /* version */)
+{
+ const XMLNodeList& children (node.children());
+ Property property;
+ string before;
+ string after;
+ const XMLProperty* prop;
+
+ for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
+
+ if ((*i)->name() != X_("Op")) {
+ continue;
+ }
+
+ if ((prop = (*i)->property (X_("property"))) == 0) {
+ return -1;
+ }
+
+ property = (Property) string_2_enum (prop->value(), property);
+
+ if ((prop = (*i)->property (X_("before"))) == 0) {
+ return -1;
+ }
+
+ before = prop->value();
+
+ if ((prop = (*i)->property (X_("after"))) == 0) {
+ return -1;
+ }
+
+ after = prop->value();
+
+ add_property_change (property, before, after);
+ }
+
+ return 0;
+}
diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc
index 70ea326230..273066855b 100644
--- a/libs/ardour/region_factory.cc
+++ b/libs/ardour/region_factory.cc
@@ -35,6 +35,7 @@ using namespace ARDOUR;
using namespace PBD;
PBD::Signal1<void,boost::shared_ptr<Region> > RegionFactory::CheckNewRegion;
+map<PBD::ID,boost::weak_ptr<Region> > RegionFactory::region_map;
boost::shared_ptr<Region>
RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start,
@@ -50,6 +51,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start,
boost::shared_ptr<AudioRegion> arp (ar);
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
ret->unlock_property_changes ();
+ map_add (ret);
if (announce) {
CheckNewRegion (ret);
}
@@ -59,6 +61,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start,
boost::shared_ptr<MidiRegion> arp (ar);
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
ret->unlock_property_changes ();
+ map_add (ret);
if (announce) {
CheckNewRegion (ret);
}
@@ -82,6 +85,7 @@ RegionFactory::create (boost::shared_ptr<const Region> region)
boost_debug_shared_ptr_mark_interesting (arn, "Region");
boost::shared_ptr<Region> ret (arn);
ret->unlock_property_changes ();
+ map_add (ret);
/* pure copy constructor - no CheckNewRegion emitted */
return ret;
} else if ((mr = boost::dynamic_pointer_cast<const MidiRegion>(region)) != 0) {
@@ -122,6 +126,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, const SourceList& srcs,
boost::shared_ptr<AudioRegion> arp (ar);
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
ret->unlock_property_changes ();
+ map_add (ret);
if (announce) {
CheckNewRegion (ret);
}
@@ -141,6 +146,7 @@ RegionFactory::create (Session& session, XMLNode& node, bool yn)
if (r) {
r->unlock_property_changes ();
+ map_add (r);
CheckNewRegion (r);
}
@@ -161,6 +167,7 @@ RegionFactory::create (const SourceList& srcs, nframes_t start, nframes_t length
boost::shared_ptr<AudioRegion> arp (ar);
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
ret->unlock_property_changes ();
+ map_add (ret);
if (announce) {
CheckNewRegion (ret);
}
@@ -172,6 +179,7 @@ RegionFactory::create (const SourceList& srcs, nframes_t start, nframes_t length
boost::shared_ptr<MidiRegion> mrp (ar);
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (mrp));
ret->unlock_property_changes ();
+ map_add (ret);
if (announce) {
CheckNewRegion (ret);
}
@@ -194,11 +202,13 @@ RegionFactory::create (SourceList& srcs, const XMLNode& node)
boost_debug_shared_ptr_mark_interesting (ar, "Region");
boost::shared_ptr<Region> ret (ar);
ret->unlock_property_changes ();
+ map_add (ret);
CheckNewRegion (ret);
return ret;
} else if (srcs[0]->type() == DataType::MIDI) {
boost::shared_ptr<Region> ret (new MidiRegion (srcs, node));
ret->unlock_property_changes ();
+ map_add (ret);
CheckNewRegion (ret);
return ret;
}
@@ -217,6 +227,7 @@ RegionFactory::create (boost::shared_ptr<Source> src, nframes_t start, nframes_t
boost_debug_shared_ptr_mark_interesting (ar, "Region");
boost::shared_ptr<Region> ret (ar);
ret->unlock_property_changes ();
+ map_add (ret);
if (announce) {
CheckNewRegion (ret);
}
@@ -224,6 +235,7 @@ RegionFactory::create (boost::shared_ptr<Source> src, nframes_t start, nframes_t
} else if ((ms = boost::dynamic_pointer_cast<MidiSource>(src)) != 0) {
boost::shared_ptr<Region> ret (new MidiRegion (ms, start, length, name, layer, flags));
ret->unlock_property_changes ();
+ map_add (ret);
if (announce) {
CheckNewRegion (ret);
}
@@ -232,3 +244,31 @@ RegionFactory::create (boost::shared_ptr<Source> src, nframes_t start, nframes_t
return boost::shared_ptr<Region>();
}
+
+void
+RegionFactory::map_add (boost::shared_ptr<Region> r)
+{
+ pair<ID,boost::weak_ptr<Region> > p;
+ p.first = r->id();
+ p.second = r;
+
+ region_map.insert (p);
+}
+
+boost::shared_ptr<Region>
+RegionFactory::region_by_id (const PBD::ID& id)
+{
+ map<ID,boost::weak_ptr<Region> >::iterator i = region_map.find (id);
+
+ if (i == region_map.end()) {
+ return boost::shared_ptr<Region>();
+ }
+
+ return i->second.lock();
+}
+
+void
+RegionFactory::clear_map ()
+{
+ region_map.clear ();
+}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 31693daff3..7b12478092 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -352,6 +352,10 @@ Session::destroy ()
_engine.remove_session ();
+ /* clear region map. it doesn't hold references, but lets just be sensible here */
+
+ RegionFactory::clear_map ();
+
/* clear history so that no references to objects are held any more */
_history.clear ();
diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc
index 828af69901..19253cc725 100644
--- a/libs/ardour/session_command.cc
+++ b/libs/ardour/session_command.cc
@@ -83,32 +83,40 @@ Session::memento_command_factory(XMLNode *n)
/* create command */
string obj_T = n->property ("type-name")->value();
+
if (obj_T == typeid (AudioRegion).name() || obj_T == typeid (MidiRegion).name() || obj_T == typeid (Region).name()) {
if (regions.count(id)) {
return new MementoCommand<Region>(*regions[id], before, after);
}
+
} else if (obj_T == typeid (AudioSource).name() || obj_T == typeid (MidiSource).name()) {
if (sources.count(id))
return new MementoCommand<Source>(*sources[id], before, after);
+
} else if (obj_T == typeid (Location).name()) {
Location* loc = _locations.get_location_by_id(id);
if (loc) {
return new MementoCommand<Location>(*loc, before, after);
}
+
} else if (obj_T == typeid (Locations).name()) {
return new MementoCommand<Locations>(_locations, before, after);
+
} else if (obj_T == typeid (TempoMap).name()) {
return new MementoCommand<TempoMap>(*_tempo_map, before, after);
+
} else if (obj_T == typeid (Playlist).name() || obj_T == typeid (AudioPlaylist).name() || obj_T == typeid (MidiPlaylist).name()) {
if (boost::shared_ptr<Playlist> pl = playlists->by_name(child->property("name")->value())) {
return new MementoCommand<Playlist>(*(pl.get()), before, after);
}
+
} else if (obj_T == typeid (Route).name() || obj_T == typeid (AudioTrack).name() || obj_T == typeid(MidiTrack).name()) {
if (boost::shared_ptr<Route> r = route_by_id(id)) {
return new MementoCommand<Route>(*r, before, after);
} else {
error << string_compose (X_("Route %1 not found in session"), id) << endmsg;
}
+
} else if (obj_T == typeid (Evoral::Curve).name() || obj_T == typeid (AutomationList).name()) {
std::map<PBD::ID, AutomationList*>::iterator i = automation_lists.find(id);
if (i != automation_lists.end()) {
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 483c9a0899..fd14094f7f 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -91,6 +91,7 @@
#include "ardour/midi_track.h"
#include "ardour/named_selection.h"
#include "ardour/processor.h"
+#include "ardour/region_command.h"
#include "ardour/region_factory.h"
#include "ardour/route_group.h"
#include "ardour/send.h"
@@ -2944,6 +2945,16 @@ Session::restore_history (string snapshot_name)
error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
}
+ } else if (n->name() == "RegionCommand") {
+ PBD::ID id (n->property ("region")->value());
+ boost::shared_ptr<Region> region = RegionFactory::region_by_id (id);
+
+ if (region) {
+ ut->add_command (new RegionCommand (region, *n));
+ } else {
+ error << string_compose (_("Region command references an unknown region ID=%1"), id.to_s()) << endmsg;
+ }
+
} else {
error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
}
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index 33de254b36..ee9aa14850 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -144,6 +144,7 @@ libardour_sources = [
'rc_configuration.cc',
'recent_sessions.cc',
'region.cc',
+ 'region_command.cc',
'region_factory.cc',
'resampled_source.cc',
'return.cc',