Browse Source

Misc stuff

tags/1.9.4
falkTX 11 years ago
parent
commit
d11d669174
16 changed files with 594 additions and 473 deletions
  1. +79
    -93
      source/backend/carla_backend.hpp
  2. +71
    -61
      source/backend/carla_engine.hpp
  3. +3
    -6
      source/backend/carla_plugin.hpp
  4. +60
    -36
      source/backend/engine/carla_engine.cpp
  5. +2
    -2
      source/backend/engine/carla_engine.pro
  6. +48
    -15
      source/backend/engine/carla_engine_internal.hpp
  7. +5
    -5
      source/backend/engine/carla_engine_osc.hpp
  8. +11
    -9
      source/backend/engine/carla_engine_thread.hpp
  9. +8
    -10
      source/backend/engine/jack.cpp
  10. +3
    -0
      source/backend/engine/rtaudio.cpp
  11. +203
    -136
      source/discovery/carla-discovery.cpp
  12. +4
    -2
      source/includes/carla_defines.hpp
  13. +47
    -80
      source/utils/carla_backend_utils.hpp
  14. +27
    -2
      source/utils/carla_lv2_utils.hpp
  15. +8
    -2
      source/utils/carla_utils.hpp
  16. +15
    -14
      source/utils/rt_list.hpp

+ 79
- 93
source/backend/carla_backend.hpp View File

@@ -9,7 +9,7 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file
@@ -18,6 +18,8 @@
#ifndef __CARLA_BACKEND_HPP__ #ifndef __CARLA_BACKEND_HPP__
#define __CARLA_BACKEND_HPP__ #define __CARLA_BACKEND_HPP__


// TODO - remove ifdef's when Carla stabilizes

#include "carla_defines.hpp" #include "carla_defines.hpp"


#include <cstdint> #include <cstdint>
@@ -39,12 +41,10 @@ CARLA_BACKEND_START_NAMESPACE
* @{ * @{
*/ */


#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
const unsigned int MAX_DEFAULT_PLUGINS = 99; //!< Maximum default number of loadable plugins
const unsigned int MAX_RACK_PLUGINS = 16; //!< Maximum number of loadable plugins in rack mode
const unsigned int MAX_PATCHBAY_PLUGINS = 999; //!< Maximum number of loadable plugins in patchbay mode
const unsigned int MAX_DEFAULT_PARAMETERS = 200; //!< Maximum default number of parameters allowed.\see OPTION_MAX_PARAMETERS


/*! /*!
* @defgroup PluginHints Plugin Hints * @defgroup PluginHints Plugin Hints
@@ -56,14 +56,17 @@ const unsigned int MAX_PARAMETERS = 200; //!< Default value for the maximum numb
#ifndef BUILD_BRIDGE #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. 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 #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 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.
const unsigned int PLUGIN_IS_RTSAFE = 0x002; //!< Plugin is hard real-time safe.
const unsigned int PLUGIN_IS_SYNTH = 0x004; //!< Plugin is a synthesizer (produces sound).
const unsigned int PLUGIN_HAS_GUI = 0x010; //!< Plugin has its own custom GUI.
const unsigned int PLUGIN_USES_CHUNKS = 0x020; //!< Plugin uses chunks to save internal data.\see CarlaPlugin::chunkData()
#ifndef BUILD_BRIDGE
const unsigned int PLUGIN_USES_SINGLE_THREAD = 0x040; //!< Plugin needs a single thread for both DSP and UI events.
#endif
const unsigned int PLUGIN_CAN_DRYWET = 0x100; //!< Plugin can make use of Dry/Wet controls.
const unsigned int PLUGIN_CAN_VOLUME = 0x200; //!< Plugin can make use of Volume controls.
const unsigned int PLUGIN_CAN_BALANCE = 0x400; //!< Plugin can make use of Left & Right Balance controls.
const unsigned int PLUGIN_CAN_FORCE_STEREO = 0x800; //!< Plugin can be used in forced-stereo mode.
/**@}*/ /**@}*/


/*! /*!
@@ -73,16 +76,17 @@ const unsigned int PLUGIN_CAN_FORCE_STEREO = 0x100; //!< Plugin can be used in
* \see CarlaPlugin::parameterData() * \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_BOOLEAN = 0x01; //!< Parameter value is always a boolean (always at minimum or maximum range).
const unsigned int PARAMETER_IS_INTEGER = 0x02; //!< Parameter value is always an integer.
const unsigned int PARAMETER_IS_LOGARITHMIC = 0x04; //!< Parameter is logarithmic.
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_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_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_SAMPLERATE = 0x20; //!< Parameter needs sample rate to work (value and ranges are multiplied by SR, and must be 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_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() const unsigned int PARAMETER_USES_CUSTOM_TEXT = 0x80; //!< Parameter uses custom text for displaying its value.\see CarlaPlugin::getParameterText()
/**@}*/ /**@}*/


#if 0
/*! /*!
* @defgroup CustomDataTypes Custom Data types * @defgroup CustomDataTypes Custom Data types
* *
@@ -95,7 +99,9 @@ const char* const CUSTOM_DATA_INVALID = nullptr;
const char* const CUSTOM_DATA_CHUNK = "http://kxstudio.sf.net/ns/carla/chunk"; //!< Carla Chunk 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 const char* const CUSTOM_DATA_STRING = "http://kxstudio.sf.net/ns/carla/string"; //!< Carla String
/**@}*/ /**@}*/
#endif


#if 0
/*! /*!
* @defgroup BridgeMessages Bridge Messages * @defgroup BridgeMessages Bridge Messages
* *
@@ -105,12 +111,13 @@ const char* const CUSTOM_DATA_STRING = "http://kxstudio.sf.net/ns/carla/string"
* TODO: Review these, may not be needed anymore * TODO: Review these, may not be needed anymore
* @{ * @{
*/ */
//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.
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.
/**@}*/ /**@}*/
#endif


/*! /*!
* The binary type of a plugin. * The binary type of a plugin.
@@ -126,7 +133,7 @@ enum BinaryType {


/*! /*!
* All the available plugin types, as provided by subclasses of CarlaPlugin.\n * All the available plugin types, as provided by subclasses of CarlaPlugin.\n
* \note Some plugin classes might provide more than 1 plugin type.
* Some plugin classes might provide more than 1 plugin type.
*/ */
enum PluginType { enum PluginType {
PLUGIN_NONE = 0, //!< Null plugin type. PLUGIN_NONE = 0, //!< Null plugin type.
@@ -184,34 +191,18 @@ enum InternalParametersIndex {
PARAMETER_ACTIVE = -2, //!< Active parameter, can only be 'true' or 'false'; default is 'false'. 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_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_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.
PARAMETER_BALANCE_LEFT = -5, //!< Stereo Balance-Left parameter, range -1.0...1.0; default is -1.0.
PARAMETER_BALANCE_RIGHT = -6, //!< Stereo Balance-Right parameter, range -1.0...1.0; default is 1.0.
PARAMETER_PANNING = -7 //!< Mono Panning parameter, range -1.0...1.0; default is 0.0.
}; };


/*! /*!
* Plugin custom GUI type.
* \see OPTION_PREFER_UI_BRIDGES
*
* TODO: these need to be handled all internally, only via showGui() backend-side
*/
//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().
* Options used in the CarlaEngine::setOption() and set_option() calls.\n
* These options must be set before initiliazing or after closing the engine.
*/ */
enum OptionsType { enum OptionsType {
/*! /*!
* Try to set the current process name.\n
* Try to set the current process name.
* \note Not available on all platforms. * \note Not available on all platforms.
*/ */
OPTION_PROCESS_NAME = 0, OPTION_PROCESS_NAME = 0,
@@ -232,54 +223,55 @@ enum OptionsType {
OPTION_PROCESS_HIGH_PRECISION = 2, OPTION_PROCESS_HIGH_PRECISION = 2,


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

/*!
* Prefered buffer size.
* Force mono plugins as stereo, by running 2 instances at the same time.
* \note Not supported by all plugins.
*/ */
OPTION_PREFERRED_BUFFER_SIZE = 4,
OPTION_FORCE_STEREO = 3,


/*! /*!
* Prefered sample rate.
* Use plugin bridges whenever possible.\n
* Default is no, and not recommended at this point!.
* EXPERIMENTAL AND INCOMPLETE!
*/ */
OPTION_PREFERRED_SAMPLE_RATE = 5,
OPTION_PREFER_PLUGIN_BRIDGES = 4,


/*! /*!
* Force mono plugins as stereo, by running 2 instances at the same time.\n
* Not supported by all plugins.
* Use OSC-UI bridges whenever possible, otherwise UIs will be handled in the main thread.\n
* Default is yes.
*/ */
OPTION_FORCE_STEREO = 6,
OPTION_PREFER_UI_BRIDGES = 5,


#ifdef WANT_DSSI #ifdef WANT_DSSI
/*! /*!
* Use (unofficial) dssi-vst chunks feature.\n * Use (unofficial) dssi-vst chunks feature.\n
* Default is no. * Default is no.
*/ */
OPTION_USE_DSSI_VST_CHUNKS = 7,
OPTION_USE_DSSI_VST_CHUNKS = 6,
#endif #endif


/*! /*!
* Use plugin bridges whenever possible.\n
* Default is no, and not recommended at this point!.
* EXPERIMENTAL AND INCOMPLETE!
* Maximum number of parameters allowed.\n
* Default is MAX_DEFAULT_PARAMETERS.
*/ */
OPTION_PREFER_PLUGIN_BRIDGES = 8,
OPTION_MAX_PARAMETERS = 7,


/*! /*!
* Use OSC-UI bridges whenever possible, otherwise UIs will be handled in the main thread.\n
* Default is yes.
* Timeout value in ms for how much to wait for OSC-Bridges to respond.\n
* Default is 4000 (4 secs).
*/ */
OPTION_PREFER_UI_BRIDGES = 9,
OPTION_OSC_UI_TIMEOUT = 8,


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


/*!
* Prefered sample rate.
*/
OPTION_PREFERRED_SAMPLE_RATE = 10,

#ifndef BUILD_BRIDGE
/*! /*!
* Set path to the native plugin bridge executable.\n * Set path to the native plugin bridge executable.\n
* Default unset. * Default unset.
@@ -309,6 +301,7 @@ enum OptionsType {
* Default unset. * Default unset.
*/ */
OPTION_PATH_BRIDGE_WIN64 = 15, OPTION_PATH_BRIDGE_WIN64 = 15,
#endif


#ifdef WANT_LV2 #ifdef WANT_LV2
/*! /*!
@@ -376,8 +369,9 @@ enum OptionsType {
}; };


/*! /*!
* Opcodes sent from the engine callback, as defined by CallbackFunc.
* Opcodes sent from the engine callback to the GUI, as defined by CallbackFunc.
* *
* \see CarlaEngine::setCallback()
* \see set_callback_function() * \see set_callback_function()
*/ */
enum CallbackType { enum CallbackType {
@@ -449,72 +443,64 @@ enum CallbackType {
* \param value1 State, as follows:.\n * \param value1 State, as follows:.\n
* 0: GUI has been closed or hidden\n * 0: GUI has been closed or hidden\n
* 1: GUI has been shown\n * 1: GUI has been shown\n
* -1: GUI has crashed and should not be shown again\n
* -1: GUI has crashed and should not be shown again
*/ */
CALLBACK_SHOW_GUI = 8, 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. * The plugin needs update.
*/ */
CALLBACK_UPDATE = 10,
CALLBACK_UPDATE = 9,


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


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


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


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


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


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


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


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


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


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


/*! /*!
@@ -598,7 +584,7 @@ struct MidiProgramData {


/*! /*!
* Custom data, saving key:value 'dictionaries'. * Custom data, saving key:value 'dictionaries'.
* \a type is an URI.
* \a type is an URI which defines the \a value type.
* *
* \see CustomDataTypes * \see CustomDataTypes
*/ */


+ 71
- 61
source/backend/carla_engine.hpp View File

@@ -9,7 +9,7 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file
@@ -172,50 +172,7 @@ struct CarlaEngineMidiEvent {
} }
}; };


/*!
* Engine BBT Time information.
*/
struct CarlaEngineTimeInfoBBT {
int32_t bar; //!< current bar
int32_t beat; //!< current beat-within-bar
int32_t tick; //!< current tick-within-beat
double barStartTick;

float beatsPerBar; //!< time signature "numerator"
float beatType; //!< time signature "denominator"

double ticksPerBeat;
double beatsPerMinute;

CarlaEngineTimeInfoBBT()
: bar(0),
beat(0),
tick(0),
barStartTick(0.0),
beatsPerBar(0.0f),
beatType(0.0f),
ticksPerBeat(0.0),
beatsPerMinute(0.0) {}
};

/*!
* Engine Time information.
*/
struct CarlaEngineTimeInfo {
static const uint32_t ValidBBT = 0x1;

bool playing;
uint32_t frame;
uint32_t time;
uint32_t valid;
CarlaEngineTimeInfoBBT bbt;

CarlaEngineTimeInfo()
: playing(false),
frame(0),
time(0),
valid(0) {}
};
// LATER - CarlaEngineExtendedMidiEvent


/*! /*!
* Engine options. * Engine options.
@@ -236,11 +193,13 @@ struct CarlaEngineOptions {
uint preferredBufferSize; uint preferredBufferSize;
uint preferredSampleRate; uint preferredSampleRate;


#ifndef BUILD_BRIDGE
CarlaString bridge_native; CarlaString bridge_native;
CarlaString bridge_posix32; CarlaString bridge_posix32;
CarlaString bridge_posix64; CarlaString bridge_posix64;
CarlaString bridge_win32; CarlaString bridge_win32;
CarlaString bridge_win64; CarlaString bridge_win64;
#endif
#ifdef WANT_LV2 #ifdef WANT_LV2
CarlaString bridge_lv2gtk2; CarlaString bridge_lv2gtk2;
CarlaString bridge_lv2gtk3; CarlaString bridge_lv2gtk3;
@@ -257,7 +216,7 @@ struct CarlaEngineOptions {
#endif #endif


CarlaEngineOptions() CarlaEngineOptions()
: processMode(PROCESS_MODE_PATCHBAY),
: processMode(PROCESS_MODE_CONTINUOUS_RACK),
processHighPrecision(false), processHighPrecision(false),
forceStereo(false), forceStereo(false),
preferPluginBridges(false), preferPluginBridges(false),
@@ -265,12 +224,57 @@ struct CarlaEngineOptions {
#ifdef WANT_DSSI #ifdef WANT_DSSI
useDssiVstChunks(false), useDssiVstChunks(false),
#endif #endif
maxParameters(MAX_PARAMETERS),
oscUiTimeout(4000/100),
maxParameters(MAX_DEFAULT_PARAMETERS),
oscUiTimeout(4000),
preferredBufferSize(512), preferredBufferSize(512),
preferredSampleRate(44100) {} preferredSampleRate(44100) {}
}; };


/*!
* Engine BBT Time information.
*/
struct CarlaEngineTimeInfoBBT {
int32_t bar; //!< current bar
int32_t beat; //!< current beat-within-bar
int32_t tick; //!< current tick-within-beat
double barStartTick;

float beatsPerBar; //!< time signature "numerator"
float beatType; //!< time signature "denominator"

double ticksPerBeat;
double beatsPerMinute;

CarlaEngineTimeInfoBBT()
: bar(0),
beat(0),
tick(0),
barStartTick(0.0),
beatsPerBar(0.0f),
beatType(0.0f),
ticksPerBeat(0.0),
beatsPerMinute(0.0) {}
};

/*!
* Engine Time information.
*/
struct CarlaEngineTimeInfo {
static const uint32_t ValidBBT = 0x1;

bool playing;
uint32_t frame;
uint32_t time;
uint32_t valid;
CarlaEngineTimeInfoBBT bbt;

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

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


/*! /*!
@@ -566,6 +570,7 @@ public:
*/ */
static CarlaEngine* newDriverByName(const char* const driverName); static CarlaEngine* newDriverByName(const char* const driverName);



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


@@ -583,7 +588,7 @@ public:
* Maximum number of loadable plugins. * Maximum number of loadable plugins.
* \note This function returns 0 if engine is not started. * \note This function returns 0 if engine is not started.
*/ */
unsigned short maxPluginNumber() const;
unsigned int maxPluginNumber() const;


// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Virtual, per-engine type calls // Virtual, per-engine type calls
@@ -626,8 +631,10 @@ public:
* Get next available plugin id.\n * Get next available plugin id.\n
* Returns -1 if no more plugins can be loaded. * Returns -1 if no more plugins can be loaded.
*/ */
short getNewPluginId() const;
int getNewPluginId() const;


#if 0
#if 0
/*! /*!
* Get plugin with id \a id. * Get plugin with id \a id.
*/ */
@@ -637,6 +644,7 @@ public:
* Get plugin with id \a id, faster unchecked version. * Get plugin with id \a id, faster unchecked version.
*/ */
CarlaPlugin* getPluginUnchecked(const unsigned short id) const; CarlaPlugin* getPluginUnchecked(const unsigned short id) const;
#endif


/*! /*!
* Get a unique plugin name within the engine.\n * Get a unique plugin name within the engine.\n
@@ -692,6 +700,14 @@ public:
return (const char*)name; return (const char*)name;
} }


/*!
* Get current buffer size.
*/
uint32_t getBufferSize() const
{
return bufferSize;
}

/*! /*!
* Get current sample rate. * Get current sample rate.
*/ */
@@ -701,11 +717,11 @@ public:
} }


/*! /*!
* Get current buffer size.
* Get the engine options (read-only).
*/ */
uint32_t getBufferSize() const
const CarlaEngineOptions& getOptions() const
{ {
return bufferSize;
return options;
} }


/*! /*!
@@ -752,14 +768,6 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Options // Options


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

#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
/*! /*!
* Get the engine options as process environment. * Get the engine options as process environment.
@@ -842,6 +850,8 @@ public:
void setOscBridgeData(const CarlaOscData* const oscData); void setOscBridgeData(const CarlaOscData* const oscData);
#endif #endif


#endif

#ifdef BUILD_BRIDGE #ifdef BUILD_BRIDGE
void osc_send_peaks(CarlaPlugin* const plugin); void osc_send_peaks(CarlaPlugin* const plugin);
#else #else


+ 3
- 6
source/backend/carla_plugin.hpp View File

@@ -93,8 +93,7 @@ enum PluginPostEventType {
PluginPostEventProgramChange, // index PluginPostEventProgramChange, // index
PluginPostEventMidiProgramChange, // index PluginPostEventMidiProgramChange, // index
PluginPostEventNoteOn, // channel, note, velo PluginPostEventNoteOn, // channel, note, velo
PluginPostEventNoteOff, // channel, note
PluginPostEventCustom
PluginPostEventNoteOff // channel, note
}; };


struct PluginAudioData { struct PluginAudioData {
@@ -159,14 +158,12 @@ struct PluginPostEvent {
int32_t value1; int32_t value1;
int32_t value2; int32_t value2;
double value3; double value3;
const void* cdata;


PluginPostEvent() PluginPostEvent()
: type(PluginPostEventNull), : type(PluginPostEventNull),
value1(-1), value1(-1),
value2(-1), value2(-1),
value3(0.0),
cdata(nullptr) {}
value3(0.0) {}
}; };


struct ExternalMidiNote { struct ExternalMidiNote {
@@ -180,7 +177,7 @@ struct ExternalMidiNote {
velo(0) {} velo(0) {}
}; };


class CarlaPluginPrivateData;
struct CarlaPluginPrivateData;


/*! /*!
* \class CarlaPlugin * \class CarlaPlugin


+ 60
- 36
source/backend/engine/carla_engine.cpp View File

@@ -80,7 +80,7 @@ void CarlaEngineAudioPort::initBuffer(CarlaEngine* const)


CarlaEngineControlPort::CarlaEngineControlPort(const bool isInput, const ProcessMode processMode) CarlaEngineControlPort::CarlaEngineControlPort(const bool isInput, const ProcessMode processMode)
: CarlaEnginePort(isInput, processMode), : CarlaEnginePort(isInput, processMode),
m_maxEventCount(processMode == PROCESS_MODE_CONTINUOUS_RACK ? CarlaEngine::MAX_CONTROL_EVENTS : PATCHBAY_EVENT_COUNT)
m_maxEventCount(/*processMode == PROCESS_MODE_CONTINUOUS_RACK ? CarlaEngine::MAX_CONTROL_EVENTS :*/ PATCHBAY_EVENT_COUNT)
{ {
qDebug("CarlaEngineControlPort::CarlaEngineControlPort(%s, %s)", bool2str(isInput), ProcessMode2Str(processMode)); qDebug("CarlaEngineControlPort::CarlaEngineControlPort(%s, %s)", bool2str(isInput), ProcessMode2Str(processMode));


@@ -224,7 +224,7 @@ void CarlaEngineControlPort::writeEvent(const CarlaEngineControlEventType type,


CarlaEngineMidiPort::CarlaEngineMidiPort(const bool isInput, const ProcessMode processMode) CarlaEngineMidiPort::CarlaEngineMidiPort(const bool isInput, const ProcessMode processMode)
: CarlaEnginePort(isInput, processMode), : CarlaEnginePort(isInput, processMode),
m_maxEventCount(processMode == PROCESS_MODE_CONTINUOUS_RACK ? CarlaEngine::MAX_MIDI_EVENTS : PATCHBAY_EVENT_COUNT)
m_maxEventCount(/*processMode == PROCESS_MODE_CONTINUOUS_RACK ? CarlaEngine::MAX_MIDI_EVENTS :*/ PATCHBAY_EVENT_COUNT)
{ {
qDebug("CarlaEngineMidiPort::CarlaEngineMidiPort(%s, %s)", bool2str(isInput), ProcessMode2Str(processMode)); qDebug("CarlaEngineMidiPort::CarlaEngineMidiPort(%s, %s)", bool2str(isInput), ProcessMode2Str(processMode));


@@ -416,7 +416,7 @@ void CarlaEngineClient::setLatency(const uint32_t samples)
} }


// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------
// Carla Engine Client
// Carla Engine


CarlaEngine::CarlaEngine() CarlaEngine::CarlaEngine()
: data(new CarlaEnginePrivateData(this)) : data(new CarlaEnginePrivateData(this))
@@ -530,7 +530,7 @@ int CarlaEngine::maxPortNameSize()
return STR_MAX; return STR_MAX;
} }


unsigned short CarlaEngine::maxPluginNumber() const
unsigned int CarlaEngine::maxPluginNumber() const
{ {
return data->maxPluginNumber; return data->maxPluginNumber;
} }
@@ -546,6 +546,7 @@ bool CarlaEngine::init(const char* const clientName)


data->aboutToClose = false; data->aboutToClose = false;
data->maxPluginNumber = 0; data->maxPluginNumber = 0;
data->nextPluginId = 0;


#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
data->oscData = data->osc.getControlData(); data->oscData = data->osc.getControlData();
@@ -558,6 +559,9 @@ bool CarlaEngine::init(const char* const clientName)
carla_setprocname(clientName); carla_setprocname(clientName);
#endif #endif


//data->postEvents.resize();
//data->plugins.resize();

data->thread.startNow(); data->thread.startNow();


return true; return true;
@@ -586,20 +590,17 @@ bool CarlaEngine::close()
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Plugin management // Plugin management


short CarlaEngine::getNewPluginId() const
int CarlaEngine::getNewPluginId() const
{ {
qDebug("CarlaEngine::getNewPluginId()"); qDebug("CarlaEngine::getNewPluginId()");
CARLA_ASSERT(data->maxPluginNumber > 0); CARLA_ASSERT(data->maxPluginNumber > 0);


for (unsigned short i=0; i < data->maxPluginNumber; i++)
{
if (! data->carlaPlugins[i])
return i;
}

return -1;
return data->nextPluginId;
} }


#if 0

#if 0
CarlaPlugin* CarlaEngine::getPlugin(const unsigned short id) const CarlaPlugin* CarlaEngine::getPlugin(const unsigned short id) const
{ {
qDebug("CarlaEngine::getPlugin(%i) [max:%i]", id, data->maxPluginNumber); qDebug("CarlaEngine::getPlugin(%i) [max:%i]", id, data->maxPluginNumber);
@@ -616,6 +617,7 @@ CarlaPlugin* CarlaEngine::getPluginUnchecked(const unsigned short id) const
{ {
return data->carlaPlugins[id]; return data->carlaPlugins[id];
} }
#endif


const char* CarlaEngine::getUniquePluginName(const char* const name) const char* CarlaEngine::getUniquePluginName(const char* const name)
{ {
@@ -631,6 +633,7 @@ const char* CarlaEngine::getUniquePluginName(const char* const name)
sname.truncate(maxClientNameSize()-5-1); // 5 = strlen(" (10)") sname.truncate(maxClientNameSize()-5-1); // 5 = strlen(" (10)")
sname.replace(':', '.'); // ':' is used in JACK1 to split client/port names sname.replace(':', '.'); // ':' is used in JACK1 to split client/port names


#if 0
for (unsigned short i=0; i < data->maxPluginNumber; i++) for (unsigned short i=0; i < data->maxPluginNumber; i++)
{ {
// Check if unique name doesn't exist // Check if unique name doesn't exist
@@ -683,6 +686,7 @@ const char* CarlaEngine::getUniquePluginName(const char* const name)
// Modify string if not // Modify string if not
sname += " (2)"; sname += " (2)";
} }
#endif


return strdup(sname); return strdup(sname);
} }
@@ -695,12 +699,24 @@ short CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, con
CARLA_ASSERT(filename); CARLA_ASSERT(filename);
CARLA_ASSERT(label); CARLA_ASSERT(label);


if (QThread::currentThread() != &data->thread)
{
EnginePostEvent postEvent;
data->postEvents.append(postEvent);
return;
}

if (data->maxPluginNumber == 0) if (data->maxPluginNumber == 0)
{ {
#ifdef BUILD_BRIDGE #ifdef BUILD_BRIDGE
data->maxPluginNumber = MAX_PLUGINS; // which is 1 data->maxPluginNumber = MAX_PLUGINS; // which is 1
#else #else
data->maxPluginNumber = (options.processMode == PROCESS_MODE_CONTINUOUS_RACK) ? 16 : MAX_PLUGINS;
if (options.processMode == PROCESS_MODE_CONTINUOUS_RACK)
data->maxPluginNumber = MAX_RACK_PLUGINS;
else if (options.processMode == PROCESS_MODE_PATCHBAY)
data->maxPluginNumber = MAX_PATCHBAY_PLUGINS;
else
data->maxPluginNumber = MAX_DEFAULT_PLUGINS;
#endif #endif
} }


@@ -781,8 +797,8 @@ short CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, con


const short id = plugin->id(); const short id = plugin->id();


data->carlaPlugins[id] = plugin;
data->uniqueNames[id] = plugin->name();
EnginePluginData pluginData(plugin);
data->plugins.append(pluginData);


return id; return id;
} }
@@ -1170,6 +1186,8 @@ void CarlaEngine::setOscBridgeData(const CarlaOscData* const oscData)
} }
#endif #endif


#endif

// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// protected calls // protected calls


@@ -1184,6 +1202,7 @@ void CarlaEngine::processRack(float* inBuf[2], float* outBuf[2], const uint32_t


bool processed = false; bool processed = false;


#if 0
// process plugins // process plugins
for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) for (unsigned short i=0, max=maxPluginNumber(); i < max; i++)
{ {
@@ -1274,6 +1293,7 @@ void CarlaEngine::processRack(float* inBuf[2], float* outBuf[2], const uint32_t


processed = true; processed = true;
} }
#endif


// if no plugins in the rack, copy inputs over outputs // if no plugins in the rack, copy inputs over outputs
if (! processed) if (! processed)
@@ -1298,11 +1318,13 @@ void CarlaEngine::bufferSizeChanged(const uint32_t newBufferSize)
{ {
qDebug("CarlaEngine::bufferSizeChanged(%i)", newBufferSize); qDebug("CarlaEngine::bufferSizeChanged(%i)", newBufferSize);


#if 0
for (unsigned short i=0; i < data->maxPluginNumber; i++) for (unsigned short i=0; i < data->maxPluginNumber; i++)
{ {
if (data->carlaPlugins[i] && data->carlaPlugins[i]->enabled() /*&& ! data->carlaPlugins[i]->data->processHighPrecision*/) if (data->carlaPlugins[i] && data->carlaPlugins[i]->enabled() /*&& ! data->carlaPlugins[i]->data->processHighPrecision*/)
data->carlaPlugins[i]->bufferSizeChanged(newBufferSize); data->carlaPlugins[i]->bufferSizeChanged(newBufferSize);
} }
#endif
} }


void CarlaEngine::sampleRateChanged(const double newSampleRate) void CarlaEngine::sampleRateChanged(const double newSampleRate)
@@ -1349,7 +1371,7 @@ void CarlaEngine::osc_send_control_add_plugin_start(const int32_t pluginId, cons
{ {
qDebug("CarlaEngine::osc_send_control_add_plugin_start(%i, \"%s\")", pluginId, pluginName); qDebug("CarlaEngine::osc_send_control_add_plugin_start(%i, \"%s\")", pluginId, pluginName);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(pluginName); CARLA_ASSERT(pluginName);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
@@ -1365,7 +1387,7 @@ void CarlaEngine::osc_send_control_add_plugin_end(const int32_t pluginId)
{ {
qDebug("CarlaEngine::osc_send_control_add_plugin_end(%i)", pluginId); qDebug("CarlaEngine::osc_send_control_add_plugin_end(%i)", pluginId);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
{ {
@@ -1380,7 +1402,7 @@ void CarlaEngine::osc_send_control_remove_plugin(const int32_t pluginId)
{ {
qDebug("CarlaEngine::osc_send_control_remove_plugin(%i)", pluginId); qDebug("CarlaEngine::osc_send_control_remove_plugin(%i)", pluginId);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
{ {
@@ -1395,7 +1417,7 @@ void CarlaEngine::osc_send_control_set_plugin_data(const int32_t pluginId, const
{ {
qDebug("CarlaEngine::osc_send_control_set_plugin_data(%i, %i, %i, %i, \"%s\", \"%s\", \"%s\", \"%s\", " P_INT64 ")", pluginId, type, category, hints, realName, label, maker, copyright, uniqueId); qDebug("CarlaEngine::osc_send_control_set_plugin_data(%i, %i, %i, %i, \"%s\", \"%s\", \"%s\", \"%s\", " P_INT64 ")", pluginId, type, category, hints, realName, label, maker, copyright, uniqueId);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(type != PLUGIN_NONE); CARLA_ASSERT(type != PLUGIN_NONE);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
@@ -1411,7 +1433,7 @@ void CarlaEngine::osc_send_control_set_plugin_ports(const int32_t pluginId, cons
{ {
qDebug("CarlaEngine::osc_send_control_set_plugin_ports(%i, %i, %i, %i, %i, %i, %i, %i)", pluginId, audioIns, audioOuts, midiIns, midiOuts, cIns, cOuts, cTotals); qDebug("CarlaEngine::osc_send_control_set_plugin_ports(%i, %i, %i, %i, %i, %i, %i, %i)", pluginId, audioIns, audioOuts, midiIns, midiOuts, cIns, cOuts, cTotals);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
{ {
@@ -1426,7 +1448,7 @@ void CarlaEngine::osc_send_control_set_parameter_data(const int32_t pluginId, co
{ {
qDebug("CarlaEngine::osc_send_control_set_parameter_data(%i, %i, %i, %i, \"%s\", \"%s\", %g)", pluginId, index, type, hints, name, label, current); qDebug("CarlaEngine::osc_send_control_set_parameter_data(%i, %i, %i, %i, \"%s\", \"%s\", %g)", pluginId, index, type, hints, name, label, current);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(index >= 0); CARLA_ASSERT(index >= 0);
CARLA_ASSERT(type != PARAMETER_UNKNOWN); CARLA_ASSERT(type != PARAMETER_UNKNOWN);


@@ -1443,7 +1465,7 @@ void CarlaEngine::osc_send_control_set_parameter_ranges(const int32_t pluginId,
{ {
qDebug("CarlaEngine::osc_send_control_set_parameter_ranges(%i, %i, %g, %g, %g, %g, %g, %g)", pluginId, index, min, max, def, step, stepSmall, stepLarge); qDebug("CarlaEngine::osc_send_control_set_parameter_ranges(%i, %i, %g, %g, %g, %g, %g, %g)", pluginId, index, min, max, def, step, stepSmall, stepLarge);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(index >= 0); CARLA_ASSERT(index >= 0);
CARLA_ASSERT(min < max); CARLA_ASSERT(min < max);


@@ -1460,7 +1482,7 @@ void CarlaEngine::osc_send_control_set_parameter_midi_cc(const int32_t pluginId,
{ {
qDebug("CarlaEngine::osc_send_control_set_parameter_midi_cc(%i, %i, %i)", pluginId, index, cc); qDebug("CarlaEngine::osc_send_control_set_parameter_midi_cc(%i, %i, %i)", pluginId, index, cc);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(index >= 0); CARLA_ASSERT(index >= 0);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
@@ -1476,7 +1498,7 @@ void CarlaEngine::osc_send_control_set_parameter_midi_channel(const int32_t plug
{ {
qDebug("CarlaEngine::osc_send_control_set_parameter_midi_channel(%i, %i, %i)", pluginId, index, channel); qDebug("CarlaEngine::osc_send_control_set_parameter_midi_channel(%i, %i, %i)", pluginId, index, channel);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(index >= 0); CARLA_ASSERT(index >= 0);
CARLA_ASSERT(channel >= 0 && channel < 16); CARLA_ASSERT(channel >= 0 && channel < 16);


@@ -1498,7 +1520,7 @@ void CarlaEngine::osc_send_control_set_parameter_value(const int32_t pluginId, c
qDebug("CarlaEngine::osc_send_control_set_parameter_value(%i, %i, %g)", pluginId, index, value); qDebug("CarlaEngine::osc_send_control_set_parameter_value(%i, %i, %g)", pluginId, index, value);
#endif #endif
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
{ {
@@ -1513,7 +1535,7 @@ void CarlaEngine::osc_send_control_set_default_value(const int32_t pluginId, con
{ {
qDebug("CarlaEngine::osc_send_control_set_default_value(%i, %i, %g)", pluginId, index, value); qDebug("CarlaEngine::osc_send_control_set_default_value(%i, %i, %g)", pluginId, index, value);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(index >= 0); CARLA_ASSERT(index >= 0);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
@@ -1529,7 +1551,7 @@ void CarlaEngine::osc_send_control_set_program(const int32_t pluginId, const int
{ {
qDebug("CarlaEngine::osc_send_control_set_program(%i, %i)", pluginId, index); qDebug("CarlaEngine::osc_send_control_set_program(%i, %i)", pluginId, index);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
{ {
@@ -1544,7 +1566,7 @@ void CarlaEngine::osc_send_control_set_program_count(const int32_t pluginId, con
{ {
qDebug("CarlaEngine::osc_send_control_set_program_count(%i, %i)", pluginId, count); qDebug("CarlaEngine::osc_send_control_set_program_count(%i, %i)", pluginId, count);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(count >= 0); CARLA_ASSERT(count >= 0);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
@@ -1560,7 +1582,7 @@ void CarlaEngine::osc_send_control_set_program_name(const int32_t pluginId, cons
{ {
qDebug("CarlaEngine::osc_send_control_set_program_name(%i, %i, \"%s\")", pluginId, index, name); qDebug("CarlaEngine::osc_send_control_set_program_name(%i, %i, \"%s\")", pluginId, index, name);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(index >= 0); CARLA_ASSERT(index >= 0);
CARLA_ASSERT(name); CARLA_ASSERT(name);


@@ -1577,7 +1599,7 @@ void CarlaEngine::osc_send_control_set_midi_program(const int32_t pluginId, cons
{ {
qDebug("CarlaEngine::osc_send_control_set_midi_program(%i, %i)", pluginId, index); qDebug("CarlaEngine::osc_send_control_set_midi_program(%i, %i)", pluginId, index);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
{ {
@@ -1592,7 +1614,7 @@ void CarlaEngine::osc_send_control_set_midi_program_count(const int32_t pluginId
{ {
qDebug("CarlaEngine::osc_send_control_set_midi_program_count(%i, %i)", pluginId, count); qDebug("CarlaEngine::osc_send_control_set_midi_program_count(%i, %i)", pluginId, count);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(count >= 0); CARLA_ASSERT(count >= 0);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
@@ -1608,7 +1630,7 @@ void CarlaEngine::osc_send_control_set_midi_program_data(const int32_t pluginId,
{ {
qDebug("CarlaEngine::osc_send_control_set_midi_program_data(%i, %i, %i, %i, \"%s\")", pluginId, index, bank, program, name); qDebug("CarlaEngine::osc_send_control_set_midi_program_data(%i, %i, %i, %i, \"%s\")", pluginId, index, bank, program, name);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(index >= 0); CARLA_ASSERT(index >= 0);
CARLA_ASSERT(bank >= 0); CARLA_ASSERT(bank >= 0);
CARLA_ASSERT(program >= 0); CARLA_ASSERT(program >= 0);
@@ -1627,7 +1649,7 @@ void CarlaEngine::osc_send_control_note_on(const int32_t pluginId, const int32_t
{ {
qDebug("CarlaEngine::osc_send_control_note_on(%i, %i, %i, %i)", pluginId, channel, note, velo); qDebug("CarlaEngine::osc_send_control_note_on(%i, %i, %i, %i)", pluginId, channel, note, velo);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(channel >= 0 && channel < 16); CARLA_ASSERT(channel >= 0 && channel < 16);
CARLA_ASSERT(note >= 0 && note < 128); CARLA_ASSERT(note >= 0 && note < 128);
CARLA_ASSERT(velo > 0 && velo < 128); CARLA_ASSERT(velo > 0 && velo < 128);
@@ -1645,7 +1667,7 @@ void CarlaEngine::osc_send_control_note_off(const int32_t pluginId, const int32_
{ {
qDebug("CarlaEngine::osc_send_control_note_off(%i, %i, %i)", pluginId, channel, note); qDebug("CarlaEngine::osc_send_control_note_off(%i, %i, %i)", pluginId, channel, note);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(channel >= 0 && channel < 16); CARLA_ASSERT(channel >= 0 && channel < 16);
CARLA_ASSERT(note >= 0 && note < 128); CARLA_ASSERT(note >= 0 && note < 128);


@@ -1658,11 +1680,12 @@ void CarlaEngine::osc_send_control_note_off(const int32_t pluginId, const int32_
} }
} }


#if 0
void CarlaEngine::osc_send_control_set_input_peak_value(const int32_t pluginId, const int32_t portId) void CarlaEngine::osc_send_control_set_input_peak_value(const int32_t pluginId, const int32_t portId)
{ {
//qDebug("CarlaEngine::osc_send_control_set_input_peak_value(%i, %i)", pluginId, portId); //qDebug("CarlaEngine::osc_send_control_set_input_peak_value(%i, %i)", pluginId, portId);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(portId == 1 || portId == 2); CARLA_ASSERT(portId == 1 || portId == 2);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
@@ -1678,7 +1701,7 @@ void CarlaEngine::osc_send_control_set_output_peak_value(const int32_t pluginId,
{ {
//qDebug("CarlaEngine::osc_send_control_set_output_peak_value(%i, %i)", pluginId, portId); //qDebug("CarlaEngine::osc_send_control_set_output_peak_value(%i, %i)", pluginId, portId);
CARLA_ASSERT(data->oscData); CARLA_ASSERT(data->oscData);
CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber);
CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber);
CARLA_ASSERT(portId == 1 || portId == 2); CARLA_ASSERT(portId == 1 || portId == 2);


if (data->oscData && data->oscData->target) if (data->oscData && data->oscData->target)
@@ -1689,6 +1712,7 @@ void CarlaEngine::osc_send_control_set_output_peak_value(const int32_t pluginId,
lo_send(data->oscData->target, target_path, "iid", pluginId, portId, data->outsPeak[pluginId*MAX_PEAKS + portId-1]); lo_send(data->oscData->target, target_path, "iid", pluginId, portId, data->outsPeak[pluginId*MAX_PEAKS + portId-1]);
} }
} }
#endif


void CarlaEngine::osc_send_control_exit() void CarlaEngine::osc_send_control_exit()
{ {


+ 2
- 2
source/backend/engine/carla_engine.pro View File

@@ -31,8 +31,8 @@ VERSION = 0.5.0


SOURCES = \ SOURCES = \
carla_engine.cpp \ carla_engine.cpp \
carla_engine_osc.cpp \
carla_engine_thread.cpp \
# carla_engine_osc.cpp \
# carla_engine_thread.cpp \
jack.cpp \ jack.cpp \
plugin.cpp \ plugin.cpp \
rtaudio.cpp rtaudio.cpp


+ 48
- 15
source/backend/engine/carla_engine_internal.hpp View File

@@ -1,6 +1,6 @@
/* /*
* Carla Engine * Carla Engine
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -9,7 +9,7 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file
@@ -24,6 +24,8 @@


#include "carla_plugin.hpp" #include "carla_plugin.hpp"


#include "rt_list.hpp"

#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
# include <QtCore/QProcessEnvironment> # include <QtCore/QProcessEnvironment>
#endif #endif
@@ -104,6 +106,37 @@ const char* CarlaEngineControlEventType2Str(const CarlaEngineControlEventType ty
const uint32_t PATCHBAY_BUFFER_SIZE = 128; const uint32_t PATCHBAY_BUFFER_SIZE = 128;
const unsigned short PATCHBAY_EVENT_COUNT = 256; const unsigned short PATCHBAY_EVENT_COUNT = 256;


enum EnginePostEventType {
EnginePostEventNull,
EnginePostEventDebug,
PluginPostEventAddPlugin, // id, ptr
PluginPostEventRemovePlugin // id
};

struct EnginePostEvent {
EnginePostEventType type;
int32_t value1;
void* valuePtr;

EnginePostEvent()
: type(EnginePostEventNull),
value1(-1),
valuePtr(nullptr) {}
};

struct EnginePluginData {
CarlaPlugin* const plugin;
double insPeak[MAX_PEAKS];
double outsPeak[MAX_PEAKS];

EnginePluginData(CarlaPlugin* const plugin_)
: plugin(plugin_),
insPeak{0},
outsPeak{0} {}

EnginePluginData() = delete;
};

struct CarlaEnginePrivateData { struct CarlaEnginePrivateData {
CarlaEngineOsc osc; CarlaEngineOsc osc;
CarlaEngineThread thread; CarlaEngineThread thread;
@@ -112,24 +145,25 @@ struct CarlaEnginePrivateData {


CallbackFunc callback; CallbackFunc callback;
void* callbackPtr; void* callbackPtr;

CarlaString lastError; CarlaString lastError;


#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
QProcessEnvironment procEnv; QProcessEnvironment procEnv;
#endif #endif


CarlaMutex procLock;
CarlaMutex midiLock;
// for postEvents
CarlaMutex eventLock;


// TODO - use ListHead for pointers, remove maximum static value
CarlaPlugin* carlaPlugins[MAX_PLUGINS];
const char* uniqueNames[MAX_PLUGINS];
// for external midi input (GUI and OSC)
CarlaMutex midiLock;


double insPeak[MAX_PLUGINS * MAX_PEAKS];
double outsPeak[MAX_PLUGINS * MAX_PEAKS];
RtList<EnginePostEvent> postEvents;
RtList<EnginePluginData> plugins;


bool aboutToClose; bool aboutToClose;
unsigned short maxPluginNumber;
unsigned int maxPluginNumber;
unsigned int nextPluginId;


CarlaEnginePrivateData(CarlaEngine* const engine) CarlaEnginePrivateData(CarlaEngine* const engine)
: osc(engine), : osc(engine),
@@ -137,12 +171,11 @@ struct CarlaEnginePrivateData {
oscData(nullptr), oscData(nullptr),
callback(nullptr), callback(nullptr),
callbackPtr(nullptr), callbackPtr(nullptr),
carlaPlugins{nullptr},
uniqueNames{nullptr},
insPeak{0.0},
outsPeak{0.0},
postEvents(1, 1),
plugins(1, 1),
aboutToClose(false), aboutToClose(false),
maxPluginNumber(0) {}
maxPluginNumber(0),
nextPluginId(0) {}
}; };


CARLA_BACKEND_END_NAMESPACE CARLA_BACKEND_END_NAMESPACE


+ 5
- 5
source/backend/engine/carla_engine_osc.hpp View File

@@ -1,6 +1,6 @@
/* /*
* Carla Engine OSC * Carla Engine OSC
* Copyright (C) 2012 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -9,14 +9,14 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file
*/ */


#ifndef CARLA_ENGINE_OSC_HPP
#define CARLA_ENGINE_OSC_HPP
#ifndef __CARLA_ENGINE_OSC_HPP__
#define __CARLA_ENGINE_OSC_HPP__


#include "carla_backend.hpp" #include "carla_backend.hpp"
#include "carla_osc_utils.hpp" #include "carla_osc_utils.hpp"
@@ -166,4 +166,4 @@ private:


CARLA_BACKEND_END_NAMESPACE CARLA_BACKEND_END_NAMESPACE


#endif // CARLA_ENGINE_OSC_HPP
#endif // __CARLA_ENGINE_OSC_HPP__

+ 11
- 9
source/backend/engine/carla_engine_thread.hpp View File

@@ -1,6 +1,6 @@
/* /*
* Carla Engine Thread * Carla Engine Thread
* Copyright (C) 2012 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -9,18 +9,18 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file
*/ */


#ifndef CARLA_ENGINE_THREAD_HPP
#define CARLA_ENGINE_THREAD_HPP
#ifndef __CARLA_ENGINE_THREAD_HPP__
#define __CARLA_ENGINE_THREAD_HPP__


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


#include <QtCore/QMutex>
#include <QtCore/QThread> #include <QtCore/QThread>


CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE
@@ -48,11 +48,12 @@ protected:
private: private:
CarlaEngine* const engine; CarlaEngine* const engine;


QMutex m_mutex;
bool m_stopNow;
CarlaMutex m_mutex;
bool m_stopNow;


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


#if 0
class ScopedLocker class ScopedLocker
{ {
public: public:
@@ -68,10 +69,11 @@ private:
} }


private: private:
QMutex* const mutex;
CarlaMutex* const mutex;
}; };
#endif
}; };


CARLA_BACKEND_END_NAMESPACE CARLA_BACKEND_END_NAMESPACE


#endif // CARLA_ENGINE_THREAD_HPP
#endif // __CARLA_ENGINE_THREAD_HPP__

+ 8
- 10
source/backend/engine/jack.cpp View File

@@ -65,7 +65,7 @@ public:
if (! m_port) if (! m_port)
return CarlaEngineAudioPort::initBuffer(engine); return CarlaEngineAudioPort::initBuffer(engine);


buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize());
//buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize());
} }


float* getBuffer() const float* getBuffer() const
@@ -118,7 +118,7 @@ public:
if (! m_port) if (! m_port)
return CarlaEngineControlPort::initBuffer(engine); return CarlaEngineControlPort::initBuffer(engine);


buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize());
//buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize());


if (! isInput) if (! isInput)
jackbridge_midi_clear_buffer(buffer); jackbridge_midi_clear_buffer(buffer);
@@ -317,7 +317,7 @@ public:
if (! m_port) if (! m_port)
return CarlaEngineMidiPort::initBuffer(engine); return CarlaEngineMidiPort::initBuffer(engine);


buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize());
//buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize());


if (! isInput) if (! isInput)
jackbridge_midi_clear_buffer(buffer); jackbridge_midi_clear_buffer(buffer);
@@ -515,9 +515,7 @@ public:
CarlaEngineJack() CarlaEngineJack()
: CarlaEngine() : CarlaEngine()
#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
# ifdef Q_COMPILER_INITIALIZER_LISTS
, m_rackPorts{nullptr} , m_rackPorts{nullptr}
# endif
#endif #endif
{ {
qDebug("CarlaEngineJack::CarlaEngineJack()"); qDebug("CarlaEngineJack::CarlaEngineJack()");
@@ -530,11 +528,6 @@ public:


#ifdef BUILD_BRIDGE #ifdef BUILD_BRIDGE
hasQuit = false; hasQuit = false;
#else
# ifndef Q_COMPILER_INITIALIZER_LISTS
for (int i=0; i < rackPortCount; i++)
m_rackPorts[i] = nullptr;
# endif
#endif #endif
} }


@@ -741,6 +734,8 @@ public:
#endif #endif
} }


#if 0

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


protected: protected:
@@ -1025,6 +1020,7 @@ protected:
} }


// ------------------------------------- // -------------------------------------
#endif


private: private:
jack_client_t* m_client; jack_client_t* m_client;
@@ -1052,6 +1048,7 @@ private:
jack_port_t* m_rackPorts[rackPortCount]; jack_port_t* m_rackPorts[rackPortCount];
#endif #endif


#if 0
// ------------------------------------- // -------------------------------------


static void processPlugin(CarlaPlugin* const p, const uint32_t nframes) static void processPlugin(CarlaPlugin* const p, const uint32_t nframes)
@@ -1192,6 +1189,7 @@ private:
if (plugin && plugin->enabled()) if (plugin && plugin->enabled())
latencyPlugin(plugin, mode); latencyPlugin(plugin, mode);
} }
#endif
}; };


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


+ 3
- 0
source/backend/engine/rtaudio.cpp View File

@@ -65,6 +65,8 @@ public:
// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------
// RtAudio Engine // RtAudio Engine


#if 0

class CarlaEngineRtAudio : public CarlaEngine class CarlaEngineRtAudio : public CarlaEngine
{ {
public: public:
@@ -433,6 +435,7 @@ const char* CarlaEngine::getRtAudioApiName(unsigned int index)


return nullptr; return nullptr;
} }
#endif


CARLA_BACKEND_END_NAMESPACE CARLA_BACKEND_END_NAMESPACE




+ 203
- 136
source/discovery/carla-discovery.cpp View File

@@ -221,7 +221,7 @@ intptr_t VSTCALLBACK vstHostCallback(AEffect* const effect, const int32_t opcode
case audioMasterGetVendorString: case audioMasterGetVendorString:
if (ptr) if (ptr)
{ {
strcpy((char*)ptr, "Cadence");
strcpy((char*)ptr, "falkTX");
ret = 1; ret = 1;
} }
break; break;
@@ -274,7 +274,25 @@ void do_ladspa_check(void* const libHandle, const bool init)


while ((descriptor = descFn(i++))) while ((descriptor = descFn(i++)))
{ {
CARLA_ASSERT(descriptor->run);
if (! descriptor->instantiate)
{
DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no instantiate()");
continue;
}
if (! descriptor->cleanup)
{
DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no cleanup()");
continue;
}
if (! descriptor->run)
{
DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no run()");
continue;
}
if (! LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
{
DISCOVERY_OUT("warning", "Plugin '" << descriptor->Name << "' is not hard real-time capable");
}


int hints = 0; int hints = 0;
int audioIns = 0; int audioIns = 0;
@@ -284,6 +302,9 @@ void do_ladspa_check(void* const libHandle, const bool init)
int parametersOuts = 0; int parametersOuts = 0;
int parametersTotal = 0; int parametersTotal = 0;


if (LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
hints |= PLUGIN_IS_RTSAFE;

for (unsigned long j=0; j < descriptor->PortCount; j++) for (unsigned long j=0; j < descriptor->PortCount; j++)
{ {
const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j]; const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
@@ -294,14 +315,16 @@ void do_ladspa_check(void* const libHandle, const bool init)
audioIns += 1; audioIns += 1;
else if (LADSPA_IS_PORT_OUTPUT(portDescriptor)) else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
audioOuts += 1; audioOuts += 1;

audioTotal += 1; audioTotal += 1;
} }
else if (LADSPA_IS_PORT_CONTROL(portDescriptor)) else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
{ {
if (LADSPA_IS_PORT_INPUT(portDescriptor)) if (LADSPA_IS_PORT_INPUT(portDescriptor))
parametersIns += 1; parametersIns += 1;
else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && strcmp(descriptor->PortNames[j], "latency") && strcmp(descriptor->PortNames[j], "_latency") && strcmp(descriptor->PortNames[j], "_sample-rate"))
else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && strcmp(descriptor->PortNames[j], "latency") && strcmp(descriptor->PortNames[j], "_latency"))
parametersOuts += 1; parametersOuts += 1;

parametersTotal += 1; parametersTotal += 1;
} }
} }
@@ -323,81 +346,79 @@ void do_ladspa_check(void* const libHandle, const bool init)
LADSPA_Data bufferParams[parametersTotal]; LADSPA_Data bufferParams[parametersTotal];
LADSPA_Data min, max, def; LADSPA_Data min, max, def;


for (unsigned long j=0, iA=0, iP=0; j < descriptor->PortCount; j++)
for (unsigned long j=0, iA=0, iC=0; j < descriptor->PortCount; j++)
{ {
const LADSPA_PortDescriptor portType = descriptor->PortDescriptors[j];
const LADSPA_PortRangeHint portHints = descriptor->PortRangeHints[j];
const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
const LADSPA_PortRangeHint portRangeHints = descriptor->PortRangeHints[j];
const char* const portName = descriptor->PortNames[j];


if (LADSPA_IS_PORT_AUDIO(portType))
if (LADSPA_IS_PORT_AUDIO(portDescriptor))
{ {
carla_zeroFloat(bufferAudio[iA], bufferSize); carla_zeroFloat(bufferAudio[iA], bufferSize);
descriptor->connect_port(handle, j, bufferAudio[iA++]); descriptor->connect_port(handle, j, bufferAudio[iA++]);
} }
else if (LADSPA_IS_PORT_CONTROL(portType))
else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
{ {
// min value // min value
if (LADSPA_IS_HINT_BOUNDED_BELOW(portHints.HintDescriptor))
min = portHints.LowerBound;
if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
min = portRangeHints.LowerBound;
else else
min = 0.0f; min = 0.0f;


// max value // max value
if (LADSPA_IS_HINT_BOUNDED_ABOVE(portHints.HintDescriptor))
max = portHints.UpperBound;
if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
max = portRangeHints.UpperBound;
else else
max = 1.0f; max = 1.0f;


if (min > max) if (min > max)
max = min;
else if (max < min)
min = max;

if (max - min == 0.0f)
{ {
DISCOVERY_OUT("error", "Broken parameter '" << descriptor->PortNames[j] << "': max - min == 0");
DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
max = min + 0.1f;
}
else if (max - min == 0.0f)
{
DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max - min == 0");
max = min + 0.1f; max = min + 0.1f;
} }


// default value // default value
def = get_default_ladspa_port_value(portHints.HintDescriptor, min, max);
def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);


if (LADSPA_IS_HINT_SAMPLE_RATE(portHints.HintDescriptor))
if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
{ {
min *= sampleRate; min *= sampleRate;
max *= sampleRate; max *= sampleRate;
def *= sampleRate; def *= sampleRate;
} }


if (LADSPA_IS_PORT_OUTPUT(portType) && (strcmp(descriptor->PortNames[j], "latency") == 0 || strcmp(descriptor->PortNames[j], "_latency") == 0))
if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (strcmp(portName, "latency") == 0 || strcmp(portName, "_latency") == 0))
{ {
// latency parameter // latency parameter
min = 0.0f;
max = sampleRate;
def = 0.0f; def = 0.0f;
} }
else
{
if (def < min)
def = min;
else if (def > max)
def = max;
}


if (def < min)
def = min;
else if (def > max)
def = max;

bufferParams[iP] = def;

descriptor->connect_port(handle, j, &bufferParams[iP++]);
bufferParams[iC] = def;
descriptor->connect_port(handle, j, &bufferParams[iC++]);
} }
} }


if (descriptor->activate) if (descriptor->activate)
descriptor->activate(handle); descriptor->activate(handle);


if (descriptor->run)
descriptor->run(handle, bufferSize);
descriptor->run(handle, bufferSize);


if (descriptor->deactivate) if (descriptor->deactivate)
descriptor->deactivate(handle); descriptor->deactivate(handle);


if (descriptor->cleanup)
descriptor->cleanup(handle);
descriptor->cleanup(handle);


// end crash-free plugin test // end crash-free plugin test
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -408,7 +429,7 @@ void do_ladspa_check(void* const libHandle, const bool init)
DISCOVERY_OUT("label", descriptor->Label); DISCOVERY_OUT("label", descriptor->Label);
DISCOVERY_OUT("maker", descriptor->Maker); DISCOVERY_OUT("maker", descriptor->Maker);
DISCOVERY_OUT("copyright", descriptor->Copyright); DISCOVERY_OUT("copyright", descriptor->Copyright);
DISCOVERY_OUT("unique_id", descriptor->UniqueID);
DISCOVERY_OUT("uniqueId", descriptor->UniqueID);
DISCOVERY_OUT("hints", hints); DISCOVERY_OUT("hints", hints);
DISCOVERY_OUT("audio.ins", audioIns); DISCOVERY_OUT("audio.ins", audioIns);
DISCOVERY_OUT("audio.outs", audioOuts); DISCOVERY_OUT("audio.outs", audioOuts);
@@ -443,8 +464,31 @@ void do_dssi_check(void* const libHandle, const bool init)
while ((descriptor = descFn(i++))) while ((descriptor = descFn(i++)))
{ {
const LADSPA_Descriptor* const ldescriptor = descriptor->LADSPA_Plugin; const LADSPA_Descriptor* const ldescriptor = descriptor->LADSPA_Plugin;
CARLA_ASSERT(ldescriptor);
CARLA_ASSERT(ldescriptor->run || descriptor->run_synth || descriptor->run_multiple_synths);

if (! ldescriptor)
{
DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no LADSPA interface");
continue;
}
if (! ldescriptor->instantiate)
{
DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no instantiate()");
continue;
}
if (! ldescriptor->cleanup)
{
DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no cleanup()");
continue;
}
if (! (ldescriptor->run || descriptor->run_synth || descriptor->run_multiple_synths))
{
DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no run(), run_synth() or run_multiple_synths()");
continue;
}
if (! LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
{
DISCOVERY_OUT("warning", "Plugin '" << ldescriptor->Name << "' is not hard real-time capable");
}


int hints = 0; int hints = 0;
int audioIns = 0; int audioIns = 0;
@@ -457,6 +501,9 @@ void do_dssi_check(void* const libHandle, const bool init)
int parametersTotal = 0; int parametersTotal = 0;
int programsTotal = 0; int programsTotal = 0;


if (LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
hints |= PLUGIN_IS_RTSAFE;

for (unsigned long j=0; j < ldescriptor->PortCount; j++) for (unsigned long j=0; j < ldescriptor->PortCount; j++)
{ {
const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j]; const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
@@ -467,14 +514,16 @@ void do_dssi_check(void* const libHandle, const bool init)
audioIns += 1; audioIns += 1;
else if (LADSPA_IS_PORT_OUTPUT(portDescriptor)) else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
audioOuts += 1; audioOuts += 1;

audioTotal += 1; audioTotal += 1;
} }
else if (LADSPA_IS_PORT_CONTROL(portDescriptor)) else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
{ {
if (LADSPA_IS_PORT_INPUT(portDescriptor)) if (LADSPA_IS_PORT_INPUT(portDescriptor))
parametersIns += 1; parametersIns += 1;
else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && strcmp(ldescriptor->PortNames[j], "latency") && strcmp(ldescriptor->PortNames[j], "_latency") && strcmp(ldescriptor->PortNames[j], "_sample-rate"))
else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && strcmp(ldescriptor->PortNames[j], "latency") && strcmp(ldescriptor->PortNames[j], "_latency"))
parametersOuts += 1; parametersOuts += 1;

parametersTotal += 1; parametersTotal += 1;
} }
} }
@@ -482,7 +531,7 @@ void do_dssi_check(void* const libHandle, const bool init)
if (descriptor->run_synth || descriptor->run_multiple_synths) if (descriptor->run_synth || descriptor->run_multiple_synths)
midiIns = midiTotal = 1; midiIns = midiTotal = 1;


if (midiIns > 0 && audioOuts > 0)
if (midiIns > 0 && audioIns == 0 && audioOuts > 0)
hints |= PLUGIN_IS_SYNTH; hints |= PLUGIN_IS_SYNTH;


if (init) if (init)
@@ -498,10 +547,9 @@ void do_dssi_check(void* const libHandle, const bool init)
continue; continue;
} }


// we can only get program info per-handle
if (descriptor->get_program && descriptor->select_program) if (descriptor->get_program && descriptor->select_program)
{ {
while ((descriptor->get_program(handle, programsTotal++)))
while (descriptor->get_program(handle, programsTotal++))
continue; continue;
} }


@@ -509,77 +557,74 @@ void do_dssi_check(void* const libHandle, const bool init)
LADSPA_Data bufferParams[parametersTotal]; LADSPA_Data bufferParams[parametersTotal];
LADSPA_Data min, max, def; LADSPA_Data min, max, def;


for (unsigned long j=0, iA=0, iP=0; j < ldescriptor->PortCount; j++)
for (unsigned long j=0, iA=0, iC=0; j < ldescriptor->PortCount; j++)
{ {
const LADSPA_PortDescriptor portType = ldescriptor->PortDescriptors[j];
const LADSPA_PortRangeHint portHints = ldescriptor->PortRangeHints[j];
const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
const LADSPA_PortRangeHint portRangeHints = ldescriptor->PortRangeHints[j];
const char* const portName = ldescriptor->PortNames[j];


if (LADSPA_IS_PORT_AUDIO(portType))
if (LADSPA_IS_PORT_AUDIO(portDescriptor))
{ {
carla_zeroFloat(bufferAudio[iA], bufferSize); carla_zeroFloat(bufferAudio[iA], bufferSize);
ldescriptor->connect_port(handle, j, bufferAudio[iA++]); ldescriptor->connect_port(handle, j, bufferAudio[iA++]);
} }
else if (LADSPA_IS_PORT_CONTROL(portType))
else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
{ {
// min value // min value
if (LADSPA_IS_HINT_BOUNDED_BELOW(portHints.HintDescriptor))
min = portHints.LowerBound;
if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
min = portRangeHints.LowerBound;
else else
min = 0.0f; min = 0.0f;


// max value // max value
if (LADSPA_IS_HINT_BOUNDED_ABOVE(portHints.HintDescriptor))
max = portHints.UpperBound;
if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
max = portRangeHints.UpperBound;
else else
max = 1.0f; max = 1.0f;


if (min > max) if (min > max)
max = min;
else if (max < min)
min = max;

if (max - min == 0.0f)
{ {
DISCOVERY_OUT("error", "Broken parameter '" << ldescriptor->PortNames[j] << "': max - min == 0");
DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
max = min + 0.1f;
}
else if (max - min == 0.0f)
{
DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max - min == 0");
max = min + 0.1f; max = min + 0.1f;
} }


// default value // default value
def = get_default_ladspa_port_value(portHints.HintDescriptor, min, max);
def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);


if (LADSPA_IS_HINT_SAMPLE_RATE(portHints.HintDescriptor))
if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
{ {
min *= sampleRate; min *= sampleRate;
max *= sampleRate; max *= sampleRate;
def *= sampleRate; def *= sampleRate;
} }


if (LADSPA_IS_PORT_OUTPUT(portType) && (strcmp(ldescriptor->PortNames[j], "latency") == 0 || strcmp(ldescriptor->PortNames[j], "_latency") == 0))
if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (strcmp(portName, "latency") == 0 || strcmp(portName, "_latency") == 0))
{ {
// latency parameter // latency parameter
min = 0.0f;
max = sampleRate;
def = 0.0f; def = 0.0f;
} }
else
{
if (def < min)
def = min;
else if (def > max)
def = max;
}


if (def < min)
def = min;
else if (def > max)
def = max;

bufferParams[iP] = def;

ldescriptor->connect_port(handle, j, &bufferParams[iP++]);
bufferParams[iC] = def;
ldescriptor->connect_port(handle, j, &bufferParams[iC++]);
} }
} }


// select first midi-program if available // select first midi-program if available
if (programsTotal > 0) if (programsTotal > 0)
{ {
const DSSI_Program_Descriptor* pDesc = descriptor->get_program(handle, 0);
CARLA_ASSERT(pDesc);

if (pDesc)
if (const DSSI_Program_Descriptor* const pDesc = descriptor->get_program(handle, 0))
descriptor->select_program(handle, pDesc->Bank, pDesc->Program); descriptor->select_program(handle, pDesc->Bank, pDesc->Program);
} }


@@ -612,14 +657,13 @@ void do_dssi_check(void* const libHandle, const bool init)
else else
descriptor->run_synth(handle, bufferSize, midiEvents, midiEventCount); descriptor->run_synth(handle, bufferSize, midiEvents, midiEventCount);
} }
else if (ldescriptor->run)
else
ldescriptor->run(handle, bufferSize); ldescriptor->run(handle, bufferSize);


if (ldescriptor->deactivate) if (ldescriptor->deactivate)
ldescriptor->deactivate(handle); ldescriptor->deactivate(handle);


if (ldescriptor->cleanup)
ldescriptor->cleanup(handle);
ldescriptor->cleanup(handle);


// end crash-free plugin test // end crash-free plugin test
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -672,7 +716,9 @@ void do_lv2_check(const char* const bundle, const bool init)
LILV_FOREACH(plugins, i, lilvPlugins) LILV_FOREACH(plugins, i, lilvPlugins)
{ {
Lilv::Plugin lilvPlugin(lilv_plugins_get(lilvPlugins, i)); Lilv::Plugin lilvPlugin(lilv_plugins_get(lilvPlugins, i));
URIs.append(QString(lilvPlugin.get_uri().as_string()));

if (const char* const uri = lilvPlugin.get_uri().as_string())
URIs.append(QString(uri));
} }


// Get & check every plugin-instance // Get & check every plugin-instance
@@ -689,80 +735,69 @@ void do_lv2_check(const char* const bundle, const bool init)


if (init) if (init)
{ {
// test if DLL is loadable
// test if DLL is loadable, twice
bool isLoadable = true;

for (int j=0; j < 2; j++)
{ {
void* const libHandle = lib_open(rdfDescriptor->Binary); void* const libHandle = lib_open(rdfDescriptor->Binary);


if (! libHandle) if (! libHandle)
{ {
isLoadable = false;
print_lib_error(rdfDescriptor->Binary); print_lib_error(rdfDescriptor->Binary);
delete rdfDescriptor; delete rdfDescriptor;
continue;
break;
} }


lib_close(libHandle); lib_close(libHandle);
} }


// test if we support all required ports and features
if (! isLoadable)
continue;
}

// test if we support all required ports and features
{
bool supported = true;

for (uint32_t j=0; j < rdfDescriptor->PortCount && supported; j++)
{ {
bool supported = true;
const LV2_RDF_Port* const rdfPort = &rdfDescriptor->Ports[j];


for (uint32_t j=0; j < rdfDescriptor->PortCount; j++)
if (is_lv2_port_supported(rdfPort->Types))
{ {
const LV2_RDF_Port* const rdfPort = &rdfDescriptor->Ports[j];

if (LV2_IS_PORT_CONTROL(rdfPort->Types))
{
pass();
}
else if (LV2_IS_PORT_AUDIO(rdfPort->Types))
{
pass();
}
else if (LV2_IS_PORT_ATOM_SEQUENCE(rdfPort->Types))
{
pass();
}
//else if (LV2_IS_PORT_CV(rdfPort->Types))
// pass();
else if (LV2_IS_PORT_EVENT(rdfPort->Types))
{
pass();
}
else if (LV2_IS_PORT_MIDI_LL(rdfPort->Types))
{
pass();
}
else if (! LV2_IS_PORT_OPTIONAL(rdfPort->Properties))
{
DISCOVERY_OUT("error", "plugin requires a non-supported port type, port-name: " << rdfPort->Name);
supported = false;
break;
}
pass();
} }

for (uint32_t j=0; j < rdfDescriptor->FeatureCount && supported; j++)
else if (! LV2_IS_PORT_OPTIONAL(rdfPort->Properties))
{ {
const LV2_RDF_Feature* const rdfFeature = &rdfDescriptor->Features[j];

if (is_lv2_feature_supported(rdfFeature->URI))
{
pass();
}
else if (LV2_IS_FEATURE_REQUIRED(rdfFeature->Type))
{
DISCOVERY_OUT("error", "plugin requires a non-supported feature " << rdfFeature->URI);
supported = false;
break;
}
DISCOVERY_OUT("error", "Plugin '" << rdfDescriptor->URI << "' requires a non-supported port type (portName: '" << rdfPort->Name << "')");
supported = false;
break;
} }
}


if (! supported)
for (uint32_t j=0; j < rdfDescriptor->FeatureCount && supported; j++)
{
const LV2_RDF_Feature* const rdfFeature = &rdfDescriptor->Features[j];

if (is_lv2_feature_supported(rdfFeature->URI))
{ {
delete rdfDescriptor;
continue;
pass();
}
else if (LV2_IS_FEATURE_REQUIRED(rdfFeature->Type))
{
DISCOVERY_OUT("error", "Plugin '" << rdfDescriptor->URI << "' requires a non-supported feature '" << rdfFeature->URI << "'");
supported = false;
break;
} }
} }

if (! supported)
{
delete rdfDescriptor;
continue;
}
} }


int hints = 0; int hints = 0;
@@ -777,6 +812,14 @@ void do_lv2_check(const char* const bundle, const bool init)
int parametersTotal = 0; int parametersTotal = 0;
int programsTotal = rdfDescriptor->PresetCount; int programsTotal = rdfDescriptor->PresetCount;


for (uint32_t j=0; j < rdfDescriptor->FeatureCount; j++)
{
const LV2_RDF_Feature* const rdfFeature = &rdfDescriptor->Features[j];

if (strcmp(rdfFeature->URI, LV2_CORE__hardRTCapable) == 0)
hints |= PLUGIN_IS_RTSAFE;
}

for (uint32_t j=0; j < rdfDescriptor->PortCount; j++) for (uint32_t j=0; j < rdfDescriptor->PortCount; j++)
{ {
const LV2_RDF_Port* const rdfPort = &rdfDescriptor->Ports[j]; const LV2_RDF_Port* const rdfPort = &rdfDescriptor->Ports[j];
@@ -787,6 +830,7 @@ void do_lv2_check(const char* const bundle, const bool init)
audioIns += 1; audioIns += 1;
else if (LV2_IS_PORT_OUTPUT(rdfPort->Types)) else if (LV2_IS_PORT_OUTPUT(rdfPort->Types))
audioOuts += 1; audioOuts += 1;

audioTotal += 1; audioTotal += 1;
} }
else if (LV2_IS_PORT_CONTROL(rdfPort->Types)) else if (LV2_IS_PORT_CONTROL(rdfPort->Types))
@@ -813,6 +857,7 @@ void do_lv2_check(const char* const bundle, const bool init)
parametersIns += 1; parametersIns += 1;
else if (LV2_IS_PORT_OUTPUT(rdfPort->Types)) else if (LV2_IS_PORT_OUTPUT(rdfPort->Types))
parametersOuts += 1; parametersOuts += 1;

parametersTotal += 1; parametersTotal += 1;
} }
} }
@@ -822,6 +867,7 @@ void do_lv2_check(const char* const bundle, const bool init)
midiIns += 1; midiIns += 1;
else if (LV2_IS_PORT_OUTPUT(rdfPort->Types)) else if (LV2_IS_PORT_OUTPUT(rdfPort->Types))
midiOuts += 1; midiOuts += 1;

midiTotal += 1; midiTotal += 1;
} }
} }
@@ -870,12 +916,14 @@ void do_vst_check(void* const libHandle, const bool init)
VST_Function vstFn = (VST_Function)lib_symbol(libHandle, "VSTPluginMain"); VST_Function vstFn = (VST_Function)lib_symbol(libHandle, "VSTPluginMain");


if (! vstFn) if (! vstFn)
{
vstFn = (VST_Function)lib_symbol(libHandle, "main"); vstFn = (VST_Function)lib_symbol(libHandle, "main");


if (! vstFn)
{
DISCOVERY_OUT("error", "Not a VST plugin");
return;
if (! vstFn)
{
DISCOVERY_OUT("error", "Not a VST plugin");
return;
}
} }


AEffect* const effect = vstFn(vstHostCallback); AEffect* const effect = vstFn(vstHostCallback);
@@ -895,7 +943,7 @@ void do_vst_check(void* const libHandle, const bool init)


intptr_t vstCategory = effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f); intptr_t vstCategory = effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f);


if (vstCategory == kPlugCategShell)
if (vstCategory == kPlugCategShell && effect->uniqueID == 0)
{ {
if ((vstCurrentUniqueId = effect->dispatcher(effect, effShellGetNextPlugin, 0, 0, strBuf, 0.0f)) != 0) if ((vstCurrentUniqueId = effect->dispatcher(effect, effShellGetNextPlugin, 0, 0, strBuf, 0.0f)) != 0)
cName = strBuf; cName = strBuf;
@@ -1409,6 +1457,25 @@ int main(int argc, char* argv[])
if (doInit && getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS")) if (doInit && getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS"))
doInit = false; doInit = false;


if (doInit && handle)
{
// test fast loading & unloading DLL without initializing the plugin(s)

if (! lib_close(handle))
{
print_lib_error(filename);
return 1;
}

handle = lib_open(filename);

if (! handle)
{
print_lib_error(filename);
return 1;
}
}

switch (type) switch (type)
{ {
case PLUGIN_LADSPA: case PLUGIN_LADSPA:
@@ -1436,7 +1503,7 @@ int main(int argc, char* argv[])
break; break;
} }


if (openLib)
if (openLib && handle)
lib_close(handle); lib_close(handle);


return 0; return 0;


+ 4
- 2
source/includes/carla_defines.hpp View File

@@ -9,7 +9,7 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file
@@ -81,9 +81,11 @@
#ifdef NDEBUG #ifdef NDEBUG
# define CARLA_ASSERT(cond) ((!(cond)) ? carla_assert(#cond, __FILE__, __LINE__) : qt_noop()) # define CARLA_ASSERT(cond) ((!(cond)) ? carla_assert(#cond, __FILE__, __LINE__) : qt_noop())
# define CARLA_ASSERT_INT(cond, value) ((!(cond)) ? carla_assert_int(#cond, __FILE__, __LINE__, value) : qt_noop()) # define CARLA_ASSERT_INT(cond, value) ((!(cond)) ? carla_assert_int(#cond, __FILE__, __LINE__, value) : qt_noop())
# define CARLA_ASSERT_INT2(cond, v1, v2) ((!(cond)) ? carla_assert_int2(#cond, __FILE__, __LINE__, v1, v2) : qt_noop())
#else #else
# define CARLA_ASSERT Q_ASSERT
# define CARLA_ASSERT(cond) Q_ASSERT(cond)
# define CARLA_ASSERT_INT(cond, value) Q_ASSERT(cond) # define CARLA_ASSERT_INT(cond, value) Q_ASSERT(cond)
# define CARLA_ASSERT_INT2(cond, v1, v2) Q_ASSERT(cond)
#endif #endif


// Define CARLA_EXPORT // Define CARLA_EXPORT


+ 47
- 80
source/utils/carla_backend_utils.hpp View File

@@ -1,5 +1,5 @@
/* /*
* Carla Backend
* Carla Backend utils
* Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com> * Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@@ -9,29 +9,21 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file
*/ */


#ifndef CARLA_BACKEND_UTILS_HPP
#define CARLA_BACKEND_UTILS_HPP
#ifndef __CARLA_BACKEND_UTILS_HPP__
#define __CARLA_BACKEND_UTILS_HPP__


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


CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE


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

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


static inline static inline
const char* BinaryType2Str(const BinaryType& type) const char* BinaryType2Str(const BinaryType& type)
@@ -156,41 +148,14 @@ const char* InternalParametersIndex2Str(const InternalParametersIndex& index)
return "PARAMETER_BALANCE_LEFT"; return "PARAMETER_BALANCE_LEFT";
case PARAMETER_BALANCE_RIGHT: case PARAMETER_BALANCE_RIGHT:
return "PARAMETER_BALANCE_RIGHT"; return "PARAMETER_BALANCE_RIGHT";
case PARAMETER_PANNING:
return "PARAMETER_PANNING";
} }


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


#if 0
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;
}
#endif

static inline static inline
const char* OptionsType2Str(const OptionsType& type) const char* OptionsType2Str(const OptionsType& type)
{ {
@@ -202,24 +167,25 @@ const char* OptionsType2Str(const OptionsType& type)
return "OPTION_PROCESS_MODE"; return "OPTION_PROCESS_MODE";
case OPTION_PROCESS_HIGH_PRECISION: case OPTION_PROCESS_HIGH_PRECISION:
return "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: case OPTION_FORCE_STEREO:
return "OPTION_FORCE_STEREO"; return "OPTION_FORCE_STEREO";
#ifdef WANT_DSSI
case OPTION_USE_DSSI_VST_CHUNKS:
return "OPTION_USE_DSSI_VST_CHUNKS";
#endif
case OPTION_PREFER_PLUGIN_BRIDGES: case OPTION_PREFER_PLUGIN_BRIDGES:
return "OPTION_PREFER_PLUGIN_BRIDGES"; return "OPTION_PREFER_PLUGIN_BRIDGES";
case OPTION_PREFER_UI_BRIDGES: case OPTION_PREFER_UI_BRIDGES:
return "OPTION_PREFER_UI_BRIDGES"; return "OPTION_PREFER_UI_BRIDGES";
#ifdef WANT_DSSI
case OPTION_USE_DSSI_VST_CHUNKS:
return "OPTION_USE_DSSI_VST_CHUNKS";
#endif
case OPTION_MAX_PARAMETERS:
return "OPTION_MAX_PARAMETERS";
case OPTION_OSC_UI_TIMEOUT: case OPTION_OSC_UI_TIMEOUT:
return "OPTION_OSC_UI_TIMEOUT"; return "OPTION_OSC_UI_TIMEOUT";
case OPTION_PREFERRED_BUFFER_SIZE:
return "OPTION_PREFERRED_BUFFER_SIZE";
case OPTION_PREFERRED_SAMPLE_RATE:
return "OPTION_PREFERRED_SAMPLE_RATE";
#ifndef BUILD_BRIDGE
case OPTION_PATH_BRIDGE_NATIVE: case OPTION_PATH_BRIDGE_NATIVE:
return "OPTION_PATH_BRIDGE_NATIVE"; return "OPTION_PATH_BRIDGE_NATIVE";
case OPTION_PATH_BRIDGE_POSIX32: case OPTION_PATH_BRIDGE_POSIX32:
@@ -230,6 +196,7 @@ const char* OptionsType2Str(const OptionsType& type)
return "OPTION_PATH_BRIDGE_WIN32"; return "OPTION_PATH_BRIDGE_WIN32";
case OPTION_PATH_BRIDGE_WIN64: case OPTION_PATH_BRIDGE_WIN64:
return "OPTION_PATH_BRIDGE_WIN64"; return "OPTION_PATH_BRIDGE_WIN64";
#endif
#ifdef WANT_LV2 #ifdef WANT_LV2
case OPTION_PATH_BRIDGE_LV2_GTK2: case OPTION_PATH_BRIDGE_LV2_GTK2:
return "OPTION_PATH_BRIDGE_LV2_GTK2"; return "OPTION_PATH_BRIDGE_LV2_GTK2";
@@ -283,8 +250,6 @@ const char* CallbackType2Str(const CallbackType& type)
return "CALLBACK_NOTE_OFF"; return "CALLBACK_NOTE_OFF";
case CALLBACK_SHOW_GUI: case CALLBACK_SHOW_GUI:
return "CALLBACK_SHOW_GUI"; return "CALLBACK_SHOW_GUI";
case CALLBACK_RESIZE_GUI:
return "CALLBACK_RESIZE_GUI";
case CALLBACK_UPDATE: case CALLBACK_UPDATE:
return "CALLBACK_UPDATE"; return "CALLBACK_UPDATE";
case CALLBACK_RELOAD_INFO: case CALLBACK_RELOAD_INFO:
@@ -332,7 +297,28 @@ const char* ProcessMode2Str(const ProcessMode& mode)
return nullptr; return nullptr;
} }


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

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 static inline
const char* getPluginTypeString(const PluginType& type) const char* getPluginTypeString(const PluginType& type)
@@ -343,8 +329,10 @@ const char* getPluginTypeString(const PluginType& type)
{ {
case PLUGIN_NONE: case PLUGIN_NONE:
return "NONE"; return "NONE";
#ifndef BUILD_BRIDGE
case PLUGIN_INTERNAL: case PLUGIN_INTERNAL:
return "INTERNAL"; return "INTERNAL";
#endif
case PLUGIN_LADSPA: case PLUGIN_LADSPA:
return "LADSPA"; return "LADSPA";
case PLUGIN_DSSI: case PLUGIN_DSSI:
@@ -353,39 +341,20 @@ const char* getPluginTypeString(const PluginType& type)
return "LV2"; return "LV2";
case PLUGIN_VST: case PLUGIN_VST:
return "VST"; return "VST";
#ifndef BUILD_BRIDGE
case PLUGIN_GIG: case PLUGIN_GIG:
return "GIG"; return "GIG";
case PLUGIN_SF2: case PLUGIN_SF2:
return "SF2"; return "SF2";
case PLUGIN_SFZ: case PLUGIN_SFZ:
return "SFZ"; return "SFZ";
#endif
} }


return "NONE"; 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 static inline
PluginCategory getPluginCategoryFromName(const char* const name) PluginCategory getPluginCategoryFromName(const char* const name)
@@ -466,8 +435,6 @@ PluginCategory getPluginCategoryFromName(const char* const name)
return PLUGIN_CATEGORY_NONE; return PLUGIN_CATEGORY_NONE;
} }


/**@}*/

CARLA_BACKEND_END_NAMESPACE CARLA_BACKEND_END_NAMESPACE


#endif // CARLA_BACKEND_UTILS_HPP
#endif // __CARLA_BACKEND_UTILS_HPP__

+ 27
- 2
source/utils/carla_lv2_utils.hpp View File

@@ -1124,10 +1124,30 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri)
return rdfDescriptor; return rdfDescriptor;
} }


// -------------------------------------------------
// Check if we support a plugin port

static inline
bool is_lv2_port_supported(const LV2_Property types)
{
if (LV2_IS_PORT_CONTROL(types))
return true;
if (LV2_IS_PORT_AUDIO(types))
return true;
if (LV2_IS_PORT_ATOM_SEQUENCE(types))
return true;
if (LV2_IS_PORT_CV(types))
return true; // TODO
if (LV2_IS_PORT_EVENT(types))
return true;
if (LV2_IS_PORT_MIDI_LL(types))
return true;
return false;
}

// ------------------------------------------------- // -------------------------------------------------
// Check if we support a plugin feature // Check if we support a plugin feature


// TODO - review these
static inline static inline
bool is_lv2_feature_supported(const LV2_URI uri) bool is_lv2_feature_supported(const LV2_URI uri)
{ {
@@ -1137,6 +1157,12 @@ bool is_lv2_feature_supported(const LV2_URI uri)
return true; return true;
if (strcmp(uri, LV2_CORE__isLive) == 0) if (strcmp(uri, LV2_CORE__isLive) == 0)
return true; return true;
if (strcmp(uri, LV2_BUF_SIZE__boundedBlockLength) == 0)
return true;
if (strcmp(uri, LV2_BUF_SIZE__fixedBlockLength) == 0)
return true;
if (strcmp(uri, LV2_BUF_SIZE__powerOf2BlockLength) == 0)
return true;
if (strcmp(uri, LV2_EVENT_URI) == 0) if (strcmp(uri, LV2_EVENT_URI) == 0)
return true; return true;
if (strcmp(uri, LV2_LOG__log) == 0) if (strcmp(uri, LV2_LOG__log) == 0)
@@ -1167,7 +1193,6 @@ bool is_lv2_feature_supported(const LV2_URI uri)
// ------------------------------------------------- // -------------------------------------------------
// Check if we support a plugin or UI feature // Check if we support a plugin or UI feature


// TODO - review these
static inline static inline
bool is_lv2_ui_feature_supported(const LV2_URI uri) bool is_lv2_ui_feature_supported(const LV2_URI uri)
{ {


+ 8
- 2
source/utils/carla_utils.hpp View File

@@ -9,7 +9,7 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file
@@ -47,8 +47,14 @@ void carla_assert_int(const char* const assertion, const char* const file, const
qCritical("Carla assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value); qCritical("Carla assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
} }


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

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


static inline static inline
void carla_sleep(const unsigned int secs) void carla_sleep(const unsigned int secs)


+ 15
- 14
source/utils/rt_list.hpp View File

@@ -36,7 +36,7 @@ public:
qcount = 0; qcount = 0;
INIT_LIST_HEAD(&queue); INIT_LIST_HEAD(&queue);


rtsafe_memory_pool_create(&mempool, nullptr, sizeof(ListHeadData), minPreallocated, maxPreallocated);
rtsafe_memory_pool_create(&mempool, nullptr, sizeof(RtListData), minPreallocated, maxPreallocated);


assert(mempool); assert(mempool);
} }
@@ -53,7 +53,7 @@ public:
clear(); clear();


rtsafe_memory_pool_destroy(mempool); rtsafe_memory_pool_destroy(mempool);
rtsafe_memory_pool_create(&mempool, nullptr, sizeof(ListHeadData), minPreallocated, maxPreallocated);
rtsafe_memory_pool_create(&mempool, nullptr, sizeof(RtListData), minPreallocated, maxPreallocated);


assert(mempool); assert(mempool);
} }
@@ -62,12 +62,12 @@ public:
{ {
if (! isEmpty()) if (! isEmpty())
{ {
ListHeadData* data;
RtListData* data;
k_list_head* entry; k_list_head* entry;


list_for_each(entry, &queue) list_for_each(entry, &queue)
{ {
data = list_entry(entry, ListHeadData, siblings);
data = list_entry(entry, RtListData, siblings);
rtsafe_memory_pool_deallocate(mempool, data); rtsafe_memory_pool_deallocate(mempool, data);
} }
} }
@@ -83,17 +83,18 @@ public:


bool isEmpty() const bool isEmpty() const
{ {
return (list_empty(&queue) != 0);
return (qcount == 0);
//return (list_empty(&queue) != 0);
} }


void append(const T& value, const bool sleepy = false) void append(const T& value, const bool sleepy = false)
{ {
ListHeadData* data;
RtListData* data;


if (sleepy) if (sleepy)
data = (ListHeadData*)rtsafe_memory_pool_allocate_sleepy(mempool);
data = (RtListData*)rtsafe_memory_pool_allocate_sleepy(mempool);
else else
data = (ListHeadData*)rtsafe_memory_pool_allocate_atomic(mempool);
data = (RtListData*)rtsafe_memory_pool_allocate_atomic(mempool);


if (data) if (data)
{ {
@@ -126,12 +127,12 @@ public:


bool removeOne(const T& value) bool removeOne(const T& value)
{ {
ListHeadData* data;
RtListData* data;
k_list_head* entry; k_list_head* entry;


list_for_each(entry, &queue) list_for_each(entry, &queue)
{ {
data = list_entry(entry, ListHeadData, siblings);
data = list_entry(entry, RtListData, siblings);


if (data->value == value) if (data->value == value)
{ {
@@ -147,13 +148,13 @@ public:


void removeAll(const T& value) void removeAll(const T& value)
{ {
ListHeadData* data;
RtListData* data;
k_list_head* entry; k_list_head* entry;
k_list_head* tmp; k_list_head* tmp;


list_for_each_safe(entry, tmp, &queue) list_for_each_safe(entry, tmp, &queue)
{ {
data = list_entry(entry, ListHeadData, siblings);
data = list_entry(entry, RtListData, siblings);


if (data->value == value) if (data->value == value)
{ {
@@ -169,7 +170,7 @@ private:
k_list_head queue; k_list_head queue;
RtMemPool_Handle mempool; RtMemPool_Handle mempool;


struct ListHeadData {
struct RtListData {
T value; T value;
k_list_head siblings; k_list_head siblings;
}; };
@@ -192,7 +193,7 @@ private:
} }


k_list_head* entry = first ? queue.next : queue.prev; k_list_head* entry = first ? queue.next : queue.prev;
ListHeadData* data = list_entry(entry, ListHeadData, siblings);
RtListData* data = list_entry(entry, RtListData, siblings);


T& ret = data->value; T& ret = data->value;




Loading…
Cancel
Save