@@ -185,6 +185,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 */ | |||
@@ -243,6 +266,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. | |||
@@ -670,6 +727,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. | |||
@@ -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; | |||
@@ -104,6 +109,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) */ | |||
@@ -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) | |||
@@ -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"; | |||
} | |||