HAAS Stereo Enhancer
[calf.git] / src / calf / giface.h
blobd1ab3f1b8021cf28d494d6ec50c4adb9b0ee27f4
1 /* Calf DSP Library
2 * Common plugin interface definitions (shared between LADSPA/LV2/DSSI/standalone).
4 * Copyright (C) 2007-2010 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02111-1307, USA.
21 #ifndef CALF_GIFACE_H
22 #define CALF_GIFACE_H
24 #include <config.h>
25 #include "primitives.h"
26 #include <complex>
27 #include <exception>
28 #include <string>
29 #include <vector>
30 #include <cairo/cairo.h>
32 namespace osctl {
33 struct osc_client;
36 namespace calf_plugins {
38 enum {
39 MAX_SAMPLE_RUN = 256
42 struct automation_range;
44 /// Values ORed together for flags field in parameter_properties
45 enum parameter_flags
47 PF_TYPEMASK = 0x000F, ///< bit mask for type
48 PF_FLOAT = 0x0000, ///< any float value
49 PF_INT = 0x0001, ///< integer value (still represented as float)
50 PF_BOOL = 0x0002, ///< bool value (usually >=0.5f is treated as TRUE, which is inconsistent with LV2 etc. which treats anything >0 as TRUE)
51 PF_ENUM = 0x0003, ///< enum value (min, min+1, ..., max, only guaranteed to work when min = 0)
52 PF_ENUM_MULTI = 0x0004, ///< SET / multiple-choice
54 PF_SCALEMASK = 0xF0, ///< bit mask for scale
55 PF_SCALE_DEFAULT = 0x00, ///< no scale given
56 PF_SCALE_LINEAR = 0x10, ///< linear scale
57 PF_SCALE_LOG = 0x20, ///< log scale
58 PF_SCALE_GAIN = 0x30, ///< gain = -96dB..0 or -inf dB
59 PF_SCALE_PERC = 0x40, ///< percent
60 PF_SCALE_QUAD = 0x50, ///< quadratic scale (decent for some gain/amplitude values)
61 PF_SCALE_LOG_INF = 0x60, ///< log scale + +inf (FAKE_INFINITY)
63 PF_CTLMASK = 0x0F00, ///< bit mask for control type
64 PF_CTL_DEFAULT = 0x0000, ///< try to figure out automatically
65 PF_CTL_KNOB = 0x0100, ///< knob
66 PF_CTL_FADER = 0x0200, ///< fader (slider)
67 PF_CTL_TOGGLE = 0x0300, ///< toggle button
68 PF_CTL_COMBO = 0x0400, ///< combo box
69 PF_CTL_RADIO = 0x0500, ///< radio button
70 PF_CTL_BUTTON = 0x0600, ///< push button
71 PF_CTL_METER = 0x0700, ///< volume meter
72 PF_CTL_LED = 0x0800, ///< light emitting diode
73 PF_CTL_LABEL = 0x0900, ///< label
75 PF_CTLOPTIONS = 0x00F000, ///< bit mask for control (widget) options
76 PF_CTLO_HORIZ = 0x001000, ///< horizontal version of the control (unused)
77 PF_CTLO_VERT = 0x002000, ///< vertical version of the control (unused)
78 PF_CTLO_LABEL = 0x004000, ///< add a text display to the control (meters only)
79 PF_CTLO_REVERSE = 0x008000, ///< use VU_MONOCHROME_REVERSE mode (meters only)
81 PF_PROP_NOBOUNDS = 0x010000, ///< no epp:hasStrictBounds
82 PF_PROP_EXPENSIVE = 0x020000, ///< epp:expensive, may trigger expensive calculation
83 PF_PROP_OUTPUT_GAIN=0x050000, ///< epp:outputGain + skip epp:hasStrictBounds
84 PF_PROP_OUTPUT = 0x080000, ///< output port
85 PF_PROP_OPTIONAL = 0x100000, ///< connection optional
86 PF_PROP_GRAPH = 0x200000, ///< add graph
88 PF_UNITMASK = 0xFF000000, ///< bit mask for units \todo reduce to use only 5 bits
89 PF_UNIT_DB = 0x01000000, ///< decibels
90 PF_UNIT_COEF = 0x02000000, ///< multiply-by factor
91 PF_UNIT_HZ = 0x03000000, ///< Hertz
92 PF_UNIT_SEC = 0x04000000, ///< second
93 PF_UNIT_MSEC = 0x05000000, ///< millisecond
94 PF_UNIT_CENTS = 0x06000000, ///< cents (1/100 of a semitone, 1/1200 of an octave)
95 PF_UNIT_SEMITONES = 0x07000000,///< semitones
96 PF_UNIT_BPM = 0x08000000, ///< beats per minute
97 PF_UNIT_DEG = 0x09000000, ///< degrees
98 PF_UNIT_NOTE = 0x0A000000, ///< MIDI note number
99 PF_UNIT_RPM = 0x0B000000, ///< revolutions per minute
100 PF_UNIT_SAMPLES = 0x0C000000, ///< samples
102 PF_SYNC_BPM = 0x10000000, ///< sync a bpm setting with the host environment
105 /// A fake infinity value (because real infinity may break some hosts)
106 #define FAKE_INFINITY (65536.0 * 65536.0)
107 /// Check for infinity (with appropriate-ish tolerance)
108 #define IS_FAKE_INFINITY(value) (fabs(value-FAKE_INFINITY) < 1.0)
110 /// Information record about plugin's menu command
111 struct plugin_command_info
113 const char *label; ///< short command name / label
114 const char *name; ///< human-readable command name
115 const char *description; ///< description (for status line etc.)
118 /// Range, default value, flags and names for a parameter
119 struct parameter_properties
121 /// default value
122 float def_value;
123 /// minimum value
124 float min;
125 /// maximum value
126 float max;
127 /// number of steps (for an integer value from 0 to 100 this will be 101; for 0/90/180/270/360 this will be 5), or 0 for continuous
128 float step;
129 /// logical OR of parameter_flags
130 uint32_t flags;
131 /// for PF_ENUM: array of text values (from min to max step 1), otherwise NULL
132 const char **choices;
133 /// parameter label (for use in LV2 label field etc.)
134 const char *short_name;
135 /// parameter human-readable name
136 const char *name;
137 /// convert from [0, 1] range to [min, max] (applying scaling)
138 float from_01(double value01) const;
139 /// convert from [min, max] to [0, 1] range (applying reverse scaling)
140 double to_01(float value) const;
141 /// stringify (in sensible way)
142 std::string to_string(float value) const;
143 /// convert string (from text entry) to value
144 float string_to_value(const char* string) const;
145 /// get required width (for reserving GUI space)
146 int get_char_count() const;
147 /// get increment step based on step value (if specified) and other factors
148 float get_increment() const;
151 struct cairo_iface
153 cairo_t *context;
154 int size_x, size_y, pad_x, pad_y;
155 virtual void set_source_rgba(float r, float g, float b, float a = 1.f) = 0;
156 virtual void set_line_width(float width) = 0;
157 virtual void set_dash(const double *dash, int length) = 0;
158 virtual void draw_label(const char *label, float x, float y, int pos, float margin, float align) = 0;
159 virtual ~cairo_iface() {}
162 class cairo_impl: public calf_plugins::cairo_iface
164 public:
165 cairo_t *context;
166 virtual void set_source_rgba(float r, float g, float b, float a = 1.f) { cairo_set_source_rgba(context, r, g, b, a); }
167 virtual void set_line_width(float width) { cairo_set_line_width(context, width); }
168 virtual void set_dash(const double *dash, int length) { cairo_set_dash(context, dash, length, 0); }
169 virtual void draw_label(const char *label, float x, float y, int pos, float margin, float align) {
170 cairo_text_extents_t extents;
171 cairo_text_extents(context, label, &extents);
172 switch(pos) {
173 case 0:
174 default:
175 // top
176 cairo_move_to(context, x - extents.width / 2, y - margin);
177 break;
178 case 1:
179 // right
180 cairo_move_to(context, x + margin, y + 2);
181 break;
182 case 2:
183 // bottom
184 cairo_move_to(context, x - extents.width / 2, y + margin + extents.height);
185 break;
186 case 3:
187 // left
188 cairo_move_to(context, x - margin - extents.width, y + 2);
189 break;
191 cairo_show_text(context, label);
195 struct progress_report_iface
197 virtual void report_progress(float percentage, const std::string &message) = 0;
198 virtual ~progress_report_iface() {}
201 /// possible bit masks for get_layers
202 enum layers_flags {
203 LG_NONE = 0x000000,
204 LG_CACHE_GRID = 0x000001,
205 LG_REALTIME_GRID = 0x000002,
206 LG_CACHE_GRAPH = 0x000004,
207 LG_REALTIME_GRAPH = 0x000008,
208 LG_CACHE_DOT = 0x000010,
209 LG_REALTIME_DOT = 0x000020,
210 LG_CACHE_MOVING = 0x000040,
211 LG_REALTIME_MOVING = 0x000080
214 /// possible values for get_moving
215 enum moving_directions {
216 LG_MOVING_LEFT = 0x000000,
217 LG_MOVING_RIGHT = 0x000001,
218 LG_MOVING_UP = 0x000002,
219 LG_MOVING_DOWN = 0x000004
222 /// 'provides live line graph values' interface
223 struct line_graph_iface
225 /// Obtain subindex'th graph of parameter 'index'
226 /// @param index parameter/graph number (usually tied to particular plugin control port)
227 /// @param subindex graph number (there may be multiple overlaid graphs for one parameter, eg. for monosynth 2x12dB filters)
228 /// @param phase 0 if in cache phase or 1 if in realtime phase
229 /// @param data buffer for normalized output values
230 /// @param points number of points to fill
231 /// @param context cairo context to adjust (for multicolour graphs etc.)
232 /// @retval true graph data was returned; subindex+1 graph may or may not be available
233 /// @retval false graph data was not returned; subindex+1 graph does not exist either
234 virtual bool get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode = 0) const { return false; }
236 /// Obtain subindex'th moving surface of parameter 'index'
237 /// @param index parameter/dot number (usually tied to particular plugin control port)
238 /// @param subindex mvoing line number (there may be multiple graphs for one parameter)
239 /// @param direction 0 if horizontal or 1 if vertical movement
240 /// @param data buffer for normalized output values
241 /// @param x number of points direction to fill in x
242 /// @param y number of points direction to fill in y
243 virtual bool get_moving(int index, int subindex, int &direction, float *data, int x, int y, int &offset, uint32_t &color) const { return false; }
245 /// Obtain subindex'th dot of parameter 'index'
246 /// @param index parameter/dot number (usually tied to particular plugin control port)
247 /// @param subindex dot number (there may be multiple dots graphs for one parameter)
248 /// @param phase 0 if in cache phase or 1 if in realtime phase
249 virtual bool get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const { return false; }
251 /// Obtain subindex'th dot of parameter 'index'
252 /// @param index parameter/dot number (usually tied to particular plugin control port)
253 /// @param subindex dot number (there may be multiple dots graphs for one parameter)
254 /// @param phase 0 if in cache phase or 1 if in realtime phase
255 virtual bool get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const { return false; }
257 /// Retrun which layers need to be redrawn in the next GTK drawing cycle
258 /// @param index Parameter/graph identifier (usually tied to particular plugin control port)
259 /// @param generation The overall amount of drawing cycles since the last full refresh of all surfaces
260 /// @param layers Bitmask defining the layers to be redrawn (see layers_flags above)
261 /// @retval true there's at least one layer to be redrawn; false nothing to draw in this cycle
262 virtual bool get_layers(int index, int generation, unsigned int &layers) const { return false; }
264 /// Return a label for the crosshairs they are enabled
265 /// @param x Position of the mouse pointer in x direction
266 /// @param y Position of the mouse pointer in y direction
267 /// @param sx Horizontal size of the widget in pixels
268 /// @param sy Vertical size of the widget in pixels
269 virtual std::string get_crosshair_label( int x, int y, int sx, int sy, cairo_iface *context ) const { std::string s = ""; return s; }
271 /// Standard destructor to make compiler happy
272 virtual ~line_graph_iface() {}
275 /// 'provides live line graph values' interface
276 struct phase_graph_iface
278 virtual bool get_phase_graph(float ** _buffer, int *_length, int * _mode, bool * _use_fade, float * _fade, int * _accuracy, bool * _display) const { return false; };
279 virtual ~phase_graph_iface() {}
282 enum table_column_type
284 TCT_UNKNOWN, ///< guard invalid type
285 TCT_FLOAT, ///< float value (encoded as C locale string)
286 TCT_ENUM, ///< enum value (see: 'values' array in table_column_info) - encoded as string base 10 representation of integer
287 TCT_STRING, ///< string value (encoded as C-escaped string)
288 TCT_OBJECT, ///< external object, encoded as string
289 TCT_LABEL, ///< string value (encoded as C-escaped string)
292 /// parameters of
293 struct table_column_info
295 const char *name; ///< column label
296 table_column_type type; ///< column data type
297 float min; ///< minimum value (for float)
298 float max; ///< maximum value (for float and enum)
299 float def_value; ///< default value (for float and enum)
300 const char **values; ///< NULL unless a TCT_ENUM, where it represents a NULL-terminated list of choices
303 /// 'has string parameters containing tabular data' interface
304 struct table_metadata_iface
306 /// retrieve the table layout for specific parameter
307 virtual const table_column_info *get_table_columns() const = 0;
309 /// return the fixed number of rows, or 0 if the number of rows is variable
310 virtual uint32_t get_table_rows() const = 0;
312 virtual ~table_metadata_iface() {}
315 /// 'may receive configure variables' interface
316 struct send_configure_iface
318 /// Called to set configure variable
319 /// @param key variable name
320 /// @param value variable content
321 virtual void send_configure(const char *key, const char *value) = 0;
323 virtual ~send_configure_iface() {}
326 /// 'may receive new status values' interface
327 struct send_updates_iface
329 /// Called to set configure variable
330 /// @param key variable name
331 /// @param value variable content
332 virtual void send_status(const char *key, const char *value) = 0;
334 virtual ~send_updates_iface() {}
337 struct plugin_command_info;
339 /// General information about the plugin - @todo XXXKF lacks the "new" id-label-name triple
340 struct ladspa_plugin_info
342 /// LADSPA ID
343 uint32_t unique_id;
344 /// plugin short name (camel case)
345 const char *label;
346 /// plugin human-readable name
347 const char *name;
348 /// maker (author)
349 const char *maker;
350 /// copyright notice
351 const char *copyright;
352 /// plugin type for LRDF/LV2
353 const char *plugin_type;
356 /// An interface returning metadata about a plugin
357 struct plugin_metadata_iface
359 enum { simulate_stereo_input = true };
360 /// @return plugin long name
361 virtual const char *get_name() const = 0;
362 /// @return plugin LV2 label
363 virtual const char *get_id() const = 0;
364 /// @return plugin human-readable label
365 virtual const char *get_label() const = 0;
366 /// @return total number of parameters
367 virtual int get_param_count() const = 0;
368 /// Return custom XML
369 virtual const char *get_gui_xml() const = 0;
370 /// @return number of audio inputs
371 virtual int get_input_count() const =0;
372 /// @return number of audio outputs
373 virtual int get_output_count() const =0;
374 /// @return number of optional inputs
375 virtual int get_inputs_optional() const =0;
376 /// @return number of optional outputs
377 virtual int get_outputs_optional() const =0;
378 /// @return true if plugin can work in hard-realtime conditions
379 virtual bool is_rt_capable() const =0;
380 /// @return true if plugin has MIDI input
381 virtual bool get_midi() const =0;
382 /// @return true if plugin has MIDI input
383 virtual bool requires_midi() const =0;
384 /// @return port offset of first control (parameter) port (= number of audio inputs + number of audio outputs in all existing plugins as for 1 Aug 2008)
385 virtual int get_param_port_offset() const = 0;
386 /// @return NULL-terminated list of menu commands
387 virtual plugin_command_info *get_commands() const { return NULL; }
388 /// @return description structure for given parameter
389 virtual const parameter_properties *get_param_props(int param_no) const = 0;
390 /// @return retrieve names of audio ports (@note control ports are named in parameter_properties, not here)
391 virtual const char **get_port_names() const = 0;
392 /// @return description structure for the plugin
393 virtual const ladspa_plugin_info &get_plugin_info() const = 0;
394 /// is a given parameter a control voltage?
395 virtual bool is_cv(int param_no) const = 0;
396 /// is the given parameter non-interpolated?
397 virtual bool is_noisy(int param_no) const = 0;
398 /// does the plugin require string port extension? (or DSSI configure) may be slow
399 virtual bool requires_configure() const = 0;
400 /// obtain array of names of configure variables (or NULL is none needed)
401 virtual void get_configure_vars(std::vector<std::string> &names) const { names.clear(); }
402 /// @return table_metadata_iface if any
403 virtual const table_metadata_iface *get_table_metadata_iface(const char *key) const { return NULL; }
404 /// @return whether to auto-connect right input with left input if unconnected
405 virtual bool get_simulate_stereo_input() const = 0;
407 /// Do-nothing destructor to silence compiler warning
408 virtual ~plugin_metadata_iface() {}
411 /// Interface for host-GUI-plugin interaction (should be really split in two, but ... meh)
412 struct plugin_ctl_iface
414 /// @return value of given parameter
415 virtual float get_param_value(int param_no) = 0;
416 /// Set value of given parameter
417 virtual void set_param_value(int param_no, float value) = 0;
418 /// Load preset with given number
419 virtual bool activate_preset(int bank, int program) = 0;
420 /// @return volume level for port'th port (if supported by the implementation, currently only jack_host<Module> implements that by measuring signal level on plugin ports)
421 virtual float get_level(unsigned int port)=0;
422 /// Execute menu command with given number
423 virtual void execute(int cmd_no)=0;
424 /// Set a configure variable on a plugin
425 virtual char *configure(const char *key, const char *value) = 0;
426 /// Send all configure variables set within a plugin to given destination (which may be limited to only those that plugin understands)
427 virtual void send_configures(send_configure_iface *)=0;
428 /// Restore all state (parameters and configure vars) to default values - implemented in giface.cpp
429 virtual void clear_preset();
430 /// Call a named function in a plugin - this will most likely be redesigned soon - and never used
431 /// @retval false call has failed, result contains an error message
432 virtual bool blobcall(const char *command, const std::string &request, std::string &result) { result = "Call not supported"; return false; }
433 /// Update status variables changed since last_serial
434 /// @return new last_serial
435 virtual int send_status_updates(send_updates_iface *sui, int last_serial) = 0;
436 /// Return metadata object
437 virtual const plugin_metadata_iface *get_metadata_iface() const = 0;
438 /// @return line_graph_iface if any
439 virtual const line_graph_iface *get_line_graph_iface() const = 0;
440 /// @return phase_graph_iface if any
441 virtual const phase_graph_iface *get_phase_graph_iface() const = 0;
442 /// @return serial number of last automation write (JACK host only)
443 virtual int get_write_serial(int param_no) { return 0; }
445 /// Add or update parameter automation routing
446 virtual void add_automation(uint32_t source, const automation_range &dest) {}
447 /// Remove parameter automation routing
448 virtual void delete_automation(uint32_t source, int param_no) {}
449 /// Retrieve automation list for a given parameter
450 /// @param param_no parameter to retrieve automation list for, or -1 for all
451 virtual void get_automation(int param_no, std::multimap<uint32_t, automation_range> &dests) {}
452 /// Return the source identifier for the most recently seen control change that could be used for automation
453 virtual uint32_t get_last_automation_source() { return 0xFFFFFFFF; }
454 virtual void send_automation_configures(send_configure_iface *) {}
455 /// Do-nothing destructor to silence compiler warning
456 virtual ~plugin_ctl_iface() {}
459 struct plugin_list_info_iface;
461 /// A class to retrieve and query the list of Calf plugins
462 class plugin_registry
464 public:
465 typedef std::vector<const plugin_metadata_iface *> plugin_vector;
466 private:
467 plugin_vector plugins;
468 plugin_registry();
469 public:
470 /// Get the singleton object.
471 static plugin_registry &instance();
473 /// Get all plugin metadata objects
474 const plugin_vector &get_all() { return plugins; }
475 /// Get single plugin metadata object by URI
476 const plugin_metadata_iface *get_by_uri(const char *URI);
477 /// Get single plugin metadata object by URI
478 const plugin_metadata_iface *get_by_id(const char *id, bool case_sensitive = false);
481 /// Load and strdup a text file with GUI definition
482 extern const char *load_gui_xml(const std::string &plugin_id);
484 /// Interface to audio processing plugins (the real things, not only metadata)
485 struct audio_module_iface
487 /// Handle MIDI Note On
488 virtual void note_on(int channel, int note, int velocity) = 0;
489 /// Handle MIDI Note Off
490 virtual void note_off(int channel, int note, int velocity) = 0;
491 /// Handle MIDI Program Change
492 virtual void program_change(int channel, int program) = 0;
493 /// Handle MIDI Control Change
494 virtual void control_change(int channel, int controller, int value) = 0;
495 /// Handle MIDI Pitch Bend
496 /// @param value pitch bend value (-8192 to 8191, defined as in MIDI ie. 8191 = 200 ct by default)
497 virtual void pitch_bend(int channel, int value) = 0;
498 /// Handle MIDI Channel Pressure
499 /// @param value channel pressure (0 to 127)
500 virtual void channel_pressure(int channel, int value) = 0;
501 /// Called when params are changed (before processing)
502 virtual void params_changed() = 0;
503 /// LADSPA-esque activate function, except it is called after ports are connected, not before
504 virtual void activate() = 0;
505 /// LADSPA-esque deactivate function
506 virtual void deactivate() = 0;
507 /// Set sample rate for the plugin
508 virtual void set_sample_rate(uint32_t sr) = 0;
509 /// Execute menu command with given number
510 virtual void execute(int cmd_no) = 0;
511 /// DSSI configure call, value = NULL = reset to default
512 virtual char *configure(const char *key, const char *value) = 0;
513 /// Send all understood configure vars (none by default)
514 virtual void send_configures(send_configure_iface *sci) = 0;
515 /// Send all supported status vars (none by default)
516 virtual int send_status_updates(send_updates_iface *sui, int last_serial) = 0;
517 /// Reset parameter values for epp:trigger type parameters (ones activated by oneshot push button instead of check box)
518 virtual void params_reset() = 0;
519 /// Called after instantiating (after all the feature pointers are set - including interfaces like progress_report_iface)
520 virtual void post_instantiate(uint32_t sample_rate) = 0;
521 /// Return the arrays of port buffer pointers
522 virtual void get_port_arrays(float **&ins_ptrs, float **&outs_ptrs, float **&params_ptrs) = 0;
523 /// Return metadata object
524 virtual const plugin_metadata_iface *get_metadata_iface() const = 0;
525 /// Set the progress report interface to communicate progress to
526 virtual void set_progress_report_iface(progress_report_iface *iface) = 0;
527 /// Clear a part of output buffers that have 0s at mask; subdivide the buffer so that no runs > MAX_SAMPLE_RUN are fed to process function
528 virtual uint32_t process_slice(uint32_t offset, uint32_t end) = 0;
529 /// The audio processing loop; assumes numsamples <= MAX_SAMPLE_RUN, for larger buffers, call process_slice
530 virtual uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) = 0;
531 /// Message port processing function
532 virtual uint32_t message_run(const void *valid_ports, void *output_ports) = 0;
533 /// @return line_graph_iface if any
534 virtual const line_graph_iface *get_line_graph_iface() const = 0;
535 /// @return phase_graph_iface if any
536 virtual const phase_graph_iface *get_phase_graph_iface() const = 0;
537 virtual ~audio_module_iface() {}
540 /// Empty implementations for plugin functions.
541 template<class Metadata>
542 class audio_module: public Metadata, public audio_module_iface
544 public:
545 typedef Metadata metadata_type;
546 using Metadata::in_count;
547 using Metadata::out_count;
548 using Metadata::param_count;
549 float *ins[Metadata::in_count];
550 float *outs[Metadata::out_count];
551 float *params[Metadata::param_count];
552 bool questionable_data_reported_in;
553 bool questionable_data_reported_out;
555 progress_report_iface *progress_report;
557 audio_module() {
558 progress_report = NULL;
559 memset(ins, 0, sizeof(ins));
560 memset(outs, 0, sizeof(outs));
561 memset(params, 0, sizeof(params));
562 questionable_data_reported_in = false;
563 questionable_data_reported_out = false;
566 /// Handle MIDI Note On
567 void note_on(int channel, int note, int velocity) {}
568 /// Handle MIDI Note Off
569 void note_off(int channel, int note, int velocity) {}
570 /// Handle MIDI Program Change
571 void program_change(int channel, int program) {}
572 /// Handle MIDI Control Change
573 void control_change(int channel, int controller, int value) {}
574 /// Handle MIDI Pitch Bend
575 /// @param value pitch bend value (-8192 to 8191, defined as in MIDI ie. 8191 = 200 ct by default)
576 void pitch_bend(int channel, int value) {}
577 /// Handle MIDI Channel Pressure
578 /// @param value channel pressure (0 to 127)
579 void channel_pressure(int channel, int value) {}
580 /// Called when params are changed (before processing)
581 void params_changed() {}
582 /// LADSPA-esque activate function, except it is called after ports are connected, not before
583 void activate() {}
584 /// LADSPA-esque deactivate function
585 void deactivate() {}
586 /// Set sample rate for the plugin
587 void set_sample_rate(uint32_t sr) { }
588 /// Execute menu command with given number
589 void execute(int cmd_no) {}
590 /// DSSI configure call
591 virtual char *configure(const char *key, const char *value) { return NULL; }
592 /// Send all understood configure vars (none by default)
593 void send_configures(send_configure_iface *sci) {}
594 /// Send all supported status vars (none by default)
595 int send_status_updates(send_updates_iface *sui, int last_serial) { return last_serial; }
596 /// Reset parameter values for epp:trigger type parameters (ones activated by oneshot push button instead of check box)
597 void params_reset() {}
598 /// Called after instantiating (after all the feature pointers are set - including interfaces like progress_report_iface)
599 void post_instantiate(uint32_t) {}
600 /// Handle 'message context' port message
601 /// @arg output_ports pointer to bit array of output port "changed" flags, note that 0 = first audio input, not first parameter (use input_count + output_count)
602 uint32_t message_run(const void *valid_ports, void *output_ports) {
603 fprintf(stderr, "ERROR: message run not implemented\n");
604 return 0;
606 /// Return the array of input port pointers
607 virtual void get_port_arrays(float **&ins_ptrs, float **&outs_ptrs, float **&params_ptrs)
609 ins_ptrs = ins;
610 outs_ptrs = outs;
611 params_ptrs = params;
613 /// Return metadata object
614 virtual const plugin_metadata_iface *get_metadata_iface() const { return this; }
615 /// Set the progress report interface to communicate progress to
616 virtual void set_progress_report_iface(progress_report_iface *iface) { progress_report = iface; }
618 /// utility function: zero port values if mask is 0
619 inline void zero_by_mask(uint32_t mask, uint32_t offset, uint32_t nsamples)
621 for (int i=0; i<Metadata::out_count; i++) {
622 if ((mask & (1 << i)) == 0) {
623 dsp::zero(outs[i] + offset, nsamples);
627 /// utility function: call process, and if it returned zeros in output masks, zero out the relevant output port buffers
628 uint32_t process_slice(uint32_t offset, uint32_t end)
630 bool had_errors = false;
631 for (int i=0; i<Metadata::in_count; ++i) {
632 float *indata = ins[i];
633 if (indata) {
634 float errval = 0;
635 for (uint32_t j = offset; j < end; j++)
637 if (!std::isfinite(indata[j]) || fabs(indata[j]) > 4294967296.0) {
638 errval = indata[j];
639 had_errors = true;
642 if (had_errors && !questionable_data_reported_in) {
643 fprintf(stderr, "Warning: Plugin %s got questionable value %f on its input %d\n", Metadata::get_name(), errval, i);
644 questionable_data_reported_in = true;
648 uint32_t total_out_mask = 0;
649 while(offset < end)
651 uint32_t newend = std::min(offset + MAX_SAMPLE_RUN, end);
652 uint32_t out_mask = !had_errors ? process(offset, newend - offset, -1, -1) : 0;
653 total_out_mask |= out_mask;
654 zero_by_mask(out_mask, offset, newend - offset);
655 offset = newend;
657 for (int i=0; i<Metadata::out_count; ++i) {
658 if (total_out_mask & (1 << i))
660 had_errors = false;
661 float *outdata = outs[i];
662 float errval = 0;
663 for (uint32_t j = offset; j < end; j++)
665 if (!std::isfinite(outdata[j]) || fabs(outdata[j]) > 4294967296.0) {
666 errval = outdata[j];
667 had_errors = true;
670 if (had_errors && !questionable_data_reported_out) {
671 fprintf(stderr, "Warning: Plugin %s generated questionable value %f on its output %d - this is most likely a bug in the plugin!\n", Metadata::get_name(), errval, i);
672 questionable_data_reported_out = true;
674 if (had_errors)
675 dsp::zero(outs[i] + offset, end - offset);
678 return total_out_mask;
680 /// @return line_graph_iface if any
681 virtual const line_graph_iface *get_line_graph_iface() const { return dynamic_cast<const line_graph_iface *>(this); }
682 /// @return phase_graph_iface if any
683 virtual const phase_graph_iface *get_phase_graph_iface() const { return dynamic_cast<const phase_graph_iface *>(this); }
686 #if USE_EXEC_GUI || USE_DSSI
688 enum line_graph_item
690 LGI_END = 0,
691 LGI_GRAPH,
692 LGI_SUBGRAPH,
693 LGI_LEGEND,
694 LGI_DOT,
695 LGI_END_ITEM,
696 LGI_SET_RGBA,
697 LGI_SET_WIDTH,
700 /// A class to send status updates via OSC
701 struct dssi_feedback_sender
703 /// OSC client object used to send updates
704 osctl::osc_client *client;
705 /// Is client shared with something else?
706 bool is_client_shared;
707 /// Quit flag (used to terminate the thread)
708 bool quit;
709 /// Indices of graphs to send
710 std::vector<int> indices;
711 /// Source for the graph data (interface to marshal)
712 const calf_plugins::line_graph_iface *graph;
714 /// Source for the graph data (interface to marshal)
715 const calf_plugins::phase_graph_iface *phase;
717 /// Create using a new client
718 dssi_feedback_sender(const char *URI, const line_graph_iface *_graph);
719 dssi_feedback_sender(osctl::osc_client *_client, const line_graph_iface *_graph);
720 void add_graphs(const calf_plugins::parameter_properties *props, int num_params);
721 void update();
722 ~dssi_feedback_sender();
724 #endif
726 /// Metadata base class template, to provide default versions of interface functions
727 template<class Metadata>
728 class plugin_metadata: public plugin_metadata_iface
730 public:
731 static const char *port_names[];
732 static parameter_properties param_props[];
733 static ladspa_plugin_info plugin_info;
734 typedef plugin_metadata<Metadata> metadata_class;
736 // These below are stock implementations based on enums and static members in Metadata classes
737 // they may be overridden to provide more interesting functionality
739 const char *get_name() const { return Metadata::impl_get_name(); }
740 const char *get_id() const { return Metadata::impl_get_id(); }
741 const char *get_label() const { return Metadata::impl_get_label(); }
742 int get_input_count() const { return Metadata::in_count; }
743 int get_output_count() const { return Metadata::out_count; }
744 int get_inputs_optional() const { return Metadata::ins_optional; }
745 int get_outputs_optional() const { return Metadata::outs_optional; }
746 int get_param_count() const { return Metadata::param_count; }
747 bool get_midi() const { return Metadata::support_midi; }
748 bool requires_midi() const { return Metadata::require_midi; }
749 bool is_rt_capable() const { return Metadata::rt_capable; }
750 int get_param_port_offset() const { return Metadata::in_count + Metadata::out_count; }
751 const char *get_gui_xml() const { static const char *data_ptr = calf_plugins::load_gui_xml(get_id()); return data_ptr; }
752 plugin_command_info *get_commands() const { return NULL; }
753 const parameter_properties *get_param_props(int param_no) const { return &param_props[param_no]; }
754 const char **get_port_names() const { return port_names; }
755 bool is_cv(int param_no) const { return true; }
756 bool is_noisy(int param_no) const { return false; }
757 const ladspa_plugin_info &get_plugin_info() const { return plugin_info; }
758 bool requires_configure() const { return false; }
759 bool get_simulate_stereo_input() const { return Metadata::simulate_stereo_input; }
762 #define CALF_PORT_NAMES(name) template<> const char *::plugin_metadata<name##_metadata>::port_names[]
763 #define CALF_PORT_PROPS(name) template<> parameter_properties plugin_metadata<name##_metadata>::param_props[name##_metadata::param_count + 1]
764 #define CALF_PLUGIN_INFO(name) template<> calf_plugins::ladspa_plugin_info plugin_metadata<name##_metadata>::plugin_info
765 #define PLUGIN_NAME_ID_LABEL(name, id, label) \
766 static const char *impl_get_name() { return name; } \
767 static const char *impl_get_id() { return id; } \
768 static const char *impl_get_label() { return label; } \
770 extern const char *calf_copyright_info;
772 bool get_freq_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context, bool use_frequencies = true, float res = 256, float ofs = 0.4);
774 /// convert amplitude value to normalized grid-ish value
775 static inline float dB_grid(float amp, float res = 256, float ofs = 0.4)
777 return log(amp) * (1.0 / log(res)) + ofs;
780 template<class Fx>
781 static bool get_graph(Fx &fx, int subindex, float *data, int points, float res = 256, float ofs = 0.4)
783 for (int i = 0; i < points; i++)
785 //typedef std::complex<double> cfloat;
786 double freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points);
787 data[i] = dB_grid(fx.freq_gain(subindex, freq), res, ofs);
789 return true;
792 /// convert normalized grid-ish value back to amplitude value
793 static inline float dB_grid_inv(float pos)
795 return pow(256.0, pos - 0.4);
798 /// Line graph interface implementation for frequency response graphs
799 class frequency_response_line_graph: public line_graph_iface
801 public:
802 mutable bool redraw_graph;
803 virtual bool get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
804 virtual bool get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const;
805 virtual bool get_layers(int index, int generation, unsigned int &layers) const;
806 virtual float freq_gain(int index, double freq) const { return 0; };
807 virtual std::string get_crosshair_label( int x, int y, int sx, int sy, cairo_iface *context ) const;
810 /// set drawing color based on channel index (0 or 1)
811 void set_channel_color(cairo_iface *context, int channel, float alpha = 0.6);
812 void set_channel_dash(cairo_iface *context, int channel);
813 void draw_cairo_label(cairo_iface *context, const char *label, float x, float y, int pos, float margin, float align);
815 struct preset_access_iface
817 virtual void store_preset() = 0;
818 virtual void activate_preset(int preset, bool builtin) = 0;
819 virtual ~preset_access_iface() {}
822 /// Implementation of table_metadata_iface providing metadata for mod matrices
823 class mod_matrix_metadata: public table_metadata_iface
825 public:
826 /// Mapping modes
827 enum mapping_mode {
828 map_positive, ///< 0..100%
829 map_bipolar, ///< -100%..100%
830 map_negative, ///< -100%..0%
831 map_squared, ///< x^2
832 map_squared_bipolar, ///< x^2 scaled to -100%..100%
833 map_antisquared, ///< 1-(1-x)^2 scaled to 0..100%
834 map_antisquared_bipolar, ///< 1-(1-x)^2 scaled to -100..100%
835 map_parabola, ///< inverted parabola (peaks at 0.5, then decreases to 0)
836 map_type_count
838 const char **mod_src_names, **mod_dest_names;
840 mod_matrix_metadata(unsigned int _rows, const char **_src_names, const char **_dest_names);
841 virtual const table_column_info *get_table_columns() const;
842 virtual uint32_t get_table_rows() const;
843 /// Return a list of configure variables used by the modulation matrix
844 void get_configure_vars(std::vector<std::string> &names) const;
846 protected:
847 /// Column descriptions for table widget
848 table_column_info table_columns[6];
850 unsigned int matrix_rows;
853 /// Check if a given key is either prefix + rows or prefix + i2s(row) + "," + i2s(column)
854 /// @arg key key to parse
855 /// @arg prefix table prefix (e.g. "modmatrix:")
856 /// @arg is_rows[out] set to true if key == prefix + "rows"
857 /// @arg row[out] if key is of a form: prefix + row + "," + i2s(column), returns row, otherwise returns -1
858 /// @arg column[out] if key is of a form: prefix + row + "," + i2s(column), returns row, otherwise returns -1
859 /// @retval true if this is one of the recognized string forms
860 extern bool parse_table_key(const char *key, const char *prefix, bool &is_rows, int &row, int &column);
862 #if USE_EXEC_GUI
863 class table_via_configure
865 protected:
866 typedef std::pair<int, int> coord;
867 std::vector<table_column_info> columns;
868 std::map<coord, std::string> values;
869 int rows;
870 public:
871 table_via_configure();
872 void configure(const char *key, const char *value);
873 virtual ~table_via_configure();
875 #endif
877 struct automation_range
879 float min_value;
880 float max_value;
881 int param_no;
883 automation_range(float l, float u, int param)
884 : min_value(l)
885 , max_value(u)
886 , param_no(param)
888 void send_configure(const plugin_metadata_iface *metadata, uint32_t from_controller, send_configure_iface *sci);
889 static automation_range *new_from_configure(const plugin_metadata_iface *metadata, const char *key, const char *value, uint32_t &from_controller);
892 struct automation_map: public std::multimap<uint32_t, automation_range>
896 inline float subindex_to_freq(int subindex)
898 float freq = 100;
899 if (subindex < 9)
900 freq = 10 * (subindex + 1);
901 else if (subindex < 18)
902 freq = 100 * (subindex - 9 + 1);
903 else if (subindex < 27)
904 freq = 1000 * (subindex - 18 + 1);
905 else
906 freq = 10000 * (subindex - 27 + 1);
908 return freq;
913 #endif