|
|
|
@@ -20,6 +20,17 @@ |
|
|
|
|
|
|
|
CARLA_BACKEND_START_NAMESPACE |
|
|
|
|
|
|
|
struct NativePluginMidiData { |
|
|
|
uint32_t count; |
|
|
|
uint32_t* rindexes; |
|
|
|
CarlaEngineMidiPort** ports; |
|
|
|
|
|
|
|
NativePluginMidiData() |
|
|
|
: count(0), |
|
|
|
rindexes(nullptr), |
|
|
|
ports(nullptr) {} |
|
|
|
}; |
|
|
|
|
|
|
|
class NativePluginScopedInitiliazer |
|
|
|
{ |
|
|
|
public: |
|
|
|
@@ -75,8 +86,24 @@ public: |
|
|
|
{ |
|
|
|
qDebug("NativePlugin::~NativePlugin()"); |
|
|
|
|
|
|
|
if (handle) |
|
|
|
pass(); |
|
|
|
if (descriptor) |
|
|
|
{ |
|
|
|
if (descriptor->deactivate && m_activeBefore) |
|
|
|
{ |
|
|
|
if (handle) |
|
|
|
descriptor->deactivate(handle); |
|
|
|
//if (h2) |
|
|
|
// descriptor->deactivate(h2); |
|
|
|
} |
|
|
|
|
|
|
|
if (descriptor->cleanup) |
|
|
|
{ |
|
|
|
if (handle) |
|
|
|
descriptor->cleanup(handle); |
|
|
|
//if (h2) |
|
|
|
// descriptor->cleanup(h2); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// ------------------------------------------------------------------- |
|
|
|
@@ -92,15 +119,73 @@ public: |
|
|
|
return getPluginCategoryFromName(m_name); |
|
|
|
} |
|
|
|
|
|
|
|
// ------------------------------------------------------------------- |
|
|
|
// Information (count) |
|
|
|
|
|
|
|
uint32_t midiInCount() |
|
|
|
{ |
|
|
|
return mIn.count; |
|
|
|
} |
|
|
|
|
|
|
|
uint32_t midiOutCount() |
|
|
|
{ |
|
|
|
return mOut.count; |
|
|
|
} |
|
|
|
|
|
|
|
uint32_t parameterScalePointCount(const uint32_t parameterId) |
|
|
|
{ |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
Q_ASSERT(parameterId < param.count); |
|
|
|
|
|
|
|
int32_t rindex = param.data[parameterId].rindex; |
|
|
|
|
|
|
|
if (descriptor && rindex < (int32_t)descriptor->portCount) |
|
|
|
{ |
|
|
|
const PluginPort* const port = &descriptor->ports[rindex]; |
|
|
|
|
|
|
|
if (port) |
|
|
|
return port->scalePointCount; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
// ------------------------------------------------------------------- |
|
|
|
// Information (per-plugin data) |
|
|
|
|
|
|
|
double getParameterValue(const uint32_t parameterId) |
|
|
|
{ |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
Q_ASSERT(handle); |
|
|
|
Q_ASSERT(parameterId < param.count); |
|
|
|
|
|
|
|
//return descriptor->get_parameter_value(); |
|
|
|
if (descriptor && handle) |
|
|
|
return descriptor->get_parameter_value(handle, parameterId); |
|
|
|
|
|
|
|
return 0.0; |
|
|
|
} |
|
|
|
|
|
|
|
double getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) |
|
|
|
{ |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
Q_ASSERT(parameterId < param.count); |
|
|
|
Q_ASSERT(scalePointId < parameterScalePointCount(parameterId)); |
|
|
|
|
|
|
|
const int32_t rindex = param.data[parameterId].rindex; |
|
|
|
|
|
|
|
if (descriptor && rindex < (int32_t)descriptor->portCount) |
|
|
|
{ |
|
|
|
const PluginPort* const port = &descriptor->ports[rindex]; |
|
|
|
|
|
|
|
if (port && scalePointId < port->scalePointCount) |
|
|
|
{ |
|
|
|
const PluginPortScalePoint* const scalePoint = &port->scalePoints[scalePointId]; |
|
|
|
|
|
|
|
if (scalePoint) |
|
|
|
return scalePoint->value; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return 0.0; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -149,12 +234,537 @@ public: |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
Q_ASSERT(parameterId < param.count); |
|
|
|
|
|
|
|
const int32_t rindex = param.data[parameterId].rindex; |
|
|
|
|
|
|
|
if (descriptor && rindex < (int32_t)descriptor->portCount) |
|
|
|
{ |
|
|
|
const PluginPort* const port = &descriptor->ports[rindex]; |
|
|
|
|
|
|
|
if (port && port->name) |
|
|
|
{ |
|
|
|
strncpy(strBuf, port->name, STR_MAX); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
CarlaPlugin::getParameterName(parameterId, strBuf); |
|
|
|
} |
|
|
|
|
|
|
|
void getParameterText(const uint32_t parameterId, char* const strBuf) |
|
|
|
{ |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
Q_ASSERT(handle); |
|
|
|
Q_ASSERT(parameterId < param.count); |
|
|
|
|
|
|
|
if (descriptor && handle) |
|
|
|
{ |
|
|
|
const int32_t rindex = param.data[parameterId].rindex; |
|
|
|
|
|
|
|
const char* const text = descriptor->get_parameter_text(handle, rindex); |
|
|
|
|
|
|
|
if (text) |
|
|
|
{ |
|
|
|
strncpy(strBuf, text, STR_MAX); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
CarlaPlugin::getParameterText(parameterId, strBuf); |
|
|
|
} |
|
|
|
|
|
|
|
void getParameterUnit(const uint32_t parameterId, char* const strBuf) |
|
|
|
{ |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
Q_ASSERT(handle); |
|
|
|
Q_ASSERT(parameterId < param.count); |
|
|
|
|
|
|
|
if (descriptor && handle) |
|
|
|
{ |
|
|
|
const int32_t rindex = param.data[parameterId].rindex; |
|
|
|
|
|
|
|
const char* const unit = descriptor->get_parameter_unit(handle, rindex); |
|
|
|
|
|
|
|
if (unit) |
|
|
|
{ |
|
|
|
strncpy(strBuf, unit, STR_MAX); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
CarlaPlugin::getParameterUnit(parameterId, strBuf); |
|
|
|
} |
|
|
|
|
|
|
|
void getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) |
|
|
|
{ |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
Q_ASSERT(parameterId < param.count); |
|
|
|
Q_ASSERT(scalePointId < parameterScalePointCount(parameterId)); |
|
|
|
|
|
|
|
int32_t rindex = param.data[parameterId].rindex; |
|
|
|
|
|
|
|
if (descriptor && rindex < (int32_t)descriptor->portCount) |
|
|
|
strncpy(strBuf, descriptor->ports[rindex].name, STR_MAX); |
|
|
|
else |
|
|
|
CarlaPlugin::getParameterName(parameterId, strBuf); |
|
|
|
{ |
|
|
|
const PluginPort* const port = &descriptor->ports[rindex]; |
|
|
|
|
|
|
|
if (port && scalePointId < port->scalePointCount) |
|
|
|
{ |
|
|
|
const PluginPortScalePoint* const scalePoint = &port->scalePoints[scalePointId]; |
|
|
|
|
|
|
|
if (scalePoint && scalePoint->label) |
|
|
|
{ |
|
|
|
strncpy(strBuf, scalePoint->label, STR_MAX); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf); |
|
|
|
} |
|
|
|
|
|
|
|
// ------------------------------------------------------------------- |
|
|
|
// Set data (plugin-specific stuff) |
|
|
|
|
|
|
|
void setParameterValue(const uint32_t parameterId, double value, const bool sendGui, const bool sendOsc, const bool sendCallback) |
|
|
|
{ |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
Q_ASSERT(handle); |
|
|
|
Q_ASSERT(parameterId < param.count); |
|
|
|
|
|
|
|
if (descriptor && handle) |
|
|
|
descriptor->set_parameter_value(handle, parameterId, fixParameterValue(value, param.ranges[parameterId])); |
|
|
|
|
|
|
|
CarlaPlugin::setParameterValue(parameterId, value, sendGui, sendOsc, sendCallback); |
|
|
|
} |
|
|
|
|
|
|
|
void setCustomData(const CustomDataType type, const char* const key, const char* const value, const bool sendGui) |
|
|
|
{ |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
Q_ASSERT(handle); |
|
|
|
Q_ASSERT(type == CUSTOM_DATA_STRING); |
|
|
|
Q_ASSERT(key); |
|
|
|
Q_ASSERT(value); |
|
|
|
|
|
|
|
if (type != CUSTOM_DATA_STRING) |
|
|
|
return qCritical("NativePlugin::setCustomData(%s, \"%s\", \"%s\", %s) - type is not string", CustomDataType2str(type), key, value, bool2str(sendGui)); |
|
|
|
|
|
|
|
if (! key) |
|
|
|
return qCritical("NativePlugin::setCustomData(%s, \"%s\", \"%s\", %s) - key is null", CustomDataType2str(type), key, value, bool2str(sendGui)); |
|
|
|
|
|
|
|
if (! value) |
|
|
|
return qCritical("Nativelugin::setCustomData(%s, \"%s\", \"%s\", %s) - value is null", CustomDataType2str(type), key, value, bool2str(sendGui)); |
|
|
|
|
|
|
|
if (descriptor && handle) |
|
|
|
descriptor->set_custom_data(handle, key, value); |
|
|
|
|
|
|
|
CarlaPlugin::setCustomData(type, key, value, sendGui); |
|
|
|
} |
|
|
|
|
|
|
|
void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool block) |
|
|
|
{ |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
Q_ASSERT(handle); |
|
|
|
Q_ASSERT(index >= -1 && index < (int32_t)midiprog.count); |
|
|
|
|
|
|
|
if (index < -1) |
|
|
|
index = -1; |
|
|
|
else if (index > (int32_t)midiprog.count) |
|
|
|
return; |
|
|
|
|
|
|
|
if (descriptor && handle && index >= 0) |
|
|
|
{ |
|
|
|
if (x_engine->isOffline()) |
|
|
|
{ |
|
|
|
const CarlaEngine::ScopedLocker m(x_engine, block); |
|
|
|
descriptor->set_midi_program(handle, midiprog.data[index].bank, midiprog.data[index].program); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
const ScopedDisabler m(this, block); |
|
|
|
descriptor->set_midi_program(handle, midiprog.data[index].bank, midiprog.data[index].program); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, block); |
|
|
|
} |
|
|
|
|
|
|
|
// ------------------------------------------------------------------- |
|
|
|
// Set gui stuff |
|
|
|
|
|
|
|
void showGui(const bool yesNo) |
|
|
|
{ |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
|
|
|
|
if (descriptor && handle) |
|
|
|
descriptor->show_gui(handle, yesNo); |
|
|
|
} |
|
|
|
|
|
|
|
void idleGui() |
|
|
|
{ |
|
|
|
// FIXME - this should not be called if there's no GUI! |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
|
|
|
|
if (descriptor && descriptor->idle_gui && handle) |
|
|
|
descriptor->idle_gui(handle); |
|
|
|
} |
|
|
|
|
|
|
|
// ------------------------------------------------------------------- |
|
|
|
// Plugin state |
|
|
|
|
|
|
|
void reload() |
|
|
|
{ |
|
|
|
qDebug("NativePlugin::reload() - start"); |
|
|
|
Q_ASSERT(descriptor); |
|
|
|
|
|
|
|
// Safely disable plugin for reload |
|
|
|
const ScopedDisabler m(this); |
|
|
|
|
|
|
|
if (x_client->isActive()) |
|
|
|
x_client->deactivate(); |
|
|
|
|
|
|
|
// Remove client ports |
|
|
|
removeClientPorts(); |
|
|
|
|
|
|
|
// Delete old data |
|
|
|
deleteBuffers(); |
|
|
|
|
|
|
|
uint32_t aIns, aOuts, mIns, mOuts, params, j; |
|
|
|
aIns = aOuts = mIns = mOuts = params = 0; |
|
|
|
|
|
|
|
const double sampleRate = x_engine->getSampleRate(); |
|
|
|
const uint32_t portCount = descriptor->portCount; |
|
|
|
|
|
|
|
for (uint32_t i=0; i < portCount; i++) |
|
|
|
{ |
|
|
|
const PortType portType = descriptor->ports[i].type; |
|
|
|
const uint32_t portHints = descriptor->ports[i].hints; |
|
|
|
|
|
|
|
if (portType == PORT_TYPE_AUDIO) |
|
|
|
{ |
|
|
|
if (portHints & PORT_HINT_IS_OUTPUT) |
|
|
|
aOuts += 1; |
|
|
|
else |
|
|
|
aIns += 1; |
|
|
|
} |
|
|
|
else if (portType == PORT_TYPE_MIDI) |
|
|
|
{ |
|
|
|
if (portHints & PORT_HINT_IS_OUTPUT) |
|
|
|
mOuts += 1; |
|
|
|
else |
|
|
|
mIns += 1; |
|
|
|
} |
|
|
|
else if (portType == PORT_TYPE_PARAMETER) |
|
|
|
params += 1; |
|
|
|
} |
|
|
|
|
|
|
|
if (aIns > 0) |
|
|
|
{ |
|
|
|
aIn.ports = new CarlaEngineAudioPort*[aIns]; |
|
|
|
aIn.rindexes = new uint32_t[aIns]; |
|
|
|
} |
|
|
|
|
|
|
|
if (aOuts > 0) |
|
|
|
{ |
|
|
|
aOut.ports = new CarlaEngineAudioPort*[aOuts]; |
|
|
|
aOut.rindexes = new uint32_t[aOuts]; |
|
|
|
} |
|
|
|
|
|
|
|
if (mIns > 0) |
|
|
|
{ |
|
|
|
mIn.ports = new CarlaEngineMidiPort*[mIns]; |
|
|
|
mIn.rindexes = new uint32_t[mIns]; |
|
|
|
} |
|
|
|
|
|
|
|
if (mOuts > 0) |
|
|
|
{ |
|
|
|
mOut.ports = new CarlaEngineMidiPort*[mOuts]; |
|
|
|
mOut.rindexes = new uint32_t[mOuts]; |
|
|
|
} |
|
|
|
|
|
|
|
if (params > 0) |
|
|
|
{ |
|
|
|
param.data = new ParameterData[params]; |
|
|
|
param.ranges = new ParameterRanges[params]; |
|
|
|
} |
|
|
|
|
|
|
|
const int portNameSize = CarlaEngine::maxPortNameSize() - 2; |
|
|
|
char portName[portNameSize]; |
|
|
|
bool needsCtrlIn = false; |
|
|
|
bool needsCtrlOut = false; |
|
|
|
|
|
|
|
for (uint32_t i=0; i < portCount; i++) |
|
|
|
{ |
|
|
|
const PortType portType = descriptor->ports[i].type; |
|
|
|
const uint32_t portHints = descriptor->ports[i].hints; |
|
|
|
|
|
|
|
if (portType == PORT_TYPE_AUDIO || portType == PORT_TYPE_MIDI) |
|
|
|
{ |
|
|
|
if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS) |
|
|
|
{ |
|
|
|
strcpy(portName, m_name); |
|
|
|
strcat(portName, ":"); |
|
|
|
strncat(portName, descriptor->ports[i].name, portNameSize/2); |
|
|
|
} |
|
|
|
else |
|
|
|
strncpy(portName, descriptor->ports[i].name, portNameSize); |
|
|
|
} |
|
|
|
|
|
|
|
if (portType == PORT_TYPE_AUDIO) |
|
|
|
{ |
|
|
|
if (portHints & PORT_HINT_IS_OUTPUT) |
|
|
|
{ |
|
|
|
j = aOut.count++; |
|
|
|
aOut.ports[j] = (CarlaEngineAudioPort*)x_client->addPort(CarlaEnginePortTypeAudio, portName, false); |
|
|
|
aOut.rindexes[j] = i; |
|
|
|
needsCtrlIn = true; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
j = aIn.count++; |
|
|
|
aIn.ports[j] = (CarlaEngineAudioPort*)x_client->addPort(CarlaEnginePortTypeAudio, portName, true); |
|
|
|
aIn.rindexes[j] = i; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (portType == PORT_TYPE_MIDI) |
|
|
|
{ |
|
|
|
if (portHints & PORT_HINT_IS_OUTPUT) |
|
|
|
{ |
|
|
|
j = aOut.count++; |
|
|
|
mOut.ports[j] = (CarlaEngineMidiPort*)x_client->addPort(CarlaEnginePortTypeMIDI, portName, false); |
|
|
|
mOut.rindexes[j] = i; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
j = aIn.count++; |
|
|
|
mIn.ports[j] = (CarlaEngineMidiPort*)x_client->addPort(CarlaEnginePortTypeMIDI, portName, true); |
|
|
|
mIn.rindexes[j] = i; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (portType == PORT_TYPE_PARAMETER) |
|
|
|
{ |
|
|
|
j = param.count++; |
|
|
|
param.data[j].index = j; |
|
|
|
param.data[j].rindex = i; |
|
|
|
param.data[j].hints = 0; |
|
|
|
param.data[j].midiChannel = 0; |
|
|
|
param.data[j].midiCC = -1; |
|
|
|
|
|
|
|
double min, max, def, step, stepSmall, stepLarge; |
|
|
|
|
|
|
|
::ParameterRanges ranges = { 0.0, 0.0, 1.0, 0.01, 0.0001, 0.1 }; |
|
|
|
descriptor->get_parameter_ranges(handle, i, &ranges); |
|
|
|
|
|
|
|
// min value |
|
|
|
min = ranges.min; |
|
|
|
|
|
|
|
// max value |
|
|
|
min = ranges.max; |
|
|
|
|
|
|
|
if (min > max) |
|
|
|
max = min; |
|
|
|
else if (max < min) |
|
|
|
min = max; |
|
|
|
|
|
|
|
if (max - min == 0.0) |
|
|
|
{ |
|
|
|
qWarning("Broken plugin parameter: max - min == 0"); |
|
|
|
max = min + 0.1; |
|
|
|
} |
|
|
|
|
|
|
|
// default value |
|
|
|
def = ranges.def; |
|
|
|
|
|
|
|
if (def < min) |
|
|
|
def = min; |
|
|
|
else if (def > max) |
|
|
|
def = max; |
|
|
|
|
|
|
|
if (portHints & PORT_HINT_USES_SAMPLE_RATE) |
|
|
|
{ |
|
|
|
min *= sampleRate; |
|
|
|
max *= sampleRate; |
|
|
|
def *= sampleRate; |
|
|
|
param.data[j].hints |= PARAMETER_USES_SAMPLERATE; |
|
|
|
} |
|
|
|
|
|
|
|
if (portHints & PORT_HINT_IS_BOOLEAN) |
|
|
|
{ |
|
|
|
step = max - min; |
|
|
|
stepSmall = step; |
|
|
|
stepLarge = step; |
|
|
|
param.data[j].hints |= PARAMETER_IS_BOOLEAN; |
|
|
|
} |
|
|
|
else if (portHints & PORT_HINT_IS_INTEGER) |
|
|
|
{ |
|
|
|
step = 1.0; |
|
|
|
stepSmall = 1.0; |
|
|
|
stepLarge = 10.0; |
|
|
|
param.data[j].hints |= PARAMETER_IS_INTEGER; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
double range = max - min; |
|
|
|
step = range/100.0; |
|
|
|
stepSmall = range/1000.0; |
|
|
|
stepLarge = range/10.0; |
|
|
|
} |
|
|
|
|
|
|
|
if (portHints & PORT_HINT_IS_OUTPUT) |
|
|
|
{ |
|
|
|
param.data[j].type = PARAMETER_OUTPUT; |
|
|
|
needsCtrlOut = true; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
param.data[j].type = PARAMETER_INPUT; |
|
|
|
needsCtrlIn = true; |
|
|
|
} |
|
|
|
|
|
|
|
// extra parameter hints |
|
|
|
if (portHints & PORT_HINT_IS_ENABLED) |
|
|
|
param.data[j].hints |= PARAMETER_IS_ENABLED; |
|
|
|
|
|
|
|
if (portHints & PORT_HINT_IS_AUTOMABLE) |
|
|
|
param.data[j].hints |= PARAMETER_IS_AUTOMABLE; |
|
|
|
|
|
|
|
if (portHints & PORT_HINT_IS_LOGARITHMIC) |
|
|
|
param.data[j].hints |= PARAMETER_IS_LOGARITHMIC; |
|
|
|
|
|
|
|
if (portHints & PORT_HINT_USES_SCALEPOINTS) |
|
|
|
param.data[j].hints |= PARAMETER_USES_SCALEPOINTS; |
|
|
|
|
|
|
|
if (portHints & PORT_HINT_USES_CUSTOM_TEXT) |
|
|
|
param.data[j].hints |= PARAMETER_USES_CUSTOM_TEXT; |
|
|
|
|
|
|
|
param.ranges[j].min = min; |
|
|
|
param.ranges[j].max = max; |
|
|
|
param.ranges[j].def = def; |
|
|
|
param.ranges[j].step = step; |
|
|
|
param.ranges[j].stepSmall = stepSmall; |
|
|
|
param.ranges[j].stepLarge = stepLarge; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (needsCtrlIn) |
|
|
|
{ |
|
|
|
if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS) |
|
|
|
{ |
|
|
|
strcpy(portName, m_name); |
|
|
|
strcat(portName, ":control-in"); |
|
|
|
} |
|
|
|
else |
|
|
|
strcpy(portName, "control-in"); |
|
|
|
|
|
|
|
param.portCin = (CarlaEngineControlPort*)x_client->addPort(CarlaEnginePortTypeControl, portName, true); |
|
|
|
} |
|
|
|
|
|
|
|
if (needsCtrlOut) |
|
|
|
{ |
|
|
|
if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS) |
|
|
|
{ |
|
|
|
strcpy(portName, m_name); |
|
|
|
strcat(portName, ":control-out"); |
|
|
|
} |
|
|
|
else |
|
|
|
strcpy(portName, "control-out"); |
|
|
|
|
|
|
|
param.portCout = (CarlaEngineControlPort*)x_client->addPort(CarlaEnginePortTypeControl, portName, false); |
|
|
|
} |
|
|
|
|
|
|
|
aIn.count = aIns; |
|
|
|
aOut.count = aOuts; |
|
|
|
param.count = params; |
|
|
|
|
|
|
|
// plugin checks |
|
|
|
m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE); |
|
|
|
|
|
|
|
if (aOuts > 0 && (aIns == aOuts || aIns == 1)) |
|
|
|
m_hints |= PLUGIN_CAN_DRYWET; |
|
|
|
|
|
|
|
if (aOuts > 0) |
|
|
|
m_hints |= PLUGIN_CAN_VOLUME; |
|
|
|
|
|
|
|
if (aOuts >= 2 && aOuts%2 == 0) |
|
|
|
m_hints |= PLUGIN_CAN_BALANCE; |
|
|
|
|
|
|
|
m_hints |= getPluginHintsFromNative(descriptor->hints); |
|
|
|
|
|
|
|
reloadPrograms(true); |
|
|
|
|
|
|
|
x_client->activate(); |
|
|
|
|
|
|
|
qDebug("NativePlugin::reload() - end"); |
|
|
|
} |
|
|
|
|
|
|
|
// ------------------------------------------------------------------- |
|
|
|
// Cleanup |
|
|
|
|
|
|
|
void removeClientPorts() |
|
|
|
{ |
|
|
|
qDebug("NativePlugin::removeClientPorts() - start"); |
|
|
|
|
|
|
|
for (uint32_t i=0; i < mIn.count; i++) |
|
|
|
{ |
|
|
|
delete mIn.ports[i]; |
|
|
|
mIn.ports[i] = nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
for (uint32_t i=0; i < mOut.count; i++) |
|
|
|
{ |
|
|
|
delete mOut.ports[i]; |
|
|
|
mOut.ports[i] = nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
CarlaPlugin::removeClientPorts(); |
|
|
|
|
|
|
|
qDebug("NativePlugin::removeClientPorts() - end"); |
|
|
|
} |
|
|
|
|
|
|
|
void initBuffers() |
|
|
|
{ |
|
|
|
uint32_t i; |
|
|
|
|
|
|
|
for (i=0; i < mIn.count; i++) |
|
|
|
{ |
|
|
|
if (mIn.ports[i]) |
|
|
|
mIn.ports[i]->initBuffer(x_engine); |
|
|
|
} |
|
|
|
|
|
|
|
for (i=0; i < mOut.count; i++) |
|
|
|
{ |
|
|
|
if (mOut.ports[i]) |
|
|
|
mOut.ports[i]->initBuffer(x_engine); |
|
|
|
} |
|
|
|
|
|
|
|
CarlaPlugin::initBuffers(); |
|
|
|
} |
|
|
|
|
|
|
|
void deleteBuffers() |
|
|
|
{ |
|
|
|
qDebug("NativePlugin::deleteBuffers() - start"); |
|
|
|
|
|
|
|
if (mIn.count > 0) |
|
|
|
{ |
|
|
|
delete[] mIn.ports; |
|
|
|
delete[] mIn.rindexes; |
|
|
|
} |
|
|
|
|
|
|
|
if (mOut.count > 0) |
|
|
|
{ |
|
|
|
delete[] mOut.ports; |
|
|
|
delete[] mOut.rindexes; |
|
|
|
} |
|
|
|
|
|
|
|
mIn.count = 0; |
|
|
|
mIn.ports = nullptr; |
|
|
|
mIn.rindexes = nullptr; |
|
|
|
|
|
|
|
mOut.count = 0; |
|
|
|
mOut.ports = nullptr; |
|
|
|
mOut.rindexes = nullptr; |
|
|
|
|
|
|
|
CarlaPlugin::deleteBuffers(); |
|
|
|
|
|
|
|
qDebug("NativePlugin::deleteBuffers() - end"); |
|
|
|
} |
|
|
|
|
|
|
|
// ------------------------------------------------------------------- |
|
|
|
@@ -184,7 +794,7 @@ public: |
|
|
|
bool init(const char* const name, const char* const label) |
|
|
|
{ |
|
|
|
// --------------------------------------------------------------- |
|
|
|
// get plugin |
|
|
|
// get descriptor that matches label |
|
|
|
|
|
|
|
for (size_t i=0; i < pluginDescriptors.size(); i++) |
|
|
|
{ |
|
|
|
@@ -206,6 +816,17 @@ public: |
|
|
|
|
|
|
|
scopedInitliazer.initializeIfNeeded(descriptor); |
|
|
|
|
|
|
|
// --------------------------------------------------------------- |
|
|
|
// initialize plugin |
|
|
|
|
|
|
|
handle = descriptor->instantiate((struct _PluginDescriptor*)descriptor, nullptr); // TODO - host |
|
|
|
|
|
|
|
if (! handle) |
|
|
|
{ |
|
|
|
setLastError("Plugin failed to initialize"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// --------------------------------------------------------------- |
|
|
|
// get info |
|
|
|
|
|
|
|
@@ -232,6 +853,9 @@ private: |
|
|
|
const PluginDescriptor* descriptor; |
|
|
|
PluginHandle handle; |
|
|
|
|
|
|
|
NativePluginMidiData mIn; |
|
|
|
NativePluginMidiData mOut; |
|
|
|
|
|
|
|
static std::vector<const PluginDescriptor*> pluginDescriptors; |
|
|
|
}; |
|
|
|
|
|
|
|
|