@@ -28,6 +28,7 @@ | |||||
#define DISTRHO_PLUGIN_WANT_LATENCY 0 | #define DISTRHO_PLUGIN_WANT_LATENCY 0 | ||||
#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | ||||
#define DISTRHO_PLUGIN_WANT_STATE 0 | #define DISTRHO_PLUGIN_WANT_STATE 0 | ||||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||||
#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/3BandEQ" | #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/3BandEQ" | ||||
@@ -28,6 +28,7 @@ | |||||
#define DISTRHO_PLUGIN_WANT_LATENCY 0 | #define DISTRHO_PLUGIN_WANT_LATENCY 0 | ||||
#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | ||||
#define DISTRHO_PLUGIN_WANT_STATE 0 | #define DISTRHO_PLUGIN_WANT_STATE 0 | ||||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||||
#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/3BandSplitter" | #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/3BandSplitter" | ||||
@@ -29,6 +29,7 @@ | |||||
#define DISTRHO_PLUGIN_WANT_LATENCY 0 | #define DISTRHO_PLUGIN_WANT_LATENCY 0 | ||||
#define DISTRHO_PLUGIN_WANT_PROGRAMS 0 | #define DISTRHO_PLUGIN_WANT_PROGRAMS 0 | ||||
#define DISTRHO_PLUGIN_WANT_STATE 0 | #define DISTRHO_PLUGIN_WANT_STATE 0 | ||||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||||
#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/Nekobi" | #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/Nekobi" | ||||
@@ -29,6 +29,7 @@ | |||||
#define DISTRHO_PLUGIN_WANT_LATENCY 0 | #define DISTRHO_PLUGIN_WANT_LATENCY 0 | ||||
#define DISTRHO_PLUGIN_WANT_PROGRAMS 0 | #define DISTRHO_PLUGIN_WANT_PROGRAMS 0 | ||||
#define DISTRHO_PLUGIN_WANT_STATE 1 | #define DISTRHO_PLUGIN_WANT_STATE 1 | ||||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||||
#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/Notes" | #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/Notes" | ||||
@@ -28,6 +28,7 @@ | |||||
#define DISTRHO_PLUGIN_WANT_LATENCY 0 | #define DISTRHO_PLUGIN_WANT_LATENCY 0 | ||||
#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | ||||
#define DISTRHO_PLUGIN_WANT_STATE 0 | #define DISTRHO_PLUGIN_WANT_STATE 0 | ||||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||||
#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/PingPongPan" | #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/PingPongPan" | ||||
@@ -28,6 +28,7 @@ | |||||
#define DISTRHO_PLUGIN_WANT_LATENCY 0 | #define DISTRHO_PLUGIN_WANT_LATENCY 0 | ||||
#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | ||||
#define DISTRHO_PLUGIN_WANT_STATE 0 | #define DISTRHO_PLUGIN_WANT_STATE 0 | ||||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||||
#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/StereoEnhancer" | #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/StereoEnhancer" | ||||
@@ -87,7 +87,7 @@ struct ParameterRanges { | |||||
value = max; | value = max; | ||||
} | } | ||||
float fixValue(const float& value) const | |||||
float fixedValue(const float& value) const | |||||
{ | { | ||||
if (value < min) | if (value < min) | ||||
return min; | return min; | ||||
@@ -96,19 +96,19 @@ struct ParameterRanges { | |||||
return value; | return value; | ||||
} | } | ||||
float normalizeValue(const float& value) const | |||||
float normalizedValue(const float& value) const | |||||
{ | { | ||||
float newValue = (value - min) / (max - min); | |||||
const float newValue((value - min) / (max - min)); | |||||
if (newValue < 0.0f) | if (newValue < 0.0f) | ||||
newValue = 0.0f; | |||||
return 0.0f; | |||||
else if (newValue > 1.0f) | else if (newValue > 1.0f) | ||||
newValue = 1.0f; | |||||
return 1.0f; | |||||
return newValue; | return newValue; | ||||
} | } | ||||
float unnormalizeValue(const float& value) const | |||||
float unnormalizedValue(const float& value) const | |||||
{ | { | ||||
return value * (max - min) + min; | return value * (max - min) + min; | ||||
} | } | ||||
@@ -189,7 +189,9 @@ public: | |||||
uint32_t d_bufferSize() const; | uint32_t d_bufferSize() const; | ||||
double d_sampleRate() const; | double d_sampleRate() const; | ||||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||||
const TimePos& d_timePos() const; | const TimePos& d_timePos() const; | ||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_LATENCY | #if DISTRHO_PLUGIN_WANT_LATENCY | ||||
void d_setLatency(uint32_t frames); | void d_setLatency(uint32_t frames); | ||||
#endif | #endif | ||||
@@ -22,6 +22,7 @@ | |||||
# include "src/DistrhoPluginLADSPA+DSSI.cpp" | # include "src/DistrhoPluginLADSPA+DSSI.cpp" | ||||
#elif defined(DISTRHO_PLUGIN_TARGET_LV2) | #elif defined(DISTRHO_PLUGIN_TARGET_LV2) | ||||
# include "src/DistrhoPluginLV2.cpp" | # include "src/DistrhoPluginLV2.cpp" | ||||
# include "src/DistrhoPluginLV2export.cpp" | |||||
#elif defined(DISTRHO_PLUGIN_TARGET_VST) | #elif defined(DISTRHO_PLUGIN_TARGET_VST) | ||||
# include "src/DistrhoPluginVST.cpp" | # include "src/DistrhoPluginVST.cpp" | ||||
#endif | #endif |
@@ -51,6 +51,10 @@ | |||||
# error DISTRHO_PLUGIN_WANT_STATE undefined! | # error DISTRHO_PLUGIN_WANT_STATE undefined! | ||||
#endif | #endif | ||||
#ifndef DISTRHO_PLUGIN_WANT_TIMEPOS | |||||
# error DISTRHO_PLUGIN_WANT_TIMEPOS undefined! | |||||
#endif | |||||
#if DISTRHO_PLUGIN_HAS_UI | #if DISTRHO_PLUGIN_HAS_UI | ||||
# if ! (defined(DISTRHO_UI_EXTERNAL) || defined(DISTRHO_UI_OPENGL) || defined(DISTRHO_UI_QT)) | # if ! (defined(DISTRHO_UI_EXTERNAL) || defined(DISTRHO_UI_OPENGL) || defined(DISTRHO_UI_QT)) | ||||
# error DISTRHO_PLUGIN_HAS_UI is defined but not its type; please define one of DISTRHO_UI_EXTERNAL, DISTRHO_UI_OPENGL or DISTRHO_UI_QT | # error DISTRHO_PLUGIN_HAS_UI is defined but not its type; please define one of DISTRHO_UI_EXTERNAL, DISTRHO_UI_OPENGL or DISTRHO_UI_QT | ||||
@@ -77,10 +77,12 @@ double Plugin::d_sampleRate() const | |||||
return pData->sampleRate; | return pData->sampleRate; | ||||
} | } | ||||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||||
const TimePos& Plugin::d_timePos() const | const TimePos& Plugin::d_timePos() const | ||||
{ | { | ||||
return pData->timePos; | return pData->timePos; | ||||
} | } | ||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_LATENCY | #if DISTRHO_PLUGIN_WANT_LATENCY | ||||
void Plugin::d_setLatency(uint32_t frames) | void Plugin::d_setLatency(uint32_t frames) | ||||
@@ -49,7 +49,11 @@ struct Plugin::PrivateData { | |||||
uint32_t latency; | uint32_t latency; | ||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||||
TimePos timePos; | TimePos timePos; | ||||
#endif | |||||
char _d; // dummy | |||||
PrivateData() | PrivateData() | ||||
: bufferSize(d_lastBufferSize), | : bufferSize(d_lastBufferSize), | ||||
@@ -67,7 +71,7 @@ struct Plugin::PrivateData { | |||||
#if DISTRHO_PLUGIN_WANT_LATENCY | #if DISTRHO_PLUGIN_WANT_LATENCY | ||||
latency(0), | latency(0), | ||||
#endif | #endif | ||||
timePos() | |||||
_d(0) | |||||
{ | { | ||||
assert(bufferSize != 0); | assert(bufferSize != 0); | ||||
assert(sampleRate != 0.0); | assert(sampleRate != 0.0); | ||||
@@ -76,16 +80,25 @@ struct Plugin::PrivateData { | |||||
~PrivateData() | ~PrivateData() | ||||
{ | { | ||||
if (parameterCount > 0 && parameters != nullptr) | if (parameterCount > 0 && parameters != nullptr) | ||||
{ | |||||
delete[] parameters; | delete[] parameters; | ||||
parameters = nullptr; | |||||
} | |||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | #if DISTRHO_PLUGIN_WANT_PROGRAMS | ||||
if (programCount > 0 && programNames != nullptr) | if (programCount > 0 && programNames != nullptr) | ||||
{ | |||||
delete[] programNames; | delete[] programNames; | ||||
programNames = nullptr; | |||||
} | |||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
if (stateCount > 0 && stateKeys != nullptr) | if (stateCount > 0 && stateKeys != nullptr) | ||||
{ | |||||
delete[] stateKeys; | delete[] stateKeys; | ||||
stateKeys = nullptr; | |||||
} | |||||
#endif | #endif | ||||
} | } | ||||
}; | }; | ||||
@@ -178,48 +191,48 @@ public: | |||||
return (kData != nullptr) ? kData->parameterCount : 0; | return (kData != nullptr) ? kData->parameterCount : 0; | ||||
} | } | ||||
uint32_t parameterHints(uint32_t index) const | |||||
uint32_t parameterHints(const uint32_t index) const | |||||
{ | { | ||||
assert(kData != nullptr && index < kData->parameterCount); | assert(kData != nullptr && index < kData->parameterCount); | ||||
return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].hints : 0x0; | return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].hints : 0x0; | ||||
} | } | ||||
bool parameterIsOutput(uint32_t index) const | |||||
bool parameterIsOutput(const uint32_t index) const | |||||
{ | { | ||||
return (parameterHints(index) & PARAMETER_IS_OUTPUT); | return (parameterHints(index) & PARAMETER_IS_OUTPUT); | ||||
} | } | ||||
const d_string& parameterName(uint32_t index) const | |||||
const d_string& parameterName(const uint32_t index) const | |||||
{ | { | ||||
assert(kData != nullptr && index < kData->parameterCount); | assert(kData != nullptr && index < kData->parameterCount); | ||||
return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].name : sFallbackString; | return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].name : sFallbackString; | ||||
} | } | ||||
const d_string& parameterSymbol(uint32_t index) const | |||||
const d_string& parameterSymbol(const uint32_t index) const | |||||
{ | { | ||||
assert(kData != nullptr && index < kData->parameterCount); | assert(kData != nullptr && index < kData->parameterCount); | ||||
return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].symbol : sFallbackString; | return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].symbol : sFallbackString; | ||||
} | } | ||||
const d_string& parameterUnit(uint32_t index) const | |||||
const d_string& parameterUnit(const uint32_t index) const | |||||
{ | { | ||||
assert(kData != nullptr && index < kData->parameterCount); | assert(kData != nullptr && index < kData->parameterCount); | ||||
return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].unit : sFallbackString; | return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].unit : sFallbackString; | ||||
} | } | ||||
const ParameterRanges& parameterRanges(uint32_t index) const | |||||
const ParameterRanges& parameterRanges(const uint32_t index) const | |||||
{ | { | ||||
assert(kData != nullptr && index < kData->parameterCount); | assert(kData != nullptr && index < kData->parameterCount); | ||||
return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].ranges : sFallbackRanges; | return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].ranges : sFallbackRanges; | ||||
} | } | ||||
float parameterValue(uint32_t index) | |||||
float parameterValue(const uint32_t index) | |||||
{ | { | ||||
assert(kPlugin != nullptr && index < kData->parameterCount); | assert(kPlugin != nullptr && index < kData->parameterCount); | ||||
return (kPlugin != nullptr && index < kData->parameterCount) ? kPlugin->d_parameterValue(index) : 0.0f; | return (kPlugin != nullptr && index < kData->parameterCount) ? kPlugin->d_parameterValue(index) : 0.0f; | ||||
} | } | ||||
void setParameterValue(uint32_t index, float value) | |||||
void setParameterValue(const uint32_t index, const float value) | |||||
{ | { | ||||
assert(kPlugin != nullptr && index < kData->parameterCount); | assert(kPlugin != nullptr && index < kData->parameterCount); | ||||
@@ -234,13 +247,13 @@ public: | |||||
return (kData != nullptr) ? kData->programCount : 0; | return (kData != nullptr) ? kData->programCount : 0; | ||||
} | } | ||||
const d_string& programName(uint32_t index) const | |||||
const d_string& programName(const uint32_t index) const | |||||
{ | { | ||||
assert(kData != nullptr && index < kData->programCount); | assert(kData != nullptr && index < kData->programCount); | ||||
return (kData != nullptr && index < kData->programCount) ? kData->programNames[index] : sFallbackString; | return (kData != nullptr && index < kData->programCount) ? kData->programNames[index] : sFallbackString; | ||||
} | } | ||||
void setProgram(uint32_t index) | |||||
void setProgram(const uint32_t index) | |||||
{ | { | ||||
assert(kPlugin != nullptr && index < kData->programCount); | assert(kPlugin != nullptr && index < kData->programCount); | ||||
@@ -256,13 +269,13 @@ public: | |||||
return kData != nullptr ? kData->stateCount : 0; | return kData != nullptr ? kData->stateCount : 0; | ||||
} | } | ||||
const d_string& stateKey(uint32_t index) const | |||||
const d_string& stateKey(const uint32_t index) const | |||||
{ | { | ||||
assert(kData != nullptr && index < kData->stateCount); | assert(kData != nullptr && index < kData->stateCount); | ||||
return (kData != nullptr && index < kData->stateCount) ? kData->stateKeys[index] : sFallbackString; | return (kData != nullptr && index < kData->stateCount) ? kData->stateKeys[index] : sFallbackString; | ||||
} | } | ||||
void setState(const char* key, const char* value) | |||||
void setState(const char* const key, const char* const value) | |||||
{ | { | ||||
assert(kPlugin != nullptr && key != nullptr && value != nullptr); | assert(kPlugin != nullptr && key != nullptr && value != nullptr); | ||||
@@ -289,7 +302,7 @@ public: | |||||
kPlugin->d_deactivate(); | kPlugin->d_deactivate(); | ||||
} | } | ||||
void run(float** inputs, float** outputs, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents) | |||||
void run(float** const inputs, float** const outputs, const uint32_t frames, const uint32_t midiEventCount, const MidiEvent* const midiEvents) | |||||
{ | { | ||||
assert(kPlugin != nullptr); | assert(kPlugin != nullptr); | ||||
@@ -299,7 +312,7 @@ public: | |||||
// --------------------------------------------- | // --------------------------------------------- | ||||
void setBufferSize(uint32_t bufferSize, bool doCallback = false) | |||||
void setBufferSize(const uint32_t bufferSize, bool doCallback = false) | |||||
{ | { | ||||
assert(kData != nullptr && kPlugin != nullptr && bufferSize >= 2); | assert(kData != nullptr && kPlugin != nullptr && bufferSize >= 2); | ||||
@@ -319,7 +332,7 @@ public: | |||||
} | } | ||||
} | } | ||||
void setSampleRate(double sampleRate, bool doCallback = false) | |||||
void setSampleRate(const double sampleRate, bool doCallback = false) | |||||
{ | { | ||||
assert(kData != nullptr && kPlugin != nullptr && sampleRate > 0.0); | assert(kData != nullptr && kPlugin != nullptr && sampleRate > 0.0); | ||||
@@ -28,12 +28,16 @@ | |||||
# endif | # endif | ||||
#endif | #endif | ||||
typedef LADSPA_Data* LADSPA_DataPtr; | |||||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||||
# warning LADSPA/DSSI does not support TimePos | |||||
#endif | |||||
// ------------------------------------------------- | // ------------------------------------------------- | ||||
START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
typedef LADSPA_Data* LADSPA_DataPtr; | |||||
class PluginLadspaDssi | class PluginLadspaDssi | ||||
{ | { | ||||
public: | public: | ||||
@@ -84,9 +88,9 @@ public: | |||||
void ladspa_connect_port(const unsigned long port, const LADSPA_DataPtr dataLocation) | void ladspa_connect_port(const unsigned long port, const LADSPA_DataPtr dataLocation) | ||||
{ | { | ||||
unsigned long i, count, index = 0; | |||||
unsigned long index = 0; | |||||
for (i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | |||||
for (unsigned long i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | |||||
{ | { | ||||
if (port == index++) | if (port == index++) | ||||
{ | { | ||||
@@ -95,7 +99,7 @@ public: | |||||
} | } | ||||
} | } | ||||
for (i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |||||
for (unsigned long i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |||||
{ | { | ||||
if (port == index++) | if (port == index++) | ||||
{ | { | ||||
@@ -112,7 +116,7 @@ public: | |||||
} | } | ||||
#endif | #endif | ||||
for (i=0, count=fPlugin.parameterCount(); i < count; ++i) | |||||
for (unsigned long i=0, count=fPlugin.parameterCount(); i < count; ++i) | |||||
{ | { | ||||
if (port == index++) | if (port == index++) | ||||
{ | { | ||||
@@ -216,10 +220,10 @@ public: | |||||
} | } | ||||
} | } | ||||
#ifdef DISTRHO_PLUGIN_TARGET_DSSI | |||||
# if DISTRHO_PLUGIN_IS_SYNTH | |||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
// Get MIDI Events | // Get MIDI Events | ||||
uint32_t midiEventCount = 0; | |||||
uint32_t midiEventCount = 0; | |||||
MidiEvent midiEvents[eventCount]; | |||||
for (uint32_t i=0, j; i < eventCount && midiEventCount < MAX_MIDI_EVENTS; ++i) | for (uint32_t i=0, j; i < eventCount && midiEventCount < MAX_MIDI_EVENTS; ++i) | ||||
{ | { | ||||
@@ -232,71 +236,64 @@ public: | |||||
{ | { | ||||
case SND_SEQ_EVENT_NOTEON: | case SND_SEQ_EVENT_NOTEON: | ||||
j = midiEventCount++; | j = midiEventCount++; | ||||
fMidiEvents[j].frame = seqEvent.time.tick; | |||||
fMidiEvents[j].buf[0] = 0x90 + seqEvent.data.note.channel; | |||||
fMidiEvents[j].buf[1] = seqEvent.data.note.note; | |||||
fMidiEvents[j].buf[2] = seqEvent.data.note.velocity; | |||||
fMidiEvents[j].buf[3] = 0; | |||||
fMidiEvents[j].size = 3; | |||||
midiEvents[j].frame = seqEvent.time.tick; | |||||
midiEvents[j].buf[0] = 0x90 + seqEvent.data.note.channel; | |||||
midiEvents[j].buf[1] = seqEvent.data.note.note; | |||||
midiEvents[j].buf[2] = seqEvent.data.note.velocity; | |||||
midiEvents[j].buf[3] = 0; | |||||
midiEvents[j].size = 3; | |||||
break; | break; | ||||
case SND_SEQ_EVENT_NOTEOFF: | case SND_SEQ_EVENT_NOTEOFF: | ||||
j = midiEventCount++; | j = midiEventCount++; | ||||
fMidiEvents[j].frame = seqEvent.time.tick; | |||||
fMidiEvents[j].buf[0] = 0x80 + seqEvent.data.note.channel; | |||||
fMidiEvents[j].buf[1] = seqEvent.data.note.note; | |||||
fMidiEvents[j].buf[2] = 0; | |||||
fMidiEvents[j].buf[3] = 0; | |||||
fMidiEvents[j].size = 3; | |||||
midiEvents[j].frame = seqEvent.time.tick; | |||||
midiEvents[j].buf[0] = 0x80 + seqEvent.data.note.channel; | |||||
midiEvents[j].buf[1] = seqEvent.data.note.note; | |||||
midiEvents[j].buf[2] = 0; | |||||
midiEvents[j].buf[3] = 0; | |||||
midiEvents[j].size = 3; | |||||
break; | break; | ||||
case SND_SEQ_EVENT_KEYPRESS: | case SND_SEQ_EVENT_KEYPRESS: | ||||
j = midiEventCount++; | j = midiEventCount++; | ||||
fMidiEvents[j].frame = seqEvent.time.tick; | |||||
fMidiEvents[j].buf[0] = 0xA0 + seqEvent.data.note.channel; | |||||
fMidiEvents[j].buf[1] = seqEvent.data.note.note; | |||||
fMidiEvents[j].buf[2] = seqEvent.data.note.velocity; | |||||
fMidiEvents[j].buf[3] = 0; | |||||
fMidiEvents[j].size = 3; | |||||
midiEvents[j].frame = seqEvent.time.tick; | |||||
midiEvents[j].buf[0] = 0xA0 + seqEvent.data.note.channel; | |||||
midiEvents[j].buf[1] = seqEvent.data.note.note; | |||||
midiEvents[j].buf[2] = seqEvent.data.note.velocity; | |||||
midiEvents[j].buf[3] = 0; | |||||
midiEvents[j].size = 3; | |||||
break; | break; | ||||
case SND_SEQ_EVENT_CONTROLLER: | case SND_SEQ_EVENT_CONTROLLER: | ||||
j = midiEventCount++; | j = midiEventCount++; | ||||
fMidiEvents[j].frame = seqEvent.time.tick; | |||||
fMidiEvents[j].buf[0] = 0xB0 + seqEvent.data.control.channel; | |||||
fMidiEvents[j].buf[1] = seqEvent.data.control.param; | |||||
fMidiEvents[j].buf[2] = seqEvent.data.control.value; | |||||
fMidiEvents[j].buf[3] = 0; | |||||
fMidiEvents[j].size = 3; | |||||
midiEvents[j].frame = seqEvent.time.tick; | |||||
midiEvents[j].buf[0] = 0xB0 + seqEvent.data.control.channel; | |||||
midiEvents[j].buf[1] = seqEvent.data.control.param; | |||||
midiEvents[j].buf[2] = seqEvent.data.control.value; | |||||
midiEvents[j].buf[3] = 0; | |||||
midiEvents[j].size = 3; | |||||
break; | break; | ||||
case SND_SEQ_EVENT_CHANPRESS: | case SND_SEQ_EVENT_CHANPRESS: | ||||
j = midiEventCount++; | j = midiEventCount++; | ||||
fMidiEvents[j].frame = seqEvent.time.tick; | |||||
fMidiEvents[j].buf[0] = 0xD0 + seqEvent.data.control.channel; | |||||
fMidiEvents[j].buf[1] = seqEvent.data.control.value; | |||||
fMidiEvents[j].buf[2] = 0; | |||||
fMidiEvents[j].buf[3] = 0; | |||||
fMidiEvents[j].size = 2; | |||||
midiEvents[j].frame = seqEvent.time.tick; | |||||
midiEvents[j].buf[0] = 0xD0 + seqEvent.data.control.channel; | |||||
midiEvents[j].buf[1] = seqEvent.data.control.value; | |||||
midiEvents[j].buf[2] = 0; | |||||
midiEvents[j].buf[3] = 0; | |||||
midiEvents[j].size = 2; | |||||
break; | break; | ||||
case SND_SEQ_EVENT_PITCHBEND: // TODO | |||||
#if 0 // TODO | |||||
case SND_SEQ_EVENT_PITCHBEND: | |||||
j = midiEventCount++; | j = midiEventCount++; | ||||
fMidiEvents[j].frame = seqEvent.time.tick; | |||||
fMidiEvents[j].buf[0] = 0xE0 + seqEvent.data.control.channel; | |||||
fMidiEvents[j].buf[1] = 0; | |||||
fMidiEvents[j].buf[2] = 0; | |||||
fMidiEvents[j].buf[3] = 0; | |||||
fMidiEvents[j].size = 3; | |||||
midiEvents[j].frame = seqEvent.time.tick; | |||||
midiEvents[j].buf[0] = 0xE0 + seqEvent.data.control.channel; | |||||
midiEvents[j].buf[1] = 0; | |||||
midiEvents[j].buf[2] = 0; | |||||
midiEvents[j].buf[3] = 0; | |||||
midiEvents[j].size = 3; | |||||
break; | break; | ||||
#endif | |||||
} | } | ||||
} | } | ||||
# else | |||||
return; | |||||
// unused | |||||
(void)events; | |||||
(void)eventCount; | |||||
# endif | |||||
#endif | |||||
// Run plugin for this cycle | |||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
fPlugin.run(fPortAudioIns, fPortAudioOuts, bufferSize, midiEventCount, fMidiEvents); | |||||
fPlugin.run(fPortAudioIns, fPortAudioOuts, bufferSize, midiEventCount, midiEvents); | |||||
#else | #else | ||||
fPlugin.run(fPortAudioIns, fPortAudioOuts, bufferSize, 0, nullptr); | fPlugin.run(fPortAudioIns, fPortAudioOuts, bufferSize, 0, nullptr); | ||||
#endif | #endif | ||||
@@ -316,10 +313,6 @@ private: | |||||
LADSPA_DataPtr fPortLatency; | LADSPA_DataPtr fPortLatency; | ||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
MidiEvent fMidiEvents[MAX_MIDI_EVENTS]; | |||||
#endif | |||||
LADSPA_Data* fLastControlValues; | LADSPA_Data* fLastControlValues; | ||||
// --------------------------------------------- | // --------------------------------------------- | ||||
@@ -480,38 +473,38 @@ public: | |||||
d_lastSampleRate = 0.0; | d_lastSampleRate = 0.0; | ||||
// Get port count, init | // Get port count, init | ||||
unsigned long i, port = 0; | |||||
unsigned long port = 0; | |||||
unsigned long portCount = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS + plugin.parameterCount(); | unsigned long portCount = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS + plugin.parameterCount(); | ||||
#if DISTRHO_PLUGIN_WANT_LATENCY | #if DISTRHO_PLUGIN_WANT_LATENCY | ||||
portCount += 1; | portCount += 1; | ||||
#endif | #endif | ||||
const char** const portNames = new const char* [portCount]; | |||||
LADSPA_PortDescriptor* portDescriptors = new LADSPA_PortDescriptor [portCount]; | |||||
LADSPA_PortRangeHint* portRangeHints = new LADSPA_PortRangeHint [portCount]; | |||||
const char** const portNames = new const char*[portCount]; | |||||
LADSPA_PortDescriptor* portDescriptors = new LADSPA_PortDescriptor[portCount]; | |||||
LADSPA_PortRangeHint* portRangeHints = new LADSPA_PortRangeHint [portCount]; | |||||
// Set ports | // Set ports | ||||
for (i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++port) | |||||
for (unsigned long i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++port) | |||||
{ | { | ||||
char portName[24] = { '\0' }; | char portName[24] = { '\0' }; | ||||
sprintf(portName, "Audio Input %lu", i+1); | |||||
std::sprintf(portName, "Audio Input %lu", i+1); | |||||
portNames[port] = strdup(portName); | portNames[port] = strdup(portName); | ||||
portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT; | portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT; | ||||
portRangeHints[port].HintDescriptor = 0; | |||||
portRangeHints[port].HintDescriptor = 0x0; | |||||
portRangeHints[port].LowerBound = 0.0f; | portRangeHints[port].LowerBound = 0.0f; | ||||
portRangeHints[port].UpperBound = 1.0f; | portRangeHints[port].UpperBound = 1.0f; | ||||
} | } | ||||
for (i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++port) | |||||
for (unsigned long i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++port) | |||||
{ | { | ||||
char portName[24] = { '\0' }; | char portName[24] = { '\0' }; | ||||
sprintf(portName, "Audio Output %lu", i+1); | |||||
std::sprintf(portName, "Audio Output %lu", i+1); | |||||
portNames[port] = strdup(portName); | portNames[port] = strdup(portName); | ||||
portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT; | portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT; | ||||
portRangeHints[port].HintDescriptor = 0; | |||||
portRangeHints[port].HintDescriptor = 0x0; | |||||
portRangeHints[port].LowerBound = 0.0f; | portRangeHints[port].LowerBound = 0.0f; | ||||
portRangeHints[port].UpperBound = 1.0f; | portRangeHints[port].UpperBound = 1.0f; | ||||
} | } | ||||
@@ -526,7 +519,7 @@ public: | |||||
++port; | ++port; | ||||
#endif | #endif | ||||
for (i=0; i < plugin.parameterCount(); ++i, ++port) | |||||
for (unsigned long i=0, count=plugin.parameterCount(); i < count; ++i, ++port) | |||||
{ | { | ||||
portNames[port] = strdup((const char*)plugin.parameterName(i)); | portNames[port] = strdup((const char*)plugin.parameterName(i)); | ||||
portDescriptors[port] = LADSPA_PORT_CONTROL; | portDescriptors[port] = LADSPA_PORT_CONTROL; | ||||
@@ -538,7 +531,7 @@ public: | |||||
{ | { | ||||
const ParameterRanges& ranges(plugin.parameterRanges(i)); | const ParameterRanges& ranges(plugin.parameterRanges(i)); | ||||
const float defValue = ranges.def; | |||||
const float defValue(ranges.def); | |||||
portRangeHints[port].HintDescriptor = LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE; | portRangeHints[port].HintDescriptor = LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE; | ||||
portRangeHints[port].LowerBound = ranges.min; | portRangeHints[port].LowerBound = ranges.min; | ||||
@@ -558,9 +551,9 @@ public: | |||||
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM; | portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM; | ||||
else | else | ||||
{ | { | ||||
const float middleValue = ranges.min/2 + ranges.max/2; | |||||
const float middleLow = (ranges.min/2 + middleValue/2)/2 + middleValue/2; | |||||
const float middleHigh = (ranges.max/2 + middleValue/2)/2 + middleValue/2; | |||||
const float middleValue = ranges.min/2.0f + ranges.max/2.0f; | |||||
const float middleLow = (ranges.min/2.0f + middleValue/2.0f)/2.0f + middleValue/2.0f; | |||||
const float middleHigh = (ranges.max/2.0f + middleValue/2.0f)/2.0f + middleValue/2.0f; | |||||
if (defValue < middleLow) | if (defValue < middleLow) | ||||
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_LOW; | portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_LOW; | ||||
@@ -598,37 +591,59 @@ public: | |||||
~DescriptorInitializer() | ~DescriptorInitializer() | ||||
{ | { | ||||
if (sLadspaDescriptor.Label != nullptr) | if (sLadspaDescriptor.Label != nullptr) | ||||
free((void*)sLadspaDescriptor.Label); | |||||
{ | |||||
std::free((void*)sLadspaDescriptor.Label); | |||||
sLadspaDescriptor.Label = nullptr; | |||||
} | |||||
if (sLadspaDescriptor.Name != nullptr) | if (sLadspaDescriptor.Name != nullptr) | ||||
free((void*)sLadspaDescriptor.Name); | |||||
{ | |||||
std::free((void*)sLadspaDescriptor.Name); | |||||
sLadspaDescriptor.Name = nullptr; | |||||
} | |||||
if (sLadspaDescriptor.Maker != nullptr) | if (sLadspaDescriptor.Maker != nullptr) | ||||
free((void*)sLadspaDescriptor.Maker); | |||||
{ | |||||
std::free((void*)sLadspaDescriptor.Maker); | |||||
sLadspaDescriptor.Maker = nullptr; | |||||
} | |||||
if (sLadspaDescriptor.Copyright != nullptr) | if (sLadspaDescriptor.Copyright != nullptr) | ||||
free((void*)sLadspaDescriptor.Copyright); | |||||
{ | |||||
std::free((void*)sLadspaDescriptor.Copyright); | |||||
sLadspaDescriptor.Copyright = nullptr; | |||||
} | |||||
if (sLadspaDescriptor.PortDescriptors != nullptr) | if (sLadspaDescriptor.PortDescriptors != nullptr) | ||||
{ | |||||
delete[] sLadspaDescriptor.PortDescriptors; | delete[] sLadspaDescriptor.PortDescriptors; | ||||
sLadspaDescriptor.PortDescriptors = nullptr; | |||||
} | |||||
if (sLadspaDescriptor.PortRangeHints != nullptr) | if (sLadspaDescriptor.PortRangeHints != nullptr) | ||||
{ | |||||
delete[] sLadspaDescriptor.PortRangeHints; | delete[] sLadspaDescriptor.PortRangeHints; | ||||
sLadspaDescriptor.PortRangeHints = nullptr; | |||||
} | |||||
if (sLadspaDescriptor.PortNames != nullptr) | if (sLadspaDescriptor.PortNames != nullptr) | ||||
{ | { | ||||
for (unsigned long i=0; i < sLadspaDescriptor.PortCount; ++i) | for (unsigned long i=0; i < sLadspaDescriptor.PortCount; ++i) | ||||
{ | { | ||||
if (sLadspaDescriptor.PortNames[i] != nullptr) | if (sLadspaDescriptor.PortNames[i] != nullptr) | ||||
free((void*)sLadspaDescriptor.PortNames[i]); | |||||
{ | |||||
std::free((void*)sLadspaDescriptor.PortNames[i]); | |||||
sLadspaDescriptor.PortNames[i] = nullptr; | |||||
} | |||||
} | } | ||||
delete[] sLadspaDescriptor.PortNames; | delete[] sLadspaDescriptor.PortNames; | ||||
sLadspaDescriptor.PortNames = nullptr; | |||||
} | } | ||||
} | } | ||||
}; | }; | ||||
static DescriptorInitializer sInit; | |||||
static DescriptorInitializer sDescInit; | |||||
END_NAMESPACE_DISTRHO | END_NAMESPACE_DISTRHO | ||||
@@ -0,0 +1,663 @@ | |||||
/* | |||||
* DISTRHO Plugin Toolkit (DPT) | |||||
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com> | |||||
* | |||||
* This program is free software; you can redistribute it and/or | |||||
* modify it under the terms of the GNU Lesser General Public | |||||
* License as published by the Free Software Foundation. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU Lesser General Public License for more details. | |||||
* | |||||
* For a full copy of the license see the LGPL.txt file | |||||
*/ | |||||
#include "DistrhoPluginInternal.hpp" | |||||
#include "lv2/lv2.h" | |||||
#include "lv2/atom.h" | |||||
#include "lv2/buf-size.h" | |||||
#include "lv2/options.h" | |||||
#include "lv2/programs.h" | |||||
#include "lv2/state.h" | |||||
#include "lv2/urid.h" | |||||
#include "lv2/worker.h" | |||||
// #include "lv2/atom-util.h" | |||||
// #include "lv2/midi.h" | |||||
#include <map> | |||||
#ifndef DISTRHO_PLUGIN_URI | |||||
# error DISTRHO_PLUGIN_URI undefined! | |||||
#endif | |||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
# warning LV2 Synth still TODO | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
# warning LV2 State still TODO | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||||
# warning LV2 TimePos still TODO | |||||
#endif | |||||
#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_STATE || DISTRHO_PLUGIN_WANT_TIMEPOS) | |||||
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_STATE) | |||||
// ------------------------------------------------- | |||||
START_NAMESPACE_DISTRHO | |||||
typedef float* floatptr; | |||||
typedef std::map<d_string,d_string> stringMap; | |||||
class PluginLv2 | |||||
{ | |||||
public: | |||||
PluginLv2(const LV2_URID_Map* const uridMap, const LV2_Worker_Schedule* const worker) | |||||
: fPortControls(nullptr), | |||||
fLastControlValues(nullptr), | |||||
fUridMap(uridMap), | |||||
fWorker(worker) | |||||
{ | |||||
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | |||||
fPortAudioIns[i] = nullptr; | |||||
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |||||
fPortAudioOuts[i] = nullptr; | |||||
{ | |||||
const uint32_t count(fPlugin.parameterCount()); | |||||
fPortControls = new floatptr[count];; | |||||
fLastControlValues = new float[count];; | |||||
for (uint32_t i=0; i < count; ++i) | |||||
{ | |||||
fPortControls[i] = nullptr; | |||||
fLastControlValues[i] = fPlugin.parameterValue(i); | |||||
} | |||||
} | |||||
#if DISTRHO_LV2_USE_EVENTS_IN | |||||
fPortEventsIn = nullptr; | |||||
#endif | |||||
#if DISTRHO_LV2_USE_EVENTS_OUT | |||||
fPortEventsOut = nullptr; | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_LATENCY | |||||
fPortLatency = nullptr; | |||||
#endif | |||||
// #if DISTRHO_LV2_USE_EVENTS | |||||
// uridIdAtomString = 0; | |||||
// # if DISTRHO_PLUGIN_IS_SYNTH | |||||
// uridIdMidiEvent = 0; | |||||
// # endif | |||||
// # if DISTRHO_PLUGIN_WANT_STATE | |||||
// # endif | |||||
// | |||||
// for (uint32_t i=0; features[i]; i++) | |||||
// { | |||||
// if (strcmp(features[i]->URI, LV2_URID__map) == 0) | |||||
// { | |||||
// uridMap = (LV2_URID_Map*)features[i]->data; | |||||
// | |||||
// uridIdAtomString = uridMap->map(uridMap->handle, LV2_ATOM__String); | |||||
// # if DISTRHO_PLUGIN_IS_SYNTH | |||||
// uridIdMidiEvent = uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent); | |||||
// # endif | |||||
// # if DISTRHO_PLUGIN_WANT_STATE | |||||
// uridIdPatchMessage = uridMap->map(uridMap->handle, LV2_PATCH__Message); | |||||
// # endif | |||||
// } | |||||
// else if (strcmp(features[i]->URI, LV2_WORKER__schedule) == 0) | |||||
// { | |||||
// workerSchedule = (LV2_Worker_Schedule*)features[i]->data; | |||||
// } | |||||
// } | |||||
// #endif | |||||
} | |||||
~PluginLv2() | |||||
{ | |||||
if (fPortControls != nullptr) | |||||
{ | |||||
delete[] fPortControls; | |||||
fPortControls = nullptr; | |||||
} | |||||
if (fLastControlValues) | |||||
{ | |||||
delete[] fLastControlValues; | |||||
fLastControlValues = nullptr; | |||||
} | |||||
// #if DISTRHO_PLUGIN_WANT_STATE | |||||
// stateMap.clear(); | |||||
// #endif | |||||
} | |||||
void lv2_activate() | |||||
{ | |||||
fPlugin.activate(); | |||||
} | |||||
void lv2_deactivate() | |||||
{ | |||||
fPlugin.deactivate(); | |||||
} | |||||
void lv2_connect_port(const uint32_t port, void* const dataLocation) | |||||
{ | |||||
uint32_t index = 0; | |||||
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | |||||
{ | |||||
if (port == index++) | |||||
{ | |||||
fPortAudioIns[i] = (floatptr)dataLocation; | |||||
return; | |||||
} | |||||
} | |||||
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |||||
{ | |||||
if (port == index++) | |||||
{ | |||||
fPortAudioOuts[i] = (floatptr)dataLocation; | |||||
return; | |||||
} | |||||
} | |||||
#if DISTRHO_LV2_USE_EVENTS_IN | |||||
if (port == index++) | |||||
{ | |||||
fPortEventsIn = (LV2_Atom_Sequence*)dataLocation; | |||||
return; | |||||
} | |||||
#endif | |||||
#if DISTRHO_LV2_USE_EVENTS_OUT | |||||
if (port == index++) | |||||
{ | |||||
fPortEventsOut = (LV2_Atom_Sequence*)dataLocation; | |||||
return; | |||||
} | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_LATENCY | |||||
if (port == index++) | |||||
{ | |||||
fPortLatency = (floatptr)dataLocation; | |||||
return; | |||||
} | |||||
#endif | |||||
for (uint32_t i=0, count=fPlugin.parameterCount(); i < count; ++i) | |||||
{ | |||||
if (port == index++) | |||||
{ | |||||
fPortControls[i] = (floatptr)dataLocation; | |||||
return; | |||||
} | |||||
} | |||||
} | |||||
void lv2_run(const uint32_t bufferSize) | |||||
{ | |||||
if (bufferSize == 0) | |||||
{ | |||||
updateParameterOutputs(); | |||||
return; | |||||
} | |||||
// Check for updated parameters | |||||
float curValue; | |||||
for (uint32_t i=0, count=fPlugin.parameterCount(); i < count; ++i) | |||||
{ | |||||
assert(fPortControls[i] != nullptr); | |||||
curValue = *fPortControls[i]; | |||||
if (fLastControlValues[i] != curValue && ! fPlugin.parameterIsOutput(i)) | |||||
{ | |||||
fLastControlValues[i] = curValue; | |||||
fPlugin.setParameterValue(i, curValue); | |||||
} | |||||
} | |||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
// Get Events, xxx | |||||
uint32_t midiEventCount = 0; | |||||
#if DISTRHO_LV2_USE_EVENTS | |||||
LV2_ATOM_SEQUENCE_FOREACH(portEventsIn, iter) | |||||
{ | |||||
const LV2_Atom_Event* event = /*(const LV2_Atom_Event*)*/iter; | |||||
if (! event) | |||||
continue; | |||||
# if DISTRHO_PLUGIN_IS_SYNTH | |||||
if (event->body.type == uridIdMidiEvent) | |||||
{ | |||||
if (event->time.frames >= bufferSize || midiEventCount >= MAX_MIDI_EVENTS) | |||||
break; | |||||
if (event->body.size > 3) | |||||
continue; | |||||
const uint8_t* data = (const uint8_t*)(event + 1); | |||||
midiEvents[midiEventCount].frame = event->time.frames; | |||||
memcpy(midiEvents[midiEventCount].buffer, data, event->body.size); | |||||
midiEventCount += 1; | |||||
continue; | |||||
} | |||||
# endif | |||||
# if DISTRHO_PLUGIN_WANT_STATE | |||||
if (event->body.type == uridIdPatchMessage) | |||||
{ | |||||
// TODO | |||||
//if (workerSchedule) | |||||
// workerSchedule->schedule_work(workerSchedule->handle, event->body.size, ) | |||||
} | |||||
# endif | |||||
} | |||||
#endif | |||||
fPlugin.run(fPortAudioIns, fPortAudioOuts, bufferSize, midiEventCount, midiEvents); | |||||
#else | |||||
fPlugin.run(fPortAudioIns, fPortAudioOuts, bufferSize, 0, nullptr); | |||||
#endif | |||||
updateParameterOutputs(); | |||||
} | |||||
uint32_t lv2_get_options(LV2_Options_Option* const /*options*/) | |||||
{ | |||||
// currently unused | |||||
return LV2_OPTIONS_SUCCESS; | |||||
} | |||||
uint32_t lv2_set_options(const LV2_Options_Option* const options) | |||||
{ | |||||
for (int i=0; options[i].key != 0; ++i) | |||||
{ | |||||
if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__maxBlockLength)) | |||||
{ | |||||
if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Int)) | |||||
{ | |||||
const int bufferSize(*(const int*)options[i].value); | |||||
fPlugin.setBufferSize(bufferSize); | |||||
} | |||||
else | |||||
d_stderr("Host changed maxBlockLength but with wrong value type"); | |||||
} | |||||
else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_CORE__sampleRate)) | |||||
{ | |||||
if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Double)) | |||||
{ | |||||
const double sampleRate(*(const double*)options[i].value); | |||||
fPlugin.setSampleRate(sampleRate); | |||||
} | |||||
else | |||||
d_stderr("Host changed sampleRate but with wrong value type"); | |||||
} | |||||
} | |||||
return LV2_OPTIONS_SUCCESS; | |||||
} | |||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
const LV2_Program_Descriptor* lv2_get_program(const uint32_t index) | |||||
{ | |||||
if (index >= fPlugin.programCount()) | |||||
return nullptr; | |||||
static LV2_Program_Descriptor desc; | |||||
desc.bank = index / 128; | |||||
desc.program = index % 128; | |||||
desc.name = fPlugin.programName(index); | |||||
return &desc; | |||||
} | |||||
void lv2_select_program(const uint32_t bank, const uint32_t program) | |||||
{ | |||||
const uint32_t realProgram(bank * 128 + program); | |||||
if (realProgram >= fPlugin.programCount()) | |||||
return; | |||||
fPlugin.setProgram(realProgram); | |||||
// Update parameters | |||||
for (uint32_t i=0, count=fPlugin.parameterCount(); i < count; ++i) | |||||
{ | |||||
if (! fPlugin.parameterIsOutput(i)) | |||||
{ | |||||
fLastControlValues[i] = fPlugin.parameterValue(i); | |||||
if (fPortControls[i] != nullptr) | |||||
*fPortControls[i] = fLastControlValues[i]; | |||||
} | |||||
} | |||||
} | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
LV2_State_Status lv2_save(LV2_State_Store_Function store, LV2_State_Handle handle, const uint32_t flags, const LV2_Feature* const* /*features*/) | |||||
{ | |||||
// flags = LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE; | |||||
// for (auto i = stateMap.begin(); i != stateMap.end(); i++) | |||||
// { | |||||
// const d_string& key = i->first; | |||||
// const d_string& value = i->second; | |||||
// | |||||
// store(handle, uridMap->map(uridMap->handle, (const char*)key), (const char*)value, value.length(), uridIdAtomString, flags); | |||||
// } | |||||
return LV2_STATE_SUCCESS; | |||||
} | |||||
LV2_State_Status lv2_restore(LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, const uint32_t flags, const LV2_Feature* const* /*features*/) | |||||
{ | |||||
// size_t size; | |||||
// uint32_t type; | |||||
// for (uint32_t i=0; i < plugin.stateCount(); i++) | |||||
// { | |||||
// const d_string& key = plugin.stateKey(i); | |||||
// | |||||
// const void* data = retrieve(handle, uridMap->map(uridMap->handle, (const char*)key), &size, &type, &flags); | |||||
// | |||||
// if (size == 0 || ! data) | |||||
// continue; | |||||
// if (type != uridIdAtomString) | |||||
// continue; | |||||
// | |||||
// const char* value = (const char*)data; | |||||
// setState(key, value); | |||||
// } | |||||
return LV2_STATE_SUCCESS; | |||||
} | |||||
LV2_Worker_Status lv2_work(LV2_Worker_Respond_Function /*respond*/, LV2_Worker_Respond_Handle /*handle*/, const uint32_t /*size*/, const void* /*data*/) | |||||
{ | |||||
// TODO | |||||
return LV2_WORKER_SUCCESS; | |||||
} | |||||
LV2_Worker_Status lv2_work_response(const uint32_t /*size*/, const void* /*body*/) | |||||
{ | |||||
// TODO | |||||
return LV2_WORKER_SUCCESS; | |||||
} | |||||
#endif | |||||
private: | |||||
PluginInternal fPlugin; | |||||
// LV2 ports | |||||
floatptr fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS]; | |||||
floatptr fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; | |||||
floatptr* fPortControls; | |||||
#if DISTRHO_LV2_USE_EVENTS_IN | |||||
LV2_Atom_Sequence* fPortEventsIn; | |||||
#endif | |||||
#if DISTRHO_LV2_USE_EVENTS_OUT | |||||
LV2_Atom_Sequence* fPortEventsOut; | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_LATENCY | |||||
floatptr fPortLatency; | |||||
#endif | |||||
// Temporary data | |||||
float* fLastControlValues; | |||||
// #if DISTRHO_PLUGIN_IS_SYNTH | |||||
// MidiEvent fMidiEvents[MAX_MIDI_EVENTS]; | |||||
// #endif | |||||
// Feature data | |||||
const LV2_URID_Map* const fUridMap; | |||||
const LV2_Worker_Schedule* const fWorker; | |||||
// xxx | |||||
// #if DISTRHO_LV2_USE_EVENTS | |||||
// | |||||
// // URIDs | |||||
// LV2_URID_Map* uridMap; | |||||
// LV2_URID uridIdAtomString; | |||||
// # if DISTRHO_PLUGIN_IS_SYNTH | |||||
// LV2_URID uridIdMidiEvent; | |||||
// # endif | |||||
// # if DISTRHO_PLUGIN_WANT_STATE | |||||
// LV2_URID uridIdPatchMessage; | |||||
// LV2_Worker_Schedule* workerSchedule; | |||||
// # endif | |||||
// #endif | |||||
// #if DISTRHO_PLUGIN_WANT_STATE | |||||
// stringMap stateMap; | |||||
// | |||||
// void setState(const char* newKey, const char* newValue) | |||||
// { | |||||
// plugin.setState(newKey, newValue); | |||||
// | |||||
// // check if key already exists | |||||
// for (auto i = stateMap.begin(); i != stateMap.end(); i++) | |||||
// { | |||||
// const d_string& key = i->first; | |||||
// | |||||
// if (key == newKey) | |||||
// { | |||||
// i->second = newValue; | |||||
// return; | |||||
// } | |||||
// } | |||||
// | |||||
// // add a new one then | |||||
// stateMap[newKey] = newValue; | |||||
// } | |||||
// #endif | |||||
void updateParameterOutputs() | |||||
{ | |||||
for (uint32_t i=0, count=fPlugin.parameterCount(); i < count; ++i) | |||||
{ | |||||
if (fPlugin.parameterIsOutput(i)) | |||||
{ | |||||
fLastControlValues[i] = fPlugin.parameterValue(i); | |||||
if (fPortControls[i] != nullptr) | |||||
*fPortControls[i] = fLastControlValues[i]; | |||||
} | |||||
} | |||||
#if DISTRHO_PLUGIN_WANT_LATENCY | |||||
if (fPortLatency != nullptr) | |||||
*fPortLatency = fPlugin.latency(); | |||||
#endif | |||||
} | |||||
}; | |||||
// ------------------------------------------------- | |||||
static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, const char*, const LV2_Feature* const* features) | |||||
{ | |||||
const LV2_Options_Option* options = nullptr; | |||||
const LV2_URID_Map* uridMap = nullptr; | |||||
const LV2_Worker_Schedule* worker = nullptr; | |||||
for (int i=0; features[i] != nullptr; ++i) | |||||
{ | |||||
if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0) | |||||
options = (const LV2_Options_Option*)features[i]->data; | |||||
else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0) | |||||
uridMap = (const LV2_URID_Map*)features[i]->data; | |||||
else if (std::strcmp(features[i]->URI, LV2_WORKER__schedule) == 0) | |||||
worker = (const LV2_Worker_Schedule*)features[i]->data; | |||||
} | |||||
if (uridMap == nullptr) | |||||
{ | |||||
d_stderr("URID Map feature missing, cannot continue!"); | |||||
return nullptr; | |||||
} | |||||
for (int i=0; options[i].key != 0; ++i) | |||||
{ | |||||
if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength)) | |||||
{ | |||||
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int)) | |||||
d_lastBufferSize = *(const int*)options[i].value; | |||||
else | |||||
d_stderr("Host provides maxBlockLength but has wrong value type"); | |||||
break; | |||||
} | |||||
} | |||||
if (d_lastBufferSize == 0) | |||||
d_lastBufferSize = 512; | |||||
d_lastSampleRate = sampleRate; | |||||
return new PluginLv2(uridMap, worker); | |||||
} | |||||
#define instancePtr ((PluginLv2*)instance) | |||||
static void lv2_connect_port(LV2_Handle instance, uint32_t port, void* dataLocation) | |||||
{ | |||||
instancePtr->lv2_connect_port(port, dataLocation); | |||||
} | |||||
static void lv2_activate(LV2_Handle instance) | |||||
{ | |||||
instancePtr->lv2_activate(); | |||||
} | |||||
static void lv2_run(LV2_Handle instance, uint32_t sampleCount) | |||||
{ | |||||
instancePtr->lv2_run(sampleCount); | |||||
} | |||||
static void lv2_deactivate(LV2_Handle instance) | |||||
{ | |||||
instancePtr->lv2_deactivate(); | |||||
} | |||||
static void lv2_cleanup(LV2_Handle instance) | |||||
{ | |||||
delete instancePtr; | |||||
} | |||||
static uint32_t lv2_get_options(LV2_Handle instance, LV2_Options_Option* options) | |||||
{ | |||||
return instancePtr->lv2_get_options(options); | |||||
} | |||||
static uint32_t lv2_set_options(LV2_Handle instance, const LV2_Options_Option* options) | |||||
{ | |||||
return instancePtr->lv2_set_options(options); | |||||
} | |||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
static const LV2_Program_Descriptor* lv2_get_program(LV2_Handle instance, uint32_t index) | |||||
{ | |||||
return instancePtr->lv2_get_program(index); | |||||
} | |||||
static void lv2_select_program(LV2_Handle instance, uint32_t bank, uint32_t program) | |||||
{ | |||||
instancePtr->lv2_select_program(bank, program); | |||||
} | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
static LV2_State_Status lv2_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* features) | |||||
{ | |||||
return instancePtr->lv2_save(store, handle, flags, features); | |||||
} | |||||
static LV2_State_Status lv2_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* features) | |||||
{ | |||||
return instancePtr->lv2_restore(retrieve, handle, flags, features); | |||||
} | |||||
LV2_Worker_Status lv2_work(LV2_Handle instance, LV2_Worker_Respond_Function respond, LV2_Worker_Respond_Handle handle, uint32_t size, const void* data) | |||||
{ | |||||
return instancePtr->lv2_work(respond, handle, size, data); | |||||
} | |||||
LV2_Worker_Status lv2_work_response(LV2_Handle instance, uint32_t size, const void* body) | |||||
{ | |||||
return instancePtr->lv2_work_response(size, body); | |||||
} | |||||
#endif | |||||
static const void* lv2_extension_data(const char* uri) | |||||
{ | |||||
static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options }; | |||||
if (std::strcmp(uri, LV2_OPTIONS__interface) == 0) | |||||
return &options; | |||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
static const LV2_Programs_Interface programs = { lv2_get_program, lv2_select_program }; | |||||
if (std::strcmp(uri, LV2_PROGRAMS__Interface) == 0) | |||||
return &programs; | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
static const LV2_State_Interface state = { lv2_save, lv2_restore }; | |||||
static const LV2_Worker_Interface worker = { lv2_work, lv2_work_response, nullptr }; | |||||
if (std::strcmp(uri, LV2_STATE__interface) == 0) | |||||
return &state; | |||||
if (std::strcmp(uri, LV2_WORKER__interface) == 0) | |||||
return &worker; | |||||
#endif | |||||
return nullptr; | |||||
} | |||||
#undef instancePtr | |||||
// ------------------------------------------------- | |||||
static LV2_Descriptor sLv2Descriptor = { | |||||
DISTRHO_PLUGIN_URI, | |||||
lv2_instantiate, | |||||
lv2_connect_port, | |||||
lv2_activate, | |||||
lv2_run, | |||||
lv2_deactivate, | |||||
lv2_cleanup, | |||||
lv2_extension_data | |||||
}; | |||||
END_NAMESPACE_DISTRHO | |||||
// ------------------------------------------------- | |||||
DISTRHO_PLUGIN_EXPORT | |||||
const LV2_Descriptor* lv2_descriptor(uint32_t index) | |||||
{ | |||||
USE_NAMESPACE_DISTRHO | |||||
return (index == 0) ? &sLv2Descriptor : nullptr; | |||||
} |
@@ -0,0 +1,359 @@ | |||||
/* | |||||
* DISTRHO Plugin Toolkit (DPT) | |||||
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com> | |||||
* | |||||
* This program is free software; you can redistribute it and/or | |||||
* modify it under the terms of the GNU Lesser General Public | |||||
* License as published by the Free Software Foundation. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU Lesser General Public License for more details. | |||||
* | |||||
* For a full copy of the license see the LGPL.txt file | |||||
*/ | |||||
#include "DistrhoPluginInternal.hpp" | |||||
#include "lv2/lv2.h" | |||||
#include "lv2/atom.h" | |||||
#include "lv2/buf-size.h" | |||||
// #include "lv2/midi.h" | |||||
#include "lv2/options.h" | |||||
#include "lv2/programs.h" | |||||
// #include "lv2/state.h" | |||||
#include "lv2/time.h" | |||||
// #include "lv2/ui.h" | |||||
#include "lv2/urid.h" | |||||
#include "lv2/units.h" | |||||
// #include "lv2/worker.h" | |||||
#include <fstream> | |||||
#include <iostream> | |||||
#ifndef DISTRHO_PLUGIN_URI | |||||
# error DISTRHO_PLUGIN_URI undefined! | |||||
#endif | |||||
// TODO: UI | |||||
#undef DISTRHO_PLUGIN_HAS_UI | |||||
#undef DISTRHO_PLUGIN_WANT_LATENCY | |||||
#undef DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
#undef DISTRHO_PLUGIN_WANT_STATE | |||||
#undef DISTRHO_PLUGIN_WANT_TIMEPOS | |||||
#define DISTRHO_PLUGIN_WANT_LATENCY 1 | |||||
#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||||
#define DISTRHO_PLUGIN_WANT_STATE 1 | |||||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | |||||
#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_STATE || DISTRHO_PLUGIN_WANT_TIMEPOS) | |||||
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_STATE) | |||||
// ------------------------------------------------- | |||||
DISTRHO_PLUGIN_EXPORT | |||||
void lv2_generate_ttl(const char* const basename) | |||||
{ | |||||
USE_NAMESPACE_DISTRHO | |||||
// Dummy plugin to get data from | |||||
d_lastBufferSize = 512; | |||||
d_lastSampleRate = 44100.0; | |||||
PluginInternal plugin; | |||||
d_lastBufferSize = 0; | |||||
d_lastSampleRate = 0.0; | |||||
d_string pluginLabel(basename); | |||||
d_string pluginTTL(pluginLabel + ".ttl"); | |||||
// --------------------------------------------- | |||||
{ | |||||
std::cout << "Writing manifest.ttl..."; std::cout.flush(); | |||||
std::fstream manifestFile("manifest.ttl", std::ios::out); | |||||
d_string manifestString; | |||||
manifestString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n"; | |||||
manifestString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n"; | |||||
#if DISTRHO_PLUGIN_HAS_UI | |||||
manifestString += "@prefix ui: <" LV2_UI_PREFIX "> .\n"; | |||||
#endif | |||||
manifestString += "\n"; | |||||
manifestString += "<" DISTRHO_PLUGIN_URI ">\n"; | |||||
manifestString += " a lv2:Plugin ;\n"; | |||||
manifestString += " lv2:binary <" + pluginLabel + "." DISTRHO_DLL_EXTENSION "> ;\n"; | |||||
manifestString += " rdfs:seeAlso <" + pluginTTL + "> .\n"; | |||||
manifestString += "\n"; | |||||
#if DISTRHO_PLUGIN_HAS_UI | |||||
manifestString += "<" DISTRHO_UI_URI ">\n"; | |||||
# if DISTRHO_OS_HAIKU | |||||
manifestString += " a ui:BeUI ;\n"; | |||||
# elif DISTRHO_OS_MACOS | |||||
manifestString += " a ui:CocoaUI ;\n"; | |||||
# elif DISTRHO_OS_WINDOWS | |||||
manifestString += " a ui:WindowsUI ;\n"; | |||||
# else | |||||
manifestString += " a ui:X11UI ;\n"; | |||||
# endif | |||||
manifestString += " ui:binary <" + pluginLabel + "_ui." DISTRHO_DLL_EXTENSION "> .\n"; | |||||
// # if DISTRHO_LV2_USE_EVENTS | |||||
// manifestString += " lv2:optionalFeature <" LV2_URID__map "> ,\n"; | |||||
// manifestString += " ui:noUserResize .\n"; | |||||
// # else | |||||
// manifestString += " lv2:optionalFeature ui:noUserResize .\n"; | |||||
// # endif | |||||
manifestString += "\n"; | |||||
#endif | |||||
manifestFile << manifestString << std::endl; | |||||
manifestFile.close(); | |||||
std::cout << " done!" << std::endl; | |||||
} | |||||
// --------------------------------------------- | |||||
{ | |||||
std::cout << "Writing " << pluginTTL << "..."; std::cout.flush(); | |||||
std::fstream pluginFile(pluginTTL, std::ios::out); | |||||
d_string pluginString; | |||||
#if DISTRHO_LV2_USE_EVENTS_IN | |||||
pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n"; | |||||
#endif | |||||
pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n"; | |||||
pluginString += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n"; | |||||
pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n"; | |||||
#if DISTRHO_PLUGIN_HAS_UI | |||||
pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n"; | |||||
#endif | |||||
pluginString += "@prefix unit: <" LV2_UNITS_PREFIX "> .\n"; | |||||
pluginString += "\n"; | |||||
pluginString += "<" DISTRHO_PLUGIN_URI ">\n"; | |||||
#if DISTRHO_PLUGIN_IS_SYNTH | |||||
pluginString += " a lv2:InstrumentPlugin, lv2:Plugin ;\n"; | |||||
#else | |||||
pluginString += " a lv2:Plugin ;\n"; | |||||
#endif | |||||
pluginString += "\n"; | |||||
#if (DISTRHO_PLUGIN_WANT_STATE || DISTRHO_PLUGIN_WANT_PROGRAMS) | |||||
pluginString += " lv2:extensionData <" LV2_OPTIONS__interface "> ,\n"; | |||||
# if DISTRHO_PLUGIN_WANT_STATE | |||||
pluginString += " <" LV2_STATE__interface "> ,\n"; | |||||
pluginString += " <" LV2_WORKER__interface "> \n"; | |||||
# if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
pluginString += ",\n"; | |||||
# else | |||||
pluginString += ";\n"; | |||||
# endif | |||||
# endif | |||||
# if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
pluginString += " <" LV2_PROGRAMS__Interface "> ;\n"; | |||||
# endif | |||||
#endif | |||||
pluginString += "\n"; | |||||
#if DISTRHO_PLUGIN_WANT_STATE | |||||
pluginString += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ,\n"; | |||||
pluginString += " <" LV2_WORKER__schedule "> ;\n"; | |||||
#else | |||||
pluginString += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ;\n"; | |||||
#endif | |||||
pluginString += "\n"; | |||||
pluginString += " lv2:requiredFeature <" LV2_BUF_SIZE__boundedBlockLength "> ,\n"; | |||||
pluginString += " <" LV2_URID__map "> ;\n"; | |||||
pluginString += "\n"; | |||||
#if DISTRHO_PLUGIN_HAS_UI | |||||
pluginString += " ui:ui <" DISTRHO_UI_URI "> ;\n"; | |||||
pluginString += "\n"; | |||||
#endif | |||||
{ | |||||
uint32_t portIndex = 0; | |||||
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | |||||
{ | |||||
if (i == 0) | |||||
pluginString += " lv2:port [\n"; | |||||
else | |||||
pluginString += " [\n"; | |||||
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"; | |||||
if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS) | |||||
pluginString += " ] ;\n\n"; | |||||
else | |||||
pluginString += " ] ,\n"; | |||||
} | |||||
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |||||
{ | |||||
if (i == 0) | |||||
pluginString += " lv2:port [\n"; | |||||
else | |||||
pluginString += " [\n"; | |||||
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"; | |||||
if (i+1 == DISTRHO_PLUGIN_NUM_OUTPUTS) | |||||
pluginString += " ] ;\n\n"; | |||||
else | |||||
pluginString += " ] ,\n"; | |||||
} | |||||
#if DISTRHO_LV2_USE_EVENTS_IN | |||||
pluginString += " lv2:port [\n"; | |||||
pluginString += " a lv2:InputPort, atom:AtomPort ;\n"; | |||||
pluginString += " lv2:index " + d_string(portIndex++) + " ;\n"; | |||||
pluginString += " lv2:name \"Events Input\" ;\n"; | |||||
pluginString += " lv2:symbol \"lv2_events_in\" ;\n"; | |||||
pluginString += " atom:bufferType atom:Sequence ;\n"; | |||||
# if (DISTRHO_PLUGIN_IS_SYNTH && DISTRHO_PLUGIN_WANT_TIMEPOS) // TODO | |||||
pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ,\n"; | |||||
pluginString += " <" LV2_TIME__Position "> ;\n"; | |||||
# elif DISTRHO_PLUGIN_IS_SYNTH | |||||
pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n"; | |||||
# else | |||||
pluginString += " atom:supports <" LV2_TIME__Position "> ;\n"; | |||||
# endif | |||||
pluginString += " ] ;\n"; | |||||
#endif | |||||
#if DISTRHO_LV2_USE_EVENTS_OUT | |||||
pluginString += " lv2:port [\n"; | |||||
pluginString += " a lv2:OutputPort, atom:AtomPort ;\n"; | |||||
pluginString += " lv2:index " + d_string(portIndex++) + " ;\n"; | |||||
pluginString += " lv2:name \"Events Output\" ;\n"; | |||||
pluginString += " lv2:symbol \"lv2_events_out\" ;\n"; | |||||
pluginString += " atom:bufferType atom:Sequence ;\n"; | |||||
pluginString += " atom:supports <something_here> ;\n"; // TODO | |||||
pluginString += " ] ;\n"; | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_LATENCY | |||||
pluginString += " lv2:port [\n"; | |||||
pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n"; | |||||
pluginString += " lv2:index " + d_string(portIndex++) + " ;\n"; | |||||
pluginString += " lv2:name \"Latency\" ;\n"; | |||||
pluginString += " lv2:symbol \"lv2_latency\" ;\n"; | |||||
pluginString += " lv2:designation lv2:latency ;\n"; | |||||
pluginString += " ] ;\n"; | |||||
#endif | |||||
for (uint32_t i=0; i < plugin.parameterCount(); ++i) | |||||
{ | |||||
if (i == 0) | |||||
pluginString += " lv2:port [\n"; | |||||
else | |||||
pluginString += " [\n"; | |||||
if (plugin.parameterIsOutput(i)) | |||||
pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n"; | |||||
else | |||||
pluginString += " a lv2:InputPort, lv2:ControlPort ;\n"; | |||||
pluginString += " lv2:index " + d_string(portIndex++) + " ;\n"; | |||||
pluginString += " lv2:name \"" + plugin.parameterName(i) + "\" ;\n"; | |||||
// symbol | |||||
{ | |||||
d_string symbol(plugin.parameterSymbol(i)); | |||||
if (symbol.isEmpty()) | |||||
symbol = "lv2_port_" + d_string(portIndex-1); | |||||
pluginString += " lv2:symbol \"" + symbol + "\" ;\n"; | |||||
} | |||||
// ranges | |||||
{ | |||||
const ParameterRanges& ranges(plugin.parameterRanges(i)); | |||||
if (plugin.parameterHints(i) & PARAMETER_IS_INTEGER) | |||||
{ | |||||
pluginString += " lv2:default " + d_string(int(plugin.parameterValue(i))) + " ;\n"; | |||||
pluginString += " lv2:minimum " + d_string(int(ranges.min)) + " ;\n"; | |||||
pluginString += " lv2:maximum " + d_string(int(ranges.max)) + " ;\n"; | |||||
} | |||||
else | |||||
{ | |||||
pluginString += " lv2:default " + d_string(plugin.parameterValue(i)) + " ;\n"; | |||||
pluginString += " lv2:minimum " + d_string(ranges.min) + " ;\n"; | |||||
pluginString += " lv2:maximum " + d_string(ranges.max) + " ;\n"; | |||||
} | |||||
} | |||||
// unit | |||||
{ | |||||
const d_string& unit(plugin.parameterUnit(i)); | |||||
if (! unit.isEmpty()) | |||||
{ | |||||
if (unit == "db" || unit == "dB") | |||||
{ | |||||
pluginString += " unit:unit unit:db ;\n"; | |||||
} | |||||
else if (unit == "hz" || unit == "Hz") | |||||
{ | |||||
pluginString += " unit:unit unit:hz ;\n"; | |||||
} | |||||
else if (unit == "khz" || unit == "kHz") | |||||
{ | |||||
pluginString += " unit:unit unit:khz ;\n"; | |||||
} | |||||
else if (unit == "mhz" || unit == "mHz") | |||||
{ | |||||
pluginString += " unit:unit unit:mhz ;\n"; | |||||
} | |||||
else | |||||
{ | |||||
pluginString += " unit:unit [\n"; | |||||
pluginString += " a unit:Unit ;\n"; | |||||
pluginString += " unit:name \"" + unit + "\" ;\n"; | |||||
pluginString += " unit:symbol \"" + unit + "\" ;\n"; | |||||
pluginString += " unit:render \"%f f\" ;\n"; | |||||
pluginString += " ] ;\n"; | |||||
} | |||||
} | |||||
} | |||||
// hints | |||||
{ | |||||
const uint32_t hints(plugin.parameterHints(i)); | |||||
if (hints & PARAMETER_IS_BOOLEAN) | |||||
pluginString += " lv2:portProperty lv2:toggled ;\n"; | |||||
if (hints & PARAMETER_IS_INTEGER) | |||||
pluginString += " lv2:portProperty lv2:integer ;\n"; | |||||
if (hints & PARAMETER_IS_LOGARITHMIC) | |||||
pluginString += " lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ;\n"; | |||||
} | |||||
if (i+1 == plugin.parameterCount()) | |||||
pluginString += " ] ;\n\n"; | |||||
else | |||||
pluginString += " ] ,\n"; | |||||
} | |||||
} | |||||
pluginString += " doap:name \"" + d_string(plugin.name()) + "\" ;\n"; | |||||
pluginString += " doap:maintainer [ foaf:name \"" + d_string(plugin.maker()) + "\" ] .\n"; | |||||
pluginFile << pluginString << std::endl; | |||||
pluginFile.close(); | |||||
std::cout << " done!" << std::endl; | |||||
} | |||||
} |
@@ -18,7 +18,7 @@ | |||||
#if DISTRHO_PLUGIN_HAS_UI | #if DISTRHO_PLUGIN_HAS_UI | ||||
# include "DistrhoUIInternal.hpp" | # include "DistrhoUIInternal.hpp" | ||||
# ifdef DISTRHO_UI_QT4 | |||||
# ifdef DISTRHO_UI_QT | |||||
# include <QtGui/QApplication> | # include <QtGui/QApplication> | ||||
# endif | # endif | ||||
#endif | #endif | ||||
@@ -33,7 +33,7 @@ | |||||
//# include "vestige/aeffectx.h" | //# include "vestige/aeffectx.h" | ||||
//# define effSetProgramName 4 | //# define effSetProgramName 4 | ||||
//#else | //#else | ||||
#include "vst/aeffectx.h" | |||||
#include "aeffectx.h" | |||||
//#endif | //#endif | ||||
START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
@@ -42,7 +42,7 @@ START_NAMESPACE_DISTRHO | |||||
#if DISTRHO_PLUGIN_HAS_UI | #if DISTRHO_PLUGIN_HAS_UI | ||||
# ifdef DISTRHO_UI_QT4 | |||||
# ifdef DISTRHO_UI_QT | |||||
class QStaticScopedAppInit | class QStaticScopedAppInit | ||||
{ | { | ||||
public: | public: | ||||
@@ -57,14 +57,14 @@ public: | |||||
fInitiated = true; | fInitiated = true; | ||||
if (qApp != nullptr) | |||||
if (QApplication* app = qApp) | |||||
{ | { | ||||
fApp = qApp; | |||||
fApp = app; | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
static int qargc = 0; | |||||
static char** qargv = nullptr; | |||||
static int qargc = 0; | |||||
static char* qargv[] = { nullptr }; | |||||
fApp = new QApplication(qargc, qargv, true); | fApp = new QApplication(qargc, qargv, true); | ||||
fApp->setQuitOnLastWindowClosed(false); | fApp->setQuitOnLastWindowClosed(false); | ||||
} | } | ||||
@@ -95,7 +95,7 @@ public: | |||||
fParameterChecks(nullptr), | fParameterChecks(nullptr), | ||||
fParameterValues(nullptr) | fParameterValues(nullptr) | ||||
{ | { | ||||
uint32_t paramCount = plugin->parameterCount(); | |||||
const uint32_t paramCount(plugin->parameterCount()); | |||||
if (paramCount > 0) | if (paramCount > 0) | ||||
{ | { | ||||
@@ -121,10 +121,16 @@ public: | |||||
~UIVst() | ~UIVst() | ||||
{ | { | ||||
if (fParameterChecks != nullptr) | if (fParameterChecks != nullptr) | ||||
{ | |||||
delete[] fParameterChecks; | delete[] fParameterChecks; | ||||
fParameterChecks = nullptr; | |||||
} | |||||
if (fParameterValues != nullptr) | if (fParameterValues != nullptr) | ||||
{ | |||||
delete[] fParameterValues; | delete[] fParameterValues; | ||||
fParameterValues = nullptr; | |||||
} | |||||
} | } | ||||
// --------------------------------------------- | // --------------------------------------------- | ||||
@@ -156,18 +162,18 @@ public: | |||||
fUi.idle(); | fUi.idle(); | ||||
} | } | ||||
int16_t getWidth() | |||||
int16_t getWidth() const | |||||
{ | { | ||||
return fUi.width(); | return fUi.width(); | ||||
} | } | ||||
int16_t getHeight() | |||||
int16_t getHeight() const | |||||
{ | { | ||||
return fUi.height(); | return fUi.height(); | ||||
} | } | ||||
// --------------------------------------------- | // --------------------------------------------- | ||||
// functions called from the plugin side, no block | |||||
// functions called from the plugin side, RT no block | |||||
void setParameterValueFromPlugin(uint32_t index, float perValue) | void setParameterValueFromPlugin(uint32_t index, float perValue) | ||||
{ | { | ||||
@@ -204,8 +210,8 @@ protected: | |||||
void setParameterValue(uint32_t index, float realValue) | void setParameterValue(uint32_t index, float realValue) | ||||
{ | { | ||||
const ParameterRanges& ranges = kPlugin->parameterRanges(index); | |||||
float perValue = ranges.normalizeValue(realValue); | |||||
const ParameterRanges& ranges(kPlugin->parameterRanges(index)); | |||||
const float perValue(ranges.normalizeValue(realValue)); | |||||
kPlugin->setParameterValue(index, realValue); | kPlugin->setParameterValue(index, realValue); | ||||
hostCallback(audioMasterAutomate, index, 0, nullptr, perValue); | hostCallback(audioMasterAutomate, index, 0, nullptr, perValue); | ||||
@@ -355,7 +361,9 @@ public: | |||||
case effGetProgramName: | case effGetProgramName: | ||||
if (ptr != nullptr && fCurProgram >= 0 && fCurProgram < static_cast<int32_t>(fPlugin.programCount())) | if (ptr != nullptr && fCurProgram >= 0 && fCurProgram < static_cast<int32_t>(fPlugin.programCount())) | ||||
{ | { | ||||
std::strncpy((char*)ptr, fPlugin.programName(fCurProgram), kVstMaxProgNameLen); | |||||
char* buf = (char*)ptr; | |||||
std::strncpy(buf, fPlugin.programName(fCurProgram), kVstMaxProgNameLen); | |||||
buf[kVstMaxProgNameLen] = '\0'; | |||||
ret = 1; | ret = 1; | ||||
} | } | ||||
break; | break; | ||||
@@ -364,7 +372,9 @@ public: | |||||
case effGetParamDisplay: | case effGetParamDisplay: | ||||
if (ptr != nullptr && index < static_cast<int32_t>(fPlugin.parameterCount())) | if (ptr != nullptr && index < static_cast<int32_t>(fPlugin.parameterCount())) | ||||
{ | { | ||||
snprintf((char*)ptr, kVstMaxParamStrLen, "%f", fPlugin.parameterValue(index)); | |||||
char* buf = (char*)ptr; | |||||
std::snprintf((char*)ptr, kVstMaxParamStrLen, "%f", fPlugin.parameterValue(index)); | |||||
buf[kVstMaxParamStrLen] = '\0'; | |||||
ret = 1; | ret = 1; | ||||
} | } | ||||
break; | break; | ||||
@@ -392,7 +402,7 @@ public: | |||||
break; | break; | ||||
case effEditOpen: | case effEditOpen: | ||||
createUiIfNeeded((intptr_t)ptr); | |||||
createUiIfNeeded((intptr_t)ptr); // FIXME - use FromVstPtr<> | |||||
ret = 1; | ret = 1; | ||||
break; | break; | ||||
@@ -461,14 +471,14 @@ public: | |||||
float vst_getParameter(int32_t index) | float vst_getParameter(int32_t index) | ||||
{ | { | ||||
const ParameterRanges& ranges = fPlugin.parameterRanges(index); | |||||
const ParameterRanges& ranges(fPlugin.parameterRanges(index)); | |||||
return ranges.normalizeValue(fPlugin.parameterValue(index)); | return ranges.normalizeValue(fPlugin.parameterValue(index)); | ||||
} | } | ||||
void vst_setParameter(int32_t index, float value) | void vst_setParameter(int32_t index, float value) | ||||
{ | { | ||||
const ParameterRanges& ranges = fPlugin.parameterRanges(index); | |||||
float realValue = ranges.unnormalizeValue(value); | |||||
const ParameterRanges& ranges(fPlugin.parameterRanges(index)); | |||||
const float realValue(ranges.unnormalizeValue(value)); | |||||
fPlugin.setParameterValue(index, realValue); | fPlugin.setParameterValue(index, realValue); | ||||
#if DISTRHO_PLUGIN_HAS_UI | #if DISTRHO_PLUGIN_HAS_UI | ||||
@@ -585,9 +595,6 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t | |||||
d_lastBufferSize = audioMaster(effect, audioMasterGetBlockSize, 0, 0, nullptr, 0.0f); | d_lastBufferSize = audioMaster(effect, audioMasterGetBlockSize, 0, 0, nullptr, 0.0f); | ||||
d_lastSampleRate = audioMaster(effect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f); | d_lastSampleRate = audioMaster(effect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f); | ||||
effect->object = new PluginVst(audioMaster, effect); | effect->object = new PluginVst(audioMaster, effect); | ||||
#ifdef DISTRHO_UI_QT4 | |||||
QStaticScopedAppInit::addOne(); | |||||
#endif | |||||
return 1; | return 1; | ||||
} | } | ||||
return 0; | return 0; | ||||
@@ -598,14 +605,11 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t | |||||
delete (PluginVst*)effect->object; | delete (PluginVst*)effect->object; | ||||
effect->object = nullptr; | effect->object = nullptr; | ||||
delete effect; | delete effect; | ||||
#ifdef DISTRHO_UI_QT4 | |||||
QStaticScopedAppInit::removeOne(); | |||||
#endif | |||||
return 1; | return 1; | ||||
} | } | ||||
return 0; | return 0; | ||||
case effGetParamLabel: | |||||
case effGetParamLabel: // FIXME - proper close buf/ptr | |||||
if (ptr != nullptr && index < static_cast<int32_t>(plugin.parameterCount())) | if (ptr != nullptr && index < static_cast<int32_t>(plugin.parameterCount())) | ||||
{ | { | ||||
std::strncpy((char*)ptr, plugin.parameterUnit(index), kVstMaxParamStrLen); | std::strncpy((char*)ptr, plugin.parameterUnit(index), kVstMaxParamStrLen); | ||||
@@ -165,7 +165,6 @@ public: | |||||
{ | { | ||||
fOscData.idle(); | fOscData.idle(); | ||||
fUI.idle(); | fUI.idle(); | ||||
glApp.idle(); | |||||
dgl_msleep(50); | dgl_msleep(50); | ||||
} | } | ||||
#endif | #endif | ||||
@@ -218,15 +218,14 @@ public: | |||||
void idle() | void idle() | ||||
{ | { | ||||
#if defined(DISTRHO_UI_EXTERNAL) | |||||
// needed? | |||||
#elif defined(DISTRHO_UI_OPENGL) | |||||
glApp.idle(); | |||||
#endif | |||||
assert(kUi != nullptr); | assert(kUi != nullptr); | ||||
if (kUi != nullptr) | if (kUi != nullptr) | ||||
kUi->d_uiIdle(); | kUi->d_uiIdle(); | ||||
#ifdef DISTRHO_UI_OPENGL | |||||
glApp.idle(); | |||||
#endif | |||||
} | } | ||||
#if defined(DISTRHO_UI_EXTERNAL) | #if defined(DISTRHO_UI_EXTERNAL) | ||||