commit f32b41625da5f988326b0657fd37ffe10ff7f2e7
parent cba9f00f2c71ec7bb40963a3d05c0d8d17887f03
Author: falkTX <falktx@gmail.com>
Date: Fri, 24 Apr 2015 00:19:29 +0200
Add AudioPort struct and hints; Implement CV and Sidechain in LV2
Diffstat:
4 files changed, 159 insertions(+), 8 deletions(-)
diff --git a/distrho/DistrhoPlugin.hpp b/distrho/DistrhoPlugin.hpp
@@ -186,6 +186,29 @@ START_NAMESPACE_DISTRHO
#endif
/* ------------------------------------------------------------------------------------------------------------
+ * Audio Port Hints */
+
+/**
+ @defgroup AudioPortHints Audio Port Hints
+
+ Various audio port hints.
+ @see AudioPort::hints
+ @{
+ */
+
+/**
+ Audio port can be used as control voltage (LV2 only).
+ */
+static const uint32_t kAudioPortIsCV = 0x1;
+
+/**
+ Audio port should be used as sidechan (LV2 only).
+ */
+static const uint32_t kAudioPortIsSidechain = 0x2;
+
+/** @} */
+
+/* ------------------------------------------------------------------------------------------------------------
* Parameter Hints */
/**
@@ -244,6 +267,40 @@ static const uint32_t kParameterIsCV = 0x20;
*/
/**
+ Audio Port.
+ */
+struct AudioPort {
+ /**
+ Hints describing this audio port.
+ @see AudioPortHints
+ */
+ uint32_t hints;
+
+ /**
+ The name of this audio port.
+ An audio port name can contain any character, but hosts might have a hard time with non-ascii ones.
+ The name doesn't have to be unique within a plugin instance, but it's recommended.
+ */
+ d_string name;
+
+ /**
+ The symbol of this audio port.
+ An audio port symbol is a short restricted name used as a machine and human readable identifier.
+ The first character must be one of _, a-z or A-Z and subsequent characters can be from _, a-z, A-Z and 0-9.
+ @note: Audio port and parameter symbols MUST be unique within a plugin instance.
+ */
+ d_string symbol;
+
+ /**
+ Default constructor for a regular audio port.
+ */
+ AudioPort() noexcept
+ : hints(0x0),
+ name(),
+ symbol() {}
+};
+
+/**
Parameter ranges.
This is used to set the default, minimum and maximum values of a parameter.
@@ -671,6 +728,12 @@ protected:
* Init */
/**
+ Initialize the audio port @a index.
+ This function will be called once, shortly after the plugin is created.
+ */
+ virtual void d_initAudioPort(bool input, uint32_t index, AudioPort& port);
+
+ /**
Initialize the parameter @a index.
This function will be called once, shortly after the plugin is created.
*/
diff --git a/distrho/src/DistrhoPlugin.cpp b/distrho/src/DistrhoPlugin.cpp
@@ -28,6 +28,7 @@ double d_lastSampleRate = 0.0;
* Static fallback data, see DistrhoPluginInternal.hpp */
const d_string PluginExporter::sFallbackString;
+const AudioPort PluginExporter::sFallbackAudioPort;
const ParameterRanges PluginExporter::sFallbackRanges;
/* ------------------------------------------------------------------------------------------------------------
@@ -36,6 +37,10 @@ const ParameterRanges PluginExporter::sFallbackRanges;
Plugin::Plugin(const uint32_t parameterCount, const uint32_t programCount, const uint32_t stateCount)
: pData(new PrivateData())
{
+#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ pData->audioPorts = new AudioPort[DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS];
+#endif
+
if (parameterCount > 0)
{
pData->parameterCount = parameterCount;
@@ -105,6 +110,27 @@ bool Plugin::d_writeMidiEvent(const MidiEvent& /*midiEvent*/) noexcept
#endif
/* ------------------------------------------------------------------------------------------------------------
+ * Init */
+
+void Plugin::d_initAudioPort(bool input, uint32_t index, AudioPort& port)
+{
+ if (port.hints & kAudioPortIsCV)
+ {
+ port.name = input ? "CV Input " : "CV Output ";
+ port.name += d_string(index+1);
+ port.symbol = input ? "cv_in_" : "cv_out_";
+ port.symbol += d_string(index+1);
+ }
+ else
+ {
+ port.name = input ? "Audio Input " : "Audio Output ";
+ port.name += d_string(index+1);
+ port.symbol = input ? "audio_in_" : "audio_out_";
+ port.symbol += d_string(index+1);
+ }
+}
+
+/* ------------------------------------------------------------------------------------------------------------
* Callbacks (optional) */
void Plugin::d_bufferSizeChanged(uint32_t) {}
diff --git a/distrho/src/DistrhoPluginInternal.hpp b/distrho/src/DistrhoPluginInternal.hpp
@@ -38,6 +38,10 @@ extern double d_lastSampleRate;
struct Plugin::PrivateData {
bool isProcessing;
+#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ AudioPort* audioPorts;
+#endif
+
uint32_t parameterCount;
Parameter* parameters;
@@ -65,6 +69,9 @@ struct Plugin::PrivateData {
PrivateData() noexcept
: isProcessing(false),
+#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ audioPorts(nullptr),
+#endif
parameterCount(0),
parameters(nullptr),
#if DISTRHO_PLUGIN_WANT_PROGRAMS
@@ -88,6 +95,14 @@ struct Plugin::PrivateData {
~PrivateData() noexcept
{
+#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ if (audioPorts != nullptr)
+ {
+ delete[] audioPorts;
+ audioPorts = nullptr;
+ }
+#endif
+
if (parameters != nullptr)
{
delete[] parameters;
@@ -132,6 +147,16 @@ public:
DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
+#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ {
+ uint32_t j=0;
+ for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++j)
+ fPlugin->d_initAudioPort(true, i, fData->audioPorts[j]);
+ for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++j)
+ fPlugin->d_initAudioPort(false, i, fData->audioPorts[j]);
+ }
+#endif
+
for (uint32_t i=0, count=fData->parameterCount; i < count; ++i)
fPlugin->d_initParameter(i, fData->parameters[i]);
@@ -211,6 +236,21 @@ public:
}
#endif
+#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ const AudioPort& getAudioPort(const bool input, const uint32_t index) const noexcept
+ {
+ DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackAudioPort);
+
+ if (input) {
+ DISTRHO_SAFE_ASSERT_RETURN(index < DISTRHO_PLUGIN_NUM_INPUTS, sFallbackAudioPort);
+ } else {
+ DISTRHO_SAFE_ASSERT_RETURN(index < DISTRHO_PLUGIN_NUM_OUTPUTS, sFallbackAudioPort);
+ }
+
+ return fData->audioPorts[index + (input ? 0 : DISTRHO_PLUGIN_NUM_INPUTS)];
+ }
+#endif
+
uint32_t getParameterCount() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
@@ -458,6 +498,7 @@ private:
// Static fallback data, see DistrhoPlugin.cpp
static const d_string sFallbackString;
+ static const AudioPort sFallbackAudioPort;
static const ParameterRanges sFallbackRanges;
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter)
diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp
@@ -109,6 +109,7 @@ void lv2_generate_ttl(const char* const basename)
# else
manifestString += " ui:binary <" + pluginDLL + "." DISTRHO_DLL_EXTENSION "> ;\n";
#endif
+ manifestString += "\n";
manifestString += " lv2:extensionData ui:idleInterface ,\n";
# if DISTRHO_PLUGIN_WANT_PROGRAMS
manifestString += " ui:showInterface ,\n";
@@ -116,9 +117,11 @@ void lv2_generate_ttl(const char* const basename)
# else
manifestString += " ui:showInterface ;\n";
# endif
+ manifestString += "\n";
manifestString += " lv2:optionalFeature ui:noUserResize ,\n";
manifestString += " ui:resize ,\n";
manifestString += " ui:touch ;\n";
+ manifestString += "\n";
# if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
manifestString += " lv2:requiredFeature <" LV2_DATA_ACCESS_URI "> ,\n";
manifestString += " <" LV2_INSTANCE_ACCESS_URI "> ,\n";
@@ -205,18 +208,27 @@ void lv2_generate_ttl(const char* const basename)
#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++portIndex)
{
+ const AudioPort& port(plugin.getAudioPort(true, i));
+
if (i == 0)
pluginString += " lv2:port [\n";
else
pluginString += " [\n";
- pluginString += " a lv2:InputPort, lv2:AudioPort ;\n";
+ if (port.hints & kAudioPortIsCV)
+ pluginString += " a lv2:InputPort, lv2:CVPort ;\n";
+ else
+ pluginString += " a lv2:InputPort, lv2:AudioPort ;\n";
+
pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
- pluginString += " lv2:symbol \"lv2_audio_in_" + d_string(i+1) + "\" ;\n";
- pluginString += " lv2:name \"Audio Input " + d_string(i+1) + "\" ;\n";
+ pluginString += " lv2:symbol \"" + port.symbol + "\" ;\n";
+ pluginString += " lv2:name \"" + port.name + "\" ;\n";
+
+ if (port.hints & kAudioPortIsSidechain)
+ pluginString += " lv2:portProperty lv2:isSideChain;\n";
if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS)
- pluginString += " ] ;\n\n";
+ pluginString += " ] ;\n";
else
pluginString += " ] ,\n";
}
@@ -226,18 +238,27 @@ void lv2_generate_ttl(const char* const basename)
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++portIndex)
{
+ const AudioPort& port(plugin.getAudioPort(false, i));
+
if (i == 0)
pluginString += " lv2:port [\n";
else
pluginString += " [\n";
- pluginString += " a lv2:OutputPort, lv2:AudioPort ;\n";
+ if (port.hints & kAudioPortIsCV)
+ pluginString += " a lv2:OutputPort, lv2:CVPort ;\n";
+ else
+ pluginString += " a lv2:OutputPort, lv2:AudioPort ;\n";
+
pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
- pluginString += " lv2:symbol \"lv2_audio_out_" + d_string(i+1) + "\" ;\n";
- pluginString += " lv2:name \"Audio Output " + d_string(i+1) + "\" ;\n";
+ pluginString += " lv2:symbol \"" + port.symbol + "\" ;\n";
+ pluginString += " lv2:name \"" + port.name + "\" ;\n";
+
+ if (port.hints & kAudioPortIsSidechain)
+ pluginString += " lv2:portProperty lv2:isSideChain;\n";
if (i+1 == DISTRHO_PLUGIN_NUM_OUTPUTS)
- pluginString += " ] ;\n\n";
+ pluginString += " ] ;\n";
else
pluginString += " ] ,\n";
}