+ Framework: eliminate a compiler warning
[calf.git] / src / calf / giface.h
blobeda0a258fe87cf5926f8f14ea6e87a950130cea2
1 /* Calf DSP Library
2 * Common plugin interface definitions (shared between LADSPA/LV2/DSSI/standalone).
4 * Copyright (C) 2007 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., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, USA.
21 #ifndef __CALF_GIFACE_H
22 #define __CALF_GIFACE_H
24 #include <stdint.h>
25 #include <stdlib.h>
26 #include <pthread.h>
27 #include <exception>
28 #include <string>
29 #include "primitives.h"
30 #include "preset.h"
32 namespace osctl {
33 struct osc_client;
36 namespace calf_plugins {
38 enum {
39 MAX_SAMPLE_RUN = 256
42 /// Values ORed together for flags field in parameter_properties
43 enum parameter_flags
45 PF_TYPEMASK = 0x000F, ///< bit mask for type
46 PF_FLOAT = 0x0000, ///< any float value
47 PF_INT = 0x0001, ///< integer value (still represented as float)
48 PF_BOOL = 0x0002, ///< bool value (usually >=0.5f is treated as TRUE, which is inconsistent with LV2 etc. which treats anything >0 as TRUE)
49 PF_ENUM = 0x0003, ///< enum value (min, min+1, ..., max, only guaranteed to work when min = 0)
50 PF_ENUM_MULTI = 0x0004, ///< SET / multiple-choice
51 PF_STRING = 0x0005, ///< see: http://lv2plug.in/docs/index.php?title=String_port
53 PF_SCALEMASK = 0xF0, ///< bit mask for scale
54 PF_SCALE_DEFAULT = 0x00, ///< no scale given
55 PF_SCALE_LINEAR = 0x10, ///< linear scale
56 PF_SCALE_LOG = 0x20, ///< log scale
57 PF_SCALE_GAIN = 0x30, ///< gain = -96dB..0 or -inf dB
58 PF_SCALE_PERC = 0x40, ///< percent
59 PF_SCALE_QUAD = 0x50, ///< quadratic scale (decent for some gain/amplitude values)
60 PF_SCALE_LOG_INF = 0x60, ///< log scale + +inf (FAKE_INFINITY)
62 PF_CTLMASK = 0x0F00, ///< bit mask for control type
63 PF_CTL_DEFAULT = 0x0000, ///< try to figure out automatically
64 PF_CTL_KNOB = 0x0100, ///< knob
65 PF_CTL_FADER = 0x0200, ///< fader (slider)
66 PF_CTL_TOGGLE = 0x0300, ///< toggle button
67 PF_CTL_COMBO = 0x0400, ///< combo box
68 PF_CTL_RADIO = 0x0500, ///< radio button
69 PF_CTL_BUTTON = 0x0600, ///< push button
70 PF_CTL_METER = 0x0700, ///< volume meter
71 PF_CTL_LED = 0x0800, ///< light emitting diode
73 PF_CTLOPTIONS = 0x00F000, ///< bit mask for control (widget) options
74 PF_CTLO_HORIZ = 0x001000, ///< horizontal version of the control (unused)
75 PF_CTLO_VERT = 0x002000, ///< vertical version of the control (unused)
76 PF_CTLO_LABEL = 0x004000, ///< add a text display to the control (meters only)
77 PF_CTLO_REVERSE = 0x008000, ///< use VU_MONOCHROME_REVERSE mode (meters only)
79 PF_PROP_NOBOUNDS = 0x010000, ///< no epp:hasStrictBounds
80 PF_PROP_EXPENSIVE = 0x020000, ///< epp:expensive, may trigger expensive calculation
81 PF_PROP_OUTPUT_GAIN=0x050000, ///< epp:outputGain + skip epp:hasStrictBounds
82 PF_PROP_OUTPUT = 0x080000, ///< output port
83 PF_PROP_OPTIONAL = 0x100000, ///< connection optional
84 PF_PROP_GRAPH = 0x200000, ///< add graph
85 PF_PROP_MSGCONTEXT= 0x400000, ///< message context
87 PF_UNITMASK = 0xFF000000, ///< bit mask for units \todo reduce to use only 5 bits
88 PF_UNIT_DB = 0x01000000, ///< decibels
89 PF_UNIT_COEF = 0x02000000, ///< multiply-by factor
90 PF_UNIT_HZ = 0x03000000, ///< Hertz
91 PF_UNIT_SEC = 0x04000000, ///< second
92 PF_UNIT_MSEC = 0x05000000, ///< millisecond
93 PF_UNIT_CENTS = 0x06000000, ///< cents (1/100 of a semitone, 1/1200 of an octave)
94 PF_UNIT_SEMITONES = 0x07000000,///< semitones
95 PF_UNIT_BPM = 0x08000000, ///< beats per minute
96 PF_UNIT_DEG = 0x09000000, ///< degrees
97 PF_UNIT_NOTE = 0x0A000000, ///< MIDI note number
98 PF_UNIT_RPM = 0x0B000000, ///< revolutions per minute
101 /// A fake infinity value (because real infinity may break some hosts)
102 #define FAKE_INFINITY (65536.0 * 65536.0)
103 /// Check for infinity (with appropriate-ish tolerance)
104 #define IS_FAKE_INFINITY(value) (fabs(value-FAKE_INFINITY) < 1.0)
106 /// Information record about plugin's menu command
107 struct plugin_command_info
109 const char *label; ///< short command name / label
110 const char *name; ///< human-readable command name
111 const char *description; ///< description (for status line etc.)
114 /// Range, default value, flags and names for a parameter
115 struct parameter_properties
117 /// default value
118 float def_value;
119 /// minimum value
120 float min;
121 /// maximum value
122 float max;
123 /// 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
124 float step;
125 /// logical OR of parameter_flags
126 uint32_t flags;
127 /// for PF_ENUM: array of text values (from min to max step 1), otherwise NULL
128 const char **choices;
129 /// parameter label (for use in LV2 label field etc.)
130 const char *short_name;
131 /// parameter human-readable name
132 const char *name;
133 /// convert from [0, 1] range to [min, max] (applying scaling)
134 float from_01(double value01) const;
135 /// convert from [min, max] to [0, 1] range (applying reverse scaling)
136 double to_01(float value) const;
137 /// stringify (in sensible way)
138 std::string to_string(float value) const;
139 /// get required width (for reserving GUI space)
140 int get_char_count() const;
141 /// get increment step based on step value (if specified) and other factors
142 float get_increment() const;
145 struct cairo_iface
147 virtual void set_source_rgba(float r, float g, float b, float a = 1.f) = 0;
148 virtual void set_line_width(float width) = 0;
149 virtual ~cairo_iface() {}
152 struct progress_report_iface
154 virtual void report_progress(float percentage, const std::string &message) = 0;
155 virtual ~progress_report_iface() {}
158 /// 'provides live line graph values' interface
159 struct line_graph_iface
161 /// Obtain subindex'th graph of parameter 'index'
162 /// @param index parameter/graph number (usually tied to particular plugin control port)
163 /// @param subindex graph number (there may be multiple overlaid graphs for one parameter, eg. for monosynth 2x12dB filters)
164 /// @param data buffer for normalized output values
165 /// @param points number of points to fill
166 /// @param context cairo context to adjust (for multicolour graphs etc.)
167 /// @retval true graph data was returned; subindex+1 graph may or may not be available
168 /// @retval false graph data was not returned; subindex+1 graph does not exist either
169 virtual bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) { return false; }
171 /// Obtain subindex'th dot of parameter 'index'
172 /// @param index parameter/dot number (usually tied to particular plugin control port)
173 /// @param subindex dot number (there may be multiple dots graphs for one parameter)
174 virtual bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) { return false; }
176 /// Obtain subindex'th dot of parameter 'index'
177 /// @param index parameter/dot number (usually tied to particular plugin control port)
178 /// @param subindex dot number (there may be multiple dots graphs for one parameter)
179 virtual bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) { return false; }
181 /// Obtain subindex'th static graph of parameter index (static graphs are only dependent on parameter value, not plugin state)
182 /// @param index parameter/graph number (usually tied to particular plugin control port)
183 /// @param subindex graph number (there may be multiple overlaid graphs for one parameter, eg. for monosynth 2x12dB filters)
184 /// @param value parameter value to pick the graph for
185 /// @param data buffer for normalized output values
186 /// @param points number of points to fill
187 /// @param context cairo context to adjust (for multicolour graphs etc.)
188 /// @retval true graph data was returned; subindex+1 graph may or may not be available
189 /// @retval false graph data was not returned; subindex+1 graph does not exist either
190 virtual bool get_static_graph(int index, int subindex, float value, float *data, int points, cairo_iface *context) { return false; }
192 /// Standard destructor to make compiler happy
193 virtual ~line_graph_iface() {}
196 /// 'may receive configure variables' interface
197 struct send_configure_iface
199 /// Called to set configure variable
200 /// @param key variable name
201 /// @param value variable content
202 virtual void send_configure(const char *key, const char *value) = 0;
204 virtual ~send_configure_iface() {}
207 struct plugin_command_info;
209 /// General information about the plugin - @todo XXXKF lacks the "new" id-label-name triple
210 struct ladspa_plugin_info
212 /// LADSPA ID
213 uint32_t unique_id;
214 /// plugin short name (camel case)
215 const char *label;
216 /// plugin human-readable name
217 const char *name;
218 /// maker (author)
219 const char *maker;
220 /// copyright notice
221 const char *copyright;
222 /// plugin type for LRDF/LV2
223 const char *plugin_type;
226 /// An interface returning metadata about a plugin
227 struct plugin_metadata_iface
229 /// @return plugin long name
230 virtual const char *get_name() = 0;
231 /// @return plugin LV2 label
232 virtual const char *get_id() = 0;
233 /// @return plugin human-readable label
234 virtual const char *get_label() = 0;
235 /// @return total number of parameters
236 virtual int get_param_count() = 0;
237 /// Return custom XML
238 virtual const char *get_gui_xml() = 0;
239 /// @return number of audio inputs
240 virtual int get_input_count()=0;
241 /// @return number of audio outputs
242 virtual int get_output_count()=0;
243 /// @return true if plugin can work in hard-realtime conditions
244 virtual bool is_rt_capable()=0;
245 /// @return true if plugin has MIDI input
246 virtual bool get_midi()=0;
247 /// @return true if plugin has MIDI input
248 virtual bool requires_midi()=0;
249 /// @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)
250 virtual int get_param_port_offset() = 0;
251 /// @return line_graph_iface if any
252 virtual line_graph_iface *get_line_graph_iface() = 0;
253 /// @return NULL-terminated list of menu commands
254 virtual plugin_command_info *get_commands() { return NULL; }
255 /// @return description structure for given parameter
256 virtual parameter_properties *get_param_props(int param_no) = 0;
257 /// @return retrieve names of audio ports (@note control ports are named in parameter_properties, not here)
258 virtual const char **get_port_names() = 0;
259 /// @return description structure for the plugin
260 virtual const ladspa_plugin_info &get_plugin_info() = 0;
261 /// is a given parameter a control voltage?
262 virtual bool is_cv(int param_no) = 0;
263 /// is the given parameter non-interpolated?
264 virtual bool is_noisy(int param_no) = 0;
265 /// does the plugin require message context? (or DSSI configure) may be slow
266 virtual bool requires_message_context() = 0;
267 /// does the plugin require string port extension? (or DSSI configure) may be slow
268 virtual bool requires_string_ports() = 0;
269 /// add all message context parameter numbers to the ports vector
270 virtual void get_message_context_parameters(std::vector<int> &ports) = 0;
272 /// Do-nothing destructor to silence compiler warning
273 virtual ~plugin_metadata_iface() {}
276 /// Interface for host-GUI-plugin interaction (should be really split in two, but ... meh)
277 struct plugin_ctl_iface: public virtual plugin_metadata_iface
279 /// @return value of given parameter
280 virtual float get_param_value(int param_no) = 0;
281 /// Set value of given parameter
282 virtual void set_param_value(int param_no, float value) = 0;
283 /// Load preset with given number
284 virtual bool activate_preset(int bank, int program) = 0;
285 /// @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)
286 virtual float get_level(unsigned int port)=0;
287 /// Execute menu command with given number
288 virtual void execute(int cmd_no)=0;
289 /// Set a configure variable on a plugin
290 virtual char *configure(const char *key, const char *value) { return NULL; }
291 /// Send all configure variables set within a plugin to given destination (which may be limited to only those that plugin understands)
292 virtual void send_configures(send_configure_iface *)=0;
293 /// Restore all state (parameters and configure vars) to default values - implemented in giface.cpp
294 virtual void clear_preset();
295 /// Do-nothing destructor to silence compiler warning
296 virtual ~plugin_ctl_iface() {}
299 struct plugin_list_info_iface;
301 /// Get a list of all "large" (effect/synthesizer) plugins
302 extern void get_all_plugins(std::vector<plugin_metadata_iface *> &plugins);
303 /// Get a list of all "small" (module) plugins
304 extern void get_all_small_plugins(plugin_list_info_iface *plii);
305 /// Load and strdup a text file with GUI definition
306 extern const char *load_gui_xml(const std::string &plugin_id);
308 /// Empty implementations for plugin functions. Note, that functions aren't virtual, because they're called via the particular
309 /// subclass (flanger_audio_module etc) via template wrappers (ladspa_wrapper<> etc), not via base class pointer/reference
310 template<class Metadata>
311 class audio_module: public Metadata
313 public:
314 typedef Metadata metadata_type;
316 progress_report_iface *progress_report;
318 audio_module() {
319 progress_report = NULL;
322 /// Handle MIDI Note On
323 inline void note_on(int note, int velocity) {}
324 /// Handle MIDI Note Off
325 inline void note_off(int note, int velocity) {}
326 /// Handle MIDI Program Change
327 inline void program_change(int program) {}
328 /// Handle MIDI Control Change
329 inline void control_change(int controller, int value) {}
330 /// Handle MIDI Pitch Bend
331 /// @param value pitch bend value (-8192 to 8191, defined as in MIDI ie. 8191 = 200 ct by default)
332 inline void pitch_bend(int value) {}
333 /// Called when params are changed (before processing)
334 inline void params_changed() {}
335 /// LADSPA-esque activate function, except it is called after ports are connected, not before
336 inline void activate() {}
337 /// LADSPA-esque deactivate function
338 inline void deactivate() {}
339 /// Set sample rate for the plugin
340 inline void set_sample_rate(uint32_t sr) { }
341 /// Execute menu command with given number
342 inline void execute(int cmd_no) {}
343 /// DSSI configure call
344 virtual char *configure(const char *key, const char *value) { return NULL; }
345 /// Send all understood configure vars
346 inline void send_configures(send_configure_iface *sci) {}
347 /// Reset parameter values for epp:trigger type parameters (ones activated by oneshot push button instead of check box)
348 inline void params_reset() {}
349 /// Called after instantiating (after all the feature pointers are set - including interfaces like progress_report_iface)
350 inline void post_instantiate() {}
351 /// Handle 'message context' port message
352 /// @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)
353 inline uint32_t message_run(const void *valid_ports, void *output_ports) {
354 fprintf(stderr, "ERROR: message run not implemented\n");
355 return 0;
359 extern bool check_for_message_context_ports(parameter_properties *parameters, int count);
360 extern bool check_for_string_ports(parameter_properties *parameters, int count);
362 #if USE_DSSI
364 enum line_graph_item
366 LGI_END = 0,
367 LGI_GRAPH,
368 LGI_SUBGRAPH,
369 LGI_LEGEND,
370 LGI_DOT,
371 LGI_END_ITEM,
372 LGI_SET_RGBA,
373 LGI_SET_WIDTH,
376 /// A class to send status updates via OSC
377 struct dssi_feedback_sender
379 /// OSC client object used to send updates
380 osctl::osc_client *client;
381 /// Background thread handle
382 pthread_t bg_thread;
383 /// Quit flag (used to terminate the thread)
384 bool quit;
385 /// Indices of graphs to send
386 std::vector<int> indices;
387 /// Source for the graph data (interface to marshal)
388 calf_plugins::line_graph_iface *graph;
390 dssi_feedback_sender(const char *URI, line_graph_iface *_graph, calf_plugins::parameter_properties *props, int num_params);
391 void update();
392 ~dssi_feedback_sender();
394 #endif
396 /// Metadata base class template, to provide default versions of interface functions
397 template<class Metadata>
398 class plugin_metadata: public virtual plugin_metadata_iface
400 public:
401 static const char *port_names[];
402 static parameter_properties param_props[];
403 static ladspa_plugin_info plugin_info;
405 // These below are stock implementations based on enums and static members in Metadata classes
406 // they may be overridden to provide more interesting functionality
408 const char *get_name() { return Metadata::impl_get_name(); }
409 const char *get_id() { return Metadata::impl_get_id(); }
410 const char *get_label() { return Metadata::impl_get_label(); }
411 int get_input_count() { return Metadata::in_count; }
412 int get_output_count() { return Metadata::out_count; }
413 int get_param_count() { return Metadata::param_count; }
414 bool get_midi() { return Metadata::support_midi; }
415 bool requires_midi() { return Metadata::require_midi; }
416 bool is_rt_capable() { return Metadata::rt_capable; }
417 line_graph_iface *get_line_graph_iface() { return dynamic_cast<line_graph_iface *>(this); }
418 int get_param_port_offset() { return Metadata::in_count + Metadata::out_count; }
419 const char *get_gui_xml() { static const char *data_ptr = calf_plugins::load_gui_xml(get_id()); return data_ptr; }
420 plugin_command_info *get_commands() { return NULL; }
421 parameter_properties *get_param_props(int param_no) { return &param_props[param_no]; }
422 const char **get_port_names() { return port_names; }
423 bool is_cv(int param_no) { return true; }
424 bool is_noisy(int param_no) { return false; }
425 const ladspa_plugin_info &get_plugin_info() { return plugin_info; }
426 bool requires_message_context() { return check_for_message_context_ports(param_props, Metadata::param_count); }
427 bool requires_string_ports() { return check_for_string_ports(param_props, Metadata::param_count); }
428 void get_message_context_parameters(std::vector<int> &ports) {
429 for (int i = 0; i < get_param_count(); ++i) {
430 if (get_param_props(i)->flags & PF_PROP_MSGCONTEXT)
431 ports.push_back(i);
436 /// A class for delegating metadata implementation to a "remote" metadata class.
437 /// Used for GUI wrappers that cannot have a dependency on actual classes,
438 /// and which instead take an "external" metadata object pointer, obtained
439 /// through get_all_plugins.
440 class plugin_metadata_proxy: public virtual plugin_metadata_iface
442 public:
443 plugin_metadata_iface *impl;
444 public:
445 plugin_metadata_proxy(plugin_metadata_iface *_impl) { impl = _impl; }
446 const char *get_name() { return impl->get_name(); }
447 const char *get_id() { return impl->get_id(); }
448 const char *get_label() { return impl->get_label(); }
449 int get_input_count() { return impl->get_input_count(); }
450 int get_output_count() { return impl->get_output_count(); }
451 int get_param_count() { return impl->get_param_count(); }
452 bool get_midi() { return impl->get_midi(); }
453 bool requires_midi() { return impl->requires_midi(); }
454 bool is_rt_capable() { return impl->is_rt_capable(); }
455 line_graph_iface *get_line_graph_iface() { return impl->get_line_graph_iface(); }
456 int get_param_port_offset() { return impl->get_param_port_offset(); }
457 const char *get_gui_xml() { return impl->get_gui_xml(); }
458 plugin_command_info *get_commands() { return impl->get_commands(); }
459 parameter_properties *get_param_props(int param_no) { return impl->get_param_props(param_no); }
460 const char **get_port_names() { return impl->get_port_names(); }
461 bool is_cv(int param_no) { return impl->is_cv(param_no); }
462 bool is_noisy(int param_no) { return impl->is_noisy(param_no); }
463 const ladspa_plugin_info &get_plugin_info() { return impl->get_plugin_info(); }
464 bool requires_message_context() { return impl->requires_message_context(); }
465 bool requires_string_ports() { return impl->requires_string_ports(); }
466 void get_message_context_parameters(std::vector<int> &ports) { impl->get_message_context_parameters(ports); }
469 #define CALF_PORT_NAMES(name) template<> const char *::plugin_metadata<name##_metadata>::port_names[]
470 #define CALF_PORT_PROPS(name) template<> parameter_properties plugin_metadata<name##_metadata>::param_props[]
471 #define CALF_PLUGIN_INFO(name) template<> calf_plugins::ladspa_plugin_info plugin_metadata<name##_metadata>::plugin_info
472 #define PLUGIN_NAME_ID_LABEL(name, id, label) \
473 static const char *impl_get_name() { return name; } \
474 static const char *impl_get_id() { return id; } \
475 static const char *impl_get_label() { return label; } \
478 extern const char *calf_copyright_info;
482 #endif