X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Froute.cc;h=4dcdcf1898a621d4a2018c08386e1565a4a82f24;hb=932d6c79d01be93f491415ef1491bca17d92671f;hp=287e3c219bd0cd97d77d5b836c931ae4c69aa826;hpb=823bad30497b67508ed4031232049ba2f9920941;p=ardour.git diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 287e3c219b..4dcdcf1898 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -58,6 +58,7 @@ #include "ardour/session.h" #include "ardour/timestamps.h" #include "ardour/utils.h" +#include "ardour/graph.h" #include "i18n.h" @@ -72,6 +73,7 @@ PBD::Signal0 Route::RemoteControlIDChange; Route::Route (Session& sess, string name, Flag flg, DataType default_type) : SessionObject (sess, name) , AutomatableControls (sess) + , GraphNode( sess.route_graph ) , _active (true) , _initial_delay (0) , _roll_delay (0) @@ -90,11 +92,7 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type) , _solo_control (new SoloControllable (X_("solo"), *this)) , _mute_control (new MuteControllable (X_("mute"), *this)) , _mute_master (new MuteMaster (sess, name)) - , _mute_points (MuteMaster::AllPoints) - , _path_muted_by_others (false) , _have_internal_generator (false) - , _physically_connected (false) - , _graph_level (-1) , _solo_safe (false) , _default_type (default_type) , _remote_control_id (0) @@ -125,7 +123,7 @@ Route::init () /* add amp processor */ - _amp.reset (new Amp (_session, _mute_master)); + _amp.reset (new Amp (_session)); add_processor (_amp, PostFader); /* add standard processors: meter, main outs, monitor out */ @@ -276,7 +274,7 @@ Route::ensure_track_or_route_name(string name, Session &session) string newname = name; while (!session.io_name_is_legal (newname)) { - newname = bump_name_once (newname); + newname = bump_name_once (newname, '.'); } return newname; @@ -452,25 +450,17 @@ Route::process_output_buffers (BufferSet& bufs, and go .... ----------------------------------------------------------------------------------------- */ - Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK); - - if (rm.locked()) { - //cerr << name() << " upstream solo " << _soloed_by_others_upstream - // << " downstream solo " << _soloed_by_others_downstream - // << " self " << _self_solo - //<< endl; - for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - - if (bufs.count() != (*i)->input_streams()) { - cerr << _name << " bufs = " << bufs.count() - << " input for " << (*i)->name() << " = " << (*i)->input_streams() - << endl; - } - assert (bufs.count() == (*i)->input_streams()); + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - (*i)->run (bufs, start_frame, end_frame, nframes, *i != _processors.back()); - bufs.set_count ((*i)->output_streams()); + if (bufs.count() != (*i)->input_streams()) { + cerr << _name << " bufs = " << bufs.count() + << " input for " << (*i)->name() << " = " << (*i)->input_streams() + << endl; } + assert (bufs.count() == (*i)->input_streams()); + + (*i)->run (bufs, start_frame, end_frame, nframes, *i != _processors.back()); + bufs.set_count ((*i)->output_streams()); } } @@ -490,7 +480,7 @@ Route::passthru (sframes_t start_frame, sframes_t end_frame, nframes_t nframes, assert (bufs.available() >= input_streams()); if (_input->n_ports() == ChanCount::ZERO) { - silence (nframes); + silence_unlocked (nframes); } bufs.set_count (input_streams()); @@ -540,8 +530,10 @@ Route::set_listen (bool yn, void* src) if (yn != _monitor_send->active()) { if (yn) { _monitor_send->activate (); - } else { + _mute_master->set_soloed (true); + } else { _monitor_send->deactivate (); + _mute_master->set_soloed (false); } listen_changed (src); /* EMIT SIGNAL */ @@ -607,6 +599,8 @@ Route::mod_solo_by_others_upstream (int32_t delta) return; } + uint32_t old_sbu = _soloed_by_others_upstream; + if (delta < 0) { if (_soloed_by_others_upstream >= (uint32_t) abs (delta)) { _soloed_by_others_upstream += delta; @@ -617,14 +611,36 @@ Route::mod_solo_by_others_upstream (int32_t delta) _soloed_by_others_upstream += delta; } + DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 SbU delta %2 = %3 old = %4 sbd %5 ss %6 exclusive %7\n", + name(), delta, _soloed_by_others_upstream, old_sbu, + _soloed_by_others_downstream, _self_solo, Config->get_exclusive_solo())); + /* push the inverse solo change to everything that feeds us. + + This is important for solo-within-group. When we solo 1 track out of N that + feed a bus, that track will cause mod_solo_by_upstream (+1) to be called + on the bus. The bus then needs to call mod_solo_by_downstream (-1) on all + tracks that feed it. This will silence them if they were audible because + of a bus solo, but the newly soloed track will still be audible (because + it is self-soloed). + + but .. do this only when we are being told to solo-by-upstream (i.e delta = +1), + not in reverse. */ - for (FedBy::iterator i = _fed_by.begin(); i != _fed_by.end(); ++i) { - boost::shared_ptr sr = i->r.lock(); - if (sr) { - sr->mod_solo_by_others_downstream (-delta); - } + if ((_self_solo || _soloed_by_others_downstream) && + ((old_sbu == 0 && _soloed_by_others_upstream > 0) || + (old_sbu > 0 && _soloed_by_others_upstream == 0))) { + + if (delta > 0 || !Config->get_exclusive_solo()) { + DEBUG_TRACE (DEBUG::Solo, "\t ... INVERT push\n"); + for (FedBy::iterator i = _fed_by.begin(); i != _fed_by.end(); ++i) { + boost::shared_ptr sr = i->r.lock(); + if (sr) { + sr->mod_solo_by_others_downstream (-delta); + } + } + } } set_mute_master_solo (); @@ -638,7 +654,7 @@ Route::mod_solo_by_others_downstream (int32_t delta) return; } - if (delta < 0) { + if (delta < 0) { if (_soloed_by_others_downstream >= (uint32_t) abs (delta)) { _soloed_by_others_downstream += delta; } else { @@ -648,6 +664,8 @@ Route::mod_solo_by_others_downstream (int32_t delta) _soloed_by_others_downstream += delta; } + DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 SbD delta %2 = %3\n", name(), delta, _soloed_by_others_downstream)); + set_mute_master_solo (); solo_changed (false, this); } @@ -655,19 +673,7 @@ Route::mod_solo_by_others_downstream (int32_t delta) void Route::set_mute_master_solo () { - SoloLevel level; - - if (self_soloed()) { - level = SelfSoloed; - } else if (soloed_by_others_upstream()) { - level = UpstreamSoloed; - } else if (soloed_by_others_downstream()) { - level = DownstreamSoloed; - } else { - level = NotSoloed; - } - - _mute_master->set_solo_level (level); + _mute_master->set_soloed (self_soloed() || soloed_by_others_downstream() || soloed_by_others_upstream()); } void @@ -701,22 +707,27 @@ Route::set_solo_isolated (bool yn, void *src) /* XXX should we back-propagate as well? (April 2010: myself and chris goddard think not) */ + bool changed = false; + if (yn) { if (_solo_isolated == 0) { _mute_master->set_solo_ignore (true); + changed = true; } _solo_isolated++; - solo_isolated_changed (src); } else { if (_solo_isolated > 0) { _solo_isolated--; if (_solo_isolated == 0) { _mute_master->set_solo_ignore (false); + changed = true; } - solo_isolated_changed (src); } } + if (changed) { + solo_isolated_changed (src); + } } bool @@ -728,11 +739,10 @@ Route::solo_isolated () const void Route::set_mute_points (MuteMaster::MutePoint mp) { - _mute_points = mp; - _mute_master->set_mute_points (MuteMaster::AllPoints); + _mute_master->set_mute_points (mp); mute_points_changed (); /* EMIT SIGNAL */ - if (_mute_master->muted()) { + if (_mute_master->muted_by_self()) { mute_changed (this); /* EMIT SIGNAL */ } } @@ -745,8 +755,8 @@ Route::set_mute (bool yn, void *src) return; } - if (self_muted() != yn) { - _mute_master->set_self_muted (yn); + if (muted() != yn) { + _mute_master->set_muted_by_self (yn); mute_changed (src); /* EMIT SIGNAL */ } } @@ -754,47 +764,7 @@ Route::set_mute (bool yn, void *src) bool Route::muted () const { - return self_muted() || muted_by_others(); -} - -bool -Route::self_muted() const -{ - return _mute_master->self_muted (); -} - -bool -Route::muted_by_others() const -{ - return _mute_master->muted_by_others (); -} - -void -Route::mod_muted_by_others (int delta) -{ - if (_solo_isolated) { - return; - } - - bool old = muted (); - _mute_master->mod_muted_by_others (delta); - if (old != muted()) { - mute_changed (this); - } -} - -void -Route::mod_path_muted_by_others (int32_t delta) -{ - if (delta < 0) { - if (_path_muted_by_others >= (uint32_t) abs (delta)) { - _path_muted_by_others += delta; - } else { - _path_muted_by_others = 0; - } - } else { - _path_muted_by_others += delta; - } + return _mute_master->muted_by_self(); } #if 0 @@ -913,6 +883,7 @@ Route::add_processor (boost::shared_ptr processor, ProcessorList::ite } processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */ + set_processor_positions (); return 0; } @@ -1057,6 +1028,7 @@ Route::add_processors (const ProcessorList& others, ProcessorList::iterator iter } processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */ + set_processor_positions (); return 0; } @@ -1257,6 +1229,7 @@ Route::clear_processors (Placement p) processor_max_streams.reset(); _have_internal_generator = false; processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */ + set_processor_positions (); if (!already_deleting) { _session.clear_deletion_in_progress(); @@ -1348,6 +1321,7 @@ Route::remove_processor (boost::shared_ptr processor, ProcessorStream processor->drop_references (); processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */ + set_processor_positions (); return 0; } @@ -1439,6 +1413,7 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams* } processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */ + set_processor_positions (); return 0; } @@ -1479,18 +1454,16 @@ Route::configure_processors_unlocked (ProcessorStreams* err) uint32_t index = 0; DEBUG_TRACE (DEBUG::Processors, string_compose ("%1: configure processors\n", _name)); -#ifndef NDEBUG DEBUG_TRACE (DEBUG::Processors, "{\n"); for (list >::const_iterator p = _processors.begin(); p != _processors.end(); ++p) { DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1 ID = %2\n", (*p)->name(), (*p)->id())); } DEBUG_TRACE (DEBUG::Processors, "}\n"); -#endif for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++index) { if ((*p)->can_support_io_configuration(in, out)) { - DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1in = %2 out = %3\n",(*p)->name(), in, out)); + DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1 in = %2 out = %3\n",(*p)->name(), in, out)); configuration.push_back(make_pair(in, out)); in = out; } else { @@ -1523,6 +1496,8 @@ Route::configure_processors_unlocked (ProcessorStreams* err) _session.ensure_buffers (n_process_buffers ()); } + DEBUG_TRACE (DEBUG::Processors, string_compose ("%1: configuration complete\n", _name)); + _in_configure_processors = false; return 0; } @@ -1684,6 +1659,7 @@ Route::reorder_processors (const ProcessorList& new_order, ProcessorStreams* err if (true) { processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */ + set_processor_positions (); } return 0; @@ -2331,6 +2307,7 @@ Route::set_processor_state (const XMLNode& node) } processors_changed (RouteProcessorChange ()); + set_processor_positions (); } void @@ -2343,31 +2320,37 @@ Route::curve_reallocate () void Route::silence (nframes_t nframes) { - if (!_silent) { - - _output->silence (nframes); - - { - Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + if (!lm.locked()) { + return; + } - if (lm.locked()) { - for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - boost::shared_ptr pi; + silence_unlocked (nframes); +} - if (!_active && (pi = boost::dynamic_pointer_cast (*i)) != 0) { - // skip plugins, they don't need anything when we're not active - continue; - } +void +Route::silence_unlocked (nframes_t nframes) +{ + /* Must be called with the processor lock held */ + + if (!_silent) { - (*i)->silence (nframes); - } + _output->silence (nframes); - if (nframes == _session.get_block_size()) { - // _silent = true; - } + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + boost::shared_ptr pi; + + if (!_active && (pi = boost::dynamic_pointer_cast (*i)) != 0) { + // skip plugins, they don't need anything when we're not active + continue; } + + (*i)->silence (nframes); + } + + if (nframes == _session.get_block_size()) { + // _silent = true; } - } } @@ -2604,12 +2587,6 @@ Route::direct_feeds (boost::shared_ptr other, bool* only_send) return false; } -void -Route::check_physical_connections () -{ - _physically_connected = _output->physically_connected (); -} - void Route::handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool can_flush_processors) { @@ -2669,12 +2646,17 @@ int Route::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, bool session_state_changing, bool /*can_record*/, bool /*rec_monitors_input*/) { + Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + if (!lm.locked()) { + return 0; + } + if (n_outputs().n_total() == 0) { return 0; } if (!_active || n_inputs() == ChanCount::ZERO) { - silence (nframes); + silence_unlocked (nframes); return 0; } if (session_state_changing) { @@ -2684,7 +2666,7 @@ Route::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, XXX note the absurdity of ::no_roll() being called when we ARE rolling! */ - silence (nframes); + silence_unlocked (nframes); return 0; } /* we're really not rolling, so we're either delivery silence or actually @@ -2704,14 +2686,14 @@ Route::check_initial_delay (nframes_t nframes, nframes_t& transport_frame) if (_roll_delay > nframes) { _roll_delay -= nframes; - silence (nframes); + silence_unlocked (nframes); /* transport frame is not legal for caller to use */ return 0; } else if (_roll_delay > 0) { nframes -= _roll_delay; - silence (_roll_delay); + silence_unlocked (_roll_delay); /* we've written _roll_delay of samples into the output ports, so make a note of that for future reference. @@ -2729,22 +2711,19 @@ int Route::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int declick, bool /*can_record*/, bool /*rec_monitors_input*/, bool& /* need_butler */) { - { - // automation snapshot can also be called from the non-rt context - // and it uses the processor list, so we try to acquire the lock here - Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); - - if (lm.locked()) { - automation_snapshot (_session.transport_frame(), false); - } + Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + if (!lm.locked()) { + return 0; } + + automation_snapshot (_session.transport_frame(), false); if (n_outputs().n_total() == 0) { return 0; } if (!_active || n_inputs().n_total() == 0) { - silence (nframes); + silence_unlocked (nframes); return 0; } @@ -3069,7 +3048,7 @@ Route::MuteControllable::set_value (float val) float Route::MuteControllable::get_value (void) const { - return route.self_muted() ? 1.0f : 0.0f; + return route.muted() ? 1.0f : 0.0f; } void @@ -3381,8 +3360,22 @@ Route::has_io_processor_named (const string& name) return false; } +MuteMaster::MutePoint +Route::mute_points () const +{ + return _mute_master->mute_points (); +} + void -Route::set_graph_level (int32_t l) +Route::set_processor_positions () { - _graph_level = l; + Glib::RWLock::ReaderLock lm (_processor_lock); + + bool had_amp = false; + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + (*i)->set_pre_fader (!had_amp); + if (boost::dynamic_pointer_cast (*i)) { + had_amp = true; + } + } }