Skip to content

Commit

Permalink
Implementing param-indication extension
Browse files Browse the repository at this point in the history
  • Loading branch information
jatinchowdhury18 committed Feb 27, 2024
1 parent e72d59a commit 65540c0
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 2 deletions.
15 changes: 15 additions & 0 deletions examples/GainPlugin/GainPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,20 @@ void GainPlugin::setStateInformation(const void *data, int sizeInBytes)
vts.replaceState(juce::ValueTree::fromXml(*xmlState));
}

void GainPlugin::paramIndicationSetMapping(const juce::RangedAudioParameter &param,
bool has_mapping, const juce::Colour *colour,
const juce::String &label,
const juce::String &description) noexcept
{
paramIndicationHelper.paramIndicationSetMapping(param, has_mapping, colour, label, description);
}

void GainPlugin::paramIndicationSetAutomation(const juce::RangedAudioParameter &param,
uint32_t automation_state,
const juce::Colour *colour) noexcept
{
paramIndicationHelper.paramIndicationSetAutomation(param, automation_state, colour);
}

// This creates new instances of the plugin
juce::AudioProcessor *JUCE_CALLTYPE createPluginFilter() { return new GainPlugin(); }
10 changes: 10 additions & 0 deletions examples/GainPlugin/GainPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <juce_dsp/juce_dsp.h>
#include "ModulatableFloatParameter.h"
#include "ParamIndicationHelper.h"

class ModulatableFloatParameter;
class GainPlugin : public juce::AudioProcessor,
Expand Down Expand Up @@ -38,6 +39,15 @@ class GainPlugin : public juce::AudioProcessor,
void getStateInformation(juce::MemoryBlock &data) override;
void setStateInformation(const void *data, int sizeInBytes) override;

bool supportsParamIndication() const noexcept override { return true; }
void paramIndicationSetMapping(const juce::RangedAudioParameter &param, bool has_mapping,
const juce::Colour *colour, const juce::String &label,
const juce::String &description) noexcept override;
void paramIndicationSetAutomation(const juce::RangedAudioParameter &param,
uint32_t automation_state,
const juce::Colour *colour) noexcept override;
ParamIndicationHelper paramIndicationHelper;

juce::String getPluginTypeString() const;
auto *getGainParameter() { return gainDBParameter; }
auto &getValueTreeState() { return vts; }
Expand Down
94 changes: 94 additions & 0 deletions examples/GainPlugin/ParamIndicationHelper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#pragma once

#include <juce_audio_processors/juce_audio_processors.h>

class ParamIndicationHelper
{
public:
ParamIndicationHelper() = default;

struct ParamIndicatorInfo
{
juce::Colour colour;
juce::String text;
};

const ParamIndicatorInfo *getParamIndicatorInfo(juce::RangedAudioParameter &param) const
{
const auto entry = indicatorInfoMap.find(&param);
if (entry == indicatorInfoMap.end())
return nullptr;
return &entry->second;
}

void paramIndicationSetMapping(const juce::RangedAudioParameter &param, bool has_mapping,
const juce::Colour *colour, const juce::String &label,
const juce::String &description) noexcept
{
if (!has_mapping)
{
removeIndicatorInfo(param);
}
else
{
ParamIndicatorInfo info;
info.colour = colour == nullptr ? juce::Colours::transparentBlack : *colour;
info.text = label + ", " + description;
indicatorInfoMap[&param] = std::move(info);
}

listeners.call(&Listener::paramIndicatorInfoChanged, param);
}

void paramIndicationSetAutomation(const juce::RangedAudioParameter &param,
uint32_t automation_state,
const juce::Colour *colour) noexcept
{
if (automation_state == CLAP_PARAM_INDICATION_AUTOMATION_NONE)
{
removeIndicatorInfo(param);
}
else
{
ParamIndicatorInfo info;
info.colour = colour == nullptr ? juce::Colours::transparentBlack : *colour;
info.text = "Automation: " + [automation_state]() -> juce::String {
if (automation_state == CLAP_PARAM_INDICATION_AUTOMATION_PRESENT)
return "PRESENT";
else if (automation_state == CLAP_PARAM_INDICATION_AUTOMATION_RECORDING)
return "RECORDING";
else if (automation_state == CLAP_PARAM_INDICATION_AUTOMATION_PLAYING)
return "PLAYING";
else if (automation_state == CLAP_PARAM_INDICATION_AUTOMATION_OVERRIDING)
return "OVERRIDING";
return "";
}();
indicatorInfoMap[&param] = std::move(info);
}

listeners.call(&Listener::paramIndicatorInfoChanged, param);
}

struct Listener
{
virtual ~Listener() = default;
virtual void paramIndicatorInfoChanged(const juce::RangedAudioParameter &) {}
};

void addListener(Listener *listener) { listeners.add(listener); }
void removeListener(Listener *listener) { listeners.remove(listener); }

private:
void removeIndicatorInfo(const juce::RangedAudioParameter &param)
{
const auto entry = indicatorInfoMap.find(&param);
if (entry != indicatorInfoMap.end())
indicatorInfoMap.erase(entry);
}

std::unordered_map<const juce::RangedAudioParameter *, ParamIndicatorInfo> indicatorInfoMap;

juce::ListenerList<Listener> listeners;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ParamIndicationHelper)
};
21 changes: 21 additions & 0 deletions examples/GainPlugin/PluginEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ PluginEditor::PluginEditor(GainPlugin &plug) : juce::AudioProcessorEditor(plug),
std::make_unique<juce::SliderParameterAttachment>(*gainParameter, *gainSlider, nullptr);

plugin.getValueTreeState().addParameterListener(gainParameter->paramID, this);
plugin.paramIndicationHelper.addListener(this);

setSize(300, 300);
setResizable (true, true);
Expand All @@ -67,6 +68,7 @@ PluginEditor::~PluginEditor()
{
auto *gainParameter = plugin.getGainParameter();
plugin.getValueTreeState().removeParameterListener(gainParameter->paramID, this);
plugin.paramIndicationHelper.removeListener(this);
}

void PluginEditor::resized()
Expand All @@ -83,6 +85,18 @@ void PluginEditor::paint(juce::Graphics &g)
const auto titleBounds = getLocalBounds().removeFromTop(30);
const auto titleText = "Gain Plugin " + plugin.getPluginTypeString();
g.drawFittedText(titleText, titleBounds, juce::Justification::centred, 1);

if (auto *paramIndicatorInfo =
plugin.paramIndicationHelper.getParamIndicatorInfo(*plugin.getGainParameter()))
{
g.setColour(paramIndicatorInfo->colour);
g.fillRect(juce::Rectangle<int>{0, 0, 15, 15});

g.setColour(juce::Colours::black);
const auto paramIndicationTextBounds = getLocalBounds().removeFromBottom(30);
g.drawFittedText(paramIndicatorInfo->text, paramIndicationTextBounds,
juce::Justification::centred, 1);
}
}

void PluginEditor::mouseDown(const juce::MouseEvent &e)
Expand Down Expand Up @@ -124,3 +138,10 @@ void PluginEditor::parameterChanged(const juce::String &, float)
auto &animator = juce::Desktop::getInstance().getAnimator();
animator.fadeOut(&flashComp, 100);
}

void PluginEditor::paramIndicatorInfoChanged(const juce::RangedAudioParameter &param)
{
if (&param != plugin.getGainParameter())
return;
repaint();
}
7 changes: 5 additions & 2 deletions examples/GainPlugin/PluginEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#include "GainPlugin.h"

class PluginEditor : public juce::AudioProcessorEditor,
private juce::AudioProcessorValueTreeState::Listener
private juce::AudioProcessorValueTreeState::Listener,
private ParamIndicationHelper::Listener
{
public:
explicit PluginEditor(GainPlugin &plugin);
Expand All @@ -12,9 +13,11 @@ class PluginEditor : public juce::AudioProcessorEditor,
void resized() override;
void paint(juce::Graphics &g) override;

void paramIndicatorInfoChanged(const juce::RangedAudioParameter &) override;

private:
void parameterChanged(const juce::String &parameterID, float newValue) override;
void mouseDown (const juce::MouseEvent& e) override;
void mouseDown(const juce::MouseEvent &e) override;

GainPlugin &plugin;

Expand Down
15 changes: 15 additions & 0 deletions include/clap-juce-extensions/clap-juce-extensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class MidiBuffer;
class AudioProcessorParameter;
class RangedAudioParameter;
class String;
class Colour;
} // namespace juce

namespace clap_juce_extensions
Expand Down Expand Up @@ -233,6 +234,20 @@ struct clap_juce_audio_processor_capabilities
noteNamesChangedSignal();
}

virtual bool supportsParamIndication() const noexcept { return false; }
virtual void paramIndicationSetMapping(const juce::RangedAudioParameter & /*param*/,
bool /*has_mapping*/, const juce::Colour * /*colour*/,
const juce::String & /*label*/,
const juce::String & /*description*/) noexcept
{
}

virtual void paramIndicationSetAutomation(const juce::RangedAudioParameter & /*param*/,
uint32_t /*automation_state*/,
const juce::Colour * /*colour*/) noexcept
{
}

/** If your plugin supports remote controls, then override this method to return true. */
virtual bool supportsRemoteControls() const noexcept { return false; }

Expand Down
53 changes: 53 additions & 0 deletions src/wrapper/clap-juce-wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,12 @@ class EditorHostContext : public juce::AudioProcessorEditorHostContext
};
#endif // JUCE_VERSION >= 0x060008

/** Converts a clap_color to a juce::Colour */
static juce::Colour clapColourToJUCEColour(const clap_color &clapColour)
{
return {clapColour.red, clapColour.green, clapColour.blue, clapColour.alpha};
}

/*
* The ClapJuceWrapper is a class which immplements a collection
* of CLAP and JUCE APIs
Expand Down Expand Up @@ -1045,6 +1051,53 @@ class ClapJuceWrapper : public clap::helpers::Plugin<
return false;
}

bool implementsParamIndication() const noexcept override
{
if (processorAsClapExtensions)
return processorAsClapExtensions->supportsParamIndication();
return false;
}
void paramIndicationSetMapping(clap_id param_id, bool has_mapping, const clap_color_t *color,
const char *label, const char *description) noexcept override
{
if (!processorAsClapExtensions)
return;

const auto &param = paramPtrByClapID[param_id];

juce::Colour juceColour{};
if (color != nullptr)
juceColour = clapColourToJUCEColour(*color);
const juce::Colour *juceColourPtr = color == nullptr ? nullptr : &juceColour;

juce::String labelStr{};
if (label != nullptr)
labelStr = (juce::CharPointer_UTF8)label;

juce::String descStr{};
if (label != nullptr)
descStr = (juce::CharPointer_UTF8)description;

processorAsClapExtensions->paramIndicationSetMapping(*param.rangedParameter, has_mapping,
juceColourPtr, labelStr, descStr);
}
void paramIndicationSetAutomation(clap_id param_id, uint32_t automation_state,
const clap_color_t *color) noexcept override
{
if (!processorAsClapExtensions)
return;

const auto &param = paramPtrByClapID[param_id];

juce::Colour juceColour{};
if (color != nullptr)
juceColour = clapColourToJUCEColour(*color);
const juce::Colour *juceColourPtr = color == nullptr ? nullptr : &juceColour;

processorAsClapExtensions->paramIndicationSetAutomation(*param.rangedParameter,
automation_state, juceColourPtr);
}

bool implementRemoteControls() const noexcept override
{
if (processorAsClapExtensions)
Expand Down

0 comments on commit 65540c0

Please sign in to comment.