Ardour  8.12
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 #ifndef __ardour_plugin_insert_h__
25 #define __ardour_plugin_insert_h__
26 
27 #include <atomic>
28 #include <memory>
29 #include <string>
30 #include <vector>
31 
32 #include "pbd/stack_allocator.h"
33 #include "pbd/timing.h"
34 
35 #include "ardour/ardour.h"
37 #include "ardour/fixed_delay.h"
38 #include "ardour/io.h"
39 #include "ardour/types.h"
41 #include "ardour/plugin.h"
43 #include "ardour/processor.h"
45 #include "ardour/sidechain.h"
46 
47 class XMLNode;
48 
49 namespace ARDOUR {
50 
51 class Session;
52 class Route;
53 class Plugin;
54 
57 class LIBARDOUR_API PluginInsert : public Processor, public PlugInsertBase, public std::enable_shared_from_this <PluginInsert>
58 {
59 public:
60  PluginInsert (Session&, Temporal::TimeDomainProvider const & tdp, std::shared_ptr<Plugin> = std::shared_ptr<Plugin>());
62 
63  void drop_references ();
64 
65  std::weak_ptr<PluginInsert> weak_ptr () {
66  return shared_from_this();
67  }
68 
69  static const std::string port_automation_node_name;
70 
71  int set_state(const XMLNode&, int version);
74  void set_state_dir (const std::string& d = "");
75 
76  void run (BufferSet& in, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool);
77  void silence (samplecnt_t nframes, samplepos_t start_sample);
78 
79  void activate ();
80  void deactivate ();
81  void flush ();
82 
83  void enable (bool yn);
84  bool enabled () const;
85  bool bypassable () const;
86 
89 
90  bool write_immediate_event (Evoral::EventType event_type, size_t size, const uint8_t* buf);
91 
92  void automation_run (samplepos_t, pframes_t, bool only_active = false);
93  bool find_next_event (Temporal::timepos_t const &, Temporal::timepos_t const &, Evoral::ControlEvent&, bool only_active = true) const;
94 
95  int set_block_size (pframes_t nframes);
96 
97  ChanMapping input_map (uint32_t num) const {
98  if (num < _in_map.size()) {
99  return _in_map.find (num)->second;
100  } else {
101  return ChanMapping ();
102  }
103  }
104 
105  ChanMapping output_map (uint32_t num) const {
106  if (num < _out_map.size()) {
107  return _out_map.find (num)->second;
108  } else {
109  return ChanMapping ();
110  }
111  }
112 
114  return _thru_map;
115  }
116 
117  bool pre_seed (const ChanCount&, const ChanCount&, const ChanMapping&, const ChanMapping&, const ChanMapping&);
118 
122  bool has_midi_bypass () const;
123  bool has_midi_thru () const;
124  bool inplace () const { return ! _no_inplace; }
125 
126  bool is_channelstrip () const;
127 
129 
130  void set_input_map (uint32_t, ChanMapping);
131  void set_output_map (uint32_t, ChanMapping);
133  bool reset_map (bool emit = true);
135  bool configured () const { return _configured; }
136 
137  // these are ports visible on the outside
140  ChanCount internal_streams() const; // with side-chain
141 
142  // actual ports of all plugins.
143  // n * natural_i/o or result of reconfigurable i/o
146 
147  // a single plugin's internal i/o
150 
153 
156  if (_sidechain) {
157  return _sidechain->input ()->n_ports ();
158  } else {
159  return ChanCount ();
160  }
161  }
162 
163  const ChanCount& required_buffers () const { return _required_buffers; }
164  const ChanCount& preset_out () const { return _preset_out; }
165 
166  // allow to override output_streams(), implies "Custom Mode"
167 
168  // only the owning route may call these (with process lock held)
169  // route is not a friend class, it owns us
170  bool set_count (uint32_t num);
171  void set_sinks (const ChanCount&); // reconfigurable I/O ONLY
172  void set_outputs (const ChanCount&);
173  void set_strict_io (bool b);
174  void set_custom_cfg (bool b);
175  bool set_preset_out (const ChanCount&);
176  bool add_sidechain (uint32_t n_audio = 1, uint32_t n_midi = 0);
177  bool del_sidechain ();
179  std::shared_ptr<SideChain> sidechain () const { return _sidechain; }
180  // end C++ class slavery!
181 
182  uint32_t get_count () const { return _plugins.size(); }
183  bool strict_io () const { return _strict_io; }
184  bool custom_cfg () const { return _custom_cfg; }
185 
188 
189  bool has_no_inputs() const;
190  bool has_no_audio_inputs() const;
191 
192  bool is_instrument () const;
193  bool has_automatables () const;
194 
198  );
199 
201  void realtime_locate (bool);
203 
205 
206  bool provides_stats () const;
207  bool get_stats (PBD::microseconds_t& min, PBD::microseconds_t& max, double& avg, double& dev) const;
208  void clear_stats ();
209 
210  struct PIControl : public PluginControl
211  {
213  PlugInsertBase* p,
214  const Evoral::Parameter& param,
215  const ParameterDescriptor& desc,
216  std::shared_ptr<AutomationList> list = std::shared_ptr<AutomationList>())
217  : PluginControl (s, p, param, desc, list) {}
218  private:
220  };
221 
222  std::shared_ptr<Plugin> plugin(uint32_t num=0) const {
223  if (num < _plugins.size()) {
224  return _plugins[num];
225  } else {
226  return _plugins[0]; // we always have one
227  }
228  }
229 
231 
232  bool has_sidechain () const {
233  return _sidechain ? true : false;
234  }
235 
236  std::shared_ptr<IO> sidechain_input () const {
237  if (_sidechain) {
238  return _sidechain->input ();
239  }
240  return std::shared_ptr<IO> ();
241  }
242 
243  PluginType type () const;
244 
245  std::shared_ptr<ReadOnlyControl> control_output (uint32_t) const;
246 
248 
250 
251  std::shared_ptr<Plugin> get_impulse_analysis_plugin();
252 
254 
255  bool strict_io_configured () const {
256  return _match.strict_io;
257  }
258 
259  bool splitting () const {
260  return _match.method == Split;
261  }
262 
263  void configured_io (ChanCount &in, ChanCount &out) const {
264  in = _configured_in;
265  out = _configured_out;
266  }
267 
268  PBD::Signal2<void,BufferSet*, BufferSet*> AnalysisDataGathered;
269  PBD::Signal0<void> PluginIoReConfigure;
270  PBD::Signal0<void> PluginMapChanged;
271  PBD::Signal0<void> PluginConfigChanged;
272 protected:
273  XMLNode& state () const;
274 
275 private:
276  /* disallow copy construction */
278 
279  void parameter_changed_externally (uint32_t, float);
280 
282 
284 
285  typedef std::vector<std::shared_ptr<Plugin> > Plugins;
287 
288  std::shared_ptr<SideChain> _sidechain;
292 
293  std::weak_ptr<Plugin> _impulseAnalysisPlugin;
294 
297 
300 
302 
304  ChanCount _configured_internal; // with side-chain
311 
317 
321 
324 
325  /* ordered map [plugin instance ID] => ARDOUR::ChanMapping */
326 #if defined(_MSC_VER) /* && (_MSC_VER < 1900)
327  * Regarding the note (below) it was initially
328  * thought that this got fixed in VS2015 - but
329  * in fact it's still faulty (JE - Feb 2021) */
330  /* Use the older (heap based) mapping for early versions of MSVC.
331  * In fact it might be safer to use this for all MSVC builds - as
332  * our StackAllocator class depends on 'boost::aligned_storage'
333  * which is known to be troublesome with Visual C++ :-
334  * https://www.boost.org/doc/libs/1_65_0/libs/type_traits/doc/html/boost_typetraits/reference/aligned_storage.html
335  */
336  class PinMappings : public std::map <uint32_t, ARDOUR::ChanMapping>
337 #else
338  class PinMappings : public std::map <uint32_t, ARDOUR::ChanMapping, std::less<uint32_t>, PBD::StackAllocator<std::pair<const uint32_t, ARDOUR::ChanMapping>, 4> >
339 #endif
340  {
341  public:
342  /* this emulates C++11's std::map::at()
343  * return mapping for given plugin instance */
344  inline ARDOUR::ChanMapping const& p (const uint32_t i) const {
345 #ifndef NDEBUG
346  const_iterator x = find (i);
347  assert (x != end ());
348  return x->second;
349 #else
350  return find(i)->second;
351 #endif
352  }
353  };
354 
357  ChanMapping _thru_map; // out-idx <= in-idx
358 
359  void automate_and_run (BufferSet& bufs, samplepos_t start, samplepos_t end, double speed, pframes_t nframes);
360  void connect_and_run (BufferSet& bufs, samplepos_t start, samplecnt_t end, double speed, pframes_t nframes, samplecnt_t offset, bool with_auto);
361  void bypass (BufferSet& bufs, pframes_t nframes);
363 
366  void set_parameter_state_2X (const XMLNode& node, int version);
367 
368  void enable_changed ();
370 
371  bool sanitize_maps ();
372  bool check_inplace ();
374 
375  void add_plugin (std::shared_ptr<Plugin>);
376  void plugin_removed (std::weak_ptr<Plugin>);
377 
378  void add_sidechain_from_xml (const XMLNode& node, int version);
379 
380  void start_touch (uint32_t param_id);
381  void end_touch (uint32_t param_id);
382 
385  uint32_t _bypass_port;
387 
388  typedef std::map<uint32_t, std::shared_ptr<ReadOnlyControl> >CtrlOutMap;
390 
392  std::atomic<int> _stat_reset;
393  std::atomic<int> _flush;
394 };
395 
396 } // namespace ARDOUR
397 
398 #endif /* __ardour_plugin_insert_h__ */
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)
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:65
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
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:97
void set_strict_io(bool b)
static const std::string port_automation_node_name
Definition: plugin_insert.h:69
XMLNode & state() const
std::weak_ptr< Plugin > _impulseAnalysisPlugin
PBD::Signal0< void > PluginConfigChanged
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)
PBD::Signal0< void > PluginIoReConfigure
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
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)
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)
PBD::Signal0< void > PluginMapChanged
PBD::Signal2< void, BufferSet *, BufferSet * > AnalysisDataGathered
PluginInsert(Session &, Temporal::TimeDomainProvider const &tdp, std::shared_ptr< Plugin >=std::shared_ptr< Plugin >())
Definition: id.h:35
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:29
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)