Browse Source

More VST work; cleanup

tags/1.9.4
falkTX 11 years ago
parent
commit
1a6b10e0c4
10 changed files with 502 additions and 330 deletions
  1. +1
    -1
      source/backend/CarlaBackend.hpp
  2. +1
    -1
      source/backend/plugin/BridgePlugin.cpp
  3. +25
    -27
      source/backend/plugin/DssiPlugin.cpp
  4. +2
    -2
      source/backend/plugin/FluidSynthPlugin.cpp
  5. +2
    -2
      source/backend/plugin/LinuxSamplerPlugin.cpp
  6. +29
    -22
      source/backend/plugin/Lv2Plugin.cpp
  7. +28
    -25
      source/backend/plugin/NativePlugin.cpp
  8. +93
    -0
      source/backend/plugin/Vst3Plugin.cpp
  9. +320
    -249
      source/backend/plugin/VstPlugin.cpp
  10. +1
    -1
      source/utils/CarlaVstUtils.hpp

+ 1
- 1
source/backend/CarlaBackend.hpp View File

@@ -26,7 +26,7 @@
#define CARLA_BACKEND_END_NAMESPACE } #define CARLA_BACKEND_END_NAMESPACE }
#define CARLA_BACKEND_USE_NAMESPACE using namespace CarlaBackend; #define CARLA_BACKEND_USE_NAMESPACE using namespace CarlaBackend;


#define STR_MAX 0xFF
#define STR_MAX 0xFF+1


CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE




+ 1
- 1
source/backend/plugin/BridgePlugin.cpp View File

@@ -119,7 +119,7 @@ public:
return fInfo.category; return fInfo.category;
} }


long uniqueId()
long uniqueId() const
{ {
return fInfo.uniqueId; return fInfo.uniqueId;
} }


+ 25
- 27
source/backend/plugin/DssiPlugin.cpp View File

@@ -42,10 +42,6 @@ public:
carla_zeroMem(fMidiEvents, sizeof(snd_seq_event_t)*MAX_MIDI_EVENTS); carla_zeroMem(fMidiEvents, sizeof(snd_seq_event_t)*MAX_MIDI_EVENTS);


kData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_DSSI_GUI); kData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_DSSI_GUI);

// FIXME
if (engine->getOptions().useDssiVstChunks)
fOptions |= PLUGIN_OPTION_USE_CHUNKS;
} }


~DssiPlugin() ~DssiPlugin()
@@ -708,13 +704,13 @@ public:
} }


// plugin hints // plugin hints
const bool haveGUI = (fHints & PLUGIN_HAS_GUI);
const bool hasGUI = (fHints & PLUGIN_HAS_GUI);
const bool isDssiVst = fFilename.contains("dssi-vst", true); const bool isDssiVst = fFilename.contains("dssi-vst", true);
const bool isZASX = fFilename.contains("zynaddsubfx", true); const bool isZASX = fFilename.contains("zynaddsubfx", true);


fHints = 0x0; fHints = 0x0;


if (haveGUI)
if (hasGUI)
fHints |= PLUGIN_HAS_GUI; fHints |= PLUGIN_HAS_GUI;


if (mIns == 1 && aIns == 0 && aOuts > 0) if (mIns == 1 && aIns == 0 && aOuts > 0)
@@ -840,34 +836,36 @@ public:
} }


if (count > 0) if (count > 0)
{
kData->midiprog.createNew(count); kData->midiprog.createNew(count);


// Update data
for (i=0; i < kData->midiprog.count; i++)
{
const DSSI_Program_Descriptor* const pdesc = fDssiDescriptor->get_program(fHandle, i);
CARLA_ASSERT(pdesc != nullptr);
CARLA_ASSERT(pdesc->Name != nullptr);
// Update data
for (i=0; i < count; i++)
{
const DSSI_Program_Descriptor* const pdesc = fDssiDescriptor->get_program(fHandle, i);
CARLA_ASSERT(pdesc != nullptr);
CARLA_ASSERT(pdesc->Name != nullptr);


kData->midiprog.data[i].bank = static_cast<uint32_t>(pdesc->Bank);
kData->midiprog.data[i].program = static_cast<uint32_t>(pdesc->Program);
kData->midiprog.data[i].name = carla_strdup(pdesc->Name);
kData->midiprog.data[i].bank = static_cast<uint32_t>(pdesc->Bank);
kData->midiprog.data[i].program = static_cast<uint32_t>(pdesc->Program);
kData->midiprog.data[i].name = carla_strdup(pdesc->Name);
}
} }


#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
// Update OSC Names // Update OSC Names
if (kData->engine->isOscControlRegistered()) if (kData->engine->isOscControlRegistered())
{ {
kData->engine->osc_send_control_set_midi_program_count(fId, kData->midiprog.count);
kData->engine->osc_send_control_set_midi_program_count(fId, count);


for (i=0; i < kData->midiprog.count; i++)
for (i=0; i < count; i++)
kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name); kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name);
} }
#endif #endif


if (init) if (init)
{ {
if (kData->midiprog.count > 0)
if (count > 0)
setMidiProgram(0, false, false, false); setMidiProgram(0, false, false, false);
} }
else else
@@ -875,30 +873,30 @@ public:
// Check if current program is invalid // Check if current program is invalid
bool programChanged = false; bool programChanged = false;


if (kData->midiprog.count == oldCount+1)
if (count == oldCount+1)
{ {
// one midi program added, probably created by user // one midi program added, probably created by user
kData->midiprog.current = oldCount; kData->midiprog.current = oldCount;
programChanged = true; programChanged = true;
} }
else if (current >= static_cast<int32_t>(kData->midiprog.count))
{
// current midi program > count
kData->midiprog.current = 0;
programChanged = true;
}
else if (current < 0 && kData->midiprog.count > 0)
else if (current < 0 && count > 0)
{ {
// programs exist now, but not before // programs exist now, but not before
kData->midiprog.current = 0; kData->midiprog.current = 0;
programChanged = true; programChanged = true;
} }
else if (current >= 0 && kData->midiprog.count == 0)
else if (current >= 0 && count == 0)
{ {
// programs existed before, but not anymore // programs existed before, but not anymore
kData->midiprog.current = -1; kData->midiprog.current = -1;
programChanged = true; programChanged = true;
} }
else if (current >= static_cast<int32_t>(count))
{
// current midi program > count
kData->midiprog.current = 0;
programChanged = true;
}
else else
{ {
// no change // no change


+ 2
- 2
source/backend/plugin/FluidSynthPlugin.cpp View File

@@ -818,9 +818,9 @@ public:
// Update OSC Names // Update OSC Names
if (kData->engine->isOscControlRegistered()) if (kData->engine->isOscControlRegistered())
{ {
kData->engine->osc_send_control_set_midi_program_count(fId, kData->midiprog.count);
kData->engine->osc_send_control_set_midi_program_count(fId, count);


for (i=0; i < kData->midiprog.count; i++)
for (i=0; i < count; i++)
kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name); kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name);
} }
#endif #endif


+ 2
- 2
source/backend/plugin/LinuxSamplerPlugin.cpp View File

@@ -427,9 +427,9 @@ public:
// Update OSC Names // Update OSC Names
if (kData->engine->isOscControlRegistered()) if (kData->engine->isOscControlRegistered())
{ {
kData->engine->osc_send_control_set_midi_program_count(fId, kData->midiprog.count);
kData->engine->osc_send_control_set_midi_program_count(fId, count);


for (i=0; i < kData->midiprog.count; i++)
for (i=0; i < count; i++)
kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name); kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name);
} }
#endif #endif


+ 29
- 22
source/backend/plugin/Lv2Plugin.cpp View File

@@ -550,7 +550,7 @@ public:
return getPluginCategoryFromName(m_name); return getPluginCategoryFromName(m_name);
} }


long uniqueId()
long uniqueId() const
{ {
CARLA_ASSERT(rdf_descriptor); CARLA_ASSERT(rdf_descriptor);


@@ -1853,34 +1853,36 @@ public:
} }


if (midiprog.count > 0) if (midiprog.count > 0)
{
midiprog.data = new MidiProgramData[midiprog.count]; midiprog.data = new MidiProgramData[midiprog.count];


// Update data
for (i=0; i < midiprog.count; i++)
{
const LV2_Program_Descriptor* const pdesc = ext.programs->get_program(handle, i);
CARLA_ASSERT(pdesc);
CARLA_ASSERT(pdesc->name);
// Update data
for (i=0; i < midiprog.count; i++)
{
const LV2_Program_Descriptor* const pdesc = ext.programs->get_program(handle, i);
CARLA_ASSERT(pdesc);
CARLA_ASSERT(pdesc->name);


midiprog.data[i].bank = pdesc->bank;
midiprog.data[i].program = pdesc->program;
midiprog.data[i].name = strdup(pdesc->name ? pdesc->name : "");
midiprog.data[i].bank = pdesc->bank;
midiprog.data[i].program = pdesc->program;
midiprog.data[i].name = strdup(pdesc->name ? pdesc->name : "");
}
} }


#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
// Update OSC Names // Update OSC Names
if (x_engine->isOscControlRegistered()) if (x_engine->isOscControlRegistered())
{ {
x_engine->osc_send_control_set_midi_program_count(m_id, midiprog.count);
x_engine->osc_send_control_set_midi_program_count(m_id, count);


for (i=0; i < midiprog.count; i++)
for (i=0; i < count; i++)
x_engine->osc_send_control_set_midi_program_data(m_id, i, midiprog.data[i].bank, midiprog.data[i].program, midiprog.data[i].name); x_engine->osc_send_control_set_midi_program_data(m_id, i, midiprog.data[i].bank, midiprog.data[i].program, midiprog.data[i].name);
} }
#endif #endif


if (init) if (init)
{ {
if (midiprog.count > 0)
if (count > 0)
setMidiProgram(0, false, false, false, true); setMidiProgram(0, false, false, false, true);
} }
else else
@@ -1890,30 +1892,35 @@ public:
// Check if current program is invalid // Check if current program is invalid
bool programChanged = false; bool programChanged = false;


if (midiprog.count == oldCount+1)
if (count == oldCount+1)
{ {
// one midi program added, probably created by user // one midi program added, probably created by user
midiprog.current = oldCount; midiprog.current = oldCount;
programChanged = true; programChanged = true;
} }
else if (midiprog.current >= (int32_t)midiprog.count)
{
// current midi program > count
midiprog.current = 0;
programChanged = true;
}
else if (midiprog.current < 0 && midiprog.count > 0)
else if (current < 0 && count > 0)
{ {
// programs exist now, but not before // programs exist now, but not before
midiprog.current = 0; midiprog.current = 0;
programChanged = true; programChanged = true;
} }
else if (midiprog.current >= 0 && midiprog.count == 0)
else if (current >= 0 && count == 0)
{ {
// programs existed before, but not anymore // programs existed before, but not anymore
midiprog.current = -1; midiprog.current = -1;
programChanged = true; programChanged = true;
} }
else if (current >= static_cast<int32_t>(count))
{
// current midi program > count
midiprog.current = 0;
programChanged = true;
}
else
{
// no change
kData->midiprog.current = current;
}


if (programChanged) if (programChanged)
setMidiProgram(midiprog.current, true, true, true, true); setMidiProgram(midiprog.current, true, true, true, true);


+ 28
- 25
source/backend/plugin/NativePlugin.cpp View File

@@ -952,34 +952,36 @@ public:
count = fDescriptor->get_midi_program_count(fHandle); count = fDescriptor->get_midi_program_count(fHandle);


if (count > 0) if (count > 0)
{
kData->midiprog.createNew(count); kData->midiprog.createNew(count);


// Update data
for (i=0; i < kData->midiprog.count; i++)
{
const ::MidiProgram* const mpDesc = fDescriptor->get_midi_program_info(fHandle, i);
CARLA_ASSERT(mpDesc != nullptr);
CARLA_ASSERT(mpDesc->name != nullptr);
// Update data
for (i=0; i < count; i++)
{
const ::MidiProgram* const mpDesc = fDescriptor->get_midi_program_info(fHandle, i);
CARLA_ASSERT(mpDesc != nullptr);
CARLA_ASSERT(mpDesc->name != nullptr);


kData->midiprog.data[i].bank = mpDesc->bank;
kData->midiprog.data[i].program = mpDesc->program;
kData->midiprog.data[i].name = carla_strdup(mpDesc->name);
kData->midiprog.data[i].bank = mpDesc->bank;
kData->midiprog.data[i].program = mpDesc->program;
kData->midiprog.data[i].name = carla_strdup(mpDesc->name);
}
} }


#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
// Update OSC Names // Update OSC Names
if (kData->engine->isOscControlRegistered()) if (kData->engine->isOscControlRegistered())
{ {
kData->engine->osc_send_control_set_midi_program_count(fId, kData->midiprog.count);
kData->engine->osc_send_control_set_midi_program_count(fId, count);


for (i=0; i < kData->midiprog.count; i++)
for (i=0; i < count; i++)
kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name); kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name);
} }
#endif #endif


if (init) if (init)
{ {
if (kData->midiprog.count > 0)
if (count > 0)
setMidiProgram(0, false, false, false); setMidiProgram(0, false, false, false);
} }
else else
@@ -987,30 +989,30 @@ public:
// Check if current program is invalid // Check if current program is invalid
bool programChanged = false; bool programChanged = false;


if (kData->midiprog.count == oldCount+1)
if (count == oldCount+1)
{ {
// one midi program added, probably created by user // one midi program added, probably created by user
kData->midiprog.current = oldCount; kData->midiprog.current = oldCount;
programChanged = true; programChanged = true;
} }
else if (current >= static_cast<int32_t>(kData->midiprog.count))
{
// current midi program > count
kData->midiprog.current = 0;
programChanged = true;
}
else if (current < 0 && kData->midiprog.count > 0)
else if (current < 0 && count > 0)
{ {
// programs exist now, but not before // programs exist now, but not before
kData->midiprog.current = 0; kData->midiprog.current = 0;
programChanged = true; programChanged = true;
} }
else if (current >= 0 && kData->midiprog.count == 0)
else if (current >= 0 && count == 0)
{ {
// programs existed before, but not anymore // programs existed before, but not anymore
kData->midiprog.current = -1; kData->midiprog.current = -1;
programChanged = true; programChanged = true;
} }
else if (current >= static_cast<int32_t>(count))
{
// current midi program > count
kData->midiprog.current = 0;
programChanged = true;
}
else else
{ {
// no change // no change
@@ -1872,10 +1874,11 @@ public:
// --------------------------------------------------------------- // ---------------------------------------------------------------
// get descriptor that matches label // get descriptor that matches label


// FIXME - use itenerator when available
for (size_t i=0; i < sPluginDescriptors.count(); i++)
for (auto it = sPluginDescriptors.begin(); it.valid(); it.next())
{ {
fDescriptor = sPluginDescriptors.getAt(i);
fDescriptor = *it;

CARLA_ASSERT(fDescriptor != nullptr);


if (fDescriptor == nullptr) if (fDescriptor == nullptr)
break; break;
@@ -2110,7 +2113,7 @@ CarlaPlugin* CarlaPlugin::newNative(const Initializer& init)


return plugin; return plugin;
#else #else
init.engine->setLastError("Internal plugins not available");
init.engine->setLastError("Internal plugins support not available");
return nullptr; return nullptr;
#endif #endif
} }


+ 93
- 0
source/backend/plugin/Vst3Plugin.cpp View File

@@ -0,0 +1,93 @@
/*
* Carla VST Plugin
* Copyright (C) 2011-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
*/

#include "CarlaPluginInternal.hpp"

#ifdef WANT_VST3

//#include "CarlaVstUtils.hpp"

CARLA_BACKEND_START_NAMESPACE

class Vst3Plugin : public CarlaPlugin
{
public:
Vst3Plugin(CarlaEngine* const engine, const unsigned short id)
: CarlaPlugin(engine, id)
{
carla_debug("Vst3Plugin::Vst3Plugin(%p, %i)", engine, id);
}

~Vst3Plugin()
{
carla_debug("Vst3Plugin::~Vst3Plugin()");

kData->singleMutex.lock();
kData->masterMutex.lock();
}

// -------------------------------------------------------------------
// Information (base)

PluginType type() const
{
return PLUGIN_VST3;
}

private:
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Vst3Plugin)
};

CARLA_BACKEND_END_NAMESPACE

#else // WANT_VST3
// no point on warning when the plugin doesn't even work yet
// # warning Building without VST3 support
#endif

CARLA_BACKEND_START_NAMESPACE

CarlaPlugin* CarlaPlugin::newVST3(const Initializer& init)
{
carla_debug("CarlaPlugin::newVST3(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label);

#ifdef WANT_VST3
Vst3Plugin* const plugin = new Vst3Plugin(init.engine, init.id);

//if (! plugin->init(init.filename, init.name, init.label))
{
delete plugin;
return nullptr;
}

plugin->reload();

if (init.engine->getProccessMode() == PROCESS_MODE_CONTINUOUS_RACK && ! CarlaPluginProtectedData::canRunInRack(plugin))
{
init.engine->setLastError("Carla's rack mode can only work with Stereo VST3 plugins, sorry!");
delete plugin;
return nullptr;
}

return plugin;
#else
init.engine->setLastError("VST3 support not available");
return nullptr;
#endif
}

CARLA_BACKEND_END_NAMESPACE

+ 320
- 249
source/backend/plugin/VstPlugin.cpp View File

@@ -140,11 +140,11 @@ public:
return getPluginCategoryFromName(fName); return getPluginCategoryFromName(fName);
} }


long uniqueId()
long uniqueId() const
{ {
CARLA_ASSERT(fEffect != nullptr); CARLA_ASSERT(fEffect != nullptr);


return fEffect ? fEffect->uniqueID : 0;
return (fEffect != nullptr) ? fEffect->uniqueID : 0;
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -313,7 +313,7 @@ public:
else if (index > static_cast<int32_t>(kData->prog.count)) else if (index > static_cast<int32_t>(kData->prog.count))
return; return;


if (index >= 0)
if (fEffect != nullptr && index >= 0)
{ {
const ScopedProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); const ScopedProcessLocker spl(this, (sendGui || sendOsc || sendCallback));


@@ -450,63 +450,65 @@ public:
CarlaPlugin::idleGui(); CarlaPlugin::idleGui();
} }


#if 0
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Plugin state // Plugin state


void reload() void reload()
{ {
carla_debug("VstPlugin::reload() - start"); carla_debug("VstPlugin::reload() - start");
CARLA_ASSERT(effect);
CARLA_ASSERT(kData->engine != nullptr);
CARLA_ASSERT(fEffect != nullptr);


const ProcessMode processMode(x_engine->getOptions().processMode);
const ProcessMode processMode(kData->engine->getProccessMode());


// Safely disable plugin for reload // Safely disable plugin for reload
const ScopedDisabler m(this);
const ScopedDisabler sd(this);


// Remove client ports
removeClientPorts();

// Delete old data
deleteBuffers(); deleteBuffers();


uint32_t aIns, aOuts, mIns, mOuts, params, j; uint32_t aIns, aOuts, mIns, mOuts, params, j;


aIns = effect->numInputs;
aOuts = effect->numOutputs;
params = effect->numParams;
bool needsCtrlIn, needsCtrlOut;
needsCtrlIn = needsCtrlOut = false;

aIns = fEffect->numInputs;
aOuts = fEffect->numOutputs;
params = fEffect->numParams;


if (vstPluginCanDo(effect, "receiveVstEvents") || vstPluginCanDo(effect, "receiveVstMidiEvent") || (effect->flags & effFlagsIsSynth) > 0 || (m_hints & PLUGIN_WANTS_MIDI_INPUT))
if (vstPluginCanDo(fEffect, "receiveVstEvents") || vstPluginCanDo(fEffect, "receiveVstMidiEvent") || (fEffect->flags & effFlagsIsSynth) > 0 || (fHints & PLUGIN_WANTS_MIDI_INPUT))
{
mIns = 1; mIns = 1;
needsCtrlIn = true;
}
else else
mIns = 0; mIns = 0;


if (vstPluginCanDo(effect, "sendVstEvents") || vstPluginCanDo(effect, "sendVstMidiEvent"))
if (vstPluginCanDo(fEffect, "sendVstEvents") || vstPluginCanDo(fEffect, "sendVstMidiEvent"))
{
mOuts = 1; mOuts = 1;
needsCtrlOut = true;
}
else else
mOuts = 0; mOuts = 0;


if (aIns > 0) if (aIns > 0)
{ {
aIn.ports = new CarlaEngineAudioPort*[aIns];
aIn.rindexes = new uint32_t[aIns];
kData->audioIn.createNew(aIns);
} }


if (aOuts > 0) if (aOuts > 0)
{ {
aOut.ports = new CarlaEngineAudioPort*[aOuts];
aOut.rindexes = new uint32_t[aOuts];
kData->audioOut.createNew(aOuts);
needsCtrlIn = true;
} }


if (params > 0) if (params > 0)
{ {
param.data = new ParameterData[params];
param.ranges = new ParameterRanges[params];
kData->param.createNew(params);
needsCtrlIn = true;
} }


bool needsCtrlIn = (aOuts > 0 || params > 0);

const int portNameSize = x_engine->maxPortNameSize();
const uint portNameSize = kData->engine->maxPortNameSize();
CarlaString portName; CarlaString portName;


// Audio Ins // Audio Ins
@@ -516,16 +518,21 @@ public:


if (processMode == PROCESS_MODE_SINGLE_CLIENT) if (processMode == PROCESS_MODE_SINGLE_CLIENT)
{ {
portName = m_name;
portName = fName;
portName += ":"; portName += ":";
} }


char tmp[12] = { 0 };
sprintf(tmp, "input_%02i", j+1);
portName += tmp;
if (aIns > 1)
{
portName += "input_";
portName += CarlaString(j+1);
}
else
portName += "input";
portName.truncate(portNameSize);


aIn.ports[j] = (CarlaEngineAudioPort*)x_client->addPort(CarlaEnginePortTypeAudio, portName, true);
aIn.rindexes[j] = j;
kData->audioIn.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, true);
kData->audioIn.ports[j].rindex = j;
} }


// Audio Outs // Audio Outs
@@ -535,82 +542,114 @@ public:


if (processMode == PROCESS_MODE_SINGLE_CLIENT) if (processMode == PROCESS_MODE_SINGLE_CLIENT)
{ {
portName = m_name;
portName = fName;
portName += ":"; portName += ":";
} }


char tmp[12] = { 0 };
sprintf(tmp, "output_%02i", j+1);
portName += tmp;
if (aOuts > 1)
{
portName += "output_";
portName += CarlaString(j+1);
}
else
portName += "output";
portName.truncate(portNameSize);


aOut.ports[j] = (CarlaEngineAudioPort*)x_client->addPort(CarlaEnginePortTypeAudio, portName, false);
aOut.rindexes[j] = j;
kData->audioOut.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, false);
kData->audioOut.ports[j].rindex = j;
} }


for (j=0; j < params; j++) for (j=0; j < params; j++)
{ {
param.data[j].type = PARAMETER_INPUT;
param.data[j].index = j;
param.data[j].rindex = j;
param.data[j].hints = 0;
param.data[j].midiChannel = 0;
param.data[j].midiCC = -1;
kData->param.data[j].type = PARAMETER_INPUT;
kData->param.data[j].index = j;
kData->param.data[j].rindex = j;
kData->param.data[j].hints = 0x0;
kData->param.data[j].midiChannel = 0;
kData->param.data[j].midiCC = -1;


double min, max, def, step, stepSmall, stepLarge;
float min, max, def, step, stepSmall, stepLarge;


VstParameterProperties prop; VstParameterProperties prop;
prop.flags = 0;
carla_zeroMem(&prop, sizeof(VstParameterProperties));


if (effect->dispatcher(effect, effGetParameterProperties, j, 0, &prop, 0))
if (fHints & PLUGIN_HAS_COCKOS_EXTENSIONS)
{ {
double range[2] = { 0.0, 1.0 }; double range[2] = { 0.0, 1.0 };


if ((m_hints & PLUGIN_HAS_COCKOS_EXTENSIONS) > 0 && effect->dispatcher(effect, effVendorSpecific, 0xdeadbef0, j, range, 0.0) >= 0xbeef)
if (dispatcher(effVendorSpecific, 0xdeadbef0, j, range, 0.0f) >= 0xbeef)
{ {
min = range[0]; min = range[0];
max = range[1]; max = range[1];

if (min > max)
max = min;
else if (max < min)
min = max;

if (max - min == 0.0f)
{
carla_stderr2("WARNING - Broken plugin parameter: max - min == 0.0f (with cockos extensions)");
max = min + 0.1f;
}
}
else
{
min = 0.0f;
max = 1.0f;
} }
else if (prop.flags & kVstParameterUsesIntegerMinMax)

if (dispatcher(effVendorSpecific, kVstParameterUsesIntStep, j, nullptr, 0.0f) >= 0xbeef)
{ {
min = prop.minInteger;
max = prop.maxInteger;
step = 1.0f;
stepSmall = 1.0f;
stepLarge = 10.0f;
} }
else else
{ {
min = 0.0;
max = 1.0;
float range = max - min;
step = range/100.0f;
stepSmall = range/1000.0f;
stepLarge = range/10.0f;
} }
}
else if (dispatcher(effGetParameterProperties, j, 0, &prop, 0) == 1)
{
if (prop.flags & kVstParameterUsesIntegerMinMax)
{
min = float(prop.minInteger);
max = float(prop.maxInteger);


if (min > max)
max = min;
else if (max < min)
min = max;
if (min > max)
max = min;
else if (max < min)
min = max;


if (max - min == 0.0)
{
carla_stderr("Broken plugin parameter: max - min == 0");
max = min + 0.1;
if (max - min == 0.0f)
{
carla_stderr2("WARNING - Broken plugin parameter: max - min == 0.0f");
max = min + 0.1f;
}
} }

if ((m_hints & PLUGIN_HAS_COCKOS_EXTENSIONS) > 0 && effect->dispatcher(effect, effVendorSpecific, kVstParameterUsesIntStep, j, nullptr, 0.0f) >= 0xbeef)
else
{ {
step = 1.0;
stepSmall = 1.0;
stepLarge = 10.0;
min = 0.0f;
max = 1.0f;
} }
else if (prop.flags & kVstParameterIsSwitch)

if (prop.flags & kVstParameterIsSwitch)
{ {
step = max - min; step = max - min;
stepSmall = step; stepSmall = step;
stepLarge = step; stepLarge = step;
param.data[j].hints |= PARAMETER_IS_BOOLEAN;
kData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
} }
else if (prop.flags & kVstParameterUsesIntStep) else if (prop.flags & kVstParameterUsesIntStep)
{ {
step = prop.stepInteger;
stepSmall = prop.stepInteger;
stepLarge = prop.largeStepInteger;
param.data[j].hints |= PARAMETER_IS_INTEGER;
step = float(prop.stepInteger);
stepSmall = float(prop.stepInteger)/10;
stepLarge = float(prop.largeStepInteger);
kData->param.data[j].hints |= PARAMETER_IS_INTEGER;
} }
else if (prop.flags & kVstParameterUsesFloatStep) else if (prop.flags & kVstParameterUsesFloatStep)
{ {
@@ -620,46 +659,46 @@ public:
} }
else else
{ {
double range = max - min;
step = range/100.0;
stepSmall = range/1000.0;
stepLarge = range/10.0;
float range = max - min;
step = range/100.0f;
stepSmall = range/1000.0f;
stepLarge = range/10.0f;
} }


if (prop.flags & kVstParameterCanRamp) if (prop.flags & kVstParameterCanRamp)
param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
kData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
} }
else else
{ {
min = 0.0;
max = 1.0;
step = 0.001;
stepSmall = 0.0001;
stepLarge = 0.1;
min = 0.0f;
max = 1.0f;
step = 0.001f;
stepSmall = 0.0001f;
stepLarge = 0.1f;
} }


kData->param.data[j].hints |= PARAMETER_IS_ENABLED;
#ifndef BUILD_BRIDGE
kData->param.data[j].hints |= PARAMETER_USES_CUSTOM_TEXT;
#endif

if ((fHints & PLUGIN_USES_OLD_VSTSDK) != 0 || dispatcher(effCanBeAutomated, j, 0, nullptr, 0.0f) == 1)
kData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;

// no such thing as VST default parameters // no such thing as VST default parameters
def = effect->getParameter(effect, j);
def = fEffect->getParameter(fEffect, j);


if (def < min) if (def < min)
def = min; def = min;
else if (def > max) else if (def > max)
def = max; def = max;


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;

param.data[j].hints |= PARAMETER_IS_ENABLED;
#ifndef BUILD_BRIDGE
param.data[j].hints |= PARAMETER_USES_CUSTOM_TEXT;
#endif

if ((m_hints & PLUGIN_USES_OLD_VSTSDK) > 0 || effect->dispatcher(effect, effCanBeAutomated, j, 0, nullptr, 0.0f) == 1)
param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
kData->param.ranges[j].min = min;
kData->param.ranges[j].max = max;
kData->param.ranges[j].def = def;
kData->param.ranges[j].step = step;
kData->param.ranges[j].stepSmall = stepSmall;
kData->param.ranges[j].stepLarge = stepLarge;
} }


if (needsCtrlIn) if (needsCtrlIn)
@@ -668,96 +707,130 @@ public:


if (processMode == PROCESS_MODE_SINGLE_CLIENT) if (processMode == PROCESS_MODE_SINGLE_CLIENT)
{ {
portName = m_name;
portName = fName;
portName += ":"; portName += ":";
} }


portName += "control-in";
portName += "event-in";
portName.truncate(portNameSize); portName.truncate(portNameSize);


param.portCin = (CarlaEngineControlPort*)x_client->addPort(CarlaEnginePortTypeControl, portName, true);
kData->event.portIn = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, true);
} }


if (mIns == 1)
if (needsCtrlOut)
{ {
portName.clear(); portName.clear();


if (processMode == PROCESS_MODE_SINGLE_CLIENT) if (processMode == PROCESS_MODE_SINGLE_CLIENT)
{ {
portName = m_name;
portName = fName;
portName += ":"; portName += ":";
} }


portName += "midi-in";
portName += "event-out";
portName.truncate(portNameSize); portName.truncate(portNameSize);


midi.portMin = (CarlaEngineMidiPort*)x_client->addPort(CarlaEnginePortTypeMIDI, portName, true);
kData->event.portOut = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, false);
} }


if (mOuts == 1)
{
portName.clear();
// plugin hints
const intptr_t vstCategory = dispatcher(effGetPlugCategory, 0, 0, nullptr, 0.0f);


if (processMode == PROCESS_MODE_SINGLE_CLIENT)
{
portName = m_name;
portName += ":";
}
fHints = 0x0;


portName += "midi-out";
portName.truncate(portNameSize);
if (vstCategory == kPlugCategSynth || vstCategory == kPlugCategGenerator)
fHints |= PLUGIN_IS_SYNTH;


midi.portMout = (CarlaEngineMidiPort*)x_client->addPort(CarlaEnginePortTypeMIDI, portName, false);
}
if (fEffect->flags & effFlagsHasEditor)
{
fHints |= PLUGIN_HAS_GUI;


aIn.count = aIns;
aOut.count = aOuts;
param.count = params;
if (! fGui.isOsc)
fHints |= PLUGIN_HAS_SINGLE_THREAD;
}


// plugin checks
m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE | PLUGIN_CAN_FORCE_STEREO);
if (dispatcher(effGetVstVersion, 0, 0, nullptr, 0.0f) < kVstVersion)
fHints |= PLUGIN_USES_OLD_VSTSDK;


intptr_t vstCategory = effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f);
if ((fEffect->flags & effFlagsCanReplacing) != 0 && fEffect->processReplacing != fEffect->process)
fHints |= PLUGIN_CAN_PROCESS_REPLACING;


if (vstCategory == kPlugCategSynth || vstCategory == kPlugCategGenerator)
m_hints |= PLUGIN_IS_SYNTH;
if (fEffect->flags & effFlagsHasEditor)
fHints |= PLUGIN_HAS_GUI;


if (effect->flags & effFlagsProgramChunks)
m_hints |= PLUGIN_USES_CHUNKS;
if (static_cast<uintptr_t>(dispatcher(effCanDo, 0, 0, (void*)"hasCockosExtensions", 0.0f)) == 0xbeef0000)
fHints |= PLUGIN_HAS_COCKOS_EXTENSIONS;


if (aOuts > 0 && (aIns == aOuts || aIns == 1)) if (aOuts > 0 && (aIns == aOuts || aIns == 1))
m_hints |= PLUGIN_CAN_DRYWET;
fHints |= PLUGIN_CAN_DRYWET;


if (aOuts > 0) if (aOuts > 0)
m_hints |= PLUGIN_CAN_VOLUME;
fHints |= PLUGIN_CAN_VOLUME;

if (aOuts >= 2 && aOuts % 2 == 0)
fHints |= PLUGIN_CAN_BALANCE;

// extra plugin hints
kData->extraHints = 0x0;


if (aOuts >= 2 && aOuts%2 == 0)
m_hints |= PLUGIN_CAN_BALANCE;
if (mIns > 0)
kData->extraHints |= PLUGIN_HINT_HAS_MIDI_IN;


if ((aIns == 0 || aIns == 2) && (aOuts == 0 || aOuts == 2))
m_hints |= PLUGIN_CAN_FORCE_STEREO;
if (mOuts > 0)
kData->extraHints |= PLUGIN_HINT_HAS_MIDI_OUT;

if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0))
kData->extraHints |= PLUGIN_HINT_CAN_RUN_RACK;

// plugin options
fOptions = 0x0;

fOptions |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;

if (fEffect->flags & effFlagsProgramChunks)
fOptions |= PLUGIN_OPTION_USE_CHUNKS;

#ifdef CARLA_OS_WIN
// Most Windows plugins have issues with this
fOptions |= PLUGIN_OPTION_FIXED_BUFFER;
#endif

if (mIns > 0)
{
fOptions |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
fOptions |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
fOptions |= PLUGIN_OPTION_SEND_PITCHBEND;
fOptions |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
}

// dummy pre-start to catch latency and possible wantEvents() call on old plugins
{
dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f);
dispatcher(effStartProcess, 0, 0, nullptr, 0.0f);
dispatcher(effStopProcess, 0, 0, nullptr, 0.0f);
dispatcher(effMainsChanged, 0, 0, nullptr, 0.0f);
}


// check latency // check latency
if (m_hints & PLUGIN_CAN_DRYWET)
if (fHints & PLUGIN_CAN_DRYWET)
{ {
#ifdef VESTIGE_HEADER #ifdef VESTIGE_HEADER
char* const empty3Ptr = &effect->empty3[0];
char* const empty3Ptr = &fEffect->empty3[0];
int32_t* initialDelayPtr = (int32_t*)empty3Ptr; int32_t* initialDelayPtr = (int32_t*)empty3Ptr;
m_latency = *initialDelayPtr;
kData->latency = *initialDelayPtr;
#else #else
m_latency = effect->initialDelay;
kData->latency = fEffect->initialDelay;
#endif #endif


x_client->setLatency(m_latency);
kData->client->setLatency(kData->latency);
recreateLatencyBuffers(); recreateLatencyBuffers();
} }


// special plugin fixes // special plugin fixes
#ifdef __WINE__
// 1. IL Harmless - disable threaded processing // 1. IL Harmless - disable threaded processing
if (effect->uniqueID == 1229484653)
if (fEffect->uniqueID == 1229484653)
{ {
char strBuf[255] = { 0 };
char strBuf[STR_MAX] = { 0 };
getLabel(strBuf); getLabel(strBuf);


if (std::strcmp(strBuf, "IL Harmless") == 0) if (std::strcmp(strBuf, "IL Harmless") == 0)
@@ -765,8 +838,8 @@ public:
// TODO - disable threaded processing // TODO - disable threaded processing
} }
} }
#endif


bufferSizeChanged(kData->engine->getBufferSize());
reloadPrograms(true); reloadPrograms(true);


carla_debug("VstPlugin::reload() - end"); carla_debug("VstPlugin::reload() - end");
@@ -775,100 +848,96 @@ public:
void reloadPrograms(const bool init) void reloadPrograms(const bool init)
{ {
carla_debug("VstPlugin::reloadPrograms(%s)", bool2str(init)); carla_debug("VstPlugin::reloadPrograms(%s)", bool2str(init));
uint32_t i, oldCount = prog.count;
uint32_t i, oldCount = kData->prog.count;
const int32_t current = kData->prog.current;


// Delete old programs // Delete old programs
if (prog.count > 0)
{
for (i=0; i < prog.count; i++)
{
if (prog.names[i])
free((void*)prog.names[i]);
}

delete[] prog.names;
}

prog.count = 0;
prog.names = nullptr;
kData->prog.clear();


// Query new programs // Query new programs
prog.count = effect->numPrograms;

if (prog.count > 0)
prog.names = new const char* [prog.count];
uint32_t count = static_cast<uint32_t>(fEffect->numPrograms);


// Update names
for (i=0; i < prog.count; i++)
if (count > 0)
{ {
char strBuf[STR_MAX] = { 0 };
if (effect->dispatcher(effect, effGetProgramNameIndexed, i, 0, strBuf, 0.0f) != 1)
kData->prog.createNew(count);

// Update names
for (i=0; i < count; i++)
{ {
// program will be [re-]changed later
effect->dispatcher(effect, effSetProgram, 0, i, nullptr, 0.0f);
effect->dispatcher(effect, effGetProgramName, 0, 0, strBuf, 0.0f);
char strBuf[STR_MAX] = { 0 };
if (dispatcher(effGetProgramNameIndexed, i, 0, strBuf, 0.0f) != 1)
{
// program will be [re-]changed later
dispatcher(effSetProgram, 0, i, nullptr, 0.0f);
dispatcher(effGetProgramName, 0, 0, strBuf, 0.0f);
}
kData->prog.names[i] = strdup(strBuf);
} }
prog.names[i] = strdup(strBuf);
} }


#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
// Update OSC Names // Update OSC Names
if (x_engine->isOscControlRegistered())
if (kData->engine->isOscControlRegistered())
{ {
x_engine->osc_send_control_set_program_count(m_id, prog.count);
kData->engine->osc_send_control_set_program_count(fId, count);


for (i=0; i < prog.count; i++)
x_engine->osc_send_control_set_program_name(m_id, i, prog.names[i]);
for (i=0; i < count; i++)
kData->engine->osc_send_control_set_program_name(fId, i, kData->prog.names[i]);
} }
#endif #endif


if (init) if (init)
{ {
if (prog.count > 0)
setProgram(0, false, false, false, true);
if (count > 0)
setProgram(0, false, false, false);
} }
else else
{ {
x_engine->callback(CALLBACK_RELOAD_PROGRAMS, m_id, 0, 0, 0.0, nullptr);

// Check if current program is invalid // Check if current program is invalid
bool programChanged = false; bool programChanged = false;


if (prog.count == oldCount+1)
if (count == oldCount+1)
{ {
// one program added, probably created by user // one program added, probably created by user
prog.current = oldCount;
kData->prog.current = oldCount;
programChanged = true; programChanged = true;
} }
else if (prog.current >= (int32_t)prog.count)
else if (current < 0 && count > 0)
{ {
// current program > count
prog.current = 0;
// programs exist now, but not before
kData->prog.current = 0;
programChanged = true; programChanged = true;
} }
else if (prog.current < 0 && prog.count > 0)
else if (current >= 0 && count == 0)
{ {
// programs exist now, but not before
prog.current = 0;
// programs existed before, but not anymore
kData->prog.current = -1;
programChanged = true; programChanged = true;
} }
else if (prog.current >= 0 && prog.count == 0)
else if (current >= static_cast<int32_t>(count))
{ {
// programs existed before, but not anymore
prog.current = -1;
// current program > count
kData->prog.current = 0;
programChanged = true; programChanged = true;
} }
else
{
// no change
kData->prog.current = current;
}


if (programChanged) if (programChanged)
{ {
setProgram(prog.current, true, true, true, true);
setProgram(kData->prog.current, true, true, true);
} }
else else
{ {
// Program was changed during update, re-set it // Program was changed during update, re-set it
if (prog.current >= 0)
effect->dispatcher(effect, effSetProgram, 0, prog.current, nullptr, 0.0f);
if (kData->prog.current >= 0)
dispatcher(effSetProgram, 0, kData->prog.current, nullptr, 0.0f);
} }

kData->engine->callback(CALLBACK_RELOAD_PROGRAMS, fId, 0, 0, 0.0f, nullptr);
} }
} }


@@ -880,6 +949,7 @@ public:
uint32_t i, k; uint32_t i, k;
uint32_t midiEventCount = 0; uint32_t midiEventCount = 0;


#if 0
vstTimeOffset = 0; vstTimeOffset = 0;


double aInsPeak[2] = { 0.0 }; double aInsPeak[2] = { 0.0 };
@@ -1406,25 +1476,26 @@ public:
x_engine->setOutputPeak(m_id, 1, aOutsPeak[1]); x_engine->setOutputPeak(m_id, 1, aOutsPeak[1]);


m_activeBefore = m_active; m_activeBefore = m_active;
#endif
} }


void bufferSizeChanged(uint32_t newBufferSize) void bufferSizeChanged(uint32_t newBufferSize)
{ {
if (m_active)
if (kData->active)
{ {
effect->dispatcher(effect, effStopProcess, 0, 0, nullptr, 0.0f);
effect->dispatcher(effect, effMainsChanged, 0, 0, nullptr, 0.0f);
dispatcher(effStopProcess, 0, 0, nullptr, 0.0f);
dispatcher(effMainsChanged, 0, 0, nullptr, 0.0f);
} }


#if ! VST_FORCE_DEPRECATED #if ! VST_FORCE_DEPRECATED
effect->dispatcher(effect, effSetBlockSizeAndSampleRate, 0, newBufferSize, nullptr, x_engine->getSampleRate());
dispatcher(effSetBlockSizeAndSampleRate, 0, newBufferSize, nullptr, kData->engine->getSampleRate());
#endif #endif
effect->dispatcher(effect, effSetBlockSize, 0, newBufferSize, nullptr, 0.0f);
dispatcher(effSetBlockSize, 0, newBufferSize, nullptr, 0.0f);


if (m_active)
if (kData->active)
{ {
effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0.0f);
effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f);
dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f);
dispatcher(effStartProcess, 0, 0, nullptr, 0.0f);
} }
} }


@@ -1433,58 +1504,81 @@ public:


void uiParameterChange(const uint32_t index, const double value) void uiParameterChange(const uint32_t index, const double value)
{ {
CARLA_ASSERT(index < param.count);
CARLA_ASSERT(index < kData->param.count);


if (index >= param.count)
if (index >= kData->param.count)
return;
if (! fGui.isOsc)
return;
if (kData->osc.data.target == nullptr)
return; return;


if (gui.type == GUI_EXTERNAL_OSC && osc.data.target)
osc_send_control(&osc.data, param.data[index].rindex, value);
osc_send_control(&kData->osc.data, kData->param.data[index].rindex, value);
} }


void uiProgramChange(const uint32_t index) void uiProgramChange(const uint32_t index)
{ {
CARLA_ASSERT(index < prog.count);
CARLA_ASSERT(index < kData->prog.count);


if (index >= prog.count)
if (index >= kData->prog.count)
return;
if (! fGui.isOsc)
return;
if (kData->osc.data.target == nullptr)
return; return;


if (gui.type == GUI_EXTERNAL_OSC && osc.data.target)
osc_send_program(&osc.data, index);
osc_send_program(&kData->osc.data, index);
} }


void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo)
{ {
CARLA_ASSERT(channel < 16);
CARLA_ASSERT(note < 128);
CARLA_ASSERT(velo > 0 && velo < 128);
CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
CARLA_ASSERT(note < MAX_MIDI_NOTE);
CARLA_ASSERT(velo > 0 && velo < MAX_MIDI_VALUE);


if (gui.type == GUI_EXTERNAL_OSC && osc.data.target)
{
uint8_t midiData[4] = { 0 };
midiData[1] = MIDI_STATUS_NOTE_ON + channel;
midiData[2] = note;
midiData[3] = velo;
osc_send_midi(&osc.data, midiData);
}
if (channel >= MAX_MIDI_CHANNELS)
return;
if (note >= MAX_MIDI_NOTE)
return;
if (velo >= MAX_MIDI_VALUE)
return;
if (! fGui.isOsc)
return;
if (kData->osc.data.target == nullptr)
return;

uint8_t midiData[4] = { 0 };
midiData[1] = MIDI_STATUS_NOTE_ON + channel;
midiData[2] = note;
midiData[3] = velo;

osc_send_midi(&kData->osc.data, midiData);
} }


void uiNoteOff(const uint8_t channel, const uint8_t note) void uiNoteOff(const uint8_t channel, const uint8_t note)
{ {
CARLA_ASSERT(channel < 16);
CARLA_ASSERT(note < 128);
CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
CARLA_ASSERT(note < MAX_MIDI_NOTE);


if (gui.type == GUI_EXTERNAL_OSC && osc.data.target)
{
uint8_t midiData[4] = { 0 };
midiData[1] = MIDI_STATUS_NOTE_OFF + channel;
midiData[2] = note;
osc_send_midi(&osc.data, midiData);
}
if (channel >= MAX_MIDI_CHANNELS)
return;
if (note >= MAX_MIDI_NOTE)
return;
if (! fGui.isOsc)
return;
if (kData->osc.data.target == nullptr)
return;

uint8_t midiData[4] = { 0 };
midiData[1] = MIDI_STATUS_NOTE_OFF + channel;
midiData[2] = note;

osc_send_midi(&kData->osc.data, midiData);
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------


#if 0
intptr_t handleAudioMasterTempoAt() intptr_t handleAudioMasterTempoAt()
{ {
const CarlaEngineTimeInfo* const timeInfo = x_engine->getTimeInfo(); const CarlaEngineTimeInfo* const timeInfo = x_engine->getTimeInfo();
@@ -1974,8 +2068,6 @@ public:
#endif #endif


dispatcher(effOpen, 0, 0, nullptr, 0.0f); dispatcher(effOpen, 0, 0, nullptr, 0.0f);
//dispatcher(effStopProcess, 0, 0, nullptr, 0.0f);
//dispatcher(effMainsChanged, 0, 0, nullptr, 0.0f);


// --------------------------------------------------------------- // ---------------------------------------------------------------
// get info // get info
@@ -2021,34 +2113,17 @@ public:
dispatcher(effStopProcess, 0, 0, nullptr, 0.0f); dispatcher(effStopProcess, 0, 0, nullptr, 0.0f);
dispatcher(effMainsChanged, 0, 0, nullptr, 0.0f); dispatcher(effMainsChanged, 0, 0, nullptr, 0.0f);


#if ! VST_FORCE_DEPRECATED
// dummy pre-start to catch possible wantEvents() call on old plugins
//dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f);
//dispatcher(effStartProcess, 0, 0, nullptr, 0.0f);
//dispatcher(effStopProcess, 0, 0, nullptr, 0.0f);
//dispatcher(effMainsChanged, 0, 0, nullptr, 0.0f);
#endif

// special checks
if (static_cast<uintptr_t>(dispatcher(effCanDo, 0, 0, (void*)"hasCockosExtensions", 0.0f)) == 0xbeef0000)
{
carla_debug("Plugin has Cockos extensions!");
fHints |= PLUGIN_HAS_COCKOS_EXTENSIONS;
}

if (dispatcher(effGetVstVersion, 0, 0, nullptr, 0.0f) < kVstVersion) if (dispatcher(effGetVstVersion, 0, 0, nullptr, 0.0f) < kVstVersion)
fHints |= PLUGIN_USES_OLD_VSTSDK; fHints |= PLUGIN_USES_OLD_VSTSDK;


if ((fEffect->flags & effFlagsCanReplacing) != 0 && fEffect->processReplacing != fEffect->process)
fHints |= PLUGIN_CAN_PROCESS_REPLACING;
if (static_cast<uintptr_t>(dispatcher(effCanDo, 0, 0, (void*)"hasCockosExtensions", 0.0f)) == 0xbeef0000)
fHints |= PLUGIN_HAS_COCKOS_EXTENSIONS;


// --------------------------------------------------------------- // ---------------------------------------------------------------
// gui stuff // gui stuff


if (fEffect->flags & effFlagsHasEditor) if (fEffect->flags & effFlagsHasEditor)
{ {
fHints |= PLUGIN_HAS_GUI;

const EngineOptions& engineOptions(kData->engine->getOptions()); const EngineOptions& engineOptions(kData->engine->getOptions());


if (engineOptions.preferUiBridges && engineOptions.bridge_vstx11.isNotEmpty() && (fEffect->flags & effFlagsProgramChunks) == 0) if (engineOptions.preferUiBridges && engineOptions.bridge_vstx11.isNotEmpty() && (fEffect->flags & effFlagsProgramChunks) == 0)
@@ -2056,10 +2131,6 @@ public:
kData->osc.thread.setOscData(engineOptions.bridge_vstx11, label); kData->osc.thread.setOscData(engineOptions.bridge_vstx11, label);
fGui.isOsc = true; fGui.isOsc = true;
} }
else
{
fHints |= PLUGIN_HAS_SINGLE_THREAD;
}
} }


return true; return true;


+ 1
- 1
source/utils/CarlaVstUtils.hpp View File

@@ -128,7 +128,7 @@ typedef AEffect* (*VST_Function)(audioMasterCallback);
// Check if feature is supported by the plugin // Check if feature is supported by the plugin


static inline static inline
bool vstPluginCanDo(AEffect* const effect, char* const feature)
bool vstPluginCanDo(AEffect* const effect, const char* const feature)
{ {
return (effect->dispatcher(effect, effCanDo, 0, 0, (void*)feature, 0.0f) == 1); return (effect->dispatcher(effect, effCanDo, 0, 0, (void*)feature, 0.0f) == 1);
} }


Loading…
Cancel
Save