From 6ff11aa6bdb3eb1db0c420d48ac141ecbb608295 Mon Sep 17 00:00:00 2001 From: Boof2015 <75185879+Boof2015@users.noreply.github.com> Date: Tue, 2 Jun 2026 17:24:48 -0400 Subject: [PATCH] fixes --- plugin/Source/PluginEditor.cpp | 40 +++++++++++++++++++++++----------- plugin/Source/PluginEditor.h | 17 +++++++++------ 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/plugin/Source/PluginEditor.cpp b/plugin/Source/PluginEditor.cpp index 091986e..6fb8fe2 100644 --- a/plugin/Source/PluginEditor.cpp +++ b/plugin/Source/PluginEditor.cpp @@ -39,6 +39,10 @@ namespace } #endif +#if JUCE_LINUX + constexpr int kLinuxFrameRateHz = 30; +#endif + std::unique_ptr makeEngine() { #if defined(PRISM_SCOPE_WAVEFORM) && PRISM_SCOPE_WAVEFORM @@ -188,23 +192,14 @@ PrismSpectrumEditor::PrismSpectrumEditor(PrismSpectrumProcessor& p) setResizable(true, true); setResizeLimits(pref.minWidth, pref.minHeight, 4096, 4096); setSize(pref.defaultWidth, pref.defaultHeight); - - if (webView != nullptr) - { -#if JUCE_WINDOWS - startTimerHz(resolveWindowsFrameRateHz(*this)); -#else - // Drive frames at the display's refresh rate (adapts to 60/120/144 Hz). - vblank = juce::VBlankAttachment(this, [this] { renderFrame(); }); -#endif - } } PrismSpectrumEditor::~PrismSpectrumEditor() { -#if JUCE_WINDOWS +#if JUCE_WINDOWS || JUCE_LINUX stopTimer(); #endif + webViewReady = false; } void PrismSpectrumEditor::resized() @@ -259,13 +254,30 @@ void PrismSpectrumEditor::showWebViewFallback() addAndMakeVisible(webViewFallback); } -#if JUCE_WINDOWS +#if JUCE_WINDOWS || JUCE_LINUX void PrismSpectrumEditor::timerCallback() { renderFrame(); } #endif +void PrismSpectrumEditor::startFrameDriver() +{ + if (webView == nullptr || ! webViewReady || frameDriverStarted) + return; + + frameDriverStarted = true; + +#if JUCE_WINDOWS + startTimerHz(resolveWindowsFrameRateHz(*this)); +#elif JUCE_LINUX + startTimerHz(kLinuxFrameRateHz); +#else + // Drive frames at the display's refresh rate (adapts to 60/120/144 Hz). + vblank = juce::VBlankAttachment(this, [this] { renderFrame(); }); +#endif +} + void PrismSpectrumEditor::onSettingsPanel(juce::var payload) { const int height = juce::jmax(0, (int) payload.getProperty("height", 0)); @@ -295,8 +307,10 @@ void PrismSpectrumEditor::onPrismConfig(juce::var payload) void PrismSpectrumEditor::onPrismReady() { + webViewReady = true; pushRestoreSettings(); sendAppDefaults(); + startFrameDriver(); } void PrismSpectrumEditor::onScopeNativeConfig(juce::var payload) @@ -379,7 +393,7 @@ void PrismSpectrumEditor::sendAppDefaults() void PrismSpectrumEditor::renderFrame() { - if (webView == nullptr) + if (webView == nullptr || ! webViewReady) return; #if JUCE_MAC diff --git a/plugin/Source/PluginEditor.h b/plugin/Source/PluginEditor.h index ce3acab..aada306 100644 --- a/plugin/Source/PluginEditor.h +++ b/plugin/Source/PluginEditor.h @@ -10,12 +10,12 @@ * Hosts the React webview UI and bridges the reused Prism spectrum DSP to it. * * Drains stereo audio buffered by the processor, feeds the selected scope engine, - * and emits frame payloads to the webview. macOS uses display vblank; Windows uses - * a steady message-thread timer because some DAW/WebView2 embeddings deliver - * vblank callbacks too slowly for data-driven scopes. + * and emits frame payloads to the webview after the UI reports readiness. macOS + * uses display vblank; Windows/Linux use steady message-thread timers to avoid + * fragile host/browser embedding behavior. */ class PrismSpectrumEditor : public juce::AudioProcessorEditor -#if JUCE_WINDOWS +#if JUCE_WINDOWS || JUCE_LINUX , private juce::Timer #endif { @@ -25,7 +25,7 @@ public: void resized() override; -#if JUCE_WINDOWS +#if JUCE_WINDOWS || JUCE_LINUX void timerCallback() override; #endif @@ -52,6 +52,7 @@ public: private: void loadWebView(); void showWebViewFallback(); + void startFrameDriver(); void renderFrame(); PrismSpectrumProcessor& processorRef; @@ -62,6 +63,8 @@ private: // Height (px) the editor is currently grown by for the open settings panel. int settingsPanelHeight = 0; + bool webViewReady = false; + bool frameDriverStarted = false; // One-time attempt to lift WKWebView's private 60fps cap (macOS). bool frameRateUncapped = false; @@ -71,8 +74,8 @@ private: juce::Label webViewFallback; // Declared last so it is destroyed first; no vblank callback can fire into a - // partially-destroyed editor. Windows uses juce::Timer instead. -#if ! JUCE_WINDOWS + // partially-destroyed editor. Windows/Linux use juce::Timer instead. +#if ! JUCE_WINDOWS && ! JUCE_LINUX juce::VBlankAttachment vblank; #endif