Browse Source

Add kParameterDesignationReset, implement for AU, CLAP and LV2

Signed-off-by: falkTX <falktx@falktx.com>
pull/491/head
falkTX 4 months ago
parent
commit
576b507dc4
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
6 changed files with 135 additions and 47 deletions
  1. +28
    -4
      distrho/DistrhoDetails.hpp
  2. +52
    -36
      distrho/src/DistrhoPluginAU.cpp
  3. +37
    -6
      distrho/src/DistrhoPluginCLAP.cpp
  4. +10
    -0
      distrho/src/DistrhoPluginLV2export.cpp
  5. +6
    -0
      distrho/src/DistrhoPluginVST3.cpp
  6. +2
    -1
      distrho/src/lv2/lv2_kxstudio_properties.h

+ 28
- 4
distrho/DistrhoDetails.hpp View File

@@ -202,7 +202,7 @@ static constexpr const uint32_t kStateIsOnlyForUI = 0x20;


/** /**
Parameter designation.@n Parameter designation.@n
Allows a parameter to be specially designated for a task, like bypass.
Allows a parameter to be specially designated for a task, like bypass and reset.


Each designation is unique, there must be only one parameter that uses it.@n Each designation is unique, there must be only one parameter that uses it.@n
The use of designated parameters is completely optional. The use of designated parameters is completely optional.
@@ -214,13 +214,20 @@ enum ParameterDesignation {
/** /**
Null or unset designation. Null or unset designation.
*/ */
kParameterDesignationNull = 0,
kParameterDesignationNull,


/** /**
Bypass designation.@n Bypass designation.@n
When on (> 0.5f), it means the plugin must run in a bypassed state. When on (> 0.5f), it means the plugin must run in a bypassed state.
*/ */
kParameterDesignationBypass = 1
kParameterDesignationBypass,

/**
Reset designation.@n
When on (> 0.5f), it means the plugin should reset its internal processing state
(like filters, oscillators, envelopes, lfos, etc) and kill all voices.
*/
kParameterDesignationReset,
}; };


/** /**
@@ -234,7 +241,12 @@ namespace ParameterDesignationSymbols {
static constexpr const char bypass[] = "dpf_bypass"; static constexpr const char bypass[] = "dpf_bypass";


/** /**
Bypass designation symbol, inverted for LV2 so it becomes "enabled".
Reset designation symbol.
*/
static constexpr const char reset[] = "dpf_reset";

/**
LV2 bypass designation symbol, inverted for LV2 so it becomes "enabled".
*/ */
static constexpr const char bypass_lv2[] = "lv2_enabled"; static constexpr const char bypass_lv2[] = "lv2_enabled";
}; };
@@ -728,6 +740,18 @@ struct Parameter {
ranges.min = 0.0f; ranges.min = 0.0f;
ranges.max = 1.0f; ranges.max = 1.0f;
break; break;
case kParameterDesignationReset:
hints = kParameterIsAutomatable|kParameterIsBoolean|kParameterIsInteger|kParameterIsTrigger;
name = "Reset";
shortName = "Reset";
symbol = ParameterDesignationSymbols::reset;
unit = "";
midiCC = 0;
groupId = kPortGroupNone;
ranges.def = 0.0f;
ranges.min = 0.0f;
ranges.max = 1.0f;
break;
} }
} }




+ 52
- 36
distrho/src/DistrhoPluginAU.cpp View File

@@ -264,7 +264,7 @@ bool isNumChannelsComboValid(const uint16_t numInputs, const uint16_t numOutputs
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------


struct PropertyListener { struct PropertyListener {
AudioUnitPropertyID prop;
AudioUnitPropertyID prop;
AudioUnitPropertyListenerProc proc; AudioUnitPropertyListenerProc proc;
void* userData; void* userData;
}; };
@@ -348,7 +348,8 @@ public:
fUsingRenderListeners(false), fUsingRenderListeners(false),
fParameterCount(fPlugin.getParameterCount()), fParameterCount(fPlugin.getParameterCount()),
fLastParameterValues(nullptr), fLastParameterValues(nullptr),
fBypassParameterIndex(UINT32_MAX)
fBypassParameterIndex(UINT32_MAX),
fResetParameterIndex(UINT32_MAX)
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
, fMidiEventCount(0) , fMidiEventCount(0)
#endif #endif
@@ -365,7 +366,7 @@ public:
, fStateCount(fPlugin.getStateCount()) , fStateCount(fPlugin.getStateCount())
#endif #endif
{ {
if (fParameterCount != 0)
if (fParameterCount != 0)
{ {
fLastParameterValues = new float[fParameterCount]; fLastParameterValues = new float[fParameterCount];
std::memset(fLastParameterValues, 0, sizeof(float) * fParameterCount); std::memset(fLastParameterValues, 0, sizeof(float) * fParameterCount);
@@ -374,8 +375,17 @@ public:
{ {
fLastParameterValues[i] = fPlugin.getParameterValue(i); fLastParameterValues[i] = fPlugin.getParameterValue(i);


if (fPlugin.getParameterDesignation(i) == kParameterDesignationBypass)
switch (fPlugin.getParameterDesignation(i))
{
case kParameterDesignationNull:
break;
case kParameterDesignationBypass:
fBypassParameterIndex = i; fBypassParameterIndex = i;
break;
case kParameterDesignationReset:
fResetParameterIndex = i;
break;
}
} }
} }


@@ -923,13 +933,13 @@ public:
case kAudioUnitProperty_FastDispatch: case kAudioUnitProperty_FastDispatch:
switch (inElement) switch (inElement)
{ {
case kAudioUnitGetParameterSelect:
case kAudioUnitGetParameterSelect:
*static_cast<AudioUnitGetParameterProc*>(outData) = FastDispatchGetParameter; *static_cast<AudioUnitGetParameterProc*>(outData) = FastDispatchGetParameter;
return noErr; return noErr;
case kAudioUnitSetParameterSelect:
case kAudioUnitSetParameterSelect:
*static_cast<AudioUnitSetParameterProc*>(outData) = FastDispatchSetParameter; *static_cast<AudioUnitSetParameterProc*>(outData) = FastDispatchSetParameter;
return noErr; return noErr;
case kAudioUnitRenderSelect:
case kAudioUnitRenderSelect:
*static_cast<AudioUnitRenderProc*>(outData) = FastDispatchRender; *static_cast<AudioUnitRenderProc*>(outData) = FastDispatchRender;
return noErr; return noErr;
} }
@@ -1458,7 +1468,7 @@ public:
const float value = bypass ? 1.f : 0.f; const float value = bypass ? 1.f : 0.f;
fLastParameterValues[fBypassParameterIndex] = value; fLastParameterValues[fBypassParameterIndex] = value;
fPlugin.setParameterValue(fBypassParameterIndex, value); fPlugin.setParameterValue(fBypassParameterIndex, value);
notifyPropertyListeners(inProp, inScope, inElement);
notifyPropertyListeners(inProp, inScope, inElement);
} }
} }
return noErr; return noErr;
@@ -1480,12 +1490,12 @@ public:
#if DISTRHO_PLUGIN_WANT_TIMEPOS #if DISTRHO_PLUGIN_WANT_TIMEPOS
{ {
const UInt32 usableDataSize = std::min(inDataSize, static_cast<UInt32>(sizeof(HostCallbackInfo))); const UInt32 usableDataSize = std::min(inDataSize, static_cast<UInt32>(sizeof(HostCallbackInfo)));
const bool changed = std::memcmp(&fHostCallbackInfo, inData, usableDataSize) != 0;
const bool changed = std::memcmp(&fHostCallbackInfo, inData, usableDataSize) != 0;


std::memcpy(&fHostCallbackInfo, inData, usableDataSize);
std::memcpy(&fHostCallbackInfo, inData, usableDataSize);


if (sizeof(HostCallbackInfo) > usableDataSize) if (sizeof(HostCallbackInfo) > usableDataSize)
std::memset(&fHostCallbackInfo + usableDataSize, 0, sizeof(HostCallbackInfo) - usableDataSize);
std::memset(&fHostCallbackInfo + usableDataSize, 0, sizeof(HostCallbackInfo) - usableDataSize);


if (changed) if (changed)
notifyPropertyListeners(inProp, inScope, inElement); notifyPropertyListeners(inProp, inScope, inElement);
@@ -1612,7 +1622,7 @@ public:
AUEventListenerNotify(NULL, NULL, &event); AUEventListenerNotify(NULL, NULL, &event);


if (fBypassParameterIndex == inElement) if (fBypassParameterIndex == inElement)
notifyPropertyListeners(kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0);
notifyPropertyListeners(kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0);
} }
return noErr; return noErr;


@@ -1821,7 +1831,12 @@ public:
DISTRHO_SAFE_ASSERT_UINT_RETURN(scope == kAudioUnitScope_Global || scope == kAudioUnitScope_Input || scope == kAudioUnitScope_Output, scope, kAudioUnitErr_InvalidScope); DISTRHO_SAFE_ASSERT_UINT_RETURN(scope == kAudioUnitScope_Global || scope == kAudioUnitScope_Input || scope == kAudioUnitScope_Output, scope, kAudioUnitErr_InvalidScope);
DISTRHO_SAFE_ASSERT_UINT_RETURN(elem == 0, elem, kAudioUnitErr_InvalidElement); DISTRHO_SAFE_ASSERT_UINT_RETURN(elem == 0, elem, kAudioUnitErr_InvalidElement);


if (fPlugin.isActive())
if (fResetParameterIndex != UINT32_MAX)
{
fPlugin.setParameterValue(fResetParameterIndex, 1.f);
fPlugin.setParameterValue(fResetParameterIndex, 0.f);
}
else if (fPlugin.isActive())
{ {
fPlugin.deactivate(); fPlugin.deactivate();
fPlugin.activate(); fPlugin.activate();
@@ -2180,6 +2195,7 @@ private:
const uint32_t fParameterCount; const uint32_t fParameterCount;
float* fLastParameterValues; float* fLastParameterValues;
uint32_t fBypassParameterIndex; uint32_t fBypassParameterIndex;
uint32_t fResetParameterIndex;


#if DISTRHO_PLUGIN_WANT_MIDI_INPUT #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
uint32_t fMidiEventCount; uint32_t fMidiEventCount;
@@ -2220,7 +2236,7 @@ private:
const PropertyListener& pl(*it); const PropertyListener& pl(*it);


if (pl.prop == prop) if (pl.prop == prop)
pl.proc(pl.userData, fComponent, prop, scope, elem);
pl.proc(pl.userData, fComponent, prop, scope, elem);
} }
} }


@@ -2845,7 +2861,7 @@ private:
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------


struct AudioComponentPlugInInstance { struct AudioComponentPlugInInstance {
AudioComponentPlugInInterface acpi;
AudioComponentPlugInInterface acpi;
PluginAU* plugin; PluginAU* plugin;


AudioComponentPlugInInstance() noexcept AudioComponentPlugInInstance() noexcept
@@ -2854,9 +2870,9 @@ struct AudioComponentPlugInInstance {
{ {
std::memset(&acpi, 0, sizeof(acpi)); std::memset(&acpi, 0, sizeof(acpi));
acpi.Open = Open; acpi.Open = Open;
acpi.Close = Close;
acpi.Lookup = Lookup;
acpi.reserved = nullptr;
acpi.Close = Close;
acpi.Lookup = Lookup;
acpi.reserved = nullptr;
} }


~AudioComponentPlugInInstance() ~AudioComponentPlugInInstance()
@@ -2864,7 +2880,7 @@ struct AudioComponentPlugInInstance {
delete plugin; delete plugin;
} }


static OSStatus Open(void* const self, const AudioUnit component)
static OSStatus Open(void* const self, const AudioUnit component)
{ {
d_debug("AudioComponentPlugInInstance::Open(%p)", self); d_debug("AudioComponentPlugInInstance::Open(%p)", self);


@@ -2872,7 +2888,7 @@ struct AudioComponentPlugInInstance {
return noErr; return noErr;
} }


static OSStatus Close(void* const self)
static OSStatus Close(void* const self)
{ {
d_debug("AudioComponentPlugInInstance::Close(%p)", self); d_debug("AudioComponentPlugInInstance::Close(%p)", self);


@@ -2964,15 +2980,15 @@ struct AudioComponentPlugInInstance {
d_debug("AudioComponentPlugInInstance::GetPropertyInfo(%p, %d:%x:%s, %d:%s, %d, ...)", d_debug("AudioComponentPlugInInstance::GetPropertyInfo(%p, %d:%x:%s, %d:%s, %d, ...)",
self, inProp, inProp, AudioUnitPropertyID2Str(inProp), inScope, AudioUnitScope2Str(inScope), inElement); self, inProp, inProp, AudioUnitPropertyID2Str(inProp), inScope, AudioUnitScope2Str(inScope), inElement);


UInt32 dataSize = 0;
Boolean writable = false;
UInt32 dataSize = 0;
Boolean writable = false;
const OSStatus res = self->plugin->auGetPropertyInfo(inProp, inScope, inElement, dataSize, writable); const OSStatus res = self->plugin->auGetPropertyInfo(inProp, inScope, inElement, dataSize, writable);


if (outDataSize != nullptr)
*outDataSize = dataSize;
if (outDataSize != nullptr)
*outDataSize = dataSize;


if (outWritable != nullptr)
*outWritable = writable;
if (outWritable != nullptr)
*outWritable = writable;


return res; return res;
} }
@@ -3016,24 +3032,24 @@ struct AudioComponentPlugInInstance {
if (res != noErr) if (res != noErr)
return res; return res;


void* outBuffer;
void* outBuffer;
uint8_t* tmpBuffer; uint8_t* tmpBuffer;
if (inDataSize < outDataSize) if (inDataSize < outDataSize)
{
tmpBuffer = new uint8_t[outDataSize];
outBuffer = tmpBuffer;
}
{
tmpBuffer = new uint8_t[outDataSize];
outBuffer = tmpBuffer;
}
else else
{ {
tmpBuffer = nullptr;
outBuffer = outData;
}
tmpBuffer = nullptr;
outBuffer = outData;
}


res = self->plugin->auGetProperty(inProp, inScope, inElement, outBuffer); res = self->plugin->auGetProperty(inProp, inScope, inElement, outBuffer);


if (res != noErr)
if (res != noErr)
{ {
*ioDataSize = 0;
*ioDataSize = 0;
return res; return res;
} }




+ 37
- 6
distrho/src/DistrhoPluginCLAP.cpp View File

@@ -751,6 +751,7 @@ public:
updateStateValueCallback), updateStateValueCallback),
fHost(host), fHost(host),
fOutputEvents(nullptr), fOutputEvents(nullptr),
fResetParameterIndex(UINT32_MAX),
#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0
fUsingCV(false), fUsingCV(false),
#endif #endif
@@ -763,7 +764,19 @@ public:
#endif #endif
fHostExtensions(host) fHostExtensions(host)
{ {
fCachedParameters.setup(fPlugin.getParameterCount());
if (const uint32_t paramCount = fPlugin.getParameterCount())
{
fCachedParameters.setup(paramCount);

for (uint32_t i=0; i<paramCount; ++i)
{
if (fPlugin.getParameterDesignation(i) == kParameterDesignationReset)
{
fResetParameterIndex = i;
break;
}
}
}


#if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT #if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT
fNotesRingBuffer.setRingBuffer(&fNotesBuffer, true); fNotesRingBuffer.setRingBuffer(&fNotesBuffer, true);
@@ -823,7 +836,18 @@ public:


void reset() void reset()
{ {
fHost->request_restart(fHost);
if (fResetParameterIndex != UINT32_MAX)
{
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
fMidiEventCount = 0;
#endif
fPlugin.setParameterValue(fResetParameterIndex, 1.f);
fPlugin.setParameterValue(fResetParameterIndex, 0.f);
}
else
{
fHost->request_restart(fHost);
}
} }


bool process(const clap_process_t* const process) bool process(const clap_process_t* const process)
@@ -1119,14 +1143,19 @@ public:
{ {
const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); const ParameterRanges& ranges(fPlugin.getParameterRanges(index));


if (fPlugin.getParameterDesignation(index) == kParameterDesignationBypass)
switch (fPlugin.getParameterDesignation(index))
{ {
case kParameterDesignationBypass:
info->flags = CLAP_PARAM_IS_STEPPED|CLAP_PARAM_IS_BYPASS|CLAP_PARAM_IS_AUTOMATABLE; info->flags = CLAP_PARAM_IS_STEPPED|CLAP_PARAM_IS_BYPASS|CLAP_PARAM_IS_AUTOMATABLE;
std::strcpy(info->name, "Bypass"); std::strcpy(info->name, "Bypass");
std::strcpy(info->module, "dpf_bypass"); std::strcpy(info->module, "dpf_bypass");
}
else
{
break;
case kParameterDesignationReset:
info->flags = CLAP_PARAM_IS_STEPPED|CLAP_PARAM_IS_READONLY;
std::strcpy(info->name, "Reset");
std::strcpy(info->module, "dpf_reset");
break;
default:
const uint32_t hints = fPlugin.getParameterHints(index); const uint32_t hints = fPlugin.getParameterHints(index);
const uint32_t groupId = fPlugin.getParameterGroupId(index); const uint32_t groupId = fPlugin.getParameterGroupId(index);


@@ -1156,6 +1185,7 @@ public:
} }


d_strncpy(info->module + wrtn, fPlugin.getParameterSymbol(index), CLAP_PATH_SIZE - wrtn); d_strncpy(info->module + wrtn, fPlugin.getParameterSymbol(index), CLAP_PATH_SIZE - wrtn);
break;
} }


info->id = index; info->id = index;
@@ -1791,6 +1821,7 @@ private:
const clap_host_t* const fHost; const clap_host_t* const fHost;
const clap_output_events_t* fOutputEvents; const clap_output_events_t* fOutputEvents;


uint32_t fResetParameterIndex;
#if DISTRHO_PLUGIN_NUM_INPUTS != 0 #if DISTRHO_PLUGIN_NUM_INPUTS != 0
const float* fAudioInputs[DISTRHO_PLUGIN_NUM_INPUTS]; const float* fAudioInputs[DISTRHO_PLUGIN_NUM_INPUTS];
#endif #endif


+ 10
- 0
distrho/src/DistrhoPluginLV2export.cpp View File

@@ -758,6 +758,16 @@ void lv2_generate_ttl(const char* const basename)
pluginString += " lv2:portProperty lv2:toggled , lv2:integer ;\n"; pluginString += " lv2:portProperty lv2:toggled , lv2:integer ;\n";
pluginString += " lv2:designation lv2:enabled ;\n"; pluginString += " lv2:designation lv2:enabled ;\n";
break; break;
case kParameterDesignationReset:
designated = true;
pluginString += " lv2:name \"Reset\" ;\n";
pluginString += " lv2:symbol \"" + String(ParameterDesignationSymbols::reset) + "\" ;\n";
pluginString += " lv2:default 0 ;\n";
pluginString += " lv2:minimum 0 ;\n";
pluginString += " lv2:maximum 1 ;\n";
pluginString += " lv2:portProperty lv2:toggled , lv2:integer , <" LV2_PORT_PROPS__trigger "> ;\n";
pluginString += " lv2:designation <" LV2_KXSTUDIO_PROPERTIES__Reset "> ;\n";
break;
} }
} }




+ 6
- 0
distrho/src/DistrhoPluginVST3.cpp View File

@@ -1747,6 +1747,12 @@ public:
case kParameterDesignationBypass: case kParameterDesignationBypass:
flags |= V3_PARAM_IS_BYPASS; flags |= V3_PARAM_IS_BYPASS;
break; break;
case kParameterDesignationReset:
info->flags = V3_PARAM_READ_ONLY | V3_PARAM_IS_HIDDEN;
info->step_count = 1;
strncpy_utf16(info->title, "Reset", 128);
strncpy_utf16(info->short_title, "Reset", 128);
return V3_OK;
} }


if (hints & kParameterIsOutput) if (hints & kParameterIsOutput)


+ 2
- 1
distrho/src/lv2/lv2_kxstudio_properties.h View File

@@ -1,6 +1,6 @@
/* /*
LV2 KXStudio Properties Extension LV2 KXStudio Properties Extension
Copyright 2014-2021 Filipe Coelho <falktx@falktx.com>
Copyright 2014-2024 Filipe Coelho <falktx@falktx.com>


Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
@@ -27,6 +27,7 @@
#define LV2_KXSTUDIO_PROPERTIES_PREFIX LV2_KXSTUDIO_PROPERTIES_URI "#" #define LV2_KXSTUDIO_PROPERTIES_PREFIX LV2_KXSTUDIO_PROPERTIES_URI "#"


#define LV2_KXSTUDIO_PROPERTIES__NonAutomatable LV2_KXSTUDIO_PROPERTIES_PREFIX "NonAutomatable" #define LV2_KXSTUDIO_PROPERTIES__NonAutomatable LV2_KXSTUDIO_PROPERTIES_PREFIX "NonAutomatable"
#define LV2_KXSTUDIO_PROPERTIES__Reset LV2_KXSTUDIO_PROPERTIES_PREFIX "Reset"
#define LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat LV2_KXSTUDIO_PROPERTIES_PREFIX "TimePositionTicksPerBeat" #define LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat LV2_KXSTUDIO_PROPERTIES_PREFIX "TimePositionTicksPerBeat"
#define LV2_KXSTUDIO_PROPERTIES__TransientWindowId LV2_KXSTUDIO_PROPERTIES_PREFIX "TransientWindowId" #define LV2_KXSTUDIO_PROPERTIES__TransientWindowId LV2_KXSTUDIO_PROPERTIES_PREFIX "TransientWindowId"




Loading…
Cancel
Save