@@ -26,7 +26,7 @@ | |||
#define CARLA_BACKEND_END_NAMESPACE } | |||
#define CARLA_BACKEND_USE_NAMESPACE using namespace CarlaBackend; | |||
#define STR_MAX 0xFF+1 | |||
#define STR_MAX 0xFF | |||
CARLA_BACKEND_START_NAMESPACE | |||
@@ -40,7 +40,7 @@ CARLA_BACKEND_START_NAMESPACE | |||
const unsigned int MAX_DEFAULT_PLUGINS = 99; //!< Maximum default number of loadable plugins | |||
const unsigned int MAX_RACK_PLUGINS = 16; //!< Maximum number of loadable plugins in rack mode | |||
const unsigned int MAX_PATCHBAY_PLUGINS = 999; //!< Maximum number of loadable plugins in patchbay mode | |||
const unsigned int MAX_PATCHBAY_PLUGINS = 255; //!< Maximum number of loadable plugins in patchbay mode | |||
const unsigned int MAX_DEFAULT_PARAMETERS = 200; //!< Maximum default number of parameters allowed.\see OPTION_MAX_PARAMETERS | |||
/*! | |||
@@ -64,9 +64,8 @@ const unsigned int PLUGIN_CAN_PANNING = 0x800; //!< Plugin can make use of | |||
/*! | |||
* @defgroup PluginOptions Plugin Options | |||
* | |||
* Various plugin options.\n | |||
* ON or OFF defines the default plugin value. | |||
* \see CarlaPlugin::options() | |||
* Various plugin options. | |||
* \see CarlaPlugin::availableOptions() and CarlaPlugin::options() | |||
* @{ | |||
*/ | |||
const unsigned int PLUGIN_OPTION_FIXED_BUFFER = 0x001; //!< Use a constant, fixed-size audio buffer | |||
@@ -77,7 +76,7 @@ const unsigned int PLUGIN_OPTION_SEND_CONTROL_CHANGES = 0x010; //!< Send MIDI C | |||
const unsigned int PLUGIN_OPTION_SEND_CHANNEL_PRESSURE = 0x020; //!< Send MIDI channel pressure events | |||
const unsigned int PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH = 0x040; //!< Send MIDI note aftertouch events | |||
const unsigned int PLUGIN_OPTION_SEND_PITCHBEND = 0x080; //!< Send MIDI pitchbend events | |||
const unsigned int PLUGIN_OPTION_SEND_ALL_SOUND_OFF = 0x100; //!< Send MIDI ALL_SOUND_OFF / ALL_NOTES_OFF events | |||
const unsigned int PLUGIN_OPTION_SEND_ALL_SOUND_OFF = 0x100; //!< Send MIDI all sounds/notes off events, single-note offs otherwise | |||
/**@}*/ | |||
/*! | |||
@@ -87,13 +86,13 @@ const unsigned int PLUGIN_OPTION_SEND_ALL_SOUND_OFF = 0x100; //!< Send MIDI A | |||
* \see CarlaPlugin::parameterData() | |||
* @{ | |||
*/ | |||
const unsigned int PARAMETER_IS_BOOLEAN = 0x01; //!< Parameter value is always a boolean (always at minimum or maximum range). | |||
const unsigned int PARAMETER_IS_INTEGER = 0x02; //!< Parameter value is always an integer. | |||
const unsigned int PARAMETER_IS_BOOLEAN = 0x01; //!< Parameter value is a boolean (always at minimum or maximum values). | |||
const unsigned int PARAMETER_IS_INTEGER = 0x02; //!< Parameter value is an integer. | |||
const unsigned int PARAMETER_IS_LOGARITHMIC = 0x04; //!< Parameter is logarithmic. | |||
const unsigned int PARAMETER_IS_ENABLED = 0x08; //!< Parameter is enabled and will be shown in the host built-in editor. | |||
const unsigned int PARAMETER_IS_AUTOMABLE = 0x10; //!< Parameter is automable (realtime safe) | |||
const unsigned int PARAMETER_USES_SAMPLERATE = 0x20; //!< Parameter needs sample rate to work (value and ranges are multiplied by SR, and must be divided by SR on save). | |||
const unsigned int PARAMETER_USES_SCALEPOINTS = 0x40; //!< Parameter uses scalepoints to define internal values in a meaninful way. | |||
const unsigned int PARAMETER_USES_SCALEPOINTS = 0x40; //!< Parameter uses scalepoints to define internal values in a meaningful way. | |||
const unsigned int PARAMETER_USES_CUSTOM_TEXT = 0x80; //!< Parameter uses custom text for displaying its value.\see CarlaPlugin::getParameterText() | |||
/**@}*/ | |||
@@ -159,15 +158,15 @@ enum BinaryType { | |||
*/ | |||
enum PluginType { | |||
PLUGIN_NONE = 0, //!< Null plugin type. | |||
PLUGIN_INTERNAL = 1, //!< Internal plugin.\see NativePlugin | |||
PLUGIN_LADSPA = 2, //!< LADSPA plugin.\see LadspaPlugin | |||
PLUGIN_DSSI = 3, //!< DSSI plugin.\see DssiPlugin | |||
PLUGIN_LV2 = 4, //!< LV2 plugin.\see Lv2Plugin | |||
PLUGIN_VST = 5, //!< VST1/2 plugin.\see VstPlugin | |||
PLUGIN_VST3 = 6, //!< VST3 plugin.\see VstPlugin | |||
PLUGIN_GIG = 7, //!< GIG sound kit, implemented via LinuxSampler.\see LinuxSamplerPlugin | |||
PLUGIN_SF2 = 8, //!< SF2 sound kit (aka SoundFont), implemented via FluidSynth.\see FluidSynthPlugin | |||
PLUGIN_SFZ = 9 //!< SFZ sound kit, implemented via LinuxSampler.\see LinuxSamplerPlugin | |||
PLUGIN_INTERNAL = 1, //!< Internal plugin. | |||
PLUGIN_LADSPA = 2, //!< LADSPA plugin. | |||
PLUGIN_DSSI = 3, //!< DSSI plugin. | |||
PLUGIN_LV2 = 4, //!< LV2 plugin. | |||
PLUGIN_VST = 5, //!< VST1/2 plugin. | |||
PLUGIN_VST3 = 6, //!< VST3 plugin. | |||
PLUGIN_GIG = 7, //!< GIG sound kit, implemented via LinuxSampler. | |||
PLUGIN_SF2 = 8, //!< SF2 sound kit (aka SoundFont), implemented via FluidSynth. | |||
PLUGIN_SFZ = 9 //!< SFZ sound kit, implemented via LinuxSampler. | |||
}; | |||
/*! | |||
@@ -219,7 +218,7 @@ enum InternalParametersIndex { | |||
/*! | |||
* Options used in the CarlaEngine::setOption() and set_option() calls.\n | |||
* These options must be set before initiliazing or after closing the engine. | |||
* All options except paths must be set before initiliazing or after closing the engine. | |||
*/ | |||
enum OptionsType { | |||
/*! | |||
@@ -250,8 +249,7 @@ enum OptionsType { | |||
/*! | |||
* Use plugin bridges whenever possible.\n | |||
* Default is no, and not recommended at this point!. | |||
* EXPERIMENTAL AND INCOMPLETE! | |||
* Default is no, EXPERIMENTAL. | |||
*/ | |||
OPTION_PREFER_PLUGIN_BRIDGES = 4, | |||
@@ -391,8 +389,7 @@ enum OptionsType { | |||
/*! | |||
* Opcodes sent from the engine callback to the GUI, as defined by CallbackFunc. | |||
* | |||
* \see CarlaEngine::setCallback() | |||
* \see set_callback_function() | |||
* \see CarlaEngine::setCallback() and set_callback_function() | |||
*/ | |||
enum CallbackType { | |||
/*! | |||
@@ -403,6 +400,7 @@ enum CallbackType { | |||
/*! | |||
* A plugin has been added. | |||
* \param valueStr Plugin name | |||
*/ | |||
CALLBACK_PLUGIN_ADDED = 1, | |||
@@ -413,6 +411,7 @@ enum CallbackType { | |||
/*! | |||
* A plugin has been renamed. | |||
* \param valueStr New name | |||
*/ | |||
CALLBACK_PLUGIN_RENAMED = 3, | |||
@@ -425,10 +424,10 @@ enum CallbackType { | |||
CALLBACK_PARAMETER_VALUE_CHANGED = 4, | |||
/*! | |||
* A parameter default has been changed. | |||
* A parameter default has changed. | |||
* | |||
* \param value1 Parameter index | |||
* \param value3 Default value | |||
* \param value3 New default value | |||
*/ | |||
CALLBACK_PARAMETER_DEFAULT_CHANGED = 5, | |||
@@ -518,31 +517,32 @@ enum CallbackType { | |||
/*! | |||
* Canvas client added | |||
* | |||
* \param value1 Client ID | |||
* \param valueStr Client Name | |||
* \param value1 Client Id | |||
* \param valueStr Client name | |||
*/ | |||
CALLBACK_PATCHBAY_CLIENT_ADDED = 18, | |||
/*! | |||
* Canvas client removed | |||
* | |||
* \param value1 Client ID | |||
* \param value1 Client Id | |||
*/ | |||
CALLBACK_PATCHBAY_CLIENT_REMOVED = 19, | |||
/*! | |||
* Canvas client renamed | |||
* | |||
* \param value1 Client ID | |||
* \param valueStr New Client name | |||
* \param value1 Client Id | |||
* \param valueStr New client name | |||
*/ | |||
CALLBACK_PATCHBAY_CLIENT_RENAMED = 20, | |||
/*! | |||
* Canvas port added | |||
* | |||
* \param value1 Client ID | |||
* \param value2 Port ID | |||
* \param value1 Client Id | |||
* \param value2 Port Id | |||
* \param value3 Port flags | |||
* \param valueStr Port name | |||
*/ | |||
CALLBACK_PATCHBAY_PORT_ADDED = 21, | |||
@@ -550,31 +550,31 @@ enum CallbackType { | |||
/*! | |||
* Canvas port remvoed | |||
* | |||
* \param value1 Port ID | |||
* \param value1 Port Id | |||
*/ | |||
CALLBACK_PATCHBAY_PORT_REMOVED = 22, | |||
/*! | |||
* Canvas port renamed | |||
* | |||
* \param value1 Port ID | |||
* \param valueStr New Port name | |||
* \param value1 Port Id | |||
* \param valueStr New port name | |||
*/ | |||
CALLBACK_PATCHBAY_PORT_RENAMED = 23, | |||
/*! | |||
* Canvas port connection added | |||
* | |||
* \param value1 Output port ID | |||
* \param value2 Input port ID | |||
* \param value1 Output port Id | |||
* \param value2 Input port Id | |||
*/ | |||
CALLBACK_PATCHBAY_CONNECTION_ADDED = 24, | |||
/*! | |||
* Canvas port connection removed | |||
* | |||
* \param value1 Output port ID | |||
* \param value2 Input port ID | |||
* \param value1 Output port Id | |||
* \param value2 Input port Id | |||
*/ | |||
CALLBACK_PATCHBAY_CONNECTION_REMOVED = 25, | |||
@@ -617,7 +617,7 @@ enum CallbackType { | |||
enum ProcessMode { | |||
PROCESS_MODE_SINGLE_CLIENT = 0, //!< Single client mode (dynamic input/outputs as needed by plugins) | |||
PROCESS_MODE_MULTIPLE_CLIENTS = 1, //!< Multiple client mode (1 master client + 1 client per plugin) | |||
PROCESS_MODE_CONTINUOUS_RACK = 2, //!< Single client, 'rack' mode. Processes plugins in order of id, with forced stereo. | |||
PROCESS_MODE_CONTINUOUS_RACK = 2, //!< Single client, 'rack' mode. Processes plugins in order of Id, with forced stereo. | |||
PROCESS_MODE_PATCHBAY = 3, //!< Single client, 'patchbay' mode. | |||
PROCESS_MODE_BRIDGE = 4 //!< Special mode, used in plugin-bridges only. | |||
}; | |||
@@ -651,7 +651,7 @@ struct ParameterData { | |||
ParameterData() | |||
: type(PARAMETER_UNKNOWN), | |||
index(-1), | |||
index(PARAMETER_NULL), | |||
rindex(-1), | |||
hints(0x0), | |||
midiChannel(0), | |||
@@ -1,232 +0,0 @@ | |||
/* | |||
* Carla Bridge API | |||
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
* published by the Free Software Foundation; either version 2 of | |||
* the License, or any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* For a full copy of the GNU General Public License see the GPL.txt file | |||
*/ | |||
#ifndef __CARLA_BRIDGE_HPP__ | |||
#define __CARLA_BRIDGE_HPP__ | |||
#include "CarlaUtils.hpp" | |||
#include <semaphore.h> | |||
#define BRIDGE_SHM_RING_BUFFER_SIZE 2048 | |||
#ifndef BUILD_BRIDGE | |||
/*! | |||
* TODO. | |||
*/ | |||
enum PluginBridgeInfoType { | |||
kPluginBridgeAudioCount, | |||
kPluginBridgeMidiCount, | |||
kPluginBridgeParameterCount, | |||
kPluginBridgeProgramCount, | |||
kPluginBridgeMidiProgramCount, | |||
kPluginBridgePluginInfo, | |||
kPluginBridgeParameterInfo, | |||
kPluginBridgeParameterData, | |||
kPluginBridgeParameterRanges, | |||
kPluginBridgeProgramInfo, | |||
kPluginBridgeMidiProgramInfo, | |||
kPluginBridgeConfigure, | |||
kPluginBridgeSetParameterValue, | |||
kPluginBridgeSetDefaultValue, | |||
kPluginBridgeSetProgram, | |||
kPluginBridgeSetMidiProgram, | |||
kPluginBridgeSetCustomData, | |||
kPluginBridgeSetChunkData, | |||
kPluginBridgeUpdateNow, | |||
kPluginBridgeError | |||
}; | |||
#endif | |||
enum PluginBridgeOpcode { | |||
kPluginBridgeOpcodeNull = 0, | |||
kPluginBridgeOpcodeReadyWait = 1, | |||
kPluginBridgeOpcodeBufferSize = 2, | |||
kPluginBridgeOpcodeSampleRate = 3, | |||
kPluginBridgeOpcodeProcess = 4 | |||
}; | |||
/*! | |||
* TODO. | |||
*/ | |||
struct BridgeRingBuffer { | |||
int head; | |||
int tail; | |||
int written; | |||
bool invalidateCommit; | |||
char buf[BRIDGE_SHM_RING_BUFFER_SIZE]; | |||
}; | |||
/*! | |||
* TODO. | |||
*/ | |||
struct BridgeShmControl { | |||
// 32 and 64-bit binaries align semaphores differently. | |||
// Let's make sure there's plenty of room for either one. | |||
union { | |||
sem_t runServer; | |||
char _alignServer[64]; | |||
}; | |||
union { | |||
sem_t runClient; | |||
char _alignClient[64]; | |||
}; | |||
BridgeRingBuffer ringBuffer; | |||
}; | |||
// --------------------------------------------------------------------------------------------- | |||
static inline | |||
void rdwr_tryRead(BridgeRingBuffer* const ringbuf, void* const buf, const size_t size) | |||
{ | |||
char* const charbuf = static_cast<char*>(buf); | |||
size_t tail = ringbuf->tail; | |||
size_t head = ringbuf->head; | |||
size_t wrap = 0; | |||
if (head <= tail) { | |||
wrap = BRIDGE_SHM_RING_BUFFER_SIZE; | |||
} | |||
if (head - tail + wrap < size) { | |||
return; | |||
} | |||
size_t readto = tail + size; | |||
if (readto >= BRIDGE_SHM_RING_BUFFER_SIZE) | |||
{ | |||
readto -= BRIDGE_SHM_RING_BUFFER_SIZE; | |||
size_t firstpart = BRIDGE_SHM_RING_BUFFER_SIZE - tail; | |||
std::memcpy(charbuf, ringbuf->buf + tail, firstpart); | |||
std::memcpy(charbuf + firstpart, ringbuf->buf, readto); | |||
} | |||
else | |||
{ | |||
std::memcpy(charbuf, ringbuf->buf + tail, size); | |||
} | |||
ringbuf->tail = readto; | |||
} | |||
static inline | |||
void rdwr_tryWrite(BridgeRingBuffer* const ringbuf, const void* const buf, const size_t size) | |||
{ | |||
const char* const charbuf = static_cast<const char*>(buf); | |||
size_t written = ringbuf->written; | |||
size_t tail = ringbuf->tail; | |||
size_t wrap = 0; | |||
if (tail <= written) | |||
{ | |||
wrap = BRIDGE_SHM_RING_BUFFER_SIZE; | |||
} | |||
if (tail - written + wrap < size) | |||
{ | |||
carla_stderr2("Operation ring buffer full! Dropping events."); | |||
ringbuf->invalidateCommit = true; | |||
return; | |||
} | |||
size_t writeto = written + size; | |||
if (writeto >= BRIDGE_SHM_RING_BUFFER_SIZE) | |||
{ | |||
writeto -= BRIDGE_SHM_RING_BUFFER_SIZE; | |||
size_t firstpart = BRIDGE_SHM_RING_BUFFER_SIZE - written; | |||
std::memcpy(ringbuf->buf + written, charbuf, firstpart); | |||
std::memcpy(ringbuf->buf, charbuf + firstpart, writeto); | |||
} | |||
else | |||
{ | |||
std::memcpy(ringbuf->buf + written, charbuf, size); | |||
} | |||
ringbuf->written = writeto; | |||
} | |||
static inline | |||
void rdwr_commitWrite(BridgeRingBuffer* const ringbuf) | |||
{ | |||
if (ringbuf->invalidateCommit) | |||
{ | |||
ringbuf->written = ringbuf->head; | |||
ringbuf->invalidateCommit = false; | |||
} | |||
else | |||
{ | |||
ringbuf->head = ringbuf->written; | |||
} | |||
} | |||
// --------------------------------------------------------------------------------------------- | |||
static inline | |||
bool rdwr_dataAvailable(BridgeRingBuffer* const ringbuf) | |||
{ | |||
return (ringbuf->tail != ringbuf->head); | |||
} | |||
static inline | |||
PluginBridgeOpcode rdwr_readOpcode(BridgeRingBuffer* const ringbuf) | |||
{ | |||
PluginBridgeOpcode code = kPluginBridgeOpcodeNull; | |||
rdwr_tryRead(ringbuf, &code, sizeof(PluginBridgeOpcode)); | |||
return code; | |||
} | |||
static inline | |||
int rdwr_readInt(BridgeRingBuffer* const ringbuf) | |||
{ | |||
int i = 0; | |||
rdwr_tryRead(ringbuf, &i, sizeof(int)); | |||
return i; | |||
} | |||
static inline | |||
float rdwr_readFloat(BridgeRingBuffer* const ringbuf) | |||
{ | |||
float f = 0.0f; | |||
rdwr_tryRead(ringbuf, &f, sizeof(float)); | |||
return f; | |||
} | |||
// --------------------------------------------------------------------------------------------- | |||
static inline | |||
void rdwr_writeOpcode(BridgeRingBuffer* const ringbuf, const PluginBridgeOpcode opcode) | |||
{ | |||
rdwr_tryWrite(ringbuf, &opcode, sizeof(PluginBridgeOpcode)); | |||
} | |||
static inline | |||
void rdwr_writeInt(BridgeRingBuffer* const ringbuf, const int value) | |||
{ | |||
rdwr_tryWrite(ringbuf, &value, sizeof(int)); | |||
} | |||
static inline | |||
void rdwr_writeFloat(BridgeRingBuffer* const ringbuf, const float value) | |||
{ | |||
rdwr_tryWrite(ringbuf, &value, sizeof(float)); | |||
} | |||
// --------------------------------------------------------------------------------------------- | |||
#endif // __CARLA_BRIDGE_HPP__ |
@@ -119,7 +119,7 @@ enum EngineControlEventType { | |||
/*! | |||
* Parameter event type.\n | |||
* \note Value uses a range of 0.0<->1.0. | |||
* \note Value uses a normalized range of 0.0<->1.0. | |||
*/ | |||
kEngineControlEventTypeParameter = 1, | |||
@@ -222,7 +222,7 @@ struct EngineEvent { | |||
// ----------------------------------------------------------------------- | |||
/*! | |||
* Engine devices | |||
* Engine devices (unused). | |||
*/ | |||
struct EngineDevices { | |||
struct Audio { | |||
@@ -284,18 +284,18 @@ struct EngineOptions { | |||
CarlaString bridge_win64; | |||
#endif | |||
#ifdef WANT_LV2 | |||
CarlaString bridge_lv2gtk2; | |||
CarlaString bridge_lv2gtk3; | |||
CarlaString bridge_lv2qt4; | |||
CarlaString bridge_lv2qt5; | |||
CarlaString bridge_lv2cocoa; | |||
CarlaString bridge_lv2win; | |||
CarlaString bridge_lv2x11; | |||
CarlaString bridge_lv2Gtk2; | |||
CarlaString bridge_lv2Gtk3; | |||
CarlaString bridge_lv2Qt4; | |||
CarlaString bridge_lv2Qt5; | |||
CarlaString bridge_lv2Cocoa; | |||
CarlaString bridge_lv2Win; | |||
CarlaString bridge_lv2X11; | |||
#endif | |||
#ifdef WANT_VST | |||
CarlaString bridge_vstcocoa; | |||
CarlaString bridge_vsthwnd; | |||
CarlaString bridge_vstx11; | |||
CarlaString bridge_vstCocoa; | |||
CarlaString bridge_vstHWND; | |||
CarlaString bridge_vstX11; | |||
#endif | |||
EngineOptions() | |||
@@ -102,7 +102,7 @@ CarlaEngineEventPort::CarlaEngineEventPort(const bool isInput, const ProcessMode | |||
carla_debug("CarlaEngineEventPort::CarlaEngineEventPort(%s, %s)", bool2str(isInput), ProcessMode2Str(processMode)); | |||
if (kProcessMode == PROCESS_MODE_PATCHBAY || kProcessMode == PROCESS_MODE_BRIDGE) | |||
fBuffer = new EngineEvent[PATCHBAY_EVENT_COUNT]; | |||
fBuffer = new EngineEvent[kMaxEventCount]; | |||
} | |||
CarlaEngineEventPort::~CarlaEngineEventPort() | |||
@@ -131,7 +131,7 @@ void CarlaEngineEventPort::initBuffer(CarlaEngine* const engine) | |||
else | |||
#endif | |||
if ((kProcessMode == PROCESS_MODE_PATCHBAY || kProcessMode == PROCESS_MODE_BRIDGE) && ! kIsInput) | |||
carla_zeroMem(fBuffer, sizeof(EngineEvent)*PATCHBAY_EVENT_COUNT); | |||
carla_zeroStruct<EngineEvent>(fBuffer, kMaxEventCount); | |||
} | |||
uint32_t CarlaEngineEventPort::getEventCount() | |||
@@ -1064,7 +1064,7 @@ bool CarlaEngine::saveProject(const char* const filename) | |||
out << "<CARLA-PROJECT VERSION='1.0'>\n"; | |||
bool firstPlugin = true; | |||
char strBuf[STR_MAX]; | |||
char strBuf[STR_MAX+1]; | |||
for (unsigned int i=0; i < kData->curPluginCount; i++) | |||
{ | |||
@@ -73,7 +73,6 @@ HEADERS = \ | |||
HEADERS += \ | |||
../CarlaBackend.hpp \ | |||
../CarlaBridge.hpp \ | |||
../CarlaEngine.hpp \ | |||
../CarlaPlugin.hpp | |||
@@ -85,6 +84,7 @@ HEADERS += \ | |||
../../utils/CarlaThread.hpp \ | |||
../../utils/CarlaUtils.hpp \ | |||
../../utils/CarlaBackendUtils.hpp \ | |||
../../utils/CarlaBridgeUtils.hpp \ | |||
../../utils/CarlaJuceUtils.hpp \ | |||
../../utils/CarlaOscUtils.hpp \ | |||
../../utils/CarlaStateUtils.hpp | |||
@@ -358,7 +358,24 @@ const char* ProcessMode2Str(const ProcessMode& mode) | |||
return "PROCESS_MODE_BRIDGE"; | |||
} | |||
carla_stderr("CarlaBackend::ProcessModeType2Str(%i) - invalid type", mode); | |||
carla_stderr("CarlaBackend::ProcessMode2Str(%i) - invalid type", mode); | |||
return nullptr; | |||
} | |||
static inline | |||
const char* TransportMode2Str(const TransportMode& mode) | |||
{ | |||
switch (mode) | |||
{ | |||
case TRANSPORT_MODE_INTERNAL: | |||
return "TRANSPORT_MODE_INTERNAL"; | |||
case TRANSPORT_MODE_JACK: | |||
return "TRANSPORT_MODE_JACK"; | |||
case TRANSPORT_MODE_BRIDGE: | |||
return "TRANSPORT_MODE_BRIDGE"; | |||
} | |||
carla_stderr("CarlaBackend::TransportMode2Str(%i) - invalid type", mode); | |||
return nullptr; | |||
} | |||
@@ -140,7 +140,7 @@ unsigned int carla_base64_decode(const char* const encoded, uint8_t* const raw) | |||
continue; | |||
} | |||
if (padCount) | |||
if (padCount > 0) | |||
{ | |||
carla_debug("Base64-encoded string \"%s\" has invalid pad sequence", encoded); | |||
return 0; | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
* Carla common utils | |||
* Carla Mutex | |||
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla Backend utils | |||
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com> | |||
* Carla State utils | |||
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
@@ -19,9 +19,10 @@ | |||
#define __CARLA_STATE_UTILS_HPP__ | |||
#include "CarlaBackendUtils.hpp" | |||
#include "CarlaMIDI.h" | |||
#include <QtXml/QDomNode> | |||
#include <QtCore/QVector> | |||
#include <QtXml/QDomNode> | |||
CARLA_BACKEND_START_NAMESPACE | |||
@@ -40,7 +41,7 @@ struct StateParameter { | |||
name(nullptr), | |||
symbol(nullptr), | |||
value(0.0f), | |||
midiChannel(1), | |||
midiChannel(0), | |||
midiCC(-1) {} | |||
~StateParameter() | |||
@@ -97,7 +98,7 @@ struct SaveState { | |||
int32_t currentMidiProgram; | |||
const char* chunk; | |||
StateParameterVector parameters; | |||
StateParameterVector parameters; | |||
StateCustomDataVector customData; | |||
SaveState() | |||
@@ -176,13 +177,13 @@ struct SaveState { | |||
for (auto it = parameters.begin(); it != parameters.end(); ++it) | |||
{ | |||
StateParameter* stateParameter = *it; | |||
StateParameter* const stateParameter(*it); | |||
delete stateParameter; | |||
} | |||
for (auto it = customData.begin(); it != customData.end(); ++it) | |||
{ | |||
StateCustomData* stateCustomData = *it; | |||
StateCustomData* const stateCustomData(*it); | |||
delete stateCustomData; | |||
} | |||
@@ -231,8 +232,8 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode) | |||
while (! xmlInfo.isNull()) | |||
{ | |||
const QString tag = xmlInfo.toElement().tagName(); | |||
const QString text = xmlInfo.toElement().text().trimmed(); | |||
const QString tag(xmlInfo.toElement().tagName()); | |||
const QString text(xmlInfo.toElement().text().trimmed()); | |||
if (tag.compare("Type", Qt::CaseInsensitive) == 0) | |||
saveState.type = xmlSafeStringChar(text, false); | |||
@@ -262,8 +263,8 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode) | |||
while (! xmlData.isNull()) | |||
{ | |||
const QString tag = xmlData.toElement().tagName(); | |||
const QString text = xmlData.toElement().text().trimmed(); | |||
const QString tag(xmlData.toElement().tagName()); | |||
const QString text(xmlData.toElement().text().trimmed()); | |||
// ---------------------------------------------- | |||
// Internal Data | |||
@@ -345,14 +346,14 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode) | |||
else if (tag.compare("Parameter", Qt::CaseInsensitive) == 0) | |||
{ | |||
StateParameter* stateParameter(new StateParameter); | |||
StateParameter* const stateParameter(new StateParameter()); | |||
QDomNode xmlSubData(xmlData.toElement().firstChild()); | |||
while (! xmlSubData.isNull()) | |||
{ | |||
const QString pTag = xmlSubData.toElement().tagName(); | |||
const QString pText = xmlSubData.toElement().text().trimmed(); | |||
const QString pTag(xmlSubData.toElement().tagName()); | |||
const QString pText(xmlSubData.toElement().text().trimmed()); | |||
if (pTag.compare("Index", Qt::CaseInsensitive) == 0) | |||
{ | |||
@@ -378,21 +379,21 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode) | |||
{ | |||
bool ok; | |||
ushort channel = pText.toUShort(&ok); | |||
if (ok && channel < 16) | |||
stateParameter->midiChannel = static_cast<uint8_t>(channel); | |||
if (ok && channel > 0 && channel < MAX_MIDI_CHANNELS) | |||
stateParameter->midiChannel = static_cast<uint8_t>(channel-1); | |||
} | |||
else if (pTag.compare("MidiCC", Qt::CaseInsensitive) == 0) | |||
{ | |||
bool ok; | |||
int cc = pText.toInt(&ok); | |||
if (ok && cc < INT16_MAX) | |||
if (ok && cc > 0 && cc < INT16_MAX) | |||
stateParameter->midiCC = static_cast<int16_t>(cc); | |||
} | |||
xmlSubData = xmlSubData.nextSibling(); | |||
} | |||
saveState.parameters.push_back(stateParameter); | |||
saveState.parameters.append(stateParameter); | |||
} | |||
// ---------------------------------------------- | |||
@@ -400,14 +401,14 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode) | |||
else if (tag.compare("CustomData", Qt::CaseInsensitive) == 0) | |||
{ | |||
StateCustomData* stateCustomData(new StateCustomData); | |||
StateCustomData* const stateCustomData(new StateCustomData()); | |||
QDomNode xmlSubData(xmlData.toElement().firstChild()); | |||
while (! xmlSubData.isNull()) | |||
{ | |||
const QString cTag = xmlSubData.toElement().tagName(); | |||
const QString cText = xmlSubData.toElement().text().trimmed(); | |||
const QString cTag(xmlSubData.toElement().tagName()); | |||
const QString cText(xmlSubData.toElement().text().trimmed()); | |||
if (cTag.compare("Type", Qt::CaseInsensitive) == 0) | |||
stateCustomData->type = xmlSafeStringChar(cText, false); | |||
@@ -419,7 +420,7 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode) | |||
xmlSubData = xmlSubData.nextSibling(); | |||
} | |||
saveState.customData.push_back(stateCustomData); | |||
saveState.customData.append(stateCustomData); | |||
} | |||
// ---------------------------------------------- | |||
@@ -447,9 +448,10 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode) | |||
// ------------------------------------------------- | |||
static inline | |||
QString getXMLFromSaveState(const SaveState& saveState) | |||
const QString& getXMLFromSaveState(const SaveState& saveState) | |||
{ | |||
QString content; | |||
static QString content; | |||
content.clear(); | |||
{ | |||
QString info(" <Info>\n"); | |||
@@ -521,22 +523,22 @@ QString getXMLFromSaveState(const SaveState& saveState) | |||
for (auto it = saveState.parameters.begin(); it != saveState.parameters.end(); ++it) | |||
{ | |||
StateParameter* stateParameter = *it; | |||
StateParameter* const stateParameter(*it); | |||
QString parameter("\n"" <Parameter>\n"); | |||
parameter += QString(" <Index>%1</Index>\n").arg(stateParameter->index); | |||
parameter += QString(" <Name>%1</Name>\n").arg(xmlSafeString(stateParameter->name, true)); | |||
if (stateParameter->symbol != nullptr && *stateParameter->symbol != 0) | |||
if (stateParameter->symbol != nullptr && *stateParameter->symbol != '\0') | |||
parameter += QString(" <Symbol>%1</Symbol>\n").arg(xmlSafeString(stateParameter->symbol, true)); | |||
parameter += QString(" <Value>%1</Value>\n").arg(stateParameter->value); | |||
if (stateParameter->midiCC > 0) | |||
if (stateParameter->midiCC > 0 && stateParameter->midiChannel >= 0) | |||
{ | |||
parameter += QString(" <MidiCC>%1</MidiCC>\n").arg(stateParameter->midiCC); | |||
parameter += QString(" <MidiChannel>%1</MidiChannel>\n").arg(stateParameter->midiChannel); | |||
parameter += QString(" <MidiChannel>%1</MidiChannel>\n").arg(stateParameter->midiChannel+1); | |||
} | |||
parameter += " </Parameter>\n"; | |||
@@ -544,13 +546,21 @@ QString getXMLFromSaveState(const SaveState& saveState) | |||
content += parameter; | |||
} | |||
if (saveState.currentProgramIndex >= 0) | |||
if (saveState.currentProgramIndex >= 0 && saveState.currentProgramName != nullptr) | |||
{ | |||
QString program("\n"); | |||
program += QString(" <CurrentProgramIndex>%1</CurrentProgramIndex>\n").arg(saveState.currentProgramIndex+1); | |||
program += QString(" <CurrentProgramName>%1</CurrentProgramName>\n").arg(xmlSafeString(saveState.currentProgramName, true)); | |||
// ignore 'default' program | |||
#ifdef __USE_GNU | |||
if ((saveState.currentProgramIndex > 0 || strcasecmp(saveState.currentProgramName, "Default") != 0)) | |||
#else | |||
if ((saveState.currentProgramIndex > 0 || std::strcmp(saveState.currentProgramName, "Default") != 0) | |||
#endif | |||
{ | |||
QString program("\n"); | |||
program += QString(" <CurrentProgramIndex>%1</CurrentProgramIndex>\n").arg(saveState.currentProgramIndex+1); | |||
program += QString(" <CurrentProgramName>%1</CurrentProgramName>\n").arg(xmlSafeString(saveState.currentProgramName, true)); | |||
content += program; | |||
content += program; | |||
} | |||
} | |||
if (saveState.currentMidiBank >= 0 && saveState.currentMidiProgram >= 0) | |||
@@ -564,7 +574,7 @@ QString getXMLFromSaveState(const SaveState& saveState) | |||
for (auto it = saveState.customData.begin(); it != saveState.customData.end(); ++it) | |||
{ | |||
StateCustomData* stateCustomData = *it; | |||
StateCustomData* const stateCustomData(*it); | |||
QString customData("\n"" <CustomData>\n"); | |||
customData += QString(" <Type>%1</Type>\n").arg(xmlSafeString(stateCustomData->type, true)); | |||
@@ -584,7 +594,7 @@ QString getXMLFromSaveState(const SaveState& saveState) | |||
content += customData; | |||
} | |||
if (saveState.chunk != nullptr && *saveState.chunk != 0) | |||
if (saveState.chunk != nullptr && *saveState.chunk != '\0') | |||
{ | |||
QString chunk("\n"" <Chunk>\n"); | |||
chunk += QString("%1\n").arg(saveState.chunk); | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla common utils | |||
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com> | |||
* Carla String | |||
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
@@ -116,7 +116,7 @@ public: | |||
} | |||
// --------------------------------------------- | |||
// deconstructor | |||
// destructor | |||
~CarlaString() | |||
{ | |||
@@ -187,9 +187,9 @@ public: | |||
truncate(0); | |||
} | |||
size_t find(const char c) | |||
size_t find(const char c) const | |||
{ | |||
for (size_t i=0; i < bufferLen; i++) | |||
for (size_t i=0; i < bufferLen; ++i) | |||
{ | |||
if (buffer[i] == c) | |||
return i; | |||
@@ -198,11 +198,11 @@ public: | |||
return 0; | |||
} | |||
size_t rfind(const char c) | |||
size_t rfind(const char c) const | |||
{ | |||
size_t pos = 0; | |||
for (size_t i=0; i < bufferLen; i++) | |||
for (size_t i=0; i < bufferLen; ++i) | |||
{ | |||
if (buffer[i] == c) | |||
pos = i; | |||
@@ -216,7 +216,7 @@ public: | |||
if (after == '\0') | |||
return; | |||
for (size_t i=0; i < bufferLen; i++) | |||
for (size_t i=0; i < bufferLen; ++i) | |||
{ | |||
if (buffer[i] == before) | |||
buffer[i] = after; | |||
@@ -230,7 +230,7 @@ public: | |||
if (n >= bufferLen) | |||
return; | |||
for (size_t i=n; i < bufferLen; i++) | |||
for (size_t i=n; i < bufferLen; ++i) | |||
buffer[i] = '\0'; | |||
bufferLen = n; | |||
@@ -238,7 +238,7 @@ public: | |||
void toBasic() | |||
{ | |||
for (size_t i=0; i < bufferLen; i++) | |||
for (size_t i=0; i < bufferLen; ++i) | |||
{ | |||
if (buffer[i] >= '0' && buffer[i] <= '9') | |||
continue; | |||
@@ -257,7 +257,7 @@ public: | |||
{ | |||
static const char charDiff = 'a' - 'A'; | |||
for (size_t i=0; i < bufferLen; i++) | |||
for (size_t i=0; i < bufferLen; ++i) | |||
{ | |||
if (buffer[i] >= 'A' && buffer[i] <= 'Z') | |||
buffer[i] += charDiff; | |||
@@ -268,7 +268,7 @@ public: | |||
{ | |||
static const char charDiff = 'a' - 'A'; | |||
for (size_t i=0; i < bufferLen; i++) | |||
for (size_t i=0; i < bufferLen; ++i) | |||
{ | |||
if (buffer[i] >= 'a' && buffer[i] <= 'z') | |||
buffer[i] -= charDiff; | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla common utils | |||
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com> | |||
* Carla Thread | |||
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
@@ -175,7 +175,7 @@ public: | |||
if (fStarted && ! fFinished) | |||
return true; | |||
// take the change to clear data | |||
// take the chance to clear data | |||
#ifdef CPP11_THREAD | |||
if (cthread != nullptr) | |||
{ | |||
@@ -56,9 +56,13 @@ void carla_debug(const char* const fmt, ...) | |||
{ | |||
va_list args; | |||
va_start(args, fmt); | |||
#ifndef CARLA_OS_WIN | |||
std::fprintf(stdout, "\x1b[30;1m"); | |||
#endif | |||
std::vfprintf(stdout, fmt, args); | |||
#ifndef CARLA_OS_WIN | |||
std::fprintf(stdout, "\x1b[0m\n"); | |||
#endif | |||
va_end(args); | |||
} | |||
#endif | |||
@@ -88,9 +92,13 @@ void carla_stderr2(const char* const fmt, ...) | |||
{ | |||
va_list args; | |||
va_start(args, fmt); | |||
#ifndef CARLA_OS_WIN | |||
std::fprintf(stderr, "\x1b[31m"); | |||
#endif | |||
std::vfprintf(stderr, fmt, args); | |||
#ifndef CARLA_OS_WIN | |||
std::fprintf(stderr, "\x1b[0m\n"); | |||
#endif | |||
va_end(args); | |||
} | |||
@@ -197,7 +205,7 @@ const char* carla_strdup(const char* const strBuf) | |||
CARLA_ASSERT(strBuf != nullptr); | |||
const size_t bufferLen = (strBuf != nullptr) ? std::strlen(strBuf) : 0; | |||
char* const buffer = new char [bufferLen+1]; | |||
char* const buffer = new char[bufferLen+1]; | |||
std::strcpy(buffer, strBuf); | |||
@@ -253,7 +261,7 @@ void carla_copy(T* dataDst, T* dataSrc, const size_t size) | |||
if (dataDst == nullptr || dataSrc == nullptr || size == 0) | |||
return; | |||
for (size_t i=0; i < size; i++) | |||
for (size_t i=0; i < size; ++i) | |||
*dataDst++ = *dataSrc++; | |||
} | |||
@@ -268,7 +276,7 @@ void carla_copy(T* dataDst, const T* dataSrc, const size_t size) | |||
if (dataDst == nullptr || dataSrc == nullptr || size == 0) | |||
return; | |||
for (size_t i=0; i < size; i++) | |||
for (size_t i=0; i < size; ++i) | |||
*dataDst++ = *dataSrc++; | |||
} | |||
@@ -282,7 +290,7 @@ void carla_fill(T* data, const size_t size, const T v) | |||
if (data == nullptr || size == 0) | |||
return; | |||
for (size_t i=0; i < size; i++) | |||
for (size_t i=0; i < size; ++i) | |||
*data++ = v; | |||
} | |||
@@ -346,6 +354,13 @@ void carla_zeroStruct(T& structure) | |||
std::memset(&structure, 0, sizeof(T)); | |||
} | |||
template <typename T> | |||
static inline | |||
void carla_zeroStruct(T& structure, const size_t count) | |||
{ | |||
std::memset(&structure, 0, sizeof(T)*count); | |||
} | |||
// ------------------------------------------------- | |||
#endif // __CARLA_UTILS_HPP__ |