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 <vector> 28 #include <string> 29 30 #include <boost/weak_ptr.hpp> 31 32 #include "pbd/stack_allocator.h" 33 #include "pbd/timing.h" 34 #include "pbd/g_atomic_compat.h" 35 36 #include "ardour/ardour.h" 37 #include "ardour/libardour_visibility.h" 38 #include "ardour/chan_mapping.h" 39 #include "ardour/fixed_delay.h" 40 #include "ardour/io.h" 41 #include "ardour/types.h" 42 #include "ardour/parameter_descriptor.h" 43 #include "ardour/plugin.h" 44 #include "ardour/processor.h" 45 #include "ardour/readonly_control.h" 46 #include "ardour/sidechain.h" 47 #include "ardour/automation_control.h" 48 49 class XMLNode; 50 51 namespace ARDOUR { 52 53 class Session; 54 class Route; 55 class Plugin; 56 57 /** Plugin inserts: send data through a plugin 58 */ 59 class LIBARDOUR_API PluginInsert : public Processor 60 { 61 public: 62 PluginInsert (Session&, boost::shared_ptr<Plugin> = boost::shared_ptr<Plugin>()); 63 ~PluginInsert (); 64 65 void drop_references (); 66 67 static const std::string port_automation_node_name; 68 69 int set_state(const XMLNode&, int version); 70 void update_id (PBD::ID); 71 void set_owner (SessionObject*); 72 void set_state_dir (const std::string& d = ""); 73 74 void run (BufferSet& in, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool); 75 void silence (samplecnt_t nframes, samplepos_t start_sample); 76 77 void activate (); 78 void deactivate (); 79 void flush (); 80 81 void enable (bool yn); 82 bool enabled () const; 83 bool bypassable () const; 84 85 bool reset_parameters_to_default (); 86 bool can_reset_all_parameters (); 87 88 bool write_immediate_event (Evoral::EventType event_type, size_t size, const uint8_t* buf); 89 90 void automation_run (samplepos_t, pframes_t, bool only_active = false); 91 bool find_next_event (double, double, Evoral::ControlEvent&, bool only_active = true) const; 92 93 int set_block_size (pframes_t nframes); 94 input_map(uint32_t num)95 ChanMapping input_map (uint32_t num) const { 96 if (num < _in_map.size()) { 97 return _in_map.find (num)->second; 98 } else { 99 return ChanMapping (); 100 } 101 } 102 output_map(uint32_t num)103 ChanMapping output_map (uint32_t num) const { 104 if (num < _out_map.size()) { 105 return _out_map.find (num)->second; 106 } else { 107 return ChanMapping (); 108 } 109 } 110 thru_map()111 ChanMapping thru_map () const { 112 return _thru_map; 113 } 114 115 bool pre_seed (const ChanCount&, const ChanCount&, const ChanMapping&, const ChanMapping&, const ChanMapping&); 116 117 ChanMapping input_map () const; ///< combined (all instances) input map 118 ChanMapping no_sc_input_map () const; ///< combined (all instances) input map w/o sidechain sinks 119 ChanMapping output_map () const; ///< combined (all instances) output map 120 bool has_midi_bypass () const; 121 bool has_midi_thru () const; inplace()122 bool inplace () const { return ! _no_inplace; } 123 124 bool is_channelstrip () const; 125 126 void set_input_map (uint32_t, ChanMapping); 127 void set_output_map (uint32_t, ChanMapping); 128 void set_thru_map (ChanMapping); 129 bool reset_map (bool emit = true); configured()130 bool configured () const { return _configured; } 131 132 // these are ports visible on the outside 133 ChanCount output_streams() const; 134 ChanCount input_streams() const; 135 ChanCount internal_streams() const; // with side-chain 136 137 // actual ports of all plugins. 138 // n * natural_i/o or result of reconfigurable i/o 139 ChanCount internal_output_streams() const; 140 ChanCount internal_input_streams() const; 141 142 // a single plugin's internal i/o 143 ChanCount natural_output_streams() const; 144 ChanCount natural_input_streams() const; 145 146 /** plugin ports marked as sidechain */ 147 ChanCount sidechain_input_pins() const; 148 149 /** Plugin-Insert IO sidechain ports */ sidechain_input_ports()150 ChanCount sidechain_input_ports() const { 151 if (_sidechain) { 152 return _sidechain->input ()->n_ports (); 153 } else { 154 return ChanCount (); 155 } 156 } 157 required_buffers()158 const ChanCount& required_buffers () const { return _required_buffers; } preset_out()159 const ChanCount& preset_out () const { return _preset_out; } 160 161 // allow to override output_streams(), implies "Custom Mode" 162 163 // only the owning route may call these (with process lock held) 164 // route is not a friend class, it owns us 165 bool set_count (uint32_t num); 166 void set_sinks (const ChanCount&); // reconfigurable I/O ONLY 167 void set_outputs (const ChanCount&); 168 void set_strict_io (bool b); 169 void set_custom_cfg (bool b); 170 bool set_preset_out (const ChanCount&); 171 bool add_sidechain (uint32_t n_audio = 1, uint32_t n_midi = 0); 172 bool del_sidechain (); 173 void update_sidechain_name (); sidechain()174 boost::shared_ptr<SideChain> sidechain () const { return _sidechain; } 175 // end C++ class slavery! 176 get_count()177 uint32_t get_count () const { return _plugins.size(); } strict_io()178 bool strict_io () const { return _strict_io; } custom_cfg()179 bool custom_cfg () const { return _custom_cfg; } 180 181 bool can_support_io_configuration (const ChanCount& in, ChanCount& out); 182 bool configure_io (ChanCount in, ChanCount out); 183 184 bool has_no_inputs() const; 185 bool has_no_audio_inputs() const; 186 187 bool is_instrument () const; 188 189 bool has_output_presets ( 190 ChanCount in = ChanCount (DataType::MIDI, 1), 191 ChanCount out = ChanCount (DataType::AUDIO, 2) 192 ); 193 194 void realtime_handle_transport_stopped (); 195 void realtime_locate (bool); 196 void monitoring_changed (); 197 198 bool load_preset (Plugin::PresetRecord); 199 200 bool provides_stats () const; 201 bool get_stats (PBD::microseconds_t& min, PBD::microseconds_t& max, double& avg, double& dev) const; 202 void clear_stats (); 203 204 /** A control that manipulates a plugin parameter (control port). */ 205 struct PluginControl : public AutomationControl 206 { 207 PluginControl (PluginInsert* p, 208 const Evoral::Parameter& param, 209 const ParameterDescriptor& desc, 210 boost::shared_ptr<AutomationList> list=boost::shared_ptr<AutomationList>()); 211 212 double get_value (void) const; 213 void catch_up_with_external_value (double val); 214 XMLNode& get_state(); 215 std::string get_user_string() const; 216 217 private: 218 PluginInsert* _plugin; 219 void actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override); 220 }; 221 222 /** A control that manipulates a plugin property (message). */ 223 struct PluginPropertyControl : public AutomationControl 224 { 225 PluginPropertyControl (PluginInsert* p, 226 const Evoral::Parameter& param, 227 const ParameterDescriptor& desc, 228 boost::shared_ptr<AutomationList> list=boost::shared_ptr<AutomationList>()); 229 230 double get_value (void) const; 231 XMLNode& get_state(); 232 protected: 233 void actually_set_value (double value, PBD::Controllable::GroupControlDisposition); 234 235 private: 236 PluginInsert* _plugin; 237 Variant _value; 238 }; 239 240 boost::shared_ptr<Plugin> plugin(uint32_t num=0) const { 241 if (num < _plugins.size()) { 242 return _plugins[num]; 243 } else { 244 return _plugins[0]; // we always have one 245 } 246 } 247 248 samplecnt_t plugin_latency () const; 249 has_sidechain()250 bool has_sidechain () const { 251 return _sidechain ? true : false; 252 } 253 sidechain_input()254 boost::shared_ptr<IO> sidechain_input () const { 255 if (_sidechain) { 256 return _sidechain->input (); 257 } 258 return boost::shared_ptr<IO> (); 259 } 260 261 PluginType type () const; 262 263 boost::shared_ptr<ReadOnlyControl> control_output (uint32_t) const; 264 265 std::string describe_parameter (Evoral::Parameter param); 266 267 samplecnt_t signal_latency () const; 268 269 boost::shared_ptr<Plugin> get_impulse_analysis_plugin(); 270 271 void collect_signal_for_analysis (samplecnt_t nframes); 272 strict_io_configured()273 bool strict_io_configured () const { 274 return _match.strict_io; 275 } 276 splitting()277 bool splitting () const { 278 return _match.method == Split; 279 } 280 configured_io(ChanCount & in,ChanCount & out)281 void configured_io (ChanCount &in, ChanCount &out) const { 282 in = _configured_in; 283 out = _configured_out; 284 } 285 286 PBD::Signal2<void,BufferSet*, BufferSet*> AnalysisDataGathered; 287 PBD::Signal0<void> PluginIoReConfigure; 288 PBD::Signal0<void> PluginMapChanged; 289 PBD::Signal0<void> PluginConfigChanged; 290 291 /** Enumeration of the ways in which we can match our insert's 292 * IO to that of the plugin(s). 293 */ 294 enum MatchingMethod { 295 Impossible, ///< we can't 296 Delegate, ///< we are delegating to the plugin, and it can handle it 297 NoInputs, ///< plugin has no inputs, so anything goes 298 ExactMatch, ///< our insert's inputs are the same as the plugin's 299 Replicate, ///< we have multiple instances of the plugin 300 Split, ///< we copy one of our insert's inputs to multiple plugin inputs 301 Hide, ///< we `hide' some of the plugin's inputs by feeding them silence 302 }; 303 304 /** Description of how we can match our plugin's IO to our own insert IO */ 305 struct Match { MatchMatch306 Match () : method (Impossible), plugins (0), strict_io (false), custom_cfg (false) {} 307 Match (MatchingMethod m, int32_t p, 308 bool strict = false, bool custom = false, ChanCount h = ChanCount ()) methodMatch309 : method (m), plugins (p), hide (h), strict_io (strict), custom_cfg (custom) {} 310 311 MatchingMethod method; ///< method to employ 312 int32_t plugins; ///< number of copies of the plugin that we need 313 ChanCount hide; ///< number of channels to hide 314 bool strict_io; ///< force in == out 315 bool custom_cfg; ///< custom config (if not strict) 316 }; 317 318 protected: 319 XMLNode& state (); 320 321 private: 322 /* disallow copy construction */ 323 PluginInsert (const PluginInsert&); 324 325 void parameter_changed_externally (uint32_t, float); 326 327 void set_parameter (Evoral::Parameter param, float val, sampleoffset_t); 328 329 float default_parameter_value (const Evoral::Parameter& param); 330 331 typedef std::vector<boost::shared_ptr<Plugin> > Plugins; 332 Plugins _plugins; 333 334 boost::shared_ptr<SideChain> _sidechain; 335 uint32_t _sc_playback_latency; 336 uint32_t _sc_capture_latency; 337 uint32_t _plugin_signal_latency; 338 339 boost::weak_ptr<Plugin> _impulseAnalysisPlugin; 340 341 samplecnt_t _signal_analysis_collect_nsamples; 342 samplecnt_t _signal_analysis_collect_nsamples_max; 343 344 BufferSet _signal_analysis_inputs; 345 BufferSet _signal_analysis_outputs; 346 347 FixedDelay _delaybuffers; 348 349 ChanCount _configured_in; 350 ChanCount _configured_internal; // with side-chain 351 ChanCount _configured_out; 352 ChanCount _custom_out; 353 ChanCount _custom_sinks; 354 ChanCount _preset_out; 355 ChanCount _cached_sidechain_pins; 356 ChanCount _required_buffers; 357 358 bool _configured; 359 bool _no_inplace; 360 bool _strict_io; 361 bool _custom_cfg; 362 bool _maps_from_state; 363 bool _mapping_changed; 364 365 Match private_can_support_io_configuration (ChanCount const &, ChanCount &) const; 366 Match internal_can_support_io_configuration (ChanCount const &, ChanCount &) const; 367 Match automatic_can_support_io_configuration (ChanCount const &, ChanCount &) const; 368 369 /** details of the match currently being used */ 370 Match _match; 371 372 /* ordered map [plugin instance ID] => ARDOUR::ChanMapping 373 * TODO: consider replacing with boost::flat_map<> or std::vector<>. 374 */ 375 #if defined(_MSC_VER) /* && (_MSC_VER < 1900) 376 * Regarding the note (below) it was initially 377 * thought that this got fixed in VS2015 - but 378 * in fact it's still faulty (JE - Feb 2021) */ 379 /* Use the older (heap based) mapping for early versions of MSVC. 380 * In fact it might be safer to use this for all MSVC builds - as 381 * our StackAllocator class depends on 'boost::aligned_storage' 382 * which is known to be troublesome with Visual C++ :- 383 * https://www.boost.org/doc/libs/1_65_0/libs/type_traits/doc/html/boost_typetraits/reference/aligned_storage.html 384 */ 385 class PinMappings : public std::map <uint32_t, ARDOUR::ChanMapping> 386 #else 387 class PinMappings : public std::map <uint32_t, ARDOUR::ChanMapping, std::less<uint32_t>, PBD::StackAllocator<std::pair<const uint32_t, ARDOUR::ChanMapping>, 4> > 388 #endif 389 { 390 public: 391 /* this emulates C++11's std::map::at() 392 * return mapping for given plugin instance */ p(const uint32_t i)393 inline ARDOUR::ChanMapping const& p (const uint32_t i) const { 394 #ifndef NDEBUG 395 const_iterator x = find (i); 396 assert (x != end ()); 397 return x->second; 398 #else 399 return find(i)->second; 400 #endif 401 } 402 }; 403 404 PinMappings _in_map; 405 PinMappings _out_map; 406 ChanMapping _thru_map; // out-idx <= in-idx 407 408 void automate_and_run (BufferSet& bufs, samplepos_t start, samplepos_t end, double speed, pframes_t nframes); 409 void connect_and_run (BufferSet& bufs, samplepos_t start, samplecnt_t end, double speed, pframes_t nframes, samplecnt_t offset, bool with_auto); 410 void bypass (BufferSet& bufs, pframes_t nframes); 411 void inplace_silence_unconnected (BufferSet&, const PinMappings&, samplecnt_t nframes, samplecnt_t offset) const; 412 413 void create_automatable_parameters (); 414 void control_list_automation_state_changed (Evoral::Parameter, AutoState); 415 void set_parameter_state_2X (const XMLNode& node, int version); 416 void set_control_ids (const XMLNode&, int version); 417 void update_control_values (const XMLNode&, int version); 418 419 void enable_changed (); 420 void bypassable_changed (); 421 422 bool sanitize_maps (); 423 bool check_inplace (); 424 void mapping_changed (); 425 426 boost::shared_ptr<Plugin> plugin_factory (boost::shared_ptr<Plugin>); 427 void add_plugin (boost::shared_ptr<Plugin>); 428 void plugin_removed (boost::weak_ptr<Plugin>); 429 430 void add_sidechain_from_xml (const XMLNode& node, int version); 431 432 void start_touch (uint32_t param_id); 433 void end_touch (uint32_t param_id); 434 435 void latency_changed (); 436 bool _latency_changed; 437 uint32_t _bypass_port; 438 bool _inverted_bypass_enable; 439 440 typedef std::map<uint32_t, boost::shared_ptr<ReadOnlyControl> >CtrlOutMap; 441 CtrlOutMap _control_outputs; 442 443 void preset_load_set_value (uint32_t, float); 444 445 PBD::TimingStats _timing_stats; 446 GATOMIC_QUAL gint _stat_reset; 447 GATOMIC_QUAL gint _flush; 448 }; 449 450 } // namespace ARDOUR 451 452 std::ostream& operator<<(std::ostream& o, const ARDOUR::PluginInsert::Match& m); 453 454 #endif /* __ardour_plugin_insert_h__ */ 455