| @@ -28,6 +28,7 @@ | |||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/3BandEQ" | |||
| @@ -28,6 +28,7 @@ | |||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/3BandSplitter" | |||
| @@ -29,6 +29,7 @@ | |||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 0 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/Nekobi" | |||
| @@ -29,6 +29,7 @@ | |||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 0 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 1 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/Notes" | |||
| @@ -28,6 +28,7 @@ | |||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/PingPongPan" | |||
| @@ -28,6 +28,7 @@ | |||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/StereoEnhancer" | |||
| @@ -87,7 +87,7 @@ struct ParameterRanges { | |||
| value = max; | |||
| } | |||
| float fixValue(const float& value) const | |||
| float fixedValue(const float& value) const | |||
| { | |||
| if (value < min) | |||
| return min; | |||
| @@ -96,19 +96,19 @@ struct ParameterRanges { | |||
| 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) | |||
| newValue = 0.0f; | |||
| return 0.0f; | |||
| else if (newValue > 1.0f) | |||
| newValue = 1.0f; | |||
| return 1.0f; | |||
| return newValue; | |||
| } | |||
| float unnormalizeValue(const float& value) const | |||
| float unnormalizedValue(const float& value) const | |||
| { | |||
| return value * (max - min) + min; | |||
| } | |||
| @@ -189,7 +189,9 @@ public: | |||
| uint32_t d_bufferSize() const; | |||
| double d_sampleRate() const; | |||
| #if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
| const TimePos& d_timePos() const; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| void d_setLatency(uint32_t frames); | |||
| #endif | |||
| @@ -22,6 +22,7 @@ | |||
| # include "src/DistrhoPluginLADSPA+DSSI.cpp" | |||
| #elif defined(DISTRHO_PLUGIN_TARGET_LV2) | |||
| # include "src/DistrhoPluginLV2.cpp" | |||
| # include "src/DistrhoPluginLV2export.cpp" | |||
| #elif defined(DISTRHO_PLUGIN_TARGET_VST) | |||
| # include "src/DistrhoPluginVST.cpp" | |||
| #endif | |||
| @@ -51,6 +51,10 @@ | |||
| # error DISTRHO_PLUGIN_WANT_STATE undefined! | |||
| #endif | |||
| #ifndef DISTRHO_PLUGIN_WANT_TIMEPOS | |||
| # error DISTRHO_PLUGIN_WANT_TIMEPOS undefined! | |||
| #endif | |||
| #if DISTRHO_PLUGIN_HAS_UI | |||
| # 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 | |||
| @@ -77,10 +77,12 @@ double Plugin::d_sampleRate() const | |||
| return pData->sampleRate; | |||
| } | |||
| #if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
| const TimePos& Plugin::d_timePos() const | |||
| { | |||
| return pData->timePos; | |||
| } | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| void Plugin::d_setLatency(uint32_t frames) | |||
| @@ -49,7 +49,11 @@ struct Plugin::PrivateData { | |||
| uint32_t latency; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
| TimePos timePos; | |||
| #endif | |||
| char _d; // dummy | |||
| PrivateData() | |||
| : bufferSize(d_lastBufferSize), | |||
| @@ -67,7 +71,7 @@ struct Plugin::PrivateData { | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| latency(0), | |||
| #endif | |||
| timePos() | |||
| _d(0) | |||
| { | |||
| assert(bufferSize != 0); | |||
| assert(sampleRate != 0.0); | |||
| @@ -76,16 +80,25 @@ struct Plugin::PrivateData { | |||
| ~PrivateData() | |||
| { | |||
| if (parameterCount > 0 && parameters != nullptr) | |||
| { | |||
| delete[] parameters; | |||
| parameters = nullptr; | |||
| } | |||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| if (programCount > 0 && programNames != nullptr) | |||
| { | |||
| delete[] programNames; | |||
| programNames = nullptr; | |||
| } | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_STATE | |||
| if (stateCount > 0 && stateKeys != nullptr) | |||
| { | |||
| delete[] stateKeys; | |||
| stateKeys = nullptr; | |||
| } | |||
| #endif | |||
| } | |||
| }; | |||
| @@ -178,48 +191,48 @@ public: | |||
| 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); | |||
| 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); | |||
| } | |||
| const d_string& parameterName(uint32_t index) const | |||
| const d_string& parameterName(const uint32_t index) const | |||
| { | |||
| assert(kData != nullptr && index < kData->parameterCount); | |||
| 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); | |||
| 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); | |||
| 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); | |||
| 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); | |||
| 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); | |||
| @@ -234,13 +247,13 @@ public: | |||
| 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); | |||
| 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); | |||
| @@ -256,13 +269,13 @@ public: | |||
| 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); | |||
| 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); | |||
| @@ -289,7 +302,7 @@ public: | |||
| 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); | |||
| @@ -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); | |||
| @@ -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); | |||
| @@ -28,12 +28,16 @@ | |||
| # endif | |||
| #endif | |||
| typedef LADSPA_Data* LADSPA_DataPtr; | |||
| #if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
| # warning LADSPA/DSSI does not support TimePos | |||
| #endif | |||
| // ------------------------------------------------- | |||
| START_NAMESPACE_DISTRHO | |||
| typedef LADSPA_Data* LADSPA_DataPtr; | |||
| class PluginLadspaDssi | |||
| { | |||
| public: | |||
| @@ -84,9 +88,9 @@ public: | |||
| 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++) | |||
| { | |||
| @@ -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++) | |||
| { | |||
| @@ -112,7 +116,7 @@ public: | |||
| } | |||
| #endif | |||
| for (i=0, count=fPlugin.parameterCount(); i < count; ++i) | |||
| for (unsigned long i=0, count=fPlugin.parameterCount(); i < count; ++i) | |||
| { | |||
| 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 | |||
| uint32_t midiEventCount = 0; | |||
| uint32_t midiEventCount = 0; | |||
| MidiEvent midiEvents[eventCount]; | |||
| for (uint32_t i=0, j; i < eventCount && midiEventCount < MAX_MIDI_EVENTS; ++i) | |||
| { | |||
| @@ -232,71 +236,64 @@ public: | |||
| { | |||
| case SND_SEQ_EVENT_NOTEON: | |||
| 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; | |||
| case SND_SEQ_EVENT_NOTEOFF: | |||
| 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; | |||
| case SND_SEQ_EVENT_KEYPRESS: | |||
| 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; | |||
| case SND_SEQ_EVENT_CONTROLLER: | |||
| 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; | |||
| case SND_SEQ_EVENT_CHANPRESS: | |||
| 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; | |||
| case SND_SEQ_EVENT_PITCHBEND: // TODO | |||
| #if 0 // TODO | |||
| case SND_SEQ_EVENT_PITCHBEND: | |||
| 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; | |||
| #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 | |||
| fPlugin.run(fPortAudioIns, fPortAudioOuts, bufferSize, 0, nullptr); | |||
| #endif | |||
| @@ -316,10 +313,6 @@ private: | |||
| LADSPA_DataPtr fPortLatency; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| MidiEvent fMidiEvents[MAX_MIDI_EVENTS]; | |||
| #endif | |||
| LADSPA_Data* fLastControlValues; | |||
| // --------------------------------------------- | |||
| @@ -480,38 +473,38 @@ public: | |||
| d_lastSampleRate = 0.0; | |||
| // 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(); | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| portCount += 1; | |||
| #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 | |||
| 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' }; | |||
| sprintf(portName, "Audio Input %lu", i+1); | |||
| std::sprintf(portName, "Audio Input %lu", i+1); | |||
| portNames[port] = strdup(portName); | |||
| portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT; | |||
| portRangeHints[port].HintDescriptor = 0; | |||
| portRangeHints[port].HintDescriptor = 0x0; | |||
| portRangeHints[port].LowerBound = 0.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' }; | |||
| sprintf(portName, "Audio Output %lu", i+1); | |||
| std::sprintf(portName, "Audio Output %lu", i+1); | |||
| portNames[port] = strdup(portName); | |||
| portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT; | |||
| portRangeHints[port].HintDescriptor = 0; | |||
| portRangeHints[port].HintDescriptor = 0x0; | |||
| portRangeHints[port].LowerBound = 0.0f; | |||
| portRangeHints[port].UpperBound = 1.0f; | |||
| } | |||
| @@ -526,7 +519,7 @@ public: | |||
| ++port; | |||
| #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)); | |||
| portDescriptors[port] = LADSPA_PORT_CONTROL; | |||
| @@ -538,7 +531,7 @@ public: | |||
| { | |||
| 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].LowerBound = ranges.min; | |||
| @@ -558,9 +551,9 @@ public: | |||
| portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM; | |||
| 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) | |||
| portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_LOW; | |||
| @@ -598,37 +591,59 @@ public: | |||
| ~DescriptorInitializer() | |||
| { | |||
| if (sLadspaDescriptor.Label != nullptr) | |||
| free((void*)sLadspaDescriptor.Label); | |||
| { | |||
| std::free((void*)sLadspaDescriptor.Label); | |||
| sLadspaDescriptor.Label = nullptr; | |||
| } | |||
| if (sLadspaDescriptor.Name != nullptr) | |||
| free((void*)sLadspaDescriptor.Name); | |||
| { | |||
| std::free((void*)sLadspaDescriptor.Name); | |||
| sLadspaDescriptor.Name = nullptr; | |||
| } | |||
| if (sLadspaDescriptor.Maker != nullptr) | |||
| free((void*)sLadspaDescriptor.Maker); | |||
| { | |||
| std::free((void*)sLadspaDescriptor.Maker); | |||
| sLadspaDescriptor.Maker = nullptr; | |||
| } | |||
| if (sLadspaDescriptor.Copyright != nullptr) | |||
| free((void*)sLadspaDescriptor.Copyright); | |||
| { | |||
| std::free((void*)sLadspaDescriptor.Copyright); | |||
| sLadspaDescriptor.Copyright = nullptr; | |||
| } | |||
| if (sLadspaDescriptor.PortDescriptors != nullptr) | |||
| { | |||
| delete[] sLadspaDescriptor.PortDescriptors; | |||
| sLadspaDescriptor.PortDescriptors = nullptr; | |||
| } | |||
| if (sLadspaDescriptor.PortRangeHints != nullptr) | |||
| { | |||
| delete[] sLadspaDescriptor.PortRangeHints; | |||
| sLadspaDescriptor.PortRangeHints = nullptr; | |||
| } | |||
| if (sLadspaDescriptor.PortNames != nullptr) | |||
| { | |||
| for (unsigned long i=0; i < sLadspaDescriptor.PortCount; ++i) | |||
| { | |||
| if (sLadspaDescriptor.PortNames[i] != nullptr) | |||
| free((void*)sLadspaDescriptor.PortNames[i]); | |||
| { | |||
| std::free((void*)sLadspaDescriptor.PortNames[i]); | |||
| sLadspaDescriptor.PortNames[i] = nullptr; | |||
| } | |||
| } | |||
| delete[] sLadspaDescriptor.PortNames; | |||
| sLadspaDescriptor.PortNames = nullptr; | |||
| } | |||
| } | |||
| }; | |||
| static DescriptorInitializer sInit; | |||
| static DescriptorInitializer sDescInit; | |||
| 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 | |||
| # include "DistrhoUIInternal.hpp" | |||
| # ifdef DISTRHO_UI_QT4 | |||
| # ifdef DISTRHO_UI_QT | |||
| # include <QtGui/QApplication> | |||
| # endif | |||
| #endif | |||
| @@ -33,7 +33,7 @@ | |||
| //# include "vestige/aeffectx.h" | |||
| //# define effSetProgramName 4 | |||
| //#else | |||
| #include "vst/aeffectx.h" | |||
| #include "aeffectx.h" | |||
| //#endif | |||
| START_NAMESPACE_DISTRHO | |||
| @@ -42,7 +42,7 @@ START_NAMESPACE_DISTRHO | |||
| #if DISTRHO_PLUGIN_HAS_UI | |||
| # ifdef DISTRHO_UI_QT4 | |||
| # ifdef DISTRHO_UI_QT | |||
| class QStaticScopedAppInit | |||
| { | |||
| public: | |||
| @@ -57,14 +57,14 @@ public: | |||
| fInitiated = true; | |||
| if (qApp != nullptr) | |||
| if (QApplication* app = qApp) | |||
| { | |||
| fApp = qApp; | |||
| fApp = app; | |||
| } | |||
| else | |||
| { | |||
| static int qargc = 0; | |||
| static char** qargv = nullptr; | |||
| static int qargc = 0; | |||
| static char* qargv[] = { nullptr }; | |||
| fApp = new QApplication(qargc, qargv, true); | |||
| fApp->setQuitOnLastWindowClosed(false); | |||
| } | |||
| @@ -95,7 +95,7 @@ public: | |||
| fParameterChecks(nullptr), | |||
| fParameterValues(nullptr) | |||
| { | |||
| uint32_t paramCount = plugin->parameterCount(); | |||
| const uint32_t paramCount(plugin->parameterCount()); | |||
| if (paramCount > 0) | |||
| { | |||
| @@ -121,10 +121,16 @@ public: | |||
| ~UIVst() | |||
| { | |||
| if (fParameterChecks != nullptr) | |||
| { | |||
| delete[] fParameterChecks; | |||
| fParameterChecks = nullptr; | |||
| } | |||
| if (fParameterValues != nullptr) | |||
| { | |||
| delete[] fParameterValues; | |||
| fParameterValues = nullptr; | |||
| } | |||
| } | |||
| // --------------------------------------------- | |||
| @@ -156,18 +162,18 @@ public: | |||
| fUi.idle(); | |||
| } | |||
| int16_t getWidth() | |||
| int16_t getWidth() const | |||
| { | |||
| return fUi.width(); | |||
| } | |||
| int16_t getHeight() | |||
| int16_t getHeight() const | |||
| { | |||
| 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) | |||
| { | |||
| @@ -204,8 +210,8 @@ protected: | |||
| 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); | |||
| hostCallback(audioMasterAutomate, index, 0, nullptr, perValue); | |||
| @@ -355,7 +361,9 @@ public: | |||
| case effGetProgramName: | |||
| 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; | |||
| } | |||
| break; | |||
| @@ -364,7 +372,9 @@ public: | |||
| case effGetParamDisplay: | |||
| 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; | |||
| } | |||
| break; | |||
| @@ -392,7 +402,7 @@ public: | |||
| break; | |||
| case effEditOpen: | |||
| createUiIfNeeded((intptr_t)ptr); | |||
| createUiIfNeeded((intptr_t)ptr); // FIXME - use FromVstPtr<> | |||
| ret = 1; | |||
| break; | |||
| @@ -461,14 +471,14 @@ public: | |||
| float vst_getParameter(int32_t index) | |||
| { | |||
| const ParameterRanges& ranges = fPlugin.parameterRanges(index); | |||
| const ParameterRanges& ranges(fPlugin.parameterRanges(index)); | |||
| return ranges.normalizeValue(fPlugin.parameterValue(index)); | |||
| } | |||
| 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); | |||
| #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_lastSampleRate = audioMaster(effect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f); | |||
| effect->object = new PluginVst(audioMaster, effect); | |||
| #ifdef DISTRHO_UI_QT4 | |||
| QStaticScopedAppInit::addOne(); | |||
| #endif | |||
| return 1; | |||
| } | |||
| return 0; | |||
| @@ -598,14 +605,11 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t | |||
| delete (PluginVst*)effect->object; | |||
| effect->object = nullptr; | |||
| delete effect; | |||
| #ifdef DISTRHO_UI_QT4 | |||
| QStaticScopedAppInit::removeOne(); | |||
| #endif | |||
| return 1; | |||
| } | |||
| return 0; | |||
| case effGetParamLabel: | |||
| case effGetParamLabel: // FIXME - proper close buf/ptr | |||
| if (ptr != nullptr && index < static_cast<int32_t>(plugin.parameterCount())) | |||
| { | |||
| std::strncpy((char*)ptr, plugin.parameterUnit(index), kVstMaxParamStrLen); | |||
| @@ -165,7 +165,6 @@ public: | |||
| { | |||
| fOscData.idle(); | |||
| fUI.idle(); | |||
| glApp.idle(); | |||
| dgl_msleep(50); | |||
| } | |||
| #endif | |||
| @@ -218,15 +218,14 @@ public: | |||
| void idle() | |||
| { | |||
| #if defined(DISTRHO_UI_EXTERNAL) | |||
| // needed? | |||
| #elif defined(DISTRHO_UI_OPENGL) | |||
| glApp.idle(); | |||
| #endif | |||
| assert(kUi != nullptr); | |||
| if (kUi != nullptr) | |||
| kUi->d_uiIdle(); | |||
| #ifdef DISTRHO_UI_OPENGL | |||
| glApp.idle(); | |||
| #endif | |||
| } | |||
| #if defined(DISTRHO_UI_EXTERNAL) | |||