summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2012-01-18 01:30:44 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2012-01-18 01:30:44 +0000
commit508c5eb5bd7e31d721c3a29fc734aab3a44aa8a9 (patch)
tree4937d96a3f4d366d4722c6225da147599b97a955 /libs
parent4b95a7912aa27b13c4715b9580ec1bb10dbfd7c3 (diff)
make monitor section an optional feature than can be added/removed as needed. this is a big commit, and breakage is possible. it has been moderately tested. this commit also locks the remote control ID of the master bus to 318 and the monitor section (if any) to 319. the numbers are based on MIDI Machine Control limits
git-svn-id: svn://localhost/ardour2/branches/3.0@11256 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/route.h13
-rw-r--r--libs/ardour/ardour/session.h10
-rw-r--r--libs/ardour/internal_return.cc8
-rw-r--r--libs/ardour/io.cc1
-rw-r--r--libs/ardour/route.cc96
-rw-r--r--libs/ardour/session.cc340
-rw-r--r--libs/ardour/session_click.cc1
-rw-r--r--libs/ardour/session_state.cc25
-rw-r--r--libs/ardour/session_transport.cc4
-rw-r--r--libs/ardour/utils.cc8
10 files changed, 325 insertions, 181 deletions
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 3fab63bb9b..e41682dd8e 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -162,6 +162,8 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
void set_listen (bool yn, void* src);
bool listening_via_monitor () const;
+ void enable_monitor_send ();
+ void disable_monitor_send ();
void set_phase_invert (uint32_t, bool yn);
void set_phase_invert (boost::dynamic_bitset<>);
@@ -242,7 +244,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
int add_processor_by_index (boost::shared_ptr<Processor>, int, ProcessorStreams* err = 0, bool activation_allowed = true);
int add_processor (boost::shared_ptr<Processor>, ProcessorList::iterator iter, ProcessorStreams* err = 0, bool activation_allowed = true);
int add_processors (const ProcessorList&, boost::shared_ptr<Processor> before, ProcessorStreams* err = 0);
- int remove_processor (boost::shared_ptr<Processor>, ProcessorStreams* err = 0);
+ int remove_processor (boost::shared_ptr<Processor>, ProcessorStreams* err = 0, bool need_process_lock = true);
int remove_processors (const ProcessorList&, ProcessorStreams* err = 0);
int reorder_processors (const ProcessorList& new_order, ProcessorStreams* err = 0);
void disable_processors (Placement);
@@ -397,6 +399,15 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
void automation_snapshot (framepos_t now, bool force=false);
void protect_automation ();
+ enum {
+ /* These numbers are taken from MIDI Machine Control,
+ which can only control up to 317 tracks without
+ doing sysex segmentation.
+ */
+ MasterBusRemoteControlID = 318,
+ MonitorBusRemoteControlID = 319,
+ };
+
void set_remote_control_id (uint32_t id, bool notify_class_listeners = true);
uint32_t remote_control_id () const;
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index ba1731bcda..fab442f07a 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -628,7 +628,10 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
PBD::Signal0<void> SoloChanged;
PBD::Signal0<void> IsolatedChanged;
- /* control/master out */
+ /* monitor/master out */
+
+ void add_monitor_section ();
+ void remove_monitor_section ();
boost::shared_ptr<Route> monitor_out() const { return _monitor_out; }
boost::shared_ptr<Route> master_out() const { return _master_out; }
@@ -1406,6 +1409,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
boost::shared_ptr<Route> _master_out;
boost::shared_ptr<Route> _monitor_out;
+ void auto_connect_master_bus ();
+
/* Windows VST support */
long _windows_vst_callback (
@@ -1505,6 +1510,9 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
and solo/mute computations.
*/
GraphEdges _current_route_graph;
+
+ uint32_t next_control_id () const;
+ bool ignore_route_processor_changes;
};
} // namespace ARDOUR
diff --git a/libs/ardour/internal_return.cc b/libs/ardour/internal_return.cc
index 19f677f368..3c75c7957d 100644
--- a/libs/ardour/internal_return.cc
+++ b/libs/ardour/internal_return.cc
@@ -57,14 +57,18 @@ InternalReturn::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*e
void
InternalReturn::add_send (InternalSend* send)
{
- Glib::Mutex::Lock lm (_session.engine().process_lock());
+ /* caller must hold process lock */
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
_sends.push_back (send);
}
void
InternalReturn::remove_send (InternalSend* send)
{
- Glib::Mutex::Lock lm (_session.engine().process_lock());
+ /* caller must hold process lock */
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
_sends.remove (send);
}
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index aac2adf784..2397c7ee06 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -1252,6 +1252,7 @@ IO::disable_connecting ()
int
IO::enable_connecting ()
{
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock());
connecting_legal = true;
boost::optional<int> r = ConnectingLegal ();
return r.get_value_or (0);
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 00507627b5..de2e801d31 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -108,6 +108,13 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
{
processor_max_streams.reset();
order_keys[N_("signal")] = order_key_cnt++;
+
+ if (is_master()) {
+ set_remote_control_id (MasterBusRemoteControlID);
+ } else if (is_monitor()) {
+ set_remote_control_id (MonitorBusRemoteControlID);
+ }
+
}
int
@@ -207,6 +214,26 @@ Route::~Route ()
void
Route::set_remote_control_id (uint32_t id, bool notify_class_listeners)
{
+ /* force IDs for master/monitor busses and prevent
+ any other route from accidentally getting these IDs
+ (i.e. legacy sessions)
+ */
+
+ if (is_master() && id != MasterBusRemoteControlID) {
+ id = MasterBusRemoteControlID;
+ }
+
+ if (is_monitor() && id != MonitorBusRemoteControlID) {
+ id = MonitorBusRemoteControlID;
+ }
+
+ /* don't allow it to collide */
+
+ if (!is_master () && !is_monitor() &&
+ (id == MasterBusRemoteControlID || id == MonitorBusRemoteControlID)) {
+ id += MonitorBusRemoteControlID;
+ }
+
if (id != _remote_control_id) {
_remote_control_id = id;
RemoteControlIDChanged ();
@@ -1330,7 +1357,7 @@ Route::clear_processors (Placement p)
}
int
-Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err)
+Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err, bool need_process_lock)
{
/* these can never be removed */
@@ -1388,9 +1415,9 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
if (!removed) {
/* what? */
return 1;
- }
+ }
- {
+ if (need_process_lock) {
Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
if (configure_processors_unlocked (err)) {
@@ -1399,6 +1426,13 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
configure_processors_unlocked (0);
return -1;
}
+ } else {
+ if (configure_processors_unlocked (err)) {
+ pstate.restore ();
+ /* we know this will work, because it worked before :) */
+ configure_processors_unlocked (0);
+ return -1;
+ }
}
_have_internal_generator = false;
@@ -2542,11 +2576,13 @@ Route::remove_send_from_internal_return (InternalSend* send)
}
}
-/** Add a monitor send (if we don't already have one) but don't activate it */
-int
-Route::listen_via_monitor ()
+void
+Route::enable_monitor_send ()
{
- /* master never sends to control outs */
+ /* Caller must hold process lock */
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
+ /* master never sends to monitor section via the normal mechanism */
assert (!is_master ());
/* make sure we have one */
@@ -2556,10 +2592,7 @@ Route::listen_via_monitor ()
}
/* set it up */
- Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
configure_processors (0);
-
- return 0;
}
/** Add an internal send to a route.
@@ -2602,31 +2635,34 @@ Route::drop_listen (boost::shared_ptr<Route> route)
ProcessorStreams err;
ProcessorList::iterator tmp;
- Glib::RWLock::ReaderLock rl(_processor_lock);
- rl.acquire ();
-
- again:
- for (ProcessorList::iterator x = _processors.begin(); x != _processors.end(); ) {
-
- boost::shared_ptr<InternalSend> d = boost::dynamic_pointer_cast<InternalSend>(*x);
-
- if (d && d->target_route() == route) {
- rl.release ();
- remove_processor (*x, &err);
- rl.acquire ();
+ {
+ Glib::RWLock::ReaderLock rl(_processor_lock);
- /* list could have been demolished while we dropped the lock
- so start over.
- */
+ /* have to do this early because otherwise processor reconfig
+ * will put _monitor_send back in the list
+ */
- goto again;
+ if (route == _session.monitor_out()) {
+ _monitor_send.reset ();
}
- }
- rl.release ();
+ again:
+ for (ProcessorList::iterator x = _processors.begin(); x != _processors.end(); ++x) {
+
+ boost::shared_ptr<InternalSend> d = boost::dynamic_pointer_cast<InternalSend>(*x);
+
+ if (d && d->target_route() == route) {
+ rl.release ();
+ remove_processor (*x, &err, false);
+ rl.acquire ();
- if (route == _session.monitor_out()) {
- _monitor_send.reset ();
+ /* list could have been demolished while we dropped the lock
+ so start over.
+ */
+
+ goto again;
+ }
+ }
}
}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 26b3d47b7e..ef0a6c2a48 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -45,6 +45,8 @@
#include "pbd/file_utils.h"
#include "pbd/convert.h"
#include "pbd/strsplit.h"
+#include "pbd/strsplit.h"
+#include "pbd/unwind.h"
#include "ardour/amp.h"
#include "ardour/analyser.h"
@@ -539,105 +541,207 @@ Session::when_engine_running ()
hookup_io ();
if (_is_new && !no_auto_connect()) {
-
Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock());
+ auto_connect_master_bus ();
+ }
- /* don't connect the master bus outputs if there is a monitor bus */
+ _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
- if (_master_out && Config->get_auto_connect_standard_busses() && !_monitor_out) {
+ /* update latencies */
- /* if requested auto-connect the outputs to the first N physical ports.
- */
+ initialize_latencies ();
- uint32_t limit = _master_out->n_outputs().n_total();
+ /* hook us up to the engine */
- for (uint32_t n = 0; n < limit; ++n) {
- boost::shared_ptr<Port> p = _master_out->output()->nth (n);
- string connect_to;
- if (outputs[p->type()].size() > n) {
- connect_to = outputs[p->type()][n];
- }
+ BootMessage (_("Connect to engine"));
+ _engine.set_session (this);
+}
- if (!connect_to.empty() && p->connected_to (connect_to) == false) {
- if (_master_out->output()->connect (p, connect_to, this)) {
- error << string_compose (_("cannot connect master output %1 to %2"), n, connect_to)
- << endmsg;
- break;
- }
- }
+void
+Session::auto_connect_master_bus ()
+{
+ if (!_master_out || !Config->get_auto_connect_standard_busses() || _monitor_out) {
+ return;
+ }
+
+ /* if requested auto-connect the outputs to the first N physical ports.
+ */
+
+ uint32_t limit = _master_out->n_outputs().n_total();
+ vector<string> outputs[DataType::num_types];
+
+ for (uint32_t i = 0; i < DataType::num_types; ++i) {
+ _engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
+ }
+
+ for (uint32_t n = 0; n < limit; ++n) {
+ boost::shared_ptr<Port> p = _master_out->output()->nth (n);
+ string connect_to;
+ if (outputs[p->type()].size() > n) {
+ connect_to = outputs[p->type()][n];
+ }
+
+ if (!connect_to.empty() && p->connected_to (connect_to) == false) {
+ if (_master_out->output()->connect (p, connect_to, this)) {
+ error << string_compose (_("cannot connect master output %1 to %2"), n, connect_to)
+ << endmsg;
+ break;
}
}
+ }
+}
- if (_monitor_out) {
+void
+Session::remove_monitor_section ()
+{
+ if (!_monitor_out) {
+ return;
+ }
- /* AUDIO ONLY as of june 29th 2009, because listen semantics for anything else
- are undefined, at best.
- */
+ /* force reversion to Solo-In-Pace */
+ Config->set_solo_control_is_listen_control (false);
- /* control out listens to master bus (but ignores it
- under some conditions)
- */
+ {
+ /* Hold process lock while doing this so that we don't hear bits and
+ * pieces of audio as we work on each route.
+ */
+
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+
+ /* Connect tracks to monitor section. Note that in an
+ existing session, the internal sends will already exist, but we want the
+ routes to notice that they connect to the control out specifically.
+ */
+
+
+ boost::shared_ptr<RouteList> r = routes.reader ();
+ PBD::Unwinder<bool> uw (ignore_route_processor_changes, true);
+
+ for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
+
+ if ((*x)->is_monitor()) {
+ /* relax */
+ } else if ((*x)->is_master()) {
+ /* relax */
+ } else {
+ (*x)->drop_listen (_monitor_out);
+ }
+ }
+ }
- uint32_t limit = _monitor_out->n_inputs().n_audio();
+ remove_route (_monitor_out);
+ auto_connect_master_bus ();
+}
- if (_master_out) {
- for (uint32_t n = 0; n < limit; ++n) {
- boost::shared_ptr<AudioPort> p = _monitor_out->input()->ports().nth_audio_port (n);
- boost::shared_ptr<AudioPort> o = _master_out->output()->ports().nth_audio_port (n);
+void
+Session::add_monitor_section ()
+{
+ RouteList rl;
- if (o) {
- string connect_to = o->name();
- if (_monitor_out->input()->connect (p, connect_to, this)) {
- error << string_compose (_("cannot connect control input %1 to %2"), n, connect_to)
- << endmsg;
- break;
- }
- }
- }
- }
+ if (_monitor_out || !_master_out) {
+ return;
+ }
- /* if control out is not connected, connect control out to physical outs
- */
+ boost::shared_ptr<Route> r (new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO));
- if (!_monitor_out->output()->connected ()) {
+ if (r->init ()) {
+ return;
+ }
- if (!Config->get_monitor_bus_preferred_bundle().empty()) {
+#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
+ // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
+#endif
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+ r->input()->ensure_io (_master_out->output()->n_ports(), false, this);
+ r->output()->ensure_io (_master_out->output()->n_ports(), false, this);
+ }
- boost::shared_ptr<Bundle> b = bundle_by_name (Config->get_monitor_bus_preferred_bundle());
+ rl.push_back (r);
+ add_routes (rl, false, false);
+
+ assert (_monitor_out);
- if (b) {
- _monitor_out->output()->connect_ports_to_bundle (b, this);
- } else {
- warning << string_compose (_("The preferred I/O for the monitor bus (%1) cannot be found"),
- Config->get_monitor_bus_preferred_bundle())
- << endmsg;
- }
+ /* AUDIO ONLY as of june 29th 2009, because listen semantics for anything else
+ are undefined, at best.
+ */
+
+ uint32_t limit = _monitor_out->n_inputs().n_audio();
+
+ if (_master_out) {
+
+ /* connect the inputs to the master bus outputs. this
+ * represents a separate data feed from the internal sends from
+ * each route. as of jan 2011, it allows the monitor section to
+ * conditionally ignore either the internal sends or the normal
+ * input feed, but we should really find a better way to do
+ * this, i think.
+ */
+
+ _master_out->output()->disconnect (this);
+
+ for (uint32_t n = 0; n < limit; ++n) {
+ boost::shared_ptr<AudioPort> p = _monitor_out->input()->ports().nth_audio_port (n);
+ boost::shared_ptr<AudioPort> o = _master_out->output()->ports().nth_audio_port (n);
+
+ if (o) {
+ string connect_to = o->name();
+ if (_monitor_out->input()->connect (p, connect_to, this)) {
+ error << string_compose (_("cannot connect control input %1 to %2"), n, connect_to)
+ << endmsg;
+ break;
+ }
+ }
+ }
+ }
+
+ /* if monitor section is not connected, connect it to physical outs
+ */
+
+ if (Config->get_auto_connect_standard_busses() && !_monitor_out->output()->connected ()) {
+
+ if (!Config->get_monitor_bus_preferred_bundle().empty()) {
+
+ boost::shared_ptr<Bundle> b = bundle_by_name (Config->get_monitor_bus_preferred_bundle());
+
+ if (b) {
+ _monitor_out->output()->connect_ports_to_bundle (b, this);
+ } else {
+ warning << string_compose (_("The preferred I/O for the monitor bus (%1) cannot be found"),
+ Config->get_monitor_bus_preferred_bundle())
+ << endmsg;
+ }
+
+ } else {
+
+ /* Monitor bus is audio only */
- } else {
+ uint32_t mod = n_physical_outputs.get (DataType::AUDIO);
+ uint32_t limit = _monitor_out->n_outputs().get (DataType::AUDIO);
+ vector<string> outputs[DataType::num_types];
- /* Monitor bus is audio only */
- uint32_t mod = n_physical_outputs.get (DataType::AUDIO);
- uint32_t limit = _monitor_out->n_outputs().get (DataType::AUDIO);
-
- if (mod != 0) {
-
- for (uint32_t n = 0; n < limit; ++n) {
-
- boost::shared_ptr<Port> p = _monitor_out->output()->ports().port(DataType::AUDIO, n);
- string connect_to;
- if (outputs[DataType::AUDIO].size() > (n % mod)) {
- connect_to = outputs[DataType::AUDIO][n % mod];
- }
-
- if (!connect_to.empty()) {
- if (_monitor_out->output()->connect (p, connect_to, this)) {
- error << string_compose (
- _("cannot connect control output %1 to %2"),
- n, connect_to)
- << endmsg;
- break;
- }
- }
+ for (uint32_t i = 0; i < DataType::num_types; ++i) {
+ _engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
+ }
+
+
+ if (mod != 0) {
+
+ for (uint32_t n = 0; n < limit; ++n) {
+
+ boost::shared_ptr<Port> p = _monitor_out->output()->ports().port(DataType::AUDIO, n);
+ string connect_to;
+ if (outputs[DataType::AUDIO].size() > (n % mod)) {
+ connect_to = outputs[DataType::AUDIO][n % mod];
+ }
+
+ if (!connect_to.empty()) {
+ if (_monitor_out->output()->connect (p, connect_to, this)) {
+ error << string_compose (
+ _("cannot connect control output %1 to %2"),
+ n, connect_to)
+ << endmsg;
+ break;
}
}
}
@@ -645,16 +749,32 @@ Session::when_engine_running ()
}
}
- _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
+ /* Hold process lock while doing this so that we don't hear bits and
+ * pieces of audio as we work on each route.
+ */
+
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
- /* update latencies */
+ /* Connect tracks to monitor section. Note that in an
+ existing session, the internal sends will already exist, but we want the
+ routes to notice that they connect to the control out specifically.
+ */
- initialize_latencies ();
- /* hook us up to the engine */
+ boost::shared_ptr<RouteList> rls = routes.reader ();
- BootMessage (_("Connect to engine"));
- _engine.set_session (this);
+ PBD::Unwinder<bool> uw (ignore_route_processor_changes, true);
+
+ for (RouteList::iterator x = rls->begin(); x != rls->end(); ++x) {
+
+ if ((*x)->is_monitor()) {
+ /* relax */
+ } else if ((*x)->is_master()) {
+ /* relax */
+ } else {
+ (*x)->enable_monitor_send ();
+ }
+ }
}
void
@@ -701,30 +821,6 @@ Session::hookup_io ()
Delivery::reset_panners ();
- /* Connect tracks to monitor/listen bus if there is one. Note that in an
- existing session, the internal sends will already exist, but we want the
- routes to notice that they connect to the control out specifically.
- */
-
- if (_monitor_out) {
- boost::shared_ptr<RouteList> r = routes.reader ();
- for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
-
- if ((*x)->is_monitor()) {
-
- /* relax */
-
- } else if ((*x)->is_master()) {
-
- /* relax */
-
- } else {
-
- (*x)->listen_via_monitor ();
- }
- }
- }
-
/* Anyone who cares about input state, wake up and do something */
IOConnectionsComplete (); /* EMIT SIGNAL */
@@ -1467,7 +1563,7 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m
list<boost::shared_ptr<MidiTrack> > ret;
uint32_t control_id;
- control_id = ntracks() + nbusses();
+ control_id = next_control_id ();
bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("MIDI");
@@ -1683,9 +1779,8 @@ Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing
* @param name_template string to use for the start of the name, or "" to use "Audio".
*/
list< boost::shared_ptr<AudioTrack> >
-Session::new_audio_track (
- int input_channels, int output_channels, TrackMode mode, RouteGroup* route_group, uint32_t how_many, string name_template
- )
+Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, RouteGroup* route_group,
+ uint32_t how_many, string name_template)
{
char track_name[32];
uint32_t track_id = 0;
@@ -1694,7 +1789,7 @@ Session::new_audio_track (
list<boost::shared_ptr<AudioTrack> > ret;
uint32_t control_id;
- control_id = ntracks() + nbusses() + 1;
+ control_id = next_control_id ();
bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("Audio");
@@ -1813,7 +1908,7 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
RouteList ret;
uint32_t control_id;
- control_id = ntracks() + nbusses() + 1;
+ control_id = next_control_id ();
bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("Bus");
@@ -1901,7 +1996,7 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
XMLNode* node = tree.root();
- control_id = ntracks() + nbusses() + 1;
+ control_id = next_control_id ();
while (how_many) {
@@ -2054,7 +2149,7 @@ Session::add_routes (RouteList& new_routes, bool auto_connect, bool save)
} else if ((*x)->is_master()) {
/* relax */
} else {
- (*x)->listen_via_monitor ();
+ (*x)->enable_monitor_send ();
}
}
@@ -2153,7 +2248,7 @@ Session::add_internal_sends (boost::shared_ptr<Route> dest, Placement p, boost::
void
Session::remove_route (boost::shared_ptr<Route> route)
{
- if (((route == _master_out) || (route == _monitor_out)) && !Config->get_allow_special_bus_removal()) {
+ if (route == _master_out) {
return;
}
@@ -2175,13 +2270,6 @@ Session::remove_route (boost::shared_ptr<Route> route)
}
if (route == _monitor_out) {
-
- /* cancel control outs for all routes */
-
- for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
- (*r)->drop_listen (_monitor_out);
- }
-
_monitor_out.reset ();
}
@@ -4564,3 +4652,9 @@ Session::session_name_is_legal (const string& path)
return 0;
}
+
+uint32_t
+Session::next_control_id () const
+{
+ return ntracks() + nbusses() + 1;
+}
diff --git a/libs/ardour/session_click.cc b/libs/ardour/session_click.cc
index a9f867e24c..72816f3f19 100644
--- a/libs/ardour/session_click.cc
+++ b/libs/ardour/session_click.cc
@@ -57,7 +57,6 @@ Session::click (framepos_t start, framecnt_t nframes)
click_distance = start - _clicks_cleared;
-
if (!clickm.locked() || _transport_speed != 1.0 || !_clicking || click_data == 0 || ((click_distance + nframes) < _worst_track_latency)) {
_click_io->silence (nframes);
return;
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 33768e1ce8..893f94831b 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -225,6 +225,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
no_questions_about_missing_files = false;
_speakers.reset (new Speakers);
_clicks_cleared = 0;
+ ignore_route_processor_changes = false;
AudioDiskstream::allocate_working_buffers();
@@ -570,7 +571,6 @@ Session::create (const string& session_template, BusProfile* bus_profile)
if (bus_profile) {
RouteList rl;
- int control_id = 1;
ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
if (bus_profile->master_out_channels) {
@@ -586,28 +586,9 @@ Session::create (const string& session_template, BusProfile* bus_profile)
r->input()->ensure_io (count, false, this);
r->output()->ensure_io (count, false, this);
}
- r->set_remote_control_id (control_id++);
rl.push_back (r);
- if (Config->get_use_monitor_bus()) {
- boost::shared_ptr<Route> r (new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO));
- if (r->init ()) {
- return -1;
- }
-#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
- // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
-#endif
- {
- Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
- r->input()->ensure_io (count, false, this);
- r->output()->ensure_io (count, false, this);
- }
- r->set_remote_control_id (control_id);
-
- rl.push_back (r);
- }
-
} else {
/* prohibit auto-connect to master, because there isn't one */
bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
@@ -629,6 +610,10 @@ Session::create (const string& session_template, BusProfile* bus_profile)
Config->set_output_auto_connect (bus_profile->output_ac);
}
+ if (Config->get_use_monitor_bus() && bus_profile) {
+ add_monitor_section ();
+ }
+
save_state ("");
return 0;
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index b1eb5caf27..84699ac718 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -1503,6 +1503,10 @@ Session::xrun_recovery ()
void
Session::route_processors_changed (RouteProcessorChange c)
{
+ if (ignore_route_processor_changes) {
+ return;
+ }
+
if (c.type == RouteProcessorChange::MeterPointChange) {
return;
}
diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc
index 8588d9ccd6..cc02386bf4 100644
--- a/libs/ardour/utils.cc
+++ b/libs/ardour/utils.cc
@@ -344,8 +344,7 @@ path_expand (string path)
if (realpath (path.c_str(), buf)) {
return buf;
} else {
- error << string_compose (_("programming error: realpath(%1) failed, errcode %2"), path, errno) << endmsg;
- return path;
+ return string();
}
}
@@ -362,7 +361,10 @@ search_path_expand (string path)
split (path, s, ':');
for (vector<string>::iterator i = s.begin(); i != s.end(); ++i) {
- n.push_back (path_expand (*i));
+ string exp = path_expand (*i);
+ if (!exp.empty()) {
+ n.push_back (exp);
+ }
}
string r;