diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b3820cb..eb72bab 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -242,9 +242,9 @@ jobs: make PAWPAW_TARGET=${{ matrix.target }} - name: Validate plugins if: false - #if: steps.cache.outputs.cache-hit == 'true' + if: steps.cache.outputs.cache-hit == 'true' run: | - # ./utils/plugin-builder/validate-plugins.sh ${{ matrix.target }} + ./utils/plugin-builder/validate-plugins.sh ${{ matrix.target }} # FIXME dirty carla leaves temp folders around rm -rf *.tmp - name: Set version tag for release diff --git a/src/PawPaw b/src/PawPaw index 43cc25c..6250a88 160000 --- a/src/PawPaw +++ b/src/PawPaw @@ -1 +1 @@ -Subproject commit 43cc25c79cac4525cf07e1aaad82ae395c436883 +Subproject commit 6250a88ce79a67ebb67ef72b62593684cea336ea diff --git a/src/mod-host b/src/mod-host index c6a567c..7d0b7a2 160000 --- a/src/mod-host +++ b/src/mod-host @@ -1 +1 @@ -Subproject commit c6a567c36afe6aa59a19884580c54ccfc20c898d +Subproject commit 7d0b7a2d7d58df3068eecfcf2594d4524b9ebeb6 diff --git a/src/plugin/ChildProcess.hpp b/src/plugin/ChildProcess.hpp index 33983a8..6b771f1 100644 --- a/src/plugin/ChildProcess.hpp +++ b/src/plugin/ChildProcess.hpp @@ -86,7 +86,7 @@ class ChildProcess nullptr, // lpProcessAttributes nullptr, // lpThreadAttributes TRUE, // bInheritHandles - /* CREATE_NO_WINDOW | */ CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags + CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags const_cast(envp), // lpEnvironment nullptr, // lpCurrentDirectory &si, // lpStartupInfo diff --git a/src/plugin/DesktopPlugin.cpp b/src/plugin/DesktopPlugin.cpp index c15c05f..c19cd66 100644 --- a/src/plugin/DesktopPlugin.cpp +++ b/src/plugin/DesktopPlugin.cpp @@ -19,6 +19,7 @@ class DesktopPlugin : public Plugin, ChildProcess jackd; ChildProcess mod_ui; SharedMemory shm; + String currentPedalboard; bool startingJackd = false; bool startingModUI = false; bool processing = false; @@ -28,7 +29,7 @@ class DesktopPlugin : public Plugin, float* tmpBuffers[2] = {}; uint32_t numFramesInShmBuffer = 0; uint32_t numFramesInTmpBuffer = 0; - uint portBaseNum = 0; + int portBaseNum = 0; #ifdef DISTRHO_OS_WINDOWS const WCHAR* envp; @@ -38,11 +39,14 @@ class DesktopPlugin : public Plugin, public: DesktopPlugin() - : Plugin(kParameterCount, 0, 0), + : Plugin(kParameterCount, 0, 1), envp(nullptr) { if (isDummyInstance()) + { + portBaseNum = -kErrorUndefined; return; + } // TODO check available ports static int port = 1; @@ -53,7 +57,7 @@ class DesktopPlugin : public Plugin, if (envp == nullptr) { - parameters[kParameterBasePortNumber] = -kErrorAppDirNotFound; + parameters[kParameterBasePortNumber] = portBaseNum = -kErrorAppDirNotFound; return; } @@ -67,11 +71,13 @@ class DesktopPlugin : public Plugin, stopRunner(); if (processing && jackd.isRunning()) + { + processing = false; shm.stopWait(); + } jackd.stop(); mod_ui.stop(); - shm.deinit(); delete[] tmpBuffers[0]; @@ -100,12 +106,18 @@ class DesktopPlugin : public Plugin, #define APP_EXT "" #endif + if (shm.data == nullptr && ! shm.init()) + { + parameters[kParameterBasePortNumber] = portBaseNum = -kErrorShmSetupFailed; + return false; + } + if (! jackd.isRunning()) { if (startingJackd) { startingJackd = false; - parameters[kParameterBasePortNumber] = -kErrorJackdExecFailed; + parameters[kParameterBasePortNumber] = portBaseNum = -kErrorJackdExecFailed; return false; } @@ -130,7 +142,7 @@ class DesktopPlugin : public Plugin, if (jackd.start(jackd_args, envp)) return true; - parameters[kParameterBasePortNumber] = -kErrorJackdExecFailed; + parameters[kParameterBasePortNumber] = portBaseNum = -kErrorJackdExecFailed; return false; } @@ -149,7 +161,7 @@ class DesktopPlugin : public Plugin, if (startingModUI) { startingModUI = false; - parameters[kParameterBasePortNumber] = -kErrorModUiExecFailed; + parameters[kParameterBasePortNumber] = portBaseNum = -kErrorModUiExecFailed; return false; } @@ -165,7 +177,7 @@ class DesktopPlugin : public Plugin, if (mod_ui.start(mod_ui_args, envp)) return true; - parameters[kParameterBasePortNumber] = -kErrorModUiExecFailed; + parameters[kParameterBasePortNumber] = portBaseNum = -kErrorModUiExecFailed; return false; } @@ -225,6 +237,7 @@ class DesktopPlugin : public Plugin, */ uint32_t getVersion() const override { + // return d_version(VERSION[0]-'0', VERSION[2]-'0', VERSION[4]-'0'); return d_version(1, 0, 0); } @@ -267,9 +280,12 @@ class DesktopPlugin : public Plugin, Set a state key and default value. This function will be called once, shortly after the plugin is created. */ - void initState(uint32_t, String&, String&) override + void initState(uint32_t, State& state) override { - // we are using states but don't want them saved in the host + state.hints = kStateIsFilenamePath | kStateIsOnlyForDSP; + state.key = "pedalboard"; + state.defaultValue = ""; + state.label = "Pedalboard"; } /* -------------------------------------------------------------------------------------------------------- @@ -291,11 +307,25 @@ class DesktopPlugin : public Plugin, // parameters[index] = value; } + /** + Get the value of an internal state. + The host may call this function from any non-realtime context. + */ + String getState(const char* const key) const override + { + if (std::strcmp(key, "pedalboard") == 0) + return currentPedalboard; + + return String(); + } + /** Change an internal state. */ - void setState(const char*, const char*) override + void setState(const char* const key, const char* const value) override { + if (std::strcmp(key, "pedalboard") == 0) + currentPedalboard = value; } /* -------------------------------------------------------------------------------------------------------- @@ -307,7 +337,7 @@ class DesktopPlugin : public Plugin, { firstTimeActivating = false; - if (envp != nullptr && shm.init() && run()) + if (run()) startRunner(500); } else @@ -315,6 +345,7 @@ class DesktopPlugin : public Plugin, shm.reset(); } + firstTimeProcessing = true; numFramesInShmBuffer = numFramesInTmpBuffer = 0; } @@ -513,14 +544,21 @@ class DesktopPlugin : public Plugin, void sampleRateChanged(double) override { - if (jackd.isRunning()) - { - stopRunner(); - jackd.stop(); + if (portBaseNum < 0 || shm.data == nullptr) + return; - if (run()) - startRunner(500); + stopRunner(); + + if (processing && jackd.isRunning()) + { + processing = false; + shm.stopWait(); } + + jackd.stop(); + shm.deinit(); + + firstTimeActivating = true; } // ------------------------------------------------------------------------------------------------------- diff --git a/src/plugin/DesktopUI.cpp b/src/plugin/DesktopUI.cpp index 3158eef..a5580b7 100644 --- a/src/plugin/DesktopUI.cpp +++ b/src/plugin/DesktopUI.cpp @@ -41,18 +41,19 @@ class DesktopUI : public UI, buttonRefresh.setAbsolutePos(2 * scaleFactor, 2 * scaleFactor); buttonRefresh.setSize(70 * scaleFactor, 26 * scaleFactor); - buttonOpenWebGui.setId(2); - buttonOpenWebGui.setLabel("Open in Web Browser"); - buttonOpenWebGui.setFontScale(scaleFactor); - buttonOpenWebGui.setAbsolutePos(74 * scaleFactor, 2 * scaleFactor); - buttonOpenWebGui.setSize(150 * scaleFactor, 26 * scaleFactor); - - buttonOpenUserFilesDir.setId(3); + buttonOpenUserFilesDir.setId(2); buttonOpenUserFilesDir.setLabel("Open User Files Dir"); buttonOpenUserFilesDir.setFontScale(scaleFactor); - buttonOpenUserFilesDir.setAbsolutePos(226 * scaleFactor, 2 * scaleFactor); + buttonOpenUserFilesDir.setAbsolutePos(74 * scaleFactor, 2 * scaleFactor); buttonOpenUserFilesDir.setSize(140 * scaleFactor, 26 * scaleFactor); + buttonOpenWebGui.setId(3); + buttonOpenWebGui.setLabel("Open in Web Browser"); + buttonOpenWebGui.setFontScale(scaleFactor); + buttonOpenWebGui.setAbsolutePos(216 * scaleFactor, 2 * scaleFactor); + buttonOpenWebGui.setSize(150 * scaleFactor, 26 * scaleFactor); + buttonOpenWebGui.hide(); + label = "MOD Desktop "; label += getPluginFormatName(); label += " v" VERSION; @@ -92,6 +93,13 @@ class DesktopUI : public UI, if (value < 0.f) { + if (webview != nullptr) + { + destroyWebView(webview); + webview = nullptr; + buttonOpenWebGui.hide(); + } + switch (-d_roundToIntNegative(value)) { case kErrorAppDirNotFound: @@ -106,11 +114,16 @@ class DesktopUI : public UI, error = "Error: Failed to start mod-ui"; errorDetail = ""; break; + case kErrorShmSetupFailed: + error = "Error initializing MOD Desktop plugin"; + errorDetail = "Shared memory setup failed"; + break; case kErrorUndefined: error = "Error initializing MOD Desktop plugin"; errorDetail = ""; break; } + repaint(); return; } @@ -126,13 +139,20 @@ class DesktopUI : public UI, { destroyWebView(webview); webview = nullptr; + + buttonOpenWebGui.hide(); + repaint(); } port = d_roundToUnsignedInt(value); DISTRHO_SAFE_ASSERT_RETURN(port != 0,); port += kPortNumOffset; + d_stderr("webview port is %d", port); webview = addWebView(getWindow().getNativeWindowHandle(), getScaleFactor(), port); + + buttonOpenWebGui.show(); + repaint(); } } @@ -182,10 +202,10 @@ class DesktopUI : public UI, reloadWebView(webview); break; case 2: - openWebGui(port); + openUserFilesDir(); break; case 3: - openUserFilesDir(); + openWebGui(port); break; } } diff --git a/src/plugin/DistrhoPluginInfo.h b/src/plugin/DistrhoPluginInfo.h index 926c8be..39551c3 100644 --- a/src/plugin/DistrhoPluginInfo.h +++ b/src/plugin/DistrhoPluginInfo.h @@ -15,9 +15,11 @@ #define DISTRHO_PLUGIN_IS_RT_SAFE 0 #define DISTRHO_PLUGIN_NUM_INPUTS 2 #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 +#define DISTRHO_PLUGIN_WANT_LATENCY 1 #define DISTRHO_PLUGIN_WANT_MIDI_INPUT 1 #define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 1 #define DISTRHO_PLUGIN_WANT_STATE 1 +#define DISTRHO_PLUGIN_WANT_FULL_STATE 1 #define DISTRHO_UI_FILE_BROWSER 0 #define DISTRHO_UI_DEFAULT_WIDTH 1170 #define DISTRHO_UI_DEFAULT_HEIGHT 600 @@ -31,6 +33,7 @@ enum Error { kErrorAppDirNotFound = 1, kErrorJackdExecFailed, kErrorModUiExecFailed, + kErrorShmSetupFailed, kErrorUndefined }; diff --git a/src/plugin/Makefile b/src/plugin/Makefile index 3f7768c..0ef829f 100644 --- a/src/plugin/Makefile +++ b/src/plugin/Makefile @@ -39,11 +39,12 @@ BUILD_CXX_FLAGS += -pthread LINK_FLAGS += -pthread ifeq ($(MACOS),true) -LINK_FLAGS += -framework IOKit -framework WebKit +LINK_FLAGS += -framework CoreFoundation -framework IOKit -framework WebKit else ifeq ($(WINDOWS),true) LINK_FLAGS += -lwinmm else ifeq ($(LINUX),true) -BUILD_CXX_FLAGS += $(shell $(PKG_CONFIG) --cflags Qt5Core) -std=gnu++14 +BUILD_CXX_FLAGS += $(shell $(PKG_CONFIG) --cflags Qt5Core) +# -std=gnu++14 LINK_FLAGS += -ldl -lrt endif diff --git a/src/plugin/SharedMemory.hpp b/src/plugin/SharedMemory.hpp index 7601799..aee7810 100644 --- a/src/plugin/SharedMemory.hpp +++ b/src/plugin/SharedMemory.hpp @@ -222,6 +222,7 @@ class SharedMemory data->magic = 7331; post(); wait(); + data->magic = 1337; } bool process(float** output, const uint32_t offset) diff --git a/src/plugin/WebViewQt.cpp b/src/plugin/WebViewQt.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/plugin/WebViewX11.cpp b/src/plugin/WebViewX11.cpp index 2732df2..d785865 100644 --- a/src/plugin/WebViewX11.cpp +++ b/src/plugin/WebViewX11.cpp @@ -472,7 +472,6 @@ static bool qt6webengine(const Window winId, const double scaleFactor, const cha QWebEngineView_setUrl(webview, *qurl); }; - QApplication_exec(); dlclose(lib); diff --git a/src/plugin/utils.cpp b/src/plugin/utils.cpp index 8efd8f6..aa96aa4 100644 --- a/src/plugin/utils.cpp +++ b/src/plugin/utils.cpp @@ -289,6 +289,7 @@ char* const* getEvironment(const uint portBaseNum) set_envp_value(envpl, L"LANG=en_US.UTF-8"); set_envp_value(envpl, L"MOD_DESKTOP=1"); set_envp_value(envpl, L"MOD_DESKTOP_PLUGIN=1"); + set_envp_value(envpl, L"MOD_LOG=0"); set_envp_value(envpl, L"PYTHONUNBUFFERED=1"); #else while (environ[envsize] != nullptr) @@ -306,6 +307,7 @@ char* const* getEvironment(const uint portBaseNum) set_envp_value(envp, "LANG=en_US.UTF-8"); set_envp_value(envp, "MOD_DESKTOP=1"); set_envp_value(envp, "MOD_DESKTOP_PLUGIN=1"); + set_envp_value(envp, "MOD_LOG=0"); set_envp_value(envp, "PYTHONUNBUFFERED=1"); #endif diff --git a/utils/debug/jackd b/utils/debug/jackd index 8c345e3..7fc4125 100755 --- a/utils/debug/jackd +++ b/utils/debug/jackd @@ -60,6 +60,9 @@ else export LD_BIND_NOW=1 export LD_LIBRARY_PATH="${PAWPAW_PREFIX}/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" export JACK_DRIVER_DIR="$(pwd)/jack" + if [ -e "/usr/lib/x86_64-linux-gnu/pipewire-0.3/jack/libjack.so.0" ] && [ -e "/etc/ld.so.conf.d/pipewire-jack-x86_64-linux-gnu.conf" ]; then + export JACKBRIDGE_FILENAME="/usr/lib/x86_64-linux-gnu/pipewire-0.3/jack/libjack.so.0" + fi fi LV2_PATH="$(convert_path "${DOCS_DIR}/MOD Desktop/lv2")"