From d11d669174b53257560542cd868f6d3c56f9db7d Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 18 Jan 2013 21:51:06 +0000 Subject: [PATCH] Misc stuff --- source/backend/carla_backend.hpp | 172 ++++----- source/backend/carla_engine.hpp | 132 +++---- source/backend/carla_plugin.hpp | 9 +- source/backend/engine/carla_engine.cpp | 96 +++-- source/backend/engine/carla_engine.pro | 4 +- .../backend/engine/carla_engine_internal.hpp | 63 +++- source/backend/engine/carla_engine_osc.hpp | 10 +- source/backend/engine/carla_engine_thread.hpp | 20 +- source/backend/engine/jack.cpp | 18 +- source/backend/engine/rtaudio.cpp | 3 + source/discovery/carla-discovery.cpp | 339 +++++++++++------- source/includes/carla_defines.hpp | 6 +- source/utils/carla_backend_utils.hpp | 127 +++---- source/utils/carla_lv2_utils.hpp | 29 +- source/utils/carla_utils.hpp | 10 +- source/utils/rt_list.hpp | 29 +- 16 files changed, 594 insertions(+), 473 deletions(-) diff --git a/source/backend/carla_backend.hpp b/source/backend/carla_backend.hpp index 7b37bf64b..5de31b04e 100644 --- a/source/backend/carla_backend.hpp +++ b/source/backend/carla_backend.hpp @@ -9,7 +9,7 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the COPYING file @@ -18,6 +18,8 @@ #ifndef __CARLA_BACKEND_HPP__ #define __CARLA_BACKEND_HPP__ +// TODO - remove ifdef's when Carla stabilizes + #include "carla_defines.hpp" #include @@ -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 @@ -56,14 +56,17 @@ const unsigned int MAX_PARAMETERS = 200; //!< Default value for the maximum numb #ifndef BUILD_BRIDGE const unsigned int PLUGIN_IS_BRIDGE = 0x001; //!< Plugin is a bridge (ie, BridgePlugin). This hint is required because "bridge" itself is not a plugin type. #endif -const unsigned int PLUGIN_IS_SYNTH = 0x002; //!< Plugin is a synthesizer (produces sound). -const unsigned int PLUGIN_HAS_GUI = 0x004; //!< Plugin has its own custom GUI. -const unsigned int PLUGIN_USES_CHUNKS = 0x008; //!< Plugin uses chunks to save internal data.\see CarlaPlugin::chunkData() -const unsigned int PLUGIN_USES_SINGLE_THREAD = 0x010; //!< Plugin needs a single thread for both DSP 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() * @{ */ -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_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_CUSTOM_TEXT = 0x80; //!< Parameter uses custom text for displaying its value.\see CarlaPlugin::getParameterText() /**@}*/ +#if 0 /*! * @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_STRING = "http://kxstudio.sf.net/ns/carla/string"; //!< Carla String /**@}*/ +#endif +#if 0 /*! * @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 * @{ */ -//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. @@ -126,7 +133,7 @@ enum BinaryType { /*! * 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 { 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_DRYWET = -3, //!< Dry/Wet parameter, range 0.0...1.0; default is 1.0. PARAMETER_VOLUME = -4, //!< Volume parameter, range 0.0...1.27; default is 1.0. - PARAMETER_BALANCE_LEFT = -5, //!< Balance-Left parameter, range -1.0...1.0; default is -1.0. - PARAMETER_BALANCE_RIGHT = -6 //!< Balance-Right parameter, range -1.0...1.0; default is 1.0. + 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 { /*! - * Try to set the current process name.\n + * Try to set the current process name. * \note Not available on all platforms. */ OPTION_PROCESS_NAME = 0, @@ -232,54 +223,55 @@ enum OptionsType { 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 /*! * Use (unofficial) dssi-vst chunks feature.\n * Default is no. */ - OPTION_USE_DSSI_VST_CHUNKS = 7, + OPTION_USE_DSSI_VST_CHUNKS = 6, #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 * Default unset. @@ -309,6 +301,7 @@ enum OptionsType { * Default unset. */ OPTION_PATH_BRIDGE_WIN64 = 15, +#endif #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() */ enum CallbackType { @@ -449,72 +443,64 @@ enum CallbackType { * \param value1 State, as follows:.\n * 0: GUI has been closed or hidden\n * 1: GUI has been shown\n - * -1: GUI has crashed and should not be shown again\n + * -1: GUI has crashed and should not be shown again */ CALLBACK_SHOW_GUI = 8, - /*! - * The plugin's custom GUI has been resized. - * - * \param value1 Width - * \param value2 Height - */ - CALLBACK_RESIZE_GUI = 9, - /*! * The plugin needs update. */ - CALLBACK_UPDATE = 10, + CALLBACK_UPDATE = 9, /*! * The plugin's data/information has changed. */ - CALLBACK_RELOAD_INFO = 11, + CALLBACK_RELOAD_INFO = 10, /*! * The plugin's parameters have changed. */ - CALLBACK_RELOAD_PARAMETERS = 12, + CALLBACK_RELOAD_PARAMETERS = 11, /*! * The plugin's programs have changed. */ - CALLBACK_RELOAD_PROGRAMS = 13, + CALLBACK_RELOAD_PROGRAMS = 12, /*! * The plugin's state has changed. */ - CALLBACK_RELOAD_ALL = 14, + CALLBACK_RELOAD_ALL = 13, /*! * Non-Session-Manager Announce message. */ - CALLBACK_NSM_ANNOUNCE = 15, + CALLBACK_NSM_ANNOUNCE = 14, /*! * Non-Session-Manager Open message #1. */ - CALLBACK_NSM_OPEN1 = 16, + CALLBACK_NSM_OPEN1 = 15, /*! * Non-Session-Manager Open message #2. */ - CALLBACK_NSM_OPEN2 = 17, + CALLBACK_NSM_OPEN2 = 16, /*! * Non-Session-Manager Save message. */ - CALLBACK_NSM_SAVE = 18, + CALLBACK_NSM_SAVE = 17, /*! * 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. */ - CALLBACK_QUIT = 20 + CALLBACK_QUIT = 19 }; /*! @@ -598,7 +584,7 @@ struct MidiProgramData { /*! * Custom data, saving key:value 'dictionaries'. - * \a type is an URI. + * \a type is an URI which defines the \a value type. * * \see CustomDataTypes */ diff --git a/source/backend/carla_engine.hpp b/source/backend/carla_engine.hpp index 7157bdeda..f0649b2a2 100644 --- a/source/backend/carla_engine.hpp +++ b/source/backend/carla_engine.hpp @@ -9,7 +9,7 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the COPYING file @@ -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. @@ -236,11 +193,13 @@ struct CarlaEngineOptions { uint preferredBufferSize; uint preferredSampleRate; +#ifndef BUILD_BRIDGE CarlaString bridge_native; CarlaString bridge_posix32; CarlaString bridge_posix64; CarlaString bridge_win32; CarlaString bridge_win64; +#endif #ifdef WANT_LV2 CarlaString bridge_lv2gtk2; CarlaString bridge_lv2gtk3; @@ -257,7 +216,7 @@ struct CarlaEngineOptions { #endif CarlaEngineOptions() - : processMode(PROCESS_MODE_PATCHBAY), + : processMode(PROCESS_MODE_CONTINUOUS_RACK), processHighPrecision(false), forceStereo(false), preferPluginBridges(false), @@ -265,12 +224,57 @@ struct CarlaEngineOptions { #ifdef WANT_DSSI useDssiVstChunks(false), #endif - maxParameters(MAX_PARAMETERS), - oscUiTimeout(4000/100), + maxParameters(MAX_DEFAULT_PARAMETERS), + oscUiTimeout(4000), preferredBufferSize(512), 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); + // ------------------------------------------------------------------- // Maximum values @@ -583,7 +588,7 @@ public: * Maximum number of loadable plugins. * \note This function returns 0 if engine is not started. */ - unsigned short maxPluginNumber() const; + unsigned int maxPluginNumber() const; // ------------------------------------------------------------------- // Virtual, per-engine type calls @@ -626,8 +631,10 @@ public: * Get next available plugin id.\n * 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. */ @@ -637,6 +644,7 @@ public: * Get plugin with id \a id, faster unchecked version. */ CarlaPlugin* getPluginUnchecked(const unsigned short id) const; +#endif /*! * Get a unique plugin name within the engine.\n @@ -692,6 +700,14 @@ public: return (const char*)name; } + /*! + * Get current buffer size. + */ + uint32_t getBufferSize() const + { + return bufferSize; + } + /*! * 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 - /*! - * Get the engine options (read-only). - */ - const CarlaEngineOptions& getOptions() const - { - return options; - } - #ifndef BUILD_BRIDGE /*! * Get the engine options as process environment. @@ -842,6 +850,8 @@ public: void setOscBridgeData(const CarlaOscData* const oscData); #endif +#endif + #ifdef BUILD_BRIDGE void osc_send_peaks(CarlaPlugin* const plugin); #else diff --git a/source/backend/carla_plugin.hpp b/source/backend/carla_plugin.hpp index 58a6c7da7..ccd094211 100644 --- a/source/backend/carla_plugin.hpp +++ b/source/backend/carla_plugin.hpp @@ -93,8 +93,7 @@ enum PluginPostEventType { PluginPostEventProgramChange, // index PluginPostEventMidiProgramChange, // index PluginPostEventNoteOn, // channel, note, velo - PluginPostEventNoteOff, // channel, note - PluginPostEventCustom + PluginPostEventNoteOff // channel, note }; struct PluginAudioData { @@ -159,14 +158,12 @@ struct PluginPostEvent { int32_t value1; int32_t value2; double value3; - const void* cdata; PluginPostEvent() : type(PluginPostEventNull), value1(-1), value2(-1), - value3(0.0), - cdata(nullptr) {} + value3(0.0) {} }; struct ExternalMidiNote { @@ -180,7 +177,7 @@ struct ExternalMidiNote { velo(0) {} }; -class CarlaPluginPrivateData; +struct CarlaPluginPrivateData; /*! * \class CarlaPlugin diff --git a/source/backend/engine/carla_engine.cpp b/source/backend/engine/carla_engine.cpp index 71cd762ec..b3635eb31 100644 --- a/source/backend/engine/carla_engine.cpp +++ b/source/backend/engine/carla_engine.cpp @@ -80,7 +80,7 @@ void CarlaEngineAudioPort::initBuffer(CarlaEngine* const) CarlaEngineControlPort::CarlaEngineControlPort(const bool isInput, const ProcessMode 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)); @@ -224,7 +224,7 @@ void CarlaEngineControlPort::writeEvent(const CarlaEngineControlEventType type, CarlaEngineMidiPort::CarlaEngineMidiPort(const bool isInput, const ProcessMode 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)); @@ -416,7 +416,7 @@ void CarlaEngineClient::setLatency(const uint32_t samples) } // ------------------------------------------------------------------------------------------------------------------- -// Carla Engine Client +// Carla Engine CarlaEngine::CarlaEngine() : data(new CarlaEnginePrivateData(this)) @@ -530,7 +530,7 @@ int CarlaEngine::maxPortNameSize() return STR_MAX; } -unsigned short CarlaEngine::maxPluginNumber() const +unsigned int CarlaEngine::maxPluginNumber() const { return data->maxPluginNumber; } @@ -546,6 +546,7 @@ bool CarlaEngine::init(const char* const clientName) data->aboutToClose = false; data->maxPluginNumber = 0; + data->nextPluginId = 0; #ifndef BUILD_BRIDGE data->oscData = data->osc.getControlData(); @@ -558,6 +559,9 @@ bool CarlaEngine::init(const char* const clientName) carla_setprocname(clientName); #endif + //data->postEvents.resize(); + //data->plugins.resize(); + data->thread.startNow(); return true; @@ -586,20 +590,17 @@ bool CarlaEngine::close() // ----------------------------------------------------------------------- // Plugin management -short CarlaEngine::getNewPluginId() const +int CarlaEngine::getNewPluginId() const { qDebug("CarlaEngine::getNewPluginId()"); 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 { 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]; } +#endif 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.replace(':', '.'); // ':' is used in JACK1 to split client/port names +#if 0 for (unsigned short i=0; i < data->maxPluginNumber; i++) { // Check if unique name doesn't exist @@ -683,6 +686,7 @@ const char* CarlaEngine::getUniquePluginName(const char* const name) // Modify string if not sname += " (2)"; } +#endif return strdup(sname); } @@ -695,12 +699,24 @@ short CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, con CARLA_ASSERT(filename); CARLA_ASSERT(label); + if (QThread::currentThread() != &data->thread) + { + EnginePostEvent postEvent; + data->postEvents.append(postEvent); + return; + } + if (data->maxPluginNumber == 0) { #ifdef BUILD_BRIDGE data->maxPluginNumber = MAX_PLUGINS; // which is 1 #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 } @@ -781,8 +797,8 @@ short CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, con const short id = plugin->id(); - data->carlaPlugins[id] = plugin; - data->uniqueNames[id] = plugin->name(); + EnginePluginData pluginData(plugin); + data->plugins.append(pluginData); return id; } @@ -1170,6 +1186,8 @@ void CarlaEngine::setOscBridgeData(const CarlaOscData* const oscData) } #endif +#endif + // ----------------------------------------------------------------------- // protected calls @@ -1184,6 +1202,7 @@ void CarlaEngine::processRack(float* inBuf[2], float* outBuf[2], const uint32_t bool processed = false; +#if 0 // process plugins 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; } +#endif // if no plugins in the rack, copy inputs over outputs if (! processed) @@ -1298,11 +1318,13 @@ void CarlaEngine::bufferSizeChanged(const uint32_t newBufferSize) { qDebug("CarlaEngine::bufferSizeChanged(%i)", newBufferSize); +#if 0 for (unsigned short i=0; i < data->maxPluginNumber; i++) { if (data->carlaPlugins[i] && data->carlaPlugins[i]->enabled() /*&& ! data->carlaPlugins[i]->data->processHighPrecision*/) data->carlaPlugins[i]->bufferSizeChanged(newBufferSize); } +#endif } 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); CARLA_ASSERT(data->oscData); - CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber); + CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber); CARLA_ASSERT(pluginName); 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); 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) { @@ -1380,7 +1402,7 @@ void CarlaEngine::osc_send_control_remove_plugin(const int32_t pluginId) { qDebug("CarlaEngine::osc_send_control_remove_plugin(%i)", pluginId); 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) { @@ -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); 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); 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); 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) { @@ -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); 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(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); 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(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); CARLA_ASSERT(data->oscData); - CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber); + CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber); CARLA_ASSERT(index >= 0); 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); 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(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); #endif 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) { @@ -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); CARLA_ASSERT(data->oscData); - CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber); + CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber); CARLA_ASSERT(index >= 0); 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); 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) { @@ -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); CARLA_ASSERT(data->oscData); - CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber); + CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber); CARLA_ASSERT(count >= 0); 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); 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(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); 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) { @@ -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); CARLA_ASSERT(data->oscData); - CARLA_ASSERT(pluginId >= 0 && pluginId < data->maxPluginNumber); + CARLA_ASSERT(pluginId >= 0 && pluginId < (int32_t)data->maxPluginNumber); CARLA_ASSERT(count >= 0); 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); 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(bank >= 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); 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(note >= 0 && note < 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); 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(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) { //qDebug("CarlaEngine::osc_send_control_set_input_peak_value(%i, %i)", pluginId, portId); 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); 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); 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); 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]); } } +#endif void CarlaEngine::osc_send_control_exit() { diff --git a/source/backend/engine/carla_engine.pro b/source/backend/engine/carla_engine.pro index 43cd806d0..b0d9ece0b 100644 --- a/source/backend/engine/carla_engine.pro +++ b/source/backend/engine/carla_engine.pro @@ -31,8 +31,8 @@ VERSION = 0.5.0 SOURCES = \ carla_engine.cpp \ - carla_engine_osc.cpp \ - carla_engine_thread.cpp \ +# carla_engine_osc.cpp \ +# carla_engine_thread.cpp \ jack.cpp \ plugin.cpp \ rtaudio.cpp diff --git a/source/backend/engine/carla_engine_internal.hpp b/source/backend/engine/carla_engine_internal.hpp index 38446a3ab..d54d621f0 100644 --- a/source/backend/engine/carla_engine_internal.hpp +++ b/source/backend/engine/carla_engine_internal.hpp @@ -1,6 +1,6 @@ /* * Carla Engine - * Copyright (C) 2013 Filipe Coelho + * Copyright (C) 2012-2013 Filipe Coelho * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -9,7 +9,7 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the COPYING file @@ -24,6 +24,8 @@ #include "carla_plugin.hpp" +#include "rt_list.hpp" + #ifndef BUILD_BRIDGE # include #endif @@ -104,6 +106,37 @@ const char* CarlaEngineControlEventType2Str(const CarlaEngineControlEventType ty const uint32_t PATCHBAY_BUFFER_SIZE = 128; 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 { CarlaEngineOsc osc; CarlaEngineThread thread; @@ -112,24 +145,25 @@ struct CarlaEnginePrivateData { CallbackFunc callback; void* callbackPtr; + CarlaString lastError; #ifndef BUILD_BRIDGE QProcessEnvironment procEnv; #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 postEvents; + RtList plugins; bool aboutToClose; - unsigned short maxPluginNumber; + unsigned int maxPluginNumber; + unsigned int nextPluginId; CarlaEnginePrivateData(CarlaEngine* const engine) : osc(engine), @@ -137,12 +171,11 @@ struct CarlaEnginePrivateData { oscData(nullptr), callback(nullptr), callbackPtr(nullptr), - carlaPlugins{nullptr}, - uniqueNames{nullptr}, - insPeak{0.0}, - outsPeak{0.0}, + postEvents(1, 1), + plugins(1, 1), aboutToClose(false), - maxPluginNumber(0) {} + maxPluginNumber(0), + nextPluginId(0) {} }; CARLA_BACKEND_END_NAMESPACE diff --git a/source/backend/engine/carla_engine_osc.hpp b/source/backend/engine/carla_engine_osc.hpp index 16d9812e9..66ed63520 100644 --- a/source/backend/engine/carla_engine_osc.hpp +++ b/source/backend/engine/carla_engine_osc.hpp @@ -1,6 +1,6 @@ /* * Carla Engine OSC - * Copyright (C) 2012 Filipe Coelho + * Copyright (C) 2012-2013 Filipe Coelho * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -9,14 +9,14 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the COPYING file */ -#ifndef CARLA_ENGINE_OSC_HPP -#define CARLA_ENGINE_OSC_HPP +#ifndef __CARLA_ENGINE_OSC_HPP__ +#define __CARLA_ENGINE_OSC_HPP__ #include "carla_backend.hpp" #include "carla_osc_utils.hpp" @@ -166,4 +166,4 @@ private: CARLA_BACKEND_END_NAMESPACE -#endif // CARLA_ENGINE_OSC_HPP +#endif // __CARLA_ENGINE_OSC_HPP__ diff --git a/source/backend/engine/carla_engine_thread.hpp b/source/backend/engine/carla_engine_thread.hpp index baceca5fa..b5a8625b0 100644 --- a/source/backend/engine/carla_engine_thread.hpp +++ b/source/backend/engine/carla_engine_thread.hpp @@ -1,6 +1,6 @@ /* * Carla Engine Thread - * Copyright (C) 2012 Filipe Coelho + * Copyright (C) 2012-2013 Filipe Coelho * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -9,18 +9,18 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the COPYING file */ -#ifndef CARLA_ENGINE_THREAD_HPP -#define CARLA_ENGINE_THREAD_HPP +#ifndef __CARLA_ENGINE_THREAD_HPP__ +#define __CARLA_ENGINE_THREAD_HPP__ #include "carla_backend.hpp" +#include "carla_utils.hpp" -#include #include CARLA_BACKEND_START_NAMESPACE @@ -48,11 +48,12 @@ protected: private: CarlaEngine* const engine; - QMutex m_mutex; - bool m_stopNow; + CarlaMutex m_mutex; + bool m_stopNow; // ---------------------------------------------- +#if 0 class ScopedLocker { public: @@ -68,10 +69,11 @@ private: } private: - QMutex* const mutex; + CarlaMutex* const mutex; }; +#endif }; CARLA_BACKEND_END_NAMESPACE -#endif // CARLA_ENGINE_THREAD_HPP +#endif // __CARLA_ENGINE_THREAD_HPP__ diff --git a/source/backend/engine/jack.cpp b/source/backend/engine/jack.cpp index 0e99590f4..db79f5248 100644 --- a/source/backend/engine/jack.cpp +++ b/source/backend/engine/jack.cpp @@ -65,7 +65,7 @@ public: if (! m_port) 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 @@ -118,7 +118,7 @@ public: if (! m_port) return CarlaEngineControlPort::initBuffer(engine); - buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize()); + //buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize()); if (! isInput) jackbridge_midi_clear_buffer(buffer); @@ -317,7 +317,7 @@ public: if (! m_port) return CarlaEngineMidiPort::initBuffer(engine); - buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize()); + //buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize()); if (! isInput) jackbridge_midi_clear_buffer(buffer); @@ -515,9 +515,7 @@ public: CarlaEngineJack() : CarlaEngine() #ifndef BUILD_BRIDGE -# ifdef Q_COMPILER_INITIALIZER_LISTS , m_rackPorts{nullptr} -# endif #endif { qDebug("CarlaEngineJack::CarlaEngineJack()"); @@ -530,11 +528,6 @@ public: #ifdef BUILD_BRIDGE hasQuit = false; -#else -# ifndef Q_COMPILER_INITIALIZER_LISTS - for (int i=0; i < rackPortCount; i++) - m_rackPorts[i] = nullptr; -# endif #endif } @@ -741,6 +734,8 @@ public: #endif } +#if 0 + // ------------------------------------- protected: @@ -1025,6 +1020,7 @@ protected: } // ------------------------------------- +#endif private: jack_client_t* m_client; @@ -1052,6 +1048,7 @@ private: jack_port_t* m_rackPorts[rackPortCount]; #endif +#if 0 // ------------------------------------- static void processPlugin(CarlaPlugin* const p, const uint32_t nframes) @@ -1192,6 +1189,7 @@ private: if (plugin && plugin->enabled()) latencyPlugin(plugin, mode); } +#endif }; // ----------------------------------------- diff --git a/source/backend/engine/rtaudio.cpp b/source/backend/engine/rtaudio.cpp index 2670a06ba..8588a975c 100644 --- a/source/backend/engine/rtaudio.cpp +++ b/source/backend/engine/rtaudio.cpp @@ -65,6 +65,8 @@ public: // ------------------------------------------------------------------------------------------------------------------- // RtAudio Engine +#if 0 + class CarlaEngineRtAudio : public CarlaEngine { public: @@ -433,6 +435,7 @@ const char* CarlaEngine::getRtAudioApiName(unsigned int index) return nullptr; } +#endif CARLA_BACKEND_END_NAMESPACE diff --git a/source/discovery/carla-discovery.cpp b/source/discovery/carla-discovery.cpp index 91ff96c4a..e07f7e25f 100644 --- a/source/discovery/carla-discovery.cpp +++ b/source/discovery/carla-discovery.cpp @@ -221,7 +221,7 @@ intptr_t VSTCALLBACK vstHostCallback(AEffect* const effect, const int32_t opcode case audioMasterGetVendorString: if (ptr) { - strcpy((char*)ptr, "Cadence"); + strcpy((char*)ptr, "falkTX"); ret = 1; } break; @@ -274,7 +274,25 @@ void do_ladspa_check(void* const libHandle, const bool init) 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 audioIns = 0; @@ -284,6 +302,9 @@ void do_ladspa_check(void* const libHandle, const bool init) int parametersOuts = 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++) { const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j]; @@ -294,14 +315,16 @@ void do_ladspa_check(void* const libHandle, const bool init) audioIns += 1; else if (LADSPA_IS_PORT_OUTPUT(portDescriptor)) audioOuts += 1; + audioTotal += 1; } else if (LADSPA_IS_PORT_CONTROL(portDescriptor)) { if (LADSPA_IS_PORT_INPUT(portDescriptor)) 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; + parametersTotal += 1; } } @@ -323,81 +346,79 @@ void do_ladspa_check(void* const libHandle, const bool init) LADSPA_Data bufferParams[parametersTotal]; 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); descriptor->connect_port(handle, j, bufferAudio[iA++]); } - else if (LADSPA_IS_PORT_CONTROL(portType)) + else if (LADSPA_IS_PORT_CONTROL(portDescriptor)) { // 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 min = 0.0f; // 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 max = 1.0f; 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; } // 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; max *= 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 - min = 0.0f; - max = sampleRate; 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) descriptor->activate(handle); - if (descriptor->run) - descriptor->run(handle, bufferSize); + descriptor->run(handle, bufferSize); if (descriptor->deactivate) descriptor->deactivate(handle); - if (descriptor->cleanup) - descriptor->cleanup(handle); + descriptor->cleanup(handle); // 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("maker", descriptor->Maker); DISCOVERY_OUT("copyright", descriptor->Copyright); - DISCOVERY_OUT("unique_id", descriptor->UniqueID); + DISCOVERY_OUT("uniqueId", descriptor->UniqueID); DISCOVERY_OUT("hints", hints); DISCOVERY_OUT("audio.ins", audioIns); DISCOVERY_OUT("audio.outs", audioOuts); @@ -443,8 +464,31 @@ void do_dssi_check(void* const libHandle, const bool init) while ((descriptor = descFn(i++))) { 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 audioIns = 0; @@ -457,6 +501,9 @@ void do_dssi_check(void* const libHandle, const bool init) int parametersTotal = 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++) { const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j]; @@ -467,14 +514,16 @@ void do_dssi_check(void* const libHandle, const bool init) audioIns += 1; else if (LADSPA_IS_PORT_OUTPUT(portDescriptor)) audioOuts += 1; + audioTotal += 1; } else if (LADSPA_IS_PORT_CONTROL(portDescriptor)) { if (LADSPA_IS_PORT_INPUT(portDescriptor)) 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; + parametersTotal += 1; } } @@ -482,7 +531,7 @@ void do_dssi_check(void* const libHandle, const bool init) if (descriptor->run_synth || descriptor->run_multiple_synths) midiIns = midiTotal = 1; - if (midiIns > 0 && audioOuts > 0) + if (midiIns > 0 && audioIns == 0 && audioOuts > 0) hints |= PLUGIN_IS_SYNTH; if (init) @@ -498,10 +547,9 @@ void do_dssi_check(void* const libHandle, const bool init) continue; } - // we can only get program info per-handle if (descriptor->get_program && descriptor->select_program) { - while ((descriptor->get_program(handle, programsTotal++))) + while (descriptor->get_program(handle, programsTotal++)) continue; } @@ -509,77 +557,74 @@ void do_dssi_check(void* const libHandle, const bool init) LADSPA_Data bufferParams[parametersTotal]; 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); ldescriptor->connect_port(handle, j, bufferAudio[iA++]); } - else if (LADSPA_IS_PORT_CONTROL(portType)) + else if (LADSPA_IS_PORT_CONTROL(portDescriptor)) { // 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 min = 0.0f; // 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 max = 1.0f; 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; } // 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; max *= 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 - min = 0.0f; - max = sampleRate; 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 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); } @@ -612,14 +657,13 @@ void do_dssi_check(void* const libHandle, const bool init) else descriptor->run_synth(handle, bufferSize, midiEvents, midiEventCount); } - else if (ldescriptor->run) + else ldescriptor->run(handle, bufferSize); if (ldescriptor->deactivate) ldescriptor->deactivate(handle); - if (ldescriptor->cleanup) - ldescriptor->cleanup(handle); + ldescriptor->cleanup(handle); // 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::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 @@ -689,80 +735,69 @@ void do_lv2_check(const char* const bundle, const bool 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); if (! libHandle) { + isLoadable = false; print_lib_error(rdfDescriptor->Binary); delete rdfDescriptor; - continue; + break; } 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; @@ -777,6 +812,14 @@ void do_lv2_check(const char* const bundle, const bool init) int parametersTotal = 0; 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++) { 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; else if (LV2_IS_PORT_OUTPUT(rdfPort->Types)) audioOuts += 1; + audioTotal += 1; } 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; else if (LV2_IS_PORT_OUTPUT(rdfPort->Types)) parametersOuts += 1; + parametersTotal += 1; } } @@ -822,6 +867,7 @@ void do_lv2_check(const char* const bundle, const bool init) midiIns += 1; else if (LV2_IS_PORT_OUTPUT(rdfPort->Types)) midiOuts += 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"); if (! vstFn) + { 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); @@ -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); - if (vstCategory == kPlugCategShell) + if (vstCategory == kPlugCategShell && effect->uniqueID == 0) { if ((vstCurrentUniqueId = effect->dispatcher(effect, effShellGetNextPlugin, 0, 0, strBuf, 0.0f)) != 0) cName = strBuf; @@ -1409,6 +1457,25 @@ int main(int argc, char* argv[]) if (doInit && getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS")) 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) { case PLUGIN_LADSPA: @@ -1436,7 +1503,7 @@ int main(int argc, char* argv[]) break; } - if (openLib) + if (openLib && handle) lib_close(handle); return 0; diff --git a/source/includes/carla_defines.hpp b/source/includes/carla_defines.hpp index 6bb0a9d21..34ce5e829 100644 --- a/source/includes/carla_defines.hpp +++ b/source/includes/carla_defines.hpp @@ -9,7 +9,7 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the COPYING file @@ -81,9 +81,11 @@ #ifdef NDEBUG # 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_INT2(cond, v1, v2) ((!(cond)) ? carla_assert_int2(#cond, __FILE__, __LINE__, v1, v2) : qt_noop()) #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_INT2(cond, v1, v2) Q_ASSERT(cond) #endif // Define CARLA_EXPORT diff --git a/source/utils/carla_backend_utils.hpp b/source/utils/carla_backend_utils.hpp index d78b3a845..379878ab0 100644 --- a/source/utils/carla_backend_utils.hpp +++ b/source/utils/carla_backend_utils.hpp @@ -1,5 +1,5 @@ /* - * Carla Backend + * Carla Backend utils * Copyright (C) 2011-2012 Filipe Coelho * * 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, * 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. * * 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_utils.hpp" CARLA_BACKEND_START_NAMESPACE -/*! - * @defgroup CarlaBackendUtils Carla Backend Utils - * - * Carla Backend Utils - * - * @{ - */ - -// ------------------------------------------------------------------------------------------------------------------- +// ------------------------------------------------- static inline const char* BinaryType2Str(const BinaryType& type) @@ -156,41 +148,14 @@ const char* InternalParametersIndex2Str(const InternalParametersIndex& index) return "PARAMETER_BALANCE_LEFT"; case PARAMETER_BALANCE_RIGHT: return "PARAMETER_BALANCE_RIGHT"; + case PARAMETER_PANNING: + return "PARAMETER_PANNING"; } qWarning("CarlaBackend::InternalParametersIndex2Str(%i) - invalid index", index); 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 const char* OptionsType2Str(const OptionsType& type) { @@ -202,24 +167,25 @@ const char* OptionsType2Str(const OptionsType& type) return "OPTION_PROCESS_MODE"; case OPTION_PROCESS_HIGH_PRECISION: return "OPTION_PROCESS_HIGH_PRECISION"; - case OPTION_MAX_PARAMETERS: - return "OPTION_MAX_PARAMETERS"; - case OPTION_PREFERRED_BUFFER_SIZE: - return "OPTION_PREFERRED_BUFFER_SIZE"; - case OPTION_PREFERRED_SAMPLE_RATE: - return "OPTION_PREFERRED_SAMPLE_RATE"; case OPTION_FORCE_STEREO: return "OPTION_FORCE_STEREO"; -#ifdef WANT_DSSI - case OPTION_USE_DSSI_VST_CHUNKS: - return "OPTION_USE_DSSI_VST_CHUNKS"; -#endif case OPTION_PREFER_PLUGIN_BRIDGES: return "OPTION_PREFER_PLUGIN_BRIDGES"; case 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: 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: return "OPTION_PATH_BRIDGE_NATIVE"; case OPTION_PATH_BRIDGE_POSIX32: @@ -230,6 +196,7 @@ const char* OptionsType2Str(const OptionsType& type) return "OPTION_PATH_BRIDGE_WIN32"; case OPTION_PATH_BRIDGE_WIN64: return "OPTION_PATH_BRIDGE_WIN64"; +#endif #ifdef WANT_LV2 case 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"; case CALLBACK_SHOW_GUI: return "CALLBACK_SHOW_GUI"; - case CALLBACK_RESIZE_GUI: - return "CALLBACK_RESIZE_GUI"; case CALLBACK_UPDATE: return "CALLBACK_UPDATE"; case CALLBACK_RELOAD_INFO: @@ -332,7 +297,28 @@ const char* ProcessMode2Str(const ProcessMode& mode) 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 const char* getPluginTypeString(const PluginType& type) @@ -343,8 +329,10 @@ const char* getPluginTypeString(const PluginType& type) { case PLUGIN_NONE: return "NONE"; +#ifndef BUILD_BRIDGE case PLUGIN_INTERNAL: return "INTERNAL"; +#endif case PLUGIN_LADSPA: return "LADSPA"; case PLUGIN_DSSI: @@ -353,39 +341,20 @@ const char* getPluginTypeString(const PluginType& type) return "LV2"; case PLUGIN_VST: return "VST"; +#ifndef BUILD_BRIDGE case PLUGIN_GIG: return "GIG"; case PLUGIN_SF2: return "SF2"; case PLUGIN_SFZ: return "SFZ"; +#endif } return "NONE"; } -// ------------------------------------------------------------------------------------------------------------------- - -static inline -uintptr_t getAddressFromPointer(void* const ptr) -{ - qDebug("CarlaBackend::getAddressFromPointer(%p)", ptr); - CARLA_ASSERT(ptr != nullptr); - - uintptr_t* addr = (uintptr_t*)&ptr; - return *addr; -} - -static inline -void* getPointerFromAddress(const uintptr_t& addr) -{ - CARLA_ASSERT(addr != 0); - - uintptr_t** const ptr = (uintptr_t**)&addr; - return *ptr; -} - -// ------------------------------------------------------------------------------------------------------------------- +// ------------------------------------------------- static inline PluginCategory getPluginCategoryFromName(const char* const name) @@ -466,8 +435,6 @@ PluginCategory getPluginCategoryFromName(const char* const name) return PLUGIN_CATEGORY_NONE; } -/**@}*/ - CARLA_BACKEND_END_NAMESPACE -#endif // CARLA_BACKEND_UTILS_HPP +#endif // __CARLA_BACKEND_UTILS_HPP__ diff --git a/source/utils/carla_lv2_utils.hpp b/source/utils/carla_lv2_utils.hpp index 0d8465c77..391e1194a 100644 --- a/source/utils/carla_lv2_utils.hpp +++ b/source/utils/carla_lv2_utils.hpp @@ -1124,10 +1124,30 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri) 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 -// TODO - review these static inline bool is_lv2_feature_supported(const LV2_URI uri) { @@ -1137,6 +1157,12 @@ bool is_lv2_feature_supported(const LV2_URI uri) return true; if (strcmp(uri, LV2_CORE__isLive) == 0) 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) return true; 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 -// TODO - review these static inline bool is_lv2_ui_feature_supported(const LV2_URI uri) { diff --git a/source/utils/carla_utils.hpp b/source/utils/carla_utils.hpp index 774184213..855bf45c2 100644 --- a/source/utils/carla_utils.hpp +++ b/source/utils/carla_utils.hpp @@ -9,7 +9,7 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the COPYING file @@ -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); } +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 void carla_sleep(const unsigned int secs) diff --git a/source/utils/rt_list.hpp b/source/utils/rt_list.hpp index 9f903c8ea..652209785 100644 --- a/source/utils/rt_list.hpp +++ b/source/utils/rt_list.hpp @@ -36,7 +36,7 @@ public: qcount = 0; 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); } @@ -53,7 +53,7 @@ public: clear(); 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); } @@ -62,12 +62,12 @@ public: { if (! isEmpty()) { - ListHeadData* data; + RtListData* data; k_list_head* entry; list_for_each(entry, &queue) { - data = list_entry(entry, ListHeadData, siblings); + data = list_entry(entry, RtListData, siblings); rtsafe_memory_pool_deallocate(mempool, data); } } @@ -83,17 +83,18 @@ public: 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) { - ListHeadData* data; + RtListData* data; if (sleepy) - data = (ListHeadData*)rtsafe_memory_pool_allocate_sleepy(mempool); + data = (RtListData*)rtsafe_memory_pool_allocate_sleepy(mempool); else - data = (ListHeadData*)rtsafe_memory_pool_allocate_atomic(mempool); + data = (RtListData*)rtsafe_memory_pool_allocate_atomic(mempool); if (data) { @@ -126,12 +127,12 @@ public: bool removeOne(const T& value) { - ListHeadData* data; + RtListData* data; k_list_head* entry; list_for_each(entry, &queue) { - data = list_entry(entry, ListHeadData, siblings); + data = list_entry(entry, RtListData, siblings); if (data->value == value) { @@ -147,13 +148,13 @@ public: void removeAll(const T& value) { - ListHeadData* data; + RtListData* data; k_list_head* entry; k_list_head* tmp; list_for_each_safe(entry, tmp, &queue) { - data = list_entry(entry, ListHeadData, siblings); + data = list_entry(entry, RtListData, siblings); if (data->value == value) { @@ -169,7 +170,7 @@ private: k_list_head queue; RtMemPool_Handle mempool; - struct ListHeadData { + struct RtListData { T value; k_list_head siblings; }; @@ -192,7 +193,7 @@ private: } 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;