kopia lustrzana https://github.com/jameshball/osci-render
				
				
				
			Refactor how syphon/spout input works to be cleaner and less buggy
							rodzic
							
								
									9e93ffc260
								
							
						
					
					
						commit
						67650b682e
					
				| 
						 | 
				
			
			@ -22,9 +22,6 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
 | 
			
		|||
                     juce::FileBrowserComponent::canSelectFiles;
 | 
			
		||||
 | 
			
		||||
        chooser->launchAsync(flags, [this](const juce::FileChooser& chooser) {
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
            juce::SpinLock::ScopedLockType syphonLock(audioProcessor.syphonLock);
 | 
			
		||||
#endif
 | 
			
		||||
            juce::SpinLock::ScopedLockType parsersLock(audioProcessor.parsersLock);
 | 
			
		||||
            bool fileAdded = false;
 | 
			
		||||
            for (auto& file : chooser.getResults()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -66,9 +63,6 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
 | 
			
		|||
 | 
			
		||||
    addAndMakeVisible(leftArrow);
 | 
			
		||||
    leftArrow.onClick = [this] {
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
        juce::SpinLock::ScopedLockType lock(audioProcessor.syphonLock);
 | 
			
		||||
#endif
 | 
			
		||||
        juce::SpinLock::ScopedLockType parserLock(audioProcessor.parsersLock);
 | 
			
		||||
        juce::SpinLock::ScopedLockType effectsLock(audioProcessor.effectsLock);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,9 +77,6 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
 | 
			
		|||
 | 
			
		||||
    addAndMakeVisible(rightArrow);
 | 
			
		||||
    rightArrow.onClick = [this] {
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
        juce::SpinLock::ScopedLockType lock(audioProcessor.syphonLock);
 | 
			
		||||
#endif
 | 
			
		||||
        juce::SpinLock::ScopedLockType parserLock(audioProcessor.parsersLock);
 | 
			
		||||
        juce::SpinLock::ScopedLockType effectsLock(audioProcessor.effectsLock);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -108,9 +99,6 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
 | 
			
		|||
    addAndMakeVisible(createFile);
 | 
			
		||||
 | 
			
		||||
    createFile.onClick = [this] {
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
        juce::SpinLock::ScopedLockType syphonLock(audioProcessor.syphonLock);
 | 
			
		||||
#endif
 | 
			
		||||
        juce::SpinLock::ScopedLockType parsersLock(audioProcessor.parsersLock);
 | 
			
		||||
        auto fileNameText = fileName.getText();
 | 
			
		||||
        auto fileTypeText = fileType.getText();
 | 
			
		||||
| 
						 | 
				
			
			@ -173,8 +161,8 @@ void MainComponent::updateFileLabel() {
 | 
			
		|||
 | 
			
		||||
    {
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
        if (audioProcessor.isSyphonInputActive()) {
 | 
			
		||||
            fileLabel.setText(audioProcessor.getSyphonSourceName(), juce::dontSendNotification);
 | 
			
		||||
        if (audioProcessor.syphonInputActive) {
 | 
			
		||||
            fileLabel.setText(pluginEditor.getSyphonSourceName(), juce::dontSendNotification);
 | 
			
		||||
        } else
 | 
			
		||||
#endif
 | 
			
		||||
            if (audioProcessor.objectServerRendering) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,9 +54,6 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
 | 
			
		|||
    colourScheme = lookAndFeel.getDefaultColourScheme();
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
        juce::SpinLock::ScopedLockType syphonLock(audioProcessor.syphonLock);
 | 
			
		||||
#endif
 | 
			
		||||
        juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock);
 | 
			
		||||
        initialiseCodeEditors();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -143,9 +140,6 @@ void OscirenderAudioProcessorEditor::filesDropped(const juce::StringArray& files
 | 
			
		|||
    if (file.hasFileExtension("osci")) {
 | 
			
		||||
        openProject(file);
 | 
			
		||||
    } else {
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
        juce::SpinLock::ScopedLockType syphonLock(audioProcessor.syphonLock);
 | 
			
		||||
#endif
 | 
			
		||||
        juce::SpinLock::ScopedLockType parsersLock(audioProcessor.parsersLock);
 | 
			
		||||
        juce::SpinLock::ScopedLockType effectsLock(audioProcessor.effectsLock);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -379,9 +373,6 @@ void OscirenderAudioProcessorEditor::handleAsyncUpdate() {
 | 
			
		|||
void OscirenderAudioProcessorEditor::changeListenerCallback(juce::ChangeBroadcaster* source) {
 | 
			
		||||
    if (source == &audioProcessor.broadcaster) {
 | 
			
		||||
        {
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
            juce::SpinLock::ScopedLockType syphonLock(audioProcessor.syphonLock);
 | 
			
		||||
#endif
 | 
			
		||||
            juce::SpinLock::ScopedLockType parsersLock(audioProcessor.parsersLock);
 | 
			
		||||
            initialiseCodeEditors();
 | 
			
		||||
            settings.update();
 | 
			
		||||
| 
						 | 
				
			
			@ -389,9 +380,6 @@ void OscirenderAudioProcessorEditor::changeListenerCallback(juce::ChangeBroadcas
 | 
			
		|||
        resized();
 | 
			
		||||
        repaint();
 | 
			
		||||
    } else if (source == &audioProcessor.fileChangeBroadcaster) {
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
        juce::SpinLock::ScopedLockType syphonLock(audioProcessor.syphonLock);
 | 
			
		||||
#endif
 | 
			
		||||
        juce::SpinLock::ScopedLockType parsersLock(audioProcessor.parsersLock);
 | 
			
		||||
        // triggered when the audioProcessor changes the current file (e.g. to Blender)
 | 
			
		||||
        settings.fileUpdated(audioProcessor.getCurrentFileName());
 | 
			
		||||
| 
						 | 
				
			
			@ -462,9 +450,6 @@ void OscirenderAudioProcessorEditor::updateCodeDocument() {
 | 
			
		|||
bool OscirenderAudioProcessorEditor::keyPressed(const juce::KeyPress& key) {
 | 
			
		||||
    bool consumeKey = false;
 | 
			
		||||
    {
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
        juce::SpinLock::ScopedLockType lock(audioProcessor.syphonLock);
 | 
			
		||||
#endif
 | 
			
		||||
        juce::SpinLock::ScopedLockType parserLock(audioProcessor.parsersLock);
 | 
			
		||||
        juce::SpinLock::ScopedLockType effectsLock(audioProcessor.effectsLock);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -527,13 +512,12 @@ void OscirenderAudioProcessorEditor::openVisualiserSettings() {
 | 
			
		|||
void OscirenderAudioProcessorEditor::openSyphonInputDialog() {
 | 
			
		||||
    SyphonInputSelectorComponent* selector = nullptr;
 | 
			
		||||
    {
 | 
			
		||||
        juce::SpinLock::ScopedLockType lock(audioProcessor.syphonLock);
 | 
			
		||||
        selector = new SyphonInputSelectorComponent(
 | 
			
		||||
            sharedTextureManager,
 | 
			
		||||
            [this](const juce::String& server, const juce::String& app) { onSyphonInputSelected(server, app); },
 | 
			
		||||
            [this]() { onSyphonInputDisconnected(); },
 | 
			
		||||
            audioProcessor.isSyphonInputActive(),
 | 
			
		||||
            audioProcessor.getSyphonSourceName());
 | 
			
		||||
            [this](const juce::String& server, const juce::String& app) { connectSyphonInput(server, app); },
 | 
			
		||||
            [this]() { disconnectSyphonInput(); },
 | 
			
		||||
            syphonFrameGrabber && syphonFrameGrabber->isActive(),
 | 
			
		||||
            getSyphonSourceName());
 | 
			
		||||
    }
 | 
			
		||||
    juce::DialogWindow::LaunchOptions options;
 | 
			
		||||
    options.content.setOwned(selector);
 | 
			
		||||
| 
						 | 
				
			
			@ -546,13 +530,36 @@ void OscirenderAudioProcessorEditor::openSyphonInputDialog() {
 | 
			
		|||
    options.launchAsync();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OscirenderAudioProcessorEditor::onSyphonInputSelected(const juce::String& server, const juce::String& app) {
 | 
			
		||||
    juce::SpinLock::ScopedLockType lock(audioProcessor.syphonLock);
 | 
			
		||||
    audioProcessor.connectSyphonInput(server, app);
 | 
			
		||||
void OscirenderAudioProcessorEditor::connectSyphonInput(const juce::String& server, const juce::String& app) {
 | 
			
		||||
    juce::SpinLock::ScopedLockType lock(syphonLock);
 | 
			
		||||
    if (!syphonFrameGrabber) {
 | 
			
		||||
        syphonFrameGrabber = std::make_unique<SyphonFrameGrabber>(sharedTextureManager, server, app, audioProcessor.syphonImageParser);
 | 
			
		||||
        audioProcessor.syphonInputActive = true;
 | 
			
		||||
        {
 | 
			
		||||
            juce::MessageManagerLock lock;
 | 
			
		||||
            audioProcessor.fileChangeBroadcaster.sendChangeMessage();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OscirenderAudioProcessorEditor::onSyphonInputDisconnected() {
 | 
			
		||||
    juce::SpinLock::ScopedLockType lock(audioProcessor.syphonLock);
 | 
			
		||||
    audioProcessor.disconnectSyphonInput();
 | 
			
		||||
void OscirenderAudioProcessorEditor::disconnectSyphonInput() {
 | 
			
		||||
    juce::SpinLock::ScopedLockType lock(syphonLock);
 | 
			
		||||
    if (!syphonFrameGrabber) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    audioProcessor.syphonInputActive = false;
 | 
			
		||||
    syphonFrameGrabber.reset();
 | 
			
		||||
    {
 | 
			
		||||
        juce::MessageManagerLock lock;
 | 
			
		||||
        audioProcessor.fileChangeBroadcaster.sendChangeMessage();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
juce::String OscirenderAudioProcessorEditor::getSyphonSourceName() const {
 | 
			
		||||
    juce::SpinLock::ScopedLockType lock(syphonLock);
 | 
			
		||||
    if (syphonFrameGrabber) {
 | 
			
		||||
        return syphonFrameGrabber->getSourceName();
 | 
			
		||||
    }
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,16 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <JuceHeader.h>
 | 
			
		||||
 | 
			
		||||
#include "CommonPluginEditor.h"
 | 
			
		||||
#include "LookAndFeel.h"
 | 
			
		||||
#include "MidiComponent.h"
 | 
			
		||||
#include "PluginProcessor.h"
 | 
			
		||||
#include "SettingsComponent.h"
 | 
			
		||||
#include "MidiComponent.h"
 | 
			
		||||
#include "components/OsciMainMenuBarModel.h"
 | 
			
		||||
#include "LookAndFeel.h"
 | 
			
		||||
#include "components/ErrorCodeEditorComponent.h"
 | 
			
		||||
#include "components/LuaConsole.h"
 | 
			
		||||
#include "components/OsciMainMenuBarModel.h"
 | 
			
		||||
#include "visualiser/VisualiserSettings.h"
 | 
			
		||||
#include "CommonPluginEditor.h"
 | 
			
		||||
 | 
			
		||||
class OscirenderAudioProcessorEditor : public CommonPluginEditor, private juce::CodeDocument::Listener, public juce::AsyncUpdater, public juce::ChangeListener, public juce::FileDragAndDropTarget {
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -18,7 +19,7 @@ public:
 | 
			
		|||
 | 
			
		||||
    void paint(juce::Graphics&) override;
 | 
			
		||||
    void resized() override;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    bool isBinaryFile(juce::String name);
 | 
			
		||||
    void initialiseCodeEditors();
 | 
			
		||||
    void addCodeEditor(int index);
 | 
			
		||||
| 
						 | 
				
			
			@ -37,15 +38,15 @@ private:
 | 
			
		|||
    void registerFileRemovedCallback();
 | 
			
		||||
 | 
			
		||||
    OscirenderAudioProcessor& audioProcessor;
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    const double CLOSED_PREF_SIZE = 30.0;
 | 
			
		||||
    const double RESIZER_BAR_SIZE = 7.0;
 | 
			
		||||
 | 
			
		||||
    std::atomic<bool> editingCustomFunction = false;
 | 
			
		||||
 | 
			
		||||
    SettingsComponent settings{audioProcessor, *this};
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
#if !OSCI_PREMIUM
 | 
			
		||||
    juce::TextButton upgradeButton{"Upgrade to premium!"};
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +63,7 @@ public:
 | 
			
		|||
    juce::CodeEditorComponent::ColourScheme colourScheme;
 | 
			
		||||
    juce::LuaTokeniser luaTokeniser;
 | 
			
		||||
    juce::XmlTokeniser xmlTokeniser;
 | 
			
		||||
	juce::ShapeButton collapseButton;
 | 
			
		||||
    juce::ShapeButton collapseButton;
 | 
			
		||||
    std::shared_ptr<juce::CodeDocument> customFunctionCodeDocument = std::make_shared<juce::CodeDocument>();
 | 
			
		||||
    std::shared_ptr<OscirenderCodeEditorComponent> customFunctionCodeEditor = std::make_shared<OscirenderCodeEditorComponent>(*customFunctionCodeDocument, &luaTokeniser, audioProcessor, CustomEffect::UNIQUE_ID, CustomEffect::FILE_NAME);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -76,8 +77,8 @@ public:
 | 
			
		|||
 | 
			
		||||
    std::atomic<bool> updatingDocumentsWithParserLock = false;
 | 
			
		||||
 | 
			
		||||
	void codeDocumentTextInserted(const juce::String& newText, int insertIndex) override;
 | 
			
		||||
	void codeDocumentTextDeleted(int startIndex, int endIndex) override;
 | 
			
		||||
    void codeDocumentTextInserted(const juce::String& newText, int insertIndex) override;
 | 
			
		||||
    void codeDocumentTextDeleted(int startIndex, int endIndex) override;
 | 
			
		||||
    void updateCodeDocument();
 | 
			
		||||
    void updateCodeEditor(bool binaryFile, bool shouldOpenEditor = false);
 | 
			
		||||
    void setCodeEditorVisible(std::optional<bool> visible);
 | 
			
		||||
| 
						 | 
				
			
			@ -86,10 +87,16 @@ public:
 | 
			
		|||
    void mouseDown(const juce::MouseEvent& event) override;
 | 
			
		||||
    void mouseMove(const juce::MouseEvent& event) override;
 | 
			
		||||
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
    // Syphon/Spout input dialog
 | 
			
		||||
    void openSyphonInputDialog();
 | 
			
		||||
    void onSyphonInputSelected(const juce::String& server, const juce::String& app);
 | 
			
		||||
    void onSyphonInputDisconnected();
 | 
			
		||||
    void connectSyphonInput(const juce::String& server, const juce::String& app);
 | 
			
		||||
    void disconnectSyphonInput();
 | 
			
		||||
    juce::String getSyphonSourceName() const;
 | 
			
		||||
 | 
			
		||||
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OscirenderAudioProcessorEditor)
 | 
			
		||||
    juce::SpinLock syphonLock;
 | 
			
		||||
    std::unique_ptr<SyphonFrameGrabber> syphonFrameGrabber;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(OscirenderAudioProcessorEditor)
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -505,8 +505,7 @@ void OscirenderAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, ju
 | 
			
		|||
 | 
			
		||||
    {
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
        juce::SpinLock::ScopedLockType sLock(syphonLock);
 | 
			
		||||
        if (isSyphonInputActive()) {
 | 
			
		||||
        if (syphonInputActive) {
 | 
			
		||||
            for (int sample = 0; sample < outputBuffer3d.getNumSamples(); sample++) {
 | 
			
		||||
                osci::Point point = syphonImageParser.getSample();
 | 
			
		||||
                outputBuffer3d.setSample(0, sample, point.x);
 | 
			
		||||
| 
						 | 
				
			
			@ -514,7 +513,7 @@ void OscirenderAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, ju
 | 
			
		|||
            }
 | 
			
		||||
        } else
 | 
			
		||||
#endif
 | 
			
		||||
        if (usingInput && totalNumInputChannels >= 1) {
 | 
			
		||||
            if (usingInput && totalNumInputChannels >= 1) {
 | 
			
		||||
            if (totalNumInputChannels >= 2) {
 | 
			
		||||
                for (auto channel = 0; channel < juce::jmin(2, totalNumInputChannels); channel++) {
 | 
			
		||||
                    outputBuffer3d.copyFrom(channel, 0, inputBuffer, channel, 0, buffer.getNumSamples());
 | 
			
		||||
| 
						 | 
				
			
			@ -898,49 +897,6 @@ void OscirenderAudioProcessor::envelopeChanged(EnvelopeComponent* changedEnvelop
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
// Syphon/Spout input management
 | 
			
		||||
 | 
			
		||||
// syphonLock must be held when calling this function
 | 
			
		||||
bool OscirenderAudioProcessor::isSyphonInputActive() const {
 | 
			
		||||
    return syphonFrameGrabber != nullptr && syphonFrameGrabber->isActive();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// syphonLock must be held when calling this function
 | 
			
		||||
bool OscirenderAudioProcessor::isSyphonInputStarted() const {
 | 
			
		||||
    return syphonFrameGrabber != nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// syphonLock must be held when calling this function
 | 
			
		||||
void OscirenderAudioProcessor::connectSyphonInput(const juce::String& server, const juce::String& app) {
 | 
			
		||||
    auto editor = dynamic_cast<OscirenderAudioProcessorEditor*>(getActiveEditor());
 | 
			
		||||
    if (!syphonFrameGrabber && editor) {
 | 
			
		||||
        syphonFrameGrabber = std::make_unique<SyphonFrameGrabber>(editor->sharedTextureManager, server, app, syphonImageParser);
 | 
			
		||||
        {
 | 
			
		||||
            juce::MessageManagerLock lock;
 | 
			
		||||
            fileChangeBroadcaster.sendChangeMessage();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// syphonLock must be held when calling this function
 | 
			
		||||
void OscirenderAudioProcessor::disconnectSyphonInput() {
 | 
			
		||||
    syphonFrameGrabber.reset();
 | 
			
		||||
    {
 | 
			
		||||
        juce::MessageManagerLock lock;
 | 
			
		||||
        fileChangeBroadcaster.sendChangeMessage();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// syphonLock must be held when calling this function
 | 
			
		||||
juce::String OscirenderAudioProcessor::getSyphonSourceName() const {
 | 
			
		||||
    if (syphonFrameGrabber) {
 | 
			
		||||
        return syphonFrameGrabber->getSourceName();
 | 
			
		||||
    }
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() {
 | 
			
		||||
    return new OscirenderAudioProcessor();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -282,19 +282,12 @@ private:
 | 
			
		|||
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
public:
 | 
			
		||||
    bool isSyphonInputActive() const;
 | 
			
		||||
    bool isSyphonInputStarted() const;
 | 
			
		||||
    void connectSyphonInput(const juce::String& server, const juce::String& app);
 | 
			
		||||
    void disconnectSyphonInput();
 | 
			
		||||
    juce::String getSyphonSourceName() const;
 | 
			
		||||
    std::atomic<bool> syphonInputActive = false;
 | 
			
		||||
 | 
			
		||||
    juce::SpinLock syphonLock;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    ImageParser syphonImageParser = ImageParser(*this);
 | 
			
		||||
    std::unique_ptr<SyphonFrameGrabber> syphonFrameGrabber;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(OscirenderAudioProcessor)
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,7 +84,7 @@ void SettingsComponent::fileUpdated(juce::String fileName) {
 | 
			
		|||
    // Check if the file is an image based on extension or Syphon/Spout input
 | 
			
		||||
    bool isSyphonActive = false;
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
    isSyphonActive = audioProcessor.isSyphonInputStarted();
 | 
			
		||||
    isSyphonActive = audioProcessor.syphonInputActive;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    bool isImage = isSyphonActive ||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,11 +64,12 @@ OsciMainMenuBarModel::OsciMainMenuBarModel(OscirenderAudioProcessor& p, Oscirend
 | 
			
		|||
 | 
			
		||||
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM
 | 
			
		||||
    // Add Syphon/Spout input menu item under Recording
 | 
			
		||||
    addMenuItem(2, audioProcessor.isSyphonInputActive() ? "Disconnect Syphon/Spout Input" : "Select Syphon/Spout Input...", [this] {
 | 
			
		||||
        if (audioProcessor.isSyphonInputActive())
 | 
			
		||||
            disconnectSyphonInput();
 | 
			
		||||
        else
 | 
			
		||||
    addMenuItem(2, audioProcessor.syphonInputActive ? "Disconnect Syphon/Spout Input" : "Select Syphon/Spout Input...", [this] {
 | 
			
		||||
        if (audioProcessor.syphonInputActive) {
 | 
			
		||||
            editor.disconnectSyphonInput();
 | 
			
		||||
        } else {
 | 
			
		||||
            openSyphonInputDialog();
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,8 +84,4 @@ OsciMainMenuBarModel::OsciMainMenuBarModel(OscirenderAudioProcessor& p, Oscirend
 | 
			
		|||
void OsciMainMenuBarModel::openSyphonInputDialog() {
 | 
			
		||||
    editor.openSyphonInputDialog();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OsciMainMenuBarModel::disconnectSyphonInput() {
 | 
			
		||||
    audioProcessor.disconnectSyphonInput();
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@
 | 
			
		|||
 | 
			
		||||
class SyphonFrameGrabber : private juce::Thread, public juce::Component {
 | 
			
		||||
public:
 | 
			
		||||
    SyphonFrameGrabber(SharedTextureManager& manager, juce::String server, juce::String app, ImageParser& parser, int pollMs = 16)
 | 
			
		||||
    SyphonFrameGrabber(SharedTextureManager& manager, juce::String server, juce::String app, ImageParser& parser, int pollMs = 8)
 | 
			
		||||
        : juce::Thread("SyphonFrameGrabber"), pollIntervalMs(pollMs), manager(manager), parser(parser) {
 | 
			
		||||
        // Create the invisible OpenGL context component
 | 
			
		||||
        glContextComponent = std::make_unique<InvisibleOpenGLContextComponent>();
 | 
			
		||||
| 
						 | 
				
			
			@ -30,6 +30,8 @@ public:
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    ~SyphonFrameGrabber() override {
 | 
			
		||||
        juce::CriticalSection::ScopedLockType lock(openGLLock);
 | 
			
		||||
 | 
			
		||||
        stopThread(500);
 | 
			
		||||
        if (receiver) {
 | 
			
		||||
            manager.removeReceiver(receiver);
 | 
			
		||||
| 
						 | 
				
			
			@ -41,6 +43,8 @@ public:
 | 
			
		|||
    void run() override {
 | 
			
		||||
        while (!threadShouldExit()) {
 | 
			
		||||
            {
 | 
			
		||||
                juce::CriticalSection::ScopedLockType lock(openGLLock);
 | 
			
		||||
 | 
			
		||||
                bool activated = false;
 | 
			
		||||
                if (glContextComponent) {
 | 
			
		||||
                    activated = glContextComponent->getContext().makeActive();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@
 | 
			
		|||
              addUsingNamespaceToJuceHeader="0" jucerFormatVersion="1" pluginCharacteristicsValue="pluginWantsMidiIn"
 | 
			
		||||
              pluginManufacturer="jameshball" aaxIdentifier="sh.ball.oscirender"
 | 
			
		||||
              cppLanguageStandard="20" projectLineFeed="
" headerPath="./include"
 | 
			
		||||
              version="2.5.0.0" companyName="James H Ball" companyWebsite="https://osci-render.com"
 | 
			
		||||
              version="2.5.0.1" companyName="James H Ball" companyWebsite="https://osci-render.com"
 | 
			
		||||
              companyEmail="james@ball.sh" defines="NOMINMAX=1
INTERNET_FLAG_NO_AUTO_REDIRECT=0
OSCI_PREMIUM=1
JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1
JUCE_MODAL_LOOPS_PERMITTED=1"
 | 
			
		||||
              pluginAUMainType="'aumf'">
 | 
			
		||||
  <MAINGROUP id="j5Ge2T" name="osci-render">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue