summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/port_matrix.cc13
-rw-r--r--gtk2_ardour/processor_box.cc2
-rw-r--r--libs/ardour/ardour/io.h26
-rw-r--r--libs/ardour/ardour/route.h6
-rw-r--r--libs/ardour/auditioner.cc14
-rw-r--r--libs/ardour/delivery.cc4
-rw-r--r--libs/ardour/io.cc124
-rw-r--r--libs/ardour/port_insert.cc17
-rw-r--r--libs/ardour/route.cc173
-rw-r--r--libs/ardour/send.cc2
-rw-r--r--libs/ardour/session.cc89
-rw-r--r--libs/ardour/session_state.cc15
-rw-r--r--libs/pbd/pbd/signals.h4
13 files changed, 333 insertions, 156 deletions
diff --git a/gtk2_ardour/port_matrix.cc b/gtk2_ardour/port_matrix.cc
index 113a11c116..052a26c25c 100644
--- a/gtk2_ardour/port_matrix.cc
+++ b/gtk2_ardour/port_matrix.cc
@@ -25,6 +25,7 @@
#include <gtkmm/menushell.h>
#include <gtkmm/menu_elems.h>
#include <gtkmm/window.h>
+#include <gtkmm/stock.h>
#include "ardour/bundle.h"
#include "ardour/types.h"
#include "ardour/session.h"
@@ -33,6 +34,7 @@
#include "port_matrix.h"
#include "port_matrix_body.h"
#include "port_matrix_component.h"
+#include "ardour_dialog.h"
#include "i18n.h"
#include "gui_thread.h"
#include "utils.h"
@@ -686,7 +688,16 @@ PortMatrix::remove_channel (ARDOUR::BundleChannel b)
if (io) {
Port* p = io->nth (b.channel);
if (p) {
- io->remove_port (p, this);
+ int const r = io->remove_port (p, this);
+ if (r == -1) {
+ ArdourDialog d (_("Port removal not allowed"));
+ Label l (_("This port cannot be removed, as the first plugin in the track or buss cannot accept the new number of inputs."));
+ d.get_vbox()->pack_start (l);
+ d.add_button (Stock::OK, RESPONSE_ACCEPT);
+ d.set_modal (true);
+ d.show_all ();
+ d.run ();
+ }
}
}
}
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index 673b3dc1bb..99875a2a47 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -801,6 +801,7 @@ ProcessorBox::choose_insert ()
_route->add_processor (processor, _placement);
}
+/* Caller must not hold process lock */
void
ProcessorBox::choose_send ()
{
@@ -813,6 +814,7 @@ ProcessorBox::choose_send ()
/* XXX need processor lock on route */
try {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock());
send->output()->ensure_io (outs, false, this);
} catch (AudioEngine::PortRegistrationFailure& err) {
error << string_compose (_("Cannot set up new send: %1"), err.what()) << endmsg;
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index a94149e178..9d423f55a5 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -133,6 +133,7 @@ class IO : public SessionObject, public Latent
const ChanCount& n_ports () const { return _ports.count(); }
+ /** Emitted with the process lock held */
PBD::Signal2<void,IOChange,void*> changed;
virtual XMLNode& state (bool full);
@@ -140,6 +141,31 @@ class IO : public SessionObject, public Latent
int set_state (const XMLNode&, int version);
int set_state_2X (const XMLNode&, int, bool);
+ class BoolCombiner {
+ public:
+
+ typedef bool result_type;
+
+ template <typename Iter>
+ bool operator() (Iter first, Iter last) const {
+ bool r = false;
+ while (first != last) {
+ if (*first) {
+ r = true;
+ }
+ ++first;
+ }
+
+ return r;
+ }
+ };
+
+ /** Emitted when the port count is about to change. Objects
+ * can attach to this, and return `true' if they want to prevent
+ * the change from happening.
+ */
+ PBD::Signal1<bool, ChanCount, BoolCombiner> PortCountChanging;
+
static int disable_connecting (void);
static int enable_connecting (void);
static int disable_ports (void);
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 9a874b459d..38300a7de9 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -261,6 +261,8 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
PBD::Signal0<void> signal_latency_changed;
PBD::Signal0<void> initial_delay_changed;
PBD::Signal0<void> order_key_changed;
+
+ /** Emitted with the process lock held */
PBD::Signal0<void> io_changed;
/* gui's call this for their own purposes. */
@@ -473,9 +475,13 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
void input_change_handler (IOChange, void *src);
void output_change_handler (IOChange, void *src);
+ bool input_port_count_changing (ChanCount);
+
bool _in_configure_processors;
int configure_processors_unlocked (ProcessorStreams*);
+ std::list<std::pair<ChanCount, ChanCount> > try_configure_processors (ChanCount, ProcessorStreams *);
+ std::list<std::pair<ChanCount, ChanCount> > try_configure_processors_unlocked (ChanCount, ProcessorStreams *);
bool add_processor_from_xml_2X (const XMLNode&, int);
diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc
index baf97292ec..37df6297da 100644
--- a/libs/ardour/auditioner.cc
+++ b/libs/ardour/auditioner.cc
@@ -176,11 +176,15 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
}
ProcessorStreams ps;
- if (configure_processors (&ps)) {
- error << string_compose (_("Cannot setup auditioner processing flow for %1 channels"),
- _diskstream->n_channels()) << endmsg;
- return;
- }
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+
+ if (configure_processors (&ps)) {
+ error << string_compose (_("Cannot setup auditioner processing flow for %1 channels"),
+ _diskstream->n_channels()) << endmsg;
+ return;
+ }
+ }
/* force a panner reset now that we have all channels */
diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc
index 4277ee4ed8..700efd8ac1 100644
--- a/libs/ardour/delivery.cc
+++ b/libs/ardour/delivery.cc
@@ -35,6 +35,7 @@
#include "ardour/panner.h"
#include "ardour/port.h"
#include "ardour/session.h"
+#include "ardour/audioengine.h"
#include "i18n.h"
@@ -178,9 +179,12 @@ Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out) con
return false;
}
+/** Caller must hold process lock */
bool
Delivery::configure_io (ChanCount in, ChanCount out)
{
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
/* check configuration by comparison with our I/O port configuration, if appropriate.
see ::can_support_io_configuration() for comments
*/
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index d9a0a3c1e0..de4d658596 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -184,38 +184,38 @@ IO::disconnect (Port* our_port, string other_port, void* src)
check_bundles_connected ();
}
+
+ changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
}
- changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
_session.set_dirty ();
return 0;
}
+/** Caller must hold process lock */
int
IO::connect (Port* our_port, string other_port, void* src)
{
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
if (other_port.length() == 0 || our_port == 0) {
return 0;
}
{
- BLOCK_PROCESS_CALLBACK ();
-
- {
- Glib::Mutex::Lock lm (io_lock);
-
- /* check that our_port is really one of ours */
-
- if ( ! _ports.contains(our_port) ) {
- return -1;
- }
-
- /* connect it to the source */
-
- if (our_port->connect (other_port)) {
- return -1;
- }
+ Glib::Mutex::Lock lm (io_lock);
+
+ /* check that our_port is really one of ours */
+
+ if ( ! _ports.contains(our_port) ) {
+ return -1;
+ }
+
+ /* connect it to the source */
+
+ if (our_port->connect (other_port)) {
+ return -1;
}
}
@@ -227,6 +227,15 @@ IO::connect (Port* our_port, string other_port, void* src)
int
IO::remove_port (Port* port, void* src)
{
+ ChanCount before = _ports.count ();
+ ChanCount after = before;
+ after.set (port->type(), after.get (port->type()) - 1);
+
+ bool const r = PortCountChanging (after); /* EMIT SIGNAL */
+ if (r) {
+ return -1;
+ }
+
IOChange change;
{
@@ -235,8 +244,6 @@ IO::remove_port (Port* port, void* src)
{
Glib::Mutex::Lock lm (io_lock);
- ChanCount before = _ports.count ();
-
if (_ports.remove(port)) {
change.type = IOChange::Type (change.type | IOChange::ConfigurationChanged);
change.before = before;
@@ -252,19 +259,22 @@ IO::remove_port (Port* port, void* src)
}
PortCountChanged (n_ports()); /* EMIT SIGNAL */
+
+ if (change.type != IOChange::NoChange) {
+ changed (change, src);
+ _session.set_dirty ();
+ }
}
if (change.type & IOChange::ConfigurationChanged) {
setup_bundle ();
}
- if (change.type != IOChange::NoChange) {
- changed (change, src);
- _session.set_dirty ();
- return 0;
+ if (change.type == IOChange::NoChange) {
+ return -1;
}
- return -1;
+ return 0;
}
/** Add a port.
@@ -312,6 +322,11 @@ IO::add_port (string destination, void* src, DataType type)
}
PortCountChanged (n_ports()); /* EMIT SIGNAL */
+
+ // pan_changed (src); /* EMIT SIGNAL */
+ change.type = IOChange::ConfigurationChanged;
+ change.after = _ports.count ();
+ changed (change, src); /* EMIT SIGNAL */
}
if (destination.length()) {
@@ -320,10 +335,6 @@ IO::add_port (string destination, void* src, DataType type)
}
}
- // pan_changed (src); /* EMIT SIGNAL */
- change.type = IOChange::ConfigurationChanged;
- change.after = _ports.count ();
- changed (change, src); /* EMIT SIGNAL */
setup_bundle ();
_session.set_dirty ();
@@ -333,28 +344,29 @@ IO::add_port (string destination, void* src, DataType type)
int
IO::disconnect (void* src)
{
+ BLOCK_PROCESS_CALLBACK ();
+
{
- BLOCK_PROCESS_CALLBACK ();
-
- {
- Glib::Mutex::Lock lm (io_lock);
-
- for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
- i->disconnect_all ();
- }
-
- check_bundles_connected ();
+ Glib::Mutex::Lock lm (io_lock);
+
+ for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
+ i->disconnect_all ();
}
+
+ check_bundles_connected ();
}
-
+
changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
return 0;
}
+/** Caller must hold process lock */
bool
IO::ensure_ports_locked (ChanCount count, bool clear, void* /*src*/)
{
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
Port* port = 0;
bool changed = false;
@@ -419,10 +431,12 @@ IO::ensure_ports_locked (ChanCount count, bool clear, void* /*src*/)
return changed;
}
-
+/** Caller must hold process lock */
int
IO::ensure_ports (ChanCount count, bool clear, void* src)
{
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
bool changed = false;
if (count == n_ports() && !clear) {
@@ -434,7 +448,6 @@ IO::ensure_ports (ChanCount count, bool clear, void* src)
change.before = _ports.count ();
{
- BLOCK_PROCESS_CALLBACK ();
Glib::Mutex::Lock im (io_lock);
changed = ensure_ports_locked (count, clear, src);
}
@@ -450,9 +463,12 @@ IO::ensure_ports (ChanCount count, bool clear, void* src)
return 0;
}
+/** Caller must hold process lock */
int
IO::ensure_io (ChanCount count, bool clear, void* src)
{
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
return ensure_ports (count, clear, src);
}
@@ -830,9 +846,13 @@ IO::create_ports (const XMLNode& node, int version)
get_port_counts (node, version, n, c);
- if (ensure_ports (n, true, this)) {
- error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
- return -1;
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+
+ if (ensure_ports (n, true, this)) {
+ error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
+ return -1;
+ }
}
/* XXX use c */
@@ -1004,9 +1024,13 @@ IO::set_ports (const string& str)
return 0;
}
- // FIXME: audio-only
- if (ensure_ports (ChanCount(DataType::AUDIO, nports), true, this)) {
- return -1;
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+
+ // FIXME: audio-only
+ if (ensure_ports (ChanCount(DataType::AUDIO, nports), true, this)) {
+ return -1;
+ }
}
string::size_type start, end, ostart;
@@ -1158,8 +1182,9 @@ IO::update_port_total_latencies ()
int
IO::connect_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
{
+ BLOCK_PROCESS_CALLBACK ();
+
{
- BLOCK_PROCESS_CALLBACK ();
Glib::Mutex::Lock lm2 (io_lock);
c->connect (_bundle, _session.engine());
@@ -1189,8 +1214,9 @@ IO::connect_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
int
IO::disconnect_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
{
+ BLOCK_PROCESS_CALLBACK ();
+
{
- BLOCK_PROCESS_CALLBACK ();
Glib::Mutex::Lock lm2 (io_lock);
c->disconnect (_bundle, _session.engine());
diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc
index 20c6b127d2..4854c08d8b 100644
--- a/libs/ardour/port_insert.cc
+++ b/libs/ardour/port_insert.cc
@@ -244,17 +244,22 @@ PortInsert::signal_latency() const
}
}
+/** Caller must not hold process lock */
bool
PortInsert::configure_io (ChanCount in, ChanCount out)
{
/* for an insert, processor input corresponds to IO output, and vice versa */
- if (_input->ensure_io (in, false, this) != 0) {
- return false;
- }
-
- if (_output->ensure_io (out, false, this) != 0) {
- return false;
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+
+ if (_input->ensure_io (in, false, this) != 0) {
+ return false;
+ }
+
+ if (_output->ensure_io (out, false, this) != 0) {
+ return false;
+ }
}
return Processor::configure_io (in, out);
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 1bb9c63db5..150d53a1fa 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -120,6 +120,8 @@ Route::init ()
_input->changed.connect_same_thread (*this, boost::bind (&Route::input_change_handler, this, _1, _2));
_output->changed.connect_same_thread (*this, boost::bind (&Route::output_change_handler, this, _1, _2));
+ _input->PortCountChanging.connect_same_thread (*this, boost::bind (&Route::input_port_count_changing, this, _1));
+
/* add amp processor */
_amp.reset (new Amp (_session));
@@ -876,13 +878,17 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite
// Set up processor list channels. This will set processor->[input|output]_streams(),
// configure redirect ports properly, etc.
- if (configure_processors_unlocked (err)) {
- ProcessorList::iterator ploc = loc;
- --ploc;
- _processors.erase(ploc);
- configure_processors_unlocked (0); // it worked before we tried to add it ...
- cerr << "configure failed\n";
- return -1;
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+
+ if (configure_processors_unlocked (err)) {
+ ProcessorList::iterator ploc = loc;
+ --ploc;
+ _processors.erase(ploc);
+ configure_processors_unlocked (0); // it worked before we tried to add it ...
+ cerr << "configure failed\n";
+ return -1;
+ }
}
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(processor)) != 0) {
@@ -1051,10 +1057,13 @@ Route::add_processors (const ProcessorList& others, ProcessorList::iterator iter
(*i)->activate ();
}
- if (configure_processors_unlocked (err)) {
- _processors.erase (inserted);
- configure_processors_unlocked (0); // it worked before we tried to add it ...
- return -1;
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+ if (configure_processors_unlocked (err)) {
+ _processors.erase (inserted);
+ configure_processors_unlocked (0); // it worked before we tried to add it ...
+ return -1;
+ }
}
(*i)->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false, false));
@@ -1259,7 +1268,11 @@ Route::clear_processors (Placement p)
}
_processors = new_list;
- configure_processors_unlocked (&err); // this can't fail
+
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+ configure_processors_unlocked (&err); // this can't fail
+ }
}
processor_max_streams.reset();
@@ -1333,12 +1346,16 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
return 1;
}
- if (configure_processors_unlocked (err)) {
- /* get back to where we where */
- _processors.insert (i, processor);
- /* we know this will work, because it worked before :) */
- configure_processors_unlocked (0);
- return -1;
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+
+ if (configure_processors_unlocked (err)) {
+ /* get back to where we where */
+ _processors.insert (i, processor);
+ /* we know this will work, because it worked before :) */
+ configure_processors_unlocked (0);
+ return -1;
+ }
}
_have_internal_generator = false;
@@ -1420,12 +1437,16 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
_output->set_user_latency (0);
- if (configure_processors_unlocked (err)) {
- /* get back to where we where */
- _processors = as_we_were;
- /* we know this will work, because it worked before :) */
- configure_processors_unlocked (0);
- return -1;
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+
+ if (configure_processors_unlocked (err)) {
+ /* get back to where we where */
+ _processors = as_we_were;
+ /* we know this will work, because it worked before :) */
+ configure_processors_unlocked (0);
+ return -1;
+ }
}
_have_internal_generator = false;
@@ -1454,10 +1475,12 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
return 0;
}
-
+/** Caller must hold process lock */
int
Route::configure_processors (ProcessorStreams* err)
{
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
if (!_in_configure_processors) {
Glib::RWLock::WriterLock lm (_processor_lock);
return configure_processors_unlocked (err);
@@ -1471,22 +1494,20 @@ Route::input_streams () const
return _input->n_ports ();
}
-/** Configure the input/output configuration of each processor in the processors list.
- * Return 0 on success, otherwise configuration is impossible.
- */
-int
-Route::configure_processors_unlocked (ProcessorStreams* err)
+list<pair<ChanCount, ChanCount> >
+Route::try_configure_processors (ChanCount in, ProcessorStreams* err)
{
- if (_in_configure_processors) {
- return 0;
- }
+ Glib::RWLock::ReaderLock lm (_processor_lock);
- _in_configure_processors = true;
+ return try_configure_processors_unlocked (in, err);
+}
+list<pair<ChanCount, ChanCount> >
+Route::try_configure_processors_unlocked (ChanCount in, ProcessorStreams* err)
+{
// Check each processor in order to see if we can configure as requested
- ChanCount in = input_streams ();
ChanCount out;
- list< pair<ChanCount,ChanCount> > configuration;
+ list<pair<ChanCount, ChanCount> > configuration;
uint32_t index = 0;
DEBUG_TRACE (DEBUG::Processors, string_compose ("%1: configure processors\n", _name));
@@ -1507,12 +1528,37 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
err->index = index;
err->count = in;
}
- _in_configure_processors = false;
- return -1;
+ return list<pair<ChanCount, ChanCount> > ();
}
}
- // We can, so configure everything
+ return configuration;
+}
+
+/** Set the input/output configuration of each processor in the processors list.
+ * Caller must hold process lock.
+ * Return 0 on success, otherwise configuration is impossible.
+ */
+int
+Route::configure_processors_unlocked (ProcessorStreams* err)
+{
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
+ if (_in_configure_processors) {
+ return 0;
+ }
+
+ _in_configure_processors = true;
+
+ list<pair<ChanCount, ChanCount> > configuration = try_configure_processors_unlocked (input_streams (), err);
+
+ if (configuration.empty ()) {
+ _in_configure_processors = false;
+ return -1;
+ }
+
+ ChanCount out;
+
list< pair<ChanCount,ChanCount> >::iterator c = configuration.begin();
for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++c) {
(*p)->configure_io(c->first, c->second);
@@ -1527,10 +1573,7 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
/* make sure we have sufficient scratch buffers to cope with the new processor
configuration */
- {
- Glib::Mutex::Lock em (_session.engine().process_lock ());
- _session.ensure_buffers (n_process_buffers ());
- }
+ _session.ensure_buffers (n_process_buffers ());
DEBUG_TRACE (DEBUG::Processors, string_compose ("%1: configuration complete\n", _name));
@@ -1686,10 +1729,14 @@ Route::reorder_processors (const ProcessorList& new_order, ProcessorStreams* err
_processors.insert (oiter, as_it_will_be.begin(), as_it_will_be.end());
- if (configure_processors_unlocked (err)) {
- _processors = as_it_was_before;
- processor_max_streams = old_pms;
- return -1;
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+
+ if (configure_processors_unlocked (err)) {
+ _processors = as_it_was_before;
+ processor_max_streams = old_pms;
+ return -1;
+ }
}
}
@@ -2335,6 +2382,7 @@ Route::set_processor_state (const XMLNode& node)
Glib::RWLock::WriterLock lm (_processor_lock);
_processors = new_order;
if (must_configure) {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
configure_processors_unlocked (0);
}
}
@@ -2647,6 +2695,7 @@ Route::handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool c
_roll_delay = _initial_delay;
}
+/** Called with the process lock held */
void
Route::input_change_handler (IOChange change, void * /*src*/)
{
@@ -2657,6 +2706,7 @@ Route::input_change_handler (IOChange change, void * /*src*/)
}
}
+/** Called with the process lock held */
void
Route::output_change_handler (IOChange change, void * /*src*/)
{
@@ -2958,10 +3008,14 @@ Route::put_monitor_send_at (Placement p)
_processors.insert (loc, _monitor_send);
- if (configure_processors_unlocked (0)) {
- _processors = as_it_was;
- configure_processors_unlocked (0); // it worked before we tried to add it ...
- return;
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+
+ if (configure_processors_unlocked (0)) {
+ _processors = as_it_was;
+ configure_processors_unlocked (0); // it worked before we tried to add it ...
+ return;
+ }
}
}
@@ -3456,3 +3510,20 @@ Route::set_processor_positions ()
}
}
+/** Called when there is a proposed change to the input port count */
+bool
+Route::input_port_count_changing (ChanCount to)
+{
+ list<pair<ChanCount, ChanCount> > c = try_configure_processors (to, 0);
+ if (c.empty()) {
+ /* The processors cannot be configured with the new input arrangement, so
+ block the change.
+ */
+ return true;
+ }
+
+ /* The change is ok */
+ return false;
+}
+
+
diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc
index bfbceb49af..74212155ec 100644
--- a/libs/ardour/send.cc
+++ b/libs/ardour/send.cc
@@ -217,6 +217,7 @@ Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
return true;
}
+/** Caller must not hold process lock */
bool
Send::configure_io (ChanCount in, ChanCount out)
{
@@ -225,6 +226,7 @@ Send::configure_io (ChanCount in, ChanCount out)
}
if (_output) {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock());
_output->ensure_io (out, false, 0);
}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index f5df3a0e6b..64c5a173c4 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -1504,6 +1504,7 @@ Session::count_existing_route_channels (ChanCount& in, ChanCount& out)
}
}
+/** Caller must not hold process lock */
list<boost::shared_ptr<MidiTrack> >
Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_many)
{
@@ -1541,15 +1542,17 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m
boost_debug_shared_ptr_mark_interesting (mt, "Track");
track = boost::shared_ptr<MidiTrack>(mt);
- if (track->input()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
- error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
- goto failed;
- }
-
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+ if (track->input()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
+ error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
+ goto failed;
+ }
- if (track->output()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
- error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
- goto failed;
+ if (track->output()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
+ error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
+ goto failed;
+ }
}
auto_connect_route (track.get(), existing_inputs, existing_outputs);
@@ -1590,7 +1593,8 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m
return ret;
}
-/** @param connect_inputs true to connect inputs as well as outputs, false to connect just outputs.
+/** Caller must hold process lock.
+ * @param connect_inputs true to connect inputs as well as outputs, false to connect just outputs.
* @param input_start Where to start from when auto-connecting inputs; e.g. if this is 0, auto-connect starting from input 0.
* @param output_start As \a input_start, but for outputs.
*/
@@ -1669,6 +1673,7 @@ Session::auto_connect_route (
existing_outputs += route->n_outputs();
}
+/** Caller must not hold process lock */
list< boost::shared_ptr<AudioTrack> >
Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, RouteGroup* route_group, uint32_t how_many)
{
@@ -1706,23 +1711,27 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
boost_debug_shared_ptr_mark_interesting (at, "Track");
track = boost::shared_ptr<AudioTrack>(at);
- if (track->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
- error << string_compose (
- _("cannot configure %1 in/%2 out configuration for new audio track"),
- input_channels, output_channels)
- << endmsg;
- goto failed;
- }
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
- if (track->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
- error << string_compose (
- _("cannot configure %1 in/%2 out configuration for new audio track"),
- input_channels, output_channels)
- << endmsg;
- goto failed;
- }
+ if (track->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
+ error << string_compose (
+ _("cannot configure %1 in/%2 out configuration for new audio track"),
+ input_channels, output_channels)
+ << endmsg;
+ goto failed;
+ }
+
+ if (track->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
+ error << string_compose (
+ _("cannot configure %1 in/%2 out configuration for new audio track"),
+ input_channels, output_channels)
+ << endmsg;
+ goto failed;
+ }
- auto_connect_route (track.get(), existing_inputs, existing_outputs);
+ auto_connect_route (track.get(), existing_inputs, existing_outputs);
+ }
if (route_group) {
route_group->add (track);
@@ -1787,7 +1796,7 @@ Session::set_remote_control_ids ()
}
}
-
+/** Caller must not hold process lock */
RouteList
Session::new_audio_route (bool aux, int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many)
{
@@ -1820,23 +1829,27 @@ Session::new_audio_route (bool aux, int input_channels, int output_channels, Rou
boost_debug_shared_ptr_mark_interesting (rt, "Route");
shared_ptr<Route> bus (rt);
- if (bus->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
- error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
- input_channels, output_channels)
- << endmsg;
- goto failure;
- }
+ {
+ Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+ if (bus->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
+ error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
+ input_channels, output_channels)
+ << endmsg;
+ goto failure;
+ }
+
+
+ if (bus->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
+ error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
+ input_channels, output_channels)
+ << endmsg;
+ goto failure;
+ }
- if (bus->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
- error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
- input_channels, output_channels)
- << endmsg;
- goto failure;
+ auto_connect_route (bus.get(), existing_inputs, existing_outputs, false);
}
- auto_connect_route (bus.get(), existing_inputs, existing_outputs, false);
-
if (route_group) {
route_group->add (bus);
}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 6ceeeb599c..9f87c77009 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -510,6 +510,7 @@ Session::ensure_subdirs ()
return 0;
}
+/** Caller must not hold process lock */
int
Session::create (const string& mix_template, BusProfile* bus_profile)
{
@@ -578,8 +579,11 @@ Session::create (const string& mix_template, BusProfile* bus_profile)
}
boost_debug_shared_ptr_mark_interesting (rt, "Route");
boost::shared_ptr<Route> r (rt);
- r->input()->ensure_io (count, false, this);
- r->output()->ensure_io (count, false, this);
+ {
+ 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);
@@ -592,8 +596,11 @@ Session::create (const string& mix_template, BusProfile* bus_profile)
}
boost_debug_shared_ptr_mark_interesting (rt, "Route");
boost::shared_ptr<Route> r (rt);
- r->input()->ensure_io (count, false, this);
- r->output()->ensure_io (count, false, this);
+ {
+ 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);
diff --git a/libs/pbd/pbd/signals.h b/libs/pbd/pbd/signals.h
index cfbbc949c9..17059ec854 100644
--- a/libs/pbd/pbd/signals.h
+++ b/libs/pbd/pbd/signals.h
@@ -110,11 +110,11 @@ private:
SignalType _signal;
};
-template<typename R, typename A>
+template<typename R, typename A, typename C = boost::signals2::optional_last_value<R> >
class Signal1 {
public:
Signal1 () {}
- typedef boost::signals2::signal<R(A)> SignalType;
+ typedef boost::signals2::signal<R(A), C> SignalType;
void connect_same_thread (ScopedConnectionList& clist,
const typename SignalType::slot_function_type& slot) {