diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h index e93ebd7f02..945dc52b31 100644 --- a/libs/ardour/ardour/audio_track.h +++ b/libs/ardour/ardour/audio_track.h @@ -37,9 +37,6 @@ class LIBARDOUR_API AudioTrack : public Track AudioTrack (Session&, std::string name, TrackMode m = Normal); ~AudioTrack (); - int roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, - int declick, bool& need_butler); - void freeze_me (InterThreadInfo&); void unfreeze (); diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 54a04d8ed3..023c18926b 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -42,8 +42,6 @@ public: int init (); - int roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler); - void realtime_locate (); void non_realtime_locate (samplepos_t); @@ -120,6 +118,8 @@ public: MidiChannelFilter& playback_filter() { return _playback_filter; } MidiChannelFilter& capture_filter() { return _capture_filter; } + virtual void filter_input (BufferSet& bufs); + boost::shared_ptr midi_playlist (); PBD::Signal1 > DataRecorded; diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 1ecf36d445..0e1d0b65e1 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -77,6 +77,7 @@ class PluginInsert; class RouteGroup; class Send; class InternalReturn; +class MonitorControl; class MonitorProcessor; class Pannable; class CapturingProcessor; @@ -128,11 +129,15 @@ public: bool set_name (const std::string& str); static void set_name_in_state (XMLNode &, const std::string &, bool rename_playlist = true); + boost::shared_ptr monitoring_control() const { return _monitoring_control; } + MonitorState monitoring_state () const; virtual MeterState metering_state () const; /* these are the core of the API of a Route. see the protected sections as well */ + virtual void filter_input (BufferSet &) {} + virtual int roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler); @@ -474,13 +479,6 @@ public: return _solo_safe_control; } - boost::shared_ptr monitoring_control() const { - /* tracks override this to provide actual monitoring control; - busses have no possible choices except input monitoring. - */ - return boost::shared_ptr (); - } - /* Route doesn't own these items, but sub-objects that it does own have them and to make UI code a bit simpler, we provide direct access to them here. @@ -603,7 +601,7 @@ public: void fill_buffers_with_input (BufferSet& bufs, boost::shared_ptr io, pframes_t nframes); - void passthru (BufferSet&, samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick); + void passthru (BufferSet&, samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick, bool gain_automation_ok); virtual void write_out_of_band_data (BufferSet& /* bufs */, samplepos_t /* start_sample */, samplepos_t /* end_sample */, samplecnt_t /* nframes */) {} @@ -640,6 +638,7 @@ public: boost::shared_ptr _pannable; boost::shared_ptr _disk_reader; boost::shared_ptr _disk_writer; + boost::shared_ptr _monitoring_control; DiskIOPoint _disk_io_point; diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 9d00f812d3..ec81e92939 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -38,7 +38,6 @@ class DiskReader; class DiskWriter; class IO; class Location; -class MonitorControl; class RecordEnableControl; class RecordSafeControl; @@ -62,9 +61,6 @@ class LIBARDOUR_API Track : public Route, public Recordable TrackMode mode () const { return _mode; } - boost::shared_ptr monitoring_control() const { return _monitoring_control; } - - MonitorState monitoring_state () const; MeterState metering_state () const; bool set_processor_state (XMLNode const & node, XMLProperty const* prop, ProcessorList& new_order, bool& must_configure); @@ -72,9 +68,6 @@ class LIBARDOUR_API Track : public Route, public Recordable virtual int no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool state_changing); - virtual int roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, - int declick, bool& need_butler) = 0; - bool needs_butler() const { return _needs_butler; } bool can_record(); @@ -197,7 +190,6 @@ class LIBARDOUR_API Track : public Route, public Recordable MeterPoint _saved_meter_point; TrackMode _mode; bool _needs_butler; - boost::shared_ptr _monitoring_control; //private: (FIXME) struct FreezeRecordProcessorInfo { diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 403d48f5c0..efce77f6d8 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -222,52 +222,6 @@ AudioTrack::set_state_part_two () } } -/** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone - * or set to false. - */ -int -AudioTrack::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler) -{ - Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK); - - if (!lm.locked()) { - return 0; - } - - if (n_outputs().n_total() == 0 && _processors.empty()) { - return 0; - } - - if (!_active) { - silence (nframes); - if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) { - _meter->reset(); - } - return 0; - } - - _silent = false; - _amp->apply_gain_automation(false); - - BufferSet& bufs = _session.get_route_buffers (n_process_buffers ()); - - fill_buffers_with_input (bufs, _input, nframes); - - if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) { - _meter->run (bufs, start_sample, end_sample, 1.0 /*speed()*/, nframes, true); - } - - process_output_buffers (bufs, start_sample, end_sample, nframes, declick, (!_disk_writer->record_enabled() && _session.transport_rolling())); - - if (_disk_reader->need_butler() || _disk_writer->need_butler()) { - need_butler = true; - } - - flush_processor_buffers_locked (nframes); - - return 0; -} - int AudioTrack::export_stuff (BufferSet& buffers, samplepos_t start, samplecnt_t nframes, boost::shared_ptr endpoint, bool include_endpoint, bool for_export, bool for_freeze) diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 91916bd914..4832ccce07 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -317,61 +317,6 @@ MidiTrack::update_controls(const BufferSet& bufs) } } -/** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone - * or set to false. - */ -int -MidiTrack::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler) -{ - Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK); - - if (!lm.locked()) { - return 0; - } - - if (n_outputs().n_total() == 0 && _processors.empty()) { - return 0; - } - - if (!_active) { - silence (nframes); - if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) { - _meter->reset(); - } - return 0; - } - - _silent = false; - _amp->apply_gain_automation (false); - - BufferSet& bufs = _session.get_route_buffers (n_process_buffers()); - - fill_buffers_with_input (bufs, _input, nframes); - - /* filter captured data before meter sees it */ - _capture_filter.filter (bufs); - - if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) { - _meter->run (bufs, start_sample, end_sample, 1.0 /*speed()*/, nframes, true); - } - - /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */ - - write_out_of_band_data (bufs, start_sample, end_sample, nframes); - - /* final argument: don't waste time with automation if we're not recording or rolling */ - - process_output_buffers (bufs, start_sample, end_sample, nframes, declick, (!_disk_writer->record_enabled() && !_session.transport_stopped())); - - if (_disk_reader->need_butler() || _disk_writer->need_butler()) { - need_butler = true; - } - - flush_processor_buffers_locked (nframes); - - return 0; -} - int MidiTrack::no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool state_changing) { @@ -863,3 +808,9 @@ MidiTrack::monitoring_state () const } return ms; } + +void +MidiTrack::filter_input (BufferSet& bufs) +{ + _capture_filter.filter (bufs); +} diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index f0bd724e44..a3ff8c1fa5 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/monitor_control.h" #include "ardour/monitor_processor.h" #include "ardour/pannable.h" #include "ardour/panner.h" @@ -598,11 +599,11 @@ Route::monitor_run (samplepos_t start_sample, samplepos_t end_sample, pframes_t assert (is_monitor()); BufferSet& bufs (_session.get_route_buffers (n_process_buffers())); fill_buffers_with_input (bufs, _input, nframes); - passthru (bufs, start_sample, end_sample, nframes, declick); + passthru (bufs, start_sample, end_sample, nframes, declick, true); } void -Route::passthru (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick) +Route::passthru (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick, bool gain_automation_ok) { _silent = false; @@ -616,8 +617,13 @@ Route::passthru (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp bufs.silence (nframes, 0); } + /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */ + write_out_of_band_data (bufs, start_sample, end_sample, nframes); - process_output_buffers (bufs, start_sample, end_sample, nframes, declick, true); + + /* run processor chain */ + + process_output_buffers (bufs, start_sample, end_sample, nframes, declick, gain_automation_ok); } void @@ -3581,7 +3587,7 @@ Route::no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sam _amp->apply_gain_automation (false); _trim->apply_gain_automation (false); - passthru (bufs, start_sample, end_sample, nframes, 0); + passthru (bufs, start_sample, end_sample, nframes, 0, true); flush_processor_buffers_locked (nframes); @@ -3589,35 +3595,42 @@ Route::no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sam } 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, int declick, bool& need_butler) { Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK); + if (!lm.locked()) { return 0; } if (!_active) { silence_unlocked (nframes); - return 0; - } - - samplepos_t unused = 0; - - if ((nframes = check_initial_delay (nframes, unused)) == 0) { + if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || (!_disk_writer || _disk_writer->record_enabled()))) { + _meter->reset(); + } return 0; } _silent = false; + _amp->apply_gain_automation(false); - BufferSet& bufs = _session.get_route_buffers (n_process_buffers()); + BufferSet& bufs = _session.get_route_buffers (n_process_buffers ()); fill_buffers_with_input (bufs, _input, nframes); - if (_meter_point == MeterInput) { - _meter->run (bufs, start_sample, end_sample, 1.0, nframes, true); + /* filter captured data before meter sees it */ + filter_input (bufs); + + if (_meter_point == MeterInput && + ((_monitoring_control->monitoring_choice() & MonitorInput) || (_disk_writer && _disk_writer->record_enabled()))) { + _meter->run (bufs, start_sample, end_sample, 1.0 /*speed()*/, nframes, true); } - passthru (bufs, start_sample, end_sample, nframes, declick); + passthru (bufs, start_sample, end_sample, nframes, declick, ((_disk_writer && !_disk_writer->record_enabled()) && _session.transport_rolling())); + + if ((_disk_reader && _disk_reader->need_butler()) || (_disk_writer && _disk_writer->need_butler())) { + need_butler = true; + } flush_processor_buffers_locked (nframes); @@ -4811,15 +4824,6 @@ Route::processor_by_id (PBD::ID id) const return boost::shared_ptr (); } -/** @return the monitoring state, or in other words what data we are pushing - * into the route (data from the inputs, data from disk or silence) - */ -MonitorState -Route::monitoring_state () const -{ - return MonitoringInput; -} - /** @return what we should be metering; either the data coming from the input * IO or the data that is flowing through the route. */ @@ -5670,3 +5674,154 @@ Route::set_disk_io_point (DiskIOPoint diop) processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */ } + +#ifdef USE_TRACKS_CODE_FEATURES + +/* This is the Tracks version of Track::monitoring_state(). + * + * Ardour developers: try to flag or fix issues if parts of the libardour API + * change in ways that invalidate this + */ + +MonitorState +Route::monitoring_state () const +{ + /* Explicit requests */ + + if (_monitoring != MonitorInput) { + return MonitoringInput; + } + + if (_monitoring & MonitorDisk) { + return MonitoringDisk; + } + + /* 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. + */ + + // GZ: NOT USED IN TRACKS + //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 const roll = _session.transport_rolling (); + bool const track_rec = _diskstream->record_enabled (); + bool session_rec = _session.actively_recording (); + + if (track_rec) { + + if (!session_rec && roll) { + return MonitoringDisk; + } else { + return MonitoringInput; + } + + } else { + + if (roll) { + return MonitoringDisk; + } + } + + return MonitoringSilence; +} + +#else + +/* This is the Ardour/Mixbus version of Track::monitoring_state(). + * + * Tracks developers: do NOT modify this method under any circumstances. + */ + +MonitorState +Route::monitoring_state () const +{ + if (!_disk_reader) { + return MonitoringInput; + } + + /* Explicit requests */ + MonitorChoice m (_monitoring_control->monitoring_choice()); + + if (m != MonitorAuto) { + + MonitorState ms ((MonitorState) 0); + + if (m & MonitorInput) { + ms = MonitoringInput; + } + + if (m & MonitorDisk) { + ms = MonitorState (ms | MonitoringDisk); + } + + return ms; + } + + switch (_session.config.get_session_monitoring ()) { + case MonitorDisk: + return MonitoringDisk; + break; + case MonitorInput: + return MonitoringInput; + break; + default: + 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: I suspect this is not the case: monitoring may differ + */ + + if (_session.config.get_punch_in() || _session.config.get_punch_out() || _session.preroll_record_punch_enabled ()) { + 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; +} + +#endif diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index d925c2c40d..48235417a5 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -548,7 +548,7 @@ Track::no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sam _meter->run (bufs, start_sample, end_sample, _session.transport_speed(), nframes, true); } - passthru (bufs, start_sample, end_sample, nframes, false); + passthru (bufs, start_sample, end_sample, nframes, false, true); } flush_processor_buffers_locked (nframes); @@ -980,152 +980,6 @@ Track::adjust_capture_buffering () } } -#ifdef USE_TRACKS_CODE_FEATURES - -/* This is the Tracks version of Track::monitoring_state(). - * - * Ardour developers: try to flag or fix issues if parts of the libardour API - * change in ways that invalidate this - */ - -MonitorState -Track::monitoring_state () const -{ - /* Explicit requests */ - - if (_monitoring != MonitorInput) { - return MonitoringInput; - } - - if (_monitoring & MonitorDisk) { - return MonitoringDisk; - } - - /* 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. - */ - - // GZ: NOT USED IN TRACKS - //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 const roll = _session.transport_rolling (); - bool const track_rec = _diskstream->record_enabled (); - bool session_rec = _session.actively_recording (); - - if (track_rec) { - - if (!session_rec && roll) { - return MonitoringDisk; - } else { - return MonitoringInput; - } - - } else { - - if (roll) { - return MonitoringDisk; - } - } - - return MonitoringSilence; -} - -#else - -/* This is the Ardour/Mixbus version of Track::monitoring_state(). - * - * Tracks developers: do NOT modify this method under any circumstances. - */ - -MonitorState -Track::monitoring_state () const -{ - /* Explicit requests */ - MonitorChoice m (_monitoring_control->monitoring_choice()); - - if (m != MonitorAuto) { - - MonitorState ms ((MonitorState) 0); - - if (m & MonitorInput) { - ms = MonitoringInput; - } - - if (m & MonitorDisk) { - ms = MonitorState (ms | MonitoringDisk); - } - - return ms; - } - - switch (_session.config.get_session_monitoring ()) { - case MonitorDisk: - return MonitoringDisk; - break; - case MonitorInput: - return MonitoringInput; - break; - default: - 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: I suspect this is not the case: monitoring may differ - */ - - if (_session.config.get_punch_in() || _session.config.get_punch_out() || _session.preroll_record_punch_enabled ()) { - 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; -} - -#endif void Track::maybe_declick (BufferSet& bufs, samplecnt_t nframes, int declick)