| @@ -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) | ||||