diff options
author | Carl Hetherington <carl@carlh.net> | 2010-08-30 22:34:21 +0000 |
---|---|---|
committer | Carl Hetherington <carl@carlh.net> | 2010-08-30 22:34:21 +0000 |
commit | b9dca83832afe48f8f3f94e702c571a3f57aef7a (patch) | |
tree | d692480ec94c80b581527e1de6adb9708e75369d | |
parent | e528e5038fa791b07bc9f00f64a39227d66f49b3 (diff) |
Auto-connect outputs that appear as a result of e.g. instruments being added to MIDI tracks. Fixes #3368.
git-svn-id: svn://localhost/ardour2/branches/3.0@7720 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | gtk2_ardour/latency_gui.cc | 1 | ||||
-rw-r--r-- | gtk2_ardour/return_ui.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/send_ui.cc | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 9 | ||||
-rw-r--r-- | libs/ardour/ardour/types.h | 20 | ||||
-rw-r--r-- | libs/ardour/audio_diskstream.cc | 4 | ||||
-rw-r--r-- | libs/ardour/auditioner.cc | 2 | ||||
-rw-r--r-- | libs/ardour/delivery.cc | 2 | ||||
-rw-r--r-- | libs/ardour/diskstream.cc | 8 | ||||
-rw-r--r-- | libs/ardour/enums.cc | 5 | ||||
-rw-r--r-- | libs/ardour/io.cc | 40 | ||||
-rw-r--r-- | libs/ardour/midi_diskstream.cc | 6 | ||||
-rw-r--r-- | libs/ardour/route.cc | 27 | ||||
-rw-r--r-- | libs/ardour/session.cc | 31 |
14 files changed, 110 insertions, 51 deletions
diff --git a/gtk2_ardour/latency_gui.cc b/gtk2_ardour/latency_gui.cc index 849edae767..e4b1cbabb1 100644 --- a/gtk2_ardour/latency_gui.cc +++ b/gtk2_ardour/latency_gui.cc @@ -3,6 +3,7 @@ #include <iomanip> #include "ardour/latent.h" +#include "pbd/convert.h" #include <gtkmm2ext/utils.h> #include "latency_gui.h" diff --git a/gtk2_ardour/return_ui.cc b/gtk2_ardour/return_ui.cc index 61fe2291a5..6e131c3b58 100644 --- a/gtk2_ardour/return_ui.cc +++ b/gtk2_ardour/return_ui.cc @@ -82,7 +82,7 @@ void ReturnUI::ins_changed (IOChange change, void* ignored) { ENSURE_GUI_THREAD (*this, &ReturnUI::ins_changed, change, ignored) - if (change & ConfigurationChanged) { + if (change.type & IOChange::ConfigurationChanged) { _gpm.setup_meters (); } } diff --git a/gtk2_ardour/send_ui.cc b/gtk2_ardour/send_ui.cc index 3cc17faaea..9638897f3b 100644 --- a/gtk2_ardour/send_ui.cc +++ b/gtk2_ardour/send_ui.cc @@ -92,7 +92,7 @@ void SendUI::ins_changed (IOChange change, void* ignored) { ENSURE_GUI_THREAD (*this, &SendUI::ins_changed, change, ignored) - if (change & ConfigurationChanged) { + if (change.type & IOChange::ConfigurationChanged) { _panners.setup_pan (); } } @@ -101,7 +101,7 @@ void SendUI::outs_changed (IOChange change, void* ignored) { ENSURE_GUI_THREAD (*this, &SendUI::outs_changed, change, ignored) - if (change & ConfigurationChanged) { + if (change.type & IOChange::ConfigurationChanged) { _panners.setup_pan (); _gpm.setup_meters (); } diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 88f62aa9b3..7834c644e6 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1190,7 +1190,14 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi bool find_route_name (const char* base, uint32_t& id, char* name, size_t name_len); void count_existing_route_channels (ChanCount& in, ChanCount& out); - void auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing_inputs, ChanCount& existing_outputs, bool connect_inputs = true); + void auto_connect_route ( + Route* route, + ChanCount& existing_inputs, + ChanCount& existing_outputs, + bool connect_inputs = true, + ChanCount input_start = ChanCount (), + ChanCount output_start = ChanCount () + ); /* mixer stuff */ diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index c666545dfa..435cf8d416 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -36,6 +36,7 @@ #include "pbd/id.h" #include "ardour/bbt_time.h" +#include "ardour/chan_count.h" #include <map> @@ -70,10 +71,21 @@ namespace ARDOUR { /* any count of audio frames */ typedef int64_t framecnt_t; - enum IOChange { - NoChange = 0, - ConfigurationChanged = 0x1, - ConnectionsChanged = 0x2 + struct IOChange { + + enum Type { + NoChange = 0, + ConfigurationChanged = 0x1, + ConnectionsChanged = 0x2 + } type; + + IOChange () : type (NoChange) {} + IOChange (Type t) : type (t) {} + + /** channel count of IO before a ConfigurationChanged, if appropriate */ + ARDOUR::ChanCount before; + /** channel count of IO after a ConfigurationChanged, if appropriate */ + ARDOUR::ChanCount after; }; enum OverlapType { diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index f59997a933..f4e7ac8e9c 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -165,7 +165,7 @@ AudioDiskstream::non_realtime_input_change () { Glib::Mutex::Lock lm (state_lock); - if (input_change_pending == NoChange) { + if (input_change_pending.type == IOChange::NoChange) { return; } @@ -192,7 +192,7 @@ AudioDiskstream::non_realtime_input_change () set_align_style_from_io (); } - input_change_pending = NoChange; + input_change_pending = IOChange::NoChange; /* implicit unlock */ } diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc index 868c8d4334..baf97292ec 100644 --- a/libs/ardour/auditioner.cc +++ b/libs/ardour/auditioner.cc @@ -235,7 +235,7 @@ Auditioner::play_audition (nframes_t nframes) void Auditioner::output_changed (IOChange change, void* /*src*/) { - if (change & ConnectionsChanged) { + if (change.type & IOChange::ConnectionsChanged) { string phys; vector<string> connections; vector<string> outputs; diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc index 50a87eb000..77e3104bd6 100644 --- a/libs/ardour/delivery.cc +++ b/libs/ardour/delivery.cc @@ -537,7 +537,7 @@ Delivery::set_name (const std::string& name) void Delivery::output_changed (IOChange change, void* /*src*/) { - if (change & ARDOUR::ConfigurationChanged) { + if (change.type & IOChange::ConfigurationChanged) { reset_panner (); } } diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index aaeb3c9270..0a79aec613 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -98,7 +98,6 @@ Diskstream::Diskstream (Session &sess, const string &name, Flag flag) , overwrite_offset (0) , _pending_overwrite (false) , overwrite_queued (false) - , input_change_pending (NoChange) , wrap_buffer_size (0) , speed_buffer_size (0) , _speed (1.0) @@ -146,7 +145,6 @@ Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/) , overwrite_offset (0) , _pending_overwrite (false) , overwrite_queued (false) - , input_change_pending (NoChange) , wrap_buffer_size (0) , speed_buffer_size (0) , _speed (1.0) @@ -184,7 +182,7 @@ Diskstream::set_track (Track* t) ic_connection.disconnect(); _io->changed.connect_same_thread (ic_connection, boost::bind (&Diskstream::handle_input_change, this, _1, _2)); - input_change_pending = ConfigurationChanged; + input_change_pending = IOChange::ConfigurationChanged; non_realtime_input_change (); set_align_style_from_io (); @@ -196,8 +194,8 @@ Diskstream::handle_input_change (IOChange change, void * /*src*/) { Glib::Mutex::Lock lm (state_lock); - if (!(input_change_pending & change)) { - input_change_pending = IOChange (input_change_pending|change); + if (!(input_change_pending.type & change.type)) { + input_change_pending.type = IOChange::Type (input_change_pending.type | change.type); _session.request_input_change_handling (); } } diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc index 2d29a59e8b..972ff2efb7 100644 --- a/libs/ardour/enums.cc +++ b/libs/ardour/enums.cc @@ -125,11 +125,6 @@ setup_enum_writer () #define REGISTER_ENUM(e) i.push_back (e); s.push_back (#e) #define REGISTER_CLASS_ENUM(t,e) i.push_back (t::e); s.push_back (#e) - REGISTER_ENUM (NoChange); - REGISTER_ENUM (ConfigurationChanged); - REGISTER_ENUM (ConnectionsChanged); - REGISTER_BITS (_IOChange); - REGISTER_ENUM (OverlapNone); REGISTER_ENUM (OverlapInternal); REGISTER_ENUM (OverlapStart); diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 338705d633..d6b5b1e7db 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -186,7 +186,7 @@ IO::disconnect (Port* our_port, string other_port, void* src) } } - changed (ConnectionsChanged, src); /* EMIT SIGNAL */ + changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ _session.set_dirty (); return 0; @@ -219,7 +219,7 @@ IO::connect (Port* our_port, string other_port, void* src) } } - changed (ConnectionsChanged, src); /* EMIT SIGNAL */ + changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ _session.set_dirty (); return 0; } @@ -227,20 +227,23 @@ IO::connect (Port* our_port, string other_port, void* src) int IO::remove_port (Port* port, void* src) { - IOChange change (NoChange); + IOChange change; { BLOCK_PROCESS_CALLBACK (); - { Glib::Mutex::Lock lm (io_lock); + ChanCount before = _ports.count (); + if (_ports.remove(port)) { - change = IOChange (change|ConfigurationChanged); + change.type = IOChange::Type (change.type | IOChange::ConfigurationChanged); + change.before = before; + change.after = _ports.count (); if (port->connected()) { - change = IOChange (change|ConnectionsChanged); + change.type = IOChange::Type (change.type | IOChange::ConnectionsChanged); } _session.engine().unregister_port (*port); @@ -251,11 +254,11 @@ IO::remove_port (Port* port, void* src) PortCountChanged (n_ports()); /* EMIT SIGNAL */ } - if (change & ConfigurationChanged) { + if (change.type & IOChange::ConfigurationChanged) { setup_bundle (); } - if (change != NoChange) { + if (change.type != IOChange::NoChange) { changed (change, src); _session.set_dirty (); return 0; @@ -279,6 +282,8 @@ IO::add_port (string destination, void* src, DataType type) type = _default_type; } + IOChange change; + { BLOCK_PROCESS_CALLBACK (); @@ -302,6 +307,7 @@ IO::add_port (string destination, void* src, DataType type) } } + change.before = _ports.count (); _ports.add (our_port); } @@ -315,7 +321,9 @@ IO::add_port (string destination, void* src, DataType type) } // pan_changed (src); /* EMIT SIGNAL */ - changed (ConfigurationChanged, src); /* EMIT SIGNAL */ + change.type = IOChange::ConfigurationChanged; + change.after = _ports.count (); + changed (change, src); /* EMIT SIGNAL */ setup_bundle (); _session.set_dirty (); @@ -339,7 +347,7 @@ IO::disconnect (void* src) } } - changed (ConnectionsChanged, src); /* EMIT SIGNAL */ + changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ return 0; } @@ -421,6 +429,10 @@ IO::ensure_ports (ChanCount count, bool clear, bool lockit, void* src) return 0; } + IOChange change; + + change.before = _ports.count (); + if (lockit) { BLOCK_PROCESS_CALLBACK (); Glib::Mutex::Lock im (io_lock); @@ -430,7 +442,9 @@ IO::ensure_ports (ChanCount count, bool clear, bool lockit, void* src) } if (changed) { - this->changed (ConfigurationChanged, src); /* EMIT SIGNAL */ + change.after = _ports.count (); + change.type = IOChange::ConfigurationChanged; + this->changed (change, src); /* EMIT SIGNAL */ setup_bundle (); _session.set_dirty (); } @@ -1170,7 +1184,7 @@ IO::connect_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src) } } - changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */ + changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ return 0; } @@ -1200,7 +1214,7 @@ IO::disconnect_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src) } } - changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */ + changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ return 0; } diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index bfd57573df..8b7d4a3d4a 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -158,11 +158,11 @@ MidiDiskstream::non_realtime_input_change () { Glib::Mutex::Lock lm (state_lock); - if (input_change_pending == NoChange) { + if (input_change_pending.type == IOChange::NoChange) { return; } - if (input_change_pending & ConfigurationChanged) { + if (input_change_pending.type & IOChange::ConfigurationChanged) { if (_io->n_ports().n_midi() != _n_channels.n_midi()) { error << "Can not feed IO " << _io->n_ports() << " with diskstream " << _n_channels << endl; @@ -179,7 +179,7 @@ MidiDiskstream::non_realtime_input_change () set_align_style_from_io (); } - input_change_pending = NoChange; + input_change_pending.type = IOChange::NoChange; /* implicit unlock */ } diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 4541783cf1..35c456622c 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -2654,7 +2654,7 @@ Route::handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool c void Route::input_change_handler (IOChange change, void * /*src*/) { - if ((change & ConfigurationChanged)) { + if ((change.type & IOChange::ConfigurationChanged)) { configure_processors (0); _phase_invert.resize (_input->n_ports().n_audio ()); io_changed (); /* EMIT SIGNAL */ @@ -2664,10 +2664,33 @@ Route::input_change_handler (IOChange change, void * /*src*/) void Route::output_change_handler (IOChange change, void * /*src*/) { - if ((change & ConfigurationChanged)) { + if ((change.type & IOChange::ConfigurationChanged)) { /* XXX resize all listeners to match _main_outs? */ + /* auto-connect newly-created outputs */ + if (Config->get_output_auto_connect()) { + + ChanCount start = change.before; + + for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) { + if (change.before.get(*i) < change.after.get(*i)) { + /* the existing ChanCounts don't matter for this call as they are only + to do with matching input and output indices, and we are only changing + outputs here. + */ + ChanCount dummy; + + /* only auto-connect the newly-created outputs, not the ones that were + already there + */ + start.set (*i, start.get (*i) + 1); + + _session.auto_connect_route (this, dummy, dummy, false, ChanCount(), change.before); + } + } + } + // configure_processors (0); } } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index a4519e14b6..0394b23944 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1470,6 +1470,7 @@ Session::find_route_name (const char* base, uint32_t& id, char* name, size_t nam return false; } +/** Count the total ins and outs of all non-hidden routes in the session and return them in in and out */ void Session::count_existing_route_channels (ChanCount& in, ChanCount& out) { @@ -1478,8 +1479,8 @@ Session::count_existing_route_channels (ChanCount& in, ChanCount& out) shared_ptr<RouteList> r = routes.reader (); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { if (!(*i)->is_hidden()) { - in += (*i)->n_inputs(); - out += (*i)->n_outputs(); + in += (*i)->n_inputs(); + out += (*i)->n_outputs(); } } } @@ -1532,7 +1533,7 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m goto failed; } - auto_connect_route (track, existing_inputs, existing_outputs); + auto_connect_route (track.get(), existing_inputs, existing_outputs); track->non_realtime_input_change(); @@ -1570,9 +1571,14 @@ 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 */ +/** @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. + */ void -Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing_inputs, ChanCount& existing_outputs, bool connect_inputs) +Session::auto_connect_route ( + Route* route, ChanCount& existing_inputs, ChanCount& existing_outputs, bool connect_inputs, ChanCount input_start, ChanCount output_start + ) { /* If both inputs and outputs are auto-connected to physical ports, use the max of input and output offsets to ensure auto-connected @@ -1604,7 +1610,7 @@ Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing if (!physinputs.empty() && connect_inputs) { uint32_t nphysical_in = physinputs.size(); - for (uint32_t i = 0; i < route->n_inputs().get(*t) && i < nphysical_in; ++i) { + for (uint32_t i = input_start.get(*t); i < route->n_inputs().get(*t) && i < nphysical_in; ++i) { string port; if (Config->get_input_auto_connect() & AutoConnectPhysical) { @@ -1620,7 +1626,7 @@ Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing if (!physoutputs.empty()) { uint32_t nphysical_out = physoutputs.size(); - for (uint32_t i = 0; i < route->n_outputs().get(*t); ++i) { + for (uint32_t i = output_start.get(*t); i < route->n_outputs().get(*t); ++i) { string port; if (Config->get_output_auto_connect() & AutoConnectPhysical) { @@ -1697,7 +1703,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod goto failed; } - auto_connect_route (track, existing_inputs, existing_outputs); + auto_connect_route (track.get(), existing_inputs, existing_outputs); if (route_group) { route_group->add (track); @@ -1810,7 +1816,7 @@ Session::new_audio_route (bool aux, int input_channels, int output_channels, Rou goto failure; } - auto_connect_route (bus, existing_inputs, existing_outputs, false); + auto_connect_route (bus.get(), existing_inputs, existing_outputs, false); if (route_group) { route_group->add (bus); @@ -1901,8 +1907,11 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template picks up the configuration of the route. During session loading this normally happens in a different way. */ - route->input()->changed (IOChange (ConfigurationChanged|ConnectionsChanged), this); - route->output()->changed (IOChange (ConfigurationChanged|ConnectionsChanged), this); + IOChange change (IOChange::Type (IOChange::ConfigurationChanged | IOChange::ConnectionsChanged)); + change.after = route->input()->n_ports(); + route->input()->changed (change, this); + change.after = route->output()->n_ports(); + route->output()->changed (change, this); } route->set_remote_control_id (control_id); |