From ef1d02bbc67feab408b8b2877dfa4f1978d1e454 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 12 Mar 2022 01:52:10 +0000 Subject: [PATCH] Finish jucewrapper details, attempt at AU packaging Signed-off-by: falkTX --- .github/workflows/build.yml | 12 +- dpf | 2 +- jucewrapper/CMakeLists.txt | 91 ++++++- jucewrapper/CardinalWrapper.cpp | 468 ++++++++++++++++++++++++++------ src/Makefile.cardinal.mk | 4 +- 5 files changed, 486 insertions(+), 91 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 334bef4..97df633 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -336,11 +336,21 @@ jobs: - name: Build extra dependencies run: | ./deps/PawPaw/bootstrap-cardinal.sh macos-universal - - name: Build macOS universal + - name: Build macOS universal (base) run: | pushd deps/PawPaw; source local.env macos-universal; popd make features make NOOPT=true WITH_LTO=true -j $(sysctl -n hw.logicalcpu) + - name: Build macOS universal (AU using juce) + run: | + pushd deps/PawPaw; source local.env macos-universal; popd + git clone --depth=1 -b master https://github.com/juce-framework/JUCE.git jucewrapper/JUCE + mkdir jucewrapper/build + pushd jucewrapper/build; cmake .. && make -j $(sysctl -n hw.logicalcpu); popd + mv jucewrapper/build/*_artefacts/AU/*.component bin/ + - name: Build macOS universal (packaging) + run: | + pushd deps/PawPaw; source local.env macos-universal; popd ./dpf/utils/package-osx-bundles.sh - name: Set sha8 (non-release) if: startsWith(github.ref, 'refs/tags/') != true diff --git a/dpf b/dpf index 2133002..215fc23 160000 --- a/dpf +++ b/dpf @@ -1 +1 @@ -Subproject commit 21330021cea0854dc6f21a0c718e0e3692dc441f +Subproject commit 215fc2317efe822abf5eb545f422eedbb473693d diff --git a/jucewrapper/CMakeLists.txt b/jucewrapper/CMakeLists.txt index e3a05a7..c0c2849 100644 --- a/jucewrapper/CMakeLists.txt +++ b/jucewrapper/CMakeLists.txt @@ -49,6 +49,9 @@ set_property(TARGET zita_resampler PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_ add_library(sCardinalFX STATIC IMPORTED) set_property(TARGET sCardinalFX PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../bin/CardinalFX.a") +add_library(sCardinalSynth STATIC IMPORTED) +set_property(TARGET sCardinalSynth PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../bin/CardinalSynth.a") + add_library(sPlugins STATIC IMPORTED) set_property(TARGET sPlugins PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../plugins/plugins.a") @@ -110,7 +113,7 @@ juce_add_plugin(CardinalFX COMPANY_WEBSITE "https://github.com/DISTRHO/Cardinal" DESCRIPTION "Virtual modular synthesizer plugin" EDITOR_WANTS_KEYBOARD_FOCUS TRUE - FORMATS Standalone AU + FORMATS Standalone VST3 AU IS_MIDI_EFFECT FALSE IS_SYNTH FALSE NEEDS_MIDI_INPUT TRUE @@ -130,6 +133,7 @@ target_include_directories(CardinalFX target_compile_definitions(CardinalFX PUBLIC + JucePlugin_PreferredChannelConfigurations={2,2} JUCE_CHECK_MEMORY_LEAKS=0 JUCE_DISABLE_NATIVE_FILECHOOSERS=0 JUCE_DISPLAY_SPLASH_SCREEN=0 @@ -188,3 +192,88 @@ target_link_libraries(CardinalFX juce::juce_recommended_warning_flags) # Synth variant + +juce_add_plugin(CardinalSynth + AU_MAIN_TYPE kAudioUnitType_Generator + COMPANY_COPYRIGHT "GPL-3.0-or-later" + COMPANY_NAME "DISTRHO" + COMPANY_WEBSITE "https://github.com/DISTRHO/Cardinal" + DESCRIPTION "Virtual modular synthesizer plugin" + EDITOR_WANTS_KEYBOARD_FOCUS TRUE + FORMATS Standalone VST3 AU + IS_MIDI_EFFECT FALSE + IS_SYNTH TRUE + NEEDS_MIDI_INPUT TRUE + NEEDS_MIDI_OUTPUT TRUE + PLUGIN_CODE DcnS + PLUGIN_MANUFACTURER_CODE Dstr + PRODUCT_NAME "CardinalSynth") + +target_sources(CardinalSynth + PRIVATE + CardinalWrapper.cpp) + +target_include_directories(CardinalSynth + PRIVATE + ../dpf/distrho + ../src/CardinalSynth) + +target_compile_definitions(CardinalSynth + PUBLIC + JucePlugin_PreferredChannelConfigurations={0,2} + JUCE_CHECK_MEMORY_LEAKS=0 + JUCE_DISABLE_NATIVE_FILECHOOSERS=0 + JUCE_DISPLAY_SPLASH_SCREEN=0 + JUCE_MODAL_LOOPS_PERMITTED=0 + JUCE_USE_CURL=0 + JUCE_USE_FLAC=0 + JUCE_USE_OGGVORBIS=0 + JUCE_USE_XINERAMA=0 + JUCE_VST3_CAN_REPLACE_VST2=0 + JUCE_ALSA=1 + JUCE_DIRECTSOUND=0 + JUCE_JACK=1 + JUCE_WASAPI=0 + JUCE_WEB_BROWSER=0) + +target_link_libraries(CardinalSynth + PRIVATE + juce::juce_audio_utils + ${STATIC_LIBS_START} + sCardinalSynth + sPlugins + sRack + carla_host_plugin + carla_engine_plugin + carla_plugin + native_plugins + audio_decoder + jackbridge + lilv + rtmempool + sfzero + water + zita_resampler + dgl + libarchive + libjansson + libquickjs + libsamplerate + libspeexdsp + libzstd + ${STATIC_LIBS_END} + ${GL_LIBRARIES} + ${DBUS_LIBRARIES} + -L${LIBLO_LIBRARY_DIRS} + ${LIBLO_LIBRARIES} + ${SNDFILE_LIBRARIES} + ${X11_LIBRARIES} + ${XCURSOR_LIBRARIES} + ${XEXT_LIBRARIES} + ${XRANDR_LIBRARIES} + ${EXTRA_LIBS} + -lmagic + PUBLIC + juce::juce_recommended_config_flags + juce::juce_recommended_lto_flags + juce::juce_recommended_warning_flags) diff --git a/jucewrapper/CardinalWrapper.cpp b/jucewrapper/CardinalWrapper.cpp index 94184c3..8503c06 100644 --- a/jucewrapper/CardinalWrapper.cpp +++ b/jucewrapper/CardinalWrapper.cpp @@ -23,39 +23,55 @@ START_NAMESPACE_DISTRHO -#if 0 +// -------------------------------------------------------------------------------------------------------------------- -// ----------------------------------------------------------------------------------------------------------- - -class ParameterForDPF : public juce::AudioProcessorParameter +class ParameterFromDPF : public juce::AudioProcessorParameter { PluginExporter& plugin; + const ParameterEnumerationValues& enumValues; + const ParameterRanges& ranges; + const uint32_t hints; const uint index; + bool* const updatedPtr; + mutable juce::StringArray dpfValueStrings; public: - ParameterForDPF(PluginExporter& plugin_, const uint index_) + ParameterFromDPF(PluginExporter& plugin_, const uint index_, bool* const updatedPtr_) : plugin(plugin_), - index(index_) {} + enumValues(plugin_.getParameterEnumValues(index_)), + ranges(plugin_.getParameterRanges(index_)), + hints(plugin_.getParameterHints(index_)), + index(index_), + updatedPtr(updatedPtr_) {} + + void setValueNotifyingHostFromDPF(const float newValue) + { + setValueNotifyingHost(ranges.getNormalizedValue(newValue)); + *updatedPtr = false; + } protected: float getValue() const override { - return plugin.getParameterRanges(index).getNormalizedValue(plugin.getParameterValue(index)); + return ranges.getNormalizedValue(plugin.getParameterValue(index)); } void setValue(const float newValue) override { - plugin.setParameterValue(index, plugin.getParameterRanges(index).getUnnormalizedValue(newValue)); + *updatedPtr = true; + plugin.setParameterValue(index, ranges.getUnnormalizedValue(newValue)); } float getDefaultValue() const override { - return plugin.getParameterDefault(index); + return ranges.getNormalizedValue(plugin.getParameterDefault(index)); } - juce::String getName(int) const override + juce::String getName(const int maximumStringLength) const override { - return plugin.getParameterName(index).buffer(); + DISTRHO_SAFE_ASSERT_RETURN(maximumStringLength > 0, {}); + + return juce::String(plugin.getParameterName(index).buffer(), static_cast(maximumStringLength)); } juce::String getLabel() const override @@ -63,55 +79,214 @@ protected: return plugin.getParameterUnit(index).buffer(); } - float getValueForText(const juce::String& text) const override + int getNumSteps() const override { - return 0.0f; - } -}; -#endif + if (hints & kParameterIsBoolean) + return 2; -// ----------------------------------------------------------------------------------------------------------- + if (enumValues.restrictedMode) + return enumValues.count; -class CardinalWrapperProcessor : public juce::AudioProcessor -{ - friend class CardinalWrapperEditor; + if (hints & kParameterIsInteger) + return ranges.max - ranges.min; - PluginExporter plugin; - TimePosition timePosition; + return juce::AudioProcessorParameter::getNumSteps(); + } - static bool writeMidi(void* ptr, const MidiEvent& midiEvent) + bool isDiscrete() const override { + if (hints & (kParameterIsBoolean|kParameterIsInteger)) + return true; + + if (enumValues.restrictedMode) + return true; + return false; } - static bool requestParameterValueChange(void* ptr, uint32_t index, float value) + bool isBoolean() const override { - return false; + return (hints & kParameterIsBoolean) != 0x0; } - static bool updateStateValue(void* ptr, const char* key, const char* value) + juce::String getText(const float normalizedValue, const int maximumStringLength) const override { - return false; + DISTRHO_SAFE_ASSERT_RETURN(maximumStringLength > 0, {}); + + float value = ranges.getUnnormalizedValue(normalizedValue); + + if (hints & kParameterIsBoolean) + { + const float midRange = ranges.min + (ranges.max - ranges.min) * 0.5f; + value = value > midRange ? ranges.max : ranges.min; + } + else if (hints & kParameterIsInteger) + { + value = std::round(value); + } + + if (enumValues.restrictedMode) + { + for (uint32_t i=0; i < enumValues.count; ++i) + { + if (d_isEqual(enumValues.values[i].value, value)) + return juce::String(enumValues.values[i].label, static_cast(maximumStringLength)); + } + } + + juce::String text; + if (hints & kParameterIsInteger) + text = juce::String(static_cast(value)); + else + text = juce::String(value); + + return juce::String(text.toRawUTF8(), static_cast(maximumStringLength)); + } + + float getValueForText(const juce::String& text) const override + { + if (enumValues.restrictedMode) + { + for (uint32_t i=0; i < enumValues.count; ++i) + { + if (text == enumValues.values[i].label.buffer()) + return ranges.getNormalizedValue(enumValues.values[i].value); + } + } + + float value; + if (hints & kParameterIsInteger) + value = std::atoi(text.toRawUTF8()); + else + value = std::atof(text.toRawUTF8()); + + return ranges.getFixedAndNormalizedValue(value); + } + + bool isAutomatable() const override + { + return (hints & kParameterIsAutomatable) != 0x0; + } + + juce::String getCurrentValueAsText() const override + { + const float value = plugin.getParameterValue(index); + + if (enumValues.restrictedMode) + { + for (uint32_t i=0; i < enumValues.count; ++i) + { + if (d_isEqual(enumValues.values[i].value, value)) + return juce::String(enumValues.values[i].label); + } + } + + if (hints & kParameterIsInteger) + return juce::String(static_cast(value)); + + return juce::String(value); + } + + juce::StringArray getAllValueStrings() const override + { + if (dpfValueStrings.size() != 0) + return dpfValueStrings; + + if (enumValues.restrictedMode) + { + for (uint32_t i=0; i < enumValues.count; ++i) + dpfValueStrings.add(enumValues.values[i].label.buffer()); + + return dpfValueStrings; + } + + if (hints & kParameterIsBoolean) + { + if (hints & kParameterIsInteger) + { + dpfValueStrings.add(juce::String(static_cast(ranges.min))); + dpfValueStrings.add(juce::String(static_cast(ranges.max))); + } + else + { + dpfValueStrings.add(juce::String(ranges.min)); + dpfValueStrings.add(juce::String(ranges.max)); + } + } + else if (hints & kParameterIsInteger) + { + const int imin = static_cast(ranges.min); + const int imax = static_cast(ranges.max); + + for (int i=imin; i<=imax; ++i) + dpfValueStrings.add(juce::String(i)); + } + + return dpfValueStrings; } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +// unused in cardinal +static constexpr const requestParameterValueChangeFunc nullRequestParameterValueChangeFunc = nullptr; + +// only needed for headless builds, which this wrapper never builds for +static constexpr const updateStateValueFunc nullUpdateStateValueFunc = nullptr; + +// DSP/processor implementation +class CardinalWrapperProcessor : public juce::AudioProcessor +{ + friend class CardinalWrapperEditor; + + PluginExporter plugin; + MidiEvent midiEvents[kMaxMidiEvents]; + TimePosition timePosition; + const uint32_t parameterCount; + + juce::AudioProcessorParameter* bypassParameter; + juce::MidiBuffer* currentMidiMessages; + bool* updatedParameters; public: CardinalWrapperProcessor() - : plugin(this, writeMidi, requestParameterValueChange, updateStateValue) + : plugin(this, writeMidiFunc, nullRequestParameterValueChangeFunc, nullUpdateStateValueFunc), + parameterCount(plugin.getParameterCount()), + bypassParameter(nullptr), + currentMidiMessages(nullptr), + updatedParameters(nullptr) { if (const double sampleRate = getSampleRate()) plugin.setSampleRate(sampleRate); - if (const int blockSize = getBlockSize()) - plugin.setBufferSize(blockSize); + if (const int samplesPerBlock = getBlockSize()) + if (samplesPerBlock > 0) + plugin.setBufferSize(static_cast(samplesPerBlock)); + + getBypassParameter(); + + if (parameterCount != 0) + { + updatedParameters = new bool[parameterCount]; + std::memset(updatedParameters, 0, sizeof(bool)*parameterCount); + + for (uint i=0; i 0,); + plugin.deactivateIfNeeded(); plugin.setSampleRate(sampleRate); - plugin.setBufferSize(samplesPerBlock); + plugin.setBufferSize(static_cast(samplesPerBlock)); plugin.activate(); } @@ -137,8 +314,33 @@ public: void processBlock(juce::AudioBuffer& buffer, juce::MidiBuffer& midiMessages) override { + const int numSamples = buffer.getNumSamples(); + DISTRHO_SAFE_ASSERT_INT_RETURN(numSamples > 0, numSamples, midiMessages.clear()); + + uint32_t midiEventCount = 0; + + for (const juce::MidiMessageMetadata midiMessage : midiMessages) + { + DISTRHO_SAFE_ASSERT_CONTINUE(midiMessage.numBytes > 0); + DISTRHO_SAFE_ASSERT_CONTINUE(midiMessage.samplePosition >= 0); + + if (midiMessage.numBytes > static_cast(MidiEvent::kDataSize)) + continue; + + MidiEvent& midiEvent(midiEvents[midiEventCount++]); + + midiEvent.frame = static_cast(midiMessage.samplePosition); + midiEvent.size = (static_cast(midiMessage.numBytes)); + std::memcpy(midiEvent.data, midiMessage.data, midiEvent.size); + + if (midiEventCount == kMaxMidiEvents) + break; + } + midiMessages.clear(); + const juce::ScopedValueSetter cvs(currentMidiMessages, &midiMessages, nullptr); + juce::AudioPlayHead* const playhead = getPlayHead(); juce::AudioPlayHead::CurrentPositionInfo posInfo; @@ -151,7 +353,7 @@ public: timePosition.bbt.ticksPerBeat = 1920.0; if (posInfo.timeInSamples >= 0) - timePosition.frame = posInfo.timeInSamples; + timePosition.frame = static_cast(posInfo.timeInSamples); else timePosition.frame = 0; @@ -188,9 +390,6 @@ public: plugin.setTimePosition(timePosition); - const int numSamples = buffer.getNumSamples(); - DISTRHO_SAFE_ASSERT_INT_RETURN(numSamples > 0, numSamples,); - DISTRHO_SAFE_ASSERT_RETURN(buffer.getNumChannels() == 2,); const float* audioBufferIn[2]; @@ -200,9 +399,12 @@ public: audioBufferOut[0] = buffer.getWritePointer(0); audioBufferOut[1] = buffer.getWritePointer(1); - plugin.run(audioBufferIn, audioBufferOut, numSamples, nullptr, 0); + plugin.run(audioBufferIn, audioBufferOut, static_cast(numSamples), midiEvents, midiEventCount); } + // fix compiler warning + void processBlock(juce::AudioBuffer&, juce::MidiBuffer&) override {} + double getTailLengthSeconds() const override { return 0.0; @@ -218,6 +420,11 @@ public: return true; } + juce::AudioProcessorParameter* getBypassParameter() const override + { + return nullptr; + } + juce::AudioProcessorEditor* createEditor() override; bool hasEditor() const override @@ -227,7 +434,7 @@ public: int getNumPrograms() override { - return 0; + return 1; } int getCurrentProgram() override @@ -241,7 +448,7 @@ public: const juce::String getProgramName(int) override { - return {}; + return "Default"; } void changeProgramName(int, const juce::String&) override @@ -250,50 +457,80 @@ public: void getStateInformation(juce::MemoryBlock& destData) override { + juce::XmlElement xmlState("CardinalState"); + + for (uint32_t i=0; i xmlState(getXmlFromBinary(data, sizeInBytes)); + DISTRHO_SAFE_ASSERT_RETURN(xmlState.get() != nullptr,); -// ----------------------------------------------------------------------------------------------------------- + const juce::Array& parameters(getParameters()); -class CardinalWrapperEditor : public juce::AudioProcessorEditor, - private juce::Timer -{ - UIExporter* ui; - void* const dspPtr; + for (uint32_t i=0; igetDoubleAttribute(plugin.getParameterSymbol(i).buffer(), + plugin.getParameterDefault(i)); + const float normalizedValue = plugin.getParameterRanges(i).getFixedAndNormalizedValue(value); + parameters.getUnchecked(static_cast(i))->setValueNotifyingHost(normalizedValue); + } - static void editParamFunc(void* ptr, uint32_t rindex, bool started) {} - static void setParamFunc(void* ptr, uint32_t rindex, float value) {} - static void setStateFunc(void* ptr, const char* key, const char* value) {} - static void sendNoteFunc(void* ptr, uint8_t channel, uint8_t note, uint8_t velo) {} + for (uint32_t i=0, stateCount=plugin.getStateCount(); igetStringAttribute(key.buffer(), + plugin.getStateDefaultValue(i).buffer()); + plugin.setState(key, value.toRawUTF8()); + } + } - static void setSizeFunc(void* ptr, uint width, uint height) +private: + static bool writeMidiFunc(void* const ptr, const MidiEvent& midiEvent) { - CardinalWrapperEditor* const editor = static_cast(ptr); - DISTRHO_SAFE_ASSERT_RETURN(editor != nullptr,); + CardinalWrapperProcessor* const processor = static_cast(ptr); + DISTRHO_SAFE_ASSERT_RETURN(processor != nullptr, false); - #ifdef DISTRHO_OS_MAC - UIExporter* const ui = editor->ui; - DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + const uint8_t* const data = midiEvent.size > MidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data; + return processor->currentMidiMessages->addEvent(data, + static_cast(midiEvent.size), + static_cast(midiEvent.frame)); + } +}; - const double scaleFactor = ui->getScaleFactor(); - width /= scaleFactor; - height /= scaleFactor; - #endif +// -------------------------------------------------------------------------------------------------------------------- - editor->setSize(width, height); - } +// unused in cardinal +static constexpr const sendNoteFunc nullSendNoteFunc = nullptr; + +// unwanted, juce file dialogs are ugly +static constexpr const fileRequestFunc nullFileRequestFunc = nullptr; + +// UI/editor implementation +class CardinalWrapperEditor : public juce::AudioProcessorEditor, + private juce::Timer +{ + CardinalWrapperProcessor& cardinalProcessor; - static bool fileRequestFunc(void* ptr, const char* key) { return false; } + UIExporter* ui; + void* const dspPtr; public: - CardinalWrapperEditor(CardinalWrapperProcessor& cardinalProcessor) - : juce::AudioProcessorEditor(cardinalProcessor), + CardinalWrapperEditor(CardinalWrapperProcessor& cardinalProc) + : juce::AudioProcessorEditor(cardinalProc), + cardinalProcessor(cardinalProc), ui(nullptr), - dspPtr(cardinalProcessor.plugin.getInstancePointer()) + dspPtr(cardinalProc.plugin.getInstancePointer()) { setOpaque(true); setResizable(true, false); @@ -309,8 +546,21 @@ public: delete ui; } +protected: void timerCallback() override { + if (ui == nullptr) + return; + + for (uint32_t i=0; iparameterChanged(i, cardinalProcessor.plugin.getParameterValue(i)); + } + } + repaint(); } @@ -318,30 +568,27 @@ public: { if (ui == nullptr) { - auto peer = getPeer(); - d_stdout("peer is %p", peer); + juce::ComponentPeer* const peer = getPeer(); + DISTRHO_SAFE_ASSERT_RETURN(peer != nullptr,); - auto handle = peer->getNativeHandle(); - d_stdout("handle is %p", handle); - - auto proc = getAudioProcessor(); - d_stdout("proc is %p", proc); + void* const nativeHandle = peer->getNativeHandle(); + DISTRHO_SAFE_ASSERT_RETURN(nativeHandle != nullptr,); ui = new UIExporter(this, - (uintptr_t)handle, - proc->getSampleRate(), + (uintptr_t)nativeHandle, + cardinalProcessor.getSampleRate(), editParamFunc, setParamFunc, setStateFunc, - sendNoteFunc, + nullSendNoteFunc, setSizeFunc, - fileRequestFunc, + nullFileRequestFunc, nullptr, // bundlePath dspPtr, 0.0 // scaleFactor ); - if (getAudioProcessor()->wrapperType == juce::AudioProcessor::wrapperType_Standalone) + if (cardinalProcessor.wrapperType == juce::AudioProcessor::wrapperType_Standalone) { const double scaleFactor = ui->getScaleFactor(); ui->setWindowOffset(4 * scaleFactor, 30 * scaleFactor); @@ -350,6 +597,57 @@ public: ui->plugin_idle(); } + +private: + static void editParamFunc(void* const ptr, const uint32_t index, const bool started) + { + CardinalWrapperEditor* const editor = static_cast(ptr); + DISTRHO_SAFE_ASSERT_RETURN(editor != nullptr,); + + CardinalWrapperProcessor& cardinalProcessor(editor->cardinalProcessor); + + if (started) + cardinalProcessor.getParameters().getUnchecked(static_cast(index))->beginChangeGesture(); + else + cardinalProcessor.getParameters().getUnchecked(static_cast(index))->endChangeGesture(); + } + + static void setParamFunc(void* const ptr, const uint32_t index, const float value) + { + CardinalWrapperEditor* const editor = static_cast(ptr); + DISTRHO_SAFE_ASSERT_RETURN(editor != nullptr,); + + CardinalWrapperProcessor& cardinalProcessor(editor->cardinalProcessor); + const juce::Array& parameters(cardinalProcessor.getParameters()); + juce::AudioProcessorParameter* const parameter = parameters.getUnchecked(static_cast(index)); + static_cast(parameter)->setValueNotifyingHostFromDPF(value); + } + + static void setStateFunc(void* const ptr, const char* const key, const char* const value) + { + CardinalWrapperEditor* const editor = static_cast(ptr); + DISTRHO_SAFE_ASSERT_RETURN(editor != nullptr,); + + CardinalWrapperProcessor& cardinalProcessor(editor->cardinalProcessor); + cardinalProcessor.plugin.setState(key, value); + } + + static void setSizeFunc(void* const ptr, uint width, uint height) + { + CardinalWrapperEditor* const editor = static_cast(ptr); + DISTRHO_SAFE_ASSERT_RETURN(editor != nullptr,); + + #ifdef DISTRHO_OS_MAC + UIExporter* const ui = editor->ui; + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + + const double scaleFactor = ui->getScaleFactor(); + width /= scaleFactor; + height /= scaleFactor; + #endif + + editor->setSize(static_cast(width), static_cast(height)); + } }; juce::AudioProcessorEditor* CardinalWrapperProcessor::createEditor() @@ -357,11 +655,11 @@ juce::AudioProcessorEditor* CardinalWrapperProcessor::createEditor() return new CardinalWrapperEditor(*this); } -// ----------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- END_NAMESPACE_DISTRHO -// ----------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- juce::AudioProcessor* createPluginFilter() { @@ -371,4 +669,4 @@ juce::AudioProcessor* createPluginFilter() return new DISTRHO_NAMESPACE::CardinalWrapperProcessor; } -// ----------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- diff --git a/src/Makefile.cardinal.mk b/src/Makefile.cardinal.mk index 748d02d..62e2bee 100644 --- a/src/Makefile.cardinal.mk +++ b/src/Makefile.cardinal.mk @@ -257,10 +257,8 @@ BUILD_CXX_FLAGS += -DCARDINAL_PLUGIN_PREFIX='"$(PREFIX)"' ifeq ($(CARDINAL_VARIANT),main) all: jack lv2 vst3 -else ifeq ($(CARDINAL_VARIANT),fx) -all: lv2 vst2 vst3 static else -all: lv2 vst2 vst3 +all: lv2 vst2 vst3 static endif CORE_RESOURCES = $(subst ../Rack/res/,,$(wildcard ../Rack/res/ComponentLibrary/*.svg ../Rack/res/fonts/*.ttf))