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., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02111-1307, USA.
21 #ifndef __CALF_GIFACE_H
22 #define __CALF_GIFACE_H
29 #include "primitives.h"
36 namespace calf_plugins
{
42 /// Values ORed together for flags field in parameter_properties
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
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
125 /// logical OR of parameter_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
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;
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 /// Return which graphs need to be redrawn and which can be cached for later reuse
193 /// @param generation 0 (at start) or the last value returned by the function (corresponds to a set of input values)
194 /// @param subindex_graph First graph that has to be redrawn (because it depends on values that might have changed)
195 /// @param subindex_dot First dot that has to be redrawn
196 /// @param subindex_gridline First gridline/legend that has to be redrawn
197 /// @retval Current generation (to pass when calling the function next time); if different than passed generation value, call the function again to retrieve which graph offsets should be put into cache
198 virtual int get_changed_offsets(int generation
, int &subindex_graph
, int &subindex_dot
, int &subindex_gridline
) { subindex_graph
= subindex_dot
= subindex_gridline
= 0; return 0; }
200 /// Standard destructor to make compiler happy
201 virtual ~line_graph_iface() {}
204 enum table_column_type
206 TCT_UNKNOWN
, ///< guard invalid type
207 TCT_FLOAT
, ///< float value (encoded as C locale string)
208 TCT_ENUM
, ///< enum value (see: 'values' array in table_column_info) - encoded as string base 10 representation of integer
209 TCT_STRING
, ///< string value (encoded as C-escaped string)
210 TCT_OBJECT
, ///< external object, encoded as string
211 TCT_LABEL
, ///< string value (encoded as C-escaped string)
215 struct table_column_info
217 const char *name
; ///< column label
218 table_column_type type
; ///< column data type
219 float min
; ///< minimum value (for float)
220 float max
; ///< maximum value (for float and enum)
221 float def_value
; ///< default value (for float and enum)
222 const char **values
; ///< NULL unless a TCT_ENUM, where it represents a NULL-terminated list of choices
225 /// 'has string parameters containing tabular data' interface
226 struct table_edit_iface
228 /// retrieve the table layout for specific parameter
229 virtual const table_column_info
*get_table_columns(int param
) = 0;
231 /// return the current number of rows
232 virtual uint32_t get_table_rows(int param
) = 0;
234 /// retrieve data item from the plugin
235 virtual std::string
get_cell(int param
, int column
) { return calf_utils::i2s(param
)+":"+calf_utils::i2s(column
); }
237 /// set data item to the plugin
238 virtual void set_cell(int param
, int column
, const std::string
&src
, std::string
&error
) { error
.clear(); }
240 /// return a line graph interface for a specific parameter/column (unused for now)
241 virtual line_graph_iface
*get_graph_iface(int param
, int column
) { return NULL
; }
243 /// return an editor name for a specific grid cell (unused for now - I don't even know how editors be implemented)
244 virtual const char *get_cell_editor(int param
, int column
) { return NULL
; }
246 virtual ~table_edit_iface() {}
249 /// 'may receive configure variables' interface
250 struct send_configure_iface
252 /// Called to set configure variable
253 /// @param key variable name
254 /// @param value variable content
255 virtual void send_configure(const char *key
, const char *value
) = 0;
257 virtual ~send_configure_iface() {}
260 /// 'may receive new status values' interface
261 struct send_updates_iface
263 /// Called to set configure variable
264 /// @param key variable name
265 /// @param value variable content
266 virtual void send_status(const char *key
, const char *value
) = 0;
268 virtual ~send_updates_iface() {}
271 struct plugin_command_info
;
273 /// General information about the plugin - @todo XXXKF lacks the "new" id-label-name triple
274 struct ladspa_plugin_info
278 /// plugin short name (camel case)
280 /// plugin human-readable name
285 const char *copyright
;
286 /// plugin type for LRDF/LV2
287 const char *plugin_type
;
290 /// An interface returning metadata about a plugin
291 struct plugin_metadata_iface
293 /// @return plugin long name
294 virtual const char *get_name() = 0;
295 /// @return plugin LV2 label
296 virtual const char *get_id() = 0;
297 /// @return plugin human-readable label
298 virtual const char *get_label() = 0;
299 /// @return total number of parameters
300 virtual int get_param_count() = 0;
301 /// Return custom XML
302 virtual const char *get_gui_xml() = 0;
303 /// @return number of audio inputs
304 virtual int get_input_count()=0;
305 /// @return number of audio outputs
306 virtual int get_output_count()=0;
307 /// @return true if plugin can work in hard-realtime conditions
308 virtual bool is_rt_capable()=0;
309 /// @return true if plugin has MIDI input
310 virtual bool get_midi()=0;
311 /// @return true if plugin has MIDI input
312 virtual bool requires_midi()=0;
313 /// @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)
314 virtual int get_param_port_offset() = 0;
315 /// @return line_graph_iface if any
316 virtual line_graph_iface
*get_line_graph_iface() = 0;
317 /// @return table_edit_iface if any
318 virtual table_edit_iface
*get_table_edit_iface() = 0;
319 /// @return NULL-terminated list of menu commands
320 virtual plugin_command_info
*get_commands() { return NULL
; }
321 /// @return description structure for given parameter
322 virtual parameter_properties
*get_param_props(int param_no
) = 0;
323 /// @return retrieve names of audio ports (@note control ports are named in parameter_properties, not here)
324 virtual const char **get_port_names() = 0;
325 /// @return description structure for the plugin
326 virtual const ladspa_plugin_info
&get_plugin_info() = 0;
327 /// is a given parameter a control voltage?
328 virtual bool is_cv(int param_no
) = 0;
329 /// is the given parameter non-interpolated?
330 virtual bool is_noisy(int param_no
) = 0;
331 /// does the plugin require message context? (or DSSI configure) may be slow
332 virtual bool requires_message_context() = 0;
333 /// does the plugin require string port extension? (or DSSI configure) may be slow
334 virtual bool requires_string_ports() = 0;
335 /// add all message context parameter numbers to the ports vector
336 virtual void get_message_context_parameters(std::vector
<int> &ports
) = 0;
338 /// Do-nothing destructor to silence compiler warning
339 virtual ~plugin_metadata_iface() {}
342 /// Interface for host-GUI-plugin interaction (should be really split in two, but ... meh)
343 struct plugin_ctl_iface
: public virtual plugin_metadata_iface
345 /// @return value of given parameter
346 virtual float get_param_value(int param_no
) = 0;
347 /// Set value of given parameter
348 virtual void set_param_value(int param_no
, float value
) = 0;
349 /// Load preset with given number
350 virtual bool activate_preset(int bank
, int program
) = 0;
351 /// @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)
352 virtual float get_level(unsigned int port
)=0;
353 /// Execute menu command with given number
354 virtual void execute(int cmd_no
)=0;
355 /// Set a configure variable on a plugin
356 virtual char *configure(const char *key
, const char *value
) { return NULL
; }
357 /// Send all configure variables set within a plugin to given destination (which may be limited to only those that plugin understands)
358 virtual void send_configures(send_configure_iface
*)=0;
359 /// Restore all state (parameters and configure vars) to default values - implemented in giface.cpp
360 virtual void clear_preset();
361 /// Call a named function in a plugin - this will most likely be redesigned soon - and never used
362 /// @retval false call has failed, result contains an error message
363 virtual bool blobcall(const char *command
, const std::string
&request
, std::string
&result
) { result
= "Call not supported"; return false; }
364 /// Update status variables changed since last_serial
365 /// @return new last_serial
366 virtual int send_status_updates(send_updates_iface
*sui
, int last_serial
) { return last_serial
; }
367 /// Do-nothing destructor to silence compiler warning
368 virtual ~plugin_ctl_iface() {}
371 struct plugin_list_info_iface
;
373 /// Get a list of all "large" (effect/synthesizer) plugins
374 extern void get_all_plugins(std::vector
<plugin_metadata_iface
*> &plugins
);
375 /// Get a list of all "small" (module) plugins
376 extern void get_all_small_plugins(plugin_list_info_iface
*plii
);
377 /// Load and strdup a text file with GUI definition
378 extern const char *load_gui_xml(const std::string
&plugin_id
);
380 /// Empty implementations for plugin functions. Note, that functions aren't virtual, because they're called via the particular
381 /// subclass (flanger_audio_module etc) via template wrappers (ladspa_wrapper<> etc), not via base class pointer/reference
382 template<class Metadata
>
383 class audio_module
: public Metadata
386 typedef Metadata metadata_type
;
388 progress_report_iface
*progress_report
;
391 progress_report
= NULL
;
394 /// Handle MIDI Note On
395 inline void note_on(int note
, int velocity
) {}
396 /// Handle MIDI Note Off
397 inline void note_off(int note
, int velocity
) {}
398 /// Handle MIDI Program Change
399 inline void program_change(int program
) {}
400 /// Handle MIDI Control Change
401 inline void control_change(int controller
, int value
) {}
402 /// Handle MIDI Pitch Bend
403 /// @param value pitch bend value (-8192 to 8191, defined as in MIDI ie. 8191 = 200 ct by default)
404 inline void pitch_bend(int value
) {}
405 /// Called when params are changed (before processing)
406 inline void params_changed() {}
407 /// LADSPA-esque activate function, except it is called after ports are connected, not before
408 inline void activate() {}
409 /// LADSPA-esque deactivate function
410 inline void deactivate() {}
411 /// Set sample rate for the plugin
412 inline void set_sample_rate(uint32_t sr
) { }
413 /// Execute menu command with given number
414 inline void execute(int cmd_no
) {}
415 /// DSSI configure call
416 virtual char *configure(const char *key
, const char *value
) { return NULL
; }
417 /// Send all understood configure vars (none by default)
418 inline void send_configures(send_configure_iface
*sci
) {}
419 /// Send all supported status vars (none by default)
420 inline int send_status_updates(send_updates_iface
*sui
, int last_serial
) { return last_serial
; }
421 /// Reset parameter values for epp:trigger type parameters (ones activated by oneshot push button instead of check box)
422 inline void params_reset() {}
423 /// Called after instantiating (after all the feature pointers are set - including interfaces like progress_report_iface)
424 inline void post_instantiate() {}
425 /// Handle 'message context' port message
426 /// @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)
427 inline uint32_t message_run(const void *valid_ports
, void *output_ports
) {
428 fprintf(stderr
, "ERROR: message run not implemented\n");
433 extern bool check_for_message_context_ports(parameter_properties
*parameters
, int count
);
434 extern bool check_for_string_ports(parameter_properties
*parameters
, int count
);
450 /// A class to send status updates via OSC
451 struct dssi_feedback_sender
453 /// OSC client object used to send updates
454 osctl::osc_client
*client
;
455 /// Background thread handle
457 /// Quit flag (used to terminate the thread)
459 /// Indices of graphs to send
460 std::vector
<int> indices
;
461 /// Source for the graph data (interface to marshal)
462 calf_plugins::line_graph_iface
*graph
;
464 dssi_feedback_sender(const char *URI
, line_graph_iface
*_graph
, calf_plugins::parameter_properties
*props
, int num_params
);
466 ~dssi_feedback_sender();
470 /// Metadata base class template, to provide default versions of interface functions
471 template<class Metadata
>
472 class plugin_metadata
: public virtual plugin_metadata_iface
475 static const char *port_names
[];
476 static parameter_properties param_props
[];
477 static ladspa_plugin_info plugin_info
;
479 // These below are stock implementations based on enums and static members in Metadata classes
480 // they may be overridden to provide more interesting functionality
482 const char *get_name() { return Metadata::impl_get_name(); }
483 const char *get_id() { return Metadata::impl_get_id(); }
484 const char *get_label() { return Metadata::impl_get_label(); }
485 int get_input_count() { return Metadata::in_count
; }
486 int get_output_count() { return Metadata::out_count
; }
487 int get_param_count() { return Metadata::param_count
; }
488 bool get_midi() { return Metadata::support_midi
; }
489 bool requires_midi() { return Metadata::require_midi
; }
490 bool is_rt_capable() { return Metadata::rt_capable
; }
491 line_graph_iface
*get_line_graph_iface() { return dynamic_cast<line_graph_iface
*>(this); }
492 table_edit_iface
*get_table_edit_iface() { return dynamic_cast<table_edit_iface
*>(this); }
493 int get_param_port_offset() { return Metadata::in_count
+ Metadata::out_count
; }
494 const char *get_gui_xml() { static const char *data_ptr
= calf_plugins::load_gui_xml(get_id()); return data_ptr
; }
495 plugin_command_info
*get_commands() { return NULL
; }
496 parameter_properties
*get_param_props(int param_no
) { return ¶m_props
[param_no
]; }
497 const char **get_port_names() { return port_names
; }
498 bool is_cv(int param_no
) { return true; }
499 bool is_noisy(int param_no
) { return false; }
500 const ladspa_plugin_info
&get_plugin_info() { return plugin_info
; }
501 bool requires_message_context() { return check_for_message_context_ports(param_props
, Metadata::param_count
); }
502 bool requires_string_ports() { return check_for_string_ports(param_props
, Metadata::param_count
); }
503 void get_message_context_parameters(std::vector
<int> &ports
) {
504 for (int i
= 0; i
< get_param_count(); ++i
) {
505 if (get_param_props(i
)->flags
& PF_PROP_MSGCONTEXT
)
511 /// A class for delegating metadata implementation to a "remote" metadata class.
512 /// Used for GUI wrappers that cannot have a dependency on actual classes,
513 /// and which instead take an "external" metadata object pointer, obtained
514 /// through get_all_plugins.
515 class plugin_metadata_proxy
: public virtual plugin_metadata_iface
518 plugin_metadata_iface
*impl
;
520 plugin_metadata_proxy(plugin_metadata_iface
*_impl
) { impl
= _impl
; }
521 const char *get_name() { return impl
->get_name(); }
522 const char *get_id() { return impl
->get_id(); }
523 const char *get_label() { return impl
->get_label(); }
524 int get_input_count() { return impl
->get_input_count(); }
525 int get_output_count() { return impl
->get_output_count(); }
526 int get_param_count() { return impl
->get_param_count(); }
527 bool get_midi() { return impl
->get_midi(); }
528 bool requires_midi() { return impl
->requires_midi(); }
529 bool is_rt_capable() { return impl
->is_rt_capable(); }
530 line_graph_iface
*get_line_graph_iface() { return impl
->get_line_graph_iface(); }
531 table_edit_iface
*get_table_edit_iface() { return impl
->get_table_edit_iface(); }
532 int get_param_port_offset() { return impl
->get_param_port_offset(); }
533 const char *get_gui_xml() { return impl
->get_gui_xml(); }
534 plugin_command_info
*get_commands() { return impl
->get_commands(); }
535 parameter_properties
*get_param_props(int param_no
) { return impl
->get_param_props(param_no
); }
536 const char **get_port_names() { return impl
->get_port_names(); }
537 bool is_cv(int param_no
) { return impl
->is_cv(param_no
); }
538 bool is_noisy(int param_no
) { return impl
->is_noisy(param_no
); }
539 const ladspa_plugin_info
&get_plugin_info() { return impl
->get_plugin_info(); }
540 bool requires_message_context() { return impl
->requires_message_context(); }
541 bool requires_string_ports() { return impl
->requires_string_ports(); }
542 void get_message_context_parameters(std::vector
<int> &ports
) { impl
->get_message_context_parameters(ports
); }
545 #define CALF_PORT_NAMES(name) template<> const char *::plugin_metadata<name##_metadata>::port_names[]
546 #define CALF_PORT_PROPS(name) template<> parameter_properties plugin_metadata<name##_metadata>::param_props[]
547 #define CALF_PLUGIN_INFO(name) template<> calf_plugins::ladspa_plugin_info plugin_metadata<name##_metadata>::plugin_info
548 #define PLUGIN_NAME_ID_LABEL(name, id, label) \
549 static const char *impl_get_name() { return name; } \
550 static const char *impl_get_id() { return id; } \
551 static const char *impl_get_label() { return label; } \
554 extern const char *calf_copyright_info
;