| @@ -0,0 +1,752 @@ | |||||
| /* | |||||
| * 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" | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| # include "DistrhoUIInternal.hpp" | |||||
| # ifdef DISTRHO_UI_QT4 | |||||
| # include <QtGui/QApplication> | |||||
| # endif | |||||
| #endif | |||||
| #ifndef __cdecl | |||||
| # define __cdecl | |||||
| #endif | |||||
| #define VST_FORCE_DEPRECATED 0 | |||||
| #include <pluginterfaces/vst2.x/aeffectx.h> | |||||
| START_NAMESPACE_DISTRHO | |||||
| // ------------------------------------------------- | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| # ifdef DISTRHO_UI_QT4 | |||||
| static int qargc = 0; | |||||
| static char** qargv = nullptr; | |||||
| class QStaticScopedAppInit | |||||
| { | |||||
| public: | |||||
| QStaticScopedAppInit() | |||||
| { | |||||
| } | |||||
| static void idle() | |||||
| { | |||||
| if (sApp != nullptr) | |||||
| sApp->processEvents(); | |||||
| } | |||||
| static void addOne() | |||||
| { | |||||
| if (sCount++ != 0) | |||||
| return; | |||||
| sApp = qApp ? qApp : new QApplication(qargc, qargv, true); | |||||
| sApp->setQuitOnLastWindowClosed(false); | |||||
| } | |||||
| static void removeOne() | |||||
| { | |||||
| if (sCount-- != 1) | |||||
| return; | |||||
| assert(sApp != nullptr); | |||||
| sApp->processEvents(); | |||||
| //sApp->quit(); | |||||
| //sApp->processEvents(); | |||||
| //delete sApp; | |||||
| //sApp = nullptr; | |||||
| } | |||||
| private: | |||||
| static QApplication* sApp; | |||||
| static uint32_t sCount; | |||||
| }; | |||||
| QApplication* QStaticScopedAppInit::sApp = nullptr; | |||||
| uint32_t QStaticScopedAppInit::sCount = 0; | |||||
| # endif | |||||
| class UIVst | |||||
| { | |||||
| public: | |||||
| UIVst(audioMasterCallback audioMaster, AEffect* effect, PluginInternal* plugin, intptr_t winId) | |||||
| : kAudioMaster(audioMaster), | |||||
| kEffect(effect), | |||||
| kPlugin(plugin), | |||||
| fUi(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback), | |||||
| fParameterChecks(nullptr), | |||||
| fParameterValues(nullptr) | |||||
| { | |||||
| uint32_t paramCount = plugin->parameterCount(); | |||||
| if (paramCount > 0) | |||||
| { | |||||
| fParameterChecks = new bool[paramCount]; | |||||
| fParameterValues = new float[paramCount]; | |||||
| for (uint32_t i=0; i < paramCount; i++) | |||||
| { | |||||
| fParameterChecks[i] = false; | |||||
| fParameterValues[i] = 0.0f; | |||||
| } | |||||
| } | |||||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| fNextProgram = -1; | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| fMidiEventCount = 0; | |||||
| #endif | |||||
| } | |||||
| ~UIVst() | |||||
| { | |||||
| if (fParameterChecks != nullptr) | |||||
| delete[] fParameterChecks; | |||||
| if (fParameterValues != nullptr) | |||||
| delete[] fParameterValues; | |||||
| } | |||||
| // --------------------------------------------- | |||||
| void idle() | |||||
| { | |||||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| if (fNextProgram != -1) | |||||
| { | |||||
| fUi.programChanged(fNextProgram); | |||||
| fNextProgram = -1; | |||||
| } | |||||
| #endif | |||||
| for (uint32_t i=0, count = kPlugin->parameterCount(); i < count; i++) | |||||
| { | |||||
| if (fParameterChecks[i]) | |||||
| { | |||||
| fParameterChecks[i] = false; | |||||
| fUi.parameterChanged(i, fParameterValues[i]); | |||||
| } | |||||
| } | |||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| // TODO - notes | |||||
| #endif | |||||
| fUi.idle(); | |||||
| } | |||||
| int16_t getWidth() | |||||
| { | |||||
| return fUi.width(); | |||||
| } | |||||
| int16_t getHeight() | |||||
| { | |||||
| return fUi.height(); | |||||
| } | |||||
| // --------------------------------------------- | |||||
| // functions called from the plugin side, no block | |||||
| void setParameterValueFromPlugin(uint32_t index, float perValue) | |||||
| { | |||||
| fParameterChecks[index] = true; | |||||
| fParameterValues[index] = perValue; | |||||
| } | |||||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| void setProgramFromPlugin(uint32_t index) | |||||
| { | |||||
| fNextProgram = index; | |||||
| // set previous parameters invalid | |||||
| for (uint32_t i=0, count = kPlugin->parameterCount(); i < count; i++) | |||||
| fParameterChecks[i] = false; | |||||
| } | |||||
| #endif | |||||
| // --------------------------------------------- | |||||
| protected: | |||||
| intptr_t hostCallback(int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) | |||||
| { | |||||
| return kAudioMaster(kEffect, opcode, index, value, ptr, opt); | |||||
| } | |||||
| void editParameter(uint32_t index, bool started) | |||||
| { | |||||
| if (started) | |||||
| hostCallback(audioMasterBeginEdit, index, 0, nullptr, 0.0f); | |||||
| else | |||||
| hostCallback(audioMasterEndEdit, index, 0, nullptr, 0.0f); | |||||
| } | |||||
| void setParameterValue(uint32_t index, float realValue) | |||||
| { | |||||
| const ParameterRanges& ranges = kPlugin->parameterRanges(index); | |||||
| float perValue = ranges.normalizeValue(realValue); | |||||
| kPlugin->setParameterValue(index, realValue); | |||||
| hostCallback(audioMasterAutomate, index, 0, nullptr, perValue); | |||||
| } | |||||
| void setState(const char* key, const char* value) | |||||
| { | |||||
| #if DISTRHO_PLUGIN_WANT_STATE | |||||
| kPlugin->setState(key, value); | |||||
| #endif | |||||
| } | |||||
| void sendNote(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) | |||||
| { | |||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| // TODO | |||||
| #endif | |||||
| } | |||||
| void uiResize(unsigned int width, unsigned int height) | |||||
| { | |||||
| hostCallback(audioMasterSizeWindow, width, height, nullptr, 0.0f); | |||||
| } | |||||
| private: | |||||
| // Vst stuff | |||||
| audioMasterCallback const kAudioMaster; | |||||
| AEffect* const kEffect; | |||||
| PluginInternal* const kPlugin; | |||||
| // Plugin UI | |||||
| UIInternal fUi; | |||||
| // Temporary data | |||||
| bool* fParameterChecks; | |||||
| float* fParameterValues; | |||||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| int32_t fNextProgram; | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| uint32_t fMidiEventCount; | |||||
| MidiEvent fMidiEvents[MAX_MIDI_EVENTS]; | |||||
| #endif | |||||
| // --------------------------------------------- | |||||
| // Callbacks | |||||
| #define handlePtr ((UIVst*)ptr) | |||||
| static void editParameterCallback(void* ptr, uint32_t index, bool started) | |||||
| { | |||||
| handlePtr->editParameter(index, started); | |||||
| } | |||||
| static void setParameterCallback(void* ptr, uint32_t rindex, float value) | |||||
| { | |||||
| handlePtr->setParameterValue(rindex, value); | |||||
| } | |||||
| static void setStateCallback(void* ptr, const char* key, const char* value) | |||||
| { | |||||
| handlePtr->setState(key, value); | |||||
| } | |||||
| static void sendNoteCallback(void* ptr, bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) | |||||
| { | |||||
| handlePtr->sendNote(onOff, channel, note, velocity); | |||||
| } | |||||
| static void uiResizeCallback(void* ptr, unsigned int width, unsigned int height) | |||||
| { | |||||
| handlePtr->uiResize(width, height); | |||||
| } | |||||
| #undef handlePtr | |||||
| }; | |||||
| #endif | |||||
| // ------------------------------------------------- | |||||
| class PluginVst | |||||
| { | |||||
| public: | |||||
| PluginVst(audioMasterCallback audioMaster, AEffect* effect) | |||||
| : kAudioMaster(audioMaster), | |||||
| kEffect(effect) | |||||
| { | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| fVstUi = nullptr; | |||||
| fVstRect.top = 0; | |||||
| fVstRect.left = 0; | |||||
| fVstRect.bottom = 0; | |||||
| fVstRect.right = 0; | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| fCurProgram = -1; | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| fMidiEventCount = 0; | |||||
| #endif | |||||
| } | |||||
| ~PluginVst() | |||||
| { | |||||
| } | |||||
| intptr_t vst_dispatcher(int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) | |||||
| { | |||||
| int32_t ret = 0; | |||||
| switch (opcode) | |||||
| { | |||||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| case effSetProgram: | |||||
| if (value >= 0 && value < static_cast<intptr_t>(fPlugin.programCount())) | |||||
| { | |||||
| fCurProgram = value; | |||||
| fPlugin.setProgram(fCurProgram); | |||||
| if (fVstUi != nullptr) | |||||
| fVstUi->setProgramFromPlugin(fCurProgram); | |||||
| ret = 1; | |||||
| } | |||||
| break; | |||||
| case effGetProgram: | |||||
| ret = fCurProgram; | |||||
| break; | |||||
| case effSetProgramName: | |||||
| // unsupported | |||||
| break; | |||||
| case effGetProgramName: | |||||
| if (ptr != nullptr && fCurProgram >= 0 && fCurProgram < static_cast<int32_t>(fPlugin.programCount())) | |||||
| { | |||||
| std::strncpy((char*)ptr, fPlugin.programName(fCurProgram), kVstMaxProgNameLen); | |||||
| ret = 1; | |||||
| } | |||||
| break; | |||||
| #endif | |||||
| case effGetParamDisplay: | |||||
| if (ptr != nullptr && index < static_cast<int32_t>(fPlugin.parameterCount())) | |||||
| { | |||||
| snprintf((char*)ptr, kVstMaxParamStrLen, "%f", fPlugin.parameterValue(index)); | |||||
| ret = 1; | |||||
| } | |||||
| break; | |||||
| case effSetSampleRate: | |||||
| fPlugin.setSampleRate(opt, true); | |||||
| break; | |||||
| case effSetBlockSize: | |||||
| fPlugin.setBufferSize(value, true); | |||||
| break; | |||||
| case effMainsChanged: | |||||
| if (value == 0) | |||||
| fPlugin.deactivate(); | |||||
| else | |||||
| fPlugin.activate(); | |||||
| break; | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| case effEditGetRect: | |||||
| createUiIfNeeded(0); | |||||
| *(ERect**)ptr = &fVstRect; | |||||
| ret = 1; | |||||
| break; | |||||
| case effEditOpen: | |||||
| createUiIfNeeded((intptr_t)ptr); | |||||
| ret = 1; | |||||
| break; | |||||
| case effEditClose: | |||||
| if (fVstUi != nullptr) | |||||
| { | |||||
| delete fVstUi; | |||||
| fVstUi = nullptr; | |||||
| # ifdef DISTRHO_UI_QT4 | |||||
| QStaticScopedAppInit::idle(); | |||||
| # endif | |||||
| ret = 1; | |||||
| } | |||||
| break; | |||||
| case effEditIdle: | |||||
| if (fVstUi != nullptr) | |||||
| fVstUi->idle(); | |||||
| # ifdef DISTRHO_UI_QT4 | |||||
| QStaticScopedAppInit::idle(); | |||||
| # endif | |||||
| break; | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_WANT_STATE | |||||
| case effGetChunk: | |||||
| case effSetChunk: | |||||
| // TODO | |||||
| break; | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| case effProcessEvents: | |||||
| if (ptr) | |||||
| { | |||||
| //VstEvents* events = (VstEvents*)ptr; | |||||
| // TODO | |||||
| } | |||||
| break; | |||||
| #endif | |||||
| case effCanBeAutomated: | |||||
| if (index < static_cast<int32_t>(fPlugin.parameterCount())) | |||||
| { | |||||
| uint32_t hints = fPlugin.parameterHints(index); | |||||
| // must be automable, and not output | |||||
| if ((hints & PARAMETER_IS_AUTOMABLE) != 0 && (hints & PARAMETER_IS_OUTPUT) == 0) | |||||
| ret = 1; | |||||
| } | |||||
| break; | |||||
| case effCanDo: | |||||
| // TODO | |||||
| break; | |||||
| case effStartProcess: | |||||
| case effStopProcess: | |||||
| break; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| float vst_getParameter(int32_t 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); | |||||
| fPlugin.setParameterValue(index, realValue); | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| if (fVstUi != nullptr) | |||||
| fVstUi->setParameterValueFromPlugin(index, realValue); | |||||
| #endif | |||||
| } | |||||
| void vst_processReplacing(float** inputs, float** outputs, int32_t sampleFrames) | |||||
| { | |||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| fPlugin.run(inputs, outputs, sampleFrames, fMidiEventCount, fMidiEvents); | |||||
| // TODO - send notes to UI | |||||
| #else | |||||
| fPlugin.run(inputs, outputs, sampleFrames, 0, nullptr); | |||||
| #endif | |||||
| } | |||||
| // --------------------------------------------- | |||||
| private: | |||||
| // VST stuff | |||||
| audioMasterCallback const kAudioMaster; | |||||
| AEffect* const kEffect; | |||||
| // Plugin | |||||
| PluginInternal fPlugin; | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| // UI | |||||
| UIVst* fVstUi; | |||||
| ERect fVstRect; | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| int32_t fCurProgram; | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| uint32_t fMidiEventCount; | |||||
| MidiEvent fMidiEvents[MAX_MIDI_EVENTS]; | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| void createUiIfNeeded(intptr_t ptr) | |||||
| { | |||||
| if (fVstUi != nullptr) | |||||
| return; | |||||
| d_lastUiSampleRate = kAudioMaster(kEffect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f); | |||||
| if (ptr == 0) | |||||
| { | |||||
| // fake temporary window, just to set ui size | |||||
| UIVst tmpUi(kAudioMaster, kEffect, &fPlugin, ptr); | |||||
| fVstRect.right = tmpUi.getWidth(); | |||||
| fVstRect.bottom = tmpUi.getHeight(); | |||||
| } | |||||
| else | |||||
| { | |||||
| // real parented ui | |||||
| fVstUi = new UIVst(kAudioMaster, kEffect, &fPlugin, ptr); | |||||
| fVstRect.right = fVstUi->getWidth(); | |||||
| fVstRect.bottom = fVstUi->getHeight(); | |||||
| # if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| if (fCurProgram >= 0) | |||||
| fVstUi->setProgramFromPlugin(fCurProgram); | |||||
| # endif | |||||
| for (uint32_t i=0, count = fPlugin.parameterCount(); i < count; i++) | |||||
| fVstUi->setParameterValueFromPlugin(i, fPlugin.parameterValue(i)); | |||||
| } | |||||
| } | |||||
| #endif | |||||
| }; | |||||
| // ------------------------------------------------- | |||||
| #define handlePtr ((PluginVst*)effect->object) | |||||
| static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) | |||||
| { | |||||
| // first internal init | |||||
| bool doInternalInit = (opcode == -1 && index == 0xdead && value == 0xf00d); | |||||
| if (doInternalInit) | |||||
| { | |||||
| // set valid but dummy values | |||||
| d_lastBufferSize = 512; | |||||
| d_lastSampleRate = 44100.0; | |||||
| } | |||||
| // Create dummy plugin to get data from | |||||
| static PluginInternal plugin; | |||||
| if (doInternalInit) | |||||
| { | |||||
| // unset | |||||
| d_lastBufferSize = 0; | |||||
| d_lastSampleRate = 0.0; | |||||
| *(PluginInternal**)ptr = &plugin; | |||||
| return 0; | |||||
| } | |||||
| // handle base opcodes | |||||
| switch (opcode) | |||||
| { | |||||
| case effOpen: | |||||
| if (effect != nullptr && effect->object == nullptr) | |||||
| { | |||||
| audioMasterCallback audioMaster = (audioMasterCallback)effect->user; | |||||
| 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; | |||||
| case effClose: | |||||
| if (effect != nullptr && effect->object != nullptr) | |||||
| { | |||||
| delete (PluginVst*)effect->object; | |||||
| effect->object = nullptr; | |||||
| delete effect; | |||||
| #ifdef DISTRHO_UI_QT4 | |||||
| QStaticScopedAppInit::removeOne(); | |||||
| #endif | |||||
| return 1; | |||||
| } | |||||
| return 0; | |||||
| case effGetParamLabel: | |||||
| if (ptr != nullptr && index < static_cast<int32_t>(plugin.parameterCount())) | |||||
| { | |||||
| std::strncpy((char*)ptr, plugin.parameterUnit(index), kVstMaxParamStrLen); | |||||
| return 1; | |||||
| } | |||||
| return 0; | |||||
| case effGetParamName: | |||||
| if (ptr != nullptr && index < static_cast<int32_t>(plugin.parameterCount())) | |||||
| { | |||||
| std::strncpy((char*)ptr, plugin.parameterName(index), kVstMaxParamStrLen); | |||||
| return 1; | |||||
| } | |||||
| return 0; | |||||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| case effGetProgramNameIndexed: | |||||
| if (ptr != nullptr && index < static_cast<int32_t>(plugin.parameterCount())) | |||||
| { | |||||
| std::strncpy((char*)ptr, plugin.programName(index), kVstMaxProgNameLen); | |||||
| return 1; | |||||
| } | |||||
| return 0; | |||||
| #endif | |||||
| case effGetPlugCategory: | |||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| return kPlugCategSynth; | |||||
| #else | |||||
| return kPlugCategUnknown; | |||||
| #endif | |||||
| case effGetEffectName: | |||||
| if (ptr != nullptr) | |||||
| { | |||||
| std::strncpy((char*)ptr, plugin.name(), kVstMaxProductStrLen); | |||||
| return 1; | |||||
| } | |||||
| return 0; | |||||
| case effGetVendorString: | |||||
| if (ptr != nullptr) | |||||
| { | |||||
| std::strncpy((char*)ptr, plugin.maker(), kVstMaxVendorStrLen); | |||||
| return 1; | |||||
| } | |||||
| return 0; | |||||
| case effGetProductString: | |||||
| if (ptr != nullptr) | |||||
| { | |||||
| std::strncpy((char*)ptr, plugin.label(), kVstMaxEffectNameLen); | |||||
| return 1; | |||||
| } | |||||
| return 0; | |||||
| case effGetVendorVersion: | |||||
| return plugin.version(); | |||||
| case effGetVstVersion: | |||||
| return kVstVersion; | |||||
| }; | |||||
| // handle object opcodes | |||||
| if (effect != nullptr && effect->object != nullptr) | |||||
| return handlePtr->vst_dispatcher(opcode, index, value, ptr, opt); | |||||
| return 0; | |||||
| } | |||||
| static float vst_getParameterCallback(AEffect* effect, int32_t index) | |||||
| { | |||||
| if (effect != nullptr && effect->object != nullptr) | |||||
| return handlePtr->vst_getParameter(index); | |||||
| return 0.0f; | |||||
| } | |||||
| static void vst_setParameterCallback(AEffect* effect, int32_t index, float value) | |||||
| { | |||||
| if (effect != nullptr && effect->object != nullptr) | |||||
| handlePtr->vst_setParameter(index, value); | |||||
| } | |||||
| static void vst_processCallback(AEffect* effect, float** inputs, float** outputs, int32_t sampleFrames) | |||||
| { | |||||
| if (effect != nullptr && effect->object != nullptr) | |||||
| handlePtr->vst_processReplacing(inputs, outputs, sampleFrames); | |||||
| } | |||||
| static void vst_processReplacingCallback(AEffect* effect, float** inputs, float** outputs, int32_t sampleFrames) | |||||
| { | |||||
| if (effect != nullptr && effect->object != nullptr) | |||||
| handlePtr->vst_processReplacing(inputs, outputs, sampleFrames); | |||||
| } | |||||
| #undef handlePtr | |||||
| END_NAMESPACE_DISTRHO | |||||
| // ------------------------------------------------- | |||||
| DISTRHO_PLUGIN_EXPORT | |||||
| const AEffect* VSTPluginMain(audioMasterCallback audioMaster) | |||||
| { | |||||
| USE_NAMESPACE_DISTRHO | |||||
| // old version | |||||
| if (audioMaster(nullptr, audioMasterVersion, 0, 0, nullptr, 0.0f) == 0) | |||||
| return nullptr; | |||||
| PluginInternal* plugin = nullptr; | |||||
| vst_dispatcherCallback(nullptr, -1, 0xdead, 0xf00d, &plugin, 0.0f); | |||||
| AEffect* effect = new AEffect; | |||||
| memset(effect, 0, sizeof(AEffect)); | |||||
| // vst fields | |||||
| effect->magic = kEffectMagic; | |||||
| effect->uniqueID = plugin->uniqueId(); | |||||
| effect->version = plugin->version(); | |||||
| // plugin fields | |||||
| effect->numParams = plugin->parameterCount(); | |||||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| effect->numPrograms = plugin->programCount(); | |||||
| #endif | |||||
| effect->numInputs = DISTRHO_PLUGIN_NUM_INPUTS; | |||||
| effect->numOutputs = DISTRHO_PLUGIN_NUM_OUTPUTS; | |||||
| // static calls | |||||
| effect->dispatcher = vst_dispatcherCallback; | |||||
| effect->process = vst_processCallback; | |||||
| effect->getParameter = vst_getParameterCallback; | |||||
| effect->setParameter = vst_setParameterCallback; | |||||
| effect->processReplacing = vst_processReplacingCallback; | |||||
| effect->processDoubleReplacing = nullptr; | |||||
| // plugin flags | |||||
| effect->flags |= effFlagsCanReplacing; | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| effect->flags |= effFlagsHasEditor; | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_WANT_STATE | |||||
| effect->flags |= effFlagsProgramChunks; | |||||
| #endif | |||||
| // pointers | |||||
| effect->object = nullptr; | |||||
| effect->user = (void*)audioMaster; | |||||
| return effect; | |||||
| } | |||||
| // ------------------------------------------------- | |||||