diff options
author | Carl Hetherington <carl@carlh.net> | 2010-11-25 23:46:24 +0000 |
---|---|---|
committer | Carl Hetherington <carl@carlh.net> | 2010-11-25 23:46:24 +0000 |
commit | 54cbc45a5a40f4eefd64fa41ad9029f5f8f6a84f (patch) | |
tree | 558e7cb27683030787fcb4d5654bd4b58ebd8e21 /libs | |
parent | 28c004f4fb0750b6a4236552bcc8de4946b9b164 (diff) |
Prevent removal of route inputs when the plugins cannot be configured with the new number. Rework locking so that the process lock is held from the point that a route input is removed until after the processors are reconfigured; fixes #3548.
git-svn-id: svn://localhost/ardour2/branches/3.0@8089 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r-- | libs/ardour/ardour/io.h | 26 | ||||
-rw-r--r-- | libs/ardour/ardour/route.h | 6 | ||||
-rw-r--r-- | libs/ardour/auditioner.cc | 14 | ||||
-rw-r--r-- | libs/ardour/delivery.cc | 4 | ||||
-rw-r--r-- | libs/ardour/io.cc | 124 | ||||
-rw-r--r-- | libs/ardour/port_insert.cc | 17 | ||||
-rw-r--r-- | libs/ardour/route.cc | 173 | ||||
-rw-r--r-- | libs/ardour/send.cc | 2 | ||||
-rw-r--r-- | libs/ardour/session.cc | 89 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 15 | ||||
-rw-r--r-- | libs/pbd/pbd/signals.h | 4 |
11 files changed, 319 insertions, 155 deletions
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) { |