From db8206200bb74c9d64a87178fc18296d3ad55a9e Mon Sep 17 00:00:00 2001 From: James H Ball Date: Fri, 25 Apr 2025 18:14:27 +0100 Subject: [PATCH] Make timeline and new text rendering appear on premium only and remove license registration --- Source/CommonPluginEditor.cpp | 4 +- Source/CommonPluginEditor.h | 9 - Source/CommonPluginProcessor.h | 2 - Source/FrameSettingsComponent.cpp | 8 + Source/FrameSettingsComponent.h | 2 + Source/MainComponent.cpp | 2 +- Source/PluginEditor.cpp | 11 +- Source/PluginProcessor.cpp | 2 +- Source/SosciPluginEditor.cpp | 9 - .../LicenseRegistrationComponent.cpp | 246 ------------------ .../components/LicenseRegistrationComponent.h | 38 --- Source/txt/TextParser.cpp | 9 +- osci-render.jucer | 4 - sosci.jucer | 4 - 14 files changed, 20 insertions(+), 330 deletions(-) delete mode 100644 Source/components/LicenseRegistrationComponent.cpp delete mode 100644 Source/components/LicenseRegistrationComponent.h diff --git a/Source/CommonPluginEditor.cpp b/Source/CommonPluginEditor.cpp index c4849d7..8209474 100644 --- a/Source/CommonPluginEditor.cpp +++ b/Source/CommonPluginEditor.cpp @@ -35,7 +35,7 @@ CommonPluginEditor::CommonPluginEditor(CommonAudioProcessor& p, juce::String app } } - addChildComponent(visualiser); + addAndMakeVisible(visualiser); int width = std::any_cast(audioProcessor.getProperty("appWidth", defaultWidth)); int height = std::any_cast(audioProcessor.getProperty("appHeight", defaultHeight)); @@ -66,8 +66,6 @@ CommonPluginEditor::CommonPluginEditor(CommonAudioProcessor& p, juce::String app #if OSCI_PREMIUM sharedTextureManager.initGL(); -#else - visualiser.setVisible(true); #endif } diff --git a/Source/CommonPluginEditor.h b/Source/CommonPluginEditor.h index 57db70f..adff077 100644 --- a/Source/CommonPluginEditor.h +++ b/Source/CommonPluginEditor.h @@ -10,10 +10,6 @@ #include "components/VolumeComponent.h" #include "components/DownloaderComponent.h" -#if OSCI_PREMIUM - #include "components/LicenseRegistrationComponent.h" -#endif - class CommonPluginEditor : public juce::AudioProcessorEditor { public: CommonPluginEditor(CommonAudioProcessor&, juce::String appName, juce::String projectFileType, int width, int height); @@ -76,11 +72,6 @@ public: juce::SharedResourcePointer tooltipWindow; juce::DropShadower tooltipDropShadow{juce::DropShadow(juce::Colours::black.withAlpha(0.5f), 6, {0,0})}; -#if OSCI_PREMIUM - LicenseRegistrationComponent licenseRegistration {audioProcessor, [this](bool success) { - visualiser.setVisible(success); - }}; -#endif bool usingNativeMenuBar = false; #if JUCE_LINUX diff --git a/Source/CommonPluginProcessor.h b/Source/CommonPluginProcessor.h index fa6e3a5..efac97b 100644 --- a/Source/CommonPluginProcessor.h +++ b/Source/CommonPluginProcessor.h @@ -88,8 +88,6 @@ public: bool hasSetSessionStartTime = false; bool programCrashedAndUserWantsToReset(); - - std::atomic licenseVerified = true; juce::SpinLock audioPlayerListenersLock; std::vector audioPlayerListeners; diff --git a/Source/FrameSettingsComponent.cpp b/Source/FrameSettingsComponent.cpp index 25e7dd7..e0e298b 100644 --- a/Source/FrameSettingsComponent.cpp +++ b/Source/FrameSettingsComponent.cpp @@ -16,7 +16,9 @@ FrameSettingsComponent::FrameSettingsComponent(OscirenderAudioProcessor& p, Osci offsetLabel.setTooltip("Offsets the animation's start point by a specified number of frames."); } else { audioProcessor.animationSyncBPM->setValueNotifyingHost(false); +#if OSCI_PREMIUM addAndMakeVisible(timeline); +#endif } addAndMakeVisible(rateLabel); addAndMakeVisible(rateBox); @@ -60,20 +62,26 @@ void FrameSettingsComponent::resized() { auto area = getLocalBounds().withTrimmedTop(20).reduced(20); double rowHeight = 20; +#if OSCI_PREMIUM auto timelineArea = juce::JUCEApplicationBase::isStandaloneApp() ? area.removeFromBottom(30) : juce::Rectangle(); +#endif auto toggleBounds = juce::JUCEApplicationBase::isStandaloneApp() ? juce::Rectangle() : area.removeFromTop(rowHeight); auto toggleWidth = juce::jmin(area.getWidth() / 3, 150); auto firstColumn = area.removeFromLeft(220); +#if OSCI_PREMIUM if (juce::JUCEApplicationBase::isStandaloneApp()) { timeline.setVisible(animated); } +#endif if (animated) { if (juce::JUCEApplicationBase::isStandaloneApp()) { +#if OSCI_PREMIUM timeline.setBounds(timelineArea); +#endif } else { animate.setBounds(toggleBounds.removeFromLeft(toggleWidth)); sync.setBounds(toggleBounds.removeFromLeft(toggleWidth)); diff --git a/Source/FrameSettingsComponent.h b/Source/FrameSettingsComponent.h index c6e6ea8..c4d35ea 100644 --- a/Source/FrameSettingsComponent.h +++ b/Source/FrameSettingsComponent.h @@ -33,7 +33,9 @@ private: juce::Label offsetLabel{ "Offset","Offset" }; DoubleTextBox rateBox{ audioProcessor.animationRate->min, audioProcessor.animationRate->max }; DoubleTextBox offsetBox{ audioProcessor.animationOffset->min, audioProcessor.animationRate->max }; +#if OSCI_PREMIUM AnimationTimelineComponent timeline{audioProcessor}; +#endif jux::SwitchButton invertImage{audioProcessor.invertImage}; EffectComponent threshold{*audioProcessor.imageThreshold}; diff --git a/Source/MainComponent.cpp b/Source/MainComponent.cpp index cd52390..1586153 100644 --- a/Source/MainComponent.cpp +++ b/Source/MainComponent.cpp @@ -128,7 +128,7 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess osci::BooleanParameter* visualiserFullScreen = audioProcessor.visualiserParameters.visualiserFullScreen; pluginEditor.visualiser.setFullScreen(visualiserFullScreen->getBoolValue()); - addChildComponent(pluginEditor.visualiser); + addAndMakeVisible(pluginEditor.visualiser); pluginEditor.visualiser.setFullScreenCallback([this, visualiserFullScreen](FullScreenMode mode) { if (mode == FullScreenMode::TOGGLE) { visualiserFullScreen->setBoolValueNotifyingHost(!visualiserFullScreen->getBoolValue()); diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index 61dc041..c0b7f4a 100644 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -77,7 +77,7 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr addAndMakeVisible(lua); addAndMakeVisible(luaResizerBar); - addChildComponent(visualiser); + addAndMakeVisible(visualiser); visualiser.openSettings = [this] { openVisualiserSettings(); @@ -95,11 +95,6 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr #endif initialiseMenuBar(model); - -#if OSCI_PREMIUM - addChildComponent(licenseRegistration); - licenseRegistration.toFront(true); -#endif } OscirenderAudioProcessorEditor::~OscirenderAudioProcessorEditor() { @@ -188,10 +183,6 @@ void OscirenderAudioProcessorEditor::resized() { CommonPluginEditor::resized(); auto area = getLocalBounds(); - -#if OSCI_PREMIUM - licenseRegistration.setBounds(area); -#endif if (audioProcessor.visualiserParameters.visualiserFullScreen->getBoolValue()) { visualiser.setBounds(area); diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 92c419f..0f1a5a5 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -620,7 +620,7 @@ void OscirenderAudioProcessor::processBlock(juce::AudioBuffer& buffer, ju threadManager.write(osci::Point(x, y, 1)); // Apply mute if active - if (muteParameter->getBoolValue() || !licenseVerified) { + if (muteParameter->getBoolValue()) { x = 0.0; y = 0.0; } diff --git a/Source/SosciPluginEditor.cpp b/Source/SosciPluginEditor.cpp index 682c812..d1d8f26 100644 --- a/Source/SosciPluginEditor.cpp +++ b/Source/SosciPluginEditor.cpp @@ -33,11 +33,6 @@ SosciPluginEditor::SosciPluginEditor(SosciAudioProcessor& p) : CommonPluginEdito manager.addChangeListener(this); currentInputDevice = getInputDeviceName(); } - -#if OSCI_PREMIUM - addChildComponent(licenseRegistration); - licenseRegistration.toFront(true); -#endif } SosciPluginEditor::~SosciPluginEditor() { @@ -57,10 +52,6 @@ void SosciPluginEditor::paint(juce::Graphics& g) { void SosciPluginEditor::resized() { CommonPluginEditor::resized(); auto area = getLocalBounds(); - -#if OSCI_PREMIUM - licenseRegistration.setBounds(area); -#endif if (audioProcessor.visualiserParameters.visualiserFullScreen->getBoolValue()) { visualiser.setBounds(area); diff --git a/Source/components/LicenseRegistrationComponent.cpp b/Source/components/LicenseRegistrationComponent.cpp deleted file mode 100644 index 5a01c4b..0000000 --- a/Source/components/LicenseRegistrationComponent.cpp +++ /dev/null @@ -1,246 +0,0 @@ -#include "LicenseRegistrationComponent.h" - -LicenseRegistrationComponent::LicenseRegistrationComponent(CommonAudioProcessor& processor, std::function onLicenseVerified) - : audioProcessor(processor), onLicenseVerified(onLicenseVerified) -{ - setupComponents(); - - auto showComponent = [this] { - // If validated within the last week, show immediately - juce::WeakReference weakThis(this); - juce::MessageManager::callAsync([weakThis]() { - if (auto* strongThis = weakThis.get()) { - strongThis->setVisible(true); - } - }); - audioProcessor.licenseVerified = false; - }; - - audioProcessor.reloadGlobalSettings(); - auto savedKey = audioProcessor.getGlobalStringValue("license_key"); - if (savedKey.isNotEmpty()) - { - // Pre-populate the license key field - licenseKeyEditor.setText(savedKey, false); - - auto lastValidated = audioProcessor.getGlobalStringValue("license_last_validated"); - if (lastValidated.isNotEmpty()) - { - auto lastValidationTime = juce::Time::fromISO8601(lastValidated); - auto weekAgo = juce::Time::getCurrentTime() - juce::RelativeTime::weeks(1); - auto hourAgo = juce::Time::getCurrentTime() - juce::RelativeTime::hours(1); - - if (lastValidationTime > weekAgo) - { - if (onLicenseVerified != nullptr) { - onLicenseVerified(true); - } - - audioProcessor.licenseVerified = true; - } else { - showComponent(); - } - - if (lastValidationTime < hourAgo) { - // Validate the license key in the background - validateSavedLicense(); - } - - // Start periodic checks every hour - startTimer(1000 * 60 * 60); - } - } else { - showComponent(); - } -} - -LicenseRegistrationComponent::~LicenseRegistrationComponent() -{ - stopTimer(); -} - -void LicenseRegistrationComponent::setupComponents() -{ - titleLabel.setText("License Registration Required", juce::dontSendNotification); - titleLabel.setFont(juce::Font(24.0f, juce::Font::bold)); - titleLabel.setJustificationType(juce::Justification::centred); - addAndMakeVisible(titleLabel); - - instructionsLabel.setText("Please enter your license key to continue", juce::dontSendNotification); - instructionsLabel.setJustificationType(juce::Justification::centred); - instructionsLabel.setFont(juce::Font(18.0f)); - addAndMakeVisible(instructionsLabel); - - licenseKeyEditor.setTextToShowWhenEmpty("XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX", juce::Colours::grey); - licenseKeyEditor.setInputRestrictions(35, "0123456789ABCDEFabcdef-"); // Allow both upper and lowercase hex digits and hyphens - licenseKeyEditor.onReturnKey = [this] { verifyButton.triggerClick(); }; - licenseKeyEditor.setFont(juce::Font(24.0f)); - licenseKeyEditor.onTextChange = [this] { - auto currentText = licenseKeyEditor.getText(); - auto upperText = currentText.toUpperCase(); - if (currentText != upperText) - { - auto cursorPos = licenseKeyEditor.getCaretPosition(); - licenseKeyEditor.setText(upperText, false); - licenseKeyEditor.setCaretPosition(cursorPos); - } - }; - addAndMakeVisible(licenseKeyEditor); - - verifyButton.setButtonText("Verify License"); - verifyButton.onClick = [this] { - if (!isVerifying) - { - verifyLicense(licenseKeyEditor.getText()); - } - }; - addAndMakeVisible(verifyButton); -} - -void LicenseRegistrationComponent::paint(juce::Graphics& g) -{ - g.fillAll(juce::Colours::black.withAlpha(0.9f)); - - auto bounds = getLocalBounds().toFloat(); -} - -void LicenseRegistrationComponent::resized() -{ - auto bounds = getLocalBounds().reduced(20); - - titleLabel.setBounds(bounds.removeFromTop(40)); - bounds.removeFromTop(20); - - instructionsLabel.setBounds(bounds.removeFromTop(30)); - bounds.removeFromTop(20); - - auto row = bounds.removeFromTop(35); - licenseKeyEditor.setBounds(row.reduced(50, 0)); - bounds.removeFromTop(20); - - auto buttonBounds = bounds.removeFromTop(40); - verifyButton.setBounds(buttonBounds.withSizeKeepingCentre(120, 40)); -} - -void LicenseRegistrationComponent::verifyLicense(const juce::String& licenseKey, bool showErrorDialog) -{ - if (licenseKey.isEmpty()) - return; - - isVerifying = true; - verifyButton.setEnabled(false); - verifyButton.setVisible(false); - - juce::URL url("https://api.osci-render.com/api/verify-license"); - - auto jsonObj = std::make_unique(); - jsonObj->setProperty("license_key", licenseKey); - juce::var jsonData(jsonObj.release()); - - url = url.withPOSTData(juce::JSON::toString(jsonData)); - - auto webStream = url.createInputStream(false, nullptr, nullptr, - "Content-Type: application/json", - 10000); - - bool successfullyVerified = false; - - if (webStream != nullptr) - { - auto response = webStream->readEntireStreamAsString(); - DBG(response); - auto json = juce::JSON::parse(response); - - if (json.hasProperty("success")) { - bool success = json["success"]; - - if (success && json.hasProperty("valid") && json.hasProperty("purchase")) { - bool valid = json["valid"]; - - auto purchase = json["purchase"].getDynamicObject(); - auto productId = purchase->getProperty("product_id").toString(); - - if (success && valid && productId == SOSCI_PRODUCT_ID) - { - // Save the license key and validation timestamp - audioProcessor.setGlobalValue("license_key", licenseKey); - audioProcessor.setGlobalValue("license_last_validated", juce::Time::getCurrentTime().toISO8601(true)); - audioProcessor.saveGlobalSettings(); - - audioProcessor.licenseVerified = true; - - successfullyVerified = true; - - juce::WeakReference weakThis(this); - juce::MessageManager::callAsync([weakThis]() { - if (auto* strongThis = weakThis.get()) { - strongThis->setVisible(false); - } - }); - startTimer(1000 * 60 * 60); // Check every hour - } - else if (showErrorDialog) - { - juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::WarningIcon, - "Invalid License", - "The license key you entered is not valid. Please check and try again."); - } - else - { - // Background check failed, clear the license - clearLicense(); - } - } else if (showErrorDialog && json.hasProperty("message")) { - auto message = json["message"].toString(); - juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::WarningIcon, "Error", message); - } - } - } - else if (showErrorDialog) - { - juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::WarningIcon, - "Connection Error", - "Could not connect to the license server. Please check your internet connection and try again."); - } - - isVerifying = false; - verifyButton.setEnabled(true); - verifyButton.setVisible(true); - - if (onLicenseVerified != nullptr) { - onLicenseVerified(successfullyVerified); - } -} - -bool LicenseRegistrationComponent::validateSavedLicense() -{ - auto savedKey = audioProcessor.getGlobalStringValue("license_key"); - if (savedKey.isNotEmpty()) - { - auto lastValidated = audioProcessor.getGlobalStringValue("license_last_validated"); - if (lastValidated.isNotEmpty()) - { - // Verify in the background without showing error dialogs - verifyLicense(savedKey, false); - return true; - } - } - return false; -} - -void LicenseRegistrationComponent::clearLicense() -{ - audioProcessor.removeGlobalValue("license_key"); - audioProcessor.removeGlobalValue("license_last_validated"); - audioProcessor.saveGlobalSettings(); - setVisible(true); - audioProcessor.licenseVerified = false; -} - -void LicenseRegistrationComponent::timerCallback() -{ - auto savedKey = audioProcessor.getGlobalStringValue("license_key"); - if (savedKey.isNotEmpty()) { - verifyLicense(savedKey, false); - } -} diff --git a/Source/components/LicenseRegistrationComponent.h b/Source/components/LicenseRegistrationComponent.h deleted file mode 100644 index 637a1bc..0000000 --- a/Source/components/LicenseRegistrationComponent.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include -#include "../CommonPluginProcessor.h" - -class LicenseRegistrationComponent : public juce::Component, - public juce::Timer -{ -public: - LicenseRegistrationComponent(CommonAudioProcessor& processor, std::function onLicenseVerified); - ~LicenseRegistrationComponent() override; - - void paint(juce::Graphics& g) override; - void resized() override; - - // Timer callback for background license verification - void timerCallback() override; - -private: - void verifyLicense(const juce::String& licenseKey, bool showErrorDialog = true); - bool validateSavedLicense(); - void clearLicense(); - void setupComponents(); - - CommonAudioProcessor& audioProcessor; - juce::Label titleLabel; - juce::Label instructionsLabel; - juce::TextEditor licenseKeyEditor; - juce::TextButton verifyButton; - bool isVerifying = false; - - const juce::String SOSCI_PRODUCT_ID = "Hsr9C58_YhTxYP0MNvsIow=="; - - std::function onLicenseVerified; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LicenseRegistrationComponent) - JUCE_DECLARE_WEAK_REFERENCEABLE(LicenseRegistrationComponent) -}; diff --git a/Source/txt/TextParser.cpp b/Source/txt/TextParser.cpp index 2aa1516..53cd93d 100644 --- a/Source/txt/TextParser.cpp +++ b/Source/txt/TextParser.cpp @@ -13,6 +13,9 @@ TextParser::~TextParser() { void TextParser::parse(juce::String text, juce::Font font) { lastFont = font; + juce::Path textPath; + +#if OSCI_PREMIUM // Apply formatting markers if the font is bold or italic juce::String formattedText = text; @@ -30,9 +33,6 @@ void TextParser::parse(juce::String text, juce::Font font) { // Create a TextLayout from the AttributedString juce::TextLayout layout; layout.createLayout(attributedString, 64.0f); - - // Create a path from the TextLayout - juce::Path textPath; juce::String displayText = attributedString.getText(); // remove all whitespace @@ -75,10 +75,13 @@ void TextParser::parse(juce::String text, juce::Font font) { // If the layout has no text, fallback to original method if (textPath.isEmpty()) { +#endif juce::GlyphArrangement glyphs; glyphs.addFittedText(font, text, -2, -2, 4, 4, juce::Justification::centred, 2); glyphs.createPath(textPath); +#if OSCI_PREMIUM } +#endif // Convert path to shapes shapes = std::vector>(); diff --git a/osci-render.jucer b/osci-render.jucer index ed2d000..c0e731b 100644 --- a/osci-render.jucer +++ b/osci-render.jucer @@ -162,10 +162,6 @@ file="Source/components/ErrorCodeEditorComponent.h"/> - - - -