Browse Source

CLAP: Deal with sending params to UI, idle callback

pull/321/merge
falkTX 2 years ago
parent
commit
f4d3e6bfbe
3 changed files with 140 additions and 64 deletions
  1. +135
    -60
      distrho/src/DistrhoPluginCLAP.cpp
  2. +4
    -4
      distrho/src/DistrhoUIInternal.hpp
  3. +1
    -0
      examples/Meters/Makefile

+ 135
- 60
distrho/src/DistrhoPluginCLAP.cpp View File

@@ -30,12 +30,11 @@


START_NAMESPACE_DISTRHO START_NAMESPACE_DISTRHO


#if DISTRHO_PLUGIN_HAS_UI

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


struct ClapEventQueue struct ClapEventQueue
{ {
#if DISTRHO_PLUGIN_HAS_UI
enum EventType { enum EventType {
kEventGestureBegin, kEventGestureBegin,
kEventGestureEnd, kEventGestureEnd,
@@ -45,8 +44,7 @@ struct ClapEventQueue
struct Event { struct Event {
EventType type; EventType type;
uint32_t index; uint32_t index;
float plain;
double value;
float value;
}; };


struct Queue { struct Queue {
@@ -83,12 +81,44 @@ struct ClapEventQueue
std::memcpy(&events[used++], &event, sizeof(Event)); std::memcpy(&events[used++], &event, sizeof(Event));
} }
} fEventQueue; } fEventQueue;
#endif

struct CachedParameters {
uint numParams;
bool* changed;
float* values;

CachedParameters()
: changed(nullptr),
values(nullptr) {}

~CachedParameters()
{
delete[] changed;
delete[] values;
}

void setup(const uint numParameters)
{
if (numParameters == 0)
return;

numParams = numParameters;
changed = new bool[numParameters];
values = new float[numParameters];

std::memset(changed, 0, sizeof(bool)*numParameters);
std::memset(values, 0, sizeof(float)*numParameters);
}
} fCachedParameters;


virtual ~ClapEventQueue() {} virtual ~ClapEventQueue() {}
}; };


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


#if DISTRHO_PLUGIN_HAS_UI

#if ! DISTRHO_PLUGIN_WANT_STATE #if ! DISTRHO_PLUGIN_WANT_STATE
static constexpr const setStateFunc setStateCallback = nullptr; static constexpr const setStateFunc setStateCallback = nullptr;
#endif #endif
@@ -99,20 +129,33 @@ static constexpr const sendNoteFunc sendNoteCallback = nullptr;
/** /**
* CLAP UI class. * CLAP UI class.
*/ */
class ClapUI
class ClapUI : public IdleCallback
{ {
public: public:
ClapUI(PluginExporter& plugin, ClapEventQueue* const eventQueue, const bool isFloating) ClapUI(PluginExporter& plugin, ClapEventQueue* const eventQueue, const bool isFloating)
: fPlugin(plugin), : fPlugin(plugin),
fEventQueue(eventQueue->fEventQueue), fEventQueue(eventQueue->fEventQueue),
fCachedParameters(eventQueue->fCachedParameters),
fUI(), fUI(),
fIsFloating(isFloating), fIsFloating(isFloating),
fCallbackRegistered(false),
fScaleFactor(0.0), fScaleFactor(0.0),
fParentWindow(0), fParentWindow(0),
fTransientWindow(0) fTransientWindow(0)
{ {
} }


~ClapUI() override
{
if (fCallbackRegistered)
{
#if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS)
if (UIExporter* const ui = fUI.get())
ui->removeIdleCallbackForVST3(this);
#endif
}
}

bool setScaleFactor(const double scaleFactor) bool setScaleFactor(const double scaleFactor)
{ {
if (d_isEqual(fScaleFactor, scaleFactor)) if (d_isEqual(fScaleFactor, scaleFactor))
@@ -283,13 +326,23 @@ public:
if (fIsFloating) if (fIsFloating)
fUI->setWindowVisible(true); fUI->setWindowVisible(true);


#if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS)
fUI->addIdleCallbackForVST3(this, 16);
#endif
fCallbackRegistered = true;
return true; return true;
} }


bool hide() bool hide()
{ {
if (UIExporter* const ui = fUI.get()) if (UIExporter* const ui = fUI.get())
{
ui->setWindowVisible(false); ui->setWindowVisible(false);
#if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS)
ui->removeIdleCallbackForVST3(this);
#endif
fCallbackRegistered = false;
}


return true; return true;
} }
@@ -300,11 +353,13 @@ private:
// Plugin and UI // Plugin and UI
PluginExporter& fPlugin; PluginExporter& fPlugin;
ClapEventQueue::Queue& fEventQueue; ClapEventQueue::Queue& fEventQueue;
ClapEventQueue::CachedParameters& fCachedParameters;
ScopedPointer<UIExporter> fUI; ScopedPointer<UIExporter> fUI;


const bool fIsFloating; const bool fIsFloating;


// Temporary data // Temporary data
bool fCallbackRegistered;
double fScaleFactor; double fScaleFactor;
uintptr_t fParentWindow; uintptr_t fParentWindow;
uintptr_t fTransientWindow; uintptr_t fTransientWindow;
@@ -337,7 +392,25 @@ private:
if (fTransientWindow != 0) if (fTransientWindow != 0)
fUI->setWindowTransientWinId(fTransientWindow); fUI->setWindowTransientWinId(fTransientWindow);
} }
}

void idleCallback() override
{
#if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS)
if (UIExporter* const ui = fUI.get())
{
ui->idleForVST3();


for (uint i=0; i<fCachedParameters.numParams; ++i)
{
if (fCachedParameters.changed[i])
{
fCachedParameters.changed[i] = false;
ui->parameterChanged(i, fCachedParameters.values[i]);
}
}
}
#endif
} }


// ---------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------------
@@ -347,7 +420,7 @@ private:
{ {
const ClapEventQueue::Event ev = { const ClapEventQueue::Event ev = {
started ? ClapEventQueue::kEventGestureBegin : ClapEventQueue::kEventGestureBegin, started ? ClapEventQueue::kEventGestureBegin : ClapEventQueue::kEventGestureBegin,
rindex, 0.f, 0.0
rindex, 0.f
}; };
fEventQueue.addEventFromUI(ev); fEventQueue.addEventFromUI(ev);
} }
@@ -357,17 +430,11 @@ private:
static_cast<ClapUI*>(ptr)->editParameter(rindex, started); static_cast<ClapUI*>(ptr)->editParameter(rindex, started);
} }


void setParameterValue(const uint32_t rindex, const float plain)
void setParameterValue(const uint32_t rindex, const float value)
{ {
double value;
if (fPlugin.isParameterInteger(rindex))
value = plain;
else
value = fPlugin.getParameterRanges(rindex).getNormalizedValue(static_cast<double>(plain));

const ClapEventQueue::Event ev = { const ClapEventQueue::Event ev = {
ClapEventQueue::kEventParamSet, ClapEventQueue::kEventParamSet,
rindex, plain, value
rindex, value
}; };
fEventQueue.addEventFromUI(ev); fEventQueue.addEventFromUI(ev);
} }
@@ -438,10 +505,7 @@ static constexpr const updateStateValueFunc updateStateValueCallback = nullptr;
/** /**
* CLAP plugin class. * CLAP plugin class.
*/ */
class PluginCLAP
#if DISTRHO_PLUGIN_HAS_UI
: ClapEventQueue
#endif
class PluginCLAP : ClapEventQueue
{ {
public: public:
PluginCLAP(const clap_host_t* const host) PluginCLAP(const clap_host_t* const host)
@@ -452,6 +516,7 @@ public:
fHost(host), fHost(host),
fOutputEvents(nullptr) fOutputEvents(nullptr)
{ {
fCachedParameters.setup(fPlugin.getParameterCount());
} }


// ---------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------------
@@ -514,7 +579,7 @@ public:
clapEvent.header.type = CLAP_EVENT_PARAM_VALUE; clapEvent.header.type = CLAP_EVENT_PARAM_VALUE;
clapEvent.param_id = event.index; clapEvent.param_id = event.index;
clapEvent.value = event.value; clapEvent.value = event.value;
fPlugin.setParameterValue(event.index, event.plain);
fPlugin.setParameterValue(event.index, event.value);
break; break;
default: default:
continue; continue;
@@ -649,11 +714,14 @@ public:
fOutputEvents = process->out_events; fOutputEvents = process->out_events;


#if DISTRHO_PLUGIN_WANT_MIDI_INPUT #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
fPlugin.run(inputs, outputs, frames, fMidiEvents, midiEventCount);
fPlugin.run(inputs, outputs, frames, nullptr, 0);
#else #else
fPlugin.run(inputs, outputs, frames); fPlugin.run(inputs, outputs, frames);
#endif #endif


// TODO set last frame
flushParameters(nullptr, process->out_events);

fOutputEvents = nullptr; fOutputEvents = nullptr;
} }


@@ -720,42 +788,29 @@ public:


bool getParameterValue(const clap_id param_id, double* const value) const bool getParameterValue(const clap_id param_id, double* const value) const
{ {
const float plain = fPlugin.getParameterValue(param_id);

if (fPlugin.isParameterInteger(param_id))
{
*value = plain;
return true;
}

*value = fPlugin.getParameterRanges(param_id).getNormalizedValue(static_cast<double>(plain));
*value = fPlugin.getParameterValue(param_id);
return true; return true;
} }


bool getParameterStringForValue(const clap_id param_id, const double value, char* const display, const uint32_t size) const
bool getParameterStringForValue(const clap_id param_id, double value, char* const display, const uint32_t size) const
{ {
const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(param_id)); const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(param_id));
const ParameterRanges& ranges(fPlugin.getParameterRanges(param_id)); const ParameterRanges& ranges(fPlugin.getParameterRanges(param_id));
const uint32_t hints = fPlugin.getParameterHints(param_id); const uint32_t hints = fPlugin.getParameterHints(param_id);


double plain;
if (hints & kParameterIsInteger)
{
plain = value;
}
else if (hints & kParameterIsBoolean)
if (hints & kParameterIsBoolean)
{ {
const float midRange = ranges.min + (ranges.max - ranges.min) * 0.5f; const float midRange = ranges.min + (ranges.max - ranges.min) * 0.5f;
plain = value > midRange ? ranges.max : ranges.min;
value = value > midRange ? ranges.max : ranges.min;
} }
else
else if (hints & kParameterIsInteger)
{ {
plain = ranges.getUnnormalizedValue(value);
value = std::round(value);
} }


for (uint32_t i=0; i < enumValues.count; ++i) for (uint32_t i=0; i < enumValues.count; ++i)
{ {
if (d_isEqual(static_cast<double>(enumValues.values[i].value), plain))
if (d_isEqual(static_cast<double>(enumValues.values[i].value), value))
{ {
DISTRHO_NAMESPACE::strncpy(display, enumValues.values[i].label, size); DISTRHO_NAMESPACE::strncpy(display, enumValues.values[i].label, size);
return true; return true;
@@ -763,9 +818,9 @@ public:
} }


if (hints & kParameterIsInteger) if (hints & kParameterIsInteger)
snprintf_i32(display, plain, size);
snprintf_i32(display, value, size);
else else
snprintf_f32(display, plain, size);
snprintf_f32(display, value, size);


return true; return true;
} }
@@ -773,42 +828,35 @@ public:
bool getParameterValueForString(const clap_id param_id, const char* const display, double* const value) const bool getParameterValueForString(const clap_id param_id, const char* const display, double* const value) const
{ {
const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(param_id)); const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(param_id));
const ParameterRanges& ranges(fPlugin.getParameterRanges(param_id));
const bool isInteger = fPlugin.isParameterInteger(param_id); const bool isInteger = fPlugin.isParameterInteger(param_id);


for (uint32_t i=0; i < enumValues.count; ++i) for (uint32_t i=0; i < enumValues.count; ++i)
{ {
if (std::strcmp(display, enumValues.values[i].label) == 0) if (std::strcmp(display, enumValues.values[i].label) == 0)
{ {
*value = isInteger
? enumValues.values[i].value
: ranges.getNormalizedValue(enumValues.values[i].value);
*value = enumValues.values[i].value;
return true; return true;
} }
} }


double plain;
if (isInteger) if (isInteger)
plain = std::atoi(display);
*value = std::atoi(display);
else else
plain = std::atof(display);
*value = std::atof(display);


*value = ranges.getNormalizedValue(plain);
return true; return true;
} }


void setParameterValueFromEvent(const clap_event_param_value* const param) void setParameterValueFromEvent(const clap_event_param_value* const param)
{ {
const double plain = fPlugin.isParameterInteger(param->param_id)
? param->value
: fPlugin.getParameterRanges(param->param_id).getFixedAndNormalizedValue(param->value);

fPlugin.setParameterValue(param->param_id, plain);
fCachedParameters.values[param->param_id] = param->value;
fCachedParameters.changed[param->param_id] = true;
fPlugin.setParameterValue(param->param_id, param->value);
} }


void flushParameters(const clap_input_events_t* const in, const clap_output_events_t* /* const out */)
void flushParameters(const clap_input_events_t* const in, const clap_output_events_t* const out)
{ {
if (const uint32_t len = in->size(in))
if (const uint32_t len = in != nullptr ? in->size(in) : 0)
{ {
for (uint32_t i=0; i<len; ++i) for (uint32_t i=0; i<len; ++i)
{ {
@@ -823,6 +871,33 @@ public:
setParameterValueFromEvent(static_cast<const clap_event_param_value*>(static_cast<const void*>(event))); setParameterValueFromEvent(static_cast<const clap_event_param_value*>(static_cast<const void*>(event)));
} }
} }

if (out != nullptr)
{
clap_event_param_value_t clapEvent = {
{ sizeof(clap_event_param_value_t), 0, 0, CLAP_EVENT_PARAM_VALUE, CLAP_EVENT_IS_LIVE },
0, nullptr, 0, 0, 0, 0, 0.0
};

float value;
for (uint i=0; i<fCachedParameters.numParams; ++i)
{
if (fPlugin.isParameterOutputOrTrigger(i))
{
value = fPlugin.getParameterValue(i);

if (d_isEqual(fCachedParameters.values[i], value))
continue;

fCachedParameters.values[i] = value;
fCachedParameters.changed[i] = true;

clapEvent.param_id = i;
clapEvent.value = value;
out->try_push(out, &clapEvent.header);
}
}
}
} }


// ---------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------------
@@ -873,7 +948,7 @@ private:


static bool writeMidiCallback(void* const ptr, const MidiEvent& midiEvent) static bool writeMidiCallback(void* const ptr, const MidiEvent& midiEvent)
{ {
return ((PluginStub*)ptr)->writeMidi(midiEvent);
return static_cast<PluginCLAP*>(ptr)->writeMidi(midiEvent);
} }
#endif #endif


@@ -885,7 +960,7 @@ private:


static bool requestParameterValueChangeCallback(void* const ptr, const uint32_t index, const float value) static bool requestParameterValueChangeCallback(void* const ptr, const uint32_t index, const float value)
{ {
return ((PluginStub*)ptr)->requestParameterValueChange(index, value);
return static_cast<PluginCLAP*>(ptr)->requestParameterValueChange(index, value);
} }
#endif #endif


@@ -897,7 +972,7 @@ private:


static bool updateStateValueCallback(void* const ptr, const char* const key, const char* const value) static bool updateStateValueCallback(void* const ptr, const char* const key, const char* const value)
{ {
return ((PluginStub*)ptr)->updateState(key, value);
return static_cast<PluginCLAP*>(ptr)->updateState(key, value);
} }
#endif #endif
}; };


+ 4
- 4
distrho/src/DistrhoUIInternal.hpp View File

@@ -262,7 +262,7 @@ public:


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


#if defined(DISTRHO_PLUGIN_TARGET_VST3) && (defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS))
#if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS)
void idleForVST3() void idleForVST3()
{ {
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
@@ -271,7 +271,7 @@ public:
ui->uiIdle(); ui->uiIdle();
} }


# if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
void addIdleCallbackForVST3(IdleCallback* const cb, const uint timerFrequencyInMs) void addIdleCallbackForVST3(IdleCallback* const cb, const uint timerFrequencyInMs)
{ {
uiData->window->addIdleCallback(cb, timerFrequencyInMs); uiData->window->addIdleCallback(cb, timerFrequencyInMs);
@@ -281,8 +281,8 @@ public:
{ {
uiData->window->removeIdleCallback(cb); uiData->window->removeIdleCallback(cb);
} }
# endif
#endif
#endif
#endif


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




+ 1
- 0
examples/Meters/Makefile View File

@@ -39,6 +39,7 @@ endif # MACOS_OR_WINDOWS
TARGETS += lv2_sep TARGETS += lv2_sep
TARGETS += vst2 TARGETS += vst2
TARGETS += vst3 TARGETS += vst3
TARGETS += clap


endif # HAVE_OPENGL endif # HAVE_OPENGL




Loading…
Cancel
Save