summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour_button.cc1
-rw-r--r--gtk2_ardour/mixer_ui.cc40
-rw-r--r--gtk2_ardour/mixer_ui.h2
-rw-r--r--gtk2_ardour/monitor_section.cc4
-rw-r--r--gtk2_ardour/session_option_editor.cc31
-rw-r--r--gtk2_ardour/session_option_editor.h3
-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
16 files changed, 389 insertions, 198 deletions
diff --git a/gtk2_ardour/ardour_button.cc b/gtk2_ardour/ardour_button.cc
index 4689b912f3..55e94a996e 100644
--- a/gtk2_ardour/ardour_button.cc
+++ b/gtk2_ardour/ardour_button.cc
@@ -468,7 +468,6 @@ ArdourButton::on_button_release_event (GdkEventButton *ev)
if (_act_on_release) {
if (_action) {
- Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (_action);
_action->activate ();
return true;
}
diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc
index 474cef2395..053f8eb595 100644
--- a/gtk2_ardour/mixer_ui.cc
+++ b/gtk2_ardour/mixer_ui.cc
@@ -250,6 +250,9 @@ Mixer_UI::Mixer_UI ()
Mixer_UI::~Mixer_UI ()
{
+ if (_monitor_section) {
+ delete _monitor_section;
+ }
}
void
@@ -323,19 +326,21 @@ Mixer_UI::add_strip (RouteList& routes)
}
if (route->is_monitor()) {
+
if (!_monitor_section) {
_monitor_section = new MonitorSection (_session);
- out_packer.pack_end (_monitor_section->tearoff(), false, false);
- } else {
- _monitor_section->set_session (_session);
- }
+
+ XMLNode* mnode = ARDOUR_UI::instance()->tearoff_settings (X_("monitor-section"));
+ if (mnode) {
+ _monitor_section->tearoff().set_state (*mnode);
+ }
+ }
+ out_packer.pack_end (_monitor_section->tearoff(), false, false);
+ _monitor_section->set_session (_session);
_monitor_section->tearoff().show_all ();
- XMLNode* mnode = ARDOUR_UI::instance()->tearoff_settings (X_("monitor-section"));
- if (mnode) {
- _monitor_section->tearoff().set_state (*mnode);
- }
+ route->DropReferences.connect (*this, invalidator(*this), ui_bind (&Mixer_UI::monitor_section_going_away, this), gui_context());
/* no regular strip shown for control out */
@@ -384,25 +389,23 @@ Mixer_UI::remove_strip (MixerStrip* strip)
return;
}
- ENSURE_GUI_THREAD (*this, &Mixer_UI::remove_strip, strip);
-
TreeModel::Children rows = track_model->children();
TreeModel::Children::iterator ri;
list<MixerStrip *>::iterator i;
-
+
if ((i = find (strips.begin(), strips.end(), strip)) != strips.end()) {
strips.erase (i);
}
-
+
strip_redisplay_does_not_sync_order_keys = true;
-
+
for (ri = rows.begin(); ri != rows.end(); ++ri) {
if ((*ri)[track_columns.strip] == strip) {
track_model->erase (ri);
break;
}
}
-
+
strip_redisplay_does_not_sync_order_keys = false;
}
@@ -1850,3 +1853,12 @@ Mixer_UI::set_route_targets_for_operation ()
_route_targets.insert (ms);
}
}
+
+void
+Mixer_UI::monitor_section_going_away ()
+{
+ if (_monitor_section) {
+ out_packer.remove (_monitor_section->tearoff());
+ _monitor_section->set_session (0);
+ }
+}
diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h
index 5a3b746457..febc62b8dd 100644
--- a/gtk2_ardour/mixer_ui.h
+++ b/gtk2_ardour/mixer_ui.h
@@ -275,6 +275,8 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
void follow_editor_selection ();
bool _following_editor_selection;
+
+ void monitor_section_going_away ();
};
#endif /* __ardour_mixer_ui_h__ */
diff --git a/gtk2_ardour/monitor_section.cc b/gtk2_ardour/monitor_section.cc
index 7de31e7d41..11d6b6925c 100644
--- a/gtk2_ardour/monitor_section.cc
+++ b/gtk2_ardour/monitor_section.cc
@@ -214,7 +214,7 @@ MonitorSection::MonitorSection (Session* s)
act = ActionManager::get_action (X_("Monitor"), X_("monitor-cut-all"));
if (act) {
cut_all_button.set_related_action (act);
- }
+ }
dim_all_button.set_text (_("dim"));
dim_all_button.set_name ("monitor section dim");
@@ -549,7 +549,7 @@ MonitorSection::cut_all ()
if (act) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
_monitor->set_cut_all (tact->get_active());
- }
+ }
}
void
diff --git a/gtk2_ardour/session_option_editor.cc b/gtk2_ardour/session_option_editor.cc
index dc72e6a045..e5cd7780f1 100644
--- a/gtk2_ardour/session_option_editor.cc
+++ b/gtk2_ardour/session_option_editor.cc
@@ -260,6 +260,13 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
sigc::mem_fun (*_session_config, &SessionConfiguration::set_auto_input)
));
+ add_option (_("Monitoring"), new BoolOption (
+ "have-monitor-section",
+ _("Use monitor section in this session"),
+ sigc::mem_fun (*this, &SessionOptionEditor::get_use_monitor_section),
+ sigc::mem_fun (*this, &SessionOptionEditor::set_use_monitor_section)
+ ));
+
/* Misc */
add_option (_("Misc"), new OptionEditorHeading (_("MIDI Options")));
@@ -341,3 +348,27 @@ SessionOptionEditor::parameter_changed (std::string const & p)
_sync_source->set_sensitive (!_session->config.get_external_sync ());
}
}
+
+/* the presence of absence of a monitor section is not really a regular session
+ * property so we provide these two functions to act as setter/getter slots
+ */
+
+bool
+SessionOptionEditor::set_use_monitor_section (bool yn)
+{
+ bool had_monitor_section = _session->monitor_out();
+
+ if (yn) {
+ _session->add_monitor_section ();
+ } else {
+ _session->remove_monitor_section ();
+ }
+
+ return had_monitor_section != yn;
+}
+
+bool
+SessionOptionEditor::get_use_monitor_section ()
+{
+ return _session->monitor_out() != 0;
+}
diff --git a/gtk2_ardour/session_option_editor.h b/gtk2_ardour/session_option_editor.h
index 2563f4153d..55d49a1e3a 100644
--- a/gtk2_ardour/session_option_editor.h
+++ b/gtk2_ardour/session_option_editor.h
@@ -35,4 +35,7 @@ private:
ARDOUR::SessionConfiguration* _session_config;
ComboOption<ARDOUR::SyncSource>* _sync_source;
+
+ bool set_use_monitor_section (bool);
+ bool get_use_monitor_section ();
};
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;