diff --git a/.gitignore b/.gitignore index 98d69b3f1..d7ced6f9f 100644 --- a/.gitignore +++ b/.gitignore @@ -91,38 +91,38 @@ src/dist/ *build-*Release/ # ZynAddSubFX UI -source/modules/carla_native/zynaddsubfx/UI/ADnoteUI.cpp -source/modules/carla_native/zynaddsubfx/UI/ADnoteUI.h -source/modules/carla_native/zynaddsubfx/UI/BankUI.cpp -source/modules/carla_native/zynaddsubfx/UI/BankUI.h -source/modules/carla_native/zynaddsubfx/UI/ConfigUI.cpp -source/modules/carla_native/zynaddsubfx/UI/ConfigUI.h -source/modules/carla_native/zynaddsubfx/UI/EffUI.cpp -source/modules/carla_native/zynaddsubfx/UI/EffUI.h -source/modules/carla_native/zynaddsubfx/UI/EnvelopeUI.cpp -source/modules/carla_native/zynaddsubfx/UI/EnvelopeUI.h -source/modules/carla_native/zynaddsubfx/UI/FilterUI.cpp -source/modules/carla_native/zynaddsubfx/UI/FilterUI.h -source/modules/carla_native/zynaddsubfx/UI/LFOUI.cpp -source/modules/carla_native/zynaddsubfx/UI/LFOUI.h -source/modules/carla_native/zynaddsubfx/UI/MasterUI.cpp -source/modules/carla_native/zynaddsubfx/UI/MasterUI.h -source/modules/carla_native/zynaddsubfx/UI/MicrotonalUI.cpp -source/modules/carla_native/zynaddsubfx/UI/MicrotonalUI.h -source/modules/carla_native/zynaddsubfx/UI/OscilGenUI.cpp -source/modules/carla_native/zynaddsubfx/UI/OscilGenUI.h -source/modules/carla_native/zynaddsubfx/UI/PADnoteUI.cpp -source/modules/carla_native/zynaddsubfx/UI/PADnoteUI.h -source/modules/carla_native/zynaddsubfx/UI/PartUI.cpp -source/modules/carla_native/zynaddsubfx/UI/PartUI.h -source/modules/carla_native/zynaddsubfx/UI/PresetsUI.cpp -source/modules/carla_native/zynaddsubfx/UI/PresetsUI.h -source/modules/carla_native/zynaddsubfx/UI/ResonanceUI.cpp -source/modules/carla_native/zynaddsubfx/UI/ResonanceUI.h -source/modules/carla_native/zynaddsubfx/UI/SUBnoteUI.cpp -source/modules/carla_native/zynaddsubfx/UI/SUBnoteUI.h -source/modules/carla_native/zynaddsubfx/UI/VirKeyboard.cpp -source/modules/carla_native/zynaddsubfx/UI/VirKeyboard.h +source/modules/daz-plugins/zynaddsubfx/UI/ADnoteUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/ADnoteUI.h +source/modules/daz-plugins/zynaddsubfx/UI/BankUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/BankUI.h +source/modules/daz-plugins/zynaddsubfx/UI/ConfigUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/ConfigUI.h +source/modules/daz-plugins/zynaddsubfx/UI/EffUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/EffUI.h +source/modules/daz-plugins/zynaddsubfx/UI/EnvelopeUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/EnvelopeUI.h +source/modules/daz-plugins/zynaddsubfx/UI/FilterUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/FilterUI.h +source/modules/daz-plugins/zynaddsubfx/UI/LFOUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/LFOUI.h +source/modules/daz-plugins/zynaddsubfx/UI/MasterUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/MasterUI.h +source/modules/daz-plugins/zynaddsubfx/UI/MicrotonalUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/MicrotonalUI.h +source/modules/daz-plugins/zynaddsubfx/UI/OscilGenUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/OscilGenUI.h +source/modules/daz-plugins/zynaddsubfx/UI/PADnoteUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/PADnoteUI.h +source/modules/daz-plugins/zynaddsubfx/UI/PartUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/PartUI.h +source/modules/daz-plugins/zynaddsubfx/UI/PresetsUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/PresetsUI.h +source/modules/daz-plugins/zynaddsubfx/UI/ResonanceUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/ResonanceUI.h +source/modules/daz-plugins/zynaddsubfx/UI/SUBnoteUI.cpp +source/modules/daz-plugins/zynaddsubfx/UI/SUBnoteUI.h +source/modules/daz-plugins/zynaddsubfx/UI/VirKeyboard.cpp +source/modules/daz-plugins/zynaddsubfx/UI/VirKeyboard.h # Other source/includes/asio/ diff --git a/source/includes/daz/daz-common.h b/source/includes/daz/daz-common.h new file mode 100644 index 000000000..8a2a43d1f --- /dev/null +++ b/source/includes/daz/daz-common.h @@ -0,0 +1,77 @@ +/* + * DAZ - Digital Audio with Zero dependencies + * Copyright (C) 2013 Filipe Coelho + * Copyright (C) 2013 Harry van Haaren + * Copyright (C) 2013 Jonathan Moore Liles + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DAZ_COMMON_H_INCLUDED +#define DAZ_COMMON_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#else +#include +#endif + +#include +#include + +/*! + * @defgroup DAZPluginAPI DAZ Plugin API + * + * The DAZ Plugin API + * + * TODO: More complete description here. + * @{ + */ + +/*! + * Current API version. + * + * Hosts may load plugins that use old versions, but not newer. + */ +#define DAZ_API_VERSION 1 + +/*! + * Symbol export. + * + * This makes sure the plugin and UI entry points are always visible, + * regardless of compile settings. + */ +#ifdef _WIN32 +# define DAZ_SYMBOL_EXPORT __declspec(dllexport) +#else +# define DAZ_SYMBOL_EXPORT __attribute__((visibility("default"))) +#endif + +/*! + * Terminator character for property lists. + */ +#define DAZ_TERMINATOR ":" + +/*! + * Host mapped value of a string. + * The value 0 is reserved as undefined. + * @see PluginHostDescriptor::map_value(), UiHostDescriptor::map_value() + */ +typedef uint32_t mapped_value_t; + +/** @} */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* DAZ_COMMON_H_INCLUDED */ diff --git a/source/includes/daz/daz-plugin.h b/source/includes/daz/daz-plugin.h new file mode 100644 index 000000000..f6533a2f3 --- /dev/null +++ b/source/includes/daz/daz-plugin.h @@ -0,0 +1,733 @@ +/* + * DAZ - Digital Audio with Zero dependencies + * Copyright (C) 2013 Filipe Coelho + * Copyright (C) 2013 Harry van Haaren + * Copyright (C) 2013 Jonathan Moore Liles + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DAZ_PLUGIN_H_INCLUDED +#define DAZ_PLUGIN_H_INCLUDED + +#include "daz-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * @defgroup DAZPluginAPI + * @{ + */ + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin Categories */ + +/*! + * @defgroup PluginCategories Plugin Categories + * + * A small list of pre-defined plugin categories. + * + * Plugins should provide at least one of these basic categories, terminating with ":". + * They can use their own custom categories as well, as long as they are lowercase and contain ASCII characters only. + * @{ + */ + +/*! + * A synthesizer or generator. + */ +#define PLUGIN_CATEGORY_SYNTH ":synth" + +/*! + * A delay or reverberator. + */ +#define PLUGIN_CATEGORY_DELAY ":delay" + +/*! + * An equalizer. + */ +#define PLUGIN_CATEGORY_EQ ":eq" + +/*! + * A filter. + */ +#define PLUGIN_CATEGORY_FILTER ":filter" + +/*! + * A distortion plugin. + */ +#define PLUGIN_CATEGORY_DISTORTION ":distortion" + +/*! + * A 'dynamic' plugin (amplifier, compressor, gate, etc). + */ +#define PLUGIN_CATEGORY_DYNAMICS ":dynamics" + +/*! + * A 'modulator' plugin (chorus, flanger, phaser, etc). + */ +#define PLUGIN_CATEGORY_MODULATOR ":modulator" + +/*! + * An 'utility' plugin (analyzer, converter, mixer, etc). + */ +#define PLUGIN_CATEGORY_UTILITY ":utility" + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin Features */ + +/*! + * @defgroup PluginFeatures Plugin Features + * + * A list of plugin features or hints. + * + * Plugins should list all features it supports, terminating with ":" + * Custom features are allowed, as long as they are lowercase and contain ASCII characters only. + * The host will decide if it can load the plugin or not based on this information. + * @{ + */ + +/*! + * Supports buffer size changes on-the-fly. + * + * If unset, the host will re-initiate the plugin when the buffer size changes. + */ +#define PLUGIN_FEATURE_BUFFER_SIZE_CHANGES ":buffer_size_changes" + +/*! + * Supports sample rate changes on-the-fly. + * + * If unset, the host will re-initiate the plugin when the sample rate changes. + */ +#define PLUGIN_FEATURE_SAMPLE_RATE_CHANGES ":sample_rate_changes" + +/*! + * Needs non-realtime idle() function regularly. + * + * This can be used by plugins that need a non-realtime thread to do work. + * The host will call PluginDescriptor::idle() at regular intervals. + * The plugin may acquire a lock, but MUST NOT block indefinitely. + * + * Alternatively, the plugin can ask the host for a one-shot idle() + * by using HOST_OPCODE_NEEDS_IDLE. + */ +#define PLUGIN_FEATURE_IDLE ":idle" + +/*! + * Supports get_state() and set_state() functions. + */ +#define PLUGIN_FEATURE_STATE ":state" + +/*! + * Uses get_time_info() host function. + */ +#define PLUGIN_FEATURE_TIME ":time" + +/*! + * Uses write_event() host function. + */ +#define PLUGIN_FEATURE_WRITE_EVENT ":write_event" + +/*! + * Uses send_ui_msg() host function. + */ +#define PLUGIN_FEATURE_SEND_MSG ":sendmsg" + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin Supports */ + +/*! + * TODO - this needs a better name... + * + * @defgroup PluginSupports Plugin Supports + * + * A list of plugin supported MIDI events. + * + * Plugins should list all the MIDI message types it supports, terminating with ":". + * @{ + */ + +/*! + * Handles MIDI programs internally instead of host-exposed/exported. + * + * When this is set, the host will not try to map MIDI program changes into + * plugin exported programs by sending MidiProgramEvent, but will send MidiEvent directly. + * + * @see MidiProgram, MidiProgramEvent + */ +#define PLUGIN_SUPPORTS_PROGRAM_CHANGES ":program" + +/*! + * Supports control changes (0xB0). + * + * @note: + * The plugin MUST NEVER change exposed parameters on its own. + * If the plugin wants to map a MIDI control change message to a parameter + * it can do so by reporting it in the meta-data, which the host will read. + */ +#define PLUGIN_SUPPORTS_CONTROL_CHANGES ":control" + +/*! + * Supports channel pressure (0xD0). + */ +#define PLUGIN_SUPPORTS_CHANNEL_PRESSURE ":pressure" + +/*! + * Supports note aftertouch (0xA0). + */ +#define PLUGIN_SUPPORTS_NOTE_AFTERTOUCH ":aftertouch" + +/*! + * Supports pitchbend (0xE0). + */ +#define PLUGIN_SUPPORTS_PITCHBEND ":pitchbend" + +/*! + * Supports all-sound-off and all-notes-off events. + * + * When this is not set, the host might want to send various note-off events to silence the plugin. + */ +#define PLUGIN_SUPPORTS_ALL_SOUND_OFF ":allsoundoff" + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Parameter Hints */ + +/*! + * @defgroup ParameterHints Parameter Hints + * + * List of parameter hints. + * + * < something something >, terminating with ":". + * @{ + */ + +/*! + * Is enabled. + * + * If set the host may show this parameter on its "built-in" dialog. + */ +#define PARAMETER_IS_ENABLED ":enabled" + +/*! + * Is output. + * + * If this is not set, the parameter should be considered input. + * + * Input parameters are managed by the host and changed by sending a ParameterEvent to the plugin. + * The plugin MUST NEVER change input parameters on its own. + * + * Output parameters are managed by the plugin. + * Most plugins that have output parameters should set PLUGIN_FEATURE_WRITE_EVENT, + * see PARAMETER_IS_RTSAFE for details. + */ +#define PARAMETER_IS_OUTPUT ":output" + +/*! + * Is not real time safe. + * + * For input parameters: + * When set, the host MUST ONLY use PluginDescriptor::non_rt_event(). + * When not set (default), the host MUST ONLY use in-process events to change this parameter. + * + * For output parameters: + * When set, the host will call PluginDescriptor::get_parameter_value() where the plugin is allowed to lock. + * When not set (default), the plugin must send a ParameterEvent to the host every time the value changes. + * + * @see PLUGIN_FEATURE_RTSAFE + */ +#define PARAMETER_IS_NON_RT ":non_rt" + +/*! + * Values are boolean (always at minimum or maximum values). + */ +#define PARAMETER_IS_BOOLEAN ":boolean" + +/*! + * Values are integer. + */ +#define PARAMETER_IS_INTEGER ":integer" + +/*! + * Values are logarithmic. + */ +#define PARAMETER_IS_LOGARITHMIC ":logarithmic" + +/*! + * Needs sample rate to work. + * + * The parameter value and ranges are multiplied by sample rate on usage + * and divided by sample rate on save. + */ +#define PARAMETER_USES_SAMPLE_RATE ":sample_rate" + +/*! + * Uses scalepoints to define internal values in a meaningful way. + */ +#define PARAMETER_USES_SCALEPOINTS ":scalepoints" + +/*! + * Uses custom text for displaying its value. + * + * @see get_parameter_text() + */ +#define PARAMETER_USES_CUSTOM_TEXT ":custom_text" + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Default Parameter Ranges */ + +/*! + * @defgroup DefaultParameterRanges Default Parameter Ranges + * + * Default values for parameter range steps. + * @{ + */ +#define PARAMETER_RANGE_DEFAULT_STEP 0.01f +#define PARAMETER_RANGE_DEFAULT_STEP_SMALL 0.0001f +#define PARAMETER_RANGE_DEFAULT_STEP_LARGE 0.1f +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Event Types */ + +/*! + * @defgroup EventTypes Event Types + * + * List of supported event types. + * + * The types are mapped into mapped_value_t by the host. + * @see PluginHostDescriptor::map_value() + * @{ + */ + +/*! + * Generic MIDI event. + * + * Realtime MIDI events are always used in-process, + * while non realtime ones should be used in PluginDescriptor::non_rt_event(). + * + * @see MidiEvent + */ +#define EVENT_TYPE_MIDI "midi" + +/*! + * Midi program event. + * + * Used in-process only. + * + * @see MidiProgramEvent + */ +#define EVENT_TYPE_MIDI_PROGRAM "midiprogram" + +/*! + * Parameter event. + * + * There are some rules for parameter events, + * please see PARAMETER_IS_RTSAFE. + * + * @see ParameterEvent + */ +#define EVENT_TYPE_PARAMETER "parameter" + +/*! + * Time information event. + * + * Used in-process only. + * + * @see TimeInfoEvent + */ +#define EVENT_TYPE_TIME "time" + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Host Dispatcher Opcodes */ + +/*! + * @defgroup HostDispatcherOpcodes Host Dispatcher Opcodes + * + * Opcodes dispatched by the plugin to report and request information from the host. + * + * The opcodes are mapped into MappedValue by the host. + * @see HostDescriptor::dispatcher() + * @{ + */ + +/*! + * Tell the host to call idle() as soon as possible (once), uses nothing. + */ +#define HOST_OPCODE_NEEDS_IDLE "needsIdle" + +/*! + * Tell the host to update parameter @a index. + * Uses index with -1 for all. + */ +#define HOST_OPCODE_UPDATE_PARAMETER "updateParameter" + +/*! + * Tell the host to update midi-program @a index. + * Uses index with -1 for all. + * May also use value for channel. <= FIXME: maybe remove this bit, but for synths it's nice to have + */ +#define HOST_OPCODE_UPDATE_MIDI_PROGRAM "updateMidiProgram" + +/*! + * Tell the host to reload all parameters data, uses nothing. + */ +#define HOST_OPCODE_RELOAD_PARAMETERS "reloadParameters" + +/*! + * Tell the host to reload all midi-programs data, uses nothing. + */ +#define HOST_OPCODE_RELOAD_MIDI_PROGRAMS "reloadMidiPrograms" + +/*! + * Tell the host to reload everything all the plugin, uses nothing. + */ +#define HOST_OPCODE_RELOAD_ALL "reloadAll" + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin Dispatcher Opcodes */ + +/*! + * @defgroup PluginDispatcherOpcodes Plugin Dispatcher Opcodes + * + * Opcodes dispatched by the host to report changes to the plugin. + * + * The opcodes are mapped into MappedValue by the host. + * @see PluginDescriptor::dispatcher() + * @{ + */ + +/*! + * Message received, uses ptr as char*. + */ +#define PLUGIN_OPCODE_MSG_RECEIVED "msgReceived" + +/*! + * Audio buffer size changed, uses value, returns 1 if supported. + * @see PluginHostDescriptor::buffer_size + */ +#define PLUGIN_OPCODE_BUFFER_SIZE_CHANGED "bufferSizeChanged" + +/*! + * Audio sample rate changed, uses opt, returns 1 if supported. + * @see PluginHostDescriptor::sample_rate + */ +#define PLUGIN_OPCODE_SAMPLE_RATE_CHANGED "sampleRateChanged" + +/*! + * Offline mode changed, uses value (0=off, 1=on). + * @see PluginHostDescriptor::is_offline + */ +#define PLUGIN_OPCODE_OFFLINE_CHANGED "offlineChanged" + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Base types */ + +/*! + * Audio sample type. + */ +typedef float audio_sample_t; + +/*! + * Opaque plugin handle. + */ +typedef void* PluginHandle; + +/*! + * Opaque host handle. + */ +typedef void* PluginHostHandle; + +/*! + * Parameter scale point. + */ +typedef struct { + const char* label; /*!< not null */ + float value; +} ParameterScalePoint; + +/*! + * Parameter ranges. + */ +typedef struct { + float def; + float min; + float max; +#if 1 + float step; + float stepSmall; + float stepLarge; +#endif +} ParameterRanges; + +/*! + * Parameter. + */ +typedef struct { + const char* hints; /*!< not null, @see ParameterHints */ + const char* name; /*!< not null */ + const char* symbol; /*!< not null */ + const char* unit; /*!< can be null */ + ParameterRanges ranges; + + uint32_t scalePointCount; + ParameterScalePoint* scalePoints; +} Parameter; + +/*! + * MIDI Program. + */ +typedef struct { + uint32_t bank; + uint32_t program; + const char* name; +} MidiProgram; + +/* ------------------------------------------------------------------------------------------------------------ + * TimeInfo related types */ + +/*! + * Bar-Beat-Tick information. + * + * @note this is the same data provided by JACK + */ +typedef struct { + bool valid; + + int32_t bar; /*!< current bar */ + int32_t beat; /*!< current beat-within-bar */ + int32_t tick; /*!< current tick-within-beat */ + double barStartTick; + + float beatsPerBar; /*!< time signature "numerator" */ + float beatType; /*!< time signature "denominator" */ + + double ticksPerBeat; + double beatsPerMinute; +} TimeInfoBBT; + +/*! + * Time information. + */ +typedef struct { + bool playing; + uint64_t frame; + uint64_t usecs; + TimeInfoBBT bbt; +} TimeInfo; + +/* ------------------------------------------------------------------------------------------------------------ + * Event related types */ + +/*! + * Generic event. + */ +typedef struct { + mapped_value_t type; /*!< Type of event. @see EventTypes */ + uint32_t frame; /*!< Frame offset since the beginning of process() */ +} Event; + +/*! + * MIDI event. + */ +typedef struct { + Event e; + uint8_t port; + uint8_t size; + uint8_t data[4]; +} MidiEvent; + +/*! + * MIDI Program event. + * + * This is a special type of event that tells to plugin to switch MIDI program. + * The plugin is allowed to change its parameter values, the host should request them afterwards if needed. + * + * If the plugin has PLUGIN_SUPPORTS_PROGRAM_CHANGES set, the host must never use event type. + * + * @see MidiProgram + */ +typedef struct { + Event e; + uint8_t channel; /* used only in synths */ + uint32_t bank; + uint32_t program; +} MidiProgramEvent; + +/*! + * Parameter event. + */ +typedef struct { + Event e; + uint32_t index; + float value; +} ParameterEvent; + +/*! + * Time information event. + */ +typedef struct { + Event e; + bool playing; + uint64_t frame; + TimeInfoBBT bbt; +} TimeInfoEvent; + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin Host Descriptor */ + +/*! + * PluginHostDescriptor + */ +typedef struct { + PluginHostHandle handle; + + /*! + * Previously used plugin version, may be NULL. + */ + const char* pluginVersion; + + /*! + * Current audio buffer size. + */ + uint32_t buffer_size; + + /*! + * Current audio sample rate. + */ + double sample_rate; + + /*! + * Wherever the host is currently processing offline. + FIXME: what is this for? + */ + bool is_offline; + + /* NOTE: NOT allowed during process() + * probably better if only allowed during instantiate() */ + mapped_value_t (*map_value)(PluginHostHandle handle, const char* valueStr); + const char* (*unmap_value)(PluginHostHandle handle, mapped_value_t value); + + /* plugin must set "time" feature to use this + * NOTE: only allowed during process() */ + const TimeInfo* (*get_time_info)(PluginHostHandle handle); + + /* plugin must set "writeevent" feature to use this + * NOTE: only allowed during process() */ + bool (*write_event)(PluginHostHandle handle, const Event* event); + + /* plugin must set "sendmsg" feature to use this + * NOTE: only allowed during idle() or non_rt_event() */ + bool (*send_ui_msg)(PluginHostHandle handle, const void* data, size_t size); + + /* uses HostDispatcherOpcodes : FIXME - use "const void* value" only? */ + int * (*dispatcher)(PluginHostHandle handle, mapped_value_t opcode, int32_t index, int32_t value, void* ptr, float opt); + +} PluginHostDescriptor; + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin Descriptor */ + +/*! + * PluginDescriptor + */ +typedef struct { + /* descriptor metadata. the required set of metadata is: (TODO review) + + const char* metadata[] = { + "api version", "1", // <-- MUST be version of API used when plugin was built. + "author", "Bob Cat, MD", + "display name", "Best EQ Evar", + "organization", "bobcat", + "uuid", "org.bobcat.best_eq_evar_v1", // <-- MUST be universally unique for this plugin major version. Only allowed punctuation is "." and "_". + "copyright", "copyright 2013 foobar inc", + "interface version", "1", // <-- MUST be incremented if the available parameters have changed in a not-backwards compatible way! + "dsp version", "0", // <-- MUST be incremented if the DSP algorithm has been changed in any audible way from previous version. + "description", "15 Band FFT EQ", + "documentation", "This eq blah blah blah", + "website", "http://bobcat.com/plugins/best_eq_evar/buyitnow", + "provides", "foo:bar", // <-- features this plugin provides + "requires", "bar", // <-- features this plugin requires + NULL // <-- MUST be NULL terminated! + }; + */ + const char* const* metadata; + + PluginHandle (*instantiate)(const PluginHostDescriptor* host); + void (*cleanup)(PluginHandle handle); + + uint32_t (*get_parameter_count)(PluginHandle handle); + const Parameter* (*get_parameter_info)(PluginHandle handle, uint32_t index); + float (*get_parameter_value)(PluginHandle handle, uint32_t index); + const char* (*get_parameter_text)(PluginHandle handle, uint32_t index, float value); /* only used if parameter hint "customtext" is set */ + + uint32_t (*get_midi_program_count)(PluginHandle handle); + const MidiProgram* (*get_midi_program_info)(PluginHandle handle, uint32_t index); + + /* only used if "idle" feature is set, or HOST_OPCODE_NEEDS_IDLE was triggered (for one-shot). + * NOTE: although it's a non-realtime function, it will probably still not be called from the host main thread */ + void (*idle)(PluginHandle handle); + + /* NOTE: host will never call this while process() is running + * FIXME: the above statement requires a lot of unnecessary house keeping in the host */ + void (*non_rt_event)(PluginHandle handle, const Event* event); + + /* only used if "state" feature is set */ + char* (*get_state)(PluginHandle handle); + void (*set_state)(PluginHandle handle, const char* data); + + void (*activate)(PluginHandle handle); + void (*deactivate)(PluginHandle handle); + void (*process)(PluginHandle handle, audio_sample_t** inBuffer, audio_sample_t** outBuffer, uint32_t frames, const Event* events, uint32_t eventCount); + + /* uses PluginDispatcherOpcodes : FIXME - use "const void* value" only? */ + int * (*dispatcher)(PluginHandle handle, mapped_value_t opcode, int32_t index, int32_t value, void* ptr, float opt); + +} PluginDescriptor; + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin entry point */ + +/*! + * Plugin entry point function used by the plugin. + */ +DAZ_SYMBOL_EXPORT +const PluginDescriptor* daz_get_plugin_descriptor(uint32_t index); + +/*! + * Plugin entry point function used by the host. + */ +typedef const PluginDescriptor* (*daz_get_plugin_descriptor_fn)(uint32_t index); + +/* ------------------------------------------------------------------------------------------------------------ */ + +/** @} */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* DAZ_PLUGIN_H_INCLUDED */ diff --git a/source/includes/daz/daz-ui.h b/source/includes/daz/daz-ui.h new file mode 100644 index 000000000..d57e73cee --- /dev/null +++ b/source/includes/daz/daz-ui.h @@ -0,0 +1,237 @@ +/* + * DAZ - Digital Audio with Zero dependencies + * Copyright (C) 2013 Filipe Coelho + * Copyright (C) 2013 Harry van Haaren + * Copyright (C) 2013 Jonathan Moore Liles + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DAZ_UI_H_INCLUDED +#define DAZ_UI_H_INCLUDED + +#include "daz-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * @defgroup DAZPluginAPI + * @{ + */ + +/*! + * @defgroup UiFeatures UI Features + * + * A list of UI features or hints. + * + * Custom features are allowed, as long as they are lowercase and contain ASCII characters only. + * The host can decide if it can load the UI or not based on this information. + * + * Multiple features can be set by using ":" in between them. + * @{ + */ + +/*! + * Supports sample rate changes on-the-fly. + * + * If unset, the host will re-initiate the UI when the sample rate changes. + */ +#define UI_FEATURE_SAMPLE_RATE_CHANGES ":sample_rate_changes" + +/*! + * Uses open_file() and/or save_file() functions. + */ +#define UI_FEATURE_OPEN_SAVE ":open_save" + +/*! + * Uses send_plugin_msg() function. + */ +#define UI_FEATURE_SEND_MSG ":send_msg" + +/** @} */ + +/*! + * @defgroup HostDispatcherOpcodes Host Dispatcher Opcodes + * + * Opcodes dispatched by the UI to report and request information from the host. + * + * The opcodes are mapped into MappedValue by the host. + * @see HostDescriptor::dispatcher() + * @{ + */ + +/*! + * Tell the host the UI can't be shown, uses nothing. + */ +#define HOST_OPCODE_UI_UNAVAILABLE "ui_unavailable" + +/** @} */ + +/*! + * @defgroup UiDispatcherOpcodes UI Dispatcher Opcodes + * + * Opcodes dispatched by the host to report changes to the UI. + * + * The opcodes are mapped into MappedValue by the host. + * @see UiDescriptor::dispatcher() + * @{ + */ + +/*! + * Message received, uses value as size, ptr for contents. + */ +#define UI_OPCODE_MSG_RECEIVED "msg_received" + +/*! + * Audio sample rate changed, uses opt, returns 1 if supported. + * + * @see UiHostDescriptor::sample_rate + */ +#define UI_OPCODE_SAMPLE_RATE_CHANGED "sample_rate_changed" + +/*! + * Offline mode changed, uses value (0=off, 1=on). + * + * @see UiHostDescriptor::is_offline + */ +#define UI_OPCODE_OFFLINE_CHANGED "offline_changed" + +/*! + * UI title changed, uses ptr. + * + * @see UiHostDescriptor::ui_title + */ +#define UI_OPCODE_TITLE_CHANGED "ui_title_thanged" + +/** @} */ + +/*! + * Opaque UI handle. + */ +typedef void* UiHandle; + +/*! + * Opaque UI host handle. + */ +typedef void* UiHostHandle; + +/*! + * UiHostDescriptor + */ +typedef struct { + /*! + * Opaque UI host handle. + */ + UiHostHandle handle; + + /*! + * Full filepath to the UI *.daz bundle. + */ + const char* bundle_dir; + + /*! + * Host desired UI title. + */ + const char* ui_title; + + /*! + * Current audio sample rate. + */ + double sample_rate; + + /*! + * Wherever the host is currently processing offline. + */ + bool is_offline; + + /* probably better if only allowed during instantiate() */ + mapped_value_t (*map_value)(UiHostHandle handle, const char* valueStr); + const char* (*unmap_value)(UiHostHandle handle, mapped_value_t value); + + /*! + * Inform the host about a parameter change. + */ + void (*parameter_changed)(UiHostHandle handle, uint32_t index, float value); + + /*! + * Inform the host about a/the MIDI program change. + * + * @note: Only synths make use the of @a channel argument. + */ + void (*midi_program_changed)(UiHostHandle handle, uint8_t channel, uint32_t bank, uint32_t program); + + /*! + * Inform the host the UI has been closed. + * + * After calling this the UI should not do any operation and simply wait + * until the host calls UiDescriptor::cleanup(). + */ + void (*closed)(UiHostHandle handle); + + /* TODO: add some msgbox call */ + + /* ui must set "opensave" feature to use these */ + const char* (*open_file)(UiHostHandle handle, bool isDir, const char* title, const char* filter); + const char* (*save_file)(UiHostHandle handle, bool isDir, const char* title, const char* filter); + + /* ui must set "sendmsg" feature to use this */ + bool (*send_plugin_msg)(UiHostHandle handle, const void* data, size_t size); + + /* uses HostDispatcherOpcodes */ + intptr_t (*dispatcher)(UiHostHandle handle, mapped_value_t opcode, int32_t index, intptr_t value, void* ptr, float opt); + +} UiHostDescriptor; + +/*! + * UiDescriptor + */ +typedef struct { + const int api; /*!< Must be set to DAZ_API_VERSION. */ + const char* const features; /*!< Features. @see UiFeatures */ + const char* const author; /*!< Author this UI applies to. */ + const char* const label; /*!< Label this UI applies to, can only contain letters, numbers and "_". May be null, in which case represents all UIs for @a maker. */ + + UiHandle (*instantiate)(const UiHostDescriptor* host); + void (*cleanup)(UiHandle handle); + + void (*show)(UiHandle handle, bool show); + void (*idle)(UiHandle handle); + + void (*set_parameter)(UiHandle handle, uint32_t index, float value); + void (*set_midi_program)(UiHandle handle, uint8_t channel, uint32_t bank, uint32_t program); + void (*set_state)(UiHandle handle, const char* state); + + /* uses UiDispatcherOpcodes */ + intptr_t (*dispatcher)(UiHandle handle, mapped_value_t opcode, int32_t index, intptr_t value, void* ptr, float opt); + +} UiDescriptor; + +/*! + * UI entry point function used by the UI. + */ +DAZ_SYMBOL_EXPORT +const UiDescriptor* daz_get_ui_descriptor(uint32_t index); + +/*! + * UI entry point function used by the host. + */ +typedef const UiDescriptor* (*daz_get_ui_descriptor_fn)(uint32_t index); + +/** @} */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* DAZ_UI_H_INCLUDED */ diff --git a/source/modules/daz-plugins/_all.c b/source/modules/daz-plugins/_all.c index 662d7c3a2..52048cb89 100644 --- a/source/modules/daz-plugins/_all.c +++ b/source/modules/daz-plugins/_all.c @@ -16,11 +16,12 @@ */ #include "CarlaDefines.h" -#include "CarlaNative.h" // Simple plugins -extern void carla_register_native_plugin_bypass(); -extern void carla_register_native_plugin_lfo(); +extern void carla_register_daz_plugin_bypass(); +extern void carla_register_daz_plugin_lfo(); + +// Simple plugins extern void carla_register_native_plugin_midiGain(); extern void carla_register_native_plugin_midiSplit(); extern void carla_register_native_plugin_midiThrough(); @@ -71,9 +72,13 @@ extern void carla_register_native_plugin_zynaddsubfx_synth(); void carla_register_all_plugins() { +#if 0 + // Simple plugins + carla_register_daz_plugin_bypass(); + carla_register_daz_plugin_lfo(); +#endif + // Simple plugins - carla_register_native_plugin_bypass(); - carla_register_native_plugin_lfo(); carla_register_native_plugin_midiGain(); carla_register_native_plugin_midiSplit(); carla_register_native_plugin_midiThrough(); diff --git a/source/modules/daz-plugins/bypass.c b/source/modules/daz-plugins/bypass.c index bb33c0550..cd85cdd2d 100644 --- a/source/modules/daz-plugins/bypass.c +++ b/source/modules/daz-plugins/bypass.c @@ -1,6 +1,6 @@ /* - * Carla Native Plugins - * Copyright (C) 2012-2013 Filipe Coelho + * Carla Internal Plugins + * Copyright (C) 2012-2014 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -15,48 +15,60 @@ * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ -#include "CarlaNative.h" +#include "daz/daz-plugin.h" #include // ----------------------------------------------------------------------- +// Implemented by Carla -static NativePluginHandle bypass_instantiate(const NativeHostDescriptor* host) +extern void carla_register_daz_plugin(const PluginDescriptor* desc); + +// ----------------------------------------------------------------------- + +static const char* bypass_metadata[] = { + "api", "1", // FIXME: should be a macro + "features", PLUGIN_FEATURE_BUFFER_SIZE_CHANGES PLUGIN_FEATURE_SAMPLE_RATE_CHANGES DAZ_TERMINATOR, + "audioIns", "1", + "audioOuts", "1", + "midiIns", "0", + "midiOuts", "0", + "paramIns", "0", + "paramOuts", "0", + "author", "falkTX", + "name", "ByPass", + "label", "bypass", + "copyright", "GNU GPL v2+", + "version", "1.0.0", + NULL +}; + +// ----------------------------------------------------------------------- + +static PluginHandle bypass_instantiate(const PluginHostDescriptor* host) { // dummy, return non-NULL - return (NativePluginHandle)0x1; + return (PluginHandle)0x1; // unused (void)host; } -static void bypass_process(NativePluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, const NativeMidiEvent* midiEvents, uint32_t midiEventCount) +static void bypass_process(PluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, const Event* events, uint32_t eventCount) { memcpy(outBuffer[0], inBuffer[0], sizeof(float)*frames); return; // unused (void)handle; - (void)midiEvents; - (void)midiEventCount; + (void)events; + (void)eventCount; } // ----------------------------------------------------------------------- -static const NativePluginDescriptor bypassDesc = { - .category = PLUGIN_CATEGORY_NONE, - .hints = PLUGIN_IS_RTSAFE, - .supports = 0x0, - .audioIns = 1, - .audioOuts = 1, - .midiIns = 0, - .midiOuts = 0, - .paramIns = 0, - .paramOuts = 0, - .name = "ByPass", - .label = "bypass", - .maker = "falkTX", - .copyright = "GNU GPL v2+", +static const PluginDescriptor bypassDesc = { + .metadata = bypass_metadata, .instantiate = bypass_instantiate, .cleanup = NULL, @@ -69,32 +81,24 @@ static const NativePluginDescriptor bypassDesc = { .get_midi_program_count = NULL, .get_midi_program_info = NULL, - .set_parameter_value = NULL, - .set_midi_program = NULL, - .set_custom_data = NULL, + .idle = NULL, + .non_rt_event = NULL, - .ui_show = NULL, - .ui_idle = NULL, - - .ui_set_parameter_value = NULL, - .ui_set_midi_program = NULL, - .ui_set_custom_data = NULL, + .get_state = NULL, + .set_state = NULL, .activate = NULL, .deactivate = NULL, .process = bypass_process, - .get_state = NULL, - .set_state = NULL, - .dispatcher = NULL }; // ----------------------------------------------------------------------- -void carla_register_native_plugin_bypass() +void carla_register_daz_plugin_bypass() { - carla_register_native_plugin(&bypassDesc); + carla_register_daz_plugin(&bypassDesc); } // ----------------------------------------------------------------------- diff --git a/source/modules/daz-plugins/lfo.c b/source/modules/daz-plugins/lfo.c index 2d5f53f3d..06df275b4 100644 --- a/source/modules/daz-plugins/lfo.c +++ b/source/modules/daz-plugins/lfo.c @@ -1,6 +1,6 @@ /* - * Carla Native Plugins - * Copyright (C) 2012-2013 Filipe Coelho + * Carla Internal Plugins + * Copyright (C) 2012-2014 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -15,13 +15,18 @@ * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ -#include "CarlaNative.h" +#include "daz/daz-plugin.h" + +#include "CarlaDefines.h" #include "CarlaMIDI.h" #include #include -typedef unsigned int uint; +// ----------------------------------------------------------------------- +// Implemented by Carla + +extern void carla_register_daz_plugin(const PluginDescriptor* desc); // ----------------------------------------------------------------------- @@ -35,42 +40,72 @@ typedef enum { } LfoParams; typedef struct { - const NativeHostDescriptor* host; + // host struct + const PluginHostDescriptor* host; + + // params int mode; double speed; float multiplier; float baseStart; float value; + + // extra + bool firstRun; + mapped_value_t evTypeParam; + mapped_value_t evTypeTime; } LfoHandle; // ----------------------------------------------------------------------- -static NativePluginHandle lfo_instantiate(const NativeHostDescriptor* host) +static const char* lfo_metadata[] = { + "api", "1", // FIXME: should be a macro + "features", PLUGIN_FEATURE_BUFFER_SIZE_CHANGES PLUGIN_FEATURE_SAMPLE_RATE_CHANGES PLUGIN_FEATURE_TIME PLUGIN_FEATURE_WRITE_EVENT DAZ_TERMINATOR, + "audioIns", "0", + "audioOuts", "0", + "midiIns", "0", + "midiOuts", "0", + "paramIns", "4", + "paramOuts", "1", + "author", "falkTX", + "name", "LFO", + "label", "lfo", + "copyright", "GNU GPL v2+", + "version", "1.0.0", + NULL +}; + +// ----------------------------------------------------------------------- + +static PluginHandle lfo_instantiate(const PluginHostDescriptor* host) { LfoHandle* const handle = (LfoHandle*)malloc(sizeof(LfoHandle)); if (handle == NULL) return NULL; - host->dispatcher(host->handle, HOST_OPCODE_SET_PROCESS_PRECISION, 0, 32, NULL, 0.0f); - - handle->host = host; - handle->mode = 1; - handle->speed = 1.0f; - handle->multiplier = 1.0f; - handle->baseStart = 0.0f; - handle->value = 0.0f; + handle->host = host; + handle->mode = 1; + handle->speed = 1.0f; + handle->multiplier = 1.0f; + handle->baseStart = 0.0f; + handle->value = 0.0f; + handle->firstRun = true; + handle->evTypeParam = host->map_value(host->handle, EVENT_TYPE_PARAMETER); + handle->evTypeTime = host->map_value(host->handle, EVENT_TYPE_TIME); return handle; } +// ----------------------------------------------------------------------- + #define handlePtr ((LfoHandle*)handle) -static void lfo_cleanup(NativePluginHandle handle) +static void lfo_cleanup(PluginHandle handle) { free(handlePtr); } -static uint32_t lfo_get_parameter_count(NativePluginHandle handle) +static uint32_t lfo_get_parameter_count(PluginHandle handle) { return PARAM_COUNT; @@ -78,15 +113,14 @@ static uint32_t lfo_get_parameter_count(NativePluginHandle handle) (void)handle; } -const NativeParameter* lfo_get_parameter_info(NativePluginHandle handle, uint32_t index) +const Parameter* lfo_get_parameter_info(PluginHandle handle, uint32_t index) { if (index > PARAM_COUNT) return NULL; - static NativeParameter param; - static NativeParameterScalePoint paramModes[5]; + static Parameter param; + static ParameterScalePoint paramModes[5]; - param.hints = PARAMETER_IS_ENABLED|PARAMETER_IS_AUTOMABLE; param.scalePointCount = 0; param.scalePoints = NULL; @@ -106,8 +140,9 @@ const NativeParameter* lfo_get_parameter_info(NativePluginHandle handle, uint32_ { case PARAM_MODE: param.name = "Mode"; + param.symbol = "mode"; param.unit = NULL; - param.hints |= PARAMETER_IS_INTEGER|PARAMETER_USES_SCALEPOINTS; + param.hints = PARAMETER_IS_ENABLED PARAMETER_IS_INTEGER PARAMETER_USES_SCALEPOINTS; param.ranges.def = 1.0f; param.ranges.min = 1.0f; param.ranges.max = 5.0f; @@ -118,8 +153,10 @@ const NativeParameter* lfo_get_parameter_info(NativePluginHandle handle, uint32_ param.scalePoints = paramModes; break; case PARAM_SPEED: - param.name = "Speed"; - param.unit = "(coef)"; + param.name = "Speed"; + param.symbol = "speed"; + param.unit = "(coef)"; + param.hints = PARAMETER_IS_ENABLED; param.ranges.def = 1.0f; param.ranges.min = 0.01f; param.ranges.max = 2.0f; @@ -128,8 +165,10 @@ const NativeParameter* lfo_get_parameter_info(NativePluginHandle handle, uint32_ param.ranges.stepLarge = 0.5f; break; case PARAM_MULTIPLIER: - param.name = "Multiplier"; - param.unit = "(coef)"; + param.name = "Multiplier"; + param.symbol = "multi"; + param.unit = "(coef)"; + param.hints = PARAMETER_IS_ENABLED; param.ranges.def = 1.0f; param.ranges.min = 0.01f; param.ranges.max = 2.0f; @@ -138,8 +177,10 @@ const NativeParameter* lfo_get_parameter_info(NativePluginHandle handle, uint32_ param.ranges.stepLarge = 0.1f; break; case PARAM_BASE_START: - param.name = "Start value"; - param.unit = NULL; + param.name = "Start value"; + param.symbol = "start"; + param.unit = NULL; + param.hints = PARAMETER_IS_ENABLED; param.ranges.def = 0.0f; param.ranges.min = -1.0f; param.ranges.max = 1.0f; @@ -149,8 +190,9 @@ const NativeParameter* lfo_get_parameter_info(NativePluginHandle handle, uint32_ break; case PARAM_LFO_OUT: param.name = "LFO Out"; + param.symbol = "out"; param.unit = NULL; - param.hints |= PARAMETER_IS_OUTPUT; + param.hints = PARAMETER_IS_ENABLED PARAMETER_IS_OUTPUT; param.ranges.def = 0.0f; param.ranges.min = 0.0f; param.ranges.max = 1.0f; @@ -166,91 +208,140 @@ const NativeParameter* lfo_get_parameter_info(NativePluginHandle handle, uint32_ (void)handle; } -static float lfo_get_parameter_value(NativePluginHandle handle, uint32_t index) +static float lfo_get_parameter_value(PluginHandle handle, uint32_t index) { + LfoHandle* const lfohandle = handlePtr; + switch (index) { case PARAM_MODE: - return (float)handlePtr->mode; + return (float)lfohandle->mode; case PARAM_SPEED: - return (float)handlePtr->speed; + return (float)lfohandle->speed; case PARAM_MULTIPLIER: - return handlePtr->multiplier; + return lfohandle->multiplier; case PARAM_BASE_START: - return handlePtr->baseStart; + return lfohandle->baseStart; case PARAM_LFO_OUT: - return handlePtr->value; + return lfohandle->value; default: return 0.0f; } } -static void lfo_set_parameter_value(NativePluginHandle handle, uint32_t index, float value) +static void lfo_parameter_changed(LfoHandle* const lfohandle, uint32_t index, float value) { switch (index) { case PARAM_MODE: - handlePtr->mode = (int)value; + lfohandle->mode = (int)value; break; case PARAM_SPEED: - handlePtr->speed = value; + lfohandle->speed = value; break; case PARAM_MULTIPLIER: - handlePtr->multiplier = value; + lfohandle->multiplier = value; break; case PARAM_BASE_START: - handlePtr->baseStart = value; - break; - case PARAM_LFO_OUT: - handlePtr->value = value; + lfohandle->baseStart = value; break; } } -static void lfo_process(NativePluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, const NativeMidiEvent* midiEvents, uint32_t midiEventCount) +static float lfo_calculate_value(LfoHandle* const lfohandle, const uint64_t frame, const double bpm, const double sampleRate) { - const NativeHostDescriptor* const host = handlePtr->host; - const NativeTimeInfo* const timeInfo = host->get_time_info(host->handle); - - if (! timeInfo->playing) - return; - - const double bpm = timeInfo->bbt.valid ? timeInfo->bbt.beatsPerMinute : 120.0; - const double sampleRate = host->get_sample_rate(host->handle); - - const double speedRate = handlePtr->speed/(bpm/60.0/sampleRate); - const uint speedRatei = (uint)speedRate; + double value; + double speedRate = lfohandle->speed/(bpm/60.0/sampleRate); + uint speedRatei = (uint)speedRate; - double value = 0.0; - - switch (handlePtr->mode) + switch (lfohandle->mode) { case 1: // Triangle - value = fabs(1.0-(double)(timeInfo->frame % speedRatei)/(speedRate/2.0)); + value = fabs(1.0-(double)(frame % speedRatei)/(speedRate/2.0)); break; case 2: // Sawtooth - value = (double)(timeInfo->frame % speedRatei)/speedRate; + value = (double)(frame % speedRatei)/speedRate; break; case 3: // Sawtooth (inverted) - value = 1.0 - (double)(timeInfo->frame % speedRatei)/speedRate; + value = 1.0 - (double)(frame % speedRatei)/speedRate; break; case 4: // Sine -- TODO! value = 0.0; break; case 5: // Square - value = (timeInfo->frame % speedRatei <= speedRatei/2) ? 1.0 : 0.0; + value = (frame % speedRatei <= speedRatei/2) ? 1.0 : 0.0; break; } - value *= handlePtr->multiplier; - value += handlePtr->baseStart; + value *= lfohandle->multiplier; + value += lfohandle->baseStart; if (value <= 0.0) - handlePtr->value = 0.0f; + { + lfohandle->value = 0.0f; + return 0.0f; + } else if (value >= 1.0) - handlePtr->value = 1.0f; + { + lfohandle->value = 1.0f; + return 1.0f; + } else - handlePtr->value = (float)value; + { + lfohandle->value = (float)value; + return lfohandle->value; + } +} + +static void lfo_activate(PluginHandle handle) +{ + handlePtr->firstRun = true; +} + +static void lfo_process(PluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, const Event* events, uint32_t eventCount) +{ + LfoHandle* const lfohandle = handlePtr; + + const PluginHostDescriptor* const host = lfohandle->host; + const TimeInfo* const timeInfo = host->get_time_info(host->handle); + + uint64_t frame = timeInfo->frame; + double bpm = timeInfo->bbt.valid ? timeInfo->bbt.beatsPerMinute : 120.0; + + ParameterEvent event; + + event.e.type = lfohandle->evTypeParam; + event.e.frame = 0; + event.index = PARAM_LFO_OUT; + + if (lfohandle->firstRun) + { + lfohandle->firstRun = false; + + event.value = lfo_calculate_value(lfohandle, frame, bpm, host->sample_rate); + host->write_event(host->handle, (const Event*)&event); + } + + for (uint32_t i=0; i < eventCount; ++i) + { + const mapped_value_t valType = events[i].type; + + if (valType == lfohandle->evTypeParam) + { + const ParameterEvent* const paramEvent = (const ParameterEvent*)&events[i]; + lfo_parameter_changed(lfohandle, paramEvent->index, paramEvent->value); + + event.e.frame = paramEvent->e.frame; + event.value = lfo_calculate_value(lfohandle, frame, bpm, host->sample_rate); + host->write_event(host->handle, (const Event*)&event); + } + else if (valType == lfohandle->evTypeTime) + { + const TimeInfoEvent* const timeEvent = (const TimeInfoEvent*)&events[i]; + frame = timeEvent->frame; + bpm = timeEvent->bbt.valid ? timeEvent->bbt.beatsPerMinute : 120.0; + } + } return; @@ -258,28 +349,14 @@ static void lfo_process(NativePluginHandle handle, float** inBuffer, float** out (void)inBuffer; (void)outBuffer; (void)frames; - (void)midiEvents; - (void)midiEventCount; } #undef handlePtr // ----------------------------------------------------------------------- -static const NativePluginDescriptor lfoDesc = { - .category = PLUGIN_CATEGORY_UTILITY, - .hints = PLUGIN_IS_RTSAFE, - .supports = 0x0, - .audioIns = 0, - .audioOuts = 0, - .midiIns = 0, - .midiOuts = 0, - .paramIns = PARAM_COUNT-1, - .paramOuts = 1, - .name = "LFO", - .label = "lfo", - .maker = "falkTX", - .copyright = "GNU GPL v2+", +static const PluginDescriptor lfoDesc = { + .metadata = lfo_metadata, .instantiate = lfo_instantiate, .cleanup = lfo_cleanup, @@ -292,32 +369,24 @@ static const NativePluginDescriptor lfoDesc = { .get_midi_program_count = NULL, .get_midi_program_info = NULL, - .set_parameter_value = lfo_set_parameter_value, - .set_midi_program = NULL, - .set_custom_data = NULL, + .idle = NULL, + .non_rt_event = NULL, - .ui_show = NULL, - .ui_idle = NULL, - - .ui_set_parameter_value = NULL, - .ui_set_midi_program = NULL, - .ui_set_custom_data = NULL, + .get_state = NULL, + .set_state = NULL, - .activate = NULL, + .activate = lfo_activate, .deactivate = NULL, .process = lfo_process, - .get_state = NULL, - .set_state = NULL, - .dispatcher = NULL }; // ----------------------------------------------------------------------- -void carla_register_native_plugin_lfo() +void carla_register_daz_plugin_lfo() { - carla_register_native_plugin(&lfoDesc); + carla_register_daz_plugin(&lfoDesc); } // ----------------------------------------------------------------------- diff --git a/source/plugin/carla-native-lv2-export.cpp b/source/plugin/carla-native-lv2-export.cpp index d10294cec..abcdc74d5 100644 --- a/source/plugin/carla-native-lv2-export.cpp +++ b/source/plugin/carla-native-lv2-export.cpp @@ -186,9 +186,13 @@ void writePluginFile(const NativePluginDescriptor* const pluginDesc) hostDesc.ui_save_file = nullptr; hostDesc.dispatcher = host_dispatcher; - NativePluginHandle pluginHandle = pluginDesc->instantiate(&hostDesc); + NativePluginHandle pluginHandle = nullptr; - CARLA_SAFE_ASSERT_RETURN(pluginHandle != nullptr,) + if (! pluginLabel.startsWithIgnoreCase("carla-")) + { + pluginHandle = pluginDesc->instantiate(&hostDesc); + CARLA_SAFE_ASSERT_RETURN(pluginHandle != nullptr,) + } // ------------------------------------------------------------------- // Header @@ -449,7 +453,7 @@ void writePluginFile(const NativePluginDescriptor* const pluginDesc) // ------------------------------------------------------------------- // Parameters - const uint32_t paramCount(pluginDesc->get_parameter_count != nullptr ? pluginDesc->get_parameter_count(pluginHandle) : 0); + const uint32_t paramCount((pluginHandle != nullptr && pluginDesc->get_parameter_count != nullptr) ? pluginDesc->get_parameter_count(pluginHandle) : 0); if (paramCount > 0) { @@ -554,7 +558,7 @@ void writePluginFile(const NativePluginDescriptor* const pluginDesc) // ------------------------------------------------------------------- // Cleanup plugin - if (pluginDesc->cleanup != nullptr) + if (pluginHandle != nullptr && pluginDesc->cleanup != nullptr) pluginDesc->cleanup(pluginHandle); }