X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Froute.cc;h=8b60d68632eade3ef4eccb66678ce1b1960096db;hb=fb01698450e5cb88c7e58fb3a5ebe6294731fdfe;hp=b5311dc4fca72dd82d8b8401fbb1b5cc2f8be66f;hpb=0c041dc372ce5e1629da6ff158750945966888be;p=ardour.git diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index b5311dc4fc..8b60d68632 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -57,6 +57,7 @@ #include "ardour/delayline.h" #include "ardour/midi_buffer.h" #include "ardour/midi_port.h" +#include "ardour/midi_track.h" #include "ardour/monitor_control.h" #include "ardour/monitor_processor.h" #include "ardour/pannable.h" @@ -99,13 +100,11 @@ Route::Route (Session& sess, string name, PresentationInfo::Flag flag, DataType , _disk_io_point (DiskIOPreFader) , _pending_process_reorder (0) , _pending_signals (0) - , _pending_declick (true) , _meter_point (MeterPostFader) , _pending_meter_point (MeterPostFader) , _meter_type (MeterPeak) , _denormal_protection (false) , _recordable (true) - , _declickable (false) , _have_internal_generator (false) , _default_type (default_type) , _loop_location (NULL) @@ -273,14 +272,14 @@ Route::~Route () } string -Route::ensure_track_or_route_name(string name, Session &session) +Route::ensure_track_or_route_name (string newname) const { - string newname = name; - - while (!session.io_name_is_legal (newname)) { + while (!_session.io_name_is_legal (newname)) { newname = bump_name_once (newname, ' '); + if (newname == name()) { + break; + } } - return newname; } @@ -291,14 +290,6 @@ Route::set_trim (gain_t val, Controllable::GroupControlDisposition /* group over // _trim_control->route_set_value (val); } -void -Route::maybe_declick (BufferSet&, samplecnt_t, int) -{ - /* this is the "bus" implementation and they never declick. - */ - return; -} - /** Process this route for one (sub) cycle (process thread) * * @param bufs Scratch buffers to use for the signal path @@ -312,7 +303,7 @@ Route::maybe_declick (BufferSet&, samplecnt_t, int) void Route::process_output_buffers (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, - int declick, bool gain_automation_ok, bool run_disk_reader) + bool gain_automation_ok, bool run_disk_reader) { /* Caller must hold process lock */ assert (!AudioEngine::instance()->process_lock().trylock()); @@ -335,6 +326,10 @@ Route::process_output_buffers (BufferSet& bufs, */ automation_run (start_sample, nframes); + if (_pannable) { + _pannable->automation_run (start_sample + _signal_latency, nframes); + } + /* figure out if we're going to use gain automation */ if (gain_automation_ok) { _amp->set_gain_automation_buffer (_session.gain_automation_buffer ()); @@ -417,15 +412,6 @@ Route::process_output_buffers (BufferSet& bufs, _main_outs->no_outs_cuz_we_no_monitor (silence); - /* ------------------------------------------------------------------------------------------- - GLOBAL DECLICK (for transport changes etc.) - ----------------------------------------------------------------------------------------- */ - - // XXX not latency compensated. calls Amp::declick, but there may be - // plugins between disk and Fader. - maybe_declick (bufs, nframes, declick); - _pending_declick = 0; - /* ------------------------------------------------------------------------------------------- DENORMAL CONTROL ----------------------------------------------------------------------------------------- */ @@ -474,27 +460,6 @@ Route::process_output_buffers (BufferSet& bufs, } #endif - if (boost::dynamic_pointer_cast(*i) != 0) { - /* set potential sidechain ports, capture and playback latency. - * This effectively sets jack port latency which should include - * up/downstream latencies. - * - * However, the value is not used by Ardour (2017-09-20) and calling - * IO::latency() is expensive, so we punt. - * - * capture should be - * input()->latenct + latency, - * playback should be - * output->latency() + _signal_latency - latency - * - * Also see note below, _signal_latency may be smaller than latency - * if a plugin's latency increases while it's running. - */ - const samplecnt_t playback_latency = std::max ((samplecnt_t)0, _signal_latency - latency); - boost::dynamic_pointer_cast(*i)->set_sidechain_latency ( - /* input->latency() + */ latency, /* output->latency() + */ playback_latency); - } - bool re_inject_oob_data = false; if ((*i) == _disk_reader) { /* Well now, we've made it past the disk-writer and to the disk-reader. @@ -543,7 +508,7 @@ Route::process_output_buffers (BufferSet& bufs, #if 0 if ((*i) == _delayline) { - latency += _delayline->get_delay (); + latency += _delayline->delay (); } #endif } @@ -674,15 +639,15 @@ Route::n_process_buffers () } void -Route::monitor_run (samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick) +Route::monitor_run (samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes) { assert (is_monitor()); Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK); - run_route (start_sample, end_sample, nframes, declick, true, false); + run_route (start_sample, end_sample, nframes, true, false); } void -Route::run_route (samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick, bool gain_automation_ok, bool run_disk_reader) +Route::run_route (samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, bool gain_automation_ok, bool run_disk_reader) { BufferSet& bufs (_session.get_route_buffers (n_process_buffers())); @@ -708,7 +673,7 @@ Route::run_route (samplepos_t start_sample, samplepos_t end_sample, pframes_t nf /* run processor chain */ - process_output_buffers (bufs, start_sample, end_sample, nframes, declick, gain_automation_ok, run_disk_reader); + process_output_buffers (bufs, start_sample, end_sample, nframes, gain_automation_ok, run_disk_reader); /* map events (e.g. MIDI-CC) back to control-parameters */ update_controls (bufs); @@ -3111,6 +3076,9 @@ Route::silence_unlocked (samplecnt_t nframes) // update owned automated controllables automation_run (now, nframes); + if (_pannable) { + _pannable->automation_run (now, nframes); + } for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { boost::shared_ptr pi; @@ -3444,6 +3412,18 @@ Route::non_realtime_transport_stop (samplepos_t now, bool flush) } } +void +Route::realtime_handle_transport_stopped () +{ + Glib::Threads::RWLock::ReaderLock lm (_processor_lock); + + /* currently only by Plugin, queue note-off events */ + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + (*i)->realtime_handle_transport_stopped (); + } +} + + void Route::input_change_handler (IOChange change, void * /*src*/) { @@ -3683,7 +3663,7 @@ Route::latency_preroll (pframes_t nframes, samplepos_t& start_sample, samplepos_ } int -Route::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler) +Route::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool& need_butler) { Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK); @@ -3701,7 +3681,7 @@ Route::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample return 0; } - run_route (start_sample, end_sample, nframes, declick, (!_disk_writer || !_disk_writer->record_enabled()) && _session.transport_rolling(), true); + run_route (start_sample, end_sample, nframes, (!_disk_writer || !_disk_writer->record_enabled()) && _session.transport_rolling(), true); if ((_disk_reader && _disk_reader->need_butler()) || (_disk_writer && _disk_writer->need_butler())) { need_butler = true; @@ -3748,7 +3728,7 @@ Route::no_roll_unlocked (pframes_t nframes, samplepos_t start_sample, samplepos_ */ } - run_route (start_sample, end_sample, nframes, 0, false, false); + run_route (start_sample, end_sample, nframes, false, false); return 0; } @@ -3989,6 +3969,9 @@ Route::update_signal_latency (bool apply_to_delayline) // here or in Session::* ? -> also zero send latencies, // and make sure that re-enabling a route updates things again... + samplecnt_t capt_lat_in = _input->connected_latency (false); + samplecnt_t play_lat_out = _output->connected_latency (true); + Glib::Threads::RWLock::ReaderLock lm (_processor_lock); samplecnt_t l_in = 0; @@ -3997,6 +3980,14 @@ Route::update_signal_latency (bool apply_to_delayline) if (boost::shared_ptr snd = boost::dynamic_pointer_cast (*i)) { snd->set_delay_in (l_out + _output->latency()); } + + if (boost::shared_ptr pi = boost::dynamic_pointer_cast (*i)) { + if (boost::shared_ptr pio = pi->sidechain_input ()) { + samplecnt_t lat = l_out + _output->latency(); + pio->set_private_port_latencies (lat, true); + pio->set_public_port_latencies (lat, true); + } + } (*i)->set_output_latency (l_out); if ((*i)->active ()) { l_out += (*i)->signal_latency (); @@ -4008,6 +3999,27 @@ Route::update_signal_latency (bool apply_to_delayline) _signal_latency = l_out; for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + + /* set sidechain, send and insert port latencies */ + if (boost::shared_ptr pi = boost::dynamic_pointer_cast (*i)) { + if (pi->input ()) { + /* propagate playback latency from output to input */ + pi->input ()->set_private_port_latencies (play_lat_out + l_in, true); + } + if (pi->output ()) { + /* propagate capture latency from input to output */ + pi->output ()->set_private_port_latencies (capt_lat_in + l_in, false); + } + + } else if (boost::shared_ptr snd = boost::dynamic_pointer_cast (*i)) { + if (snd->output ()) { + /* set capture latency */ + snd->output ()->set_private_port_latencies (capt_lat_in + l_in, false); + /* take send-target's playback latency into account */ + snd->set_delay_out (snd->output ()->connected_latency (true)); + } + } + (*i)->set_input_latency (l_in); (*i)->set_playback_offset (_signal_latency + _output->latency ()); (*i)->set_capture_offset (_input->latency ()); @@ -4041,7 +4053,7 @@ void Route::apply_latency_compensation () { if (_delayline) { - samplecnt_t old = _delayline->get_delay (); + samplecnt_t old = _delayline->delay (); samplecnt_t play_lat_in = _input->connected_latency (true); samplecnt_t play_lat_out = _output->connected_latency (true); @@ -4057,7 +4069,7 @@ Route::apply_latency_compensation () _delayline->set_delay (latcomp > 0 ? latcomp : 0); - if (old != _delayline->get_delay ()) { + if (old != _delayline->delay ()) { signal_latency_updated (); /* EMIT SIGNAL */ } } @@ -4080,22 +4092,6 @@ Route::protect_automation () (*i)->protect_automation(); } -/** @param declick 1 to set a pending declick fade-in, - * -1 to set a pending declick fade-out - */ -void -Route::set_pending_declick (int declick) -{ - if (_declickable) { - /* this call is not allowed to turn off a pending declick */ - if (declick) { - _pending_declick = declick; - } - } else { - _pending_declick = 0; - } -} - /** Shift automation forwards from a particular place, thereby inserting time. * Adds undo commands for any shifts that are performed. * @@ -4216,10 +4212,15 @@ Route::set_name (const string& str) return true; } - string name = Route::ensure_track_or_route_name (str, _session); - SessionObject::set_name (name); + string newname = Route::ensure_track_or_route_name (str); + + if (newname == name()) { + return true; + } + + SessionObject::set_name (newname); - bool ret = (_input->set_name(name) && _output->set_name(name)); + bool ret = (_input->set_name(newname) && _output->set_name(newname)); if (ret) { /* rename the main outs. Leave other IO processors @@ -4229,7 +4230,7 @@ Route::set_name (const string& str) */ if (_main_outs) { - if (_main_outs->set_name (name)) { + if (_main_outs->set_name (newname)) { /* XXX returning false here is stupid because we already changed the route name. */ @@ -4590,6 +4591,7 @@ Route::set_private_port_latencies (bool playback) const */ for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) { + if ((*i)->active ()) { own_latency += (*i)->signal_latency (); } @@ -4607,28 +4609,26 @@ Route::set_private_port_latencies (bool playback) const void Route::set_public_port_latencies (samplecnt_t value, bool playback) const { - /* this is called to set the JACK-visible port latencies, which take - latency compensation into account. - */ - - LatencyRange range; - - range.min = value; - range.max = value; - - { - const PortSet& ports (_input->ports()); - for (PortSet::const_iterator p = ports.begin(); p != ports.end(); ++p) { - p->set_public_latency_range (range, playback); + /* publish private latencies */ + Glib::Threads::RWLock::ReaderLock lm (_processor_lock); + for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) { + boost::shared_ptr iop = boost::dynamic_pointer_cast(*i); + if (!iop) { + continue; } - } - - { - const PortSet& ports (_output->ports()); - for (PortSet::const_iterator p = ports.begin(); p != ports.end(); ++p) { - p->set_public_latency_range (range, playback); + if (iop->input ()) { + iop->input ()->set_public_port_latencies (iop->input()->latency(), true); + } + if (iop->output ()) { + iop->output ()->set_public_port_latencies (iop->output()->latency(), false); } } + + /* this is called to set the JACK-visible port latencies, which take + * latency compensation into account. + */ + _input->set_public_port_latencies (value, playback); + _output->set_public_port_latencies (value, playback); } /** Put the invisible processors in the right place in _processors. @@ -5024,7 +5024,11 @@ Route::the_instrument_unlocked () const return boost::shared_ptr(); } - +bool +Route::is_track() +{ + return dynamic_cast(this) != 0; +} void Route::non_realtime_locate (samplepos_t pos) @@ -5986,67 +5990,6 @@ Route::monitoring_state () const break; } - /* This is an implementation of the truth table in doc/monitor_modes.pdf; - I don't think it's ever going to be too pretty too look at. - */ - - bool const roll = _session.transport_rolling (); - bool const track_rec = _disk_writer->record_enabled (); - bool const auto_input = _session.config.get_auto_input (); - bool const software_monitor = Config->get_monitoring_model() == SoftwareMonitoring; - bool const tape_machine_mode = Config->get_tape_machine_mode (); - bool session_rec; - - /* I suspect that just use actively_recording() is good enough all the - * time, but just to keep the semantics the same as they were before - * sept 26th 2012, we differentiate between the cases where punch is - * enabled and those where it is not. - * - * rg: sept 30 2017: Above is not the case: punch-in/out location is - * global session playhead position. - * When this method is called from process_output_buffers() we need - * to use delay-compensated route's process-position. - * - * NB. Disk reader/writer may also be offset by a same amount of time. - * - * Also keep in mind that _session.transport_rolling() is false during - * pre-roll but the disk already produces output. - * - * TODO: FIXME - */ - - if (_session.config.get_punch_in() || _session.config.get_punch_out()) { - session_rec = _session.actively_recording (); - } else { - session_rec = _session.get_record_enabled(); - } - - if (track_rec) { - - if (!session_rec && roll && auto_input) { - return MonitoringDisk; - } else { - return software_monitor ? MonitoringInput : MonitoringSilence; - } - - } else { - - if (tape_machine_mode) { - - return MonitoringDisk; - - } else { - - if (!roll && auto_input) { - return software_monitor ? MonitoringInput : MonitoringSilence; - } else { - return MonitoringDisk; - } - - } - } - - abort(); /* NOTREACHED */ - return MonitoringSilence; + return get_auto_monitoring_state(); } #endif