| @@ -199,15 +199,6 @@ jobs: | |||
| source deps/PawPaw/local.env macos-${{ matrix.target }} | |||
| make features | |||
| make NOOPT=true -j $(sysctl -n hw.logicalcpu) | |||
| - name: Build macOS (AU using juce) | |||
| if: steps.cache.outputs.cache-hit == 'true' | |||
| shell: bash | |||
| run: | | |||
| export PATH="/usr/local/opt/ccache/libexec:${PATH}" | |||
| source deps/PawPaw/local.env macos-${{ matrix.target }} | |||
| mkdir -p jucewrapper/build | |||
| pushd jucewrapper/build; cmake -DCMAKE_BUILD_TYPE=Release .. && make VERBOSE=1 -j $(sysctl -n hw.logicalcpu); popd | |||
| mv jucewrapper/build/*_artefacts/Release/AU/*.component bin/ | |||
| - name: Build macOS (packaging) | |||
| if: steps.cache.outputs.cache-hit == 'true' | |||
| shell: bash | |||
| @@ -1 +1 @@ | |||
| Subproject commit 8d161477fdd47d43563dbd7569fc4349676b42e2 | |||
| Subproject commit adc561b0f6c49ba8904584e00ba112b5b94682e1 | |||
| @@ -1,547 +0,0 @@ | |||
| cmake_minimum_required(VERSION 3.15) | |||
| project(Cardinal VERSION 24.01) | |||
| include(FetchContent) | |||
| FetchContent_Declare(JUCE | |||
| GIT_REPOSITORY https://github.com/DISTRHO/JUCE.git | |||
| GIT_TAG v6.1.6 | |||
| GIT_SHALLOW TRUE | |||
| ) | |||
| FetchContent_MakeAvailable(JUCE) | |||
| # Config | |||
| set(CMAKE_C_VISIBILITY_PRESET hidden) | |||
| set(CMAKE_CXX_VISIBILITY_PRESET hidden) | |||
| # Define static libs | |||
| add_library(dgl STATIC IMPORTED) | |||
| set_property(TARGET dgl PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../dpf/build/libdgl-opengl.a") | |||
| add_library(carla_host_plugin STATIC IMPORTED) | |||
| set_property(TARGET carla_host_plugin PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../carla/build/plugin/${CMAKE_BUILD_TYPE}/carla-host-plugin.cpp.o") | |||
| add_library(carla_engine_plugin STATIC IMPORTED) | |||
| set_property(TARGET carla_engine_plugin PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../carla/build/modules/${CMAKE_BUILD_TYPE}/carla_engine_plugin.a") | |||
| add_library(carla_plugin STATIC IMPORTED) | |||
| set_property(TARGET carla_plugin PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../carla/build/modules/${CMAKE_BUILD_TYPE}/carla_plugin.a") | |||
| add_library(native_plugins STATIC IMPORTED) | |||
| set_property(TARGET native_plugins PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../carla/build/modules/${CMAKE_BUILD_TYPE}/native-plugins.a") | |||
| add_library(audio_decoder STATIC IMPORTED) | |||
| set_property(TARGET audio_decoder PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../carla/build/modules/${CMAKE_BUILD_TYPE}/audio_decoder.a") | |||
| add_library(jackbridge STATIC IMPORTED) | |||
| set_property(TARGET jackbridge PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../carla/build/modules/${CMAKE_BUILD_TYPE}/jackbridge.min.a") | |||
| add_library(lilv STATIC IMPORTED) | |||
| set_property(TARGET lilv PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../carla/build/modules/${CMAKE_BUILD_TYPE}/lilv.a") | |||
| add_library(rtmempool STATIC IMPORTED) | |||
| set_property(TARGET rtmempool PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../carla/build/modules/${CMAKE_BUILD_TYPE}/rtmempool.a") | |||
| add_library(water STATIC IMPORTED) | |||
| set_property(TARGET water PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../carla/build/modules/${CMAKE_BUILD_TYPE}/water.a") | |||
| add_library(ysfx STATIC IMPORTED) | |||
| set_property(TARGET ysfx PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../carla/build/modules/${CMAKE_BUILD_TYPE}/ysfx.a") | |||
| add_library(zita_resampler STATIC IMPORTED) | |||
| set_property(TARGET zita_resampler PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../carla/build/modules/${CMAKE_BUILD_TYPE}/zita-resampler.a") | |||
| add_library(sCardinal STATIC IMPORTED) | |||
| set_property(TARGET sCardinal PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../bin/Cardinal.a") | |||
| 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") | |||
| add_library(sRack STATIC IMPORTED) | |||
| set_property(TARGET sRack PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../src/rack.a") | |||
| add_library(libaubio STATIC IMPORTED) | |||
| set_property(TARGET libaubio PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../deps/aubio/libaubio.a") | |||
| add_library(libarchive STATIC IMPORTED) | |||
| if (WIN32) | |||
| set_property(TARGET libarchive PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../src/Rack/dep/lib/libarchive_static.a") | |||
| else (WIN32) | |||
| set_property(TARGET libarchive PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../src/Rack/dep/lib/libarchive.a") | |||
| endif (WIN32) | |||
| add_library(libjansson STATIC IMPORTED) | |||
| set_property(TARGET libjansson PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../src/Rack/dep/lib/libjansson.a") | |||
| add_library(libquickjs STATIC IMPORTED) | |||
| set_property(TARGET libquickjs PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../src/Rack/dep/lib/libquickjs.a") | |||
| add_library(libsamplerate STATIC IMPORTED) | |||
| set_property(TARGET libsamplerate PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../src/Rack/dep/lib/libsamplerate.a") | |||
| add_library(libspeexdsp STATIC IMPORTED) | |||
| set_property(TARGET libspeexdsp PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../src/Rack/dep/lib/libspeexdsp.a") | |||
| add_library(libzstd STATIC IMPORTED) | |||
| set_property(TARGET libzstd PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/../src/Rack/dep/lib/libzstd.a") | |||
| set(SURGE_DEP_PATH "${PROJECT_SOURCE_DIR}/../deps/surge-build") | |||
| add_library(surgedep01 STATIC IMPORTED) | |||
| add_library(surgedep02 STATIC IMPORTED) | |||
| add_library(surgedep03 STATIC IMPORTED) | |||
| add_library(surgedep04 STATIC IMPORTED) | |||
| add_library(surgedep05 STATIC IMPORTED) | |||
| add_library(surgedep06 STATIC IMPORTED) | |||
| add_library(surgedep07 STATIC IMPORTED) | |||
| #add_library(surgedep08 STATIC IMPORTED) | |||
| add_library(surgedep09 STATIC IMPORTED) | |||
| add_library(surgedep10 STATIC IMPORTED) | |||
| set_property(TARGET surgedep01 PROPERTY IMPORTED_LOCATION "${SURGE_DEP_PATH}/src/common/libsurge-common.a") | |||
| set_property(TARGET surgedep02 PROPERTY IMPORTED_LOCATION "${SURGE_DEP_PATH}/src/common/libjuce_dsp_rack_sub.a") | |||
| set_property(TARGET surgedep03 PROPERTY IMPORTED_LOCATION "${SURGE_DEP_PATH}/libs/airwindows/libairwindows.a") | |||
| set_property(TARGET surgedep04 PROPERTY IMPORTED_LOCATION "${SURGE_DEP_PATH}/libs/eurorack/libeurorack.a") | |||
| set_property(TARGET surgedep05 PROPERTY IMPORTED_LOCATION "${SURGE_DEP_PATH}/libs/fmt/libfmt.a") | |||
| set_property(TARGET surgedep06 PROPERTY IMPORTED_LOCATION "${SURGE_DEP_PATH}/libs/sqlite-3.23.3/libsqlite.a") | |||
| set_property(TARGET surgedep07 PROPERTY IMPORTED_LOCATION "${SURGE_DEP_PATH}/libs/sst/sst-plugininfra/libsst-plugininfra.a") | |||
| #set_property(TARGET surgedep08 PROPERTY IMPORTED_LOCATION "${SURGE_DEP_PATH}/libs/sst/sst-plugininfra/libs/filesystem/libfilesystem.a") | |||
| set_property(TARGET surgedep09 PROPERTY IMPORTED_LOCATION "${SURGE_DEP_PATH}/libs/sst/sst-plugininfra/libs/strnatcmp/libstrnatcmp.a") | |||
| set_property(TARGET surgedep10 PROPERTY IMPORTED_LOCATION "${SURGE_DEP_PATH}/libs/sst/sst-plugininfra/libs/tinyxml/libtinyxml.a") | |||
| # dependencies | |||
| find_package(PkgConfig REQUIRED) | |||
| pkg_check_modules(FFTW3F REQUIRED fftw3f) | |||
| pkg_check_modules(LIBLO REQUIRED liblo) | |||
| pkg_check_modules(SNDFILE REQUIRED sndfile) | |||
| if (APPLE) | |||
| set(EXTRA_LIBS "-lz") | |||
| set(GL_LIBRARIES "-framework OpenGL") | |||
| set(PLUGIN_FORMATS AU) | |||
| else (APPLE) | |||
| pkg_check_modules(DBUS REQUIRED dbus-1) | |||
| pkg_check_modules(GL REQUIRED gl) | |||
| pkg_check_modules(X11 REQUIRED x11) | |||
| pkg_check_modules(XCURSOR REQUIRED xcursor) | |||
| pkg_check_modules(XEXT REQUIRED xext) | |||
| pkg_check_modules(XRANDR REQUIRED xrandr) | |||
| set(EXTRA_LIBS "-lrt") | |||
| set(STATIC_LIBS_START "-Wl,--whole-archive") | |||
| set(STATIC_LIBS_END "-Wl,--no-whole-archive") | |||
| set(PLUGIN_FORMATS Standalone VST3) | |||
| endif (APPLE) | |||
| # Main variant | |||
| #[[ | |||
| juce_add_plugin(Cardinal | |||
| AU_MAIN_TYPE kAudioUnitType_MusicEffect | |||
| 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 FALSE | |||
| FORMATS ${PLUGIN_FORMATS} | |||
| IS_MIDI_EFFECT FALSE | |||
| IS_SYNTH FALSE | |||
| NEEDS_MIDI_INPUT TRUE | |||
| NEEDS_MIDI_OUTPUT TRUE | |||
| PLUGIN_CODE DcnM | |||
| PLUGIN_MANUFACTURER_CODE Dstr | |||
| PRODUCT_NAME "Cardinal") | |||
| target_sources(Cardinal | |||
| PRIVATE | |||
| CardinalWrapper.cpp) | |||
| target_include_directories(Cardinal | |||
| PRIVATE | |||
| ../dpf/distrho | |||
| ../dpf/dgl/src/pugl-upstream/include | |||
| ../src/Cardinal) | |||
| target_compile_definitions(Cardinal | |||
| PUBLIC | |||
| DISTRHO_NAMESPACE=CardinalDISTRHO | |||
| DGL_NAMESPACE=CardinalDGL | |||
| JucePlugin_PreferredChannelConfigurations=8,8 | |||
| JUCE_CHECK_MEMORY_LEAKS=0 | |||
| JUCE_DISABLE_NATIVE_FILECHOOSERS=1 | |||
| 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=0 | |||
| JUCE_DIRECTSOUND=0 | |||
| JUCE_JACK=0 | |||
| JUCE_WASAPI=0 | |||
| JUCE_WEB_BROWSER=0) | |||
| target_link_libraries(Cardinal | |||
| PRIVATE | |||
| juce::juce_audio_utils | |||
| ${STATIC_LIBS_START} | |||
| sPlugins | |||
| sCardinal | |||
| sRack | |||
| carla_host_plugin | |||
| carla_engine_plugin | |||
| carla_plugin | |||
| native_plugins | |||
| audio_decoder | |||
| jackbridge | |||
| lilv | |||
| rtmempool | |||
| water | |||
| ysfx | |||
| zita_resampler | |||
| dgl | |||
| surgedep01 | |||
| surgedep02 | |||
| surgedep03 | |||
| surgedep04 | |||
| surgedep05 | |||
| surgedep06 | |||
| surgedep07 | |||
| #surgedep08 | |||
| surgedep09 | |||
| surgedep10 | |||
| libaubio | |||
| libarchive | |||
| libjansson | |||
| libquickjs | |||
| libsamplerate | |||
| libspeexdsp | |||
| libzstd | |||
| ${STATIC_LIBS_END} | |||
| ${GL_LIBRARIES} | |||
| ${DBUS_LIBRARIES} | |||
| -L${LIBLO_LIBRARY_DIRS} | |||
| ${FFTW3F_LIBRARIES} | |||
| ${LIBLO_LIBRARIES} | |||
| ${SNDFILE_LIBRARIES} | |||
| ${X11_LIBRARIES} | |||
| ${XCURSOR_LIBRARIES} | |||
| ${XEXT_LIBRARIES} | |||
| ${XRANDR_LIBRARIES} | |||
| ${EXTRA_LIBS} | |||
| -lmagic | |||
| PUBLIC | |||
| juce::juce_recommended_config_flags | |||
| juce::juce_recommended_warning_flags) | |||
| #]] | |||
| # FX variant | |||
| juce_add_plugin(CardinalFX | |||
| AU_MAIN_TYPE kAudioUnitType_MusicEffect | |||
| 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 FALSE | |||
| FORMATS ${PLUGIN_FORMATS} | |||
| IS_MIDI_EFFECT FALSE | |||
| IS_SYNTH FALSE | |||
| NEEDS_MIDI_INPUT TRUE | |||
| NEEDS_MIDI_OUTPUT TRUE | |||
| PLUGIN_CODE DcnF | |||
| PLUGIN_MANUFACTURER_CODE Dstr | |||
| PRODUCT_NAME "CardinalFX") | |||
| target_sources(CardinalFX | |||
| PRIVATE | |||
| CardinalWrapper.cpp) | |||
| target_include_directories(CardinalFX | |||
| PRIVATE | |||
| ../dpf/distrho | |||
| ../dpf/dgl/src/pugl-upstream/include | |||
| ../src/CardinalFX) | |||
| target_compile_definitions(CardinalFX | |||
| PUBLIC | |||
| DISTRHO_NAMESPACE=CardinalDISTRHO | |||
| DGL_NAMESPACE=CardinalDGL | |||
| JucePlugin_PreferredChannelConfigurations=2,2 | |||
| JUCE_CHECK_MEMORY_LEAKS=0 | |||
| JUCE_DISABLE_NATIVE_FILECHOOSERS=1 | |||
| 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=0 | |||
| JUCE_DIRECTSOUND=0 | |||
| JUCE_JACK=0 | |||
| JUCE_WASAPI=0 | |||
| JUCE_WEB_BROWSER=0) | |||
| target_link_libraries(CardinalFX | |||
| PRIVATE | |||
| juce::juce_audio_utils | |||
| ${STATIC_LIBS_START} | |||
| sPlugins | |||
| sCardinalFX | |||
| sRack | |||
| carla_host_plugin | |||
| carla_engine_plugin | |||
| carla_plugin | |||
| native_plugins | |||
| audio_decoder | |||
| jackbridge | |||
| lilv | |||
| rtmempool | |||
| water | |||
| ysfx | |||
| zita_resampler | |||
| dgl | |||
| surgedep01 | |||
| surgedep02 | |||
| surgedep03 | |||
| surgedep04 | |||
| surgedep05 | |||
| surgedep06 | |||
| surgedep07 | |||
| #surgedep08 | |||
| surgedep09 | |||
| surgedep10 | |||
| libaubio | |||
| libarchive | |||
| libjansson | |||
| libquickjs | |||
| libsamplerate | |||
| libspeexdsp | |||
| libzstd | |||
| ${STATIC_LIBS_END} | |||
| ${GL_LIBRARIES} | |||
| ${DBUS_LIBRARIES} | |||
| -L${LIBLO_LIBRARY_DIRS} | |||
| ${FFTW3F_LIBRARIES} | |||
| ${LIBLO_LIBRARIES} | |||
| ${SNDFILE_LIBRARIES} | |||
| ${X11_LIBRARIES} | |||
| ${XCURSOR_LIBRARIES} | |||
| ${XEXT_LIBRARIES} | |||
| ${XRANDR_LIBRARIES} | |||
| ${EXTRA_LIBS} | |||
| -lmagic | |||
| PUBLIC | |||
| juce::juce_recommended_config_flags | |||
| juce::juce_recommended_warning_flags) | |||
| # MIDI variant | |||
| juce_add_plugin(CardinalMIDI | |||
| AU_MAIN_TYPE kAudioUnitType_MIDIProcessor | |||
| 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 FALSE | |||
| FORMATS ${PLUGIN_FORMATS} | |||
| IS_MIDI_EFFECT TRUE | |||
| IS_SYNTH FALSE | |||
| NEEDS_MIDI_INPUT TRUE | |||
| NEEDS_MIDI_OUTPUT TRUE | |||
| PLUGIN_CODE DcnM | |||
| PLUGIN_MANUFACTURER_CODE Dstr | |||
| PRODUCT_NAME "CardinalMIDI") | |||
| target_sources(CardinalMIDI | |||
| PRIVATE | |||
| CardinalWrapper.cpp) | |||
| target_include_directories(CardinalMIDI | |||
| PRIVATE | |||
| ../dpf/distrho | |||
| ../dpf/dgl/src/pugl-upstream/include | |||
| ../src/CardinalFX) | |||
| target_compile_definitions(CardinalMIDI | |||
| PUBLIC | |||
| DISTRHO_NAMESPACE=CardinalDISTRHO | |||
| DGL_NAMESPACE=CardinalDGL | |||
| JucePlugin_PreferredChannelConfigurations=2,2 | |||
| JUCE_CHECK_MEMORY_LEAKS=0 | |||
| JUCE_DISABLE_NATIVE_FILECHOOSERS=1 | |||
| 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=0 | |||
| JUCE_DIRECTSOUND=0 | |||
| JUCE_JACK=0 | |||
| JUCE_WASAPI=0 | |||
| JUCE_WEB_BROWSER=0) | |||
| target_link_libraries(CardinalMIDI | |||
| PRIVATE | |||
| juce::juce_audio_utils | |||
| ${STATIC_LIBS_START} | |||
| sPlugins | |||
| sCardinalFX | |||
| sRack | |||
| carla_host_plugin | |||
| carla_engine_plugin | |||
| carla_plugin | |||
| native_plugins | |||
| audio_decoder | |||
| jackbridge | |||
| lilv | |||
| rtmempool | |||
| water | |||
| ysfx | |||
| zita_resampler | |||
| dgl | |||
| surgedep01 | |||
| surgedep02 | |||
| surgedep03 | |||
| surgedep04 | |||
| surgedep05 | |||
| surgedep06 | |||
| surgedep07 | |||
| #surgedep08 | |||
| surgedep09 | |||
| surgedep10 | |||
| libaubio | |||
| libarchive | |||
| libjansson | |||
| libquickjs | |||
| libsamplerate | |||
| libspeexdsp | |||
| libzstd | |||
| ${STATIC_LIBS_END} | |||
| ${GL_LIBRARIES} | |||
| ${DBUS_LIBRARIES} | |||
| -L${LIBLO_LIBRARY_DIRS} | |||
| ${FFTW3F_LIBRARIES} | |||
| ${LIBLO_LIBRARIES} | |||
| ${SNDFILE_LIBRARIES} | |||
| ${X11_LIBRARIES} | |||
| ${XCURSOR_LIBRARIES} | |||
| ${XEXT_LIBRARIES} | |||
| ${XRANDR_LIBRARIES} | |||
| ${EXTRA_LIBS} | |||
| -lmagic | |||
| PUBLIC | |||
| juce::juce_recommended_config_flags | |||
| juce::juce_recommended_warning_flags) | |||
| # Synth variant | |||
| juce_add_plugin(CardinalSynth | |||
| AU_MAIN_TYPE kAudioUnitType_MusicDevice | |||
| 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 FALSE | |||
| FORMATS ${PLUGIN_FORMATS} | |||
| 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 | |||
| ../dpf/dgl/src/pugl-upstream/include | |||
| ../src/CardinalSynth) | |||
| target_compile_definitions(CardinalSynth | |||
| PUBLIC | |||
| DISTRHO_NAMESPACE=CardinalDISTRHO | |||
| DGL_NAMESPACE=CardinalDGL | |||
| JucePlugin_PreferredChannelConfigurations=0,2 | |||
| JUCE_CHECK_MEMORY_LEAKS=0 | |||
| JUCE_DISABLE_NATIVE_FILECHOOSERS=1 | |||
| 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=0 | |||
| JUCE_DIRECTSOUND=0 | |||
| JUCE_JACK=0 | |||
| JUCE_WASAPI=0 | |||
| JUCE_WEB_BROWSER=0) | |||
| target_link_libraries(CardinalSynth | |||
| PRIVATE | |||
| juce::juce_audio_utils | |||
| ${STATIC_LIBS_START} | |||
| sPlugins | |||
| sCardinalSynth | |||
| sRack | |||
| carla_host_plugin | |||
| carla_engine_plugin | |||
| carla_plugin | |||
| native_plugins | |||
| audio_decoder | |||
| jackbridge | |||
| lilv | |||
| rtmempool | |||
| water | |||
| ysfx | |||
| zita_resampler | |||
| dgl | |||
| surgedep01 | |||
| surgedep02 | |||
| surgedep03 | |||
| surgedep04 | |||
| surgedep05 | |||
| surgedep06 | |||
| surgedep07 | |||
| #surgedep08 | |||
| surgedep09 | |||
| surgedep10 | |||
| libaubio | |||
| libarchive | |||
| libjansson | |||
| libquickjs | |||
| libsamplerate | |||
| libspeexdsp | |||
| libzstd | |||
| ${STATIC_LIBS_END} | |||
| ${GL_LIBRARIES} | |||
| ${DBUS_LIBRARIES} | |||
| -L${LIBLO_LIBRARY_DIRS} | |||
| ${FFTW3F_LIBRARIES} | |||
| ${LIBLO_LIBRARIES} | |||
| ${SNDFILE_LIBRARIES} | |||
| ${X11_LIBRARIES} | |||
| ${XCURSOR_LIBRARIES} | |||
| ${XEXT_LIBRARIES} | |||
| ${XRANDR_LIBRARIES} | |||
| ${EXTRA_LIBS} | |||
| -lmagic | |||
| PUBLIC | |||
| juce::juce_recommended_config_flags | |||
| juce::juce_recommended_warning_flags) | |||
| @@ -1,694 +0,0 @@ | |||
| /* | |||
| * DISTRHO Cardinal Plugin | |||
| * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 3 of | |||
| * the License, or any later version. | |||
| * | |||
| * 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 General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||
| */ | |||
| #include <juce_audio_processors/juce_audio_processors.h> | |||
| #include <AvailabilityMacros.h> | |||
| #if MAC_OS_X_VERSION_MAX_ALLOWED > 101500 | |||
| #error unwanted macOS version, too new | |||
| #endif | |||
| #define createPlugin createStaticPlugin | |||
| #include "src/DistrhoPluginInternal.hpp" | |||
| #include "src/DistrhoUIInternal.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| 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: | |||
| ParameterFromDPF(PluginExporter& plugin_, const uint index_, bool* const updatedPtr_) | |||
| : plugin(plugin_), | |||
| 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 ranges.getNormalizedValue(plugin.getParameterValue(index)); | |||
| } | |||
| void setValue(const float newValue) override | |||
| { | |||
| *updatedPtr = true; | |||
| plugin.setParameterValue(index, ranges.getUnnormalizedValue(newValue)); | |||
| } | |||
| float getDefaultValue() const override | |||
| { | |||
| return ranges.getNormalizedValue(plugin.getParameterDefault(index)); | |||
| } | |||
| juce::String getName(const int maximumStringLength) const override | |||
| { | |||
| if (maximumStringLength <= 0) | |||
| return juce::String(plugin.getParameterName(index).buffer()); | |||
| return juce::String(plugin.getParameterName(index).buffer(), static_cast<size_t>(maximumStringLength)); | |||
| } | |||
| juce::String getLabel() const override | |||
| { | |||
| return plugin.getParameterUnit(index).buffer(); | |||
| } | |||
| int getNumSteps() const override | |||
| { | |||
| if (hints & kParameterIsBoolean) | |||
| return 2; | |||
| if (enumValues.restrictedMode) | |||
| return enumValues.count; | |||
| if (hints & kParameterIsInteger) | |||
| return ranges.max - ranges.min; | |||
| return juce::AudioProcessorParameter::getNumSteps(); | |||
| } | |||
| bool isDiscrete() const override | |||
| { | |||
| if (hints & (kParameterIsBoolean|kParameterIsInteger)) | |||
| return true; | |||
| if (enumValues.restrictedMode) | |||
| return true; | |||
| return false; | |||
| } | |||
| bool isBoolean() const override | |||
| { | |||
| return (hints & kParameterIsBoolean) != 0x0; | |||
| } | |||
| juce::String getText(const float normalizedValue, const int maximumStringLength) const override | |||
| { | |||
| 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)) | |||
| { | |||
| if (maximumStringLength <= 0) | |||
| return juce::String(enumValues.values[i].label); | |||
| return juce::String(enumValues.values[i].label, static_cast<size_t>(maximumStringLength)); | |||
| } | |||
| } | |||
| } | |||
| juce::String text; | |||
| if (hints & kParameterIsInteger) | |||
| text = juce::String(static_cast<int>(value)); | |||
| else | |||
| text = juce::String(value); | |||
| if (maximumStringLength <= 0) | |||
| return text; | |||
| return juce::String(text.toRawUTF8(), static_cast<size_t>(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<int>(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<int>(ranges.min))); | |||
| dpfValueStrings.add(juce::String(static_cast<int>(ranges.max))); | |||
| } | |||
| else | |||
| { | |||
| dpfValueStrings.add(juce::String(ranges.min)); | |||
| dpfValueStrings.add(juce::String(ranges.max)); | |||
| } | |||
| } | |||
| else if (hints & kParameterIsInteger) | |||
| { | |||
| const int imin = static_cast<int>(ranges.min); | |||
| const int imax = static_cast<int>(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, writeMidiFunc, nullRequestParameterValueChangeFunc, nullUpdateStateValueFunc), | |||
| parameterCount(plugin.getParameterCount()), | |||
| bypassParameter(nullptr), | |||
| currentMidiMessages(nullptr), | |||
| updatedParameters(nullptr) | |||
| { | |||
| if (const double sampleRate = getSampleRate()) | |||
| if (sampleRate > 0.0) | |||
| plugin.setSampleRate(sampleRate, true); | |||
| if (const int samplesPerBlock = getBlockSize()) | |||
| if (samplesPerBlock > 0) | |||
| plugin.setBufferSize(static_cast<uint32_t>(samplesPerBlock), true); | |||
| if (parameterCount != 0) | |||
| { | |||
| updatedParameters = new bool[parameterCount]; | |||
| std::memset(updatedParameters, 0, sizeof(bool)*parameterCount); | |||
| for (uint i=0; i<parameterCount; ++i) | |||
| { | |||
| ParameterFromDPF* const param = new ParameterFromDPF(plugin, i, updatedParameters + i); | |||
| addParameter(param); | |||
| if (plugin.getParameterDesignation(i) == kParameterDesignationBypass) | |||
| bypassParameter = param; | |||
| } | |||
| } | |||
| } | |||
| ~CardinalWrapperProcessor() override | |||
| { | |||
| delete[] updatedParameters; | |||
| } | |||
| protected: | |||
| const juce::String getName() const override | |||
| { | |||
| return plugin.getName(); | |||
| } | |||
| juce::StringArray getAlternateDisplayNames() const override | |||
| { | |||
| return juce::StringArray(plugin.getLabel()); | |||
| } | |||
| void prepareToPlay(const double sampleRate, const int samplesPerBlock) override | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(samplesPerBlock > 0,); | |||
| plugin.deactivateIfNeeded(); | |||
| plugin.setSampleRate(sampleRate, true); | |||
| plugin.setBufferSize(static_cast<uint32_t>(samplesPerBlock), true); | |||
| plugin.activate(); | |||
| } | |||
| void releaseResources() override | |||
| { | |||
| plugin.deactivateIfNeeded(); | |||
| } | |||
| void processBlock(juce::AudioBuffer<float>& 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<int>(MidiEvent::kDataSize)) | |||
| continue; | |||
| MidiEvent& midiEvent(midiEvents[midiEventCount++]); | |||
| midiEvent.frame = static_cast<uint32_t>(midiMessage.samplePosition); | |||
| midiEvent.size = (static_cast<uint8_t>(midiMessage.numBytes)); | |||
| std::memcpy(midiEvent.data, midiMessage.data, midiEvent.size); | |||
| if (midiEventCount == kMaxMidiEvents) | |||
| break; | |||
| } | |||
| midiMessages.clear(); | |||
| const juce::ScopedValueSetter<juce::MidiBuffer*> cvs(currentMidiMessages, &midiMessages, nullptr); | |||
| juce::AudioPlayHead* const playhead = getPlayHead(); | |||
| juce::AudioPlayHead::CurrentPositionInfo posInfo; | |||
| if (playhead != nullptr && playhead->getCurrentPosition(posInfo)) | |||
| { | |||
| timePosition.playing = posInfo.isPlaying; | |||
| timePosition.bbt.valid = true; | |||
| // ticksPerBeat is not possible with JUCE | |||
| timePosition.bbt.ticksPerBeat = 1920.0; | |||
| if (posInfo.timeInSamples >= 0) | |||
| timePosition.frame = static_cast<uint64_t>(posInfo.timeInSamples); | |||
| else | |||
| timePosition.frame = 0; | |||
| // use 4/4 as fallback time signature if not provided by the host | |||
| if (posInfo.timeSigNumerator == 0) | |||
| posInfo.timeSigNumerator = 4; | |||
| if (posInfo.timeSigDenominator == 0) | |||
| posInfo.timeSigDenominator = 4; | |||
| timePosition.bbt.beatsPerMinute = posInfo.bpm; | |||
| const double ppqPos = std::abs(posInfo.ppqPosition); | |||
| const int ppqPerBar = posInfo.timeSigNumerator * 4 / posInfo.timeSigDenominator; | |||
| const double barBeats = (std::fmod(ppqPos, ppqPerBar) / ppqPerBar) * posInfo.timeSigNumerator; | |||
| const double rest = std::fmod(barBeats, 1.0); | |||
| timePosition.bbt.bar = static_cast<int32_t>(ppqPos) / ppqPerBar + 1; | |||
| timePosition.bbt.beat = static_cast<int32_t>(barBeats - rest + 0.5) + 1; | |||
| timePosition.bbt.tick = rest * timePosition.bbt.ticksPerBeat; | |||
| timePosition.bbt.beatsPerBar = posInfo.timeSigNumerator; | |||
| timePosition.bbt.beatType = posInfo.timeSigDenominator; | |||
| if (posInfo.ppqPosition < 0.0) | |||
| { | |||
| --timePosition.bbt.bar; | |||
| timePosition.bbt.beat = posInfo.timeSigNumerator - timePosition.bbt.beat + 1; | |||
| timePosition.bbt.tick = timePosition.bbt.ticksPerBeat - timePosition.bbt.tick - 1; | |||
| } | |||
| timePosition.bbt.barStartTick = timePosition.bbt.ticksPerBeat* | |||
| timePosition.bbt.beatsPerBar* | |||
| (timePosition.bbt.bar-1); | |||
| } | |||
| else | |||
| { | |||
| timePosition.frame = 0; | |||
| timePosition.playing = false; | |||
| timePosition.bbt.valid = false; | |||
| } | |||
| plugin.setTimePosition(timePosition); | |||
| DISTRHO_SAFE_ASSERT_RETURN(buffer.getNumChannels() >= 2,); | |||
| const float* audioBufferIn[18] = {}; | |||
| float* audioBufferOut[18] = {}; | |||
| for (int i=buffer.getNumChannels(); --i >= 0;) | |||
| { | |||
| audioBufferIn[i] = buffer.getReadPointer(i); | |||
| audioBufferOut[i] = buffer.getWritePointer(i); | |||
| } | |||
| plugin.run(audioBufferIn, audioBufferOut, static_cast<uint32_t>(numSamples), midiEvents, midiEventCount); | |||
| } | |||
| // fix compiler warning | |||
| void processBlock(juce::AudioBuffer<double>&, juce::MidiBuffer&) override {} | |||
| double getTailLengthSeconds() const override | |||
| { | |||
| return 0.0; | |||
| } | |||
| bool acceptsMidi() const override | |||
| { | |||
| return true; | |||
| } | |||
| bool producesMidi() const override | |||
| { | |||
| return true; | |||
| } | |||
| juce::AudioProcessorParameter* getBypassParameter() const override | |||
| { | |||
| return bypassParameter; | |||
| } | |||
| juce::AudioProcessorEditor* createEditor() override; | |||
| bool hasEditor() const override | |||
| { | |||
| return true; | |||
| } | |||
| int getNumPrograms() override | |||
| { | |||
| return 1; | |||
| } | |||
| int getCurrentProgram() override | |||
| { | |||
| return 0; | |||
| } | |||
| void setCurrentProgram(int) override | |||
| { | |||
| } | |||
| const juce::String getProgramName(int) override | |||
| { | |||
| return "Default"; | |||
| } | |||
| void changeProgramName(int, const juce::String&) override | |||
| { | |||
| } | |||
| void getStateInformation(juce::MemoryBlock& destData) override | |||
| { | |||
| juce::XmlElement xmlState("CardinalState"); | |||
| for (uint32_t i=0; i<parameterCount; ++i) | |||
| xmlState.setAttribute(plugin.getParameterSymbol(i).buffer(), plugin.getParameterValue(i)); | |||
| for (uint32_t i=0, stateCount=plugin.getStateCount(); i<stateCount; ++i) | |||
| { | |||
| const String& key(plugin.getStateKey(i)); | |||
| xmlState.setAttribute(key.buffer(), plugin.getStateValue(key).buffer()); | |||
| } | |||
| copyXmlToBinary(xmlState, destData); | |||
| } | |||
| void setStateInformation(const void* const data, const int sizeInBytes) override | |||
| { | |||
| std::unique_ptr<juce::XmlElement> xmlState(getXmlFromBinary(data, sizeInBytes)); | |||
| DISTRHO_SAFE_ASSERT_RETURN(xmlState.get() != nullptr,); | |||
| const juce::Array<juce::AudioProcessorParameter*>& parameters(getParameters()); | |||
| for (uint32_t i=0; i<parameterCount; ++i) | |||
| { | |||
| const double value = xmlState->getDoubleAttribute(plugin.getParameterSymbol(i).buffer(), | |||
| plugin.getParameterDefault(i)); | |||
| const float normalizedValue = plugin.getParameterRanges(i).getFixedAndNormalizedValue(value); | |||
| parameters.getUnchecked(static_cast<int>(i))->setValueNotifyingHost(normalizedValue); | |||
| } | |||
| for (uint32_t i=0, stateCount=plugin.getStateCount(); i<stateCount; ++i) | |||
| { | |||
| const String& key(plugin.getStateKey(i)); | |||
| const juce::String value = xmlState->getStringAttribute(key.buffer(), | |||
| plugin.getStateDefaultValue(i).buffer()); | |||
| plugin.setState(key, value.toRawUTF8()); | |||
| } | |||
| } | |||
| private: | |||
| static bool writeMidiFunc(void* const ptr, const MidiEvent& midiEvent) | |||
| { | |||
| CardinalWrapperProcessor* const processor = static_cast<CardinalWrapperProcessor*>(ptr); | |||
| DISTRHO_SAFE_ASSERT_RETURN(processor != nullptr, false); | |||
| juce::MidiBuffer* const currentMidiMessages = processor->currentMidiMessages; | |||
| DISTRHO_SAFE_ASSERT_RETURN(currentMidiMessages != nullptr, false); | |||
| const uint8_t* const data = midiEvent.size > MidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data; | |||
| return currentMidiMessages->addEvent(data, | |||
| static_cast<int>(midiEvent.size), | |||
| static_cast<int>(midiEvent.frame)); | |||
| } | |||
| }; | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // 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; | |||
| UIExporter* ui; | |||
| void* const dspPtr; | |||
| public: | |||
| CardinalWrapperEditor(CardinalWrapperProcessor& cardinalProc) | |||
| : juce::AudioProcessorEditor(cardinalProc), | |||
| cardinalProcessor(cardinalProc), | |||
| ui(nullptr), | |||
| dspPtr(cardinalProc.plugin.getInstancePointer()) | |||
| { | |||
| setOpaque(true); | |||
| setResizable(true, false); | |||
| // setResizeLimits(648, 538, -1, -1); | |||
| setSize(1228, 666); | |||
| startTimer(1000.0 / 60.0); | |||
| } | |||
| ~CardinalWrapperEditor() override | |||
| { | |||
| stopTimer(); | |||
| delete ui; | |||
| } | |||
| protected: | |||
| void timerCallback() override | |||
| { | |||
| if (ui == nullptr) | |||
| return; | |||
| for (uint32_t i=0; i<cardinalProcessor.parameterCount; ++i) | |||
| { | |||
| if (cardinalProcessor.updatedParameters[i]) | |||
| { | |||
| cardinalProcessor.updatedParameters[i] = false; | |||
| ui->parameterChanged(i, cardinalProcessor.plugin.getParameterValue(i)); | |||
| } | |||
| } | |||
| repaint(); | |||
| } | |||
| void paint(juce::Graphics&) override | |||
| { | |||
| if (ui == nullptr) | |||
| { | |||
| juce::ComponentPeer* const peer = getPeer(); | |||
| DISTRHO_SAFE_ASSERT_RETURN(peer != nullptr,); | |||
| void* const nativeHandle = peer->getNativeHandle(); | |||
| DISTRHO_SAFE_ASSERT_RETURN(nativeHandle != nullptr,); | |||
| ui = new UIExporter(this, | |||
| (uintptr_t)nativeHandle, | |||
| cardinalProcessor.getSampleRate(), | |||
| editParamFunc, | |||
| setParamFunc, | |||
| setStateFunc, | |||
| nullSendNoteFunc, | |||
| setSizeFunc, | |||
| nullFileRequestFunc, | |||
| nullptr, // bundlePath | |||
| dspPtr, | |||
| 0.0 // scaleFactor | |||
| ); | |||
| if (cardinalProcessor.wrapperType == juce::AudioProcessor::wrapperType_Standalone) | |||
| { | |||
| const double scaleFactor = ui->getScaleFactor(); | |||
| ui->setWindowOffset(4 * scaleFactor, 30 * scaleFactor); | |||
| } | |||
| } | |||
| ui->plugin_idle(); | |||
| } | |||
| private: | |||
| static void editParamFunc(void* const ptr, const uint32_t index, const bool started) | |||
| { | |||
| CardinalWrapperEditor* const editor = static_cast<CardinalWrapperEditor*>(ptr); | |||
| DISTRHO_SAFE_ASSERT_RETURN(editor != nullptr,); | |||
| CardinalWrapperProcessor& cardinalProcessor(editor->cardinalProcessor); | |||
| if (started) | |||
| cardinalProcessor.getParameters().getUnchecked(static_cast<int>(index))->beginChangeGesture(); | |||
| else | |||
| cardinalProcessor.getParameters().getUnchecked(static_cast<int>(index))->endChangeGesture(); | |||
| } | |||
| static void setParamFunc(void* const ptr, const uint32_t index, const float value) | |||
| { | |||
| CardinalWrapperEditor* const editor = static_cast<CardinalWrapperEditor*>(ptr); | |||
| DISTRHO_SAFE_ASSERT_RETURN(editor != nullptr,); | |||
| CardinalWrapperProcessor& cardinalProcessor(editor->cardinalProcessor); | |||
| const juce::Array<juce::AudioProcessorParameter*>& parameters(cardinalProcessor.getParameters()); | |||
| juce::AudioProcessorParameter* const parameter = parameters.getUnchecked(static_cast<int>(index)); | |||
| static_cast<ParameterFromDPF*>(parameter)->setValueNotifyingHostFromDPF(value); | |||
| } | |||
| static void setStateFunc(void* const ptr, const char* const key, const char* const value) | |||
| { | |||
| CardinalWrapperEditor* const editor = static_cast<CardinalWrapperEditor*>(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<CardinalWrapperEditor*>(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<int>(width), static_cast<int>(height)); | |||
| } | |||
| }; | |||
| juce::AudioProcessorEditor* CardinalWrapperProcessor::createEditor() | |||
| { | |||
| return new CardinalWrapperEditor(*this); | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| juce::AudioProcessor* createPluginFilter() | |||
| { | |||
| // set valid but dummy values | |||
| d_nextBufferSize = 512; | |||
| d_nextSampleRate = 48000.0; | |||
| return new DISTRHO_NAMESPACE::CardinalWrapperProcessor; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Cardinal Plugin | |||
| * Copyright (C) 2021-2023 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2021-2024 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -33,6 +33,10 @@ | |||
| #define DISTRHO_PLUGIN_URI "https://distrho.kx.studio/plugins/cardinal" | |||
| #define DISTRHO_PLUGIN_CLAP_ID "studio.kx.distrho.cardinal" | |||
| #define DISTRHO_PLUGIN_AU_TYPE aumf | |||
| #define DISTRHO_PLUGIN_BRAND_ID Dstr | |||
| #define DISTRHO_PLUGIN_UNIQUE_ID DcnM | |||
| #ifdef HEADLESS | |||
| #define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0 | |||
| @@ -56,4 +60,6 @@ | |||
| #define DISTRHO_PLUGIN_USES_CUSTOM_MODGUI 1 | |||
| #define DISTRHO_PLUGIN_LV2_CATEGORY "mod:ControlVoltagePlugin, lv2:UtilityPlugin" | |||
| #define DPF_VST3_DONT_USE_BRAND_ID | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Cardinal Plugin | |||
| * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2021-2024 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -31,6 +31,10 @@ | |||
| #define DISTRHO_PLUGIN_URI "https://distrho.kx.studio/plugins/cardinal#fx" | |||
| #define DISTRHO_PLUGIN_CLAP_ID "studio.kx.distrho.cardinal#fx" | |||
| #define DISTRHO_PLUGIN_AU_TYPE aumf | |||
| #define DISTRHO_PLUGIN_BRAND_ID Dstr | |||
| #define DISTRHO_PLUGIN_UNIQUE_ID DcnF | |||
| #define DISTRHO_PLUGIN_NAME "Cardinal FX" | |||
| #define DISTRHO_PLUGIN_LABEL "CardinalFX" | |||
| @@ -58,4 +62,6 @@ | |||
| #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:UtilityPlugin" | |||
| #define DISTRHO_PLUGIN_VST3_CATEGORIES "Fx|Generator" | |||
| #define DPF_VST3_DONT_USE_BRAND_ID | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Cardinal Plugin | |||
| * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2021-2024 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -19,6 +19,7 @@ | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define CARDINAL_VARIANT_MAIN 0 | |||
| #define CARDINAL_VARIANT_MINI 0 | |||
| #define CARDINAL_VARIANT_FX 0 | |||
| #define CARDINAL_VARIANT_NATIVE 0 | |||
| #define CARDINAL_VARIANT_SYNTH 1 | |||
| @@ -32,6 +33,10 @@ | |||
| #define DISTRHO_PLUGIN_URI "https://distrho.kx.studio/plugins/cardinal#synth" | |||
| #define DISTRHO_PLUGIN_CLAP_ID "studio.kx.distrho.cardinal#synth" | |||
| #define DISTRHO_PLUGIN_AU_TYPE aumu | |||
| #define DISTRHO_PLUGIN_BRAND_ID Dstr | |||
| #define DISTRHO_PLUGIN_UNIQUE_ID DcnS | |||
| #ifdef HEADLESS | |||
| #define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0 | |||
| @@ -53,4 +58,6 @@ | |||
| #define DISTRHO_PLUGIN_WANT_STATE 1 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | |||
| #define DPF_VST3_DONT_USE_BRAND_ID | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -203,6 +203,7 @@ LV2_RESOURCES = $(CORE_RESOURCES:%=$(TARGET_DIR)/$(NAME).lv2/resources/%) | |||
| VST3_RESOURCES = $(CORE_RESOURCES:%=$(TARGET_DIR)/$(NAME).vst3/Contents/Resources/%) | |||
| ifeq ($(MACOS),true) | |||
| AU_RESOURCES = $(CORE_RESOURCES:%=$(TARGET_DIR)/$(NAME).component/Contents/Resources/%) | |||
| CLAP_RESOURCES = $(CORE_RESOURCES:%=$(TARGET_DIR)/$(NAME).clap/Contents/Resources/%) | |||
| else | |||
| CLAP_RESOURCES = $(CORE_RESOURCES:%=$(TARGET_DIR)/Cardinal.clap/resources/%) | |||
| @@ -418,15 +419,22 @@ TARGETS = jack | |||
| else ifeq ($(CARDINAL_VARIANT),native) | |||
| TARGETS = jack | |||
| else | |||
| TARGETS = lv2 vst2 vst3 clap static | |||
| TARGETS = au clap lv2 vst2 vst3 | |||
| endif | |||
| all: $(TARGETS) | |||
| au: $(AU_RESOURCES) | |||
| clap: $(CLAP_RESOURCES) | |||
| lv2: $(LV2_RESOURCES) | |||
| lv2_sep: $(LV2_RESOURCES) | |||
| vst2: $(VST2_RESOURCES) | |||
| vst3: $(VST3_RESOURCES) | |||
| clap: $(CLAP_RESOURCES) | |||
| # -------------------------------------------------------------- | |||
| # Extra rules for macOS app bundle | |||
| @@ -503,15 +511,19 @@ $(TARGET_DIR)/Cardinal.clap/resources/%: ../Rack/res/% | |||
| -@mkdir -p "$(shell dirname $@)" | |||
| $(SILENT)ln -sf $(abspath $<) $@ | |||
| $(TARGET_DIR)/$(NAME).vst/Contents/Resources/%: ../Rack/res/% | |||
| $(TARGET_DIR)/$(NAME).clap/Contents/Resources/%: ../Rack/res/% | |||
| -@mkdir -p "$(shell dirname $@)" | |||
| $(SILENT)ln -sf $(abspath $<) $@ | |||
| $(TARGET_DIR)/$(NAME).vst3/Contents/Resources/%: ../Rack/res/% | |||
| $(TARGET_DIR)/$(NAME).component/Contents/Resources/%: ../Rack/res/% | |||
| -@mkdir -p "$(shell dirname $@)" | |||
| $(SILENT)ln -sf $(abspath $<) $@ | |||
| $(TARGET_DIR)/$(NAME).clap/Contents/Resources/%: ../Rack/res/% | |||
| $(TARGET_DIR)/$(NAME).vst/Contents/Resources/%: ../Rack/res/% | |||
| -@mkdir -p "$(shell dirname $@)" | |||
| $(SILENT)ln -sf $(abspath $<) $@ | |||
| $(TARGET_DIR)/$(NAME).vst3/Contents/Resources/%: ../Rack/res/% | |||
| -@mkdir -p "$(shell dirname $@)" | |||
| $(SILENT)ln -sf $(abspath $<) $@ | |||