@@ -516,10 +516,11 @@ enum CallbackType { | |||||
* | * | ||||
* \see OPTION_PROCESS_MODE | * \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_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_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 | static inline | ||||
const char* ProcessModeType2Str(const ProcessModeType& type) | |||||
const char* ProcessMode2Str(const ProcessMode& mode) | |||||
{ | { | ||||
switch (type) | |||||
switch (mode) | |||||
{ | { | ||||
case PROCESS_MODE_SINGLE_CLIENT: | case PROCESS_MODE_SINGLE_CLIENT: | ||||
return "PROCESS_MODE_SINGLE_CLIENT"; | return "PROCESS_MODE_SINGLE_CLIENT"; | ||||
@@ -333,9 +333,11 @@ const char* ProcessModeType2Str(const ProcessModeType& type) | |||||
return "PROCESS_MODE_MULTIPLE_CLIENTS"; | return "PROCESS_MODE_MULTIPLE_CLIENTS"; | ||||
case PROCESS_MODE_CONTINUOUS_RACK: | case PROCESS_MODE_CONTINUOUS_RACK: | ||||
return "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; | 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 | static inline | ||||
uintptr_t getAddressFromPointer(void* const ptr) | uintptr_t getAddressFromPointer(void* const ptr) | ||||
{ | { | ||||
@@ -434,6 +426,16 @@ uintptr_t getAddressFromPointer(void* const ptr) | |||||
return *addr; | 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 | static inline | ||||
PluginCategory getPluginCategoryFromName(const char* const name) | PluginCategory getPluginCategoryFromName(const char* const name) | ||||
{ | { | ||||
@@ -443,7 +445,7 @@ PluginCategory getPluginCategoryFromName(const char* const name) | |||||
if (! name) | if (! name) | ||||
return PLUGIN_CATEGORY_NONE; | return PLUGIN_CATEGORY_NONE; | ||||
carla_string sname(name); | |||||
CarlaString sname(name); | |||||
if (sname.isEmpty()) | if (sname.isEmpty()) | ||||
return PLUGIN_CATEGORY_NONE; | return PLUGIN_CATEGORY_NONE; | ||||
@@ -241,7 +241,7 @@ EXPAND_ONLY_PREDEF = NO | |||||
SEARCH_INCLUDES = YES | SEARCH_INCLUDES = YES | ||||
INCLUDE_PATH = | INCLUDE_PATH = | ||||
INCLUDE_FILE_PATTERNS = | INCLUDE_FILE_PATTERNS = | ||||
PREDEFINED = DOXYGEN | |||||
PREDEFINED = DOXYGEN CARLA_ENGINE_JACK CARLA_ENGINE_RTAUDIO | |||||
EXPAND_AS_DEFINED = | EXPAND_AS_DEFINED = | ||||
SKIP_FUNCTION_MACROS = YES | SKIP_FUNCTION_MACROS = YES | ||||
#--------------------------------------------------------------------------- | #--------------------------------------------------------------------------- | ||||
@@ -21,15 +21,6 @@ | |||||
#include "carla_engine_osc.hpp" | #include "carla_engine_osc.hpp" | ||||
#include "carla_engine_thread.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 | CARLA_BACKEND_START_NAMESPACE | ||||
/*! | /*! | ||||
@@ -48,28 +39,99 @@ CARLA_BACKEND_START_NAMESPACE | |||||
const uint32_t CarlaEngineTimeBBT = 0x1; | const uint32_t CarlaEngineTimeBBT = 0x1; | ||||
/**@}*/ | /**@}*/ | ||||
/*! | |||||
* The type of an engine. | |||||
*/ | |||||
enum CarlaEngineType { | 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 { | 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 { | 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 { | struct CarlaEngineControlEvent { | ||||
CarlaEngineControlEventType type; | CarlaEngineControlEventType type; | ||||
uint32_t time; | uint32_t time; | ||||
@@ -78,29 +140,35 @@ struct CarlaEngineControlEvent { | |||||
double value; | double value; | ||||
CarlaEngineControlEvent() | CarlaEngineControlEvent() | ||||
: type(CarlaEngineEventNull), | |||||
: type(CarlaEngineNullEvent), | |||||
time(0), | time(0), | ||||
channel(0), | channel(0), | ||||
controller(0), | controller(0), | ||||
value(0.0) {} | value(0.0) {} | ||||
}; | }; | ||||
/*! | |||||
* Engine MIDI event. | |||||
*/ | |||||
struct CarlaEngineMidiEvent { | struct CarlaEngineMidiEvent { | ||||
uint32_t time; | uint32_t time; | ||||
uint8_t size; | uint8_t size; | ||||
uint8_t data[4]; | |||||
uint8_t data[3]; | |||||
CarlaEngineMidiEvent() | CarlaEngineMidiEvent() | ||||
: time(0), | : time(0), | ||||
#ifdef Q_COMPILER_INITIALIZER_LISTS | |||||
#ifdef Q_COMPILER_INITIALIZER_LISTS | |||||
size(0), | size(0), | ||||
data{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 bar; | ||||
int32_t beat; | int32_t beat; | ||||
int32_t tick; | int32_t tick; | ||||
@@ -110,7 +178,7 @@ struct CarlaTimeInfoBBT { | |||||
double ticks_per_beat; | double ticks_per_beat; | ||||
double beats_per_minute; | double beats_per_minute; | ||||
CarlaTimeInfoBBT() | |||||
CarlaEngineTimeInfoBBT() | |||||
: bar(0), | : bar(0), | ||||
beat(0), | beat(0), | ||||
tick(0), | tick(0), | ||||
@@ -121,26 +189,29 @@ struct CarlaTimeInfoBBT { | |||||
beats_per_minute(0.0) {} | beats_per_minute(0.0) {} | ||||
}; | }; | ||||
struct CarlaTimeInfo { | |||||
/*! | |||||
* Engine Time information. | |||||
*/ | |||||
struct CarlaEngineTimeInfo { | |||||
bool playing; | bool playing; | ||||
uint32_t frame; | uint32_t frame; | ||||
uint32_t time; | uint32_t time; | ||||
uint32_t valid; | uint32_t valid; | ||||
CarlaTimeInfoBBT bbt; | |||||
CarlaEngineTimeInfoBBT bbt; | |||||
CarlaTimeInfo() | |||||
CarlaEngineTimeInfo() | |||||
: playing(false), | : playing(false), | ||||
frame(0), | frame(0), | ||||
time(0), | time(0), | ||||
valid(0) {} | valid(0) {} | ||||
}; | }; | ||||
struct CarlaEngineClientNativeHandle; | |||||
struct CarlaEnginePortNativeHandle; | |||||
#ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
// Global options | |||||
/*! | |||||
* Engine options. | |||||
*/ | |||||
struct CarlaEngineOptions { | struct CarlaEngineOptions { | ||||
ProcessMode processMode; | |||||
bool processHighPrecision; | bool processHighPrecision; | ||||
uint maxParameters; | uint maxParameters; | ||||
@@ -154,19 +225,20 @@ struct CarlaEngineOptions { | |||||
bool preferUiBridges; | bool preferUiBridges; | ||||
uint oscUiTimeout; | 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() | CarlaEngineOptions() | ||||
: processHighPrecision(false), | |||||
: processMode(PROCESS_MODE_CONTINUOUS_RACK), | |||||
processHighPrecision(false), | |||||
maxParameters(MAX_PARAMETERS), | maxParameters(MAX_PARAMETERS), | ||||
preferredBufferSize(512), | preferredBufferSize(512), | ||||
preferredSampleRate(44100), | preferredSampleRate(44100), | ||||
@@ -174,71 +246,344 @@ struct CarlaEngineOptions { | |||||
useDssiVstChunks(false), | useDssiVstChunks(false), | ||||
preferPluginBridges(false), | preferPluginBridges(false), | ||||
preferUiBridges(true), | 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 | #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 | class CarlaEngine | ||||
{ | { | ||||
public: | public: | ||||
/*! | |||||
* The contructor.\n | |||||
* \note This only initializes engine data, it doesn't initialize the engine itself. | |||||
*/ | |||||
CarlaEngine(); | CarlaEngine(); | ||||
/*! | |||||
* The decontructor. | |||||
* The engine must have been closed before this happens. | |||||
*/ | |||||
virtual ~CarlaEngine(); | virtual ~CarlaEngine(); | ||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
// Static values | // 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 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 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, per-engine type calls | ||||
virtual bool init(const char* const clientName); | virtual bool init(const char* const clientName); | ||||
virtual bool close(); | 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; | virtual CarlaEngineClient* addClient(CarlaPlugin* const plugin) = 0; | ||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
@@ -267,11 +612,10 @@ public: | |||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
// Information (base) | // Information (base) | ||||
CarlaEngineType getType() const; | |||||
const char* getName() const; | const char* getName() const; | ||||
double getSampleRate() const; | double getSampleRate() const; | ||||
uint32_t getBufferSize() const; | uint32_t getBufferSize() const; | ||||
const CarlaTimeInfo* getTimeInfo() const; | |||||
const CarlaEngineTimeInfo* getTimeInfo() const; | |||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
// Information (audio peaks) | // Information (audio peaks) | ||||
@@ -293,6 +637,18 @@ public: | |||||
const char* getLastError() const; | const char* getLastError() const; | ||||
void setLastError(const char* const error); | 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 | // Mutex locks | ||||
@@ -333,8 +689,8 @@ public: | |||||
void osc_send_bridge_set_midi_program(const int32_t index); | void osc_send_bridge_set_midi_program(const int32_t index); | ||||
void osc_send_bridge_set_custom_data(const char* const stype, const char* const key, const char* const value); | 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_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 | #else | ||||
void osc_send_control_add_plugin_start(const int32_t pluginId, const char* const pluginName); | void osc_send_control_add_plugin_start(const int32_t pluginId, const char* const pluginName); | ||||
void osc_send_control_add_plugin_end(const int32_t pluginId); | void osc_send_control_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_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_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_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(); | void osc_send_control_exit(); | ||||
#endif | #endif | ||||
@@ -392,35 +748,35 @@ public: | |||||
* \param lock Wherever to lock the engine or not, true by default | * \param lock Wherever to lock the engine or not, true by default | ||||
*/ | */ | ||||
ScopedLocker(CarlaEngine* const engine, bool lock = true) | ScopedLocker(CarlaEngine* const engine, bool lock = true) | ||||
: m_engine(engine), | |||||
: mutex(&engine->m_procLock), | |||||
m_lock(lock) | m_lock(lock) | ||||
{ | { | ||||
if (m_lock) | if (m_lock) | ||||
m_engine->processLock(); | |||||
mutex->lock(); | |||||
} | } | ||||
~ScopedLocker() | ~ScopedLocker() | ||||
{ | { | ||||
if (m_lock) | if (m_lock) | ||||
m_engine->processUnlock(); | |||||
mutex->unlock(); | |||||
} | } | ||||
private: | private: | ||||
CarlaEngine* const m_engine; | |||||
QMutex* const mutex; | |||||
const bool m_lock; | const bool m_lock; | ||||
}; | }; | ||||
// ------------------------------------- | // ------------------------------------- | ||||
protected: | protected: | ||||
CarlaEngineType type; | |||||
const char* name; | |||||
CarlaEngineOptions options; | |||||
CarlaString name; | |||||
uint32_t bufferSize; | uint32_t bufferSize; | ||||
double sampleRate; | double sampleRate; | ||||
CarlaTimeInfo timeInfo; | |||||
CarlaEngineTimeInfo timeInfo; | |||||
void bufferSizeChanged(const uint32_t newBufferSize); | void bufferSizeChanged(const uint32_t newBufferSize); | ||||
void startCheckThread(); | |||||
private: | private: | ||||
CarlaEngineThread m_thread; | CarlaEngineThread m_thread; | ||||
@@ -433,7 +789,7 @@ private: | |||||
CallbackFunc m_callback; | CallbackFunc m_callback; | ||||
void* m_callbackPtr; | void* m_callbackPtr; | ||||
carla_string m_lastError; | |||||
CarlaString m_lastError; | |||||
QMutex m_procLock; | QMutex m_procLock; | ||||
QMutex m_midiLock; | QMutex m_midiLock; | ||||
@@ -444,104 +800,29 @@ private: | |||||
double m_insPeak[MAX_PLUGINS * MAX_PEAKS]; | double m_insPeak[MAX_PLUGINS * MAX_PEAKS]; | ||||
double m_outsPeak[MAX_PLUGINS * MAX_PEAKS]; | double m_outsPeak[MAX_PLUGINS * MAX_PEAKS]; | ||||
static unsigned short m_maxPluginNumber; | |||||
unsigned short m_maxPluginNumber; | |||||
#ifdef CARLA_ENGINE_JACK | #ifdef CARLA_ENGINE_JACK | ||||
static CarlaEngine* newJack(); | static CarlaEngine* newJack(); | ||||
#endif | #endif | ||||
#ifdef CARLA_ENGINE_RTAUDIO | #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 | #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_osc.cpp \ | ||||
carla_engine_thread.cpp \ | carla_engine_thread.cpp \ | ||||
jack.cpp \ | jack.cpp \ | ||||
rtaudio.cpp | |||||
rtaudio.cpp \ | |||||
plugin.cpp | |||||
HEADERS = \ | HEADERS = \ | ||||
carla_engine.hpp \ | carla_engine.hpp \ | ||||
@@ -48,4 +49,7 @@ INCLUDEPATH += rtmidi-2.0.1 | |||||
SOURCES += rtaudio-4.0.11/RtAudio.cpp | SOURCES += rtaudio-4.0.11/RtAudio.cpp | ||||
SOURCES += rtmidi-2.0.1/RtMidi.cpp | SOURCES += rtmidi-2.0.1/RtMidi.cpp | ||||
# Plugin | |||||
INCLUDEPATH += distrho-plugin-toolkit | |||||
QMAKE_CXXFLAGS *= -std=c++0x | QMAKE_CXXFLAGS *= -std=c++0x |
@@ -1,5 +1,5 @@ | |||||
/* | /* | ||||
* Carla Engine | |||||
* Carla Engine OSC | |||||
* Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com> | * Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com> | ||||
* | * | ||||
* This program is free software; you can redistribute it and/or modify | * This program is free software; you can redistribute it and/or modify | ||||
@@ -40,8 +40,6 @@ CarlaEngineOsc::CarlaEngineOsc(CarlaEngine* const engine_) | |||||
m_serverTCP = nullptr; | m_serverTCP = nullptr; | ||||
m_serverUDP = nullptr; | m_serverUDP = nullptr; | ||||
m_serverPathTCP = nullptr; | |||||
m_serverPathUDP = nullptr; | |||||
m_controlData.path = nullptr; | m_controlData.path = nullptr; | ||||
m_controlData.source = nullptr; | m_controlData.source = nullptr; | ||||
m_controlData.target = nullptr; | m_controlData.target = nullptr; | ||||
@@ -60,28 +58,30 @@ void CarlaEngineOsc::init(const char* const name) | |||||
qDebug("CarlaEngineOsc::init(\"%s\")", name); | qDebug("CarlaEngineOsc::init(\"%s\")", name); | ||||
CARLA_ASSERT(! m_serverTCP); | CARLA_ASSERT(! m_serverTCP); | ||||
CARLA_ASSERT(! m_serverUDP); | 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(m_nameSize == 0); | ||||
CARLA_ASSERT(name); | |||||
m_name = strdup(name ? name : ""); | m_name = strdup(name ? name : ""); | ||||
m_nameSize = strlen(m_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_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); | 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); | 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); | free(serverPathTCP); | ||||
char* const serverPathUDP = lo_server_get_url(m_serverUDP); | 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); | 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_serverTCP, nullptr, nullptr, osc_message_handler, this); | ||||
lo_server_add_method(m_serverUDP, 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()"); | qDebug("CarlaEngineOsc::close()"); | ||||
CARLA_ASSERT(m_serverTCP); | CARLA_ASSERT(m_serverTCP); | ||||
CARLA_ASSERT(m_serverUDP); | 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); | CARLA_ASSERT(m_name); | ||||
m_controlData.free(); | m_controlData.free(); | ||||
@@ -121,13 +121,10 @@ void CarlaEngineOsc::close() | |||||
lo_server_thread_free(m_serverTCP); | lo_server_thread_free(m_serverTCP); | ||||
lo_server_thread_free(m_serverUDP); | lo_server_thread_free(m_serverUDP); | ||||
free((void*)m_serverPathTCP); | |||||
free((void*)m_serverPathUDP); | |||||
m_serverTCP = nullptr; | m_serverTCP = nullptr; | ||||
m_serverUDP = nullptr; | m_serverUDP = nullptr; | ||||
m_serverPathTCP = nullptr; | |||||
m_serverPathUDP = nullptr; | |||||
m_serverPathTCP.clear(); | |||||
m_serverPathUDP.clear(); | |||||
free(m_name); | free(m_name); | ||||
m_name = nullptr; | 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); | qDebug("CarlaEngineOsc::handleMessage(%s, %i, %p, %s, %p)", path, argc, argv, types, msg); | ||||
#endif | #endif | ||||
CARLA_ASSERT(m_serverTCP || m_serverUDP); | 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); | CARLA_ASSERT(path); | ||||
if (! 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])) | if (std::isdigit(path[m_nameSize+3])) | ||||
pluginId += (path[m_nameSize+3]-'0')*10; | 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); | qCritical("CarlaEngineOsc::handleMessage() - failed to get plugin, wrong id '%i'", pluginId); | ||||
return 1; | return 1; | ||||
@@ -334,8 +332,7 @@ int CarlaEngineOsc::handleMsgRegister(const int argc, const lo_arg* const* const | |||||
free((void*)host); | free((void*)host); | ||||
free((void*)port); | 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); | 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 | * This program is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
@@ -22,7 +22,7 @@ | |||||
#include "carla_osc_utils.hpp" | #include "carla_osc_utils.hpp" | ||||
#define CARLA_ENGINE_OSC_HANDLE_ARGS1 CarlaPlugin* const plugin | #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) \ | #define CARLA_ENGINE_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ | ||||
/* check argument count */ \ | /* check argument count */ \ | ||||
@@ -91,8 +91,8 @@ private: | |||||
lo_server m_serverTCP; | lo_server m_serverTCP; | ||||
lo_server m_serverUDP; | lo_server m_serverUDP; | ||||
const char* m_serverPathTCP; | |||||
const char* m_serverPathUDP; | |||||
CarlaString m_serverPathTCP; | |||||
CarlaString m_serverPathUDP; | |||||
CarlaOscData m_controlData; // for carla-control | CarlaOscData m_controlData; // for carla-control | ||||
char* m_name; | char* m_name; | ||||
@@ -1,5 +1,5 @@ | |||||
/* | /* | ||||
* Carla Engine | |||||
* Carla Engine Thread | |||||
* Copyright (C) 2012 Filipe Coelho <falktx@falktx.com> | * Copyright (C) 2012 Filipe Coelho <falktx@falktx.com> | ||||
* | * | ||||
* This program is free software; you can redistribute it and/or modify | * This program is free software; you can redistribute it and/or modify | ||||
@@ -80,7 +80,7 @@ void CarlaEngineThread::run() | |||||
const ScopedLocker m(this); | const ScopedLocker m(this); | ||||
oscControlRegisted = engine->isOscControlRegisted(); | 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); | CarlaPlugin* const plugin = engine->getPluginUnchecked(i); | ||||
@@ -124,7 +124,7 @@ void CarlaEngineThread::run() | |||||
} | } | ||||
// ------------------------------------------------------- | // ------------------------------------------------------- | ||||
// Update OSC control client | |||||
// Update OSC control client (peaks) | |||||
if (oscControlRegisted) | if (oscControlRegisted) | ||||
{ | { | ||||
@@ -132,21 +132,21 @@ void CarlaEngineThread::run() | |||||
if (plugin->audioInCount() > 0) | if (plugin->audioInCount() > 0) | ||||
{ | { | ||||
#ifdef BUILD_BRIDGE | #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 | #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 | #endif | ||||
} | } | ||||
if (plugin->audioOutCount() > 0) | if (plugin->audioOutCount() > 0) | ||||
{ | { | ||||
#ifdef BUILD_BRIDGE | #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 | #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 | #endif | ||||
} | } | ||||
} | } | ||||
@@ -154,7 +154,7 @@ void CarlaEngineThread::run() | |||||
} | } | ||||
if (! engine->idleOsc()) | 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> | * Copyright (C) 2012 Filipe Coelho <falktx@falktx.com> | ||||
* | * | ||||
* This program is free software; you can redistribute it and/or modify | * This program is free software; you can redistribute it and/or modify | ||||
@@ -36,9 +36,13 @@ public: | |||||
void startNow(); | void startNow(); | ||||
void stopNow(); | void stopNow(); | ||||
// ---------------------------------------------- | |||||
protected: | protected: | ||||
void run(); | void run(); | ||||
// ---------------------------------------------- | |||||
private: | private: | ||||
CarlaEngine* const engine; | CarlaEngine* const engine; | ||||
@@ -24,37 +24,385 @@ | |||||
CARLA_BACKEND_START_NAMESPACE | 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 | class CarlaEngineJack : public CarlaEngine | ||||
{ | { | ||||
@@ -62,26 +410,24 @@ public: | |||||
CarlaEngineJack() | CarlaEngineJack() | ||||
: CarlaEngine() | : CarlaEngine() | ||||
#ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
# ifdef Q_COMPILER_INITIALIZER_LISTS | |||||
# ifdef Q_COMPILER_INITIALIZER_LISTS | |||||
, rackJackPorts{nullptr} | , rackJackPorts{nullptr} | ||||
# endif | |||||
# endif | |||||
#endif | #endif | ||||
{ | { | ||||
qDebug("CarlaEngineJack::CarlaEngineJack()"); | qDebug("CarlaEngineJack::CarlaEngineJack()"); | ||||
type = CarlaEngineTypeJack; | |||||
client = nullptr; | |||||
state = JackTransportStopped; | |||||
freewheel = false; | |||||
globalClient = nullptr; | |||||
state = JackTransportStopped; | |||||
freewheel = false; | |||||
memset(&pos, 0, sizeof(jack_position_t)); | memset(&pos, 0, sizeof(jack_position_t)); | ||||
#ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
# ifndef Q_COMPILER_INITIALIZER_LISTS | |||||
# ifndef Q_COMPILER_INITIALIZER_LISTS | |||||
for (unsigned short i=0; i < rackPortCount; i++) | for (unsigned short i=0; i < rackPortCount; i++) | ||||
rackJackPorts[i] = nullptr; | rackJackPorts[i] = nullptr; | ||||
# endif | |||||
# endif | |||||
#endif | #endif | ||||
} | } | ||||
@@ -100,42 +446,43 @@ public: | |||||
state = JackTransportStopped; | state = JackTransportStopped; | ||||
#ifndef BUILD_BRIDGE | #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); | CarlaEngine::init(name); | ||||
return true; | return true; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
setLastError("Failed to activate the JACK client"); | setLastError("Failed to activate the JACK client"); | ||||
client = nullptr; | |||||
globalClient = nullptr; | |||||
} | } | ||||
} | } | ||||
else | else | ||||
@@ -143,7 +490,9 @@ public: | |||||
return false; | return false; | ||||
#else | #else | ||||
name = getFixedClientName(clientName); | |||||
name = clientName; | |||||
name.toBasic(); | |||||
CarlaEngine::init(name); | CarlaEngine::init(name); | ||||
return true; | return true; | ||||
#endif | #endif | ||||
@@ -154,33 +503,27 @@ public: | |||||
qDebug("CarlaEngineJack::close()"); | qDebug("CarlaEngineJack::close()"); | ||||
CarlaEngine::close(); | CarlaEngine::close(); | ||||
if (name) | |||||
{ | |||||
free((void*)name); | |||||
name = nullptr; | |||||
} | |||||
#ifdef BUILD_BRIDGE | #ifdef BUILD_BRIDGE | ||||
client = nullptr; | |||||
globalClient = nullptr; | |||||
return true; | return true; | ||||
#else | #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; | return true; | ||||
} | } | ||||
else | else | ||||
@@ -189,28 +532,32 @@ public: | |||||
else | else | ||||
setLastError("Failed to deactivate the JACK client"); | setLastError("Failed to deactivate the JACK client"); | ||||
client = nullptr; | |||||
globalClient = nullptr; | |||||
#endif | #endif | ||||
return false; | return false; | ||||
} | } | ||||
bool isOffline() | |||||
bool isOffline() const | |||||
{ | { | ||||
return freewheel; | return freewheel; | ||||
} | } | ||||
bool isRunning() | |||||
bool isRunning() const | |||||
{ | |||||
return bool(globalClient); | |||||
} | |||||
CarlaEngineType type() const | |||||
{ | { | ||||
return bool(client); | |||||
return CarlaEngineTypeJack; | |||||
} | } | ||||
CarlaEngineClient* addClient(CarlaPlugin* const plugin) | CarlaEngineClient* addClient(CarlaPlugin* const plugin) | ||||
{ | { | ||||
CarlaEngineClientNativeHandle* handle = new CarlaEngineClientNativeHandle; | |||||
handle->type = CarlaEngineTypeJack; | |||||
jack_client_t* client = nullptr; | |||||
#ifdef BUILD_BRIDGE | #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); | sampleRate = jackbridge_get_sample_rate(client); | ||||
bufferSize = jackbridge_get_buffer_size(client); | bufferSize = jackbridge_get_buffer_size(client); | ||||
@@ -222,19 +569,19 @@ public: | |||||
jackbridge_set_latency_callback(handle.jackClient, carla_jack_latency_callback, this); | jackbridge_set_latency_callback(handle.jackClient, carla_jack_latency_callback, this); | ||||
jackbridge_on_shutdown(client, carla_jack_shutdown_callback, this); | jackbridge_on_shutdown(client, carla_jack_shutdown_callback, this); | ||||
#else | #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 | #endif | ||||
return new CarlaEngineClient(handle); | |||||
return new CarlaEngineJackClient(client, CarlaEngineTypeJack, options.processMode); | |||||
} | } | ||||
// ------------------------------------- | // ------------------------------------- | ||||
@@ -266,7 +613,7 @@ protected: | |||||
if (maxPluginNumber() == 0) | if (maxPluginNumber() == 0) | ||||
return; | return; | ||||
#endif | #endif | ||||
state = jackbridge_transport_query(client, &pos); | |||||
state = jackbridge_transport_query(globalClient, &pos); | |||||
timeInfo.playing = (state != JackTransportStopped); | timeInfo.playing = (state != JackTransportStopped); | ||||
@@ -297,7 +644,7 @@ protected: | |||||
} | } | ||||
#ifndef BUILD_BRIDGE | #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++) | for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | ||||
{ | { | ||||
@@ -319,7 +666,7 @@ protected: | |||||
plugin->engineProcessUnlock(); | plugin->engineProcessUnlock(); | ||||
} | } | ||||
} | } | ||||
else if (processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||||
else if (options.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||||
{ | { | ||||
// get buffers from jack | // get buffers from jack | ||||
float* audioIn1 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioIn1], nframes); | float* audioIn1 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioIn1], nframes); | ||||
@@ -373,21 +720,21 @@ protected: | |||||
if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) | if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) | ||||
{ | { | ||||
uint8_t midiBank = jackEvent.buffer[2]; | uint8_t midiBank = jackEvent.buffer[2]; | ||||
carlaEvent->type = CarlaEngineEventMidiBankChange; | |||||
carlaEvent->type = CarlaEngineMidiBankChangeEvent; | |||||
carlaEvent->value = midiBank; | carlaEvent->value = midiBank; | ||||
} | } | ||||
else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) | else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) | ||||
{ | { | ||||
carlaEvent->type = CarlaEngineEventAllSoundOff; | |||||
carlaEvent->type = CarlaEngineAllSoundOffEvent; | |||||
} | } | ||||
else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) | else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) | ||||
{ | { | ||||
carlaEvent->type = CarlaEngineEventAllNotesOff; | |||||
carlaEvent->type = CarlaEngineAllNotesOffEvent; | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
uint8_t midiValue = jackEvent.buffer[2]; | uint8_t midiValue = jackEvent.buffer[2]; | ||||
carlaEvent->type = CarlaEngineEventControlChange; | |||||
carlaEvent->type = CarlaEngineParameterChangeEvent; | |||||
carlaEvent->controller = midiControl; | carlaEvent->controller = midiControl; | ||||
carlaEvent->value = double(midiValue)/127; | carlaEvent->value = double(midiValue)/127; | ||||
} | } | ||||
@@ -395,7 +742,7 @@ protected: | |||||
else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus)) | else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus)) | ||||
{ | { | ||||
uint8_t midiProgram = jackEvent.buffer[1]; | uint8_t midiProgram = jackEvent.buffer[1]; | ||||
carlaEvent->type = CarlaEngineEventMidiProgramChange; | |||||
carlaEvent->type = CarlaEngineMidiProgramChangeEvent; | |||||
carlaEvent->value = midiProgram; | carlaEvent->value = midiProgram; | ||||
} | } | ||||
} | } | ||||
@@ -433,38 +780,38 @@ protected: | |||||
{ | { | ||||
CarlaEngineControlEvent* const event = &rackControlEventsOut[i]; | 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 }; | uint8_t data[4] = { 0 }; | ||||
switch (event->type) | switch (event->type) | ||||
{ | { | ||||
case CarlaEngineEventNull: | |||||
case CarlaEngineNullEvent: | |||||
break; | break; | ||||
case CarlaEngineEventControlChange: | |||||
case CarlaEngineParameterChangeEvent: | |||||
data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | ||||
data[1] = event->controller; | data[1] = event->controller; | ||||
data[2] = event->value * 127; | data[2] = event->value * 127; | ||||
jackbridge_midi_event_write(controlOut, event->time, data, 3); | jackbridge_midi_event_write(controlOut, event->time, data, 3); | ||||
break; | break; | ||||
case CarlaEngineEventMidiBankChange: | |||||
case CarlaEngineMidiBankChangeEvent: | |||||
data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | ||||
data[1] = MIDI_CONTROL_BANK_SELECT; | data[1] = MIDI_CONTROL_BANK_SELECT; | ||||
data[2] = event->value; | data[2] = event->value; | ||||
jackbridge_midi_event_write(controlOut, event->time, data, 3); | jackbridge_midi_event_write(controlOut, event->time, data, 3); | ||||
break; | break; | ||||
case CarlaEngineEventMidiProgramChange: | |||||
case CarlaEngineMidiProgramChangeEvent: | |||||
data[0] = MIDI_STATUS_PROGRAM_CHANGE + event->channel; | data[0] = MIDI_STATUS_PROGRAM_CHANGE + event->channel; | ||||
data[1] = event->value; | data[1] = event->value; | ||||
jackbridge_midi_event_write(controlOut, event->time, data, 2); | jackbridge_midi_event_write(controlOut, event->time, data, 2); | ||||
break; | break; | ||||
case CarlaEngineEventAllSoundOff: | |||||
case CarlaEngineAllSoundOffEvent: | |||||
data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | ||||
data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | ||||
jackbridge_midi_event_write(controlOut, event->time, data, 2); | jackbridge_midi_event_write(controlOut, event->time, data, 2); | ||||
break; | break; | ||||
case CarlaEngineEventAllNotesOff: | |||||
case CarlaEngineAllNotesOffEvent: | |||||
data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | ||||
data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | ||||
jackbridge_midi_event_write(controlOut, event->time, data, 2); | jackbridge_midi_event_write(controlOut, event->time, data, 2); | ||||
@@ -509,7 +856,7 @@ protected: | |||||
void handleLatencyCallback(jack_latency_callback_mode_t mode) | void handleLatencyCallback(jack_latency_callback_mode_t mode) | ||||
{ | { | ||||
#ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
if (processMode != PROCESS_MODE_SINGLE_CLIENT) | |||||
if (options.processMode != PROCESS_MODE_SINGLE_CLIENT) | |||||
return; | return; | ||||
#endif | #endif | ||||
@@ -532,14 +879,14 @@ protected: | |||||
plugin->x_client = nullptr; | plugin->x_client = nullptr; | ||||
} | } | ||||
client = nullptr; | |||||
globalClient = nullptr; | |||||
callback(CALLBACK_QUIT, 0, 0, 0, 0.0); | callback(CALLBACK_QUIT, 0, 0, 0, 0.0); | ||||
} | } | ||||
// ------------------------------------- | // ------------------------------------- | ||||
private: | private: | ||||
jack_client_t* client; | |||||
jack_client_t* globalClient; | |||||
jack_transport_state_t state; | jack_transport_state_t state; | ||||
jack_position_t pos; | jack_position_t pos; | ||||
bool freewheel; | bool freewheel; | ||||
@@ -567,11 +914,13 @@ private: | |||||
float* inBuffer[p->aIn.count]; | float* inBuffer[p->aIn.count]; | ||||
float* outBuffer[p->aOut.count]; | float* outBuffer[p->aOut.count]; | ||||
#if 0 | |||||
for (uint32_t i=0; i < p->aIn.count; i++) | 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++) | 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 | #ifndef BUILD_BRIDGE | ||||
if (/*options.processHighPrecision*/ 0) | if (/*options.processHighPrecision*/ 0) | ||||
@@ -597,11 +946,15 @@ private: | |||||
static void processPluginNOT(CarlaPlugin* const p, const uint32_t nframes) | 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++) | 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) | 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++) | for (uint32_t i=0; i < p->aIn.count; i++) | ||||
{ | { | ||||
uint aOutI = (i >= p->aOut.count) ? p->aOut.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); | jackbridge_port_get_latency_range(portIn, mode, &range); | ||||
range.min += pluginLatency; | range.min += pluginLatency; | ||||
@@ -631,8 +984,8 @@ private: | |||||
for (uint32_t i=0; i < p->aOut.count; i++) | for (uint32_t i=0; i < p->aOut.count; i++) | ||||
{ | { | ||||
uint aInI = (i >= p->aIn.count) ? p->aIn.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); | jackbridge_port_get_latency_range(portOut, mode, &range); | ||||
range.min += pluginLatency; | range.min += pluginLatency; | ||||
@@ -39,6 +39,42 @@ static const unsigned int paramPan = 8; | |||||
static const unsigned int paramCount = sizeof(paramMap); | static const unsigned int paramCount = sizeof(paramMap); | ||||
static const unsigned int programCount = 128; | 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, | class CarlaEnginePlugin : public CarlaEngine, | ||||
@@ -64,7 +100,7 @@ public: | |||||
memcpy(prevParamBuffers, paramBuffers, sizeof(float)*paramCount); | memcpy(prevParamBuffers, paramBuffers, sizeof(float)*paramCount); | ||||
// set-up engine | // set-up engine | ||||
processMode = PROCESS_MODE_CONTINUOUS_RACK; | |||||
options.processMode = PROCESS_MODE_CONTINUOUS_RACK; | |||||
options.forceStereo = true; | options.forceStereo = true; | ||||
options.preferPluginBridges = false; | options.preferPluginBridges = false; | ||||
options.preferUiBridges = false; | options.preferUiBridges = false; | ||||
@@ -96,9 +132,10 @@ public: | |||||
bufferSize = d_bufferSize(); | bufferSize = d_bufferSize(); | ||||
sampleRate = d_sampleRate(); | sampleRate = d_sampleRate(); | ||||
name = strdup(clientName); | |||||
CarlaEngine::init(name); | |||||
name = clientName; | |||||
name.toBasic(); | |||||
CarlaEngine::init(name); | |||||
return true; | return true; | ||||
} | } | ||||
@@ -107,32 +144,27 @@ public: | |||||
qDebug("CarlaEnginePlugin::close()"); | qDebug("CarlaEnginePlugin::close()"); | ||||
CarlaEngine::close(); | CarlaEngine::close(); | ||||
if (name) | |||||
{ | |||||
free((void*)name); | |||||
name = nullptr; | |||||
} | |||||
return true; | return true; | ||||
} | } | ||||
bool isOffline() | |||||
bool isOffline() const | |||||
{ | { | ||||
return false; | return false; | ||||
} | } | ||||
bool isRunning() | |||||
bool isRunning() const | |||||
{ | { | ||||
return true; | 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: | protected: | ||||
@@ -441,7 +473,7 @@ protected: | |||||
CarlaEngineControlEvent* const carlaEvent = &rackControlEventsIn[carlaEventIndex++]; | CarlaEngineControlEvent* const carlaEvent = &rackControlEventsIn[carlaEventIndex++]; | ||||
carlaEvent->type = CarlaEngineEventControlChange; | |||||
carlaEvent->type = CarlaEngineParameterChangeEvent; | |||||
carlaEvent->controller = paramMap[i]; | carlaEvent->controller = paramMap[i]; | ||||
carlaEvent->value = paramBuffers[i]/127; | carlaEvent->value = paramBuffers[i]/127; | ||||
} | } | ||||
@@ -25,22 +25,44 @@ | |||||
CARLA_BACKEND_START_NAMESPACE | 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 | class CarlaEngineRtAudio : public CarlaEngine | ||||
{ | { | ||||
@@ -51,14 +73,12 @@ public: | |||||
{ | { | ||||
qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()"); | qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()"); | ||||
type = CarlaEngineTypeRtAudio; | |||||
midiIn = nullptr; | midiIn = nullptr; | ||||
midiOut = nullptr; | midiOut = nullptr; | ||||
// just to make sure | // just to make sure | ||||
options.forceStereo = true; | options.forceStereo = true; | ||||
processMode = PROCESS_MODE_CONTINUOUS_RACK; | |||||
options.processMode = PROCESS_MODE_CONTINUOUS_RACK; | |||||
} | } | ||||
~CarlaEngineRtAudio() | ~CarlaEngineRtAudio() | ||||
@@ -118,7 +138,9 @@ public: | |||||
midiOut->openVirtualPort("control-out"); | midiOut->openVirtualPort("control-out"); | ||||
midiOut->openVirtualPort("midi-out"); | midiOut->openVirtualPort("midi-out"); | ||||
name = getFixedClientName(clientName); | |||||
name = clientName; | |||||
name.toBasic(); | |||||
CarlaEngine::init(name); | CarlaEngine::init(name); | ||||
return true; | return true; | ||||
} | } | ||||
@@ -128,12 +150,6 @@ public: | |||||
qDebug("CarlaEngineRtAudio::close()"); | qDebug("CarlaEngineRtAudio::close()"); | ||||
CarlaEngine::close(); | CarlaEngine::close(); | ||||
if (name) | |||||
{ | |||||
free((void*)name); | |||||
name = nullptr; | |||||
} | |||||
if (audio.isStreamRunning()) | if (audio.isStreamRunning()) | ||||
audio.stopStream(); | audio.stopStream(); | ||||
@@ -158,22 +174,24 @@ public: | |||||
return true; | return true; | ||||
} | } | ||||
bool isOffline() | |||||
bool isOffline() const | |||||
{ | { | ||||
return false; | return false; | ||||
} | } | ||||
bool isRunning() | |||||
bool isRunning() const | |||||
{ | { | ||||
return audio.isStreamRunning(); | 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) | 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 | CARLA_BACKEND_END_NAMESPACE | ||||
@@ -740,7 +740,7 @@ public: | |||||
/*! | /*! | ||||
* Process all the post-poned events. | * 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(); | void postEventsRun(); | ||||
@@ -847,7 +847,7 @@ public: | |||||
#endif | #endif | ||||
static size_t getNativePluginCount(); | 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; | return value; | ||||
} | } | ||||
static double abs(const double& value) | |||||
{ | |||||
return (value < 0.0) ? -value : value; | |||||
} | |||||
friend class CarlaEngineJack; | friend class CarlaEngineJack; | ||||
}; | }; | ||||
@@ -121,30 +121,30 @@ static inline | |||||
void pass() {} | void pass() {} | ||||
// ------------------------------------------------- | // ------------------------------------------------- | ||||
// carla_string class | |||||
// CarlaString class | |||||
class carla_string | |||||
class CarlaString | |||||
{ | { | ||||
public: | public: | ||||
// --------------------------------------------- | // --------------------------------------------- | ||||
// constructors (no explicit conversions allowed) | // constructors (no explicit conversions allowed) | ||||
explicit carla_string() | |||||
explicit CarlaString() | |||||
{ | { | ||||
buffer = ::strdup(""); | buffer = ::strdup(""); | ||||
} | } | ||||
explicit carla_string(char* const strBuf) | |||||
explicit CarlaString(char* const strBuf) | |||||
{ | { | ||||
buffer = ::strdup(strBuf ? strBuf : ""); | buffer = ::strdup(strBuf ? strBuf : ""); | ||||
} | } | ||||
explicit carla_string(const char* const strBuf) | |||||
explicit CarlaString(const char* const strBuf) | |||||
{ | { | ||||
buffer = ::strdup(strBuf ? strBuf : ""); | buffer = ::strdup(strBuf ? strBuf : ""); | ||||
} | } | ||||
explicit carla_string(const int value) | |||||
explicit CarlaString(const int value) | |||||
{ | { | ||||
const size_t strBufSize = ::abs(value/10) + 3; | const size_t strBufSize = ::abs(value/10) + 3; | ||||
char strBuf[strBufSize]; | char strBuf[strBufSize]; | ||||
@@ -153,7 +153,7 @@ public: | |||||
buffer = ::strdup(strBuf); | 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); | const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0); | ||||
char strBuf[strBufSize]; | char strBuf[strBufSize]; | ||||
@@ -162,7 +162,7 @@ public: | |||||
buffer = ::strdup(strBuf); | buffer = ::strdup(strBuf); | ||||
} | } | ||||
explicit carla_string(const long int value) | |||||
explicit CarlaString(const long int value) | |||||
{ | { | ||||
const size_t strBufSize = ::labs(value/10) + 3; | const size_t strBufSize = ::labs(value/10) + 3; | ||||
char strBuf[strBufSize]; | char strBuf[strBufSize]; | ||||
@@ -171,7 +171,7 @@ public: | |||||
buffer = ::strdup(strBuf); | 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); | const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0); | ||||
char strBuf[strBufSize]; | char strBuf[strBufSize]; | ||||
@@ -180,7 +180,7 @@ public: | |||||
buffer = ::strdup(strBuf); | buffer = ::strdup(strBuf); | ||||
} | } | ||||
explicit carla_string(const float value) | |||||
explicit CarlaString(const float value) | |||||
{ | { | ||||
char strBuf[0xff]; | char strBuf[0xff]; | ||||
::snprintf(strBuf, 0xff, "%f", value); | ::snprintf(strBuf, 0xff, "%f", value); | ||||
@@ -188,7 +188,7 @@ public: | |||||
buffer = ::strdup(strBuf); | buffer = ::strdup(strBuf); | ||||
} | } | ||||
explicit carla_string(const double value) | |||||
explicit CarlaString(const double value) | |||||
{ | { | ||||
char strBuf[0xff]; | char strBuf[0xff]; | ||||
::snprintf(strBuf, 0xff, "%g", value); | ::snprintf(strBuf, 0xff, "%g", value); | ||||
@@ -199,7 +199,7 @@ public: | |||||
// --------------------------------------------- | // --------------------------------------------- | ||||
// non-explicit constructor | // non-explicit constructor | ||||
carla_string(const carla_string& str) | |||||
CarlaString(const CarlaString& str) | |||||
{ | { | ||||
buffer = ::strdup(str.buffer); | buffer = ::strdup(str.buffer); | ||||
} | } | ||||
@@ -207,7 +207,7 @@ public: | |||||
// --------------------------------------------- | // --------------------------------------------- | ||||
// deconstructor | // deconstructor | ||||
~carla_string() | |||||
~CarlaString() | |||||
{ | { | ||||
::free(buffer); | ::free(buffer); | ||||
} | } | ||||
@@ -225,6 +225,11 @@ public: | |||||
return (*buffer == 0); | return (*buffer == 0); | ||||
} | } | ||||
bool isNotEmpty() const | |||||
{ | |||||
return !isEmpty(); | |||||
} | |||||
bool contains(const char* const strBuf) const | bool contains(const char* const strBuf) const | ||||
{ | { | ||||
if (! strBuf) | if (! strBuf) | ||||
@@ -249,11 +254,51 @@ public: | |||||
return false; | return false; | ||||
} | } | ||||
bool contains(const carla_string& str) const | |||||
bool contains(const CarlaString& str) const | |||||
{ | { | ||||
return contains(str.buffer); | 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() | void toLower() | ||||
{ | { | ||||
for (size_t i=0, len = ::strlen(buffer); i < len; i++) | for (size_t i=0, len = ::strlen(buffer); i < len; i++) | ||||
@@ -280,12 +325,17 @@ public: | |||||
return buffer; | return buffer; | ||||
} | } | ||||
char& operator[](int pos) | |||||
{ | |||||
return buffer[pos]; | |||||
} | |||||
bool operator==(const char* const strBuf) const | bool operator==(const char* const strBuf) const | ||||
{ | { | ||||
return (strBuf && ::strcmp(buffer, strBuf) == 0); | return (strBuf && ::strcmp(buffer, strBuf) == 0); | ||||
} | } | ||||
bool operator==(const carla_string& str) const | |||||
bool operator==(const CarlaString& str) const | |||||
{ | { | ||||
return operator==(str.buffer); | return operator==(str.buffer); | ||||
} | } | ||||
@@ -295,12 +345,12 @@ public: | |||||
return !operator==(strBuf); | return !operator==(strBuf); | ||||
} | } | ||||
bool operator!=(const carla_string& str) const | |||||
bool operator!=(const CarlaString& str) const | |||||
{ | { | ||||
return !operator==(str.buffer); | return !operator==(str.buffer); | ||||
} | } | ||||
carla_string& operator=(const char* const strBuf) | |||||
CarlaString& operator=(const char* const strBuf) | |||||
{ | { | ||||
::free(buffer); | ::free(buffer); | ||||
@@ -309,12 +359,12 @@ public: | |||||
return *this; | return *this; | ||||
} | } | ||||
carla_string& operator=(const carla_string& str) | |||||
CarlaString& operator=(const CarlaString& str) | |||||
{ | { | ||||
return operator=(str.buffer); | 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; | const size_t newBufSize = ::strlen(buffer) + (strBuf ? ::strlen(strBuf) : 0) + 1; | ||||
char newBuf[newBufSize]; | char newBuf[newBufSize]; | ||||
@@ -328,12 +378,12 @@ public: | |||||
return *this; | return *this; | ||||
} | } | ||||
carla_string& operator+=(const carla_string& str) | |||||
CarlaString& operator+=(const CarlaString& str) | |||||
{ | { | ||||
return operator+=(str.buffer); | 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; | const size_t newBufSize = ::strlen(buffer) + (strBuf ? ::strlen(strBuf) : 0) + 1; | ||||
char newBuf[newBufSize]; | char newBuf[newBufSize]; | ||||
@@ -341,10 +391,10 @@ public: | |||||
::strcpy(newBuf, buffer); | ::strcpy(newBuf, buffer); | ||||
::strcat(newBuf, strBuf); | ::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); | return operator+(str.buffer); | ||||
} | } | ||||
@@ -356,7 +406,7 @@ private: | |||||
}; | }; | ||||
static inline | 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 char* const strBufAfter = (const char*)strAfter; | ||||
const size_t newBufSize = (strBufBefore ? ::strlen(strBufBefore) : 0) + ::strlen(strBufAfter) + 1; | 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); | ::strcpy(newBuf, strBufBefore); | ||||
::strcat(newBuf, strBufAfter); | ::strcat(newBuf, strBufAfter); | ||||
return carla_string(newBuf); | |||||
return CarlaString(newBuf); | |||||
} | } | ||||
// ------------------------------------------------- | // ------------------------------------------------- | ||||
@@ -201,11 +201,12 @@ CALLBACK_QUIT = 20 | |||||
PROCESS_MODE_SINGLE_CLIENT = 0 | PROCESS_MODE_SINGLE_CLIENT = 0 | ||||
PROCESS_MODE_MULTIPLE_CLIENTS = 1 | PROCESS_MODE_MULTIPLE_CLIENTS = 1 | ||||
PROCESS_MODE_CONTINUOUS_RACK = 2 | PROCESS_MODE_CONTINUOUS_RACK = 2 | ||||
PROCESS_MODE_PATCHBAY = 3 | |||||
# ------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------ | ||||
# Carla GUI stuff | # Carla GUI stuff | ||||
Carla.processMode = PROCESS_MODE_MULTIPLE_CLIENTS | |||||
Carla.processMode = PROCESS_MODE_CONTINUOUS_RACK | |||||
Carla.maxParameters = MAX_PARAMETERS | Carla.maxParameters = MAX_PARAMETERS | ||||
# set native binary type | # set native binary type | ||||