Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

734 lines
20KB

  1. /*
  2. * DAZ - Digital Audio with Zero dependencies
  3. * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
  4. * Copyright (C) 2013 Harry van Haaren <harryhaaren@gmail.com>
  5. * Copyright (C) 2013 Jonathan Moore Liles <male@tuxfamily.org>
  6. *
  7. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  8. * or without fee is hereby granted, provided that the above copyright notice and this
  9. * permission notice appear in all copies.
  10. *
  11. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  12. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  13. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  14. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  15. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  16. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #ifndef DAZ_PLUGIN_H_INCLUDED
  19. #define DAZ_PLUGIN_H_INCLUDED
  20. #include "daz-common.h"
  21. #ifdef __cplusplus
  22. extern "C" {
  23. #endif
  24. /*!
  25. * @defgroup DAZPluginAPI
  26. * @{
  27. */
  28. /* ------------------------------------------------------------------------------------------------------------
  29. * Plugin Categories */
  30. /*!
  31. * @defgroup PluginCategories Plugin Categories
  32. *
  33. * A small list of pre-defined plugin categories.
  34. *
  35. * Plugins should provide at least one of these basic categories, terminating with ":".
  36. * They can use their own custom categories as well, as long as they are lowercase and contain ASCII characters only.
  37. * @{
  38. */
  39. /*!
  40. * A synthesizer or generator.
  41. */
  42. #define PLUGIN_CATEGORY_SYNTH ":synth"
  43. /*!
  44. * A delay or reverberator.
  45. */
  46. #define PLUGIN_CATEGORY_DELAY ":delay"
  47. /*!
  48. * An equalizer.
  49. */
  50. #define PLUGIN_CATEGORY_EQ ":eq"
  51. /*!
  52. * A filter.
  53. */
  54. #define PLUGIN_CATEGORY_FILTER ":filter"
  55. /*!
  56. * A distortion plugin.
  57. */
  58. #define PLUGIN_CATEGORY_DISTORTION ":distortion"
  59. /*!
  60. * A 'dynamic' plugin (amplifier, compressor, gate, etc).
  61. */
  62. #define PLUGIN_CATEGORY_DYNAMICS ":dynamics"
  63. /*!
  64. * A 'modulator' plugin (chorus, flanger, phaser, etc).
  65. */
  66. #define PLUGIN_CATEGORY_MODULATOR ":modulator"
  67. /*!
  68. * An 'utility' plugin (analyzer, converter, mixer, etc).
  69. */
  70. #define PLUGIN_CATEGORY_UTILITY ":utility"
  71. /** @} */
  72. /* ------------------------------------------------------------------------------------------------------------
  73. * Plugin Features */
  74. /*!
  75. * @defgroup PluginFeatures Plugin Features
  76. *
  77. * A list of plugin features or hints.
  78. *
  79. * Plugins should list all features it supports, terminating with ":"
  80. * Custom features are allowed, as long as they are lowercase and contain ASCII characters only.
  81. * The host will decide if it can load the plugin or not based on this information.
  82. * @{
  83. */
  84. /*!
  85. * Supports buffer size changes on-the-fly.
  86. *
  87. * If unset, the host will re-initiate the plugin when the buffer size changes.
  88. */
  89. #define PLUGIN_FEATURE_BUFFER_SIZE_CHANGES ":buffer_size_changes"
  90. /*!
  91. * Supports sample rate changes on-the-fly.
  92. *
  93. * If unset, the host will re-initiate the plugin when the sample rate changes.
  94. */
  95. #define PLUGIN_FEATURE_SAMPLE_RATE_CHANGES ":sample_rate_changes"
  96. /*!
  97. * Needs non-realtime idle() function regularly.
  98. *
  99. * This can be used by plugins that need a non-realtime thread to do work.
  100. * The host will call PluginDescriptor::idle() at regular intervals.
  101. * The plugin may acquire a lock, but MUST NOT block indefinitely.
  102. *
  103. * Alternatively, the plugin can ask the host for a one-shot idle()
  104. * by using HOST_OPCODE_NEEDS_IDLE.
  105. */
  106. #define PLUGIN_FEATURE_IDLE ":idle"
  107. /*!
  108. * Supports get_state() and set_state() functions.
  109. */
  110. #define PLUGIN_FEATURE_STATE ":state"
  111. /*!
  112. * Uses get_time_info() host function.
  113. */
  114. #define PLUGIN_FEATURE_TIME ":time"
  115. /*!
  116. * Uses write_event() host function.
  117. */
  118. #define PLUGIN_FEATURE_WRITE_EVENT ":write_event"
  119. /*!
  120. * Uses send_ui_msg() host function.
  121. */
  122. #define PLUGIN_FEATURE_SEND_MSG ":sendmsg"
  123. /** @} */
  124. /* ------------------------------------------------------------------------------------------------------------
  125. * Plugin Supports */
  126. /*!
  127. * TODO - this needs a better name...
  128. *
  129. * @defgroup PluginSupports Plugin Supports
  130. *
  131. * A list of plugin supported MIDI events.
  132. *
  133. * Plugins should list all the MIDI message types it supports, terminating with ":".
  134. * @{
  135. */
  136. /*!
  137. * Handles MIDI programs internally instead of host-exposed/exported.
  138. *
  139. * When this is set, the host will not try to map MIDI program changes into
  140. * plugin exported programs by sending MidiProgramEvent, but will send MidiEvent directly.
  141. *
  142. * @see MidiProgram, MidiProgramEvent
  143. */
  144. #define PLUGIN_SUPPORTS_PROGRAM_CHANGES ":program"
  145. /*!
  146. * Supports control changes (0xB0).
  147. *
  148. * @note:
  149. * The plugin MUST NEVER change exposed parameters on its own.
  150. * If the plugin wants to map a MIDI control change message to a parameter
  151. * it can do so by reporting it in the meta-data, which the host will read.
  152. */
  153. #define PLUGIN_SUPPORTS_CONTROL_CHANGES ":control"
  154. /*!
  155. * Supports channel pressure (0xD0).
  156. */
  157. #define PLUGIN_SUPPORTS_CHANNEL_PRESSURE ":pressure"
  158. /*!
  159. * Supports note aftertouch (0xA0).
  160. */
  161. #define PLUGIN_SUPPORTS_NOTE_AFTERTOUCH ":aftertouch"
  162. /*!
  163. * Supports pitchbend (0xE0).
  164. */
  165. #define PLUGIN_SUPPORTS_PITCHBEND ":pitchbend"
  166. /*!
  167. * Supports all-sound-off and all-notes-off events.
  168. *
  169. * When this is not set, the host might want to send various note-off events to silence the plugin.
  170. */
  171. #define PLUGIN_SUPPORTS_ALL_SOUND_OFF ":allsoundoff"
  172. /** @} */
  173. /* ------------------------------------------------------------------------------------------------------------
  174. * Parameter Hints */
  175. /*!
  176. * @defgroup ParameterHints Parameter Hints
  177. *
  178. * List of parameter hints.
  179. *
  180. * < something something >, terminating with ":".
  181. * @{
  182. */
  183. /*!
  184. * Is enabled.
  185. *
  186. * If set the host may show this parameter on its "built-in" dialog.
  187. */
  188. #define PARAMETER_IS_ENABLED ":enabled"
  189. /*!
  190. * Is output.
  191. *
  192. * If this is not set, the parameter should be considered input.
  193. *
  194. * Input parameters are managed by the host and changed by sending a ParameterEvent to the plugin.
  195. * The plugin MUST NEVER change input parameters on its own.
  196. *
  197. * Output parameters are managed by the plugin.
  198. * Most plugins that have output parameters should set PLUGIN_FEATURE_WRITE_EVENT,
  199. * see PARAMETER_IS_RTSAFE for details.
  200. */
  201. #define PARAMETER_IS_OUTPUT ":output"
  202. /*!
  203. * Is not real time safe.
  204. *
  205. * For input parameters:
  206. * When set, the host MUST ONLY use PluginDescriptor::non_rt_event().
  207. * When not set (default), the host MUST ONLY use in-process events to change this parameter.
  208. *
  209. * For output parameters:
  210. * When set, the host will call PluginDescriptor::get_parameter_value() where the plugin is allowed to lock.
  211. * When not set (default), the plugin must send a ParameterEvent to the host every time the value changes.
  212. *
  213. * @see PLUGIN_FEATURE_RTSAFE
  214. */
  215. #define PARAMETER_IS_NON_RT ":non_rt"
  216. /*!
  217. * Values are boolean (always at minimum or maximum values).
  218. */
  219. #define PARAMETER_IS_BOOLEAN ":boolean"
  220. /*!
  221. * Values are integer.
  222. */
  223. #define PARAMETER_IS_INTEGER ":integer"
  224. /*!
  225. * Values are logarithmic.
  226. */
  227. #define PARAMETER_IS_LOGARITHMIC ":logarithmic"
  228. /*!
  229. * Needs sample rate to work.
  230. *
  231. * The parameter value and ranges are multiplied by sample rate on usage
  232. * and divided by sample rate on save.
  233. */
  234. #define PARAMETER_USES_SAMPLE_RATE ":sample_rate"
  235. /*!
  236. * Uses scalepoints to define internal values in a meaningful way.
  237. */
  238. #define PARAMETER_USES_SCALEPOINTS ":scalepoints"
  239. /*!
  240. * Uses custom text for displaying its value.
  241. *
  242. * @see get_parameter_text()
  243. */
  244. #define PARAMETER_USES_CUSTOM_TEXT ":custom_text"
  245. /** @} */
  246. /* ------------------------------------------------------------------------------------------------------------
  247. * Default Parameter Ranges */
  248. /*!
  249. * @defgroup DefaultParameterRanges Default Parameter Ranges
  250. *
  251. * Default values for parameter range steps.
  252. * @{
  253. */
  254. #define PARAMETER_RANGE_DEFAULT_STEP 0.01f
  255. #define PARAMETER_RANGE_DEFAULT_STEP_SMALL 0.0001f
  256. #define PARAMETER_RANGE_DEFAULT_STEP_LARGE 0.1f
  257. /** @} */
  258. /* ------------------------------------------------------------------------------------------------------------
  259. * Event Types */
  260. /*!
  261. * @defgroup EventTypes Event Types
  262. *
  263. * List of supported event types.
  264. *
  265. * The types are mapped into mapped_value_t by the host.
  266. * @see PluginHostDescriptor::map_value()
  267. * @{
  268. */
  269. /*!
  270. * Generic MIDI event.
  271. *
  272. * Realtime MIDI events are always used in-process,
  273. * while non realtime ones should be used in PluginDescriptor::non_rt_event().
  274. *
  275. * @see MidiEvent
  276. */
  277. #define EVENT_TYPE_MIDI "midi"
  278. /*!
  279. * Midi program event.
  280. *
  281. * Used in-process only.
  282. *
  283. * @see MidiProgramEvent
  284. */
  285. #define EVENT_TYPE_MIDI_PROGRAM "midiprogram"
  286. /*!
  287. * Parameter event.
  288. *
  289. * There are some rules for parameter events,
  290. * please see PARAMETER_IS_RTSAFE.
  291. *
  292. * @see ParameterEvent
  293. */
  294. #define EVENT_TYPE_PARAMETER "parameter"
  295. /*!
  296. * Time information event.
  297. *
  298. * Used in-process only.
  299. *
  300. * @see TimeInfoEvent
  301. */
  302. #define EVENT_TYPE_TIME "time"
  303. /** @} */
  304. /* ------------------------------------------------------------------------------------------------------------
  305. * Host Dispatcher Opcodes */
  306. /*!
  307. * @defgroup HostDispatcherOpcodes Host Dispatcher Opcodes
  308. *
  309. * Opcodes dispatched by the plugin to report and request information from the host.
  310. *
  311. * The opcodes are mapped into MappedValue by the host.
  312. * @see HostDescriptor::dispatcher()
  313. * @{
  314. */
  315. /*!
  316. * Tell the host to call idle() as soon as possible (once), uses nothing.
  317. */
  318. #define HOST_OPCODE_NEEDS_IDLE "needsIdle"
  319. /*!
  320. * Tell the host to update parameter @a index.
  321. * Uses index with -1 for all.
  322. */
  323. #define HOST_OPCODE_UPDATE_PARAMETER "updateParameter"
  324. /*!
  325. * Tell the host to update midi-program @a index.
  326. * Uses index with -1 for all.
  327. * May also use value for channel. <= FIXME: maybe remove this bit, but for synths it's nice to have
  328. */
  329. #define HOST_OPCODE_UPDATE_MIDI_PROGRAM "updateMidiProgram"
  330. /*!
  331. * Tell the host to reload all parameters data, uses nothing.
  332. */
  333. #define HOST_OPCODE_RELOAD_PARAMETERS "reloadParameters"
  334. /*!
  335. * Tell the host to reload all midi-programs data, uses nothing.
  336. */
  337. #define HOST_OPCODE_RELOAD_MIDI_PROGRAMS "reloadMidiPrograms"
  338. /*!
  339. * Tell the host to reload everything all the plugin, uses nothing.
  340. */
  341. #define HOST_OPCODE_RELOAD_ALL "reloadAll"
  342. /** @} */
  343. /* ------------------------------------------------------------------------------------------------------------
  344. * Plugin Dispatcher Opcodes */
  345. /*!
  346. * @defgroup PluginDispatcherOpcodes Plugin Dispatcher Opcodes
  347. *
  348. * Opcodes dispatched by the host to report changes to the plugin.
  349. *
  350. * The opcodes are mapped into MappedValue by the host.
  351. * @see PluginDescriptor::dispatcher()
  352. * @{
  353. */
  354. /*!
  355. * Message received, uses ptr as char*.
  356. */
  357. #define PLUGIN_OPCODE_MSG_RECEIVED "msgReceived"
  358. /*!
  359. * Audio buffer size changed, uses value, returns 1 if supported.
  360. * @see PluginHostDescriptor::buffer_size
  361. */
  362. #define PLUGIN_OPCODE_BUFFER_SIZE_CHANGED "bufferSizeChanged"
  363. /*!
  364. * Audio sample rate changed, uses opt, returns 1 if supported.
  365. * @see PluginHostDescriptor::sample_rate
  366. */
  367. #define PLUGIN_OPCODE_SAMPLE_RATE_CHANGED "sampleRateChanged"
  368. /*!
  369. * Offline mode changed, uses value (0=off, 1=on).
  370. * @see PluginHostDescriptor::is_offline
  371. */
  372. #define PLUGIN_OPCODE_OFFLINE_CHANGED "offlineChanged"
  373. /** @} */
  374. /* ------------------------------------------------------------------------------------------------------------
  375. * Base types */
  376. /*!
  377. * Audio sample type.
  378. */
  379. typedef float audio_sample_t;
  380. /*!
  381. * Opaque plugin handle.
  382. */
  383. typedef void* PluginHandle;
  384. /*!
  385. * Opaque host handle.
  386. */
  387. typedef void* PluginHostHandle;
  388. /*!
  389. * Parameter scale point.
  390. */
  391. typedef struct {
  392. const char* label; /*!< not null */
  393. float value;
  394. } ParameterScalePoint;
  395. /*!
  396. * Parameter ranges.
  397. */
  398. typedef struct {
  399. float def;
  400. float min;
  401. float max;
  402. #if 1
  403. float step;
  404. float stepSmall;
  405. float stepLarge;
  406. #endif
  407. } ParameterRanges;
  408. /*!
  409. * Parameter.
  410. */
  411. typedef struct {
  412. const char* hints; /*!< not null, @see ParameterHints */
  413. const char* name; /*!< not null */
  414. const char* symbol; /*!< not null */
  415. const char* unit; /*!< can be null */
  416. ParameterRanges ranges;
  417. uint32_t scalePointCount;
  418. ParameterScalePoint* scalePoints;
  419. } Parameter;
  420. /*!
  421. * MIDI Program.
  422. */
  423. typedef struct {
  424. uint32_t bank;
  425. uint32_t program;
  426. const char* name;
  427. } MidiProgram;
  428. /* ------------------------------------------------------------------------------------------------------------
  429. * TimeInfo related types */
  430. /*!
  431. * Bar-Beat-Tick information.
  432. *
  433. * @note this is the same data provided by JACK
  434. */
  435. typedef struct {
  436. bool valid;
  437. int32_t bar; /*!< current bar */
  438. int32_t beat; /*!< current beat-within-bar */
  439. int32_t tick; /*!< current tick-within-beat */
  440. double barStartTick;
  441. float beatsPerBar; /*!< time signature "numerator" */
  442. float beatType; /*!< time signature "denominator" */
  443. double ticksPerBeat;
  444. double beatsPerMinute;
  445. } TimeInfoBBT;
  446. /*!
  447. * Time information.
  448. */
  449. typedef struct {
  450. bool playing;
  451. uint64_t frame;
  452. uint64_t usecs;
  453. TimeInfoBBT bbt;
  454. } TimeInfo;
  455. /* ------------------------------------------------------------------------------------------------------------
  456. * Event related types */
  457. /*!
  458. * Generic event.
  459. */
  460. typedef struct {
  461. mapped_value_t type; /*!< Type of event. @see EventTypes */
  462. uint32_t frame; /*!< Frame offset since the beginning of process() */
  463. } Event;
  464. /*!
  465. * MIDI event.
  466. */
  467. typedef struct {
  468. Event e;
  469. uint8_t port;
  470. uint8_t size;
  471. uint8_t data[4];
  472. } MidiEvent;
  473. /*!
  474. * MIDI Program event.
  475. *
  476. * This is a special type of event that tells to plugin to switch MIDI program.
  477. * The plugin is allowed to change its parameter values, the host should request them afterwards if needed.
  478. *
  479. * If the plugin has PLUGIN_SUPPORTS_PROGRAM_CHANGES set, the host must never use event type.
  480. *
  481. * @see MidiProgram
  482. */
  483. typedef struct {
  484. Event e;
  485. uint8_t channel; /* used only in synths */
  486. uint32_t bank;
  487. uint32_t program;
  488. } MidiProgramEvent;
  489. /*!
  490. * Parameter event.
  491. */
  492. typedef struct {
  493. Event e;
  494. uint32_t index;
  495. float value;
  496. } ParameterEvent;
  497. /*!
  498. * Time information event.
  499. */
  500. typedef struct {
  501. Event e;
  502. bool playing;
  503. uint64_t frame;
  504. TimeInfoBBT bbt;
  505. } TimeInfoEvent;
  506. /* ------------------------------------------------------------------------------------------------------------
  507. * Plugin Host Descriptor */
  508. /*!
  509. * PluginHostDescriptor
  510. */
  511. typedef struct {
  512. PluginHostHandle handle;
  513. /*!
  514. * Previously used plugin version, may be NULL.
  515. */
  516. const char* pluginVersion;
  517. /*!
  518. * Current audio buffer size.
  519. */
  520. uint32_t buffer_size;
  521. /*!
  522. * Current audio sample rate.
  523. */
  524. double sample_rate;
  525. /*!
  526. * Wherever the host is currently processing offline.
  527. FIXME: what is this for?
  528. */
  529. bool is_offline;
  530. /* NOTE: NOT allowed during process()
  531. * probably better if only allowed during instantiate() */
  532. mapped_value_t (*map_value)(PluginHostHandle handle, const char* valueStr);
  533. const char* (*unmap_value)(PluginHostHandle handle, mapped_value_t value);
  534. /* plugin must set "time" feature to use this
  535. * NOTE: only allowed during process() */
  536. const TimeInfo* (*get_time_info)(PluginHostHandle handle);
  537. /* plugin must set "writeevent" feature to use this
  538. * NOTE: only allowed during process() */
  539. bool (*write_event)(PluginHostHandle handle, const Event* event);
  540. /* plugin must set "sendmsg" feature to use this
  541. * NOTE: only allowed during idle() or non_rt_event() */
  542. bool (*send_ui_msg)(PluginHostHandle handle, const void* data, size_t size);
  543. /* uses HostDispatcherOpcodes : FIXME - use "const void* value" only? */
  544. int * (*dispatcher)(PluginHostHandle handle, mapped_value_t opcode, int32_t index, int32_t value, void* ptr, float opt);
  545. } PluginHostDescriptor;
  546. /* ------------------------------------------------------------------------------------------------------------
  547. * Plugin Descriptor */
  548. /*!
  549. * PluginDescriptor
  550. */
  551. typedef struct {
  552. /* descriptor metadata. the required set of metadata is: (TODO review)
  553. const char* metadata[] = {
  554. "api version", "1", // <-- MUST be version of API used when plugin was built.
  555. "author", "Bob Cat, MD",
  556. "display name", "Best EQ Evar",
  557. "organization", "bobcat",
  558. "uuid", "org.bobcat.best_eq_evar_v1", // <-- MUST be universally unique for this plugin major version. Only allowed punctuation is "." and "_".
  559. "copyright", "copyright 2013 foobar inc",
  560. "interface version", "1", // <-- MUST be incremented if the available parameters have changed in a not-backwards compatible way!
  561. "dsp version", "0", // <-- MUST be incremented if the DSP algorithm has been changed in any audible way from previous version.
  562. "description", "15 Band FFT EQ",
  563. "documentation", "This eq blah blah blah",
  564. "website", "http://bobcat.com/plugins/best_eq_evar/buyitnow",
  565. "provides", "foo:bar", // <-- features this plugin provides
  566. "requires", "bar", // <-- features this plugin requires
  567. NULL // <-- MUST be NULL terminated!
  568. };
  569. */
  570. const char* const* metadata;
  571. PluginHandle (*instantiate)(const PluginHostDescriptor* host);
  572. void (*cleanup)(PluginHandle handle);
  573. uint32_t (*get_parameter_count)(PluginHandle handle);
  574. const Parameter* (*get_parameter_info)(PluginHandle handle, uint32_t index);
  575. float (*get_parameter_value)(PluginHandle handle, uint32_t index);
  576. const char* (*get_parameter_text)(PluginHandle handle, uint32_t index, float value); /* only used if parameter hint "customtext" is set */
  577. uint32_t (*get_midi_program_count)(PluginHandle handle);
  578. const MidiProgram* (*get_midi_program_info)(PluginHandle handle, uint32_t index);
  579. /* only used if "idle" feature is set, or HOST_OPCODE_NEEDS_IDLE was triggered (for one-shot).
  580. * NOTE: although it's a non-realtime function, it will probably still not be called from the host main thread */
  581. void (*idle)(PluginHandle handle);
  582. /* NOTE: host will never call this while process() is running
  583. * FIXME: the above statement requires a lot of unnecessary house keeping in the host */
  584. void (*non_rt_event)(PluginHandle handle, const Event* event);
  585. /* only used if "state" feature is set */
  586. char* (*get_state)(PluginHandle handle);
  587. void (*set_state)(PluginHandle handle, const char* data);
  588. void (*activate)(PluginHandle handle);
  589. void (*deactivate)(PluginHandle handle);
  590. void (*process)(PluginHandle handle, audio_sample_t** inBuffer, audio_sample_t** outBuffer, uint32_t frames, const Event* events, uint32_t eventCount);
  591. /* uses PluginDispatcherOpcodes : FIXME - use "const void* value" only? */
  592. int * (*dispatcher)(PluginHandle handle, mapped_value_t opcode, int32_t index, int32_t value, void* ptr, float opt);
  593. } PluginDescriptor;
  594. /* ------------------------------------------------------------------------------------------------------------
  595. * Plugin entry point */
  596. /*!
  597. * Plugin entry point function used by the plugin.
  598. */
  599. DAZ_SYMBOL_EXPORT
  600. const PluginDescriptor* daz_get_plugin_descriptor(uint32_t index);
  601. /*!
  602. * Plugin entry point function used by the host.
  603. */
  604. typedef const PluginDescriptor* (*daz_get_plugin_descriptor_fn)(uint32_t index);
  605. /* ------------------------------------------------------------------------------------------------------------ */
  606. /** @} */
  607. #ifdef __cplusplus
  608. } /* extern "C" */
  609. #endif
  610. #endif /* DAZ_PLUGIN_H_INCLUDED */