Browse Source

Add more files, carla-discovery

tags/1.9.4
falkTX 12 years ago
parent
commit
3a955f2328
15 changed files with 8157 additions and 0 deletions
  1. +581
    -0
      source/backend/carla_backend.hpp
  2. +985
    -0
      source/backend/carla_engine.hpp
  3. +1073
    -0
      source/backend/carla_plugin.hpp
  4. +88
    -0
      source/discovery/Makefile
  5. +1405
    -0
      source/discovery/carla-discovery.cpp
  6. +51
    -0
      source/discovery/carla-discovery.pro
  7. +192
    -0
      source/includes/lv2_atom_queue.hpp
  8. +567
    -0
      source/includes/lv2_rdf.hpp
  9. +459
    -0
      source/utils/carla_backend_utils.hpp
  10. +212
    -0
      source/utils/carla_ladspa_utils.hpp
  11. +98
    -0
      source/utils/carla_lib_utils.hpp
  12. +1173
    -0
      source/utils/carla_lv2_utils.hpp
  13. +348
    -0
      source/utils/carla_osc_utils.hpp
  14. +471
    -0
      source/utils/carla_utils.hpp
  15. +454
    -0
      source/utils/carla_vst_utils.hpp

+ 581
- 0
source/backend/carla_backend.hpp View File

@@ -0,0 +1,581 @@
/*
* Carla Backend
* Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CARLA_BACKEND_HPP
#define CARLA_BACKEND_HPP

#include "carla_defines.hpp"

#include <cstdint>

#define CARLA_BACKEND_START_NAMESPACE namespace CarlaBackend {
#define CARLA_BACKEND_END_NAMESPACE }
#define CARLA_BACKEND_USE_NAMESPACE using namespace CarlaBackend;

CARLA_BACKEND_START_NAMESPACE

#define STR_MAX 0xFF

/*!
* @defgroup CarlaBackendAPI Carla Backend API
*
* The Carla Backend API
*
* @{
*/

#ifdef BUILD_BRIDGE
const unsigned short MAX_PLUGINS = 1;
#else
const unsigned short MAX_PLUGINS = 99; //!< Maximum number of loadable plugins
#endif
const unsigned int MAX_PARAMETERS = 200; //!< Default value for the maximum number of parameters allowed.\see OPTION_MAX_PARAMETERS

/*!
* @defgroup PluginHints Plugin Hints
*
* Various plugin hints.
* \see CarlaPlugin::hints()
* @{
*/
#ifndef BUILD_BRIDGE
const unsigned int PLUGIN_IS_BRIDGE = 0x001; //!< Plugin is a bridge (ie, BridgePlugin). This hint is required because "bridge" itself is not a plugin type.
#endif
const unsigned int PLUGIN_IS_SYNTH = 0x002; //!< Plugin is a synthesizer (produces sound).
const unsigned int PLUGIN_HAS_GUI = 0x004; //!< Plugin has its own custom GUI.
const unsigned int PLUGIN_USES_CHUNKS = 0x008; //!< Plugin uses chunks to save internal data.\see CarlaPlugin::chunkData()
const unsigned int PLUGIN_USES_SINGLE_THREAD = 0x010; //!< Plugin needs a single thread for both DSP processing and UI events.
const unsigned int PLUGIN_CAN_DRYWET = 0x020; //!< Plugin can make use of Dry/Wet controls.
const unsigned int PLUGIN_CAN_VOLUME = 0x040; //!< Plugin can make use of Volume controls.
const unsigned int PLUGIN_CAN_BALANCE = 0x080; //!< Plugin can make use of Left & Right Balance controls.
const unsigned int PLUGIN_CAN_FORCE_STEREO = 0x100; //!< Plugin can be used in forced-stereo mode.
/**@}*/

/*!
* @defgroup ParameterHints Parameter Hints
*
* Various parameter hints.
* \see CarlaPlugin::parameterData()
* @{
*/
const unsigned int PARAMETER_IS_BOOLEAN = 0x01; //!< Parameter value is of boolean type (always at minimum or maximum).
const unsigned int PARAMETER_IS_INTEGER = 0x02; //!< Parameter values are always integer.
const unsigned int PARAMETER_IS_LOGARITHMIC = 0x04; //!< Parameter is logarithmic (informative only, not really implemented).
const unsigned int PARAMETER_IS_ENABLED = 0x08; //!< Parameter is enabled and will be shown in the host built-in editor.
const unsigned int PARAMETER_IS_AUTOMABLE = 0x10; //!< Parameter is automable (realtime safe)
const unsigned int PARAMETER_USES_SAMPLERATE = 0x20; //!< Parameter needs sample rate to work (value and ranges are multiplied by SR, and divided by SR on save).
const unsigned int PARAMETER_USES_SCALEPOINTS = 0x40; //!< Parameter uses scalepoints to define internal values in a meaninful way.
const unsigned int PARAMETER_USES_CUSTOM_TEXT = 0x80; //!< Parameter uses custom text for displaying its value.\see CarlaPlugin::getParameterText()
/**@}*/

/*!
* @defgroup CustomDataTypes Custom Data types
*
* The type defines how the \param value in CustomData is stored.
*
* Types are valid URIs.\n
* Any non-string type is saved in a base64 encoded format.
*/
const char* const CUSTOM_DATA_INVALID = nullptr; //!< Null/Invalid data.
const char* const CUSTOM_DATA_CHUNK = "http://kxstudio.sf.net/ns/carla/chunk"; //!< Carla Chunk
const char* const CUSTOM_DATA_STRING = "http://kxstudio.sf.net/ns/carla/string"; //!< Carla String
/**@}*/

/*!
* @defgroup BridgeMessages Bridge Messages
*
* Various bridge related messages, used as configure(<message>, value).
* \note This is for internal use only.
* @{
*/
const char* const CARLA_BRIDGE_MSG_HIDE_GUI = "CarlaBridgeHideGUI"; //!< Plugin -> Host call, tells host GUI is now hidden
const char* const CARLA_BRIDGE_MSG_SAVED = "CarlaBridgeSaved"; //!< Plugin -> Host call, tells host state is saved
const char* const CARLA_BRIDGE_MSG_SAVE_NOW = "CarlaBridgeSaveNow"; //!< Host -> Plugin call, tells plugin to save state now
const char* const CARLA_BRIDGE_MSG_SET_CHUNK = "CarlaBridgeSetChunk"; //!< Host -> Plugin call, tells plugin to set chunk in file \a value
const char* const CARLA_BRIDGE_MSG_SET_CUSTOM = "CarlaBridgeSetCustom"; //!< Host -> Plugin call, tells plugin to set a custom data set using \a value ("type·key·rvalue").\n If \a type is 'chunk' or 'binary' \a rvalue refers to chunk file.
/**@}*/

/*!
* The binary type of a plugin.
*/
enum BinaryType {
BINARY_NONE = 0, //!< Null binary type.
BINARY_POSIX32 = 1, //!< POSIX 32bit.
BINARY_POSIX64 = 2, //!< POSIX 64bit.
BINARY_WIN32 = 3, //!< Windows 32bit.
BINARY_WIN64 = 4, //!< Windows 64bit.
BINARY_OTHER = 5 //!< Other.
};

/*!
* All the available plugin types, as provided by subclasses of CarlaPlugin.\n
* \note Some plugin classes might provide more than 1 plugin type.
*/
enum PluginType {
PLUGIN_NONE = 0, //!< Null plugin type.
PLUGIN_INTERNAL = 1, //!< Internal plugin.\see NativePlugin
PLUGIN_LADSPA = 2, //!< LADSPA plugin.\see LadspaPlugin
PLUGIN_DSSI = 3, //!< DSSI plugin.\see DssiPlugin
PLUGIN_LV2 = 4, //!< LV2 plugin.\see Lv2Plugin
PLUGIN_VST = 5, //!< VST plugin.\see VstPlugin
PLUGIN_GIG = 6, //!< GIG sound kit, implemented via LinuxSampler.\see LinuxSamplerPlugin
PLUGIN_SF2 = 7, //!< SF2 sound kit (aka SoundFont), implemented via FluidSynth.\see FluidSynthPlugin
PLUGIN_SFZ = 8 //!< SFZ sound kit, implemented via LinuxSampler.\see LinuxSamplerPlugin
};

/*!
* Plugin category, describing the funtionality of a plugin.\n
* When a plugin fails to tell his own category, one is atributted to it based on its name.
*/
enum PluginCategory {
PLUGIN_CATEGORY_NONE = 0, //!< Null plugin category.
PLUGIN_CATEGORY_SYNTH = 1, //!< A synthesizer or generator.
PLUGIN_CATEGORY_DELAY = 2, //!< A delay or reverberator.
PLUGIN_CATEGORY_EQ = 3, //!< An equalizer.
PLUGIN_CATEGORY_FILTER = 4, //!< A filter.
PLUGIN_CATEGORY_DYNAMICS = 5, //!< A 'dynamic' plugin (amplifier, compressor, gate, etc).
PLUGIN_CATEGORY_MODULATOR = 6, //!< A 'modulator' plugin (chorus, flanger, phaser, etc).
PLUGIN_CATEGORY_UTILITY = 7, //!< An 'utility' plugin (analyzer, converter, mixer, etc).
PLUGIN_CATEGORY_OTHER = 8 //!< Misc plugin (used to check if the plugin has a category).
};

/*!
* Plugin parameter type.
*/
enum ParameterType {
PARAMETER_UNKNOWN = 0, //!< Null parameter type.
PARAMETER_INPUT = 1, //!< Input parameter.
PARAMETER_OUTPUT = 2, //!< Ouput parameter.
PARAMETER_LATENCY = 3, //!< Special latency parameter, used in LADSPA, DSSI and LV2 plugins.
PARAMETER_SAMPLE_RATE = 4, //!< Special sample-rate parameter, used in LADSPA, DSSI and LV2 plugins.
PARAMETER_LV2_FREEWHEEL = 5, //!< Special LV2 Plugin parameter used to report freewheel (offline) mode.
PARAMETER_LV2_TIME = 6 //!< Special LV2 Plugin parameter used to report time information.
};

/*!
* Internal parameter indexes.\n
* These are special parameters used internally, plugins do not know about their existence.
*/
enum InternalParametersIndex {
PARAMETER_NULL = -1, //!< Null parameter.
PARAMETER_ACTIVE = -2, //!< Active parameter, can only be 'true' or 'false'; default is 'false'.
PARAMETER_DRYWET = -3, //!< Dry/Wet parameter, range 0.0...1.0; default is 1.0.
PARAMETER_VOLUME = -4, //!< Volume parameter, range 0.0...1.27; default is 1.0.
PARAMETER_BALANCE_LEFT = -5, //!< Balance-Left parameter, range -1.0...1.0; default is -1.0.
PARAMETER_BALANCE_RIGHT = -6 //!< Balance-Right parameter, range -1.0...1.0; default is 1.0.
};

/*!
* Plugin custom GUI type.
* \see OPTION_PREFER_UI_BRIDGES
*/
enum GuiType {
GUI_NONE = 0, //!< Null type, plugin has no custom GUI.
GUI_INTERNAL_QT4 = 1, //!< Qt4 type, handled internally.
GUI_INTERNAL_COCOA = 2, //!< Reparented MacOS native type, handled internally.
GUI_INTERNAL_HWND = 3, //!< Reparented Windows native type, handled internally.
GUI_INTERNAL_X11 = 4, //!< Reparented X11 native type, handled internally.
GUI_EXTERNAL_LV2 = 5, //!< External LV2-UI type, handled internally.
GUI_EXTERNAL_SUIL = 6, //!< SUIL type, currently used only for lv2 gtk2 direct-access UIs.\note This type will be removed in the future!
GUI_EXTERNAL_OSC = 7 //!< External, osc-bridge controlled, UI.
};

/*!
* Options used in the set_option() call.\n
* These options must be set before calling engine_init() or after engine_close().
*/
enum OptionsType {
/*!
* Try to set the current process name.\n
* \note Not available on all platforms.
*/
OPTION_PROCESS_NAME = 0,

/*!
* Set the engine processing mode.\n
* Default is PROCESS_MODE_MULTIPLE_CLIENTS.
* \see ProcessMode
*/
OPTION_PROCESS_MODE = 1,

/*!
* High-Precision processing mode.\n
* When enabled, audio will be processed by blocks of 8 samples at a time, indenpendently of the buffer size.\n
* Default is off.\n
* EXPERIMENTAL!
*/
OPTION_PROCESS_HIGH_PRECISION = 2,

/*!
* Maximum number of parameters allowed.\n
* Default is MAX_PARAMETERS.
*/
OPTION_MAX_PARAMETERS = 3,

/*!
* Prefered buffer size, currently unused.
*/
OPTION_PREFERRED_BUFFER_SIZE = 4,

/*!
* Prefered sample rate, currently unused.
*/
OPTION_PREFERRED_SAMPLE_RATE = 5,

/*!
* Force mono plugins as stereo, by running 2 instances at the same time.\n
* Not supported in VST plugins.
*/
OPTION_FORCE_STEREO = 6,

/*!
* Use (unofficial) dssi-vst chunks feature.\n
* Default is no.\n
* EXPERIMENTAL!
*/
OPTION_USE_DSSI_VST_CHUNKS = 7,

/*!
* Use plugin bridges whenever possible.\n
* Default is no, and not recommended at this point!.
* EXPERIMENTAL!
*/
OPTION_PREFER_PLUGIN_BRIDGES = 8,

/*!
* Use OSC-UI bridges whenever possible, otherwise UIs will be handled in the main thread.\n
* Default is yes.
*/
OPTION_PREFER_UI_BRIDGES = 9,

/*!
* Timeout value in ms for how much to wait for OSC-UIs to respond.\n
* Default is 4000 ms (4 secs).
*/
OPTION_OSC_UI_TIMEOUT = 10,

/*!
* Set path to the POSIX 32bit plugin bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_POSIX32 = 11,

/*!
* Set path to the POSIX 64bit plugin bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_POSIX64 = 12,

/*!
* Set path to the Windows 32bit plugin bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_WIN32 = 13,

/*!
* Set path to the Windows 64bit plugin bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_WIN64 = 14,

/*!
* Set path to the LV2 Gtk2 UI bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_LV2_GTK2 = 15,

/*!
* Set path to the LV2 Gtk3 UI bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_LV2_GTK3 = 16,

/*!
* Set path to the LV2 Qt4 UI bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_LV2_QT4 = 17,

/*!
* Set path to the LV2 Qt5 UI bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_LV2_QT5 = 18,

/*!
* Set path to the LV2 Cocoa UI bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_LV2_COCOA = 19,

/*!
* Set path to the LV2 Windows UI bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_LV2_WINDOWS = 20,

/*!
* Set path to the LV2 X11 UI bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_LV2_X11 = 21,

/*!
* Set path to the VST Cocoa UI bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_VST_COCOA = 22,

/*!
* Set path to the VST HWND UI bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_VST_HWND = 23,

/*!
* Set path to the VST X11 UI bridge executable.\n
* Default unset.
*/
OPTION_PATH_BRIDGE_VST_X11 = 24
};

/*!
* Opcodes sent from the engine callback, as defined by CallbackFunc.
*
* \see set_callback_function()
*/
enum CallbackType {
/*!
* Debug.\n
* This opcode is undefined and used only for testing purposes.
*/
CALLBACK_DEBUG = 0,

/*!
* A parameter has been changed.
*
* \param value1 Parameter index
* \param value3 Value
*/
CALLBACK_PARAMETER_VALUE_CHANGED = 1,

/*!
* A parameter's MIDI channel has been changed.
*
* \param value1 Parameter index
* \param value2 MIDI channel
*/
CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED = 2,

/*!
* A parameter's MIDI CC has been changed.
*
* \param value1 Parameter index
* \param value2 MIDI CC
*/
CALLBACK_PARAMETER_MIDI_CC_CHANGED = 3,

/*!
* The current program has has been changed.
*
* \param value1 Program index
*/
CALLBACK_PROGRAM_CHANGED = 4,

/*!
* The current MIDI program has been changed.
*
* \param value1 MIDI bank
* \param value2 MIDI program
*/
CALLBACK_MIDI_PROGRAM_CHANGED = 5,

/*!
* A note has been pressed.
*
* \param value1 Channel
* \param value2 Note
* \param value3 Velocity
*/
CALLBACK_NOTE_ON = 6,

/*!
* A note has been released.
*
* \param value1 Channel
* \param value2 Note
*/
CALLBACK_NOTE_OFF = 7,

/*!
* The plugin's custom GUI state has changed.
*
* \param value1 State, as follows:.\n
* 0: GUI has been closed or hidden\n
* 1: GUI has been shown\n
* -1: GUI has crashed and should not be shown again\n
*/
CALLBACK_SHOW_GUI = 8,

/*!
* The plugin's custom GUI has been resized.
*
* \param value1 Width
* \param value2 Height
*/
CALLBACK_RESIZE_GUI = 9,

/*!
* The plugin needs update.
*/
CALLBACK_UPDATE = 10,

/*!
* The plugin's data/information has changed.
*/
CALLBACK_RELOAD_INFO = 11,

/*!
* The plugin's parameters have changed.
*/
CALLBACK_RELOAD_PARAMETERS = 12,

/*!
* The plugin's programs have changed.
*/
CALLBACK_RELOAD_PROGRAMS = 13,

/*!
* The plugin's state has changed.
*/
CALLBACK_RELOAD_ALL = 14,

/*!
* Non-Session-Manager Announce message.
*/
CALLBACK_NSM_ANNOUNCE = 15,

/*!
* Non-Session-Manager Open message #1.
*/
CALLBACK_NSM_OPEN1 = 16,

/*!
* Non-Session-Manager Open message #2.
*/
CALLBACK_NSM_OPEN2 = 17,

/*!
* Non-Session-Manager Save message.
*/
CALLBACK_NSM_SAVE = 18,

/*!
* An error occurred, show last error to user.
*/
CALLBACK_ERROR = 19,

/*!
* The engine has crashed or malfunctioned and will no longer work.
*/
CALLBACK_QUIT = 20
};

/*!
* Engine process mode, changed using set_option().
*
* \see OPTION_PROCESS_MODE
*/
enum ProcessMode {
PROCESS_MODE_SINGLE_CLIENT = 0, //!< Single client mode (dynamic input/outputs as needed by plugins)
PROCESS_MODE_MULTIPLE_CLIENTS = 1, //!< Multiple client mode (1 master client + 1 client per plugin)
PROCESS_MODE_CONTINUOUS_RACK = 2, //!< Single client, 'rack' mode. Processes plugins in order of id, with forced stereo.
PROCESS_MODE_PATCHBAY = 3 //!< Single client, 'patchbay' mode.
};

/*!
* Callback function the backend will call when something interesting happens.
*
* \see set_callback_function()
*/
typedef void (*CallbackFunc)(void* ptr, CallbackType action, unsigned short pluginId, int value1, int value2, double value3, const char* valueStr);

struct ParameterData {
ParameterType type;
int32_t index;
int32_t rindex;
int32_t hints;
uint8_t midiChannel;
int16_t midiCC;

ParameterData()
: type(PARAMETER_UNKNOWN),
index(-1),
rindex(-1),
hints(0),
midiChannel(0),
midiCC(-1) {}
};

struct ParameterRanges {
double def;
double min;
double max;
double step;
double stepSmall;
double stepLarge;

ParameterRanges()
: def(0.0),
min(0.0),
max(1.0),
step(0.01),
stepSmall(0.0001),
stepLarge(0.1) {}
};

struct MidiProgramData {
uint32_t bank;
uint32_t program;
const char* name;

MidiProgramData()
: bank(0),
program(0),
name(nullptr) {}
};

struct CustomData {
const char* type;
const char* key;
const char* value;

CustomData()
: type(nullptr),
key(nullptr),
value(nullptr) {}
};

/**@}*/

// forward declarations of commonly used Carla classes
class CarlaEngine;
class CarlaPlugin;

CARLA_BACKEND_END_NAMESPACE

#endif // CARLA_BACKEND_HPP

+ 985
- 0
source/backend/carla_engine.hpp View File

@@ -0,0 +1,985 @@
/*
* Carla Engine
* Copyright (C) 2012 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CARLA_ENGINE_HPP
#define CARLA_ENGINE_HPP

#include "carla_engine_osc.hpp"
#include "carla_engine_thread.hpp"

#include <QtCore/QProcessEnvironment>

CARLA_BACKEND_START_NAMESPACE

/*!
* @defgroup CarlaBackendEngine Carla Backend Engine
*
* The Carla Backend Engine
* @{
*/

/*!
* @defgroup TimeInfoValidHints TimeInfo Valid Hints
*
* Various hints used for CarlaTimeInfo::valid.
* @{
*/
const uint32_t CarlaEngineTimeBBT = 0x1;
/**@}*/

/*!
* The type of an engine.
*/
enum CarlaEngineType {
/*!
* Null engine type.
*/
CarlaEngineTypeNull = 0,

/*!
* Jack engine type.\n
* Provides single, multi-client, and rack processing modes.
*/
CarlaEngineTypeJack = 1,

/*!
* RtAudio engine type, used to provide ALSA, PulseAudio, DirectSound, ASIO and CoreAudio/Midi support.\n
* Provides rack mode processing only.
*/
CarlaEngineTypeRtAudio = 2,

/*!
* Plugin engine type, used to export the engine as a plugin (DSSI, LV2 and VST) via the DISTRHO Plugin Toolkit.\n
* Works in rack mode only.
*/
CarlaEngineTypePlugin = 3
};

/*!
* The type of an engine port.
*/
enum CarlaEnginePortType {
/*!
* Null engine port type.
*/
CarlaEnginePortTypeNull = 0,

/*!
* Audio port.
*/
CarlaEnginePortTypeAudio = 1,

/*!
* Control port.\n
* These are MIDI ports on some engine types, by handling MIDI-CC as control.
*/
CarlaEnginePortTypeControl = 2,

/*!
* MIDI port.
*/
CarlaEnginePortTypeMIDI = 3
};

/*!
* The type of a control event.
*/
enum CarlaEngineControlEventType {
/*!
* Null event type.
*/
CarlaEngineNullEvent = 0,

/*!
* Parameter change event.\n
* \note Value uses a range of 0.0<->1.0.
*/
CarlaEngineParameterChangeEvent = 1,

/*!
* MIDI Bank change event.
*/
CarlaEngineMidiBankChangeEvent = 2,

/*!
* MIDI Program change event.
*/
CarlaEngineMidiProgramChangeEvent = 3,

/*!
* All sound off event.
*/
CarlaEngineAllSoundOffEvent = 4,

/*!
* All notes off event.
*/
CarlaEngineAllNotesOffEvent = 5
};

/*!
* Engine control event.
*/
struct CarlaEngineControlEvent {
CarlaEngineControlEventType type;
uint32_t time;
uint8_t channel;
uint16_t parameter;
double value;

CarlaEngineControlEvent()
: type(CarlaEngineNullEvent),
time(0),
channel(0),
parameter(0),
value(0.0) {}
};

/*!
* Engine MIDI event.
*/
struct CarlaEngineMidiEvent {
uint32_t time;
uint8_t size;
uint8_t data[3];

CarlaEngineMidiEvent()
: time(0),
size(0),
data{0} {}
};

/*!
* Engine BBT Time information.
*/
struct CarlaEngineTimeInfoBBT {
int32_t bar;
int32_t beat;
int32_t tick;
double bar_start_tick;
float beats_per_bar;
float beat_type;
double ticks_per_beat;
double beats_per_minute;

CarlaEngineTimeInfoBBT()
: bar(0),
beat(0),
tick(0),
bar_start_tick(0.0),
beats_per_bar(0.0f),
beat_type(0.0f),
ticks_per_beat(0.0),
beats_per_minute(0.0) {}
};

/*!
* Engine Time information.
*/
struct CarlaEngineTimeInfo {
bool playing;
uint32_t frame;
uint32_t time;
uint32_t valid;
CarlaEngineTimeInfoBBT bbt;

CarlaEngineTimeInfo()
: playing(false),
frame(0),
time(0),
valid(0) {}
};

/*!
* Engine options.
*/
struct CarlaEngineOptions {
ProcessMode processMode;
bool processHighPrecision;

uint maxParameters;
uint preferredBufferSize;
uint preferredSampleRate;

bool forceStereo;
bool useDssiVstChunks;

bool preferPluginBridges;
bool preferUiBridges;
uint oscUiTimeout;

CarlaString bridge_posix32;
CarlaString bridge_posix64;
CarlaString bridge_win32;
CarlaString bridge_win64;
CarlaString bridge_lv2gtk2;
CarlaString bridge_lv2gtk3;
CarlaString bridge_lv2qt4;
CarlaString bridge_lv2qt5;
CarlaString bridge_lv2cocoa;
CarlaString bridge_lv2win;
CarlaString bridge_lv2x11;
CarlaString bridge_vstcocoa;
CarlaString bridge_vsthwnd;
CarlaString bridge_vstx11;

CarlaEngineOptions()
: processMode(PROCESS_MODE_CONTINUOUS_RACK),
processHighPrecision(false),
maxParameters(MAX_PARAMETERS),
preferredBufferSize(512),
preferredSampleRate(44100),
forceStereo(false),
useDssiVstChunks(false),
preferPluginBridges(false),
preferUiBridges(true),
oscUiTimeout(4000/100) {}
};

// -----------------------------------------------------------------------

/*!
* Engine port (Base).\n
* This is the base class for all Carla engine ports.
*/
class CarlaEngineBasePort
{
public:
/*!
* The contructor.\n
* Param \a isInput defines wherever this is an input port or not (output otherwise).\n
* Input/output state is constant for the lifetime of the port.
*/
CarlaEngineBasePort(const bool isInput, const ProcessMode processMode);

/*!
* The decontructor.
*/
virtual ~CarlaEngineBasePort();

/*!
* Get the type of the port, as provided by the respective subclasses.
*/
virtual CarlaEnginePortType type() const = 0;

/*!
* Initialize the port's internal buffer for \a engine.
*/
virtual void initBuffer(CarlaEngine* const engine) = 0;

protected:
const bool isInput;
const ProcessMode processMode;
void* buffer;
};

// -----------------------------------------------------------------------

/*!
* Engine port (Audio).
*/
class CarlaEngineAudioPort : public CarlaEngineBasePort
{
public:
/*!
* The contructor.\n
* Param \a isInput defines wherever this is an input port or not (output otherwise).\n
* Input/output state is constant for the lifetime of the port.
*/
CarlaEngineAudioPort(const bool isInput, const ProcessMode processMode);

/*!
* The decontructor.
*/
virtual ~CarlaEngineAudioPort();

/*!
* Get the type of the port, in this case CarlaEnginePortTypeAudio.
*/
CarlaEnginePortType type() const
{
return CarlaEnginePortTypeAudio;
}

/*!
* Initialize the port's internal buffer for \a engine.
*/
virtual void initBuffer(CarlaEngine* const engine);
};

// -----------------------------------------------------------------------

/*!
* Engine port (Control).
*/
class CarlaEngineControlPort : public CarlaEngineBasePort
{
public:
/*!
* The contructor.\n
* Param \a isInput defines wherever this is an input port or not (output otherwise).\n
* Input/output state is constant for the lifetime of the port.
*/
CarlaEngineControlPort(const bool isInput, const ProcessMode processMode);

/*!
* The decontructor.
*/
virtual ~CarlaEngineControlPort();

/*!
* Get the type of the port, in this case CarlaEnginePortTypeControl.
*/
CarlaEnginePortType type() const
{
return CarlaEnginePortTypeControl;
}

/*!
* Initialize the port's internal buffer for \a engine.
*/
virtual void initBuffer(CarlaEngine* const engine);

/*!
* Get the number of control events present in the buffer.
* \note You must only call this for input ports.
*/
virtual uint32_t getEventCount();

/*!
* Get the control event at \a index.
** \note You must only call this for input ports.
*/
virtual const CarlaEngineControlEvent* getEvent(const uint32_t index);

/*!
* Write a control event to the buffer.\n
* Arguments are the same as in the CarlaEngineControlEvent struct.
** \note You must only call this for output ports.
*/
virtual void writeEvent(const CarlaEngineControlEventType type, const uint32_t time, const uint8_t channel, const uint16_t parameter, const double value);
};

// -----------------------------------------------------------------------

/*!
* Engine port (MIDI).
*/
class CarlaEngineMidiPort : public CarlaEngineBasePort
{
public:
/*!
* The contructor.\n
* Param \a isInput defines wherever this is an input port or not (output otherwise).\n
* Input/output state is constant for the lifetime of the port.
*/
CarlaEngineMidiPort(const bool isInput, const ProcessMode processMode);

/*!
* The decontructor.
*/
virtual ~CarlaEngineMidiPort();

/*!
* Get the type of the port, in this case CarlaEnginePortTypeMIDI.
*/
CarlaEnginePortType type() const
{
return CarlaEnginePortTypeMIDI;
}

/*!
* Initialize the port's internal buffer for \a engine.
*/
virtual void initBuffer(CarlaEngine* const engine);

/*!
* Get the number of MIDI events present in the buffer.
* \note You must only call this for input ports.
*/
virtual uint32_t getEventCount();

/*!
* Get the MIDI event at \a index.
** \note You must only call this for input ports.
*/
virtual const CarlaEngineMidiEvent* getEvent(const uint32_t index);

/*!
* Write a MIDI event to the buffer.\n
* Arguments are the same as in the CarlaEngineMidiEvent struct.
** \note You must only call this for output ports.
*/
virtual void writeEvent(const uint32_t time, const uint8_t* const data, const uint8_t size);
};

// -----------------------------------------------------------------------

/*!
* Engine client.\n
* Each plugin requires one client from the engine (created via CarlaEngine::addPort()).\n
* \note This is a virtual class, each engine type provides its own funtionality.
*/
class CarlaEngineClient
{
public:
/*!
* The contructor.\n
* All constructor parameters are constant and will never change in the lifetime of the client.\n
* Client starts in deactivated state.
*/
CarlaEngineClient(const CarlaEngineType engineType, const ProcessMode processMode);

/*!
* The decontructor.
*/
virtual ~CarlaEngineClient();

/*!
* Activate this client.\n
* \note Client must be deactivated before calling this function.
*/
virtual void activate();

/*!
* Deactivate this client.\n
* \note Client must be activated before calling this function.
*/
virtual void deactivate();

/*!
* Check if the client is activated.
*/
virtual bool isActive() const;

/*!
* Check if the client is ok.\n
* Plugins will refuse to instantiate if this returns false.
* \note This is always true in rack and patchbay processing modes.
*/
virtual bool isOk() const;

/*!
* Get the current latency, in samples.
*/
virtual uint32_t getLatency() const;

/*!
* Change the client's latency.
*/
virtual void setLatency(const uint32_t samples);

/*!
* Add a new port of type \a portType.
* \note This function does nothing in rack processing mode since its ports are static (2 audio, 1 midi and 1 control for both input and output).
*/
virtual const CarlaEngineBasePort* addPort(const CarlaEnginePortType portType, const char* const name, const bool isInput) = 0;

protected:
const CarlaEngineType engineType;
const ProcessMode processMode;

private:
bool m_active;
uint32_t m_latency;
};

// -----------------------------------------------------------------------

/*!
* Carla Engine.
* \note This is a virtual class for all available engine types available in Carla.
*/
class CarlaEngine
{
public:
/*!
* The decontructor.
* The engine must have been closed before this happens.
*/
virtual ~CarlaEngine();

// -------------------------------------------------------------------
// Static values and calls

/*!
* Maximum number of peaks per plugin.\n
* \note There are both input and output peaks.
*/
static const unsigned short MAX_PEAKS = 2;

/*!
* Get the number of available engine drivers.
*/
static unsigned int getDriverCount();

/*!
* Get the name of the engine driver at \a index.
*/
static const char* getDriverName(unsigned int index);

/*!
* Create a new engine, using driver \a driverName.\n
* Returned variable must be deleted when no longer needed.
*/
static CarlaEngine* newDriverByName(const char* const driverName);

// -------------------------------------------------------------------
// Maximum values

/*!
* Maximum client name size.
*/
virtual int maxClientNameSize();

/*!
* Maximum port name size.
*/
virtual int maxPortNameSize();

/*!
* Maximum number of loadable plugins.
* \note This function returns 0 if engine is not started.
*/
unsigned short maxPluginNumber() const;

// -------------------------------------------------------------------
// Virtual, per-engine type calls

/*!
* Initialize engine, using \a clientName.
*/
virtual bool init(const char* const clientName);

/*!
* Close engine.
*/
virtual bool close();

/*!
* Check if engine is running.
*/
virtual bool isRunning() const = 0;

/*!
* Check if engine is running offline (aka freewheel mode).
*/
virtual bool isOffline() const = 0;

/*!
* Get engine type.
*/
virtual CarlaEngineType type() const = 0;

/*!
* Add new engine client.
* \note This must only be called within a plugin class.
*/
virtual CarlaEngineClient* addClient(CarlaPlugin* const plugin) = 0;

// -------------------------------------------------------------------
// Plugin management

/*!
* Get next available plugin id.\n
* Returns -1 if no more plugins can be loaded.
*/
short getNewPluginId() const;

/*!
* Get plugin with id \a id.
*/
CarlaPlugin* getPlugin(const unsigned short id) const;

/*!
* Get plugin with id \a id, faster unchecked version.
*/
CarlaPlugin* getPluginUnchecked(const unsigned short id) const;

/*!
* Get a unique plugin name within the engine.\n
* Returned variable must be free'd when no longer needed.
*/
const char* getUniquePluginName(const char* const name);

/*!
* Add new plugin.\n
* Returns the id of the plugin, or -1 if the operation failed.
*/
short addPlugin(const BinaryType btype, const PluginType ptype, const char* const filename, const char* const name, const char* const label, void* const extra = nullptr);

/*!
* Add new plugin, using native binary type.\n
* Returns the id of the plugin, or -1 if the operation failed.
*/
short addPlugin(const PluginType ptype, const char* const filename, const char* const name, const char* const label, void* const extra = nullptr);

/*!
* Remove plugin with id \a id.
*/
bool removePlugin(const unsigned short id);

/*!
* Remove all plugins.
*/
void removeAllPlugins();

/*!
* Idle all plugins GUIs.
*/
void idlePluginGuis();

// bridge, internal use only
// TODO - find a better way for this
void __bridgePluginRegister(const unsigned short id, CarlaPlugin* const plugin)
{
m_carlaPlugins[id] = plugin;
}

// -------------------------------------------------------------------
// Information (base)

/*!
* Get engine name.
*/
const char* getName() const;

/*!
* Get current sample rate.
*/
double getSampleRate() const;

/*!
* Get current buffer size.
*/
uint32_t getBufferSize() const;

/*!
* Get current Time information.
*/
const CarlaEngineTimeInfo* getTimeInfo() const;

/*!
* Tell the engine it's about to close.\n
* This is used to prevent the engine thread from reactivating.
*/
void aboutToClose();

// -------------------------------------------------------------------
// Information (audio peaks)

double getInputPeak(const unsigned short pluginId, const unsigned short id) const;
double getOutputPeak(const unsigned short pluginId, const unsigned short id) const;
void setInputPeak(const unsigned short pluginId, const unsigned short id, double value);
void setOutputPeak(const unsigned short pluginId, const unsigned short id, double value);

// -------------------------------------------------------------------
// Callback

void callback(const CallbackType action, const unsigned short pluginId, const int value1, const int value2, const double value3, const char* const valueStr);
void setCallback(const CallbackFunc func, void* const ptr);

// -------------------------------------------------------------------
// Error handling

/*!
* Get last error.
*/
const char* getLastError() const;

/*!
* Set last error.
*/
void setLastError(const char* const error);

// -------------------------------------------------------------------
// Options

/*!
* Get the engine options (read-only).
*/
const CarlaEngineOptions& getOptions() const
{
return options;
}

#ifndef BUILD_BRIDGE
/*!
* Get the engine options as process environment.
*/
const QProcessEnvironment& getOptionsAsProcessEnvironment() const
{
return m_procEnv;
}

/*!
* Set the engine option \a option.
*/
void setOption(const OptionsType option, const int value, const char* const valueStr);
#endif

// -------------------------------------------------------------------
// Mutex locks

/*!
* Lock processing.
*/
void processLock();

/*!
* Try Lock processing.
*/
void processTryLock();

/*!
* Unlock processing.
*/
void processUnlock();

/*!
* Lock MIDI.
*/
void midiLock();

/*!
* Try Lock MIDI.
*/
void midiTryLock();

/*!
* Unlock MIDI.
*/
void midiUnlock();

// -------------------------------------------------------------------
// OSC Stuff

#ifndef BUILD_BRIDGE
/*!
* Check if OSC controller is registered.
*/
bool isOscControlRegistered() const;
#else
/*!
* Check if OSC bridge is registered.
*/
bool isOscBridgeRegistered() const;
#endif

/*!
* Idle OSC.
*/
void idleOsc();

/*!
* Get OSC TCP server path.
*/
const char* getOscServerPathTCP() const;

/*!
* Get OSC UDP server path.
*/
const char* getOscServerPathUDP() const;

#ifdef BUILD_BRIDGE
/*!
* Set OSC bridge data.
*/
void setOscBridgeData(const CarlaOscData* const oscData);
#endif

#ifdef BUILD_BRIDGE
void osc_send_peaks(CarlaPlugin* const plugin);
#else
void osc_send_peaks(CarlaPlugin* const plugin, const unsigned short& id);
#endif

#ifdef BUILD_BRIDGE
void osc_send_bridge_audio_count(const int32_t ins, const int32_t outs, const int32_t total);
void osc_send_bridge_midi_count(const int32_t ins, const int32_t outs, const int32_t total);
void osc_send_bridge_parameter_count(const int32_t ins, const int32_t outs, const int32_t total);
void osc_send_bridge_program_count(const int32_t count);
void osc_send_bridge_midi_program_count(const int32_t count);
void osc_send_bridge_plugin_info(const int32_t category, const int32_t hints, const char* const name, const char* const label, const char* const maker, const char* const copyright, const int64_t uniqueId);
void osc_send_bridge_parameter_info(const int32_t index, const char* const name, const char* const unit);
void osc_send_bridge_parameter_data(const int32_t index, const int32_t type, const int32_t rindex, const int32_t hints, const int32_t midiChannel, const int32_t midiCC);
void osc_send_bridge_parameter_ranges(const int32_t index, const double def, const double min, const double max, const double step, const double stepSmall, const double stepLarge);
void osc_send_bridge_program_info(const int32_t index, const char* const name);
void osc_send_bridge_midi_program_info(const int32_t index, const int32_t bank, const int32_t program, const char* const label);
void osc_send_bridge_configure(const char* const key, const char* const value);
void osc_send_bridge_set_parameter_value(const int32_t index, const double value);
void osc_send_bridge_set_default_value(const int32_t index, const double value);
void osc_send_bridge_set_program(const int32_t index);
void osc_send_bridge_set_midi_program(const int32_t index);
void osc_send_bridge_set_custom_data(const char* const type, const char* const key, const char* const value);
void osc_send_bridge_set_chunk_data(const char* const chunkFile);
void osc_send_bridge_set_inpeak(const int32_t portId);
void osc_send_bridge_set_outpeak(const int32_t portId);
#else
void osc_send_control_add_plugin_start(const int32_t pluginId, const char* const pluginName);
void osc_send_control_add_plugin_end(const int32_t pluginId);
void osc_send_control_remove_plugin(const int32_t pluginId);
void osc_send_control_set_plugin_data(const int32_t pluginId, const int32_t type, const int32_t category, const int32_t hints, const char* const realName, const char* const label, const char* const maker, const char* const copyright, const int64_t uniqueId);
void osc_send_control_set_plugin_ports(const int32_t pluginId, const int32_t audioIns, const int32_t audioOuts, const int32_t midiIns, const int32_t midiOuts, const int32_t cIns, const int32_t cOuts, const int32_t cTotals);
void osc_send_control_set_parameter_data(const int32_t pluginId, const int32_t index, const int32_t type, const int32_t hints, const char* const name, const char* const label, const double current);
void osc_send_control_set_parameter_ranges(const int32_t pluginId, const int32_t index, const double min, const double max, const double def, const double step, const double stepSmall, const double stepLarge);
void osc_send_control_set_parameter_midi_cc(const int32_t pluginId, const int32_t index, const int32_t cc);
void osc_send_control_set_parameter_midi_channel(const int32_t pluginId, const int32_t index, const int32_t channel);
void osc_send_control_set_parameter_value(const int32_t pluginId, const int32_t index, const double value);
void osc_send_control_set_default_value(const int32_t pluginId, const int32_t index, const double value);
void osc_send_control_set_program(const int32_t pluginId, const int32_t index);
void osc_send_control_set_program_count(const int32_t pluginId, const int32_t count);
void osc_send_control_set_program_name(const int32_t pluginId, const int32_t index, const char* const name);
void osc_send_control_set_midi_program(const int32_t pluginId, const int32_t index);
void osc_send_control_set_midi_program_count(const int32_t pluginId, const int32_t count);
void osc_send_control_set_midi_program_data(const int32_t pluginId, const int32_t index, const int32_t bank, const int32_t program, const char* const name);
void osc_send_control_note_on(const int32_t pluginId, const int32_t channel, const int32_t note, const int32_t velo);
void osc_send_control_note_off(const int32_t pluginId, const int32_t channel, const int32_t note);
void osc_send_control_set_input_peak_value(const int32_t pluginId, const int32_t portId);
void osc_send_control_set_output_peak_value(const int32_t pluginId, const int32_t portId);
void osc_send_control_exit();
#endif

#ifndef BUILD_BRIDGE
// -------------------------------------------------------------------
// Rack mode

static const unsigned short MAX_CONTROL_EVENTS = 512;
static const unsigned short MAX_MIDI_EVENTS = 512;
CarlaEngineControlEvent rackControlEventsIn[MAX_CONTROL_EVENTS];
CarlaEngineControlEvent rackControlEventsOut[MAX_CONTROL_EVENTS];
CarlaEngineMidiEvent rackMidiEventsIn[MAX_MIDI_EVENTS];
CarlaEngineMidiEvent rackMidiEventsOut[MAX_MIDI_EVENTS];
#endif

// -------------------------------------

/*!
* \class ScopedLocker
*
* \brief Carla engine scoped locker
*
* This is a handy class that temporarily locks an engine during a function scope.
*/
class ScopedLocker
{
public:
/*!
* Lock the engine \a engine if \a lock is true.
* The engine is unlocked in the deconstructor of this class if \a lock is true.
*
* \param engine The engine to lock
* \param lock Wherever to lock the engine or not, true by default
*/
ScopedLocker(CarlaEngine* const engine, bool lock = true)
: mutex(&engine->m_procLock),
m_lock(lock)
{
if (m_lock)
mutex->lock();
}

~ScopedLocker()
{
if (m_lock)
mutex->unlock();
}

private:
QMutex* const mutex;
const bool m_lock;
};

// -------------------------------------

protected:
/*!
* The contructor, protected.\n
* \note This only initializes engine data, it doesn't initialize the engine itself.
*/
CarlaEngine();

#ifndef BUILD_BRIDGE
/*!
* Proccess audio buffer in rack mode, protected.
*/
void processRack(float* inBuf[2], float* outBuf[2], const uint32_t frames);
#endif

CarlaEngineOptions options;

CarlaString name;
uint32_t bufferSize;
double sampleRate;
CarlaEngineTimeInfo timeInfo;

void bufferSizeChanged(const uint32_t newBufferSize);

private:
CarlaEngineOsc m_osc;
CarlaEngineThread m_thread;

const CarlaOscData* m_oscData;

CallbackFunc m_callback;
void* m_callbackPtr;
CarlaString m_lastError;

#ifndef BUILD_BRIDGE
QProcessEnvironment m_procEnv;
#endif

QMutex m_procLock;
QMutex m_midiLock;

CarlaPlugin* m_carlaPlugins[MAX_PLUGINS];
const char* m_uniqueNames[MAX_PLUGINS];

double m_insPeak[MAX_PLUGINS * MAX_PEAKS];
double m_outsPeak[MAX_PLUGINS * MAX_PEAKS];

bool m_aboutToClose;
unsigned short m_maxPluginNumber;

#ifdef CARLA_ENGINE_JACK
static CarlaEngine* newJack();
#endif
#ifdef CARLA_ENGINE_RTAUDIO
enum RtAudioApi {
RTAUDIO_DUMMY = 0,
RTAUDIO_LINUX_ALSA = 1,
RTAUDIO_LINUX_PULSE = 2,
RTAUDIO_LINUX_OSS = 3,
RTAUDIO_UNIX_JACK = 4,
RTAUDIO_MACOSX_CORE = 5,
RTAUDIO_WINDOWS_ASIO = 6,
RTAUDIO_WINDOWS_DS = 7
};

static CarlaEngine* newRtAudio(RtAudioApi api);
static unsigned int getRtAudioApiCount();
static const char* getRtAudioApiName(unsigned int index);
#endif
};

// -----------------------------------------------------------------------

/**@}*/

CARLA_BACKEND_END_NAMESPACE

#endif // CARLA_ENGINE_HPP

+ 1073
- 0
source/backend/carla_plugin.hpp
File diff suppressed because it is too large
View File


+ 88
- 0
source/discovery/Makefile View File

@@ -0,0 +1,88 @@
#!/usr/bin/make -f
# Makefile for carla-discovery #
# ----------------------------------------- #
# Created by falkTX
#

include ../Makefile.mk

# --------------------------------------------------------------

BUILD_CXX_FLAGS += -I../backend -I../includes -I../utils
BUILD_CXX_FLAGS += $(shell pkg-config --cflags QtCore)
LINK_FLAGS += $(shell pkg-config --libs QtCore)

ifeq ($(CARLA_PLUGIN_SUPPORT),true)
BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST
endif

ifeq ($(HAVE_FLUIDSYNTH),true)
NATIVE_FLAGS += $(shell pkg-config --cflags --libs fluidsynth) -DWANT_FLUIDSYNTH
endif

ifeq ($(HAVE_LINUXSAMPLER),true)
NATIVE_FLAGS += $(shell pkg-config --cflags --libs linuxsampler) -DWANT_LINUXSAMPLER
endif

# --------------------------------------------------------------

POSIX_BUILD_FLAGS = $(BUILD_CXX_FLAGS)
POSIX_32BIT_FLAGS = $(32BIT_FLAGS) -L/usr/lib32 -L/usr/lib/i386-linux-gnu
POSIX_64BIT_FLAGS = $(64BIT_FLAGS) -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu
POSIX_LINK_FLAGS = $(LINK_FLAGS) -ldl
#-lpthread

WIN_BUILD_FLAGS = $(BUILD_CXX_FLAGS)
WIN_32BIT_FLAGS = $(32BIT_FLAGS)
WIN_64BIT_FLAGS = $(64BIT_FLAGS)
WIN_LINK_FLAGS = $(LINK_FLAGS) -static -mwindows -lole32 -luuid -lws2_32

# --------------------------------------------------------------

all: carla-discovery-native

posix32: carla-discovery-posix32
posix64: carla-discovery-posix64
win32: carla-discovery-win32.exe
win64: carla-discovery-win64.exe

# --------------------------------------------------------------

OBJS = carla-discovery.cpp

carla-discovery-native: $(OBJS) ../libs/lilv.a
$(CXX) $^ $(POSIX_BUILD_FLAGS) $(POSIX_LINK_FLAGS) $(NATIVE_FLAGS) -o $@ && $(STRIP) $@

carla-discovery-posix32: $(OBJS) ../libs/lilv_posix32.a
$(CXX) $^ $(POSIX_BUILD_FLAGS) $(POSIX_32BIT_FLAGS) $(POSIX_LINK_FLAGS) -o $@ && $(STRIP) $@

carla-discovery-posix64: $(OBJS) ../libs/lilv_posix64.a
$(CXX) $^ $(POSIX_BUILD_FLAGS) $(POSIX_64BIT_FLAGS) $(POSIX_LINK_FLAGS) -o $@ && $(STRIP) $@

carla-discovery-win32.exe: $(OBJS) ../libs/lilv_win32.a
$(CXX) $^ $(WIN_BUILD_FLAGS) $(WIN_32BIT_FLAGS) $(WIN_LINK_FLAGS) -o $@ && $(STRIP) $@

carla-discovery-win64.exe: $(OBJS) ../libs/lilv_win64.a
$(CXX) $^ $(WIN_BUILD_FLAGS) $(WIN_64BIT_FLAGS) $(WIN_LINK_FLAGS) -o $@ && $(STRIP) $@

# --------------------------------------------------------------

../libs/lilv.a:
$(MAKE) -C ../libs/lilv

../libs/lilv_posix32.a:
$(MAKE) -C ../libs/lilv posix32

../libs/lilv_posix64.a:
$(MAKE) -C ../libs/lilv posix64

../libs/lilv_win32.a:
$(MAKE) -C ../libs/lilv win32

../libs/lilv_win64.a:
$(MAKE) -C ../libs/lilv win64

# --------------------------------------------------------------

clean:
rm -f carla-discovery-*

+ 1405
- 0
source/discovery/carla-discovery.cpp
File diff suppressed because it is too large
View File


+ 51
- 0
source/discovery/carla-discovery.pro View File

@@ -0,0 +1,51 @@
# QtCreator project file

QT = core

win {
CONFIG = release
} else {
CONFIG = debug
}
CONFIG += link_pkgconfig qt warn_on

DEFINES = DEBUG
DEFINES += WANT_LADSPA WANT_DSSI WANT_LV2 WANT_VST
DEFINES += WANT_FLUIDSYNTH WANT_LINUXSAMPLER
PKGCONFIG = fluidsynth linuxsampler

TARGET = carla-discovery-qtcreator
TEMPLATE = app
VERSION = 0.5.0

SOURCES = \
carla-discovery.cpp

HEADERS = \
../includes/carla_defines.hpp \
../includes/carla_midi.h \
../includes/ladspa_rdf.hpp \
../includes/lv2_rdf.hpp \
../backend/carla_backend.hpp \
../utils/carla_utils.hpp \
../utils/carla_lib_utils.hpp \
../utils/carla_ladspa_utils.hpp \
../utils/carla_lv2_utils.hpp \
../utils/carla_vst_utils.hpp

INCLUDEPATH = \
../backend \
../includes \
../utils

LIBS = \
../libs/lilv.a

unix {
LIBS += -ldl
}
mingw {
LIBS += -static -mwindows
}

QMAKE_CXXFLAGS *= -std=c++0x

+ 192
- 0
source/includes/lv2_atom_queue.hpp View File

@@ -0,0 +1,192 @@
/*
* Simple Queue, specially developed for Atom types
* Copyright (C) 2012 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef __LV2_ATOM_QUEUE_HPP__
#define __LV2_ATOM_QUEUE_HPP__

#include "carla_utils.hpp"
#include "lv2/atom.h"

#include <cstring> // memcpy, memset
#include <pthread.h>

class Lv2AtomQueue
{
public:
Lv2AtomQueue()
: mutex(PTHREAD_MUTEX_INITIALIZER)
{
index = indexPool = 0;
empty = true;
full = false;

::memset(dataPool, 0, sizeof(unsigned char)*MAX_POOL_SIZE);
}

void copyDataFrom(Lv2AtomQueue* const queue)
{
// lock mutexes
queue->lock();
lock();

// copy data from queue
::memcpy(data, queue->data, sizeof(datatype)*MAX_SIZE);
::memcpy(dataPool, queue->dataPool, sizeof(unsigned char)*MAX_POOL_SIZE);
index = queue->index;
indexPool = queue->indexPool;
empty = queue->empty;
full = queue->full;

// unlock our mutex, no longer needed
unlock();

// reset queque
::memset(queue->data, 0, sizeof(datatype)*MAX_SIZE);
::memset(queue->dataPool, 0, sizeof(unsigned char)*MAX_POOL_SIZE);
queue->index = queue->indexPool = 0;
queue->empty = true;
queue->full = false;

// unlock queque mutex
queue->unlock();
}

bool isEmpty()
{
return empty;
}

bool isFull()
{
return full;
}

bool lock()
{
return (pthread_mutex_lock(&mutex) == 0);
}

bool tryLock()
{
return (pthread_mutex_trylock(&mutex) == 0);
}

bool unlock()
{
return (pthread_mutex_unlock(&mutex) == 0);
}

void put(const uint32_t portIndex, const LV2_Atom* const atom)
{
CARLA_ASSERT(atom && atom->size > 0);
CARLA_ASSERT(indexPool + atom->size < MAX_POOL_SIZE); // overflow

if (full || atom->size == 0 || indexPool + atom->size >= MAX_POOL_SIZE)
return;

lock();

for (unsigned short i=0; i < MAX_SIZE; i++)
{
if (data[i].size == 0)
{
data[i].portIndex = portIndex;
data[i].size = atom->size;
data[i].type = atom->type;
data[i].poolOffset = indexPool;
::memcpy(dataPool + indexPool, (const unsigned char*)LV2_ATOM_BODY_CONST(atom), atom->size);
empty = false;
full = (i == MAX_SIZE-1);
indexPool += atom->size;
break;
}
}

unlock();
}

bool get(uint32_t* const portIndex, const LV2_Atom** const atom)
{
CARLA_ASSERT(portIndex && atom);

if (empty || ! (portIndex && atom))
return false;

if (! tryLock())
return false;

full = false;

if (data[index].size == 0)
{
index = indexPool = 0;
empty = true;

unlock();
return false;
}

retAtom.atom.size = data[index].size;
retAtom.atom.type = data[index].type;
::memcpy(retAtom.data, dataPool + data[index].poolOffset, data[index].size);

*portIndex = data[index].portIndex;
*atom = (LV2_Atom*)&retAtom;

data[index].portIndex = 0;
data[index].size = 0;
data[index].type = 0;
data[index].poolOffset = 0;
index++;
empty = false;

unlock();
return true;
}

private:
struct datatype {
size_t size;
uint32_t type;
uint32_t portIndex;
uint32_t poolOffset;

datatype()
: size(0),
type(0),
portIndex(0),
poolOffset(0) {}
};

static const unsigned short MAX_SIZE = 128;
static const unsigned short MAX_POOL_SIZE = 8192;

datatype data[MAX_SIZE];
unsigned char dataPool[MAX_POOL_SIZE];

struct {
LV2_Atom atom;
unsigned char data[MAX_POOL_SIZE];
} retAtom;

unsigned short index, indexPool;
bool empty, full;

pthread_mutex_t mutex;
};

#endif // __LV2_ATOM_QUEUE_HPP__

+ 567
- 0
source/includes/lv2_rdf.hpp View File

@@ -0,0 +1,567 @@
/*
* Custom types to store LV2 information
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef LV2_RDF_INCLUDED
#define LV2_RDF_INCLUDED

#include <cstdint>
#include <cstdlib>

// Base Types
typedef const char* LV2_URI;
typedef uint32_t LV2_Property;

struct LV2_Type {
LV2_Property Value;
LV2_URI URI;

LV2_Type()
: Value(0),
URI(nullptr) {}

~LV2_Type()
{
if (URI)
::free((void*)URI);
}
};

// Port Midi Map Types
#define LV2_PORT_MIDI_MAP_CC 0x1
#define LV2_PORT_MIDI_MAP_NRPN 0x2

#define LV2_IS_PORT_MIDI_MAP_CC(x) ((x) == LV2_PORT_MIDI_MAP_CC)
#define LV2_IS_PORT_MIDI_MAP_NRPN(x) ((x) == LV2_PORT_MIDI_MAP_NRPN)

// Port Point Hints
#define LV2_PORT_POINT_DEFAULT 0x1
#define LV2_PORT_POINT_MINIMUM 0x2
#define LV2_PORT_POINT_MAXIMUM 0x4

#define LV2_HAVE_DEFAULT_PORT_POINT(x) ((x) & LV2_PORT_POINT_DEFAULT)
#define LV2_HAVE_MINIMUM_PORT_POINT(x) ((x) & LV2_PORT_POINT_MINIMUM)
#define LV2_HAVE_MAXIMUM_PORT_POINT(x) ((x) & LV2_PORT_POINT_MAXIMUM)

// Port Unit Hints
#define LV2_PORT_UNIT_NAME 0x1
#define LV2_PORT_UNIT_RENDER 0x2
#define LV2_PORT_UNIT_SYMBOL 0x4
#define LV2_PORT_UNIT_UNIT 0x8

#define LV2_HAVE_PORT_UNIT_NAME(x) ((x) & LV2_PORT_UNIT_NAME)
#define LV2_HAVE_PORT_UNIT_RENDER(x) ((x) & LV2_PORT_UNIT_RENDER)
#define LV2_HAVE_PORT_UNIT_SYMBOL(x) ((x) & LV2_PORT_UNIT_SYMBOL)
#define LV2_HAVE_PORT_UNIT_UNIT(x) ((x) & LV2_PORT_UNIT_UNIT)

// Port Unit Unit
#define LV2_PORT_UNIT_BAR 0x01
#define LV2_PORT_UNIT_BEAT 0x02
#define LV2_PORT_UNIT_BPM 0x03
#define LV2_PORT_UNIT_CENT 0x04
#define LV2_PORT_UNIT_CM 0x05
#define LV2_PORT_UNIT_COEF 0x06
#define LV2_PORT_UNIT_DB 0x07
#define LV2_PORT_UNIT_DEGREE 0x08
#define LV2_PORT_UNIT_FRAME 0x09
#define LV2_PORT_UNIT_HZ 0x0A
#define LV2_PORT_UNIT_INCH 0x0B
#define LV2_PORT_UNIT_KHZ 0x0C
#define LV2_PORT_UNIT_KM 0x0D
#define LV2_PORT_UNIT_M 0x0E
#define LV2_PORT_UNIT_MHZ 0x0F
#define LV2_PORT_UNIT_MIDINOTE 0x10
#define LV2_PORT_UNIT_MILE 0x11
#define LV2_PORT_UNIT_MIN 0x12
#define LV2_PORT_UNIT_MM 0x13
#define LV2_PORT_UNIT_MS 0x14
#define LV2_PORT_UNIT_OCT 0x15
#define LV2_PORT_UNIT_PC 0x16
#define LV2_PORT_UNIT_S 0x17
#define LV2_PORT_UNIT_SEMITONE 0x18

#define LV2_IS_PORT_UNIT_BAR(x) ((x) == LV2_PORT_UNIT_BAR)
#define LV2_IS_PORT_UNIT_BEAT(x) ((x) == LV2_PORT_UNIT_BEAT)
#define LV2_IS_PORT_UNIT_BPM(x) ((x) == LV2_PORT_UNIT_BPM)
#define LV2_IS_PORT_UNIT_CENT(x) ((x) == LV2_PORT_UNIT_CENT)
#define LV2_IS_PORT_UNIT_CM(x) ((x) == LV2_PORT_UNIT_CM)
#define LV2_IS_PORT_UNIT_COEF(x) ((x) == LV2_PORT_UNIT_COEF)
#define LV2_IS_PORT_UNIT_DB(x) ((x) == LV2_PORT_UNIT_DB)
#define LV2_IS_PORT_UNIT_DEGREE(x) ((x) == LV2_PORT_UNIT_DEGREE)
#define LV2_IS_PORT_UNIT_FRAME(x) ((x) == LV2_PORT_UNIT_FRAME)
#define LV2_IS_PORT_UNIT_HZ(x) ((x) == LV2_PORT_UNIT_HZ)
#define LV2_IS_PORT_UNIT_INCH(x) ((x) == LV2_PORT_UNIT_INCH)
#define LV2_IS_PORT_UNIT_KHZ(x) ((x) == LV2_PORT_UNIT_KHZ)
#define LV2_IS_PORT_UNIT_KM(x) ((x) == LV2_PORT_UNIT_KM)
#define LV2_IS_PORT_UNIT_M(x) ((x) == LV2_PORT_UNIT_M)
#define LV2_IS_PORT_UNIT_MHZ(x) ((x) == LV2_PORT_UNIT_MHZ)
#define LV2_IS_PORT_UNIT_MIDINOTE(x) ((x) == LV2_PORT_UNIT_MIDINOTE)
#define LV2_IS_PORT_UNIT_MILE(x) ((x) == LV2_PORT_UNIT_MILE)
#define LV2_IS_PORT_UNIT_MIN(x) ((x) == LV2_PORT_UNIT_MIN)
#define LV2_IS_PORT_UNIT_MM(x) ((x) == LV2_PORT_UNIT_MM)
#define LV2_IS_PORT_UNIT_MS(x) ((x) == LV2_PORT_UNIT_MS)
#define LV2_IS_PORT_UNIT_OCT(x) ((x) == LV2_PORT_UNIT_OCT)
#define LV2_IS_PORT_UNIT_PC(x) ((x) == LV2_PORT_UNIT_PC)
#define LV2_IS_PORT_UNIT_S(x) ((x) == LV2_PORT_UNIT_S)
#define LV2_IS_PORT_UNIT_SEMITONE(x) ((x) == LV2_PORT_UNIT_SEMITONE)

// Port Types
#define LV2_PORT_INPUT 0x01
#define LV2_PORT_OUTPUT 0x02
#define LV2_PORT_CONTROL 0x04
#define LV2_PORT_AUDIO 0x08
#define LV2_PORT_CV 0x10
#define LV2_PORT_ATOM 0x20
#define LV2_PORT_ATOM_SEQUENCE (0x40 | LV2_PORT_ATOM)
#define LV2_PORT_EVENT 0x80
#define LV2_PORT_MIDI_LL 0x100

// Port Data Types
#define LV2_PORT_DATA_MIDI_EVENT 0x1000
#define LV2_PORT_DATA_PATCH_MESSAGE 0x2000

#define LV2_IS_PORT_INPUT(x) ((x) & LV2_PORT_INPUT)
#define LV2_IS_PORT_OUTPUT(x) ((x) & LV2_PORT_OUTPUT)
#define LV2_IS_PORT_CONTROL(x) ((x) & LV2_PORT_CONTROL)
#define LV2_IS_PORT_AUDIO(x) ((x) & LV2_PORT_AUDIO)
#define LV2_IS_PORT_ATOM_SEQUENCE(x) ((x) & LV2_PORT_ATOM_SEQUENCE)
#define LV2_IS_PORT_CV(x) ((x) & LV2_PORT_CV)
#define LV2_IS_PORT_EVENT(x) ((x) & LV2_PORT_EVENT)
#define LV2_IS_PORT_MIDI_LL(x) ((x) & LV2_PORT_MIDI_LL)

#define LV2_PORT_SUPPORTS_MIDI_EVENT ((x) & LV2_PORT_DATA_MIDI_EVENT)
#define LV2_PORT_SUPPORTS_PATCH_MESSAGE ((x) & LV2_PORT_DATA_PATCH_MESSAGE)

// Port Properties
#define LV2_PORT_OPTIONAL 0x0001
#define LV2_PORT_ENUMERATION 0x0002
#define LV2_PORT_INTEGER 0x0004
#define LV2_PORT_SAMPLE_RATE 0x0008
#define LV2_PORT_TOGGLED 0x0010
#define LV2_PORT_CAUSES_ARTIFACTS 0x0020
#define LV2_PORT_CONTINUOUS_CV 0x0040
#define LV2_PORT_DISCRETE_CV 0x0080
#define LV2_PORT_EXPENSIVE 0x0100
#define LV2_PORT_STRICT_BOUNDS 0x0200
#define LV2_PORT_LOGARITHMIC 0x0400
#define LV2_PORT_NOT_AUTOMATIC 0x0800
#define LV2_PORT_NOT_ON_GUI 0x1000
#define LV2_PORT_TRIGGER 0x2000

#define LV2_IS_PORT_OPTIONAL(x) ((x) & LV2_PORT_OPTIONAL)
#define LV2_IS_PORT_ENUMERATION(x) ((x) & LV2_PORT_ENUMERATION)
#define LV2_IS_PORT_INTEGER(x) ((x) & LV2_PORT_INTEGER)
#define LV2_IS_PORT_SAMPLE_RATE(x) ((x) & LV2_PORT_SAMPLE_RATE)
#define LV2_IS_PORT_TOGGLED(x) ((x) & LV2_PORT_TOGGLED)
#define LV2_IS_PORT_CAUSES_ARTIFACTS(x) ((x) & LV2_PORT_CAUSES_ARTIFACTS)
#define LV2_IS_PORT_CONTINUOUS_CV(x) ((x) & LV2_PORT_CONTINUOUS_CV)
#define LV2_IS_PORT_DISCRETE_CV(x) ((x) & LV2_PORT_DISCRETE_CV)
#define LV2_IS_PORT_EXPENSIVE(x) ((x) & LV2_PORT_EXPENSIVE)
#define LV2_IS_PORT_STRICT_BOUNDS(x) ((x) & LV2_PORT_STRICT_BOUNDS)
#define LV2_IS_PORT_LOGARITHMIC(x) ((x) & LV2_PORT_LOGARITHMIC)
#define LV2_IS_PORT_NOT_AUTOMATIC(x) ((x) & LV2_PORT_NOT_AUTOMATIC)
#define LV2_IS_PORT_NOT_ON_GUI(x) ((x) & LV2_PORT_NOT_ON_GUI)
#define LV2_IS_PORT_TRIGGER(x) ((x) & LV2_PORT_TRIGGER)

// Port Designation
#define LV2_PORT_DESIGNATION_FREEWHEELING 0x1
#define LV2_PORT_DESIGNATION_LATENCY 0x2
#define LV2_PORT_DESIGNATION_SAMPLE_RATE 0x3
#define LV2_PORT_DESIGNATION_TIME_BAR 0x4
#define LV2_PORT_DESIGNATION_TIME_BAR_BEAT 0x5
#define LV2_PORT_DESIGNATION_TIME_BEAT 0x6
#define LV2_PORT_DESIGNATION_TIME_BEAT_UNIT 0x7
#define LV2_PORT_DESIGNATION_TIME_BEATS_PER_BAR 0x8
#define LV2_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE 0x9
#define LV2_PORT_DESIGNATION_TIME_FRAME 0xA
#define LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND 0xB
#define LV2_PORT_DESIGNATION_TIME_POSITION 0xC
#define LV2_PORT_DESIGNATION_TIME_SPEED 0xD

#define LV2_IS_PORT_DESIGNATION_FREEWHEELING(x) ((x) == LV2_PORT_DESIGNATION_FREEWHEELING)
#define LV2_IS_PORT_DESIGNATION_LATENCY(x) ((x) == LV2_PORT_DESIGNATION_LATENCY)
#define LV2_IS_PORT_DESIGNATION_SAMPLE_RATE(x) ((x) == LV2_PORT_DESIGNATION_SAMPLE_RATE)
#define LV2_IS_PORT_DESIGNATION_TIME_BAR(x) ((x) == LV2_PORT_DESIGNATION_TIME_BAR)
#define LV2_IS_PORT_DESIGNATION_TIME_BAR_BEAT(x) ((x) == LV2_PORT_DESIGNATION_TIME_BAR_BEAT)
#define LV2_IS_PORT_DESIGNATION_TIME_BEAT(x) ((x) == LV2_PORT_DESIGNATION_TIME_BEAT)
#define LV2_IS_PORT_DESIGNATION_TIME_BEAT_UNIT(x) ((x) == LV2_PORT_DESIGNATION_TIME_BEAT_UNIT)
#define LV2_IS_PORT_DESIGNATION_TIME_BEATS_PER_BAR(x) ((x) == LV2_PORT_DESIGNATION_TIME_BEATS_PER_BAR)
#define LV2_IS_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE(x) ((x) == LV2_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE)
#define LV2_IS_PORT_DESIGNATION_TIME_FRAME(x) ((x) == LV2_PORT_DESIGNATION_TIME_FRAME)
#define LV2_IS_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND(x) ((x) == LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND)
#define LV2_IS_PORT_DESIGNATION_TIME_POSITION(x) ((x) == LV2_PORT_DESIGNATION_TIME_POSITION)
#define LV2_IS_PORT_DESIGNATION_TIME_SPEED(x) ((x) == LV2_PORT_DESIGNATION_TIME_SPEED)
#define LV2_IS_PORT_DESIGNATION_TIME(x) ((x) >= LV2_PORT_DESIGNATION_TIME_BAR && (x) <= LV2_PORT_DESIGNATION_TIME_SPEED)

// Feature Types
#define LV2_FEATURE_OPTIONAL 0x1
#define LV2_FEATURE_REQUIRED 0x2

#define LV2_IS_FEATURE_OPTIONAL(x) ((x) == LV2_FEATURE_OPTIONAL)
#define LV2_IS_FEATURE_REQUIRED(x) ((x) == LV2_FEATURE_REQUIRED)

// UI Types
#define LV2_UI_GTK2 0x1
#define LV2_UI_GTK3 0x2
#define LV2_UI_QT4 0x3
#define LV2_UI_QT5 0x4
#define LV2_UI_COCOA 0x5
#define LV2_UI_WINDOWS 0x6
#define LV2_UI_X11 0x7
#define LV2_UI_EXTERNAL 0x8
#define LV2_UI_OLD_EXTERNAL 0x9

#define LV2_IS_UI_GTK2(x) ((x) == LV2_UI_GTK2)
#define LV2_IS_UI_GTK3(x) ((x) == LV2_UI_GTK3)
#define LV2_IS_UI_QT4(x) ((x) == LV2_UI_QT4)
#define LV2_IS_UI_QT5(x) ((x) == LV2_UI_QT5)
#define LV2_IS_UI_COCOA(x) ((x) == LV2_UI_COCOA)
#define LV2_IS_UI_WINDOWS(x) ((x) == LV2_UI_WINDOWS)
#define LV2_IS_UI_X11(x) ((x) == LV2_UI_X11)
#define LV2_IS_UI_EXTERNAL(x) ((x) == LV2_UI_EXTERNAL)
#define LV2_IS_UI_OLD_EXTERNAL(x) ((x) == LV2_UI_OLD_EXTERNAL)

// Plugin Types
#define LV2_PLUGIN_DELAY 0x000001
#define LV2_PLUGIN_REVERB 0x000002
#define LV2_PLUGIN_SIMULATOR 0x000004
#define LV2_PLUGIN_DISTORTION 0x000008
#define LV2_PLUGIN_WAVESHAPER 0x000010
#define LV2_PLUGIN_DYNAMICS 0x000020
#define LV2_PLUGIN_AMPLIFIER 0x000040
#define LV2_PLUGIN_COMPRESSOR 0x000080
#define LV2_PLUGIN_ENVELOPE 0x000100
#define LV2_PLUGIN_EXPANDER 0x000200
#define LV2_PLUGIN_GATE 0x000400
#define LV2_PLUGIN_LIMITER 0x000800
#define LV2_PLUGIN_EQ 0x001000
#define LV2_PLUGIN_MULTI_EQ 0x002000
#define LV2_PLUGIN_PARA_EQ 0x004000
#define LV2_PLUGIN_FILTER 0x008000
#define LV2_PLUGIN_ALLPASS 0x010000
#define LV2_PLUGIN_BANDPASS 0x020000
#define LV2_PLUGIN_COMB 0x040000
#define LV2_PLUGIN_HIGHPASS 0x080000
#define LV2_PLUGIN_LOWPASS 0x100000

#define LV2_PLUGIN_GENERATOR 0x000001
#define LV2_PLUGIN_CONSTANT 0x000002
#define LV2_PLUGIN_INSTRUMENT 0x000004
#define LV2_PLUGIN_OSCILLATOR 0x000008
#define LV2_PLUGIN_MODULATOR 0x000010
#define LV2_PLUGIN_CHORUS 0x000020
#define LV2_PLUGIN_FLANGER 0x000040
#define LV2_PLUGIN_PHASER 0x000080
#define LV2_PLUGIN_SPATIAL 0x000100
#define LV2_PLUGIN_SPECTRAL 0x000200
#define LV2_PLUGIN_PITCH 0x000400
#define LV2_PLUGIN_UTILITY 0x000800
#define LV2_PLUGIN_ANALYSER 0x001000
#define LV2_PLUGIN_CONVERTER 0x002000
#define LV2_PLUGIN_FUNCTION 0x008000
#define LV2_PLUGIN_MIXER 0x010000

#define LV2_GROUP_DELAY (LV2_PLUGIN_DELAY|LV2_PLUGIN_REVERB)
#define LV2_GROUP_DISTORTION (LV2_PLUGIN_DISTORTION|LV2_PLUGIN_WAVESHAPER)
#define LV2_GROUP_DYNAMICS (LV2_PLUGIN_DYNAMICS|LV2_PLUGIN_AMPLIFIER|LV2_PLUGIN_COMPRESSOR|LV2_PLUGIN_ENVELOPE|LV2_PLUGIN_EXPANDER|LV2_PLUGIN_GATE|LV2_PLUGIN_LIMITER)
#define LV2_GROUP_EQ (LV2_PLUGIN_EQ|LV2_PLUGIN_MULTI_EQ|LV2_PLUGIN_PARA_EQ)
#define LV2_GROUP_FILTER (LV2_PLUGIN_FILTER|LV2_PLUGIN_ALLPASS|LV2_PLUGIN_BANDPASS|LV2_PLUGIN_COMB|LV2_GROUP_EQ|LV2_PLUGIN_HIGHPASS|LV2_PLUGIN_LOWPASS)
#define LV2_GROUP_GENERATOR (LV2_PLUGIN_GENERATOR|LV2_PLUGIN_CONSTANT|LV2_PLUGIN_INSTRUMENT|LV2_PLUGIN_OSCILLATOR)
#define LV2_GROUP_MODULATOR (LV2_PLUGIN_MODULATOR|LV2_PLUGIN_CHORUS|LV2_PLUGIN_FLANGER|LV2_PLUGIN_PHASER)
#define LV2_GROUP_REVERB (LV2_PLUGIN_REVERB)
#define LV2_GROUP_SIMULATOR (LV2_PLUGIN_SIMULATOR|LV2_PLUGIN_REVERB)
#define LV2_GROUP_SPATIAL (LV2_PLUGIN_SPATIAL)
#define LV2_GROUP_SPECTRAL (LV2_PLUGIN_SPECTRAL|LV2_PLUGIN_PITCH)
#define LV2_GROUP_UTILITY (LV2_PLUGIN_UTILITY|LV2_PLUGIN_ANALYSER|LV2_PLUGIN_CONVERTER|LV2_PLUGIN_FUNCTION|LV2_PLUGIN_MIXER)

#define LV2_IS_DELAY(x, y) (((x) & LV2_GROUP_DELAY) || ((y) & LV2_GROUP_DELAY))
#define LV2_IS_DISTORTION(x, y) (((x) & LV2_GROUP_DISTORTION) || ((y) & LV2_GROUP_DISTORTION))
#define LV2_IS_DYNAMICS(x, y) (((x) & LV2_GROUP_DYNAMICS) || ((y) & LV2_GROUP_DYNAMICS))
#define LV2_IS_EQ(x, y) (((x) & LV2_GROUP_EQ) || ((y) & LV2_GROUP_EQ))
#define LV2_IS_FILTER(x, y) (((x) & LV2_GROUP_FILTER) || ((y) & LV2_GROUP_FILTER))
#define LV2_IS_GENERATOR(x, y) (((x) & LV2_GROUP_GENERATOR) || ((y) & LV2_GROUP_GENERATOR))
#define LV2_IS_MODULATOR(x, y) (((x) & LV2_GROUP_MODULATOR) || ((y) & LV2_GROUP_MODULATOR))
#define LV2_IS_REVERB(x, y) (((x) & LV2_GROUP_REVERB) || ((y) & LV2_GROUP_REVERB))
#define LV2_IS_SIMULATOR(x, y) (((x) & LV2_GROUP_SIMULATOR) || ((y) & LV2_GROUP_SIMULATOR))
#define LV2_IS_SPATIAL(x, y) (((x) & LV2_GROUP_SPATIAL) || ((y) & LV2_GROUP_SPATIAL))
#define LV2_IS_SPECTRAL(x, y) (((x) & LV2_GROUP_SPECTRAL) || ((y) & LV2_GROUP_SPECTRAL))
#define LV2_IS_UTILITY(x, y) (((x) & LV2_GROUP_UTILITY) || ((y) & LV2_GROUP_UTILITY))

// Port Midi Map
struct LV2_RDF_PortMidiMap {
LV2_Property Type;
uint32_t Number;

LV2_RDF_PortMidiMap()
: Type(0),
Number(0) {}
};

// Port Points
struct LV2_RDF_PortPoints {
LV2_Property Hints;
float Default;
float Minimum;
float Maximum;

LV2_RDF_PortPoints()
: Hints(0x0),
Default(0.0f),
Minimum(0.0f),
Maximum(1.0f) {}
};

// Port Unit
struct LV2_RDF_PortUnit {
LV2_Property Hints;
const char* Name;
const char* Render;
const char* Symbol;
LV2_Property Unit;

LV2_RDF_PortUnit()
: Hints(0x0),
Name(nullptr),
Render(nullptr),
Symbol(nullptr),
Unit(0) {}

~LV2_RDF_PortUnit()
{
if (Name)
::free((void*)Name);

if (Render)
::free((void*)Render);

if (Symbol)
::free((void*)Symbol);
}
};

// Port Scale Point
struct LV2_RDF_PortScalePoint {
const char* Label;
float Value;

LV2_RDF_PortScalePoint()
: Label(nullptr),
Value(0.0f) {}

~LV2_RDF_PortScalePoint()
{
if (Label)
::free((void*)Label);
}
};

// Port
struct LV2_RDF_Port {
LV2_Property Types;
LV2_Property Properties;
LV2_Property Designation;
const char* Name;
const char* Symbol;

LV2_RDF_PortMidiMap MidiMap;
LV2_RDF_PortPoints Points;
LV2_RDF_PortUnit Unit;

uint32_t ScalePointCount;
LV2_RDF_PortScalePoint* ScalePoints;

LV2_RDF_Port()
: Types(0x0),
Properties(0x0),
Designation(0),
Name(nullptr),
Symbol(nullptr),
ScalePointCount(0),
ScalePoints(nullptr) {}

~LV2_RDF_Port()
{
if (Name)
::free((void*)Name);

if (Symbol)
::free((void*)Symbol);

if (ScalePoints)
delete[] ScalePoints;
}
};

// Preset
struct LV2_RDF_Preset {
LV2_URI URI;
const char* Label;

LV2_RDF_Preset()
: URI(nullptr),
Label(nullptr) {}

~LV2_RDF_Preset()
{
if (URI)
::free((void*)URI);

if (Label)
::free((void*)Label);
}
};

// Feature
struct LV2_RDF_Feature {
LV2_Property Type;
LV2_URI URI;

LV2_RDF_Feature()
: Type(0),
URI(nullptr) {}

~LV2_RDF_Feature()
{
if (URI)
::free((void*)URI);
}
};

// UI
struct LV2_RDF_UI {
LV2_Type Type;
LV2_URI URI;
const char* Binary;
const char* Bundle;

uint32_t FeatureCount;
LV2_RDF_Feature* Features;

uint32_t ExtensionCount;
LV2_URI* Extensions;

LV2_RDF_UI()
: URI(nullptr),
Binary(nullptr),
Bundle(nullptr),
FeatureCount(0),
Features(nullptr),
ExtensionCount(0),
Extensions(nullptr) {}

~LV2_RDF_UI()
{
if (URI)
::free((void*)URI);

if (Binary)
::free((void*)Binary);

if (Bundle)
::free((void*)Bundle);

if (Features)
delete[] Features;

if (Extensions)
delete[] Extensions;
}
};

// Plugin
struct LV2_RDF_Descriptor {
LV2_Property Type[2];
LV2_URI URI;
const char* Name;
const char* Author;
const char* License;
const char* Binary;
const char* Bundle;
unsigned long UniqueID;

uint32_t PortCount;
LV2_RDF_Port* Ports;

uint32_t PresetCount;
LV2_RDF_Preset* Presets;

uint32_t FeatureCount;
LV2_RDF_Feature* Features;

uint32_t ExtensionCount;
LV2_URI* Extensions;

uint32_t UICount;
LV2_RDF_UI* UIs;

LV2_RDF_Descriptor()
: Type{0x0, 0x0}, // FIXME ?
URI(nullptr),
Name(nullptr),
Author(nullptr),
License(nullptr),
Binary(nullptr),
Bundle(nullptr),
UniqueID(0),
PortCount(0),
Ports(nullptr),
PresetCount(0),
Presets(nullptr),
FeatureCount(0),
Features(nullptr),
ExtensionCount(0),
Extensions(nullptr),
UICount(0),
UIs(nullptr) {}

~LV2_RDF_Descriptor()
{
if (URI)
::free((void*)URI);

if (Name)
::free((void*)Name);

if (Author)
::free((void*)Author);

if (License)
::free((void*)License);

if (Binary)
::free((void*)Binary);

if (Bundle)
::free((void*)Bundle);

if (Ports)
delete[] Ports;

if (Presets)
delete[] Presets;

if (Features)
delete[] Features;

if (Extensions)
delete[] Extensions;

if (UIs)
delete[] UIs;
}
};

#endif // LV2_RDF_INCLUDED

+ 459
- 0
source/utils/carla_backend_utils.hpp View File

@@ -0,0 +1,459 @@
/*
* Carla Backend
* Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CARLA_BACKEND_UTILS_HPP
#define CARLA_BACKEND_UTILS_HPP

#include "carla_backend.hpp"
#include "carla_utils.hpp"

CARLA_BACKEND_START_NAMESPACE

/*!
* @defgroup CarlaBackendUtils Carla Backend Utils
*
* Carla Backend Utils
*
* @{
*/

static inline
const char* BinaryType2Str(const BinaryType& type)
{
switch (type)
{
case BINARY_NONE:
return "BINARY_NONE";
case BINARY_POSIX32:
return "BINARY_POSIX32";
case BINARY_POSIX64:
return "BINARY_POSIX64";
case BINARY_WIN32:
return "BINARY_WIN32";
case BINARY_WIN64:
return "BINARY_WIN64";
case BINARY_OTHER:
return "BINARY_OTHER";
}

qWarning("CarlaBackend::BinaryType2Str(%i) - invalid type", type);
return nullptr;
}

static inline
const char* PluginType2Str(const PluginType& type)
{
switch (type)
{
case PLUGIN_NONE:
return "PLUGIN_NONE";
case PLUGIN_INTERNAL:
return "PLUGIN_INTERNAL";
case PLUGIN_LADSPA:
return "PLUGIN_LADSPA";
case PLUGIN_DSSI:
return "PLUGIN_DSSI";
case PLUGIN_LV2:
return "PLUGIN_LV2";
case PLUGIN_VST:
return "PLUGIN_VST";
case PLUGIN_GIG:
return "PLUGIN_GIG";
case PLUGIN_SF2:
return "PLUGIN_SF2";
case PLUGIN_SFZ:
return "PLUGIN_SFZ";
}

qWarning("CarlaBackend::PluginType2Str(%i) - invalid type", type);
return nullptr;
}

static inline
const char* PluginCategory2Str(const PluginCategory& category)
{
switch (category)
{
case PLUGIN_CATEGORY_NONE:
return "PLUGIN_CATEGORY_NONE";
case PLUGIN_CATEGORY_SYNTH:
return "PLUGIN_CATEGORY_SYNTH";
case PLUGIN_CATEGORY_DELAY:
return "PLUGIN_CATEGORY_DELAY";
case PLUGIN_CATEGORY_EQ:
return "PLUGIN_CATEGORY_EQ";
case PLUGIN_CATEGORY_FILTER:
return "PLUGIN_CATEGORY_FILTER";
case PLUGIN_CATEGORY_DYNAMICS:
return "PLUGIN_CATEGORY_DYNAMICS";
case PLUGIN_CATEGORY_MODULATOR:
return "PLUGIN_CATEGORY_MODULATOR";
case PLUGIN_CATEGORY_UTILITY:
return "PLUGIN_CATEGORY_UTILITY";
case PLUGIN_CATEGORY_OTHER:
return "PLUGIN_CATEGORY_OTHER";
}

qWarning("CarlaBackend::PluginCategory2Str(%i) - invalid category", category);
return nullptr;
}

static inline
const char* ParameterType2Str(const ParameterType& type)
{
switch (type)
{
case PARAMETER_UNKNOWN:
return "PARAMETER_UNKNOWN";
case PARAMETER_INPUT:
return "PARAMETER_INPUT";
case PARAMETER_OUTPUT:
return "PARAMETER_OUTPUT";
case PARAMETER_LATENCY:
return "PARAMETER_LATENCY";
case PARAMETER_SAMPLE_RATE:
return "PARAMETER_SAMPLE_RATE";
case PARAMETER_LV2_FREEWHEEL:
return "PARAMETER_LV2_FREEWHEEL";
case PARAMETER_LV2_TIME:
return "PARAMETER_LV2_TIME";
}

qWarning("CarlaBackend::ParameterType2Str(%i) - invalid type", type);
return nullptr;
}

static inline
const char* InternalParametersIndex2Str(const InternalParametersIndex& index)
{
switch (index)
{
case PARAMETER_NULL:
return "PARAMETER_NULL";
case PARAMETER_ACTIVE:
return "PARAMETER_ACTIVE";
case PARAMETER_DRYWET:
return "PARAMETER_DRYWET";
case PARAMETER_VOLUME:
return "PARAMETER_VOLUME";
case PARAMETER_BALANCE_LEFT:
return "PARAMETER_BALANCE_LEFT";
case PARAMETER_BALANCE_RIGHT:
return "PARAMETER_BALANCE_RIGHT";
}

qWarning("CarlaBackend::InternalParametersIndex2Str(%i) - invalid index", index);
return nullptr;
}

static inline
const char* GuiType2Str(const GuiType& type)
{
switch (type)
{
case GUI_NONE:
return "GUI_NONE";
case GUI_INTERNAL_QT4:
return "GUI_INTERNAL_QT4";
case GUI_INTERNAL_COCOA:
return "GUI_INTERNAL_COCOA";
case GUI_INTERNAL_HWND:
return "GUI_INTERNAL_HWND";
case GUI_INTERNAL_X11:
return "GUI_INTERNAL_X11";
case GUI_EXTERNAL_LV2:
return "GUI_EXTERNAL_LV2";
case GUI_EXTERNAL_SUIL:
return "GUI_EXTERNAL_SUIL";
case GUI_EXTERNAL_OSC:
return "GUI_EXTERNAL_OSC";
}

qWarning("CarlaBackend::GuiType2Str(%i) - invalid type", type);
return nullptr;
}

static inline
const char* OptionsType2Str(const OptionsType& type)
{
switch (type)
{
case OPTION_PROCESS_NAME:
return "OPTION_PROCESS_NAME";
case OPTION_PROCESS_MODE:
return "OPTION_PROCESS_MODE";
case OPTION_PROCESS_HIGH_PRECISION:
return "OPTION_PROCESS_HIGH_PRECISION";
case OPTION_MAX_PARAMETERS:
return "OPTION_MAX_PARAMETERS";
case OPTION_PREFERRED_BUFFER_SIZE:
return "OPTION_PREFERRED_BUFFER_SIZE";
case OPTION_PREFERRED_SAMPLE_RATE:
return "OPTION_PREFERRED_SAMPLE_RATE";
case OPTION_FORCE_STEREO:
return "OPTION_FORCE_STEREO";
case OPTION_USE_DSSI_VST_CHUNKS:
return "OPTION_USE_DSSI_VST_CHUNKS";
case OPTION_PREFER_PLUGIN_BRIDGES:
return "OPTION_PREFER_PLUGIN_BRIDGES";
case OPTION_PREFER_UI_BRIDGES:
return "OPTION_PREFER_UI_BRIDGES";
case OPTION_OSC_UI_TIMEOUT:
return "OPTION_OSC_UI_TIMEOUT";
case OPTION_PATH_BRIDGE_POSIX32:
return "OPTION_PATH_BRIDGE_POSIX32";
case OPTION_PATH_BRIDGE_POSIX64:
return "OPTION_PATH_BRIDGE_POSIX64";
case OPTION_PATH_BRIDGE_WIN32:
return "OPTION_PATH_BRIDGE_WIN32";
case OPTION_PATH_BRIDGE_WIN64:
return "OPTION_PATH_BRIDGE_WIN64";
case OPTION_PATH_BRIDGE_LV2_GTK2:
return "OPTION_PATH_BRIDGE_LV2_GTK2";
case OPTION_PATH_BRIDGE_LV2_GTK3:
return "OPTION_PATH_BRIDGE_LV2_GTK3";
case OPTION_PATH_BRIDGE_LV2_QT4:
return "OPTION_PATH_BRIDGE_LV2_QT4";
case OPTION_PATH_BRIDGE_LV2_QT5:
return "OPTION_PATH_BRIDGE_LV2_QT5";
case OPTION_PATH_BRIDGE_LV2_COCOA:
return "OPTION_PATH_BRIDGE_LV2_COCOA";
case OPTION_PATH_BRIDGE_LV2_WINDOWS:
return "OPTION_PATH_BRIDGE_LV2_WINDOWS";
case OPTION_PATH_BRIDGE_LV2_X11:
return "OPTION_PATH_BRIDGE_LV2_X11";
case OPTION_PATH_BRIDGE_VST_COCOA:
return "OPTION_PATH_BRIDGE_VST_COCOA";
case OPTION_PATH_BRIDGE_VST_HWND:
return "OPTION_PATH_BRIDGE_VST_HWND";
case OPTION_PATH_BRIDGE_VST_X11:
return "OPTION_PATH_BRIDGE_VST_X11";
}

qWarning("CarlaBackend::OptionsType2Str(%i) - invalid type", type);
return nullptr;
}

static inline
const char* CallbackType2Str(const CallbackType& type)
{
switch (type)
{
case CALLBACK_DEBUG:
return "CALLBACK_DEBUG";
case CALLBACK_PARAMETER_VALUE_CHANGED:
return "CALLBACK_PARAMETER_VALUE_CHANGED";
case CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED:
return "CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED";
case CALLBACK_PARAMETER_MIDI_CC_CHANGED:
return "CALLBACK_PARAMETER_MIDI_CC_CHANGED";
case CALLBACK_PROGRAM_CHANGED:
return "CALLBACK_PROGRAM_CHANGED";
case CALLBACK_MIDI_PROGRAM_CHANGED:
return "CALLBACK_MIDI_PROGRAM_CHANGED";
case CALLBACK_NOTE_ON:
return "CALLBACK_NOTE_ON";
case CALLBACK_NOTE_OFF:
return "CALLBACK_NOTE_OFF";
case CALLBACK_SHOW_GUI:
return "CALLBACK_SHOW_GUI";
case CALLBACK_RESIZE_GUI:
return "CALLBACK_RESIZE_GUI";
case CALLBACK_UPDATE:
return "CALLBACK_UPDATE";
case CALLBACK_RELOAD_INFO:
return "CALLBACK_RELOAD_INFO";
case CALLBACK_RELOAD_PARAMETERS:
return "CALLBACK_RELOAD_PARAMETERS";
case CALLBACK_RELOAD_PROGRAMS:
return "CALLBACK_RELOAD_PROGRAMS";
case CALLBACK_RELOAD_ALL:
return "CALLBACK_RELOAD_ALL";
case CALLBACK_NSM_ANNOUNCE:
return "CALLBACK_NSM_ANNOUNCE";
case CALLBACK_NSM_OPEN1:
return "CALLBACK_NSM_OPEN1";
case CALLBACK_NSM_OPEN2:
return "CALLBACK_NSM_OPEN2";
case CALLBACK_NSM_SAVE:
return "CALLBACK_NSM_SAVE";
case CALLBACK_ERROR:
return "CALLBACK_ERROR";
case CALLBACK_QUIT:
return "CALLBACK_QUIT";
}

qWarning("CarlaBackend::CallbackType2Str(%i) - invalid type", type);
return nullptr;
}

static inline
const char* ProcessMode2Str(const ProcessMode& mode)
{
switch (mode)
{
case PROCESS_MODE_SINGLE_CLIENT:
return "PROCESS_MODE_SINGLE_CLIENT";
case PROCESS_MODE_MULTIPLE_CLIENTS:
return "PROCESS_MODE_MULTIPLE_CLIENTS";
case PROCESS_MODE_CONTINUOUS_RACK:
return "PROCESS_MODE_CONTINUOUS_RACK";
case PROCESS_MODE_PATCHBAY:
return "PROCESS_MODE_PATCHBAY";
}

qWarning("CarlaBackend::ProcessModeType2Str(%i) - invalid type", mode);
return nullptr;
}

// -------------------------------------------------------------------------------------------------------------------

static inline
const char* getPluginTypeString(const PluginType& type)
{
qDebug("CarlaBackend::getPluginTypeString(%s)", PluginType2Str(type));

switch (type)
{
case PLUGIN_NONE:
return "NONE";
case PLUGIN_INTERNAL:
return "INTERNAL";
case PLUGIN_LADSPA:
return "LADSPA";
case PLUGIN_DSSI:
return "DSSI";
case PLUGIN_LV2:
return "LV2";
case PLUGIN_VST:
return "VST";
case PLUGIN_GIG:
return "GIG";
case PLUGIN_SF2:
return "SF2";
case PLUGIN_SFZ:
return "SFZ";
}

return "NONE";
}

// -------------------------------------------------------------------------------------------------------------------

static inline
uintptr_t getAddressFromPointer(void* const ptr)
{
qDebug("CarlaBackend::getAddressFromPointer(%p)", ptr);
CARLA_ASSERT(ptr != nullptr);

uintptr_t* addr = (uintptr_t*)&ptr;
return *addr;
}

static inline
void* getPointerFromAddress(const uintptr_t& addr)
{
CARLA_ASSERT(addr != 0);

uintptr_t** const ptr = (uintptr_t**)&addr;
return *ptr;
}

static inline
PluginCategory getPluginCategoryFromName(const char* const name)
{
qDebug("CarlaBackend::getPluginCategoryFromName(\"%s\")", name);
CARLA_ASSERT(name);

if (! name)
return PLUGIN_CATEGORY_NONE;

CarlaString sname(name);

if (sname.isEmpty())
return PLUGIN_CATEGORY_NONE;

sname.toLower();

// generic tags first
if (sname.contains("delay"))
return PLUGIN_CATEGORY_DELAY;
if (sname.contains("reverb"))
return PLUGIN_CATEGORY_DELAY;

// filter
if (sname.contains("filter"))
return PLUGIN_CATEGORY_FILTER;

// dynamics
if (sname.contains("dynamics"))
return PLUGIN_CATEGORY_DYNAMICS;
if (sname.contains("amplifier"))
return PLUGIN_CATEGORY_DYNAMICS;
if (sname.contains("compressor"))
return PLUGIN_CATEGORY_DYNAMICS;
if (sname.contains("enhancer"))
return PLUGIN_CATEGORY_DYNAMICS;
if (sname.contains("exciter"))
return PLUGIN_CATEGORY_DYNAMICS;
if (sname.contains("gate"))
return PLUGIN_CATEGORY_DYNAMICS;
if (sname.contains("limiter"))
return PLUGIN_CATEGORY_DYNAMICS;

// modulator
if (sname.contains("modulator"))
return PLUGIN_CATEGORY_MODULATOR;
if (sname.contains("chorus"))
return PLUGIN_CATEGORY_MODULATOR;
if (sname.contains("flanger"))
return PLUGIN_CATEGORY_MODULATOR;
if (sname.contains("phaser"))
return PLUGIN_CATEGORY_MODULATOR;
if (sname.contains("saturator"))
return PLUGIN_CATEGORY_MODULATOR;

// utility
if (sname.contains("utility"))
return PLUGIN_CATEGORY_UTILITY;
if (sname.contains("analyzer"))
return PLUGIN_CATEGORY_UTILITY;
if (sname.contains("converter"))
return PLUGIN_CATEGORY_UTILITY;
if (sname.contains("deesser"))
return PLUGIN_CATEGORY_UTILITY;
if (sname.contains("mixer"))
return PLUGIN_CATEGORY_UTILITY;

// common tags
if (sname.contains("verb"))
return PLUGIN_CATEGORY_DELAY;

if (sname.contains("eq"))
return PLUGIN_CATEGORY_EQ;

if (sname.contains("tool"))
return PLUGIN_CATEGORY_UTILITY;

return PLUGIN_CATEGORY_NONE;
}

/**@}*/

CARLA_BACKEND_END_NAMESPACE

#endif // CARLA_BACKEND_UTILS_HPP

+ 212
- 0
source/utils/carla_ladspa_utils.hpp View File

@@ -0,0 +1,212 @@
/*
* Carla LADSPA utils
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef __CARLA_LADSPA_UTILS_HPP__
#define __CARLA_LADSPA_UTILS_HPP__

#include "carla_utils.hpp"

#include "ladspa/ladspa.h"
#include "ladspa_rdf.hpp"

#include <cmath>
#include <cstring>

// -------------------------------------------------
// Copy RDF object

static inline
const LADSPA_RDF_Descriptor* ladspa_rdf_dup(const LADSPA_RDF_Descriptor* const oldDescriptor)
{
CARLA_ASSERT(oldDescriptor);

if (! oldDescriptor)
return nullptr;

LADSPA_RDF_Descriptor* const newDescriptor = new LADSPA_RDF_Descriptor;

newDescriptor->Type = oldDescriptor->Type;
newDescriptor->UniqueID = oldDescriptor->UniqueID;
newDescriptor->PortCount = oldDescriptor->PortCount;

if (oldDescriptor->Title)
newDescriptor->Title = strdup(oldDescriptor->Title);

if (oldDescriptor->Creator)
newDescriptor->Creator = strdup(oldDescriptor->Creator);

if (newDescriptor->PortCount > 0)
{
newDescriptor->Ports = new LADSPA_RDF_Port[newDescriptor->PortCount];

for (unsigned long i=0; i < newDescriptor->PortCount; i++)
{
LADSPA_RDF_Port* const newPort = &newDescriptor->Ports[i];
newPort->Type = oldDescriptor->Ports[i].Type;
newPort->Hints = oldDescriptor->Ports[i].Hints;
newPort->Default = oldDescriptor->Ports[i].Default;
newPort->Unit = oldDescriptor->Ports[i].Unit;
newPort->ScalePointCount = oldDescriptor->Ports[i].ScalePointCount;

if (oldDescriptor->Ports[i].Label)
newPort->Label = strdup(oldDescriptor->Ports[i].Label);

if (newPort->ScalePointCount > 0)
{
newPort->ScalePoints = new LADSPA_RDF_ScalePoint[newPort->ScalePointCount];

for (unsigned long j=0; j < newPort->ScalePointCount; j++)
{
LADSPA_RDF_ScalePoint* const newScalePoint = &newPort->ScalePoints[j];
newScalePoint->Value = oldDescriptor->Ports[i].ScalePoints[j].Value;

if (oldDescriptor->Ports[i].ScalePoints[j].Label)
newScalePoint->Label = strdup(oldDescriptor->Ports[i].ScalePoints[j].Label);
}
}
}
}

return newDescriptor;
}

// -------------------------------------------------
// Check if 2 ports match types

static inline
bool is_ladspa_port_good(const LADSPA_PortDescriptor port1, const LADSPA_PortDescriptor port2)
{
if (LADSPA_IS_PORT_INPUT(port1) && ! LADSPA_IS_PORT_INPUT(port2))
return false;
if (LADSPA_IS_PORT_OUTPUT(port1) && ! LADSPA_IS_PORT_OUTPUT(port2))
return false;
if (LADSPA_IS_PORT_CONTROL(port1) && ! LADSPA_IS_PORT_CONTROL(port2))
return false;
if (LADSPA_IS_PORT_AUDIO(port1) && ! LADSPA_IS_PORT_AUDIO(port2))
return false;
return true;
}

// -------------------------------------------------
// Check if rdf data matches descriptor

static inline
bool is_ladspa_rdf_descriptor_valid(const LADSPA_RDF_Descriptor* const rdfDescriptor, const LADSPA_Descriptor* const descriptor)
{
CARLA_ASSERT(rdfDescriptor);
CARLA_ASSERT(descriptor);

if (! rdfDescriptor)
return false;
if (! descriptor)
return false;

if (rdfDescriptor->UniqueID != descriptor->UniqueID)
{
qWarning("WARNING - Plugin has wrong UniqueID: %li != %li", rdfDescriptor->UniqueID, descriptor->UniqueID);
return false;
}

if (rdfDescriptor->PortCount > descriptor->PortCount)
{
qWarning("WARNING - Plugin has RDF data, but invalid PortCount: %li > %li", rdfDescriptor->PortCount, descriptor->PortCount);
return false;
}

for (unsigned long i=0; i < rdfDescriptor->PortCount; i++)
{
if (! is_ladspa_port_good(rdfDescriptor->Ports[i].Type, descriptor->PortDescriptors[i]))
{
qWarning("WARNING - Plugin has RDF data, but invalid PortTypes: %i != %i", rdfDescriptor->Ports[i].Type, descriptor->PortDescriptors[i]);
return false;
}
}

return true;
}

// -------------------------------------------------
// Get default control port value

static inline
LADSPA_Data get_default_ladspa_port_value(const LADSPA_PortRangeHintDescriptor hintDescriptor, const LADSPA_Data min, const LADSPA_Data max)
{
LADSPA_Data def;

if (LADSPA_IS_HINT_HAS_DEFAULT(hintDescriptor))
{
switch (hintDescriptor & LADSPA_HINT_DEFAULT_MASK)
{
case LADSPA_HINT_DEFAULT_MINIMUM:
def = min;
break;
case LADSPA_HINT_DEFAULT_MAXIMUM:
def = max;
break;
case LADSPA_HINT_DEFAULT_0:
def = 0.0f;
break;
case LADSPA_HINT_DEFAULT_1:
def = 1.0f;
break;
case LADSPA_HINT_DEFAULT_100:
def = 100.0f;
break;
case LADSPA_HINT_DEFAULT_440:
def = 440.0f;
break;
case LADSPA_HINT_DEFAULT_LOW:
if (LADSPA_IS_HINT_LOGARITHMIC(hintDescriptor))
def = std::exp((std::log(min)*0.75f) + (std::log(max)*0.25f));
else
def = (min*0.75f) + (max*0.25f);
break;
case LADSPA_HINT_DEFAULT_MIDDLE:
if (LADSPA_IS_HINT_LOGARITHMIC(hintDescriptor))
def = std::sqrt(min*max);
else
def = (min+max)/2;
break;
case LADSPA_HINT_DEFAULT_HIGH:
if (LADSPA_IS_HINT_LOGARITHMIC(hintDescriptor))
def = std::exp((std::log(min)*0.25f) + (std::log(max)*0.75f));
else
def = (min*0.25f) + (max*0.75f);
break;
default:
if (min < 0.0f && max > 0.0f)
def = 0.0f;
else
def = min;
break;
}
}
else
{
// no default value
if (min < 0.0f && max > 0.0f)
def = 0.0f;
else
def = min;
}

return def;
}

// -------------------------------------------------

#endif // __CARLA_LADSPA_UTILS_HPP__

+ 98
- 0
source/utils/carla_lib_utils.hpp View File

@@ -0,0 +1,98 @@
/*
* Carla library utils
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef __CARLA_LIB_UTILS_HPP__
#define __CARLA_LIB_UTILS_HPP__

#include "carla_utils.hpp"

#ifndef Q_OS_WIN
# include <dlfcn.h>
#endif

// -------------------------------------------------
// library related calls

static inline
void* lib_open(const char* const filename)
{
CARLA_ASSERT(filename);

#ifdef Q_OS_WIN
return LoadLibraryA(filename);
#else
return dlopen(filename, RTLD_NOW|RTLD_LOCAL);
#endif
}

static inline
bool lib_close(void* const lib)
{
CARLA_ASSERT(lib);

if (! lib)
return false;

#ifdef Q_OS_WIN
return FreeLibrary((HMODULE)lib);
#else
return (dlclose(lib) == 0);
#endif
}

static inline
void* lib_symbol(void* const lib, const char* const symbol)
{
CARLA_ASSERT(lib);
CARLA_ASSERT(symbol);

if (! (lib && symbol))
return nullptr;

#ifdef Q_OS_WIN
return (void*)GetProcAddress((HMODULE)lib, symbol);
#else
return dlsym(lib, symbol);
#endif
}

static inline
const char* lib_error(const char* const filename)
{
CARLA_ASSERT(filename);

#ifdef Q_OS_WIN
static char libError[2048];
memset(libError, 0, sizeof(char)*2048);

LPVOID winErrorString;
DWORD winErrorCode = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, winErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&winErrorString, 0, nullptr);

snprintf(libError, 2048, "%s: error code %li: %s", filename, winErrorCode, (const char*)winErrorString);
LocalFree(winErrorString);

return libError;
#else
return dlerror();
Q_UNUSED(filename);
#endif
}

// -------------------------------------------------

#endif // __CARLA_LIB_UTILS_HPP__

+ 1173
- 0
source/utils/carla_lv2_utils.hpp
File diff suppressed because it is too large
View File


+ 348
- 0
source/utils/carla_osc_utils.hpp View File

@@ -0,0 +1,348 @@
/*
* Carla OSC utils
* Copyright (C) 2012 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CARLA_OSC_UTILS_HPP
#define CARLA_OSC_UTILS_HPP

#include "carla_utils.hpp"

#include <cstdint>
#include <lo/lo.h>

// ------------------------------------------------------------------------------------------------

struct CarlaOscData {
const char* path;
lo_address source;
lo_address target;

CarlaOscData()
: path(nullptr),
source(nullptr),
target(nullptr) {}

~CarlaOscData()
{
free();
}

void free()
{
if (path)
::free((void*)path);

if (source)
::lo_address_free(source);

if (target)
::lo_address_free(target);

path = nullptr;
source = nullptr;
target = nullptr;
}
};

// ------------------------------------------------------------------------------------------------

static inline
void osc_send_configure(const CarlaOscData* const oscData, const char* const key, const char* const value)
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(key);
CARLA_ASSERT(value);
qDebug("osc_send_configure(path:\"%s\", \"%s\", \"%s\")", oscData->path, key, value);

if (oscData && oscData->path && oscData->target && key && value)
{
char targetPath[strlen(oscData->path)+11];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/configure");
lo_send(oscData->target, targetPath, "ss", key, value);
}
}

static inline
void osc_send_control(const CarlaOscData* const oscData, const int32_t index, const float value)
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(index != -1); // -1 == PARAMETER_NULL
qDebug("osc_send_control(path:\"%s\", %i, %f)", oscData->path, index, value);

if (oscData && oscData->path && oscData->target && index != -1)
{
char targetPath[strlen(oscData->path)+9];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/control");
lo_send(oscData->target, targetPath, "if", index, value);
}
}

static inline
void osc_send_program(const CarlaOscData* const oscData, const int32_t index)
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(index >= 0);
qDebug("osc_send_program(path:\"%s\", %i)", oscData->path, index);

if (oscData && oscData->path && oscData->target && index >= 0)
{
char targetPath[strlen(oscData->path)+9];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/program");
lo_send(oscData->target, targetPath, "i", index);
}
}

static inline
void osc_send_program(const CarlaOscData* const oscData, const int32_t bank, const int32_t program)
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(program >= 0);
CARLA_ASSERT(bank >= 0);
qDebug("osc_send_program(path:\"%s\", %i, %i)", oscData->path, bank, program);

if (oscData && oscData->path && oscData->target && bank >= 0 && program >= 0)
{
char targetPath[strlen(oscData->path)+9];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/program");
lo_send(oscData->target, targetPath, "ii", bank, program);
}
}

static inline
void osc_send_midi_program(const CarlaOscData* const oscData, const int32_t index)
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(index >= 0);
qDebug("osc_send_midi_program(path:\"%s\", %i)", oscData->path, index);

if (oscData && oscData->path && oscData->target && index >= 0)
{
char targetPath[strlen(oscData->path)+14];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/midi_program");
lo_send(oscData->target, targetPath, "i", index);
}
}

static inline
void osc_send_midi_program(const CarlaOscData* const oscData, const int32_t bank, const int32_t program)
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(program >= 0);
CARLA_ASSERT(bank >= 0);
qDebug("osc_send_midi_program(path:\"%s\", %i, %i)", oscData->path, bank, program);

if (oscData && oscData->path && oscData->target && bank >= 0 && program >= 0)
{
char targetPath[strlen(oscData->path)+14];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/midi_program");
lo_send(oscData->target, targetPath, "ii", bank, program);
}
}

static inline
void osc_send_midi(const CarlaOscData* const oscData, const uint8_t buf[4])
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(buf[0] == 0);
CARLA_ASSERT(buf[1] != 0);
qDebug("osc_send_midi(path:\"%s\", 0x%X, %03u, %03u)", oscData->path, buf[1], buf[2], buf[3]);

if (oscData && oscData->path && oscData->target && buf[0] == 0 && buf[1] != 0)
{
char targetPath[strlen(oscData->path)+6];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/midi");
lo_send(oscData->target, targetPath, "m", buf);
}
}

static inline
void osc_send_sample_rate(const CarlaOscData* const oscData, const float sampleRate)
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(sampleRate > 0.0f);
qDebug("osc_send_sample_rate(path:\"%s\", %f)", oscData->path, sampleRate);

if (oscData && oscData->path && oscData->target && sampleRate > 0.0f)
{
char targetPath[strlen(oscData->path)+13];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/sample-rate");
lo_send(oscData->target, targetPath, "f", sampleRate);
}
}

#ifdef BUILD_BRIDGE
static inline
void osc_send_update(const CarlaOscData* const oscData, const char* const url)
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(url);
qDebug("osc_send_update(path:\"%s\", \"%s\")", oscData->path, url);

if (oscData && oscData->path && oscData->target && url)
{
char targetPath[strlen(oscData->path)+8];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/update");
lo_send(oscData->target, targetPath, "s", url);
}
}

static inline
void osc_send_exiting(const CarlaOscData* const oscData)
{
CARLA_ASSERT(oscData && oscData->path);
qDebug("osc_send_exiting(path:\"%s\")", oscData->path);

if (oscData && oscData->path && oscData->target)
{
char targetPath[strlen(oscData->path)+9];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/exiting");
lo_send(oscData->target, targetPath, "");
}
}
#endif

static inline
void osc_send_show(const CarlaOscData* const oscData)
{
CARLA_ASSERT(oscData && oscData->path);
qDebug("osc_send_show(path:\"%s\")", oscData->path);

if (oscData && oscData->path && oscData->target)
{
char targetPath[strlen(oscData->path)+6];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/show");
lo_send(oscData->target, targetPath, "");
}
}

static inline
void osc_send_hide(const CarlaOscData* const oscData)
{
CARLA_ASSERT(oscData && oscData->path);
qDebug("osc_send_hide(path:\"%s\")", oscData->path);

if (oscData && oscData->path && oscData->target)
{
char targetPath[strlen(oscData->path)+6];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/hide");
lo_send(oscData->target, targetPath, "");
}
}

static inline
void osc_send_quit(const CarlaOscData* const oscData)
{
CARLA_ASSERT(oscData && oscData->path);
qDebug("osc_send_quit(path:\"%s\")", oscData->path);

if (oscData && oscData->path && oscData->target)
{
char targetPath[strlen(oscData->path)+6];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/quit");
lo_send(oscData->target, targetPath, "");
}
}

// ------------------------------------------------------------------------------------------------

#ifdef BUILD_BRIDGE_PLUGIN
static inline
void osc_send_bridge_update(const CarlaOscData* const oscData, const char* const url)
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(url);
qDebug("osc_send_bridge_update(path:\"%s\", \"%s\")", oscData->path, url);

if (oscData && oscData->path && oscData->target && url)
{
char targetPath[strlen(oscData->path)+15];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/bridge_update");
lo_send(oscData->target, targetPath, "s", url);
}
}

static inline
void osc_send_bridge_error(const CarlaOscData* const oscData, const char* const error)
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(error);
qDebug("osc_send_bridge_error(path:\"%s\", \"%s\")", oscData->path, error);

if (oscData && oscData->path && oscData->target && error)
{
char targetPath[strlen(oscData->path)+14];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/bridge_error");
lo_send(oscData->target, targetPath, "s", error);
}
}
#endif

#if defined(BRIDGE_LV2) || defined(WANT_LV2)
static inline
void osc_send_lv2_transfer_atom(const CarlaOscData* const oscData, const int32_t portIndex, const char* const typeStr, const char* const atomBuf)
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(portIndex >= 0);
CARLA_ASSERT(typeStr);
CARLA_ASSERT(atomBuf);
qDebug("osc_send_lv2_transfer_atom(path:\"%s\", %i, \"%s\", <atomBuf:%p>)", oscData->path, portIndex, typeStr, atomBuf);

if (oscData && oscData->path && oscData->target && portIndex >= 0 && typeStr && atomBuf)
{
char targetPath[strlen(oscData->path)+19];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/lv2_atom_transfer");
lo_send(oscData->target, targetPath, "iss", portIndex, typeStr, atomBuf);
}
}

static inline
void osc_send_lv2_transfer_event(const CarlaOscData* const oscData, const int32_t portIndex, const char* const typeStr, const char* const atomBuf)
{
CARLA_ASSERT(oscData && oscData->path);
CARLA_ASSERT(portIndex >= 0);
CARLA_ASSERT(typeStr);
CARLA_ASSERT(atomBuf);
qDebug("osc_send_lv2_transfer_event(path:\"%s\", %i, \"%s\", <atomBuf:%p>)", oscData->path, portIndex, typeStr, atomBuf);

if (oscData && oscData->path && oscData->target && portIndex >= 0 && typeStr && atomBuf)
{
char targetPath[strlen(oscData->path)+20];
strcpy(targetPath, oscData->path);
strcat(targetPath, "/lv2_event_transfer");
lo_send(oscData->target, targetPath, "iss", portIndex, typeStr, atomBuf);
}
}
#endif

// ------------------------------------------------------------------------------------------------

#endif // CARLA_OSC_UTILS_HPP

+ 471
- 0
source/utils/carla_utils.hpp View File

@@ -0,0 +1,471 @@
/*
* Carla common utils
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef __CARLA_UTILS_HPP__
#define __CARLA_UTILS_HPP__

#include "carla_defines.hpp"

#include <cstdio>
#include <cstdlib>
#include <cstring>

#if defined(Q_OS_HAIKU)
# include <kernel/OS.h>
#elif defined(Q_OS_LINUX)
# include <sys/prctl.h>
# include <linux/prctl.h>
#endif

// -------------------------------------------------
// carla_assert*

static inline
void carla_assert(const char* const assertion, const char* const file, const int line)
{
qCritical("Carla assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
}

static inline
void carla_assert_int(const char* const assertion, const char* const file, const int line, const int value)
{
qCritical("Carla assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
}

// -------------------------------------------------
// carla_*sleep (carla_usleep not possible in Windows)

static inline
void carla_sleep(const int secs)
{
CARLA_ASSERT(secs > 0);

#ifdef Q_OS_WIN
Sleep(secs * 1000);
#else
sleep(secs);
#endif
}

static inline
void carla_msleep(const int msecs)
{
CARLA_ASSERT(msecs > 0);

#ifdef Q_OS_WIN
Sleep(msecs);
#else
usleep(msecs * 1000);
#endif
}

static inline
void carla_usleep(const int usecs)
{
CARLA_ASSERT(usecs > 0);

#ifdef Q_OS_WIN
Sleep(usecs / 1000);
#else
usleep(usecs);
#endif
}

// -------------------------------------------------
// carla_setenv

static inline
void carla_setenv(const char* const key, const char* const value)
{
CARLA_ASSERT(key);
CARLA_ASSERT(value);

#ifdef Q_OS_WIN
SetEnvironmentVariableA(key, value);
#else
setenv(key, value, 1);
#endif
}

// -------------------------------------------------
// carla_setprocname (not available on all platforms)

static inline
void carla_setprocname(const char* const name)
{
CARLA_ASSERT(name);

#if defined(Q_OS_HAIKU)
if ((thread_id this_thread = find_thread(nullptr)) != B_NAME_NOT_FOUND)
rename_thread(this_thread, name);
#elif defined(Q_OS_LINUX)
prctl(PR_SET_NAME, name);
#else
qWarning("carla_setprocname(\"%s\") - unsupported on this platform", name);
#endif
}

// -------------------------------------------------
// math functions

template<typename T>
static inline
const T& carla_min(const T& v1, const T& v2, const T& min)
{
return ((v1 < min || v2 < min) ? min : (v1 < v2 ? v1 : v2));
}

template<typename T>
static inline
void carla_fill(T* data, const unsigned int size, const T v)
{
CARLA_ASSERT(data);
CARLA_ASSERT(size > 0);

for (unsigned int i=0; i < size; i++)
*data++ = v;
}

void carla_zeroDouble(double* data, const unsigned size)
{
carla_fill<double>(data, size, 0.0);
}

void carla_zeroFloat(float* data, const unsigned size)
{
carla_fill<float>(data, size, 0.0f);
}

// -------------------------------------------------
// other misc functions

static inline
const char* bool2str(const bool yesNo)
{
return yesNo ? "true" : "false";
}

static inline
void pass() {}

// -------------------------------------------------
// CarlaString class

class CarlaString
{
public:
// ---------------------------------------------
// constructors (no explicit conversions allowed)

explicit CarlaString()
{
buffer = ::strdup("");
}

explicit CarlaString(char* const strBuf)
{
buffer = ::strdup(strBuf ? strBuf : "");
}

explicit CarlaString(const char* const strBuf)
{
buffer = ::strdup(strBuf ? strBuf : "");
}

explicit CarlaString(const int value)
{
const size_t strBufSize = ::abs(value/10) + 3;
char strBuf[strBufSize];
::snprintf(strBuf, strBufSize, "%d", value);

buffer = ::strdup(strBuf);
}

explicit CarlaString(const unsigned int value, const bool hexadecimal = false)
{
const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0);
char strBuf[strBufSize];
::snprintf(strBuf, strBufSize, hexadecimal ? "%u" : "0x%x", value);

buffer = ::strdup(strBuf);
}

explicit CarlaString(const long int value)
{
const size_t strBufSize = ::labs(value/10) + 3;
char strBuf[strBufSize];
::snprintf(strBuf, strBufSize, "%ld", value);

buffer = ::strdup(strBuf);
}

explicit CarlaString(const unsigned long int value, const bool hexadecimal = false)
{
const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0);
char strBuf[strBufSize];
::snprintf(strBuf, strBufSize, hexadecimal ? "%lu" : "0x%lx", value);

buffer = ::strdup(strBuf);
}

explicit CarlaString(const float value)
{
char strBuf[0xff];
::snprintf(strBuf, 0xff, "%f", value);

buffer = ::strdup(strBuf);
}

explicit CarlaString(const double value)
{
char strBuf[0xff];
::snprintf(strBuf, 0xff, "%g", value);

buffer = ::strdup(strBuf);
}

// ---------------------------------------------
// non-explicit constructor

CarlaString(const CarlaString& str)
{
buffer = ::strdup(str.buffer);
}

// ---------------------------------------------
// deconstructor

~CarlaString()
{
CARLA_ASSERT(buffer);
::free(buffer);
}

// ---------------------------------------------
// public methods

size_t length() const
{
return ::strlen(buffer);
}

bool isEmpty() const
{
return (*buffer == 0);
}

bool isNotEmpty() const
{
return (*buffer != 0);
}

bool contains(const char* const strBuf) const
{
if (! strBuf)
return false;
if (*strBuf == 0)
return false;

size_t thisLen = ::strlen(buffer);
size_t thatLen = ::strlen(strBuf)-1;

for (size_t i=0, j=0; i < thisLen; i++)
{
if (buffer[i] == strBuf[j])
j++;
else
j = 0;

if (j == thatLen)
return true;
}

return false;
}

bool contains(const CarlaString& str) const
{
return contains(str.buffer);
}

bool isDigit(const size_t pos) const
{
if (pos >= length())
return false;

return (buffer[pos] >= '0' && buffer[pos] <= '9');
}

void clear()
{
truncate(0);
}

void replace(const char before, const char after)
{
for (size_t i=0, len = ::strlen(buffer); i < len; i++)
{
if (buffer[i] == before)
buffer[i] = after;
}
}

void truncate(const unsigned int n)
{
for (size_t i=n, len = ::strlen(buffer); i < len; i++)
buffer[i] = 0;
}

void toBasic()
{
for (size_t i=0, len = ::strlen(buffer); i < len; i++)
{
if (buffer[i] >= '0' && buffer[i] <= '9')
continue;
if (buffer[i] >= 'A' && buffer[i] <= 'Z')
continue;
if (buffer[i] >= 'a' && buffer[i] <= 'z')
continue;
if (buffer[i] == '_')
continue;

buffer[i] = '_';
}
}

void toLower()
{
for (size_t i=0, len = ::strlen(buffer); i < len; i++)
{
if (buffer[i] >= 'A' && buffer[i] <= 'Z')
buffer[i] += 32;
}
}

void toUpper()
{
for (size_t i=0, len = ::strlen(buffer); i < len; i++)
{
if (buffer[i] >= 'a' && buffer[i] <= 'z')
buffer[i] -= 32;
}
}

// ---------------------------------------------
// public operators

operator const char*() const
{
return buffer;
}

char& operator[](const unsigned int pos)
{
return buffer[pos];
}

bool operator==(const char* const strBuf) const
{
return (strBuf && ::strcmp(buffer, strBuf) == 0);
}

bool operator==(const CarlaString& str) const
{
return operator==(str.buffer);
}

bool operator!=(const char* const strBuf) const
{
return !operator==(strBuf);
}

bool operator!=(const CarlaString& str) const
{
return !operator==(str.buffer);
}

CarlaString& operator=(const char* const strBuf)
{
::free(buffer);

buffer = ::strdup(strBuf ? strBuf : "");

return *this;
}

CarlaString& operator=(const CarlaString& str)
{
return operator=(str.buffer);
}

CarlaString& operator+=(const char* const strBuf)
{
const size_t newBufSize = ::strlen(buffer) + (strBuf ? ::strlen(strBuf) : 0) + 1;
char newBuf[newBufSize];

::strcpy(newBuf, buffer);
::strcat(newBuf, strBuf);
::free(buffer);

buffer = ::strdup(newBuf);

return *this;
}

CarlaString& operator+=(const CarlaString& str)
{
return operator+=(str.buffer);
}

CarlaString operator+(const char* const strBuf)
{
const size_t newBufSize = ::strlen(buffer) + (strBuf ? ::strlen(strBuf) : 0) + 1;
char newBuf[newBufSize];

::strcpy(newBuf, buffer);
::strcat(newBuf, strBuf);

return CarlaString(newBuf);
}

CarlaString operator+(const CarlaString& str)
{
return operator+(str.buffer);
}

// ---------------------------------------------

private:
char* buffer;
};

static inline
CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter)
{
const char* const strBufAfter = (const char*)strAfter;
const size_t newBufSize = (strBufBefore ? ::strlen(strBufBefore) : 0) + ::strlen(strBufAfter) + 1;
char newBuf[newBufSize];

::strcpy(newBuf, strBufBefore);
::strcat(newBuf, strBufAfter);

return CarlaString(newBuf);
}

// -------------------------------------------------

#endif // __CARLA_UTILS_HPP__

+ 454
- 0
source/utils/carla_vst_utils.hpp View File

@@ -0,0 +1,454 @@
/*
* Carla VST utils
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef __CARLA_VST_UTILS_HPP__
#define __CARLA_VST_UTILS_HPP__

// Disable deprecated VST features (NOT)
#define VST_FORCE_DEPRECATED 0

#include "carla_utils.hpp"

#include <cstdint>

// -------------------------------------------------
// Include fixes

#if VESTIGE_HEADER
#include "vestige/aeffectx.h"
#define audioMasterGetOutputSpeakerArrangement audioMasterGetSpeakerArrangement
#define effFlagsProgramChunks (1 << 5)
#define effSetProgramName 4
#define effGetParamLabel 6
#define effGetParamDisplay 7
#define effGetVu 9
#define effEditDraw 16
#define effEditMouse 17
#define effEditKey 18
#define effEditSleep 21
#define effIdentify 22
#define effGetChunk 23
#define effSetChunk 24
#define effCanBeAutomated 26
#define effString2Parameter 27
#define effGetNumProgramCategories 28
#define effGetProgramNameIndexed 29
#define effCopyProgram 30
#define effConnectInput 31
#define effConnectOutput 32
#define effGetInputProperties 33
#define effGetOutputProperties 34
#define effGetPlugCategory 35
#define effGetCurrentPosition 36
#define effGetDestinationBuffer 37
#define effOfflineNotify 38
#define effOfflinePrepare 39
#define effOfflineRun 40
#define effProcessVarIo 41
#define effSetSpeakerArrangement 42
#define effSetBlockSizeAndSampleRate 43
#define effSetBypass 44
#define effGetErrorText 46
#define effVendorSpecific 50
#define effGetTailSize 52
#define effIdle 53
#define effGetIcon 54
#define effSetViewPosition 55
#define effKeysRequired 57
#define effEditKeyDown 59
#define effEditKeyUp 60
#define effSetEditKnobMode 61
#define effGetMidiProgramName 62
#define effGetCurrentMidiProgram 63
#define effGetMidiProgramCategory 64
#define effHasMidiProgramsChanged 65
#define effGetMidiKeyName 66
#define effBeginSetProgram 67
#define effEndSetProgram 68
#define effGetSpeakerArrangement 69
#define effShellGetNextPlugin 70
#define effStartProcess 71
#define effStopProcess 72
#define effSetTotalSampleToProcess 73
#define effSetPanLaw 74
#define effBeginLoadBank 75
#define effBeginLoadProgram 76
#define effSetProcessPrecision 77
#define effGetNumMidiInputChannels 78
#define effGetNumMidiOutputChannels 79
#define kPlugCategSynth 2
#define kPlugCategAnalysis 3
#define kPlugCategMastering 4
#define kPlugCategRoomFx 6
#define kPlugCategRestoration 8
#define kPlugCategShell 10
#define kPlugCategGenerator 11
#define kVstAutomationOff 1
#define kVstAutomationReadWrite 4
#define kVstProcessLevelUnknown 0
#define kVstProcessLevelUser 1
#define kVstProcessLevelRealtime 2
#define kVstProcessLevelOffline 4
#define kVstProcessPrecision32 0
#define kVstTransportChanged 1
#define kVstVersion 2400
#define VSTCALLBACK
struct ERect {
int16_t top, left, bottom, right;
};
struct VstTimeInfo_R {
double samplePos, sampleRate, nanoSeconds, ppqPos, tempo, barStartPos, cycleStartPos, cycleEndPos;
int32_t timeSigNumerator, timeSigDenominator, smpteOffset, smpteFrameRate, samplesToNextClock, flags;
};
#else
#include "vst/aeffectx.h"
typedef VstTimeInfo VstTimeInfo_R;
#endif

// -------------------------------------------------
// Plugin callback

typedef AEffect* (*VST_Function)(audioMasterCallback);

// -------------------------------------------------
// Check if feature is supported by the plugin

static inline
bool vstPluginCanDo(AEffect* const effect, const char* const feature)
{
return (effect->dispatcher(effect, effCanDo, 0, 0, (void*)feature, 0.0f) == 1);
}

// -------------------------------------------------
// Convert Effect opcode to string

static inline
const char* vstEffectOpcode2str(const int32_t opcode)
{
switch (opcode)
{
case effOpen:
return "effOpen";
case effClose:
return "effClose";
case effSetProgram:
return "effSetProgram";
case effGetProgram:
return "effGetProgram";
case effSetProgramName:
return "effSetProgramName";
case effGetProgramName:
return "effGetProgramName";
case effGetParamLabel:
return "effGetParamLabel";
case effGetParamDisplay:
return "effGetParamDisplay";
case effGetParamName:
return "effGetParamName";
#if ! VST_FORCE_DEPRECATED
case effGetVu:
return "effGetVu";
#endif
case effSetSampleRate:
return "effSetSampleRate";
case effSetBlockSize:
return "effSetBlockSize";
case effMainsChanged:
return "effMainsChanged";
case effEditGetRect:
return "effEditGetRect";
case effEditOpen:
return "effEditOpen";
case effEditClose:
return "effEditClose";
#if ! VST_FORCE_DEPRECATED
case effEditDraw:
return "effEditDraw";
case effEditMouse:
return "effEditMouse";
case effEditKey:
return "effEditKey";
case effEditTop:
return "effEditTop";
case effEditSleep:
return "effEditSleep";
case effIdentify:
return "effIdentify";
#endif
case effGetChunk:
return "effGetChunk";
case effSetChunk:
return "effSetChunk";
case effProcessEvents:
return "effProcessEvents";
case effCanBeAutomated:
return "effCanBeAutomated";
case effString2Parameter:
return "effString2Parameter";
#if ! VST_FORCE_DEPRECATED
case effGetNumProgramCategories:
return "effGetNumProgramCategories";
#endif
case effGetProgramNameIndexed:
return "effGetProgramNameIndexed";
#if ! VST_FORCE_DEPRECATED
case effCopyProgram:
return "effCopyProgram";
case effConnectInput:
return "effConnectInput";
case effConnectOutput:
return "effConnectOutput";
#endif
case effGetInputProperties:
return "effGetInputProperties";
case effGetOutputProperties:
return "effGetOutputProperties";
case effGetPlugCategory:
return "effGetPlugCategory";
#if ! VST_FORCE_DEPRECATED
case effGetCurrentPosition:
return "effGetCurrentPosition";
case effGetDestinationBuffer:
return "effGetDestinationBuffer";
#endif
case effOfflineNotify:
return "effOfflineNotify";
case effOfflinePrepare:
return "effOfflinePrepare";
case effOfflineRun:
return "effOfflineRun";
case effProcessVarIo:
return "effProcessVarIo";
case effSetSpeakerArrangement:
return "effSetSpeakerArrangement";
#if ! VST_FORCE_DEPRECATED
case effSetBlockSizeAndSampleRate:
return "effSetBlockSizeAndSampleRate";
#endif
case effSetBypass:
return "effSetBypass";
case effGetEffectName:
return "effGetEffectName";
#if ! VST_FORCE_DEPRECATED
case effGetErrorText:
return "effGetErrorText";
#endif
case effGetVendorString:
return "effGetVendorString";
case effGetProductString:
return "effGetProductString";
case effGetVendorVersion:
return "effGetVendorVersion";
case effVendorSpecific:
return "effVendorSpecific";
case effCanDo:
return "effCanDo";
case effGetTailSize:
return "effGetTailSize";
#if ! VST_FORCE_DEPRECATED
case effIdle:
return "effIdle";
case effGetIcon:
return "effGetIcon";
case effSetViewPosition:
return "effSetViewPosition";
#endif
case effGetParameterProperties:
return "effGetParameterProperties";
#if ! VST_FORCE_DEPRECATED
case effKeysRequired:
return "effKeysRequired";
#endif
case effGetVstVersion:
return "effGetVstVersion";
case effEditKeyDown:
return "effEditKeyDown";
case effEditKeyUp:
return "effEditKeyUp";
case effSetEditKnobMode:
return "effSetEditKnobMode";
case effGetMidiProgramName:
return "effGetMidiProgramName";
case effGetCurrentMidiProgram:
return "effGetCurrentMidiProgram";
case effGetMidiProgramCategory:
return "effGetMidiProgramCategory";
case effHasMidiProgramsChanged:
return "effHasMidiProgramsChanged";
case effGetMidiKeyName:
return "effGetMidiKeyName";
case effBeginSetProgram:
return "effBeginSetProgram";
case effEndSetProgram:
return "effEndSetProgram";
case effGetSpeakerArrangement:
return "effGetSpeakerArrangement";
case effShellGetNextPlugin:
return "effShellGetNextPlugin";
case effStartProcess:
return "effStartProcess";
case effStopProcess:
return "effStopProcess";
case effSetTotalSampleToProcess:
return "effSetTotalSampleToProcess";
case effSetPanLaw:
return "effSetPanLaw";
case effBeginLoadBank:
return "effBeginLoadBank";
case effBeginLoadProgram:
return "effBeginLoadProgram";
case effSetProcessPrecision:
return "effSetProcessPrecision";
case effGetNumMidiInputChannels:
return "effGetNumMidiInputChannels";
case effGetNumMidiOutputChannels:
return "effGetNumMidiOutputChannels";
default:
return "unknown";
}
}

// -------------------------------------------------
// Convert Host/Master opcode to string

static inline
const char* vstMasterOpcode2str(const int32_t opcode)
{
switch (opcode)
{
case audioMasterAutomate:
return "audioMasterAutomate";
case audioMasterVersion:
return "audioMasterVersion";
case audioMasterCurrentId:
return "audioMasterCurrentId";
case audioMasterIdle:
return "audioMasterIdle";
#if ! VST_FORCE_DEPRECATED
case audioMasterPinConnected:
return "audioMasterPinConnected";
case audioMasterWantMidi:
return "audioMasterWantMidi";
#endif
case audioMasterGetTime:
return "audioMasterGetTime";
case audioMasterProcessEvents:
return "audioMasterProcessEvents";
#if ! VST_FORCE_DEPRECATED
case audioMasterSetTime:
return "audioMasterSetTime";
case audioMasterTempoAt:
return "audioMasterTempoAt";
case audioMasterGetNumAutomatableParameters:
return "audioMasterGetNumAutomatableParameters";
case audioMasterGetParameterQuantization:
return "audioMasterGetParameterQuantization";
#endif
case audioMasterIOChanged:
return "audioMasterIOChanged";
#if ! VST_FORCE_DEPRECATED
case audioMasterNeedIdle:
return "audioMasterNeedIdle";
#endif
case audioMasterSizeWindow:
return "audioMasterSizeWindow";
case audioMasterGetSampleRate:
return "audioMasterGetSampleRate";
case audioMasterGetBlockSize:
return "audioMasterGetBlockSize";
case audioMasterGetInputLatency:
return "audioMasterGetInputLatency";
case audioMasterGetOutputLatency:
return "audioMasterGetOutputLatency";
#if ! VST_FORCE_DEPRECATED
case audioMasterGetPreviousPlug:
return "audioMasterGetPreviousPlug";
case audioMasterGetNextPlug:
return "audioMasterGetNextPlug";
case audioMasterWillReplaceOrAccumulate:
return "audioMasterWillReplaceOrAccumulate";
#endif
case audioMasterGetCurrentProcessLevel:
return "audioMasterGetCurrentProcessLevel";
case audioMasterGetAutomationState:
return "audioMasterGetAutomationState";
case audioMasterOfflineStart:
return "audioMasterOfflineStart";
case audioMasterOfflineRead:
return "audioMasterOfflineRead";
case audioMasterOfflineWrite:
return "audioMasterOfflineWrite";
case audioMasterOfflineGetCurrentPass:
return "audioMasterOfflineGetCurrentPass";
case audioMasterOfflineGetCurrentMetaPass:
return "audioMasterOfflineGetCurrentMetaPass";
#if ! VST_FORCE_DEPRECATED
case audioMasterSetOutputSampleRate:
return "audioMasterSetOutputSampleRate";
case audioMasterGetOutputSpeakerArrangement:
return "audioMasterGetOutputSpeakerArrangement";
#endif
case audioMasterGetVendorString:
return "audioMasterGetVendorString";
case audioMasterGetProductString:
return "audioMasterGetProductString";
case audioMasterGetVendorVersion:
return "audioMasterGetVendorVersion";
case audioMasterVendorSpecific:
return "audioMasterVendorSpecific";
#if ! VST_FORCE_DEPRECATED
case audioMasterSetIcon:
return "audioMasterSetIcon";
#endif
case audioMasterCanDo:
return "audioMasterCanDo";
case audioMasterGetLanguage:
return "audioMasterGetLanguage";
#if ! VST_FORCE_DEPRECATED
case audioMasterOpenWindow:
return "audioMasterOpenWindow";
case audioMasterCloseWindow:
return "audioMasterCloseWindow";
#endif
case audioMasterGetDirectory:
return "audioMasterGetDirectory";
case audioMasterUpdateDisplay:
return "audioMasterUpdateDisplay";
case audioMasterBeginEdit:
return "audioMasterBeginEdit";
case audioMasterEndEdit:
return "audioMasterEndEdit";
case audioMasterOpenFileSelector:
return "audioMasterOpenFileSelector";
case audioMasterCloseFileSelector:
return "audioMasterCloseFileSelector";
#if ! VST_FORCE_DEPRECATED
case audioMasterEditFile:
return "audioMasterEditFile";
case audioMasterGetChunkFile:
return "audioMasterGetChunkFile";
case audioMasterGetInputSpeakerArrangement:
return "audioMasterGetInputSpeakerArrangement";
#endif
default:
return "unknown";
}
}

// -------------------------------------------------

#endif // __CARLA_VST_UTILS_HPP__

Loading…
Cancel
Save