X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Froute.cc;h=57793098d803151ffa291ef0aaa3a348ac53fe41;hb=58dbe9ed13cede08f9e11f428fa6c188325db009;hp=97a6e200ba40f5e148e0bfe9f14b33746a5b723c;hpb=153ee4e441eeebc9aceaa3121e4a785c6011a962;p=ardour.git diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 97a6e200ba..57793098d8 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -65,7 +65,6 @@ #include "ardour/session.h" #include "ardour/timestamps.h" #include "ardour/utils.h" -#include "ardour/graph.h" #include "ardour/unknown_processor.h" #include "ardour/capturing_processor.h" @@ -82,7 +81,7 @@ PBD::Signal0 Route::RemoteControlIDChange; Route::Route (Session& sess, string name, Flag flg, DataType default_type) : SessionObject (sess, name) , Automatable (sess) - , GraphNode( sess.route_graph ) + , GraphNode (sess._process_graph) , _active (true) , _signal_latency (0) , _initial_delay (0) @@ -104,6 +103,8 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type) , _default_type (default_type) , _remote_control_id (0) , _in_configure_processors (false) + , _custom_meter_position_noted (false) + , _last_custom_meter_was_at_end (false) { processor_max_streams.reset(); order_keys[N_("signal")] = order_key_cnt++; @@ -126,11 +127,7 @@ Route::init () /* panning */ if (!(_flags & Route::MonitorOut)) { - Pannable* p = new Pannable (_session); -#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS - boost_debug_shared_ptr_mark_interesting (p, "Pannable"); -#endif - _pannable.reset (p); + _pannable.reset (new Pannable (_session)); } /* input and output objects */ @@ -558,6 +555,7 @@ void Route::passthru_silence (framepos_t start_frame, framepos_t end_frame, pframes_t nframes, int declick) { BufferSet& bufs (_session.get_silent_buffers (n_process_buffers())); + bufs.set_count (_input->n_ports()); write_out_of_band_data (bufs, start_frame, end_frame, nframes); process_output_buffers (bufs, start_frame, end_frame, nframes, true, declick, false); @@ -748,7 +746,7 @@ Route::set_solo_isolated (bool yn, void *src) } bool sends_only; - bool does_feed = direct_feeds (*i, &sends_only); // we will recurse anyway, so don't use ::feeds() + bool does_feed = direct_feeds_according_to_graph (*i, &sends_only); // we will recurse anyway, so don't use ::feeds() if (does_feed && !sends_only) { (*i)->set_solo_isolated (yn, (*i)->route_group()); @@ -1627,34 +1625,11 @@ Route::configure_processors_unlocked (ProcessorStreams* err) return 0; } -void -Route::all_processors_flip () -{ - Glib::RWLock::ReaderLock lm (_processor_lock); - - if (_processors.empty()) { - return; - } - - bool first_is_on = _processors.front()->active(); - - for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - if (first_is_on) { - (*i)->deactivate (); - } else { - (*i)->activate (); - } - } - - _session.set_dirty (); -} - -/** Set all processors with a given placement to a given active state. - * @param p Placement of processors to change. - * @param state New active state for those processors. +/** Set all visible processors to a given active state (except Fader, whose state is not changed) + * @param state New active state for those processors. */ void -Route::all_processors_active (Placement p, bool state) +Route::all_visible_processors_active (bool state) { Glib::RWLock::ReaderLock lm (_processor_lock); @@ -1662,10 +1637,11 @@ Route::all_processors_active (Placement p, bool state) return; } - ProcessorList::iterator start, end; - placement_range(p, start, end); - - for (ProcessorList::iterator i = start; i != end; ++i) { + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + if (!(*i)->display_to_user() || boost::dynamic_pointer_cast (*i)) { + continue; + } + if (state) { (*i)->activate (); } else { @@ -1676,31 +1652,6 @@ Route::all_processors_active (Placement p, bool state) _session.set_dirty (); } -bool -Route::processor_is_prefader (boost::shared_ptr p) -{ - bool pre_fader = true; - Glib::RWLock::ReaderLock lm (_processor_lock); - - for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - - /* semantic note: if p == amp, we want to return true, so test - for equality before checking if this is the amp - */ - - if ((*i) == p) { - break; - } - - if ((*i) == _amp) { - pre_fader = false; - break; - } - } - - return pre_fader; -} - int Route::reorder_processors (const ProcessorList& new_order, ProcessorStreams* err) { @@ -1769,6 +1720,9 @@ Route::reorder_processors (const ProcessorList& new_order, ProcessorStreams* err _processors.insert (oiter, as_it_will_be.begin(), as_it_will_be.end()); + /* If the meter is in a custom position, find it and make a rough note of its position */ + maybe_note_meter_position (); + { Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ()); @@ -1874,24 +1828,28 @@ Route::state(bool full_state) node->add_child_nocopy((*i)->state (full_state)); } - if (_extra_xml){ + if (_extra_xml) { node->add_child_copy (*_extra_xml); } + if (_custom_meter_position_noted) { + boost::shared_ptr after = _processor_after_last_custom_meter.lock (); + if (after) { + after->id().print (buf, sizeof (buf)); + node->add_property (X_("processor-after-last-custom-meter"), buf); + } + + node->add_property (X_("last-custom-meter-was-at-end"), _last_custom_meter_was_at_end ? "yes" : "no"); + } + return *node; } int Route::set_state (const XMLNode& node, int version) -{ - return _set_state (node, version, true); -} - -int -Route::_set_state (const XMLNode& node, int version, bool /*call_base*/) { if (version < 3000) { - return _set_state_2X (node, version); + return set_state_2X (node, version); } XMLNodeList nlist; @@ -1965,6 +1923,14 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/) } } + if ((prop = node.property (X_("meter-point"))) != 0) { + MeterPoint mp = MeterPoint (string_2_enum (prop->value (), _meter_point)); + set_meter_point (mp, true); + if (_meter) { + _meter->set_display_to_user (_meter_point == MeterCustom); + } + } + set_processor_state (processor_state); if ((prop = node.property ("self-solo")) != 0) { @@ -2003,14 +1969,6 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/) set_active (yn, this); } - if ((prop = node.property (X_("meter-point"))) != 0) { - MeterPoint mp = MeterPoint (string_2_enum (prop->value (), _meter_point)); - set_meter_point (mp, true); - if (_meter) { - _meter->set_display_to_user (_meter_point == MeterCustom); - } - } - if ((prop = node.property (X_("order-keys"))) != 0) { int32_t n; @@ -2042,6 +2000,24 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/) } } + if ((prop = node.property (X_("processor-after-last-custom-meter"))) != 0) { + PBD::ID id (prop->value ()); + Glib::RWLock::ReaderLock lm (_processor_lock); + ProcessorList::const_iterator i = _processors.begin (); + while (i != _processors.end() && (*i)->id() != id) { + ++i; + } + + if (i != _processors.end ()) { + _processor_after_last_custom_meter = *i; + _custom_meter_position_noted = true; + } + } + + if ((prop = node.property (X_("last-custom-meter-was-at-end"))) != 0) { + _last_custom_meter_was_at_end = string_is_affirmative (prop->value ()); + } + for (niter = nlist.begin(); niter != nlist.end(); ++niter){ child = *niter; @@ -2073,7 +2049,7 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/) } int -Route::_set_state_2X (const XMLNode& node, int version) +Route::set_state_2X (const XMLNode& node, int version) { XMLNodeList nlist; XMLNodeConstIterator niter; @@ -2360,6 +2336,7 @@ Route::set_processor_state (const XMLNode& node) new_order.push_back (_amp); } else if (prop->value() == "meter") { _meter->set_state (**niter, Stateful::current_state_version); + new_order.push_back (_meter); } else if (prop->value() == "main-outs") { _main_outs->set_state (**niter, Stateful::current_state_version); } else if (prop->value() == "intreturn") { @@ -2401,7 +2378,7 @@ Route::set_processor_state (const XMLNode& node) } else if (prop->value() == "ladspa" || prop->value() == "Ladspa" || prop->value() == "lv2" || prop->value() == "vst" || - prop->value() == "lxvst" || + prop->value() == "lxvst" || prop->value() == "audiounit") { processor.reset (new PluginInsert(_session)); @@ -2694,14 +2671,14 @@ Route::feeds (boost::shared_ptr other, bool* via_sends_only) } bool -Route::direct_feeds (boost::shared_ptr other, bool* only_send) +Route::direct_feeds_according_to_reality (boost::shared_ptr other, bool* via_send_only) { DEBUG_TRACE (DEBUG::Graph, string_compose ("Feeds? %1\n", _name)); if (_output->connected_to (other->input())) { DEBUG_TRACE (DEBUG::Graph, string_compose ("\tdirect FEEDS %2\n", other->name())); - if (only_send) { - *only_send = false; + if (via_send_only) { + *via_send_only = false; } return true; @@ -2715,8 +2692,8 @@ Route::direct_feeds (boost::shared_ptr other, bool* only_send) if ((iop = boost::dynamic_pointer_cast(*r)) != 0) { if (iop->feeds (other)) { DEBUG_TRACE (DEBUG::Graph, string_compose ("\tIOP %1 does feed %2\n", iop->name(), other->name())); - if (only_send) { - *only_send = true; + if (via_send_only) { + *via_send_only = true; } return true; } else { @@ -2732,6 +2709,12 @@ Route::direct_feeds (boost::shared_ptr other, bool* only_send) return false; } +bool +Route::direct_feeds_according_to_graph (boost::shared_ptr other, bool* via_send_only) +{ + return _session._current_route_graph.has (shared_from_this (), other, via_send_only); +} + /** Called from the (non-realtime) butler thread when the transport is stopped */ void Route::nonrealtime_handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool can_flush_processors) @@ -2782,8 +2765,7 @@ Route::pans_required () const } int -Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, - bool session_state_changing, bool /*can_record*/) +Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool session_state_changing) { Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); if (!lm.locked()) { @@ -2820,8 +2802,7 @@ Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, } int -Route::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, - bool /*can_record*/, bool& /* need_butler */) +Route::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& /* need_butler */) { Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); if (!lm.locked()) { @@ -2853,8 +2834,7 @@ Route::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, in } int -Route::silent_roll (pframes_t nframes, framepos_t /*start_frame*/, framepos_t /*end_frame*/, - bool /*can_record*/, bool& /* need_butler */) +Route::silent_roll (pframes_t nframes, framepos_t /*start_frame*/, framepos_t /*end_frame*/, bool& /* need_butler */) { silence (nframes); return 0; @@ -2919,45 +2899,63 @@ Route::set_meter_point (MeterPoint p, bool force) return; } - _meter_point = p; - bool meter_was_visible_to_user = _meter->display_to_user (); { Glib::RWLock::WriterLock lm (_processor_lock); + maybe_note_meter_position (); + + _meter_point = p; + if (_meter_point != MeterCustom) { _meter->set_display_to_user (false); setup_invisible_processors (); - ProcessorList::iterator loc = find (_processors.begin(), _processors.end(), _meter); + } else { - ChanCount m_in; + _meter->set_display_to_user (true); - if (loc == _processors.begin()) { - m_in = _input->n_ports(); - } else { - ProcessorList::iterator before = loc; - --before; - m_in = (*before)->output_streams (); + /* If we have a previous position for the custom meter, try to put it there */ + if (_custom_meter_position_noted) { + boost::shared_ptr after = _processor_after_last_custom_meter.lock (); + + if (after) { + ProcessorList::iterator i = find (_processors.begin(), _processors.end(), after); + if (i != _processors.end ()) { + _processors.remove (_meter); + _processors.insert (i, _meter); + } + } else if (_last_custom_meter_was_at_end) { + _processors.remove (_meter); + _processors.push_back (_meter); + } } + } - _meter->reflect_inputs (m_in); - - /* we do not need to reconfigure the processors, because the meter - (a) is always ready to handle processor_max_streams - (b) is always an N-in/N-out processor, and thus moving - it doesn't require any changes to the other processors. - */ + /* Set up the meter for its new position */ + ProcessorList::iterator loc = find (_processors.begin(), _processors.end(), _meter); + + ChanCount m_in; + + if (loc == _processors.begin()) { + m_in = _input->n_ports(); } else { - - // just make it visible and let the user move it - - _meter->set_display_to_user (true); + ProcessorList::iterator before = loc; + --before; + m_in = (*before)->output_streams (); } + + _meter->reflect_inputs (m_in); + + /* we do not need to reconfigure the processors, because the meter + (a) is always ready to handle processor_max_streams + (b) is always an N-in/N-out processor, and thus moving + it doesn't require any changes to the other processors. + */ } meter_change (); /* EMIT SIGNAL */ @@ -3850,3 +3848,32 @@ Route::unpan () } } } + +/** If the meter point is `Custom', make a note of where the meter is. + * This is so that if the meter point is subsequently set to something else, + * and then back to custom, we can put the meter back where it was last time + * custom was enabled. + * + * Must be called with the _processor_lock held. + */ +void +Route::maybe_note_meter_position () +{ + if (_meter_point != MeterCustom) { + return; + } + + _custom_meter_position_noted = true; + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + if (boost::dynamic_pointer_cast (*i)) { + ProcessorList::iterator j = i; + ++j; + if (j != _processors.end ()) { + _processor_after_last_custom_meter = *j; + _last_custom_meter_was_at_end = false; + } else { + _last_custom_meter_was_at_end = true; + } + } + } +}