| @@ -516,10 +516,11 @@ enum CallbackType { | |||
| * | |||
| * \see OPTION_PROCESS_MODE | |||
| */ | |||
| enum ProcessModeType { | |||
| enum ProcessMode { | |||
| PROCESS_MODE_SINGLE_CLIENT = 0, //!< Single client mode (dynamic input/outputs as needed by plugins) | |||
| PROCESS_MODE_MULTIPLE_CLIENTS = 1, //!< Multiple client mode (1 master client + 1 client per plugin) | |||
| PROCESS_MODE_CONTINUOUS_RACK = 2 //!< Single client, "rack" mode. Processes plugins in order of id, with forced stereo. | |||
| PROCESS_MODE_CONTINUOUS_RACK = 2, //!< Single client, "rack" mode. Processes plugins in order of id, with forced stereo. | |||
| PROCESS_MODE_PATCHBAY = 3 //!< Single client, "patchbay" mode. | |||
| }; | |||
| /*! | |||
| @@ -323,9 +323,9 @@ const char* CallbackType2Str(const CallbackType& type) | |||
| } | |||
| static inline | |||
| const char* ProcessModeType2Str(const ProcessModeType& type) | |||
| const char* ProcessMode2Str(const ProcessMode& mode) | |||
| { | |||
| switch (type) | |||
| switch (mode) | |||
| { | |||
| case PROCESS_MODE_SINGLE_CLIENT: | |||
| return "PROCESS_MODE_SINGLE_CLIENT"; | |||
| @@ -333,9 +333,11 @@ const char* ProcessModeType2Str(const ProcessModeType& type) | |||
| return "PROCESS_MODE_MULTIPLE_CLIENTS"; | |||
| case PROCESS_MODE_CONTINUOUS_RACK: | |||
| return "PROCESS_MODE_CONTINUOUS_RACK"; | |||
| case PROCESS_MODE_PATCHBAY: | |||
| return "PROCESS_MODE_PATCHBAY"; | |||
| } | |||
| qWarning("CarlaBackend::ProcessModeType2Str(%i) - invalid type", type); | |||
| qWarning("CarlaBackend::ProcessModeType2Str(%i) - invalid type", mode); | |||
| return nullptr; | |||
| } | |||
| @@ -414,16 +416,6 @@ const char* getPluginTypeString(const PluginType& type) | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| static inline | |||
| void* getPointerFromAddress(const uintptr_t& addr) | |||
| { | |||
| qDebug("CarlaBackend::getPointerFromAddress(" P_UINTPTR ")", addr); | |||
| CARLA_ASSERT(addr != 0); | |||
| uintptr_t** const ptr = (uintptr_t**)&addr; | |||
| return *ptr; | |||
| } | |||
| static inline | |||
| uintptr_t getAddressFromPointer(void* const ptr) | |||
| { | |||
| @@ -434,6 +426,16 @@ uintptr_t getAddressFromPointer(void* const ptr) | |||
| return *addr; | |||
| } | |||
| static inline | |||
| void* getPointerFromAddress(const uintptr_t& addr) | |||
| { | |||
| qDebug("CarlaBackend::getPointerFromAddress(" P_UINTPTR ")", addr); | |||
| CARLA_ASSERT(addr != 0); | |||
| uintptr_t** const ptr = (uintptr_t**)&addr; | |||
| return *ptr; | |||
| } | |||
| static inline | |||
| PluginCategory getPluginCategoryFromName(const char* const name) | |||
| { | |||
| @@ -443,7 +445,7 @@ PluginCategory getPluginCategoryFromName(const char* const name) | |||
| if (! name) | |||
| return PLUGIN_CATEGORY_NONE; | |||
| carla_string sname(name); | |||
| CarlaString sname(name); | |||
| if (sname.isEmpty()) | |||
| return PLUGIN_CATEGORY_NONE; | |||
| @@ -241,7 +241,7 @@ EXPAND_ONLY_PREDEF = NO | |||
| SEARCH_INCLUDES = YES | |||
| INCLUDE_PATH = | |||
| INCLUDE_FILE_PATTERNS = | |||
| PREDEFINED = DOXYGEN | |||
| PREDEFINED = DOXYGEN CARLA_ENGINE_JACK CARLA_ENGINE_RTAUDIO | |||
| EXPAND_AS_DEFINED = | |||
| SKIP_FUNCTION_MACROS = YES | |||
| #--------------------------------------------------------------------------- | |||
| @@ -21,15 +21,6 @@ | |||
| #include "carla_engine_osc.hpp" | |||
| #include "carla_engine_thread.hpp" | |||
| //#ifdef CARLA_ENGINE_JACK | |||
| //typedef struct _jack_client jack_client_t; | |||
| //typedef struct _jack_port jack_port_t; | |||
| //#endif | |||
| #ifdef CARLA_ENGINE_RTAUDIO | |||
| typedef int RtAudioApi; | |||
| #endif | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| /*! | |||
| @@ -48,28 +39,99 @@ CARLA_BACKEND_START_NAMESPACE | |||
| const uint32_t CarlaEngineTimeBBT = 0x1; | |||
| /**@}*/ | |||
| /*! | |||
| * The type of an engine. | |||
| */ | |||
| enum CarlaEngineType { | |||
| CarlaEngineTypeNull, | |||
| CarlaEngineTypeJack, | |||
| CarlaEngineTypeRtAudio, | |||
| CarlaEngineTypePlugin | |||
| /*! | |||
| * Null engine type. | |||
| */ | |||
| CarlaEngineTypeNull = 0, | |||
| /*! | |||
| * Jack engine type.\n | |||
| * Provides single, multi-client, and rack processing modes. | |||
| */ | |||
| CarlaEngineTypeJack = 1, | |||
| /*! | |||
| * RtAudio engine type, used to provide ALSA, PulseAudio, DirectSound, ASIO and CoreAudio/Midi support.\n | |||
| * Provides rack mode processing only. | |||
| */ | |||
| CarlaEngineTypeRtAudio = 2, | |||
| /*! | |||
| * Plugin engine type, used to export the engine as a plugin (DSSI, LV2 and VST) via the DISTRHO Plugin Toolkit.\n | |||
| * Works in rack mode only. | |||
| */ | |||
| CarlaEngineTypePlugin = 3 | |||
| }; | |||
| /*! | |||
| * The type of an engine port. | |||
| */ | |||
| enum CarlaEnginePortType { | |||
| CarlaEnginePortTypeAudio, | |||
| CarlaEnginePortTypeControl, | |||
| CarlaEnginePortTypeMIDI | |||
| /*! | |||
| * Null engine port type. | |||
| */ | |||
| CarlaEnginePortTypeNull = 0, | |||
| /*! | |||
| * Audio port. | |||
| */ | |||
| CarlaEnginePortTypeAudio = 1, | |||
| /*! | |||
| * Control port.\n | |||
| * These are MIDI ports on some engine types, by handling MIDI-CC as control. | |||
| */ | |||
| CarlaEnginePortTypeControl = 2, | |||
| /*! | |||
| * MIDI port. | |||
| */ | |||
| CarlaEnginePortTypeMIDI = 3 | |||
| }; | |||
| /*! | |||
| * The type of a control event. | |||
| */ | |||
| enum CarlaEngineControlEventType { | |||
| CarlaEngineEventNull = 0, | |||
| CarlaEngineEventControlChange, | |||
| CarlaEngineEventMidiBankChange, | |||
| CarlaEngineEventMidiProgramChange, | |||
| CarlaEngineEventAllSoundOff, | |||
| CarlaEngineEventAllNotesOff | |||
| /*! | |||
| * Null event type. | |||
| */ | |||
| CarlaEngineNullEvent = 0, | |||
| /*! | |||
| * Parameter change event.\n | |||
| * \note Value uses a range of 0.0<->1.0. | |||
| */ | |||
| CarlaEngineParameterChangeEvent = 1, | |||
| /*! | |||
| * MIDI Bank change event. | |||
| */ | |||
| CarlaEngineMidiBankChangeEvent = 2, | |||
| /*! | |||
| * MIDI Program change event. | |||
| */ | |||
| CarlaEngineMidiProgramChangeEvent = 3, | |||
| /*! | |||
| * All sound off event. | |||
| */ | |||
| CarlaEngineAllSoundOffEvent = 4, | |||
| /*! | |||
| * All notes off event. | |||
| */ | |||
| CarlaEngineAllNotesOffEvent = 5 | |||
| }; | |||
| /*! | |||
| * Engine control event. | |||
| */ | |||
| struct CarlaEngineControlEvent { | |||
| CarlaEngineControlEventType type; | |||
| uint32_t time; | |||
| @@ -78,29 +140,35 @@ struct CarlaEngineControlEvent { | |||
| double value; | |||
| CarlaEngineControlEvent() | |||
| : type(CarlaEngineEventNull), | |||
| : type(CarlaEngineNullEvent), | |||
| time(0), | |||
| channel(0), | |||
| controller(0), | |||
| value(0.0) {} | |||
| }; | |||
| /*! | |||
| * Engine MIDI event. | |||
| */ | |||
| struct CarlaEngineMidiEvent { | |||
| uint32_t time; | |||
| uint8_t size; | |||
| uint8_t data[4]; | |||
| uint8_t data[3]; | |||
| CarlaEngineMidiEvent() | |||
| : time(0), | |||
| #ifdef Q_COMPILER_INITIALIZER_LISTS | |||
| #ifdef Q_COMPILER_INITIALIZER_LISTS | |||
| size(0), | |||
| data{0} {} | |||
| #else | |||
| size(0) { data[0] = data[1] = data[2] = data[3] = 0; } | |||
| #endif | |||
| #else | |||
| size(0) { data[0] = data[1] = data[2] = 0; } | |||
| #endif | |||
| }; | |||
| struct CarlaTimeInfoBBT { | |||
| /*! | |||
| * Engine BBT Time information. | |||
| */ | |||
| struct CarlaEngineTimeInfoBBT { | |||
| int32_t bar; | |||
| int32_t beat; | |||
| int32_t tick; | |||
| @@ -110,7 +178,7 @@ struct CarlaTimeInfoBBT { | |||
| double ticks_per_beat; | |||
| double beats_per_minute; | |||
| CarlaTimeInfoBBT() | |||
| CarlaEngineTimeInfoBBT() | |||
| : bar(0), | |||
| beat(0), | |||
| tick(0), | |||
| @@ -121,26 +189,29 @@ struct CarlaTimeInfoBBT { | |||
| beats_per_minute(0.0) {} | |||
| }; | |||
| struct CarlaTimeInfo { | |||
| /*! | |||
| * Engine Time information. | |||
| */ | |||
| struct CarlaEngineTimeInfo { | |||
| bool playing; | |||
| uint32_t frame; | |||
| uint32_t time; | |||
| uint32_t valid; | |||
| CarlaTimeInfoBBT bbt; | |||
| CarlaEngineTimeInfoBBT bbt; | |||
| CarlaTimeInfo() | |||
| CarlaEngineTimeInfo() | |||
| : playing(false), | |||
| frame(0), | |||
| time(0), | |||
| valid(0) {} | |||
| }; | |||
| struct CarlaEngineClientNativeHandle; | |||
| struct CarlaEnginePortNativeHandle; | |||
| #ifndef BUILD_BRIDGE | |||
| // Global options | |||
| /*! | |||
| * Engine options. | |||
| */ | |||
| struct CarlaEngineOptions { | |||
| ProcessMode processMode; | |||
| bool processHighPrecision; | |||
| uint maxParameters; | |||
| @@ -154,19 +225,20 @@ struct CarlaEngineOptions { | |||
| bool preferUiBridges; | |||
| uint oscUiTimeout; | |||
| const char* bridge_posix32; | |||
| const char* bridge_posix64; | |||
| const char* bridge_win32; | |||
| const char* bridge_win64; | |||
| const char* bridge_lv2gtk2; | |||
| const char* bridge_lv2gtk3; | |||
| const char* bridge_lv2qt4; | |||
| const char* bridge_lv2x11; | |||
| const char* bridge_vsthwnd; | |||
| const char* bridge_vstx11; | |||
| CarlaString bridge_posix32; | |||
| CarlaString bridge_posix64; | |||
| CarlaString bridge_win32; | |||
| CarlaString bridge_win64; | |||
| CarlaString bridge_lv2gtk2; | |||
| CarlaString bridge_lv2gtk3; | |||
| CarlaString bridge_lv2qt4; | |||
| CarlaString bridge_lv2x11; | |||
| CarlaString bridge_vsthwnd; | |||
| CarlaString bridge_vstx11; | |||
| CarlaEngineOptions() | |||
| : processHighPrecision(false), | |||
| : processMode(PROCESS_MODE_CONTINUOUS_RACK), | |||
| processHighPrecision(false), | |||
| maxParameters(MAX_PARAMETERS), | |||
| preferredBufferSize(512), | |||
| preferredSampleRate(44100), | |||
| @@ -174,71 +246,344 @@ struct CarlaEngineOptions { | |||
| useDssiVstChunks(false), | |||
| preferPluginBridges(false), | |||
| preferUiBridges(true), | |||
| oscUiTimeout(4000/100), | |||
| bridge_posix32(nullptr), | |||
| bridge_posix64(nullptr), | |||
| bridge_win32(nullptr), | |||
| bridge_win64(nullptr), | |||
| bridge_lv2gtk2(nullptr), | |||
| bridge_lv2gtk3(nullptr), | |||
| bridge_lv2qt4(nullptr), | |||
| bridge_lv2x11(nullptr), | |||
| bridge_vsthwnd(nullptr), | |||
| bridge_vstx11(nullptr) {} | |||
| oscUiTimeout(4000/100) {} | |||
| // void reset() | |||
| // { | |||
| // processMode = PROCESS_MODE_CONTINUOUS_RACK; | |||
| // processHighPrecision = false; | |||
| // maxParameters = MAX_PARAMETERS; | |||
| // preferredBufferSize = 512; | |||
| // preferredSampleRate = 44100; | |||
| // forceStereo = false; | |||
| // useDssiVstChunks = false; | |||
| // preferPluginBridges = false; | |||
| // preferUiBridges = true; | |||
| // oscUiTimeout = 4000/100; | |||
| // bridge_posix32.clear(); | |||
| // bridge_posix64.clear(); | |||
| // bridge_win32.clear(); | |||
| // bridge_win64.clear(); | |||
| // bridge_lv2gtk2.clear(); | |||
| // bridge_lv2gtk3.clear(); | |||
| // bridge_lv2qt4.clear(); | |||
| // bridge_lv2x11.clear(); | |||
| // bridge_vsthwnd.clear(); | |||
| // bridge_vstx11.clear(); | |||
| // } | |||
| }; | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| class CarlaEngineClient; | |||
| class CarlaEngineBasePort; | |||
| /*! | |||
| * Engine port (Base).\n | |||
| * This is the base class for all Carla engine ports. | |||
| */ | |||
| class CarlaEngineBasePort | |||
| { | |||
| public: | |||
| /*! | |||
| * The contructor.\n | |||
| * Param \a isInput defines wherever this is an input port or not (output otherwise).\n | |||
| * Input/output state is constant for the lifetime of the port. | |||
| */ | |||
| CarlaEngineBasePort(const bool isInput, const ProcessMode processMode); | |||
| /*! | |||
| * The decontructor. | |||
| */ | |||
| virtual ~CarlaEngineBasePort(); | |||
| /*! | |||
| * Get the type of the port, as provided by the respective subclasses. | |||
| */ | |||
| virtual CarlaEnginePortType type() = 0; | |||
| /*! | |||
| * Initialize the port's internal buffer for \a engine. | |||
| */ | |||
| virtual void initBuffer(CarlaEngine* const engine) = 0; | |||
| protected: | |||
| const bool isInput; | |||
| const ProcessMode processMode; | |||
| void* buffer; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| /*! | |||
| * \class CarlaEngine | |||
| * | |||
| * \brief Carla Backend base engine class | |||
| * | |||
| * This is the base class for all available engine types available in Carla Backend. | |||
| * Engine port (Audio). | |||
| */ | |||
| class CarlaEngineAudioPort : public CarlaEngineBasePort | |||
| { | |||
| public: | |||
| /*! | |||
| * The contructor.\n | |||
| * Param \a isInput defines wherever this is an input port or not (output otherwise).\n | |||
| * Input/output state is constant for the lifetime of the port. | |||
| */ | |||
| CarlaEngineAudioPort(const bool isInput, const ProcessMode processMode); | |||
| /*! | |||
| * The decontructor. | |||
| */ | |||
| virtual ~CarlaEngineAudioPort(); | |||
| /*! | |||
| * Get the type of the port, in this case CarlaEnginePortTypeAudio. | |||
| */ | |||
| CarlaEnginePortType type() | |||
| { | |||
| return CarlaEnginePortTypeAudio; | |||
| } | |||
| /*! | |||
| * Initialize the port's internal buffer for \a engine. | |||
| */ | |||
| virtual void initBuffer(CarlaEngine* const engine); | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| /*! | |||
| * Engine port (Control). | |||
| */ | |||
| class CarlaEngineControlPort : public CarlaEngineBasePort | |||
| { | |||
| public: | |||
| /*! | |||
| * The contructor.\n | |||
| * Param \a isInput defines wherever this is an input port or not (output otherwise).\n | |||
| * Input/output state is constant for the lifetime of the port. | |||
| */ | |||
| CarlaEngineControlPort(const bool isInput, const ProcessMode processMode); | |||
| /*! | |||
| * The decontructor. | |||
| */ | |||
| virtual ~CarlaEngineControlPort(); | |||
| /*! | |||
| * Get the type of the port, in this case CarlaEnginePortTypeControl. | |||
| */ | |||
| CarlaEnginePortType type() | |||
| { | |||
| return CarlaEnginePortTypeControl; | |||
| } | |||
| /*! | |||
| * Initialize the port's internal buffer for \a engine. | |||
| */ | |||
| virtual void initBuffer(CarlaEngine* const engine); | |||
| /*! | |||
| * Get the number of control events present in the buffer. | |||
| * \note You must only call this for input ports. | |||
| */ | |||
| virtual uint32_t getEventCount(); | |||
| /*! | |||
| * Get the control event at \a index. | |||
| ** \note You must only call this for input ports. | |||
| */ | |||
| virtual const CarlaEngineControlEvent* getEvent(uint32_t index); | |||
| /*! | |||
| * Write a control event to the buffer.\n | |||
| * Arguments are the same as in the CarlaEngineControlEvent struct. | |||
| ** \note You must only call this for output ports. | |||
| */ | |||
| virtual void writeEvent(CarlaEngineControlEventType type, uint32_t time, uint8_t channel, uint16_t controller, double value); | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| /*! | |||
| * Engine port (MIDI). | |||
| */ | |||
| class CarlaEngineMidiPort : public CarlaEngineBasePort | |||
| { | |||
| public: | |||
| /*! | |||
| * The contructor.\n | |||
| * Param \a isInput defines wherever this is an input port or not (output otherwise).\n | |||
| * Input/output state is constant for the lifetime of the port. | |||
| */ | |||
| CarlaEngineMidiPort(const bool isInput, const ProcessMode processMode); | |||
| /*! | |||
| * The decontructor. | |||
| */ | |||
| virtual ~CarlaEngineMidiPort(); | |||
| /*! | |||
| * Get the type of the port, in this case CarlaEnginePortTypeMIDI. | |||
| */ | |||
| CarlaEnginePortType type() | |||
| { | |||
| return CarlaEnginePortTypeMIDI; | |||
| } | |||
| /*! | |||
| * Initialize the port's internal buffer for \a engine. | |||
| */ | |||
| virtual void initBuffer(CarlaEngine* const engine); | |||
| /*! | |||
| * Get the number of MIDI events present in the buffer. | |||
| * \note You must only call this for input ports. | |||
| */ | |||
| virtual uint32_t getEventCount(); | |||
| /*! | |||
| * Get the MIDI event at \a index. | |||
| ** \note You must only call this for input ports. | |||
| */ | |||
| virtual const CarlaEngineMidiEvent* getEvent(uint32_t index); | |||
| /*! | |||
| * Write a MIDI event to the buffer.\n | |||
| * Arguments are the same as in the CarlaEngineMidiEvent struct. | |||
| ** \note You must only call this for output ports. | |||
| */ | |||
| virtual void writeEvent(uint32_t time, const uint8_t* data, uint8_t size); | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| /*! | |||
| * Engine client.\n | |||
| * Each plugin requires one client from the engine (created via CarlaEngine::addPort()).\n | |||
| * \note This is a virtual class, each engine type provides its own funtionality. | |||
| */ | |||
| class CarlaEngineClient | |||
| { | |||
| public: | |||
| /*! | |||
| * The contructor.\n | |||
| * All constructor parameters are constant and will never change in the lifetime of the client.\n | |||
| * Client starts in deactivated state. | |||
| */ | |||
| CarlaEngineClient(const CarlaEngineType engineType, const ProcessMode processMode); | |||
| /*! | |||
| * The decontructor. | |||
| */ | |||
| virtual ~CarlaEngineClient(); | |||
| /*! | |||
| * Activate this client.\n | |||
| * \note Client must be deactivated before calling this function. | |||
| */ | |||
| virtual void activate(); | |||
| /*! | |||
| * Deactivate this client.\n | |||
| * \note Client must be activated before calling this function. | |||
| */ | |||
| virtual void deactivate(); | |||
| /*! | |||
| * Check if the client is activated. | |||
| */ | |||
| virtual bool isActive() const; | |||
| /*! | |||
| * Check if the client is ok.\n | |||
| * Plugins will refuse to instantiate if this returns false. | |||
| * \note This is always true in rack and patchbay processing modes. | |||
| */ | |||
| virtual bool isOk() const; | |||
| /*! | |||
| * Get the current latency, in samples. | |||
| */ | |||
| virtual uint32_t getLatency() const; | |||
| /*! | |||
| * Change the client's latency. | |||
| */ | |||
| virtual void setLatency(const uint32_t samples); | |||
| /*! | |||
| * Add a new port of type \a portType. | |||
| * \note This function does nothing in rack processing mode since its ports are static (2 audio, 1 midi and 1 control for both input and output). | |||
| */ | |||
| virtual const CarlaEngineBasePort* addPort(const CarlaEnginePortType portType, const char* const name, const bool isInput) = 0; | |||
| protected: | |||
| const CarlaEngineType engineType; | |||
| const ProcessMode processMode; | |||
| private: | |||
| bool m_active; | |||
| uint32_t m_latency; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| /*! | |||
| * Carla Engine. | |||
| * \note This is a virtual class for all available engine types available in Carla. | |||
| */ | |||
| class CarlaEngine | |||
| { | |||
| public: | |||
| /*! | |||
| * The contructor.\n | |||
| * \note This only initializes engine data, it doesn't initialize the engine itself. | |||
| */ | |||
| CarlaEngine(); | |||
| /*! | |||
| * The decontructor. | |||
| * The engine must have been closed before this happens. | |||
| */ | |||
| virtual ~CarlaEngine(); | |||
| // ------------------------------------------------------------------- | |||
| // Static values | |||
| /*! | |||
| * Maximum number of peaks per plugin.\n | |||
| * \note There are both input and output peaks. | |||
| */ | |||
| static const unsigned short MAX_PEAKS = 2; | |||
| static int maxClientNameSize(); | |||
| static int maxPortNameSize(); | |||
| static unsigned short maxPluginNumber(); | |||
| static const char* getFixedClientName(const char* const clientName); | |||
| /*! | |||
| * Get the number of available engine drivers. | |||
| */ | |||
| static unsigned int getDriverCount(); | |||
| static const char* getDriverName(unsigned int index); | |||
| static CarlaEngine* newDriverByName(const char* driverName); | |||
| #ifndef BUILD_BRIDGE | |||
| // ------------------------------------------------------------------- | |||
| // Global options | |||
| /*! | |||
| * Get the name of the engine driver at \a index. | |||
| */ | |||
| static const char* getDriverName(unsigned int index); | |||
| CarlaEngineOptions options; | |||
| static ProcessModeType processMode; | |||
| /*! | |||
| * Create a new engine, using driver \a driverName. | |||
| */ | |||
| static CarlaEngine* newDriverByName(const char* const driverName); | |||
| void setOption(const OptionsType option, const int value, const char* const valueStr); | |||
| void resetOptions(); | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| // Maximum values | |||
| virtual int maxClientNameSize(); | |||
| virtual int maxPortNameSize(); | |||
| unsigned short maxPluginNumber(); | |||
| // ------------------------------------------------------------------- | |||
| // Virtual, per-engine type calls | |||
| virtual bool init(const char* const clientName); | |||
| virtual bool close(); | |||
| virtual bool isOffline() = 0; | |||
| virtual bool isRunning() = 0; | |||
| virtual bool isOffline() const = 0; | |||
| virtual bool isRunning() const = 0; | |||
| virtual CarlaEngineType type() const = 0; | |||
| virtual CarlaEngineClient* addClient(CarlaPlugin* const plugin) = 0; | |||
| // ------------------------------------------------------------------- | |||
| @@ -267,11 +612,10 @@ public: | |||
| // ------------------------------------------------------------------- | |||
| // Information (base) | |||
| CarlaEngineType getType() const; | |||
| const char* getName() const; | |||
| double getSampleRate() const; | |||
| uint32_t getBufferSize() const; | |||
| const CarlaTimeInfo* getTimeInfo() const; | |||
| const CarlaEngineTimeInfo* getTimeInfo() const; | |||
| // ------------------------------------------------------------------- | |||
| // Information (audio peaks) | |||
| @@ -293,6 +637,18 @@ public: | |||
| const char* getLastError() const; | |||
| void setLastError(const char* const error); | |||
| #ifndef BUILD_BRIDGE | |||
| // ------------------------------------------------------------------- | |||
| // Options | |||
| void setOption(const OptionsType option, const int value, const char* const valueStr); | |||
| ProcessMode processMode() const | |||
| { | |||
| return options.processMode; | |||
| } | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| // Mutex locks | |||
| @@ -333,8 +689,8 @@ public: | |||
| void osc_send_bridge_set_midi_program(const int32_t index); | |||
| void osc_send_bridge_set_custom_data(const char* const stype, const char* const key, const char* const value); | |||
| void osc_send_bridge_set_chunk_data(const char* const chunkFile); | |||
| void osc_send_bridge_set_inpeak(const int32_t portId, const double value); | |||
| void osc_send_bridge_set_outpeak(const int32_t portId, const double value); | |||
| void osc_send_bridge_set_inpeak(const int32_t portId); | |||
| void osc_send_bridge_set_outpeak(const int32_t portId); | |||
| #else | |||
| void osc_send_control_add_plugin_start(const int32_t pluginId, const char* const pluginName); | |||
| void osc_send_control_add_plugin_end(const int32_t pluginId); | |||
| @@ -355,8 +711,8 @@ public: | |||
| void osc_send_control_set_midi_program_data(const int32_t pluginId, const int32_t index, const int32_t bank, const int32_t program, const char* const name); | |||
| void osc_send_control_note_on(const int32_t pluginId, const int32_t channel, const int32_t note, const int32_t velo); | |||
| void osc_send_control_note_off(const int32_t pluginId, const int32_t channel, const int32_t note); | |||
| void osc_send_control_set_input_peak_value(const int32_t pluginId, const int32_t portId, const double value); | |||
| void osc_send_control_set_output_peak_value(const int32_t pluginId, const int32_t portId, const double value); | |||
| void osc_send_control_set_input_peak_value(const int32_t pluginId, const int32_t portId); | |||
| void osc_send_control_set_output_peak_value(const int32_t pluginId, const int32_t portId); | |||
| void osc_send_control_exit(); | |||
| #endif | |||
| @@ -392,35 +748,35 @@ public: | |||
| * \param lock Wherever to lock the engine or not, true by default | |||
| */ | |||
| ScopedLocker(CarlaEngine* const engine, bool lock = true) | |||
| : m_engine(engine), | |||
| : mutex(&engine->m_procLock), | |||
| m_lock(lock) | |||
| { | |||
| if (m_lock) | |||
| m_engine->processLock(); | |||
| mutex->lock(); | |||
| } | |||
| ~ScopedLocker() | |||
| { | |||
| if (m_lock) | |||
| m_engine->processUnlock(); | |||
| mutex->unlock(); | |||
| } | |||
| private: | |||
| CarlaEngine* const m_engine; | |||
| QMutex* const mutex; | |||
| const bool m_lock; | |||
| }; | |||
| // ------------------------------------- | |||
| protected: | |||
| CarlaEngineType type; | |||
| const char* name; | |||
| CarlaEngineOptions options; | |||
| CarlaString name; | |||
| uint32_t bufferSize; | |||
| double sampleRate; | |||
| CarlaTimeInfo timeInfo; | |||
| CarlaEngineTimeInfo timeInfo; | |||
| void bufferSizeChanged(const uint32_t newBufferSize); | |||
| void startCheckThread(); | |||
| private: | |||
| CarlaEngineThread m_thread; | |||
| @@ -433,7 +789,7 @@ private: | |||
| CallbackFunc m_callback; | |||
| void* m_callbackPtr; | |||
| carla_string m_lastError; | |||
| CarlaString m_lastError; | |||
| QMutex m_procLock; | |||
| QMutex m_midiLock; | |||
| @@ -444,104 +800,29 @@ private: | |||
| double m_insPeak[MAX_PLUGINS * MAX_PEAKS]; | |||
| double m_outsPeak[MAX_PLUGINS * MAX_PEAKS]; | |||
| static unsigned short m_maxPluginNumber; | |||
| unsigned short m_maxPluginNumber; | |||
| #ifdef CARLA_ENGINE_JACK | |||
| static CarlaEngine* newJack(); | |||
| #endif | |||
| #ifdef CARLA_ENGINE_RTAUDIO | |||
| static CarlaEngine* newRtAudio(RtAudioApi api); | |||
| #endif | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| class CarlaEngineClient | |||
| { | |||
| public: | |||
| CarlaEngineClient(const CarlaEngineClientNativeHandle* handle); | |||
| ~CarlaEngineClient(); | |||
| void activate(); | |||
| void deactivate(); | |||
| bool isActive() const; | |||
| bool isOk() const; | |||
| uint32_t getLatency() const; | |||
| void setLatency(const uint32_t samples); | |||
| const CarlaEngineBasePort* addPort(const CarlaEnginePortType portType, const char* const name, const bool isInput); | |||
| private: | |||
| bool m_active; | |||
| uint32_t m_latency; | |||
| const CarlaEngineClientNativeHandle* handle; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| // base | |||
| class CarlaEngineBasePort | |||
| { | |||
| public: | |||
| CarlaEngineBasePort(const CarlaEnginePortNativeHandle* handle, const bool isInput); | |||
| virtual ~CarlaEngineBasePort(); | |||
| virtual void initBuffer(CarlaEngine* const engine) = 0; | |||
| const CarlaEnginePortNativeHandle* getHandle() const | |||
| { | |||
| return handle; | |||
| } | |||
| protected: | |||
| void* buffer; | |||
| const bool isInput; | |||
| const CarlaEnginePortNativeHandle* handle; | |||
| }; | |||
| // audio | |||
| class CarlaEngineAudioPort : public CarlaEngineBasePort | |||
| { | |||
| public: | |||
| CarlaEngineAudioPort(const CarlaEnginePortNativeHandle* handle, const bool isInput); | |||
| void initBuffer(CarlaEngine* const engine); | |||
| enum RtAudioApi { | |||
| RTAUDIO_DUMMY = 0, | |||
| RTAUDIO_LINUX_ALSA = 1, | |||
| RTAUDIO_LINUX_PULSE = 2, | |||
| RTAUDIO_LINUX_OSS = 3, | |||
| RTAUDIO_UNIX_JACK = 4, | |||
| RTAUDIO_MACOSX_CORE = 5, | |||
| RTAUDIO_WINDOWS_ASIO = 6, | |||
| RTAUDIO_WINDOWS_DS = 7 | |||
| }; | |||
| #ifdef CARLA_ENGINE_JACK | |||
| float* getJackAudioBuffer(uint32_t nframes); | |||
| static CarlaEngine* newRtAudio(RtAudioApi api); | |||
| static unsigned int getRtAudioApiCount(); | |||
| static const char* getRtAudioApiName(unsigned int index); | |||
| #endif | |||
| }; | |||
| // control | |||
| class CarlaEngineControlPort : public CarlaEngineBasePort | |||
| { | |||
| public: | |||
| CarlaEngineControlPort(const CarlaEnginePortNativeHandle* handle, const bool isInput); | |||
| void initBuffer(CarlaEngine* const engine); | |||
| uint32_t getEventCount(); | |||
| const CarlaEngineControlEvent* getEvent(uint32_t index); | |||
| void writeEvent(CarlaEngineControlEventType type, uint32_t time, uint8_t channel, uint8_t controller, double value); | |||
| }; | |||
| // midi | |||
| class CarlaEngineMidiPort : public CarlaEngineBasePort | |||
| { | |||
| public: | |||
| CarlaEngineMidiPort(const CarlaEnginePortNativeHandle* handle, const bool isInput); | |||
| void initBuffer(CarlaEngine* const engine); | |||
| uint32_t getEventCount(); | |||
| const CarlaEngineMidiEvent* getEvent(uint32_t index); | |||
| void writeEvent(uint32_t time, const uint8_t* data, uint8_t size); | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| /**@}*/ | |||
| @@ -26,7 +26,8 @@ SOURCES = \ | |||
| carla_engine_osc.cpp \ | |||
| carla_engine_thread.cpp \ | |||
| jack.cpp \ | |||
| rtaudio.cpp | |||
| rtaudio.cpp \ | |||
| plugin.cpp | |||
| HEADERS = \ | |||
| carla_engine.hpp \ | |||
| @@ -48,4 +49,7 @@ INCLUDEPATH += rtmidi-2.0.1 | |||
| SOURCES += rtaudio-4.0.11/RtAudio.cpp | |||
| SOURCES += rtmidi-2.0.1/RtMidi.cpp | |||
| # Plugin | |||
| INCLUDEPATH += distrho-plugin-toolkit | |||
| QMAKE_CXXFLAGS *= -std=c++0x | |||
| @@ -1,5 +1,5 @@ | |||
| /* | |||
| * Carla Engine | |||
| * Carla Engine OSC | |||
| * Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| @@ -40,8 +40,6 @@ CarlaEngineOsc::CarlaEngineOsc(CarlaEngine* const engine_) | |||
| m_serverTCP = nullptr; | |||
| m_serverUDP = nullptr; | |||
| m_serverPathTCP = nullptr; | |||
| m_serverPathUDP = nullptr; | |||
| m_controlData.path = nullptr; | |||
| m_controlData.source = nullptr; | |||
| m_controlData.target = nullptr; | |||
| @@ -60,28 +58,30 @@ void CarlaEngineOsc::init(const char* const name) | |||
| qDebug("CarlaEngineOsc::init(\"%s\")", name); | |||
| CARLA_ASSERT(! m_serverTCP); | |||
| CARLA_ASSERT(! m_serverUDP); | |||
| CARLA_ASSERT(! m_serverPathTCP); | |||
| CARLA_ASSERT(! m_serverPathUDP); | |||
| CARLA_ASSERT(name); | |||
| CARLA_ASSERT(m_serverPathTCP.isEmpty()); | |||
| CARLA_ASSERT(m_serverPathUDP.isEmpty()); | |||
| CARLA_ASSERT(m_nameSize == 0); | |||
| CARLA_ASSERT(name); | |||
| m_name = strdup(name ? name : ""); | |||
| m_nameSize = strlen(m_name); | |||
| // create new OSC thread | |||
| // create new OSC severs | |||
| m_serverTCP = lo_server_new_with_proto(nullptr, LO_TCP, osc_error_handlerTCP); | |||
| m_serverUDP = lo_server_new_with_proto(nullptr, LO_UDP, osc_error_handlerUDP); | |||
| // get our full OSC server path | |||
| // get our full OSC servers path | |||
| char* const serverPathTCP = lo_server_get_url(m_serverTCP); | |||
| m_serverPathTCP = strdup(QString("%1%2").arg(serverPathTCP).arg(m_name).toUtf8().constData()); | |||
| m_serverPathTCP = serverPathTCP; | |||
| m_serverPathTCP += m_name; | |||
| free(serverPathTCP); | |||
| char* const serverPathUDP = lo_server_get_url(m_serverUDP); | |||
| m_serverPathUDP = strdup(QString("%1%2").arg(serverPathUDP).arg(m_name).toUtf8().constData()); | |||
| m_serverPathUDP = serverPathUDP; | |||
| m_serverPathUDP += m_name; | |||
| free(serverPathUDP); | |||
| // register message handler and start OSC thread | |||
| // register message handler | |||
| lo_server_add_method(m_serverTCP, nullptr, nullptr, osc_message_handler, this); | |||
| lo_server_add_method(m_serverUDP, nullptr, nullptr, osc_message_handler, this); | |||
| } | |||
| @@ -110,8 +110,8 @@ void CarlaEngineOsc::close() | |||
| qDebug("CarlaEngineOsc::close()"); | |||
| CARLA_ASSERT(m_serverTCP); | |||
| CARLA_ASSERT(m_serverUDP); | |||
| CARLA_ASSERT(m_serverPathTCP); | |||
| CARLA_ASSERT(m_serverPathUDP); | |||
| CARLA_ASSERT(m_serverPathTCP.isNotEmpty()); | |||
| CARLA_ASSERT(m_serverPathUDP.isNotEmpty()); | |||
| CARLA_ASSERT(m_name); | |||
| m_controlData.free(); | |||
| @@ -121,13 +121,10 @@ void CarlaEngineOsc::close() | |||
| lo_server_thread_free(m_serverTCP); | |||
| lo_server_thread_free(m_serverUDP); | |||
| free((void*)m_serverPathTCP); | |||
| free((void*)m_serverPathUDP); | |||
| m_serverTCP = nullptr; | |||
| m_serverUDP = nullptr; | |||
| m_serverPathTCP = nullptr; | |||
| m_serverPathUDP = nullptr; | |||
| m_serverPathTCP.clear(); | |||
| m_serverPathUDP.clear(); | |||
| free(m_name); | |||
| m_name = nullptr; | |||
| @@ -143,7 +140,8 @@ int CarlaEngineOsc::handleMessage(const char* const path, const int argc, const | |||
| qDebug("CarlaEngineOsc::handleMessage(%s, %i, %p, %s, %p)", path, argc, argv, types, msg); | |||
| #endif | |||
| CARLA_ASSERT(m_serverTCP || m_serverUDP); | |||
| CARLA_ASSERT(m_serverPathTCP || m_serverPathUDP); | |||
| CARLA_ASSERT(m_serverPathTCP.isNotEmpty() || m_serverPathUDP.isNotEmpty()); | |||
| CARLA_ASSERT(m_name); | |||
| CARLA_ASSERT(path); | |||
| if (! path) | |||
| @@ -176,7 +174,7 @@ int CarlaEngineOsc::handleMessage(const char* const path, const int argc, const | |||
| if (std::isdigit(path[m_nameSize+3])) | |||
| pluginId += (path[m_nameSize+3]-'0')*10; | |||
| if (pluginId < 0 || pluginId > CarlaEngine::maxPluginNumber()) | |||
| if (pluginId < 0 || pluginId > engine->maxPluginNumber()) | |||
| { | |||
| qCritical("CarlaEngineOsc::handleMessage() - failed to get plugin, wrong id '%i'", pluginId); | |||
| return 1; | |||
| @@ -334,8 +332,7 @@ int CarlaEngineOsc::handleMsgRegister(const int argc, const lo_arg* const* const | |||
| free((void*)host); | |||
| free((void*)port); | |||
| // FIXME - max plugins | |||
| for (unsigned short i=0; i < CarlaEngine::maxPluginNumber(); i++) | |||
| for (unsigned short i=0; i < engine->maxPluginNumber(); i++) | |||
| { | |||
| CarlaPlugin* const plugin = engine->getPluginUnchecked(i); | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Engine | |||
| * Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com> | |||
| * Carla Engine OSC | |||
| * Copyright (C) 2012 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| @@ -22,7 +22,7 @@ | |||
| #include "carla_osc_utils.hpp" | |||
| #define CARLA_ENGINE_OSC_HANDLE_ARGS1 CarlaPlugin* const plugin | |||
| #define CARLA_ENGINE_OSC_HANDLE_ARGS2 CARLA_ENGINE_OSC_HANDLE_ARGS1, const int argc, const lo_arg* const* const argv, const char* const types | |||
| #define CARLA_ENGINE_OSC_HANDLE_ARGS2 CarlaPlugin* const plugin, const int argc, const lo_arg* const* const argv, const char* const types | |||
| #define CARLA_ENGINE_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ | |||
| /* check argument count */ \ | |||
| @@ -91,8 +91,8 @@ private: | |||
| lo_server m_serverTCP; | |||
| lo_server m_serverUDP; | |||
| const char* m_serverPathTCP; | |||
| const char* m_serverPathUDP; | |||
| CarlaString m_serverPathTCP; | |||
| CarlaString m_serverPathUDP; | |||
| CarlaOscData m_controlData; // for carla-control | |||
| char* m_name; | |||
| @@ -1,5 +1,5 @@ | |||
| /* | |||
| * Carla Engine | |||
| * Carla Engine Thread | |||
| * Copyright (C) 2012 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| @@ -80,7 +80,7 @@ void CarlaEngineThread::run() | |||
| const ScopedLocker m(this); | |||
| oscControlRegisted = engine->isOscControlRegisted(); | |||
| for (unsigned short i=0, max = CarlaEngine::maxPluginNumber(); i < max; i++) | |||
| for (unsigned short i=0; i < engine->maxPluginNumber(); i++) | |||
| { | |||
| CarlaPlugin* const plugin = engine->getPluginUnchecked(i); | |||
| @@ -124,7 +124,7 @@ void CarlaEngineThread::run() | |||
| } | |||
| // ------------------------------------------------------- | |||
| // Update OSC control client | |||
| // Update OSC control client (peaks) | |||
| if (oscControlRegisted) | |||
| { | |||
| @@ -132,21 +132,21 @@ void CarlaEngineThread::run() | |||
| if (plugin->audioInCount() > 0) | |||
| { | |||
| #ifdef BUILD_BRIDGE | |||
| engine->osc_send_bridge_set_inpeak(1, engine->getInputPeak(id, 0)); | |||
| engine->osc_send_bridge_set_inpeak(2, engine->getInputPeak(id, 1)); | |||
| engine->osc_send_bridge_set_inpeak(1); | |||
| engine->osc_send_bridge_set_inpeak(2); | |||
| #else | |||
| engine->osc_send_control_set_input_peak_value(id, 1, engine->getInputPeak(id, 0)); | |||
| engine->osc_send_control_set_input_peak_value(id, 2, engine->getInputPeak(id, 1)); | |||
| engine->osc_send_control_set_input_peak_value(id, 1); | |||
| engine->osc_send_control_set_input_peak_value(id, 2); | |||
| #endif | |||
| } | |||
| if (plugin->audioOutCount() > 0) | |||
| { | |||
| #ifdef BUILD_BRIDGE | |||
| engine->osc_send_bridge_set_outpeak(1, engine->getOutputPeak(id, 0)); | |||
| engine->osc_send_bridge_set_outpeak(2, engine->getOutputPeak(id, 1)); | |||
| engine->osc_send_bridge_set_outpeak(1); | |||
| engine->osc_send_bridge_set_outpeak(2); | |||
| #else | |||
| engine->osc_send_control_set_output_peak_value(id, 1, engine->getOutputPeak(id, 0)); | |||
| engine->osc_send_control_set_output_peak_value(id, 2, engine->getOutputPeak(id, 1)); | |||
| engine->osc_send_control_set_output_peak_value(id, 1); | |||
| engine->osc_send_control_set_output_peak_value(id, 2); | |||
| #endif | |||
| } | |||
| } | |||
| @@ -154,7 +154,7 @@ void CarlaEngineThread::run() | |||
| } | |||
| if (! engine->idleOsc()) | |||
| QThread::msleep(50); | |||
| msleep(50); | |||
| } | |||
| } | |||
| @@ -1,5 +1,5 @@ | |||
| /* | |||
| * Carla Engine | |||
| * Carla Engine Thread | |||
| * Copyright (C) 2012 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| @@ -36,9 +36,13 @@ public: | |||
| void startNow(); | |||
| void stopNow(); | |||
| // ---------------------------------------------- | |||
| protected: | |||
| void run(); | |||
| // ---------------------------------------------- | |||
| private: | |||
| CarlaEngine* const engine; | |||
| @@ -24,37 +24,385 @@ | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| struct CarlaEngineClientNativeHandle { | |||
| CarlaEngineType type; | |||
| #ifdef CARLA_ENGINE_JACK | |||
| jack_client_t* jackClient; | |||
| #endif | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Engine port (JackAudio) | |||
| CarlaEngineClientNativeHandle() | |||
| class CarlaEngineJackAudioPort : public CarlaEngineAudioPort | |||
| { | |||
| public: | |||
| CarlaEngineJackAudioPort(const bool isInput, const ProcessMode processMode, jack_client_t* const client_, jack_port_t* const port_) | |||
| : CarlaEngineAudioPort(isInput, processMode), | |||
| client(client_), | |||
| port(port_) | |||
| { | |||
| type = CarlaEngineTypeNull; | |||
| #ifdef CARLA_ENGINE_JACK | |||
| jackClient = nullptr; | |||
| #endif | |||
| if (processMode == PROCESS_MODE_CONTINUOUS_RACK || processMode == PROCESS_MODE_PATCHBAY) | |||
| CARLA_ASSERT(! port); | |||
| } | |||
| ~CarlaEngineJackAudioPort() | |||
| { | |||
| if (client && port) | |||
| jackbridge_port_unregister(client, port); | |||
| } | |||
| void initBuffer(CarlaEngine* const engine) | |||
| { | |||
| if (! port) | |||
| return CarlaEngineAudioPort::initBuffer(engine); | |||
| buffer = jackbridge_port_get_buffer(port, engine->getBufferSize()); | |||
| } | |||
| private: | |||
| jack_client_t* const client; | |||
| jack_port_t* const port; | |||
| friend class CarlaEngineJack; | |||
| }; | |||
| struct CarlaEnginePortNativeHandle { | |||
| #ifdef CARLA_ENGINE_JACK | |||
| jack_client_t* jackClient; | |||
| jack_port_t* jackPort; | |||
| #endif | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Engine port (JackControl) | |||
| CarlaEnginePortNativeHandle() | |||
| class CarlaEngineJackControlPort : public CarlaEngineControlPort | |||
| { | |||
| public: | |||
| CarlaEngineJackControlPort(const bool isInput, const ProcessMode processMode, jack_client_t* const client_, jack_port_t* const port_) | |||
| : CarlaEngineControlPort(isInput, processMode), | |||
| client(client_), | |||
| port(port_) | |||
| { | |||
| #ifdef CARLA_ENGINE_JACK | |||
| jackClient = nullptr; | |||
| jackPort = nullptr; | |||
| #endif | |||
| if (processMode == PROCESS_MODE_CONTINUOUS_RACK || processMode == PROCESS_MODE_PATCHBAY) | |||
| CARLA_ASSERT(! port); | |||
| } | |||
| ~CarlaEngineJackControlPort() | |||
| { | |||
| if (client && port) | |||
| jackbridge_port_unregister(client, port); | |||
| } | |||
| void initBuffer(CarlaEngine* const engine) | |||
| { | |||
| if (! port) | |||
| return CarlaEngineControlPort::initBuffer(engine); | |||
| buffer = jackbridge_port_get_buffer(port, engine->getBufferSize()); | |||
| if (! isInput) | |||
| jackbridge_midi_clear_buffer(buffer); | |||
| } | |||
| uint32_t getEventCount() | |||
| { | |||
| if (! port) | |||
| return CarlaEngineControlPort::getEventCount(); | |||
| if (! isInput) | |||
| return 0; | |||
| return jackbridge_midi_get_event_count(buffer); | |||
| } | |||
| const CarlaEngineControlEvent* getEvent(uint32_t index) | |||
| { | |||
| if (! port) | |||
| return CarlaEngineControlPort::getEvent(index); | |||
| if (! isInput) | |||
| return nullptr; | |||
| static jack_midi_event_t jackEvent; | |||
| static CarlaEngineControlEvent carlaEvent; | |||
| if (jackbridge_midi_event_get(&jackEvent, buffer, index) != 0) | |||
| return nullptr; | |||
| memset(&carlaEvent, 0, sizeof(CarlaEngineControlEvent)); | |||
| uint8_t midiStatus = jackEvent.buffer[0]; | |||
| uint8_t midiChannel = midiStatus & 0x0F; | |||
| carlaEvent.time = jackEvent.time; | |||
| carlaEvent.channel = midiChannel; | |||
| if (MIDI_IS_STATUS_CONTROL_CHANGE(midiStatus)) | |||
| { | |||
| uint8_t midiControl = jackEvent.buffer[1]; | |||
| if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) | |||
| { | |||
| uint8_t midiBank = jackEvent.buffer[2]; | |||
| carlaEvent.type = CarlaEngineMidiBankChangeEvent; | |||
| carlaEvent.value = midiBank; | |||
| } | |||
| else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) | |||
| { | |||
| carlaEvent.type = CarlaEngineAllSoundOffEvent; | |||
| } | |||
| else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) | |||
| { | |||
| carlaEvent.type = CarlaEngineAllNotesOffEvent; | |||
| } | |||
| else | |||
| { | |||
| uint8_t midiValue = jackEvent.buffer[2]; | |||
| carlaEvent.type = CarlaEngineParameterChangeEvent; | |||
| carlaEvent.controller = midiControl; | |||
| carlaEvent.value = double(midiValue)/127; | |||
| } | |||
| return &carlaEvent; | |||
| } | |||
| if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus)) | |||
| { | |||
| uint8_t midiProgram = jackEvent.buffer[1]; | |||
| carlaEvent.type = CarlaEngineMidiProgramChangeEvent; | |||
| carlaEvent.value = midiProgram; | |||
| return &carlaEvent; | |||
| } | |||
| return nullptr; | |||
| } | |||
| void writeEvent(CarlaEngineControlEventType type, uint32_t time, uint8_t channel, uint16_t controller, double value) | |||
| { | |||
| if (! port) | |||
| return CarlaEngineControlPort::writeEvent(type, time, channel, controller, value); | |||
| if (isInput) | |||
| return; | |||
| if (type == CarlaEngineParameterChangeEvent && MIDI_IS_CONTROL_BANK_SELECT(controller)) | |||
| type = CarlaEngineMidiBankChangeEvent; | |||
| uint8_t data[3] = { 0 }; | |||
| switch (type) | |||
| { | |||
| case CarlaEngineNullEvent: | |||
| break; | |||
| case CarlaEngineParameterChangeEvent: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
| data[1] = controller; | |||
| data[2] = value * 127; | |||
| jackbridge_midi_event_write(buffer, time, data, 3); | |||
| break; | |||
| case CarlaEngineMidiBankChangeEvent: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
| data[1] = MIDI_CONTROL_BANK_SELECT; | |||
| data[2] = value; | |||
| jackbridge_midi_event_write(buffer, time, data, 3); | |||
| break; | |||
| case CarlaEngineMidiProgramChangeEvent: | |||
| data[0] = MIDI_STATUS_PROGRAM_CHANGE + channel; | |||
| data[1] = value; | |||
| jackbridge_midi_event_write(buffer, time, data, 2); | |||
| break; | |||
| case CarlaEngineAllSoundOffEvent: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
| data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
| jackbridge_midi_event_write(buffer, time, data, 2); | |||
| break; | |||
| case CarlaEngineAllNotesOffEvent: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
| data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
| jackbridge_midi_event_write(buffer, time, data, 2); | |||
| break; | |||
| } | |||
| } | |||
| private: | |||
| jack_client_t* const client; | |||
| jack_port_t* const port; | |||
| }; | |||
| // ----------------------------------------- | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Engine port (JackMIDI) | |||
| class CarlaEngineJackMidiPort : public CarlaEngineMidiPort | |||
| { | |||
| public: | |||
| CarlaEngineJackMidiPort(const bool isInput, const ProcessMode processMode, jack_client_t* const client_, jack_port_t* const port_) | |||
| : CarlaEngineMidiPort(isInput, processMode), | |||
| client(client_), | |||
| port(port_) | |||
| { | |||
| if (processMode == PROCESS_MODE_CONTINUOUS_RACK || processMode == PROCESS_MODE_PATCHBAY) | |||
| CARLA_ASSERT(! port); | |||
| } | |||
| ~CarlaEngineJackMidiPort() | |||
| { | |||
| if (client && port) | |||
| jackbridge_port_unregister(client, port); | |||
| } | |||
| void initBuffer(CarlaEngine* const engine) | |||
| { | |||
| if (! port) | |||
| return CarlaEngineMidiPort::initBuffer(engine); | |||
| buffer = jackbridge_port_get_buffer(port, engine->getBufferSize()); | |||
| if (! isInput) | |||
| jackbridge_midi_clear_buffer(buffer); | |||
| } | |||
| uint32_t getEventCount() | |||
| { | |||
| if (! port) | |||
| return CarlaEngineMidiPort::getEventCount(); | |||
| if (! isInput) | |||
| return 0; | |||
| return jackbridge_midi_get_event_count(buffer); | |||
| } | |||
| const CarlaEngineMidiEvent* getEvent(uint32_t index) | |||
| { | |||
| if (! port) | |||
| return CarlaEngineMidiPort::getEvent(index); | |||
| if (! isInput) | |||
| return nullptr; | |||
| static jack_midi_event_t jackEvent; | |||
| static CarlaEngineMidiEvent carlaEvent; | |||
| if (jackbridge_midi_event_get(&jackEvent, buffer, index) == 0 && jackEvent.size <= 4) | |||
| { | |||
| carlaEvent.time = jackEvent.time; | |||
| carlaEvent.size = jackEvent.size; | |||
| memcpy(carlaEvent.data, jackEvent.buffer, jackEvent.size); | |||
| return &carlaEvent; | |||
| } | |||
| return nullptr; | |||
| } | |||
| void writeEvent(uint32_t time, const uint8_t* data, uint8_t size) | |||
| { | |||
| if (! port) | |||
| return CarlaEngineMidiPort::writeEvent(time, data, size); | |||
| if (isInput) | |||
| return; | |||
| jackbridge_midi_event_write(buffer, time, data, size); | |||
| } | |||
| private: | |||
| jack_client_t* const client; | |||
| jack_port_t* const port; | |||
| }; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Jack Engine client | |||
| class CarlaEngineJackClient : public CarlaEngineClient | |||
| { | |||
| public: | |||
| CarlaEngineJackClient(jack_client_t* const client_, const CarlaEngineType engineType, const ProcessMode processMode) | |||
| : CarlaEngineClient(engineType, processMode), | |||
| client(client_) | |||
| { | |||
| } | |||
| ~CarlaEngineJackClient() | |||
| { | |||
| if (processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| if (client) | |||
| jackbridge_client_close(client); | |||
| } | |||
| } | |||
| void activate() | |||
| { | |||
| if (processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| if (client && ! isActive()) | |||
| jackbridge_activate(client); | |||
| } | |||
| CarlaEngineClient::activate(); | |||
| } | |||
| void deactivate() | |||
| { | |||
| CarlaEngineClient::deactivate(); | |||
| if (processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| if (client && isActive()) | |||
| jackbridge_deactivate(client); | |||
| } | |||
| } | |||
| bool isOk() const | |||
| { | |||
| if (processMode != PROCESS_MODE_CONTINUOUS_RACK) | |||
| return bool(client); | |||
| return CarlaEngineClient::isOk(); | |||
| } | |||
| void setLatency(const uint32_t samples) | |||
| { | |||
| CarlaEngineClient::setLatency(samples); | |||
| if (processMode != PROCESS_MODE_CONTINUOUS_RACK) | |||
| jackbridge_recompute_total_latencies(client); | |||
| } | |||
| const CarlaEngineBasePort* addPort(const CarlaEnginePortType portType, const char* const name, const bool isInput) | |||
| { | |||
| qDebug("CarlaEngineClient::addPort(%i, \"%s\", %s)", portType, name, bool2str(isInput)); | |||
| jack_port_t* port = nullptr; | |||
| // Create Jack port if needed | |||
| if (processMode != PROCESS_MODE_CONTINUOUS_RACK) | |||
| { | |||
| switch (portType) | |||
| { | |||
| case CarlaEnginePortTypeNull: | |||
| break; | |||
| case CarlaEnginePortTypeAudio: | |||
| port = jackbridge_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0); | |||
| break; | |||
| case CarlaEnginePortTypeControl: | |||
| case CarlaEnginePortTypeMIDI: | |||
| port = jackbridge_port_register(client, name, JACK_DEFAULT_MIDI_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0); | |||
| break; | |||
| } | |||
| } | |||
| // Create Engine port | |||
| switch (portType) | |||
| { | |||
| case CarlaEnginePortTypeNull: | |||
| break; | |||
| case CarlaEnginePortTypeAudio: | |||
| return new CarlaEngineJackAudioPort(isInput, processMode, client, port); | |||
| case CarlaEnginePortTypeControl: | |||
| return new CarlaEngineJackControlPort(isInput, processMode, client, port); | |||
| case CarlaEnginePortTypeMIDI: | |||
| return new CarlaEngineJackMidiPort(isInput, processMode, client, port); | |||
| } | |||
| qCritical("CarlaEngineClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput)); | |||
| return nullptr; | |||
| } | |||
| private: | |||
| jack_client_t* const client; | |||
| }; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Jack Engine | |||
| class CarlaEngineJack : public CarlaEngine | |||
| { | |||
| @@ -62,26 +410,24 @@ public: | |||
| CarlaEngineJack() | |||
| : CarlaEngine() | |||
| #ifndef BUILD_BRIDGE | |||
| # ifdef Q_COMPILER_INITIALIZER_LISTS | |||
| # ifdef Q_COMPILER_INITIALIZER_LISTS | |||
| , rackJackPorts{nullptr} | |||
| # endif | |||
| # endif | |||
| #endif | |||
| { | |||
| qDebug("CarlaEngineJack::CarlaEngineJack()"); | |||
| type = CarlaEngineTypeJack; | |||
| client = nullptr; | |||
| state = JackTransportStopped; | |||
| freewheel = false; | |||
| globalClient = nullptr; | |||
| state = JackTransportStopped; | |||
| freewheel = false; | |||
| memset(&pos, 0, sizeof(jack_position_t)); | |||
| #ifndef BUILD_BRIDGE | |||
| # ifndef Q_COMPILER_INITIALIZER_LISTS | |||
| # ifndef Q_COMPILER_INITIALIZER_LISTS | |||
| for (unsigned short i=0; i < rackPortCount; i++) | |||
| rackJackPorts[i] = nullptr; | |||
| # endif | |||
| # endif | |||
| #endif | |||
| } | |||
| @@ -100,42 +446,43 @@ public: | |||
| state = JackTransportStopped; | |||
| #ifndef BUILD_BRIDGE | |||
| client = jackbridge_client_open(clientName, JackNullOption, nullptr); | |||
| globalClient = jackbridge_client_open(clientName, JackNullOption, nullptr); | |||
| if (client) | |||
| if (globalClient) | |||
| { | |||
| sampleRate = jackbridge_get_sample_rate(client); | |||
| bufferSize = jackbridge_get_buffer_size(client); | |||
| sampleRate = jackbridge_get_sample_rate(globalClient); | |||
| bufferSize = jackbridge_get_buffer_size(globalClient); | |||
| jackbridge_set_sample_rate_callback(client, carla_jack_srate_callback, this); | |||
| jackbridge_set_buffer_size_callback(client, carla_jack_bufsize_callback, this); | |||
| jackbridge_set_freewheel_callback(client, carla_jack_freewheel_callback, this); | |||
| jackbridge_set_process_callback(client, carla_jack_process_callback, this); | |||
| jackbridge_set_latency_callback(client, carla_jack_latency_callback, this); | |||
| jackbridge_on_shutdown(client, carla_jack_shutdown_callback, this); | |||
| jackbridge_set_sample_rate_callback(globalClient, carla_jack_srate_callback, this); | |||
| jackbridge_set_buffer_size_callback(globalClient, carla_jack_bufsize_callback, this); | |||
| jackbridge_set_freewheel_callback(globalClient, carla_jack_freewheel_callback, this); | |||
| jackbridge_set_process_callback(globalClient, carla_jack_process_callback, this); | |||
| jackbridge_set_latency_callback(globalClient, carla_jack_latency_callback, this); | |||
| jackbridge_on_shutdown(globalClient, carla_jack_shutdown_callback, this); | |||
| if (processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| if (options.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| { | |||
| rackJackPorts[rackPortAudioIn1] = jackbridge_port_register(client, "in1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| rackJackPorts[rackPortAudioIn2] = jackbridge_port_register(client, "in2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| rackJackPorts[rackPortAudioOut1] = jackbridge_port_register(client, "out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| rackJackPorts[rackPortAudioOut2] = jackbridge_port_register(client, "out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| rackJackPorts[rackPortControlIn] = jackbridge_port_register(client, "control-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| rackJackPorts[rackPortControlOut] = jackbridge_port_register(client, "control-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||
| rackJackPorts[rackPortMidiIn] = jackbridge_port_register(client, "midi-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| rackJackPorts[rackPortMidiOut] = jackbridge_port_register(client, "midi-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||
| rackJackPorts[rackPortAudioIn1] = jackbridge_port_register(globalClient, "in1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| rackJackPorts[rackPortAudioIn2] = jackbridge_port_register(globalClient, "in2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| rackJackPorts[rackPortAudioOut1] = jackbridge_port_register(globalClient, "out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| rackJackPorts[rackPortAudioOut2] = jackbridge_port_register(globalClient, "out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| rackJackPorts[rackPortControlIn] = jackbridge_port_register(globalClient, "control-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| rackJackPorts[rackPortControlOut] = jackbridge_port_register(globalClient, "control-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||
| rackJackPorts[rackPortMidiIn] = jackbridge_port_register(globalClient, "midi-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| rackJackPorts[rackPortMidiOut] = jackbridge_port_register(globalClient, "midi-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||
| } | |||
| if (jackbridge_activate(client) == 0) | |||
| if (jackbridge_activate(globalClient) == 0) | |||
| { | |||
| name = getFixedClientName(jackbridge_get_client_name(client)); | |||
| name = jackbridge_get_client_name(globalClient); | |||
| name.toBasic(); | |||
| CarlaEngine::init(name); | |||
| return true; | |||
| } | |||
| else | |||
| { | |||
| setLastError("Failed to activate the JACK client"); | |||
| client = nullptr; | |||
| globalClient = nullptr; | |||
| } | |||
| } | |||
| else | |||
| @@ -143,7 +490,9 @@ public: | |||
| return false; | |||
| #else | |||
| name = getFixedClientName(clientName); | |||
| name = clientName; | |||
| name.toBasic(); | |||
| CarlaEngine::init(name); | |||
| return true; | |||
| #endif | |||
| @@ -154,33 +503,27 @@ public: | |||
| qDebug("CarlaEngineJack::close()"); | |||
| CarlaEngine::close(); | |||
| if (name) | |||
| { | |||
| free((void*)name); | |||
| name = nullptr; | |||
| } | |||
| #ifdef BUILD_BRIDGE | |||
| client = nullptr; | |||
| globalClient = nullptr; | |||
| return true; | |||
| #else | |||
| if (jackbridge_deactivate(client) == 0) | |||
| if (jackbridge_deactivate(globalClient) == 0) | |||
| { | |||
| if (processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| if (options.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| { | |||
| jackbridge_port_unregister(client, rackJackPorts[rackPortAudioIn1]); | |||
| jackbridge_port_unregister(client, rackJackPorts[rackPortAudioIn2]); | |||
| jackbridge_port_unregister(client, rackJackPorts[rackPortAudioOut1]); | |||
| jackbridge_port_unregister(client, rackJackPorts[rackPortAudioOut2]); | |||
| jackbridge_port_unregister(client, rackJackPorts[rackPortControlIn]); | |||
| jackbridge_port_unregister(client, rackJackPorts[rackPortControlOut]); | |||
| jackbridge_port_unregister(client, rackJackPorts[rackPortMidiIn]); | |||
| jackbridge_port_unregister(client, rackJackPorts[rackPortMidiOut]); | |||
| jackbridge_port_unregister(globalClient, rackJackPorts[rackPortAudioIn1]); | |||
| jackbridge_port_unregister(globalClient, rackJackPorts[rackPortAudioIn2]); | |||
| jackbridge_port_unregister(globalClient, rackJackPorts[rackPortAudioOut1]); | |||
| jackbridge_port_unregister(globalClient, rackJackPorts[rackPortAudioOut2]); | |||
| jackbridge_port_unregister(globalClient, rackJackPorts[rackPortControlIn]); | |||
| jackbridge_port_unregister(globalClient, rackJackPorts[rackPortControlOut]); | |||
| jackbridge_port_unregister(globalClient, rackJackPorts[rackPortMidiIn]); | |||
| jackbridge_port_unregister(globalClient, rackJackPorts[rackPortMidiOut]); | |||
| } | |||
| if (jackbridge_client_close(client) == 0) | |||
| if (jackbridge_client_close(globalClient) == 0) | |||
| { | |||
| client = nullptr; | |||
| globalClient = nullptr; | |||
| return true; | |||
| } | |||
| else | |||
| @@ -189,28 +532,32 @@ public: | |||
| else | |||
| setLastError("Failed to deactivate the JACK client"); | |||
| client = nullptr; | |||
| globalClient = nullptr; | |||
| #endif | |||
| return false; | |||
| } | |||
| bool isOffline() | |||
| bool isOffline() const | |||
| { | |||
| return freewheel; | |||
| } | |||
| bool isRunning() | |||
| bool isRunning() const | |||
| { | |||
| return bool(globalClient); | |||
| } | |||
| CarlaEngineType type() const | |||
| { | |||
| return bool(client); | |||
| return CarlaEngineTypeJack; | |||
| } | |||
| CarlaEngineClient* addClient(CarlaPlugin* const plugin) | |||
| { | |||
| CarlaEngineClientNativeHandle* handle = new CarlaEngineClientNativeHandle; | |||
| handle->type = CarlaEngineTypeJack; | |||
| jack_client_t* client = nullptr; | |||
| #ifdef BUILD_BRIDGE | |||
| client = handle.jackClient = jackbridge_client_open(plugin->name(), JackNullOption, nullptr); | |||
| client = globalClient = jackbridge_client_open(plugin->name(), JackNullOption, nullptr); | |||
| sampleRate = jackbridge_get_sample_rate(client); | |||
| bufferSize = jackbridge_get_buffer_size(client); | |||
| @@ -222,19 +569,19 @@ public: | |||
| jackbridge_set_latency_callback(handle.jackClient, carla_jack_latency_callback, this); | |||
| jackbridge_on_shutdown(client, carla_jack_shutdown_callback, this); | |||
| #else | |||
| if (processMode == PROCESS_MODE_SINGLE_CLIENT) | |||
| if (options.processMode == PROCESS_MODE_SINGLE_CLIENT) | |||
| { | |||
| handle->jackClient = client; | |||
| client = globalClient; | |||
| } | |||
| else if (processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| else if (options.processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| handle->jackClient = jackbridge_client_open(plugin->name(), JackNullOption, nullptr); | |||
| jackbridge_set_process_callback(handle->jackClient, carla_jack_process_callback_plugin, plugin); | |||
| jackbridge_set_latency_callback(handle->jackClient, carla_jack_latency_callback_plugin, plugin); | |||
| client = jackbridge_client_open(plugin->name(), JackNullOption, nullptr); | |||
| jackbridge_set_process_callback(client, carla_jack_process_callback_plugin, plugin); | |||
| jackbridge_set_latency_callback(client, carla_jack_latency_callback_plugin, plugin); | |||
| } | |||
| #endif | |||
| return new CarlaEngineClient(handle); | |||
| return new CarlaEngineJackClient(client, CarlaEngineTypeJack, options.processMode); | |||
| } | |||
| // ------------------------------------- | |||
| @@ -266,7 +613,7 @@ protected: | |||
| if (maxPluginNumber() == 0) | |||
| return; | |||
| #endif | |||
| state = jackbridge_transport_query(client, &pos); | |||
| state = jackbridge_transport_query(globalClient, &pos); | |||
| timeInfo.playing = (state != JackTransportStopped); | |||
| @@ -297,7 +644,7 @@ protected: | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| if (processMode == PROCESS_MODE_SINGLE_CLIENT) | |||
| if (options.processMode == PROCESS_MODE_SINGLE_CLIENT) | |||
| { | |||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||
| { | |||
| @@ -319,7 +666,7 @@ protected: | |||
| plugin->engineProcessUnlock(); | |||
| } | |||
| } | |||
| else if (processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| else if (options.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| { | |||
| // get buffers from jack | |||
| float* audioIn1 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioIn1], nframes); | |||
| @@ -373,21 +720,21 @@ protected: | |||
| if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) | |||
| { | |||
| uint8_t midiBank = jackEvent.buffer[2]; | |||
| carlaEvent->type = CarlaEngineEventMidiBankChange; | |||
| carlaEvent->type = CarlaEngineMidiBankChangeEvent; | |||
| carlaEvent->value = midiBank; | |||
| } | |||
| else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) | |||
| { | |||
| carlaEvent->type = CarlaEngineEventAllSoundOff; | |||
| carlaEvent->type = CarlaEngineAllSoundOffEvent; | |||
| } | |||
| else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) | |||
| { | |||
| carlaEvent->type = CarlaEngineEventAllNotesOff; | |||
| carlaEvent->type = CarlaEngineAllNotesOffEvent; | |||
| } | |||
| else | |||
| { | |||
| uint8_t midiValue = jackEvent.buffer[2]; | |||
| carlaEvent->type = CarlaEngineEventControlChange; | |||
| carlaEvent->type = CarlaEngineParameterChangeEvent; | |||
| carlaEvent->controller = midiControl; | |||
| carlaEvent->value = double(midiValue)/127; | |||
| } | |||
| @@ -395,7 +742,7 @@ protected: | |||
| else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus)) | |||
| { | |||
| uint8_t midiProgram = jackEvent.buffer[1]; | |||
| carlaEvent->type = CarlaEngineEventMidiProgramChange; | |||
| carlaEvent->type = CarlaEngineMidiProgramChangeEvent; | |||
| carlaEvent->value = midiProgram; | |||
| } | |||
| } | |||
| @@ -433,38 +780,38 @@ protected: | |||
| { | |||
| CarlaEngineControlEvent* const event = &rackControlEventsOut[i]; | |||
| if (event->type == CarlaEngineEventControlChange && MIDI_IS_CONTROL_BANK_SELECT(event->controller)) | |||
| event->type = CarlaEngineEventMidiBankChange; | |||
| if (event->type == CarlaEngineParameterChangeEvent && MIDI_IS_CONTROL_BANK_SELECT(event->controller)) | |||
| event->type = CarlaEngineMidiBankChangeEvent; | |||
| uint8_t data[4] = { 0 }; | |||
| switch (event->type) | |||
| { | |||
| case CarlaEngineEventNull: | |||
| case CarlaEngineNullEvent: | |||
| break; | |||
| case CarlaEngineEventControlChange: | |||
| case CarlaEngineParameterChangeEvent: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | |||
| data[1] = event->controller; | |||
| data[2] = event->value * 127; | |||
| jackbridge_midi_event_write(controlOut, event->time, data, 3); | |||
| break; | |||
| case CarlaEngineEventMidiBankChange: | |||
| case CarlaEngineMidiBankChangeEvent: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | |||
| data[1] = MIDI_CONTROL_BANK_SELECT; | |||
| data[2] = event->value; | |||
| jackbridge_midi_event_write(controlOut, event->time, data, 3); | |||
| break; | |||
| case CarlaEngineEventMidiProgramChange: | |||
| case CarlaEngineMidiProgramChangeEvent: | |||
| data[0] = MIDI_STATUS_PROGRAM_CHANGE + event->channel; | |||
| data[1] = event->value; | |||
| jackbridge_midi_event_write(controlOut, event->time, data, 2); | |||
| break; | |||
| case CarlaEngineEventAllSoundOff: | |||
| case CarlaEngineAllSoundOffEvent: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | |||
| data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
| jackbridge_midi_event_write(controlOut, event->time, data, 2); | |||
| break; | |||
| case CarlaEngineEventAllNotesOff: | |||
| case CarlaEngineAllNotesOffEvent: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | |||
| data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
| jackbridge_midi_event_write(controlOut, event->time, data, 2); | |||
| @@ -509,7 +856,7 @@ protected: | |||
| void handleLatencyCallback(jack_latency_callback_mode_t mode) | |||
| { | |||
| #ifndef BUILD_BRIDGE | |||
| if (processMode != PROCESS_MODE_SINGLE_CLIENT) | |||
| if (options.processMode != PROCESS_MODE_SINGLE_CLIENT) | |||
| return; | |||
| #endif | |||
| @@ -532,14 +879,14 @@ protected: | |||
| plugin->x_client = nullptr; | |||
| } | |||
| client = nullptr; | |||
| globalClient = nullptr; | |||
| callback(CALLBACK_QUIT, 0, 0, 0, 0.0); | |||
| } | |||
| // ------------------------------------- | |||
| private: | |||
| jack_client_t* client; | |||
| jack_client_t* globalClient; | |||
| jack_transport_state_t state; | |||
| jack_position_t pos; | |||
| bool freewheel; | |||
| @@ -567,11 +914,13 @@ private: | |||
| float* inBuffer[p->aIn.count]; | |||
| float* outBuffer[p->aOut.count]; | |||
| #if 0 | |||
| for (uint32_t i=0; i < p->aIn.count; i++) | |||
| inBuffer[i] = p->aIn.ports[i]->getJackAudioBuffer(nframes); | |||
| inBuffer[i] = (float*)jackbridge_port_get_buffer(p->aIn.ports[i]->handle.jackPort, nframes); | |||
| for (uint32_t i=0; i < p->aOut.count; i++) | |||
| outBuffer[i] = p->aOut.ports[i]->getJackAudioBuffer(nframes); | |||
| outBuffer[i] = (float*)jackbridge_port_get_buffer(p->aOut.ports[i]->handle.jackPort, nframes); | |||
| #endif | |||
| #ifndef BUILD_BRIDGE | |||
| if (/*options.processHighPrecision*/ 0) | |||
| @@ -597,11 +946,15 @@ private: | |||
| static void processPluginNOT(CarlaPlugin* const p, const uint32_t nframes) | |||
| { | |||
| for (uint32_t i=0; i < p->aIn.count; i++) | |||
| carla_zeroF(p->aIn.ports[i]->getJackAudioBuffer(nframes), nframes); | |||
| CarlaEngineJackAudioPort* port; | |||
| float* buffer; | |||
| for (uint32_t i=0; i < p->aOut.count; i++) | |||
| carla_zeroF(p->aOut.ports[i]->getJackAudioBuffer(nframes), nframes); | |||
| { | |||
| port = (CarlaEngineJackAudioPort*)p->aOut.ports[i]; | |||
| buffer = (float*)jackbridge_port_get_buffer(port->port, nframes); | |||
| carla_zeroF(buffer, nframes); | |||
| } | |||
| } | |||
| static void latencyPlugin(CarlaPlugin* const p, jack_latency_callback_mode_t mode) | |||
| @@ -617,8 +970,8 @@ private: | |||
| for (uint32_t i=0; i < p->aIn.count; i++) | |||
| { | |||
| uint aOutI = (i >= p->aOut.count) ? p->aOut.count : i; | |||
| jack_port_t* const portIn = p->aIn.ports[i]->getHandle()->jackPort; | |||
| jack_port_t* const portOut = p->aOut.ports[aOutI]->getHandle()->jackPort; | |||
| jack_port_t* const portIn = ((CarlaEngineJackAudioPort*)p->aIn.ports[i])->port; | |||
| jack_port_t* const portOut = ((CarlaEngineJackAudioPort*)p->aOut.ports[aOutI])->port; | |||
| jackbridge_port_get_latency_range(portIn, mode, &range); | |||
| range.min += pluginLatency; | |||
| @@ -631,8 +984,8 @@ private: | |||
| for (uint32_t i=0; i < p->aOut.count; i++) | |||
| { | |||
| uint aInI = (i >= p->aIn.count) ? p->aIn.count : i; | |||
| jack_port_t* const portIn = p->aIn.ports[aInI]->getHandle()->jackPort; | |||
| jack_port_t* const portOut = p->aOut.ports[i]->getHandle()->jackPort; | |||
| jack_port_t* const portIn = ((CarlaEngineJackAudioPort*)p->aIn.ports[aInI])->port; | |||
| jack_port_t* const portOut = ((CarlaEngineJackAudioPort*)p->aOut.ports[i])->port; | |||
| jackbridge_port_get_latency_range(portOut, mode, &range); | |||
| range.min += pluginLatency; | |||
| @@ -39,6 +39,42 @@ static const unsigned int paramPan = 8; | |||
| static const unsigned int paramCount = sizeof(paramMap); | |||
| static const unsigned int programCount = 128; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Plugin Engine client | |||
| class CarlaEnginePluginClient : public CarlaEngineClient | |||
| { | |||
| public: | |||
| CarlaEnginePluginClient(const CarlaEngineType engineType, const ProcessMode processMode) | |||
| : CarlaEngineClient(engineType, processMode) | |||
| { | |||
| } | |||
| ~CarlaEnginePluginClient() | |||
| { | |||
| } | |||
| const CarlaEngineBasePort* addPort(const CarlaEnginePortType portType, const char* const name, const bool isInput) | |||
| { | |||
| qDebug("CarlaEnginePluginClient::addPort(%i, \"%s\", %s)", portType, name, bool2str(isInput)); | |||
| switch (portType) | |||
| { | |||
| case CarlaEnginePortTypeNull: | |||
| break; | |||
| case CarlaEnginePortTypeAudio: | |||
| return new CarlaEngineAudioPort(isInput, processMode); | |||
| case CarlaEnginePortTypeControl: | |||
| return new CarlaEngineControlPort(isInput, processMode); | |||
| case CarlaEnginePortTypeMIDI: | |||
| return new CarlaEngineMidiPort(isInput, processMode); | |||
| } | |||
| qCritical("CarlaEnginePluginClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput)); | |||
| return nullptr; | |||
| } | |||
| }; | |||
| // ----------------------------------------- | |||
| class CarlaEnginePlugin : public CarlaEngine, | |||
| @@ -64,7 +100,7 @@ public: | |||
| memcpy(prevParamBuffers, paramBuffers, sizeof(float)*paramCount); | |||
| // set-up engine | |||
| processMode = PROCESS_MODE_CONTINUOUS_RACK; | |||
| options.processMode = PROCESS_MODE_CONTINUOUS_RACK; | |||
| options.forceStereo = true; | |||
| options.preferPluginBridges = false; | |||
| options.preferUiBridges = false; | |||
| @@ -96,9 +132,10 @@ public: | |||
| bufferSize = d_bufferSize(); | |||
| sampleRate = d_sampleRate(); | |||
| name = strdup(clientName); | |||
| CarlaEngine::init(name); | |||
| name = clientName; | |||
| name.toBasic(); | |||
| CarlaEngine::init(name); | |||
| return true; | |||
| } | |||
| @@ -107,32 +144,27 @@ public: | |||
| qDebug("CarlaEnginePlugin::close()"); | |||
| CarlaEngine::close(); | |||
| if (name) | |||
| { | |||
| free((void*)name); | |||
| name = nullptr; | |||
| } | |||
| return true; | |||
| } | |||
| bool isOffline() | |||
| bool isOffline() const | |||
| { | |||
| return false; | |||
| } | |||
| bool isRunning() | |||
| bool isRunning() const | |||
| { | |||
| return true; | |||
| } | |||
| CarlaEngineClient* addClient(CarlaPlugin* const plugin) | |||
| CarlaEngineType type() const | |||
| { | |||
| CarlaEngineClientNativeHandle handle; | |||
| handle.type = CarlaEngineTypeRtAudio; | |||
| return CarlaEngineTypeRtAudio; | |||
| } | |||
| return new CarlaEngineClient(handle); | |||
| Q_UNUSED(plugin); | |||
| CarlaEngineClient* addClient(CarlaPlugin* const) | |||
| { | |||
| return new CarlaEnginePluginClient(CarlaEngineTypeRtAudio, options.processMode); | |||
| } | |||
| protected: | |||
| @@ -441,7 +473,7 @@ protected: | |||
| CarlaEngineControlEvent* const carlaEvent = &rackControlEventsIn[carlaEventIndex++]; | |||
| carlaEvent->type = CarlaEngineEventControlChange; | |||
| carlaEvent->type = CarlaEngineParameterChangeEvent; | |||
| carlaEvent->controller = paramMap[i]; | |||
| carlaEvent->value = paramBuffers[i]/127; | |||
| } | |||
| @@ -25,22 +25,44 @@ | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| struct CarlaEngineClientNativeHandle { | |||
| CarlaEngineType type; | |||
| #ifdef CARLA_ENGINE_JACK | |||
| void* jackClient; | |||
| #endif | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // RtAudio Engine client | |||
| CarlaEngineClientNativeHandle() | |||
| class CarlaEngineRtAudioClient : public CarlaEngineClient | |||
| { | |||
| public: | |||
| CarlaEngineRtAudioClient(const CarlaEngineType engineType, const ProcessMode processMode) | |||
| : CarlaEngineClient(engineType, processMode) | |||
| { | |||
| } | |||
| ~CarlaEngineRtAudioClient() | |||
| { | |||
| type = CarlaEngineTypeNull; | |||
| #ifdef CARLA_ENGINE_JACK | |||
| jackClient = nullptr; | |||
| #endif | |||
| } | |||
| const CarlaEngineBasePort* addPort(const CarlaEnginePortType portType, const char* const name, const bool isInput) | |||
| { | |||
| qDebug("CarlaEngineRtAudioClient::addPort(%i, \"%s\", %s)", portType, name, bool2str(isInput)); | |||
| switch (portType) | |||
| { | |||
| case CarlaEnginePortTypeNull: | |||
| break; | |||
| case CarlaEnginePortTypeAudio: | |||
| return new CarlaEngineAudioPort(isInput, processMode); | |||
| case CarlaEnginePortTypeControl: | |||
| return new CarlaEngineControlPort(isInput, processMode); | |||
| case CarlaEnginePortTypeMIDI: | |||
| return new CarlaEngineMidiPort(isInput, processMode); | |||
| } | |||
| qCritical("CarlaEngineRtAudioClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput)); | |||
| return nullptr; | |||
| } | |||
| }; | |||
| // ----------------------------------------- | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // RtAudio Engine | |||
| class CarlaEngineRtAudio : public CarlaEngine | |||
| { | |||
| @@ -51,14 +73,12 @@ public: | |||
| { | |||
| qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()"); | |||
| type = CarlaEngineTypeRtAudio; | |||
| midiIn = nullptr; | |||
| midiOut = nullptr; | |||
| // just to make sure | |||
| options.forceStereo = true; | |||
| processMode = PROCESS_MODE_CONTINUOUS_RACK; | |||
| options.processMode = PROCESS_MODE_CONTINUOUS_RACK; | |||
| } | |||
| ~CarlaEngineRtAudio() | |||
| @@ -118,7 +138,9 @@ public: | |||
| midiOut->openVirtualPort("control-out"); | |||
| midiOut->openVirtualPort("midi-out"); | |||
| name = getFixedClientName(clientName); | |||
| name = clientName; | |||
| name.toBasic(); | |||
| CarlaEngine::init(name); | |||
| return true; | |||
| } | |||
| @@ -128,12 +150,6 @@ public: | |||
| qDebug("CarlaEngineRtAudio::close()"); | |||
| CarlaEngine::close(); | |||
| if (name) | |||
| { | |||
| free((void*)name); | |||
| name = nullptr; | |||
| } | |||
| if (audio.isStreamRunning()) | |||
| audio.stopStream(); | |||
| @@ -158,22 +174,24 @@ public: | |||
| return true; | |||
| } | |||
| bool isOffline() | |||
| bool isOffline() const | |||
| { | |||
| return false; | |||
| } | |||
| bool isRunning() | |||
| bool isRunning() const | |||
| { | |||
| return audio.isStreamRunning(); | |||
| } | |||
| CarlaEngineClient* addClient(CarlaPlugin* const) | |||
| CarlaEngineType type() const | |||
| { | |||
| CarlaEngineClientNativeHandle* handle = new CarlaEngineClientNativeHandle; | |||
| handle->type = CarlaEngineTypeRtAudio; | |||
| return CarlaEngineTypeRtAudio; | |||
| } | |||
| return new CarlaEngineClient(handle); | |||
| CarlaEngineClient* addClient(CarlaPlugin* const) | |||
| { | |||
| return new CarlaEngineRtAudioClient(CarlaEngineTypeRtAudio, options.processMode); | |||
| } | |||
| // ------------------------------------- | |||
| @@ -267,10 +285,80 @@ private: | |||
| CarlaEngine* CarlaEngine::newRtAudio(RtAudioApi api) | |||
| { | |||
| return new CarlaEngineRtAudio(static_cast<RtAudio::Api>(api)); | |||
| RtAudio::Api rtApi = RtAudio::UNSPECIFIED; | |||
| switch (api) | |||
| { | |||
| case RTAUDIO_DUMMY: | |||
| rtApi = RtAudio::RTAUDIO_DUMMY; | |||
| break; | |||
| case RTAUDIO_LINUX_ALSA: | |||
| rtApi = RtAudio::LINUX_ALSA; | |||
| break; | |||
| case RTAUDIO_LINUX_PULSE: | |||
| rtApi = RtAudio::LINUX_PULSE; | |||
| break; | |||
| case RTAUDIO_LINUX_OSS: | |||
| rtApi = RtAudio::LINUX_OSS; | |||
| break; | |||
| case RTAUDIO_UNIX_JACK: | |||
| rtApi = RtAudio::UNIX_JACK; | |||
| break; | |||
| case RTAUDIO_MACOSX_CORE: | |||
| rtApi = RtAudio::MACOSX_CORE; | |||
| break; | |||
| case RTAUDIO_WINDOWS_ASIO: | |||
| rtApi = RtAudio::WINDOWS_ASIO; | |||
| break; | |||
| case RTAUDIO_WINDOWS_DS: | |||
| rtApi = RtAudio::WINDOWS_DS; | |||
| break; | |||
| } | |||
| return new CarlaEngineRtAudio(rtApi); | |||
| } | |||
| unsigned int CarlaEngine::getRtAudioApiCount() | |||
| { | |||
| std::vector<RtAudio::Api> apis; | |||
| RtAudio::getCompiledApi(apis); | |||
| return apis.size(); | |||
| } | |||
| // ----------------------------------------- | |||
| const char* CarlaEngine::getRtAudioApiName(unsigned int index) | |||
| { | |||
| std::vector<RtAudio::Api> apis; | |||
| RtAudio::getCompiledApi(apis); | |||
| if (index < apis.size()) | |||
| { | |||
| const RtAudio::Api& api(apis[index]); | |||
| switch (api) | |||
| { | |||
| case RtAudio::UNSPECIFIED: | |||
| return "Unspecified"; | |||
| case RtAudio::LINUX_ALSA: | |||
| return "ALSA"; | |||
| case RtAudio::LINUX_PULSE: | |||
| return "PulseAudio"; | |||
| case RtAudio::LINUX_OSS: | |||
| return "OSS"; | |||
| case RtAudio::UNIX_JACK: | |||
| return "JACK (RtAudio)"; | |||
| case RtAudio::MACOSX_CORE: | |||
| return "CoreAudio"; | |||
| case RtAudio::WINDOWS_ASIO: | |||
| return "ASIO"; | |||
| case RtAudio::WINDOWS_DS: | |||
| return "DirectSound"; | |||
| case RtAudio::RTAUDIO_DUMMY: | |||
| return "Dummy"; | |||
| } | |||
| } | |||
| return nullptr; | |||
| } | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| @@ -740,7 +740,7 @@ public: | |||
| /*! | |||
| * Process all the post-poned events. | |||
| * This function will only be called from the main thread if PLUGIN_USES_SINGLE_THREAD is set. | |||
| * This function must be called from the main thread (ie, idleGui()) if PLUGIN_USES_SINGLE_THREAD is set. | |||
| */ | |||
| void postEventsRun(); | |||
| @@ -847,7 +847,7 @@ public: | |||
| #endif | |||
| static size_t getNativePluginCount(); | |||
| static const PluginDescriptor* getNativePlugin(size_t index); | |||
| static const PluginDescriptor* getNativePluginDescriptor(const size_t index); | |||
| // ------------------------------------------------------------------- | |||
| @@ -976,11 +976,6 @@ protected: | |||
| return value; | |||
| } | |||
| static double abs(const double& value) | |||
| { | |||
| return (value < 0.0) ? -value : value; | |||
| } | |||
| friend class CarlaEngineJack; | |||
| }; | |||
| @@ -121,30 +121,30 @@ static inline | |||
| void pass() {} | |||
| // ------------------------------------------------- | |||
| // carla_string class | |||
| // CarlaString class | |||
| class carla_string | |||
| class CarlaString | |||
| { | |||
| public: | |||
| // --------------------------------------------- | |||
| // constructors (no explicit conversions allowed) | |||
| explicit carla_string() | |||
| explicit CarlaString() | |||
| { | |||
| buffer = ::strdup(""); | |||
| } | |||
| explicit carla_string(char* const strBuf) | |||
| explicit CarlaString(char* const strBuf) | |||
| { | |||
| buffer = ::strdup(strBuf ? strBuf : ""); | |||
| } | |||
| explicit carla_string(const char* const strBuf) | |||
| explicit CarlaString(const char* const strBuf) | |||
| { | |||
| buffer = ::strdup(strBuf ? strBuf : ""); | |||
| } | |||
| explicit carla_string(const int value) | |||
| explicit CarlaString(const int value) | |||
| { | |||
| const size_t strBufSize = ::abs(value/10) + 3; | |||
| char strBuf[strBufSize]; | |||
| @@ -153,7 +153,7 @@ public: | |||
| buffer = ::strdup(strBuf); | |||
| } | |||
| explicit carla_string(const unsigned int value, const bool hexadecimal = false) | |||
| explicit CarlaString(const unsigned int value, const bool hexadecimal = false) | |||
| { | |||
| const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0); | |||
| char strBuf[strBufSize]; | |||
| @@ -162,7 +162,7 @@ public: | |||
| buffer = ::strdup(strBuf); | |||
| } | |||
| explicit carla_string(const long int value) | |||
| explicit CarlaString(const long int value) | |||
| { | |||
| const size_t strBufSize = ::labs(value/10) + 3; | |||
| char strBuf[strBufSize]; | |||
| @@ -171,7 +171,7 @@ public: | |||
| buffer = ::strdup(strBuf); | |||
| } | |||
| explicit carla_string(const unsigned long int value, const bool hexadecimal = false) | |||
| explicit CarlaString(const unsigned long int value, const bool hexadecimal = false) | |||
| { | |||
| const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0); | |||
| char strBuf[strBufSize]; | |||
| @@ -180,7 +180,7 @@ public: | |||
| buffer = ::strdup(strBuf); | |||
| } | |||
| explicit carla_string(const float value) | |||
| explicit CarlaString(const float value) | |||
| { | |||
| char strBuf[0xff]; | |||
| ::snprintf(strBuf, 0xff, "%f", value); | |||
| @@ -188,7 +188,7 @@ public: | |||
| buffer = ::strdup(strBuf); | |||
| } | |||
| explicit carla_string(const double value) | |||
| explicit CarlaString(const double value) | |||
| { | |||
| char strBuf[0xff]; | |||
| ::snprintf(strBuf, 0xff, "%g", value); | |||
| @@ -199,7 +199,7 @@ public: | |||
| // --------------------------------------------- | |||
| // non-explicit constructor | |||
| carla_string(const carla_string& str) | |||
| CarlaString(const CarlaString& str) | |||
| { | |||
| buffer = ::strdup(str.buffer); | |||
| } | |||
| @@ -207,7 +207,7 @@ public: | |||
| // --------------------------------------------- | |||
| // deconstructor | |||
| ~carla_string() | |||
| ~CarlaString() | |||
| { | |||
| ::free(buffer); | |||
| } | |||
| @@ -225,6 +225,11 @@ public: | |||
| return (*buffer == 0); | |||
| } | |||
| bool isNotEmpty() const | |||
| { | |||
| return !isEmpty(); | |||
| } | |||
| bool contains(const char* const strBuf) const | |||
| { | |||
| if (! strBuf) | |||
| @@ -249,11 +254,51 @@ public: | |||
| return false; | |||
| } | |||
| bool contains(const carla_string& str) const | |||
| bool contains(const CarlaString& str) const | |||
| { | |||
| return contains(str.buffer); | |||
| } | |||
| bool isDigit(size_t pos) const | |||
| { | |||
| if (pos >= length()) | |||
| return false; | |||
| return (buffer[pos] >= '0' && buffer[pos] <= '9'); | |||
| } | |||
| void clear() | |||
| { | |||
| for (size_t i=0, len = ::strlen(buffer); i < len; i++) | |||
| buffer[i] = 0; | |||
| } | |||
| void replace(char before, char after) | |||
| { | |||
| for (size_t i=0, len = ::strlen(buffer); i < len; i++) | |||
| { | |||
| if (buffer[i] == before) | |||
| buffer[i] = after; | |||
| } | |||
| } | |||
| void truncate(unsigned int n) | |||
| { | |||
| for (size_t i=n, len = ::strlen(buffer); i < len; i++) | |||
| buffer[i] = 0; | |||
| } | |||
| void toBasic() | |||
| { | |||
| for (size_t i=0, len = ::strlen(buffer); i < len; i++) | |||
| { | |||
| if ((buffer[i] >= '0' && buffer[i] <= '9') || (buffer[i] >= 'A' && buffer[i] <= 'Z') || (buffer[i] >= 'a' && buffer[i] <= '<')) | |||
| continue; | |||
| buffer[i] = '_'; | |||
| } | |||
| } | |||
| void toLower() | |||
| { | |||
| for (size_t i=0, len = ::strlen(buffer); i < len; i++) | |||
| @@ -280,12 +325,17 @@ public: | |||
| return buffer; | |||
| } | |||
| char& operator[](int pos) | |||
| { | |||
| return buffer[pos]; | |||
| } | |||
| bool operator==(const char* const strBuf) const | |||
| { | |||
| return (strBuf && ::strcmp(buffer, strBuf) == 0); | |||
| } | |||
| bool operator==(const carla_string& str) const | |||
| bool operator==(const CarlaString& str) const | |||
| { | |||
| return operator==(str.buffer); | |||
| } | |||
| @@ -295,12 +345,12 @@ public: | |||
| return !operator==(strBuf); | |||
| } | |||
| bool operator!=(const carla_string& str) const | |||
| bool operator!=(const CarlaString& str) const | |||
| { | |||
| return !operator==(str.buffer); | |||
| } | |||
| carla_string& operator=(const char* const strBuf) | |||
| CarlaString& operator=(const char* const strBuf) | |||
| { | |||
| ::free(buffer); | |||
| @@ -309,12 +359,12 @@ public: | |||
| return *this; | |||
| } | |||
| carla_string& operator=(const carla_string& str) | |||
| CarlaString& operator=(const CarlaString& str) | |||
| { | |||
| return operator=(str.buffer); | |||
| } | |||
| carla_string& operator+=(const char* const strBuf) | |||
| CarlaString& operator+=(const char* const strBuf) | |||
| { | |||
| const size_t newBufSize = ::strlen(buffer) + (strBuf ? ::strlen(strBuf) : 0) + 1; | |||
| char newBuf[newBufSize]; | |||
| @@ -328,12 +378,12 @@ public: | |||
| return *this; | |||
| } | |||
| carla_string& operator+=(const carla_string& str) | |||
| CarlaString& operator+=(const CarlaString& str) | |||
| { | |||
| return operator+=(str.buffer); | |||
| } | |||
| carla_string operator+(const char* const strBuf) | |||
| CarlaString operator+(const char* const strBuf) | |||
| { | |||
| const size_t newBufSize = ::strlen(buffer) + (strBuf ? ::strlen(strBuf) : 0) + 1; | |||
| char newBuf[newBufSize]; | |||
| @@ -341,10 +391,10 @@ public: | |||
| ::strcpy(newBuf, buffer); | |||
| ::strcat(newBuf, strBuf); | |||
| return carla_string(newBuf); | |||
| return CarlaString(newBuf); | |||
| } | |||
| carla_string operator+(const carla_string& str) | |||
| CarlaString operator+(const CarlaString& str) | |||
| { | |||
| return operator+(str.buffer); | |||
| } | |||
| @@ -356,7 +406,7 @@ private: | |||
| }; | |||
| static inline | |||
| carla_string operator+(const char* const strBufBefore, const carla_string& strAfter) | |||
| CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter) | |||
| { | |||
| const char* const strBufAfter = (const char*)strAfter; | |||
| const size_t newBufSize = (strBufBefore ? ::strlen(strBufBefore) : 0) + ::strlen(strBufAfter) + 1; | |||
| @@ -365,7 +415,7 @@ carla_string operator+(const char* const strBufBefore, const carla_string& strAf | |||
| ::strcpy(newBuf, strBufBefore); | |||
| ::strcat(newBuf, strBufAfter); | |||
| return carla_string(newBuf); | |||
| return CarlaString(newBuf); | |||
| } | |||
| // ------------------------------------------------- | |||
| @@ -201,11 +201,12 @@ CALLBACK_QUIT = 20 | |||
| PROCESS_MODE_SINGLE_CLIENT = 0 | |||
| PROCESS_MODE_MULTIPLE_CLIENTS = 1 | |||
| PROCESS_MODE_CONTINUOUS_RACK = 2 | |||
| PROCESS_MODE_PATCHBAY = 3 | |||
| # ------------------------------------------------------------------------------------------------ | |||
| # Carla GUI stuff | |||
| Carla.processMode = PROCESS_MODE_MULTIPLE_CLIENTS | |||
| Carla.processMode = PROCESS_MODE_CONTINUOUS_RACK | |||
| Carla.maxParameters = MAX_PARAMETERS | |||
| # set native binary type | |||