summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2006-12-20 17:26:07 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2006-12-20 17:26:07 +0000
commit99e92a1172d73f829c088ca1a15bb71a5de3fb4b (patch)
tree36201955e0fae77624d0bb97586116dded8d5432
parent9062d7c731472bd9455bea829653653681ce4f17 (diff)
reconstruct and use global state commands (mute/solo/rec-enable/meter point)
git-svn-id: svn://localhost/ardour2/trunk@1235 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/gain_meter.cc15
-rw-r--r--libs/ardour/ardour/session.h98
-rw-r--r--libs/ardour/session_command.cc411
-rw-r--r--libs/ardour/session_state.cc22
4 files changed, 450 insertions, 96 deletions
diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc
index bcd5bd0344..9c222b62c8 100644
--- a/gtk2_ardour/gain_meter.cc
+++ b/gtk2_ardour/gain_meter.cc
@@ -678,7 +678,13 @@ GainMeter::meter_press(GdkEventButton* ev)
/* ctrl-shift-click applies change to all routes */
+ _session.begin_reversible_command (_("meter point change"));
+ Session::GlobalMeteringStateCommand *cmd = new Session::GlobalMeteringStateCommand (_session, this);
_session.foreach_route (this, &GainMeter::set_meter_point, next_meter_point (_route->meter_point()));
+ cmd->mark();
+ _session.add_command (cmd);
+ _session.commit_reversible_command ();
+
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
@@ -687,12 +693,19 @@ GainMeter::meter_press(GdkEventButton* ev)
*/
if (ev->button == 1) {
+ _session.begin_reversible_command (_("meter point change"));
+ Session::GlobalMeteringStateCommand *cmd = new Session::GlobalMeteringStateCommand (_session, this);
set_mix_group_meter_point (*_route, next_meter_point (_route->meter_point()));
+ cmd->mark();
+ _session.add_command (cmd);
+ _session.commit_reversible_command ();
}
} else {
- /* click: solo this route */
+ /* click: change just this route */
+
+ // XXX no undo yet
_route->set_meter_point (next_meter_point (_route->meter_point()), this);
}
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 3ea443d9ef..6987698167 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -107,9 +107,9 @@ class Session : public PBD::StatefulDestructible
{
private:
- typedef std::pair<boost::shared_ptr<Route>,bool> RouteBooleanState;
+ typedef std::pair<boost::weak_ptr<Route>,bool> RouteBooleanState;
typedef vector<RouteBooleanState> GlobalRouteBooleanState;
- typedef std::pair<boost::shared_ptr<Route>,MeterPoint> RouteMeterState;
+ typedef std::pair<boost::weak_ptr<Route>,MeterPoint> RouteMeterState;
typedef vector<RouteMeterState> GlobalRouteMeterState;
public:
@@ -766,58 +766,72 @@ class Session : public PBD::StatefulDestructible
Command* memento_command_factory(XMLNode* n);
void register_with_memento_command_factory(PBD::ID, PBD::StatefulThingWithGoingAway*);
- Command* global_state_command_factory (XMLNode* n);
+ Command* global_state_command_factory (const XMLNode& n);
- class GlobalSoloStateCommand : public Command
+ class GlobalRouteStateCommand : public Command
+ {
+ public:
+ GlobalRouteStateCommand (Session&, void*);
+ GlobalRouteStateCommand (Session&, const XMLNode& node);
+ int set_state (const XMLNode&);
+ XMLNode& get_state ();
+
+ protected:
+ GlobalRouteBooleanState before, after;
+ Session& sess;
+ void* src;
+
+ };
+
+ class GlobalSoloStateCommand : public GlobalRouteStateCommand
{
- GlobalRouteBooleanState before, after;
- Session &sess;
- void *src;
- public:
- GlobalSoloStateCommand(Session &, void *src);
- void operator()();
- void undo();
- XMLNode &get_state();
- void mark();
+ public:
+ GlobalSoloStateCommand (Session &, void *src);
+ GlobalSoloStateCommand (Session&, const XMLNode&);
+ void operator()(); //redo
+ void undo();
+ XMLNode &get_state();
+ void mark();
};
- class GlobalMuteStateCommand : public Command
+ class GlobalMuteStateCommand : public GlobalRouteStateCommand
{
- GlobalRouteBooleanState before, after;
- Session &sess;
- void *src;
- public:
- GlobalMuteStateCommand(Session &, void *src);
- void operator()();
- void undo();
- XMLNode &get_state();
- void mark();
+ public:
+ GlobalMuteStateCommand(Session &, void *src);
+ GlobalMuteStateCommand (Session&, const XMLNode&);
+ void operator()(); // redo
+ void undo();
+ XMLNode &get_state();
+ void mark();
};
- class GlobalRecordEnableStateCommand : public Command
+ class GlobalRecordEnableStateCommand : public GlobalRouteStateCommand
{
- GlobalRouteBooleanState before, after;
- Session &sess;
- void *src;
- public:
- GlobalRecordEnableStateCommand(Session &, void *src);
- void operator()();
- void undo();
- XMLNode &get_state();
- void mark();
+ public:
+ GlobalRecordEnableStateCommand(Session &, void *src);
+ GlobalRecordEnableStateCommand (Session&, const XMLNode&);
+ void operator()(); // redo
+ void undo();
+ XMLNode &get_state();
+ void mark();
};
class GlobalMeteringStateCommand : public Command
{
- GlobalRouteMeterState before, after;
- Session &sess;
- void *src;
- public:
- GlobalMeteringStateCommand(Session &, void *src);
- void operator()();
- void undo();
- XMLNode &get_state();
- void mark();
+ public:
+ GlobalMeteringStateCommand(Session &, void *src);
+ GlobalMeteringStateCommand (Session&, const XMLNode&);
+ void operator()();
+ void undo();
+ XMLNode &get_state();
+ int set_state (const XMLNode&);
+ void mark();
+
+ protected:
+ Session& sess;
+ void* src;
+ GlobalRouteMeterState before;
+ GlobalRouteMeterState after;
};
/* clicking */
diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc
index 022aa43145..14ec340f41 100644
--- a/libs/ardour/session_command.cc
+++ b/libs/ardour/session_command.cc
@@ -9,14 +9,15 @@
#include <ardour/audiosource.h>
#include <ardour/audioregion.h>
#include <pbd/error.h>
+#include <pbd/id.h>
#include <pbd/statefuldestructible.h>
+#include <pbd/failed_constructor.h>
using namespace PBD;
+using namespace ARDOUR;
#include "i18n.h"
-namespace ARDOUR {
-
void Session::register_with_memento_command_factory(PBD::ID id, PBD::StatefulThingWithGoingAway *ptr)
{
registry[id] = ptr;
@@ -89,106 +90,424 @@ Session::memento_command_factory(XMLNode *n)
}
Command *
-Session::global_state_command_factory(XMLNode *n)
+Session::global_state_command_factory (const XMLNode& node)
+{
+ const XMLProperty* prop;
+ Command* command = 0;
+
+ if ((prop = node.property ("type")) == 0) {
+ error << _("GlobalRouteStateCommand has no \"type\" node, ignoring") << endmsg;
+ return 0;
+ }
+
+ try {
+
+ if (prop->value() == "solo") {
+ command = new GlobalSoloStateCommand (*this, node);
+ } else if (prop->value() == "mute") {
+ command = new GlobalMuteStateCommand (*this, node);
+ } else if (prop->value() == "rec-enable") {
+ command = new GlobalRecordEnableStateCommand (*this, node);
+ } else if (prop->value() == "metering") {
+ command = new GlobalMeteringStateCommand (*this, node);
+ } else {
+ error << string_compose (_("unknown type of GlobalRouteStateCommand (%1), ignored"), prop->value()) << endmsg;
+ }
+ }
+
+ catch (failed_constructor& err) {
+ return 0;
+ }
+
+ return command;
+}
+
+Session::GlobalRouteStateCommand::GlobalRouteStateCommand (Session& s, void* p)
+ : sess (s), src (p)
+{
+}
+
+Session::GlobalRouteStateCommand::GlobalRouteStateCommand (Session& s, const XMLNode& node)
+ : sess (s), src (this)
+{
+ if (set_state (node)) {
+ throw failed_constructor ();
+ }
+}
+
+int
+Session::GlobalRouteStateCommand::set_state (const XMLNode& node)
+{
+ GlobalRouteBooleanState states;
+ XMLNodeList nlist;
+ const XMLProperty* prop;
+ XMLNode* child;
+ XMLNodeConstIterator niter;
+ int loop;
+
+ before.clear ();
+ after.clear ();
+
+ for (loop = 0; loop < 2; ++loop) {
+
+ const char *str;
+
+ if (loop) {
+ str = "after";
+ } else {
+ str = "before";
+ }
+
+ if ((child = node.child (str)) == 0) {
+ warning << string_compose (_("global route state command has no \"%1\" node, ignoring entire command"), str) << endmsg;
+ return -1;
+ }
+
+ nlist = child->children();
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+
+ RouteBooleanState rbs;
+ boost::shared_ptr<Route> route;
+ ID id;
+
+ prop = (*niter)->property ("id");
+ id = prop->value ();
+
+ if ((route = sess.route_by_id (id)) == 0) {
+ warning << string_compose (_("cannot find track/bus \"%1\" while rebuilding a global route state command, ignored"), id.to_s()) << endmsg;
+ continue;
+ }
+
+ rbs.first = boost::weak_ptr<Route> (route);
+
+ prop = (*niter)->property ("yn");
+ rbs.second = (prop->value() == "1");
+
+ if (loop) {
+ after.push_back (rbs);
+ } else {
+ before.push_back (rbs);
+ }
+ }
+ }
+
+ return 0;
+}
+
+XMLNode&
+Session::GlobalRouteStateCommand::get_state ()
{
- error << string_compose (_("cannot reconstitute %1 from XML yet, ignored"), n->name()) << endmsg;
- return 0 ;
+ XMLNode* node = new XMLNode (X_("GlobalRouteStateCommand"));
+ XMLNode* nbefore = new XMLNode (X_("before"));
+ XMLNode* nafter = new XMLNode (X_("after"));
+
+ for (Session::GlobalRouteBooleanState::iterator x = before.begin(); x != before.end(); ++x) {
+ XMLNode* child = new XMLNode ("s");
+ boost::shared_ptr<Route> r = x->first.lock();
+
+ if (r) {
+ child->add_property (X_("id"), r->id().to_s());
+ child->add_property (X_("yn"), (x->second ? "1" : "0"));
+ nbefore->add_child_nocopy (*child);
+ }
+ }
+
+ for (Session::GlobalRouteBooleanState::iterator x = after.begin(); x != after.end(); ++x) {
+ XMLNode* child = new XMLNode ("s");
+ boost::shared_ptr<Route> r = x->first.lock();
+
+ if (r) {
+ child->add_property (X_("id"), r->id().to_s());
+ child->add_property (X_("yn"), (x->second ? "1" : "0"));
+ nafter->add_child_nocopy (*child);
+ }
+ }
+
+ node->add_child_nocopy (*nbefore);
+ node->add_child_nocopy (*nafter);
+
+ return *node;
}
// solo
+
Session::GlobalSoloStateCommand::GlobalSoloStateCommand(Session &sess, void *src)
- : sess(sess), src(src)
+ : GlobalRouteStateCommand (sess, src)
{
after = before = sess.get_global_route_boolean(&Route::soloed);
}
-void Session::GlobalSoloStateCommand::mark()
+
+Session::GlobalSoloStateCommand::GlobalSoloStateCommand (Session& sess, const XMLNode& node)
+ : Session::GlobalRouteStateCommand (sess, node)
+{
+}
+
+void
+Session::GlobalSoloStateCommand::mark()
{
after = sess.get_global_route_boolean(&Route::soloed);
}
-void Session::GlobalSoloStateCommand::operator()()
+
+void
+Session::GlobalSoloStateCommand::operator()()
{
sess.set_global_solo(after, src);
}
-void Session::GlobalSoloStateCommand::undo()
+
+void
+Session::GlobalSoloStateCommand::undo()
{
sess.set_global_solo(before, src);
}
-XMLNode &Session::GlobalSoloStateCommand::get_state()
+
+XMLNode&
+Session::GlobalSoloStateCommand::get_state()
{
- XMLNode *node = new XMLNode("GlobalSoloStateCommand");
- return *node;
+ XMLNode& node = GlobalRouteStateCommand::get_state();
+ node.add_property ("type", "solo");
+ return node;
}
// mute
Session::GlobalMuteStateCommand::GlobalMuteStateCommand(Session &sess, void *src)
- : sess(sess), src(src)
+ : GlobalRouteStateCommand (sess, src)
{
after = before = sess.get_global_route_boolean(&Route::muted);
}
-void Session::GlobalMuteStateCommand::mark()
+
+Session::GlobalMuteStateCommand::GlobalMuteStateCommand (Session& sess, const XMLNode& node)
+ : Session::GlobalRouteStateCommand (sess, node)
+{
+}
+
+void
+Session::GlobalMuteStateCommand::mark()
{
- after = sess.get_global_route_boolean(&Route::muted);
+ after = sess.get_global_route_boolean(&Route::muted);
}
-void Session::GlobalMuteStateCommand::operator()()
+
+void
+Session::GlobalMuteStateCommand::operator()()
{
- sess.set_global_mute(after, src);
+ sess.set_global_mute(after, src);
}
-void Session::GlobalMuteStateCommand::undo()
+
+void
+Session::GlobalMuteStateCommand::undo()
{
- sess.set_global_mute(before, src);
+ sess.set_global_mute(before, src);
}
-XMLNode &Session::GlobalMuteStateCommand::get_state()
+
+XMLNode&
+Session::GlobalMuteStateCommand::get_state()
{
- XMLNode *node = new XMLNode("GlobalMuteStateCommand");
- return *node;
+ XMLNode& node = GlobalRouteStateCommand::get_state();
+ node.add_property ("type", "mute");
+ return node;
}
// record enable
Session::GlobalRecordEnableStateCommand::GlobalRecordEnableStateCommand(Session &sess, void *src)
- : sess(sess), src(src)
+ : GlobalRouteStateCommand (sess, src)
{
- after = before = sess.get_global_route_boolean(&Route::record_enabled);
+ after = before = sess.get_global_route_boolean(&Route::record_enabled);
}
-void Session::GlobalRecordEnableStateCommand::mark()
+
+Session::GlobalRecordEnableStateCommand::GlobalRecordEnableStateCommand (Session& sess, const XMLNode& node)
+ : Session::GlobalRouteStateCommand (sess, node)
{
- after = sess.get_global_route_boolean(&Route::record_enabled);
}
-void Session::GlobalRecordEnableStateCommand::operator()()
+
+void
+Session::GlobalRecordEnableStateCommand::mark()
+{
+ after = sess.get_global_route_boolean(&Route::record_enabled);
+}
+
+void
+Session::GlobalRecordEnableStateCommand::operator()()
{
- sess.set_global_record_enable(after, src);
+ sess.set_global_record_enable(after, src);
}
-void Session::GlobalRecordEnableStateCommand::undo()
+
+void
+Session::GlobalRecordEnableStateCommand::undo()
{
- sess.set_global_record_enable(before, src);
+ sess.set_global_record_enable(before, src);
}
-XMLNode &Session::GlobalRecordEnableStateCommand::get_state()
+
+XMLNode&
+Session::GlobalRecordEnableStateCommand::get_state()
{
- XMLNode *node = new XMLNode("GlobalRecordEnableStateCommand");
- return *node;
+ XMLNode& node = GlobalRouteStateCommand::get_state();
+ node.add_property ("type", "rec-enable");
+ return node;
}
// metering
-Session::GlobalMeteringStateCommand::GlobalMeteringStateCommand(Session &sess, void *src)
- : sess(sess), src(src)
+Session::GlobalMeteringStateCommand::GlobalMeteringStateCommand(Session &s, void *p)
+ : sess (s), src (p)
+{
+ after = before = sess.get_global_route_metering();
+}
+
+Session::GlobalMeteringStateCommand::GlobalMeteringStateCommand (Session& s, const XMLNode& node)
+ : sess (s), src (this)
{
- after = before = sess.get_global_route_metering();
+ if (set_state (node)) {
+ throw failed_constructor();
+ }
}
-void Session::GlobalMeteringStateCommand::mark()
+
+void
+Session::GlobalMeteringStateCommand::mark()
{
- after = sess.get_global_route_metering();
+ after = sess.get_global_route_metering();
}
-void Session::GlobalMeteringStateCommand::operator()()
+
+void
+Session::GlobalMeteringStateCommand::operator()()
{
- sess.set_global_route_metering(after, src);
+ sess.set_global_route_metering(after, src);
}
-void Session::GlobalMeteringStateCommand::undo()
+
+void
+Session::GlobalMeteringStateCommand::undo()
{
- sess.set_global_route_metering(before, src);
+ sess.set_global_route_metering(before, src);
}
-XMLNode &Session::GlobalMeteringStateCommand::get_state()
+
+XMLNode&
+Session::GlobalMeteringStateCommand::get_state()
{
- XMLNode *node = new XMLNode("GlobalMeteringStateCommand");
- return *node;
+ XMLNode* node = new XMLNode (X_("GlobalRouteStateCommand"));
+ XMLNode* nbefore = new XMLNode (X_("before"));
+ XMLNode* nafter = new XMLNode (X_("after"));
+
+ for (Session::GlobalRouteMeterState::iterator x = before.begin(); x != before.end(); ++x) {
+ XMLNode* child = new XMLNode ("s");
+ boost::shared_ptr<Route> r = x->first.lock();
+
+ if (r) {
+ child->add_property (X_("id"), r->id().to_s());
+
+ const char* meterstr;
+
+ switch (x->second) {
+ case MeterInput:
+ meterstr = X_("input");
+ break;
+ case MeterPreFader:
+ meterstr = X_("pre");
+ break;
+ case MeterPostFader:
+ meterstr = X_("post");
+ break;
+ }
+
+ child->add_property (X_("meter"), meterstr);
+ nbefore->add_child_nocopy (*child);
+ }
+ }
+
+ for (Session::GlobalRouteMeterState::iterator x = after.begin(); x != after.end(); ++x) {
+ XMLNode* child = new XMLNode ("s");
+ boost::shared_ptr<Route> r = x->first.lock();
+
+ if (r) {
+ child->add_property (X_("id"), r->id().to_s());
+
+ const char* meterstr;
+
+ switch (x->second) {
+ case MeterInput:
+ meterstr = X_("input");
+ break;
+ case MeterPreFader:
+ meterstr = X_("pre");
+ break;
+ case MeterPostFader:
+ meterstr = X_("post");
+ break;
+ }
+
+ child->add_property (X_("meter"), meterstr);
+ nafter->add_child_nocopy (*child);
+ }
+ }
+
+ node->add_child_nocopy (*nbefore);
+ node->add_child_nocopy (*nafter);
+
+ node->add_property ("type", "metering");
+
+ return *node;
}
-} // namespace ARDOUR
+int
+Session::GlobalMeteringStateCommand::set_state (const XMLNode& node)
+{
+ GlobalRouteBooleanState states;
+ XMLNodeList nlist;
+ const XMLProperty* prop;
+ XMLNode* child;
+ XMLNodeConstIterator niter;
+ int loop;
+
+ before.clear ();
+ after.clear ();
+
+ for (loop = 0; loop < 2; ++loop) {
+
+ const char *str;
+
+ if (loop) {
+ str = "after";
+ } else {
+ str = "before";
+ }
+
+ if ((child = node.child (str)) == 0) {
+ warning << string_compose (_("global route meter state command has no \"%1\" node, ignoring entire command"), str) << endmsg;
+ return -1;
+ }
+
+ nlist = child->children();
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+
+ RouteMeterState rms;
+ boost::shared_ptr<Route> route;
+ ID id;
+
+ prop = (*niter)->property ("id");
+ id = prop->value ();
+
+ if ((route = sess.route_by_id (id)) == 0) {
+ warning << string_compose (_("cannot find track/bus \"%1\" while rebuilding a global route state command, ignored"), id.to_s()) << endmsg;
+ continue;
+ }
+
+ rms.first = boost::weak_ptr<Route> (route);
+
+ prop = (*niter)->property ("meter");
+
+ if (prop->value() == X_("pre")) {
+ rms.second = MeterPreFader;
+ } else if (prop->value() == X_("post")) {
+ rms.second = MeterPostFader;
+ } else {
+ rms.second = MeterInput;
+ }
+
+ if (loop) {
+ after.push_back (rms);
+ } else {
+ before.push_back (rms);
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index cbc363a203..986656af5a 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -2161,7 +2161,12 @@ void
Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
{
for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
- i->first->set_meter_point (i->second, arg);
+
+ boost::shared_ptr<Route> r = (i->first.lock());
+
+ if (r) {
+ r->set_meter_point (i->second, arg);
+ }
}
}
@@ -2169,8 +2174,13 @@ void
Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
{
for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
- Route* r = i->first.get();
- (r->*method) (i->second, arg);
+
+ boost::shared_ptr<Route> r = (i->first.lock());
+
+ if (r) {
+ Route* rp = r.get();
+ (rp->*method) (i->second, arg);
+ }
}
}
@@ -2971,11 +2981,9 @@ Session::restore_history (string snapshot_name)
ut->add_command(c);
}
- } else if (n->name() == "GlobalRecordEnableStateCommand" ||
- n->name() == "GlobalSoloStateCommand" ||
- n->name() == "GlobalMuteStateCommand") {
+ } else if (n->name() == X_("GlobalRouteStateCommand")) {
- if ((c = global_state_command_factory (n))) {
+ if ((c = global_state_command_factory (*n))) {
ut->add_command (c);
}