summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-12-10 17:45:18 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-12-10 17:45:18 +0000
commit90d6916ca3443b81a4eaf615c014ac065554b4f2 (patch)
tree69d14f3bf15b34f054455afd71791ae3616b8260 /libs/ardour
parentb5ca5713fbf2d58485084d7cd70a2a52fb1d7ef5 (diff)
restore rec-enable, solo & mute functionality; remove all Global*Command cruft; reimplement momentary solo&mute; refactor session RT event stuff to be even cleaner and finally compatible with everything-is-a-UI idea ; make all UIs derive from a primitive type that pprovides only void call_slot (sigc::slot<void>) as a way to execute arbitrary code in the UI thread
git-svn-id: svn://localhost/ardour2/branches/3.0@6338 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/session.h104
-rw-r--r--libs/ardour/ardour/session_event.h5
-rw-r--r--libs/ardour/session.cc65
-rw-r--r--libs/ardour/session_command.cc425
-rw-r--r--libs/ardour/session_process.cc8
-rw-r--r--libs/ardour/session_rtevents.cc169
-rw-r--r--libs/ardour/session_state.cc92
-rw-r--r--libs/ardour/wscript1
8 files changed, 195 insertions, 674 deletions
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 4e1721bae0..c4f101ce5c 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -122,12 +122,6 @@ extern void setup_enum_writer ();
class Session : public PBD::StatefulDestructible, public SessionEventManager, public boost::noncopyable
{
- private:
- typedef std::pair<boost::weak_ptr<Route>,bool> RouteBooleanState;
- typedef std::vector<RouteBooleanState> GlobalRouteBooleanState;
- typedef std::pair<boost::weak_ptr<Route>,MeterPoint> RouteMeterState;
- typedef std::vector<RouteMeterState> GlobalRouteMeterState;
-
public:
enum RecordState {
Disabled = 0,
@@ -617,14 +611,17 @@ class Session : public PBD::StatefulDestructible, public SessionEventManager, pu
bool soloing() const { return _non_soloed_outs_muted; }
bool listening() const { return _listen_cnt > 0; }
- void set_solo (boost::shared_ptr<RouteList>, bool);
- void set_mute (boost::shared_ptr<RouteList>, bool);
- void set_listen (boost::shared_ptr<RouteList>, bool);
+ static const sigc::slot<void,SessionEvent*> rt_cleanup;
+
+ void set_solo (boost::shared_ptr<RouteList>, bool, sigc::slot<void,SessionEvent*> after = rt_cleanup, bool group_override = false);
+ void set_just_one_solo (boost::shared_ptr<Route>, bool, sigc::slot<void,SessionEvent*> after = rt_cleanup);
+ void set_mute (boost::shared_ptr<RouteList>, bool, sigc::slot<void,SessionEvent*> after = rt_cleanup, bool group_override = false);
+ void set_listen (boost::shared_ptr<RouteList>, bool, sigc::slot<void,SessionEvent*> after = rt_cleanup, bool group_override = false);
+ void set_record_enable (boost::shared_ptr<RouteList>, bool, sigc::slot<void,SessionEvent*> after = rt_cleanup, bool group_override = false);
sigc::signal<void,bool> SoloActive;
sigc::signal<void> SoloChanged;
- void set_record_enable (boost::shared_ptr<RouteList>, bool);
/* control/master out */
@@ -735,73 +732,6 @@ class Session : public PBD::StatefulDestructible, public SessionEventManager, pu
Command* memento_command_factory(XMLNode* n);
void register_with_memento_command_factory(PBD::ID, PBD::StatefulThingWithGoingAway*);
- Command* global_state_command_factory (const XMLNode& n);
-
- class GlobalRouteStateCommand : public Command
- {
- public:
- GlobalRouteStateCommand (Session&, void*);
- GlobalRouteStateCommand (Session&, const XMLNode& node);
- int set_state (const XMLNode&, int version);
- XMLNode& get_state ();
-
- protected:
- GlobalRouteBooleanState before, after;
- Session& sess;
- void* src;
- };
-
- class GlobalSoloStateCommand : public GlobalRouteStateCommand
- {
- public:
- GlobalSoloStateCommand (Session &, void *src);
- GlobalSoloStateCommand (Session&, const XMLNode&);
- void operator()(); //redo
- void undo();
- XMLNode &get_state();
- void mark();
- };
-
- class GlobalMuteStateCommand : public GlobalRouteStateCommand
- {
- public:
- GlobalMuteStateCommand(Session &, void *src);
- GlobalMuteStateCommand (Session&, const XMLNode&);
- void operator()(); // redo
- void undo();
- XMLNode &get_state();
- void mark();
- };
-
- class GlobalRecordEnableStateCommand : public GlobalRouteStateCommand
- {
- public:
- GlobalRecordEnableStateCommand(Session &, void *src);
- GlobalRecordEnableStateCommand (Session&, const XMLNode&);
- void operator()(); // redo
- void undo();
- XMLNode &get_state();
- void mark();
- };
-
- class GlobalMeteringStateCommand : public Command
- {
- public:
- GlobalMeteringStateCommand(Session &, void *src);
- GlobalMeteringStateCommand (Session&, const XMLNode&);
- void operator()();
- void undo();
- XMLNode &get_state();
- int set_state (const XMLNode&, int version);
- void mark();
-
- protected:
- Session& sess;
- void* src;
- GlobalRouteMeterState before;
- GlobalRouteMeterState after;
- };
-
/* clicking */
boost::shared_ptr<IO> click_io() { return _click_io; }
@@ -1443,16 +1373,6 @@ class Session : public PBD::StatefulDestructible, public SessionEventManager, pu
UndoHistory _history;
std::stack<UndoTransaction*> _current_trans;
- GlobalRouteBooleanState get_global_route_boolean (bool (Route::*method)(void) const);
- GlobalRouteMeterState get_global_route_metering ();
-
- void set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void *arg);
- void set_global_route_metering (GlobalRouteMeterState s, void *arg);
-
- void set_global_mute (GlobalRouteBooleanState s, void *src);
- void set_global_solo (GlobalRouteBooleanState s, void *src);
- void set_global_record_enable (GlobalRouteBooleanState s, void *src);
-
void jack_timebase_callback (jack_transport_state_t, nframes_t, jack_position_t*, int);
int jack_sync_callback (jack_transport_state_t, jack_position_t*);
void reset_jack_connection (jack_client_t* jack);
@@ -1549,6 +1469,16 @@ class Session : public PBD::StatefulDestructible, public SessionEventManager, pu
void update_have_rec_enabled_diskstream ();
gint _have_rec_enabled_diskstream;
+
+ /* realtime "apply to set of routes" operations */
+ SessionEvent* get_rt_event (boost::shared_ptr<RouteList> rl, bool yn, sigc::slot<void,SessionEvent*> after, bool group_override,
+ void (Session::*method) (boost::shared_ptr<RouteList>, bool, bool));
+
+ void rt_set_solo (boost::shared_ptr<RouteList>, bool yn, bool group_override);
+ void rt_set_just_one_solo (boost::shared_ptr<RouteList>, bool yn, bool /* ignored*/ );
+ void rt_set_mute (boost::shared_ptr<RouteList>, bool yn, bool group_override);
+ void rt_set_listen (boost::shared_ptr<RouteList>, bool yn, bool group_override);
+ void rt_set_record_enable (boost::shared_ptr<RouteList>, bool yn, bool group_override);
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/session_event.h b/libs/ardour/ardour/session_event.h
index 7775f4b1ad..bb5b5f49ce 100644
--- a/libs/ardour/ardour/session_event.h
+++ b/libs/ardour/ardour/session_event.h
@@ -7,6 +7,7 @@
#include "pbd/pool.h"
#include "pbd/ringbuffer.h"
+#include "pbd/ui_callback.h"
#include "ardour/types.h"
@@ -68,6 +69,7 @@ struct SessionEvent {
boost::shared_ptr<RouteList> routes;
sigc::slot<void> rt_slot; /* what to call in RT context */
sigc::slot<void,SessionEvent*> rt_return; /* called after rt_slot, with this event as an argument */
+ PBD::UICallback* ui;
std::list<AudioRange> audio_range;
std::list<MusicRange> music_range;
@@ -81,7 +83,8 @@ struct SessionEvent {
, target_frame (where)
, speed (spd)
, yes_or_no (yn)
- , second_yes_or_no (yn2) {}
+ , second_yes_or_no (yn2)
+ , ui (0) {}
void set_ptr (void* p) {
ptr = p;
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 0bf161bb5d..24700b8893 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -117,6 +117,9 @@ sigc::signal<void> Session::AutoBindingOn;
sigc::signal<void> Session::AutoBindingOff;
sigc::signal<void, std::string, std::string> Session::Exported;
+static void clean_up_session_event (SessionEvent* ev) { delete ev; }
+const sigc::slot<void,SessionEvent*> Session::rt_cleanup (sigc::ptr_fun (&clean_up_session_event));
+
Session::Session (AudioEngine &eng,
const string& fullpath,
const string& snapshot_name,
@@ -3515,42 +3518,6 @@ Session::is_auditioning () const
}
}
-void
-Session::set_solo (boost::shared_ptr<RouteList> r, bool yn)
-{
- for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->is_hidden()) {
- (*i)->set_solo (yn, this);
- }
- }
-
- set_dirty();
-}
-
-void
-Session::set_listen (boost::shared_ptr<RouteList> r, bool yn)
-{
- for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->is_hidden()) {
- (*i)->set_listen (yn, this);
- }
- }
-
- set_dirty();
-}
-
-void
-Session::set_mute (boost::shared_ptr<RouteList> r, bool yn)
-{
- for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->is_hidden()) {
- (*i)->set_mute (yn, this);
- }
- }
-
- set_dirty();
-}
-
uint32_t
Session::n_diskstreams () const
{
@@ -3597,32 +3564,6 @@ Session::graph_reordered ()
}
void
-Session::set_record_enable (boost::shared_ptr<RouteList> rl, bool yn)
-{
- if (!writable()) {
- return;
- }
-
- for (RouteList::iterator i = rl->begin(); i != rl->end(); ) {
- boost::shared_ptr<Track> t;
-
- if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
- t->set_record_enable (yn, this);
- if (t->meter_point() == MeterCustom) {
- /* don't change metering for this track */
- i = rl->erase (i);
- } else {
- ++i;
- }
- } else {
- ++i;
- }
- }
-
- set_dirty ();
-}
-
-void
Session::add_processor (Processor* processor)
{
processor->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_processor), processor));
diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc
index d1ce09cbf6..4d733264fb 100644
--- a/libs/ardour/session_command.cc
+++ b/libs/ardour/session_command.cc
@@ -124,428 +124,3 @@ Session::memento_command_factory(XMLNode *n)
return 0 ;
}
-Command *
-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, Stateful::loading_state_version)) {
- throw failed_constructor ();
- }
-}
-
-int
-Session::GlobalRouteStateCommand::set_state (const XMLNode& node, int /*version*/)
-{
- 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 ()
-{
- 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)
- : GlobalRouteStateCommand (sess, src)
-{
- after = before = sess.get_global_route_boolean(&Route::soloed);
-}
-
-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()()
-{
- sess.set_global_solo(after, src);
-}
-
-void
-Session::GlobalSoloStateCommand::undo()
-{
- sess.set_global_solo(before, src);
-}
-
-XMLNode&
-Session::GlobalSoloStateCommand::get_state()
-{
- XMLNode& node = GlobalRouteStateCommand::get_state();
- node.add_property ("type", "solo");
- return node;
-}
-
-// mute
-Session::GlobalMuteStateCommand::GlobalMuteStateCommand(Session &sess, void *src)
- : GlobalRouteStateCommand (sess, src)
-{
- after = before = sess.get_global_route_boolean(&Route::muted);
-}
-
-Session::GlobalMuteStateCommand::GlobalMuteStateCommand (Session& sess, const XMLNode& node)
- : Session::GlobalRouteStateCommand (sess, node)
-{
-}
-
-void
-Session::GlobalMuteStateCommand::mark()
-{
- after = sess.get_global_route_boolean(&Route::muted);
-}
-
-void
-Session::GlobalMuteStateCommand::operator()()
-{
- sess.set_global_mute(after, src);
-}
-
-void
-Session::GlobalMuteStateCommand::undo()
-{
- sess.set_global_mute(before, src);
-}
-
-XMLNode&
-Session::GlobalMuteStateCommand::get_state()
-{
- XMLNode& node = GlobalRouteStateCommand::get_state();
- node.add_property ("type", "mute");
- return node;
-}
-
-// record enable
-Session::GlobalRecordEnableStateCommand::GlobalRecordEnableStateCommand(Session &sess, void *src)
- : GlobalRouteStateCommand (sess, src)
-{
- after = before = sess.get_global_route_boolean(&Route::record_enabled);
-}
-
-Session::GlobalRecordEnableStateCommand::GlobalRecordEnableStateCommand (Session& sess, const XMLNode& node)
- : Session::GlobalRouteStateCommand (sess, node)
-{
-}
-
-void
-Session::GlobalRecordEnableStateCommand::mark()
-{
- after = sess.get_global_route_boolean(&Route::record_enabled);
-}
-
-void
-Session::GlobalRecordEnableStateCommand::operator()()
-{
- sess.set_global_record_enable(after, src);
-}
-
-void
-Session::GlobalRecordEnableStateCommand::undo()
-{
- sess.set_global_record_enable(before, src);
-}
-
-XMLNode&
-Session::GlobalRecordEnableStateCommand::get_state()
-{
- XMLNode& node = GlobalRouteStateCommand::get_state();
- node.add_property ("type", "rec-enable");
- return node;
-}
-
-// metering
-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)
-{
- if (set_state (node, Stateful::loading_state_version)) {
- throw failed_constructor();
- }
-}
-
-void
-Session::GlobalMeteringStateCommand::mark()
-{
- after = sess.get_global_route_metering();
-}
-
-void
-Session::GlobalMeteringStateCommand::operator()()
-{
- sess.set_global_route_metering(after, src);
-}
-
-void
-Session::GlobalMeteringStateCommand::undo()
-{
- sess.set_global_route_metering(before, src);
-}
-
-XMLNode&
-Session::GlobalMeteringStateCommand::get_state()
-{
- 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 = 0;
-
- switch (x->second) {
- case MeterInput:
- meterstr = X_("input");
- break;
- case MeterPreFader:
- meterstr = X_("pre");
- break;
- case MeterPostFader:
- meterstr = X_("post");
- break;
- default:
- fatal << string_compose (_("programming error: %1") , "no meter state in Session::GlobalMeteringStateCommand::get_state") << endmsg;
- }
-
- 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;
- default: meterstr = "";
- }
-
- 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;
-}
-
-int
-Session::GlobalMeteringStateCommand::set_state (const XMLNode& node, int /*version*/)
-{
- 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_process.cc b/libs/ardour/session_process.cc
index 568017c064..9766a1b159 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -577,7 +577,7 @@ Session::follow_slave (nframes_t nframes)
slave_speed));
}
-#if 0
+#if 1
if (abs(average_slave_delta) > _slave->resolution()) {
cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
goto silent_motion;
@@ -1141,9 +1141,3 @@ Session::process_event (SessionEvent* ev)
}
}
-void
-Session::process_rtop (SessionEvent* ev)
-{
- ev->rt_slot ();
- ev->rt_return (ev);
-}
diff --git a/libs/ardour/session_rtevents.cc b/libs/ardour/session_rtevents.cc
new file mode 100644
index 0000000000..6d3e7ce78c
--- /dev/null
+++ b/libs/ardour/session_rtevents.cc
@@ -0,0 +1,169 @@
+/*
+ Copyright (C) 1999-2009 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "pbd/error.h"
+#include "pbd/compose.h"
+
+#include "ardour/session.h"
+#include "ardour/route.h"
+#include "ardour/track.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace PBD;
+using namespace ARDOUR;
+using namespace Glib;
+
+SessionEvent*
+Session::get_rt_event (boost::shared_ptr<RouteList> rl, bool yn, sigc::slot<void,SessionEvent*> after, bool group_override,
+ void (Session::*method) (boost::shared_ptr<RouteList>, bool, bool))
+{
+ SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
+ ev->rt_slot = bind (sigc::mem_fun (*this, method), rl, yn, group_override);
+ ev->rt_return = after;
+ ev->ui = UICallback::get_ui_for_thread ();
+
+ return ev;
+}
+
+void
+Session::set_solo (boost::shared_ptr<RouteList> rl, bool yn, sigc::slot<void,SessionEvent*> after, bool group_override)
+{
+ queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_solo));
+}
+
+void
+Session::rt_set_solo (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
+{
+ for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
+ if (!(*i)->is_hidden()) {
+ (*i)->set_solo (yn, this);
+ }
+ }
+
+ set_dirty();
+}
+
+void
+Session::set_just_one_solo (boost::shared_ptr<Route> r, bool yn, sigc::slot<void,SessionEvent*> after)
+{
+ /* its a bit silly to have to do this, but it keeps the API for this public method sane (we're
+ only going to solo one route) and keeps our ability to use get_rt_event() for the internal
+ private method.
+ */
+
+ boost::shared_ptr<RouteList> rl (new RouteList);
+ rl->push_back (r);
+
+ queue_event (get_rt_event (rl, yn, after, false, &Session::rt_set_just_one_solo));
+}
+
+void
+Session::rt_set_just_one_solo (boost::shared_ptr<RouteList> just_one, bool yn, bool /*ignored*/)
+{
+ boost::shared_ptr<RouteList> rl = routes.reader ();
+ boost::shared_ptr<Route> r = just_one->front();
+
+ for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
+ if (!(*i)->is_hidden() && r != *i) {
+ (*i)->set_solo (!yn, (*i)->route_group());
+ }
+ }
+
+ r->set_solo (yn, r->route_group());
+
+ set_dirty();
+}
+
+void
+Session::set_listen (boost::shared_ptr<RouteList> rl, bool yn, sigc::slot<void,SessionEvent*> after, bool group_override)
+{
+ queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_listen));
+}
+
+void
+Session::rt_set_listen (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
+{
+ for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
+ if (!(*i)->is_hidden()) {
+ (*i)->set_listen (yn, this);
+ }
+ }
+
+ set_dirty();
+}
+
+void
+Session::set_mute (boost::shared_ptr<RouteList> rl, bool yn, sigc::slot<void,SessionEvent*> after, bool group_override)
+{
+ queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_mute));
+}
+
+void
+Session::rt_set_mute (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
+{
+ for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
+ if (!(*i)->is_hidden()) {
+ (*i)->set_mute (yn, this);
+ }
+ }
+
+ set_dirty();
+}
+
+void
+Session::set_record_enable (boost::shared_ptr<RouteList> rl, bool yn, sigc::slot<void,SessionEvent*> after, bool group_override)
+{
+ if (!writable()) {
+ return;
+ }
+
+ queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_record_enable));
+}
+
+void
+Session::rt_set_record_enable (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
+{
+ for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
+ if ((*i)->is_hidden()) {
+ continue;
+ }
+
+ boost::shared_ptr<Track> t;
+
+ if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
+ t->set_record_enable (yn, (group_override ? (void*) t->route_group() : (void *) this));
+ }
+ }
+
+ set_dirty ();
+}
+
+void
+Session::process_rtop (SessionEvent* ev)
+{
+ ev->rt_slot ();
+
+ if (ev->ui) {
+ ev->ui->call_slot (bind (ev->rt_return, ev));
+ } else {
+ warning << string_compose ("programming error: %1", X_("Session RT event queued from thread without a UI - cleanup in RT thread!")) << endmsg;
+ ev->rt_return (ev);
+ }
+}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index db3d9e94ae..74578039a8 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -2176,92 +2176,6 @@ Session::commit_reversible_command(Command *cmd)
_current_trans.pop();
}
-Session::GlobalRouteBooleanState
-Session::get_global_route_boolean (bool (Route::*method)(void) const)
-{
- GlobalRouteBooleanState s;
- boost::shared_ptr<RouteList> r = routes.reader ();
-
- for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->is_hidden()) {
- RouteBooleanState v;
-
- v.first =* i;
- Route* r = (*i).get();
- v.second = (r->*method)();
-
- s.push_back (v);
- }
- }
-
- return s;
-}
-
-Session::GlobalRouteMeterState
-Session::get_global_route_metering ()
-{
- GlobalRouteMeterState s;
- boost::shared_ptr<RouteList> r = routes.reader ();
-
- for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->is_hidden()) {
- RouteMeterState v;
-
- v.first =* i;
- v.second = (*i)->meter_point();
-
- s.push_back (v);
- }
- }
-
- return s;
-}
-
-void
-Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
-{
- for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
-
- boost::shared_ptr<Route> r = (i->first.lock());
-
- if (r) {
- r->set_meter_point (i->second, arg);
- }
- }
-}
-
-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) {
-
- boost::shared_ptr<Route> r = (i->first.lock());
-
- if (r) {
- Route* rp = r.get();
- (rp->*method) (i->second, arg);
- }
- }
-}
-
-void
-Session::set_global_mute (GlobalRouteBooleanState s, void* src)
-{
- set_global_route_boolean (s, &Route::set_mute, src);
-}
-
-void
-Session::set_global_solo (GlobalRouteBooleanState s, void* src)
-{
- set_global_route_boolean (s, &Route::set_solo, src);
-}
-
-void
-Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
-{
- set_global_route_boolean (s, &Route::set_record_enable, src);
-}
-
static bool
accept_all_non_peak_files (const string& path, void */*arg*/)
{
@@ -2892,12 +2806,6 @@ Session::restore_history (string snapshot_name)
ut->add_command(c);
}
- } else if (n->name() == X_("GlobalRouteStateCommand")) {
-
- if ((c = global_state_command_factory (*n))) {
- ut->add_command (c);
- }
-
} else if (n->name() == "DeltaCommand") {
PBD::ID id(n->property("midi-source")->value());
boost::shared_ptr<MidiSource> midi_source =
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index 9f056d9223..0dcfea7056 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -168,6 +168,7 @@ libardour_sources = [
'session_midi.cc',
'session_playlists.cc',
'session_process.cc',
+ 'session_rtevents.cc',
'session_state.cc',
'session_state_utils.cc',
'session_time.cc',