Ardour  9.0-pre0-582-g084a23a80d
plugin_insert.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2000-2017 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2007-2014 David Robillard <d@drobilla.net>
4  * Copyright (C) 2008-2009 Sampo Savolainen <v2@iki.fi>
5  * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
6  * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
7  * Copyright (C) 2018 Johannes Mueller <github@johannes-mueller.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #pragma once
25 
26 #include <atomic>
27 #include <memory>
28 #include <string>
29 #include <vector>
30 
31 #include "pbd/stack_allocator.h"
32 #include "pbd/timing.h"
33 
34 #include "ardour/ardour.h"
36 #include "ardour/fixed_delay.h"
37 #include "ardour/io.h"
38 #include "ardour/types.h"
40 #include "ardour/plugin.h"
42 #include "ardour/processor.h"
44 #include "ardour/sidechain.h"
45 
46 class XMLNode;
47 
48 namespace ARDOUR {
49 
50 class Session;
51 class Route;
52 class Plugin;
53 
56 class LIBARDOUR_API PluginInsert : public Processor, public PlugInsertBase, public std::enable_shared_from_this <PluginInsert>
57 {
58 public:
59  PluginInsert (Session&, Temporal::TimeDomainProvider const & tdp, std::shared_ptr<Plugin> = std::shared_ptr<Plugin>());
61 
62  void drop_references ();
63 
64  std::weak_ptr<PluginInsert> weak_ptr () {
65  return shared_from_this();
66  }
67 
68  static const std::string port_automation_node_name;
69 
70  int set_state(const XMLNode&, int version);
73  void set_state_dir (const std::string& d = "");
74 
75  void run (BufferSet& in, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool);
76  void silence (samplecnt_t nframes, samplepos_t start_sample);
77 
78  void activate ();
79  void deactivate ();
80  void flush ();
81 
82  void enable (bool yn);
83  bool enabled () const;
84  bool bypassable () const;
85 
88 
89  bool write_immediate_event (Evoral::EventType event_type, size_t size, const uint8_t* buf);
90 
91  void automation_run (samplepos_t, pframes_t, bool only_active = false);
92  bool find_next_event (Temporal::timepos_t const &, Temporal::timepos_t const &, Evoral::ControlEvent&, bool only_active = true) const;
93 
94  int set_block_size (pframes_t nframes);
95 
96  ChanMapping input_map (uint32_t num) const {
97  if (num < _in_map.size()) {
98  return _in_map.find (num)->second;
99  } else {
100  return ChanMapping ();
101  }
102  }
103 
104  ChanMapping output_map (uint32_t num) const {
105  if (num < _out_map.size()) {
106  return _out_map.find (num)->second;
107  } else {
108  return ChanMapping ();
109  }
110  }
111 
113  return _thru_map;
114  }
115 
116  bool pre_seed (const ChanCount&, const ChanCount&, const ChanMapping&, const ChanMapping&, const ChanMapping&);
117 
121  bool has_midi_bypass () const;
122  bool has_midi_thru () const;
123  bool inplace () const { return ! _no_inplace; }
124 
125  bool is_channelstrip () const;
126 
128 
129  void set_input_map (uint32_t, ChanMapping);
130  void set_output_map (uint32_t, ChanMapping);
132  bool reset_map (bool emit = true);
134  bool configured () const { return _configured; }
135 
136  // these are ports visible on the outside
139  ChanCount internal_streams() const; // with side-chain
140 
141  // actual ports of all plugins.
142  // n * natural_i/o or result of reconfigurable i/o
145 
146  // a single plugin's internal i/o
149 
152 
155  if (_sidechain) {
156  return _sidechain->input ()->n_ports ();
157  } else {
158  return ChanCount ();
159  }
160  }
161 
162  const ChanCount& required_buffers () const { return _required_buffers; }
163  const ChanCount& preset_out () const { return _preset_out; }
164 
165  // allow to override output_streams(), implies "Custom Mode"
166 
167  // only the owning route may call these (with process lock held)
168  // route is not a friend class, it owns us
169  bool set_count (uint32_t num);
170  void set_sinks (const ChanCount&); // reconfigurable I/O ONLY
171  void set_outputs (const ChanCount&);
172  void set_strict_io (bool b);
173  void set_custom_cfg (bool b);
174  bool set_preset_out (const ChanCount&);
175  bool add_sidechain (uint32_t n_audio = 1, uint32_t n_midi = 0);
176  bool del_sidechain ();
178  std::shared_ptr<SideChain> sidechain () const { return _sidechain; }
179  // end C++ class slavery!
180 
181  uint32_t get_count () const { return _plugins.size(); }
182  bool strict_io () const { return _strict_io; }
183  bool custom_cfg () const { return _custom_cfg; }
184 
187 
188  bool has_no_inputs() const;
189  bool has_no_audio_inputs() const;
190 
191  bool is_instrument () const;
192  bool has_automatables () const;
193 
197  );
198 
200  void realtime_locate (bool);
202 
204 
205  bool provides_stats () const;
206  bool get_stats (PBD::microseconds_t& min, PBD::microseconds_t& max, double& avg, double& dev) const;
207  void clear_stats ();
208 
209  struct PIControl : public PluginControl
210  {
212  PlugInsertBase* p,
213  const Evoral::Parameter& param,
214  const ParameterDescriptor& desc,
215  std::shared_ptr<AutomationList> list = std::shared_ptr<AutomationList>())
216  : PluginControl (s, p, param, desc, list) {}
217  private:
219  };
220 
221  std::shared_ptr<Plugin> plugin(uint32_t num=0) const {
222  if (num < _plugins.size()) {
223  return _plugins[num];
224  } else {
225  return _plugins[0]; // we always have one
226  }
227  }
228 
230 
231  bool has_sidechain () const {
232  return _sidechain ? true : false;
233  }
234 
235  std::shared_ptr<IO> sidechain_input () const {
236  if (_sidechain) {
237  return _sidechain->input ();
238  }
239  return std::shared_ptr<IO> ();
240  }
241 
242  PluginType type () const;
243 
244  std::shared_ptr<ReadOnlyControl> control_output (uint32_t) const;
245 
247 
249 
250  std::shared_ptr<Plugin> get_impulse_analysis_plugin();
251 
253 
254  bool strict_io_configured () const {
255  return _match.strict_io;
256  }
257 
258  bool splitting () const {
259  return _match.method == Split;
260  }
261 
262  void configured_io (ChanCount &in, ChanCount &out) const {
263  in = _configured_in;
264  out = _configured_out;
265  }
266 
271 protected:
272  XMLNode& state () const;
273 
274 private:
275  /* disallow copy construction */
277 
278  void parameter_changed_externally (uint32_t, float);
279 
281 
283 
284  typedef std::vector<std::shared_ptr<Plugin> > Plugins;
286 
287  std::shared_ptr<SideChain> _sidechain;
291 
292  std::weak_ptr<Plugin> _impulseAnalysisPlugin;
293 
296 
299 
301 
303  ChanCount _configured_internal; // with side-chain
310 
316 
320 
323 
324  /* ordered map [plugin instance ID] => ARDOUR::ChanMapping */
325 #if defined(_MSC_VER) /* && (_MSC_VER < 1900)
326  * Regarding the note (below) it was initially
327  * thought that this got fixed in VS2015 - but
328  * in fact it's still faulty (JE - Feb 2021) */
329  /* Use the older (heap based) mapping for early versions of MSVC.
330  * In fact it might be safer to use this for all MSVC builds - as
331  * our StackAllocator class depends on 'boost::aligned_storage'
332  * which is known to be troublesome with Visual C++ :-
333  * https://www.boost.org/doc/libs/1_65_0/libs/type_traits/doc/html/boost_typetraits/reference/aligned_storage.html
334  */
335  class PinMappings : public std::map <uint32_t, ARDOUR::ChanMapping>
336 #else
337  class PinMappings : public std::map <uint32_t, ARDOUR::ChanMapping, std::less<uint32_t>, PBD::StackAllocator<std::pair<const uint32_t, ARDOUR::ChanMapping>, 4> >
338 #endif
339  {
340  public:
341  /* this emulates C++11's std::map::at()
342  * return mapping for given plugin instance */
343  inline ARDOUR::ChanMapping const& p (const uint32_t i) const {
344 #ifndef NDEBUG
345  const_iterator x = find (i);
346  assert (x != end ());
347  return x->second;
348 #else
349  return find(i)->second;
350 #endif
351  }
352  };
353 
356  ChanMapping _thru_map; // out-idx <= in-idx
357 
358  void automate_and_run (BufferSet& bufs, samplepos_t start, samplepos_t end, double speed, pframes_t nframes);
359  void connect_and_run (BufferSet& bufs, samplepos_t start, samplecnt_t end, double speed, pframes_t nframes, samplecnt_t offset, bool with_auto);
360  void bypass (BufferSet& bufs, pframes_t nframes);
362 
365  void set_parameter_state_2X (const XMLNode& node, int version);
366 
367  void enable_changed ();
369 
370  bool sanitize_maps ();
371  bool check_inplace ();
373 
374  void add_plugin (std::shared_ptr<Plugin>);
375  void plugin_removed (std::weak_ptr<Plugin>);
376 
377  void add_sidechain_from_xml (const XMLNode& node, int version);
378 
379  void start_touch (uint32_t param_id);
380  void end_touch (uint32_t param_id);
381 
384  uint32_t _bypass_port;
386 
387  typedef std::map<uint32_t, std::shared_ptr<ReadOnlyControl> >CtrlOutMap;
389 
391  std::atomic<int> _stat_reset;
392  std::atomic<int> _flush;
393 };
394 
395 } // namespace ARDOUR
396 
ARDOUR::ChanMapping const & p(const uint32_t i) const
bool provides_stats() const
void set_thru_map(ChanMapping)
ChanMapping no_sc_input_map() const
combined (all instances) input map w/o sidechain sinks
void set_state_dir(const std::string &d="")
PBD::TimingStats _timing_stats
void inplace_silence_unconnected(BufferSet &, const PinMappings &, samplecnt_t nframes, samplecnt_t offset) const
bool write_immediate_event(Evoral::EventType event_type, size_t size, const uint8_t *buf)
bool reset_parameters_to_default()
bool load_preset(Plugin::PresetRecord)
ChanCount _required_buffers
bool set_count(uint32_t num)
bool can_support_io_configuration(const ChanCount &in, ChanCount &out)
ChanCount internal_output_streams() const
bool pre_seed(const ChanCount &, const ChanCount &, const ChanMapping &, const ChanMapping &, const ChanMapping &)
ChanCount natural_input_streams() const
void set_parameter_state_2X(const XMLNode &node, int version)
bool custom_cfg() const
void start_touch(uint32_t param_id)
void set_input_map(uint32_t, ChanMapping)
std::string describe_parameter(Evoral::Parameter param)
PBD::Signal< void()> PluginMapChanged
void automation_run(samplepos_t, pframes_t, bool only_active=false)
UIElements ui_elements() const
ChanCount internal_input_streams() const
std::shared_ptr< SideChain > sidechain() const
bool configured() const
std::atomic< int > _stat_reset
bool get_stats(PBD::microseconds_t &min, PBD::microseconds_t &max, double &avg, double &dev) const
void set_outputs(const ChanCount &)
BufferSet _signal_analysis_inputs
float default_parameter_value(const Evoral::Parameter &param)
void add_plugin(std::shared_ptr< Plugin >)
std::shared_ptr< Plugin > get_impulse_analysis_plugin()
void update_id(PBD::ID)
bool has_no_inputs() const
bool has_sidechain() const
ChanMapping thru_map() const
void configured_io(ChanCount &in, ChanCount &out) const
void collect_signal_for_analysis(samplecnt_t nframes)
ChanMapping output_map(uint32_t num) const
void enable(bool yn)
std::shared_ptr< Plugin > plugin(uint32_t num=0) const
void add_sidechain_from_xml(const XMLNode &node, int version)
bool has_midi_bypass() const
std::weak_ptr< PluginInsert > weak_ptr()
Definition: plugin_insert.h:64
void set_custom_cfg(bool b)
bool enabled() const
processor enabled/bypass
std::atomic< int > _flush
uint32_t _sc_capture_latency
void set_owner(SessionObject *)
std::shared_ptr< IO > sidechain_input() const
ChanCount sidechain_input_ports() const
bool inplace() const
bool strict_io() const
void realtime_locate(bool)
ChanCount _configured_internal
PBD::Signal< void()> PluginIoReConfigure
void realtime_handle_transport_stopped()
ChanCount internal_streams() const
PluginType type() const
samplecnt_t signal_latency() const
samplecnt_t plugin_latency() const
ChanMapping output_map() const
combined (all instances) output map
bool has_midi_thru() const
uint32_t _sc_playback_latency
ChanMapping input_map(uint32_t num) const
Definition: plugin_insert.h:96
void set_strict_io(bool b)
static const std::string port_automation_node_name
Definition: plugin_insert.h:68
XMLNode & state() const
std::weak_ptr< Plugin > _impulseAnalysisPlugin
void set_sinks(const ChanCount &)
const ChanCount & required_buffers() const
ChanCount _cached_sidechain_pins
ChanCount input_streams() const
void silence(samplecnt_t nframes, samplepos_t start_sample)
BufferSet _signal_analysis_outputs
bool is_instrument() const
bool configure_io(ChanCount in, ChanCount out)
int set_state(const XMLNode &, int version)
FixedDelay _delaybuffers
Match private_can_support_io_configuration(ChanCount const &, ChanCount &) const
void bypass(BufferSet &bufs, pframes_t nframes)
bool can_reset_all_parameters()
void set_parameter(Evoral::Parameter param, float val, sampleoffset_t)
Match automatic_can_support_io_configuration(ChanCount const &, ChanCount &) const
std::map< uint32_t, std::shared_ptr< ReadOnlyControl > > CtrlOutMap
void automate_and_run(BufferSet &bufs, samplepos_t start, samplepos_t end, double speed, pframes_t nframes)
ChanMapping input_map() const
combined (all instances) input map
bool strict_io_configured() const
void set_output_map(uint32_t, ChanMapping)
std::shared_ptr< ReadOnlyControl > control_output(uint32_t) const
samplecnt_t _signal_analysis_collect_nsamples
bool find_next_event(Temporal::timepos_t const &, Temporal::timepos_t const &, Evoral::ControlEvent &, bool only_active=true) const
bool is_channelstrip() const
ChanCount output_streams() const
samplecnt_t _signal_analysis_collect_nsamples_max
PBD::Signal< void()> PluginConfigChanged
ChanCount natural_output_streams() const
bool has_no_audio_inputs() const
int set_block_size(pframes_t nframes)
uint32_t _plugin_signal_latency
bool has_output_presets(ChanCount in=ChanCount(DataType::MIDI, 1), ChanCount out=ChanCount(DataType::AUDIO, 2))
const ChanCount & preset_out() const
bool add_sidechain(uint32_t n_audio=1, uint32_t n_midi=0)
std::vector< std::shared_ptr< Plugin > > Plugins
void end_touch(uint32_t param_id)
ChanCount sidechain_input_pins() const
void create_automatable_parameters()
void parameter_changed_externally(uint32_t, float)
void run(BufferSet &in, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool)
bool has_automatables() const
Match internal_can_support_io_configuration(ChanCount const &, ChanCount &) const
void connect_and_run(BufferSet &bufs, samplepos_t start, samplecnt_t end, double speed, pframes_t nframes, samplecnt_t offset, bool with_auto)
PBD::Signal< void(BufferSet *, BufferSet *)> AnalysisDataGathered
CtrlOutMap _control_outputs
void control_list_automation_state_changed(Evoral::Parameter, AutoState)
PluginInsert(const PluginInsert &)
bool splitting() const
uint32_t get_count() const
void plugin_removed(std::weak_ptr< Plugin >)
bool bypassable() const
enable is not automated or locked
std::shared_ptr< SideChain > _sidechain
bool set_preset_out(const ChanCount &)
bool reset_map(bool emit=true)
PluginInsert(Session &, Temporal::TimeDomainProvider const &tdp, std::shared_ptr< Plugin >=std::shared_ptr< Plugin >())
Definition: id.h:34
Definition: xml++.h:114
#define LIBARDOUR_API
PBD::PropertyDescriptor< timepos_t > start
uint32_t pframes_t
Temporal::samplecnt_t samplecnt_t
Temporal::sampleoffset_t sampleoffset_t
Temporal::samplepos_t samplepos_t
DebugBits ChanMapping
int64_t microseconds_t
Definition: microseconds.h:28
PIControl(Session &s, PlugInsertBase *p, const Evoral::Parameter &param, const ParameterDescriptor &desc, std::shared_ptr< AutomationList > list=std::shared_ptr< AutomationList >())
void actually_set_value(double val, PBD::Controllable::GroupControlDisposition group_override)