Add fullscreen mode to sosci and rename screen type to screen overlay

pre-release-3
James H Ball 2025-01-07 18:28:55 +00:00
rodzic e9a92f1c9d
commit 8cedb4f55c
8 zmienionych plików z 97 dodań i 73 usunięć

Wyświetl plik

@ -135,8 +135,6 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
} else if (mode == FullScreenMode::MAIN_COMPONENT) {
visualiserFullScreen->setBoolValueNotifyingHost(false);
}
pluginEditor.visualiser.setFullScreen(visualiserFullScreen->getBoolValue());
pluginEditor.resized();
pluginEditor.repaint();

Wyświetl plik

@ -7,6 +7,24 @@ SosciPluginEditor::SosciPluginEditor(SosciAudioProcessor& p) : CommonPluginEdito
addAndMakeVisible(volume);
addAndMakeVisible(visualiserSettingsWrapper);
BooleanParameter* visualiserFullScreen = audioProcessor.visualiserParameters.visualiserFullScreen;
visualiserFullScreenChanged();
visualiser.setFullScreenCallback([this, visualiserFullScreen](FullScreenMode mode) {
if (mode == FullScreenMode::TOGGLE) {
visualiserFullScreen->setBoolValueNotifyingHost(!visualiserFullScreen->getBoolValue());
} else if (mode == FullScreenMode::FULL_SCREEN) {
visualiserFullScreen->setBoolValueNotifyingHost(true);
} else if (mode == FullScreenMode::MAIN_COMPONENT) {
visualiserFullScreen->setBoolValueNotifyingHost(false);
}
visualiserFullScreenChanged();
resized();
repaint();
});
resized();
}
@ -21,19 +39,23 @@ void SosciPluginEditor::paint(juce::Graphics& g) {
void SosciPluginEditor::resized() {
auto area = getLocalBounds();
menuBar.setBounds(area.removeFromTop(25));
if (audioProcessor.visualiserParameters.visualiserFullScreen->getBoolValue()) {
visualiser.setBounds(area);
} else {
menuBar.setBounds(area.removeFromTop(25));
auto volumeArea = area.removeFromLeft(30);
volume.setBounds(volumeArea.withSizeKeepingCentre(volumeArea.getWidth(), juce::jmin(volumeArea.getHeight(), 300)));
auto volumeArea = area.removeFromLeft(30);
volume.setBounds(volumeArea.withSizeKeepingCentre(volumeArea.getWidth(), juce::jmin(volumeArea.getHeight(), 300)));
auto settingsArea = area.removeFromRight(juce::jmax(juce::jmin(0.4 * getWidth(), 550.0), 350.0));
visualiserSettings.setSize(settingsArea.getWidth(), 550);
visualiserSettingsWrapper.setBounds(settingsArea);
auto settingsArea = area.removeFromRight(juce::jmax(juce::jmin(0.4 * getWidth(), 550.0), 350.0));
visualiserSettings.setSize(settingsArea.getWidth(), 550);
visualiserSettingsWrapper.setBounds(settingsArea);
if (area.getWidth() < 10 || area.getHeight() < 10) {
return;
if (area.getWidth() < 10 || area.getHeight() < 10) {
return;
}
visualiser.setBounds(area);
}
visualiser.setBounds(area);
}
bool SosciPluginEditor::isInterestedInFileDrag(const juce::StringArray& files) {
@ -56,3 +78,11 @@ void SosciPluginEditor::filesDropped(const juce::StringArray& files, int x, int
juce::File file(files[0]);
audioProcessor.loadAudioFile(file);
}
void SosciPluginEditor::visualiserFullScreenChanged() {
bool fullScreen = audioProcessor.visualiserParameters.visualiserFullScreen->getBoolValue();
volume.setVisible(!fullScreen);
visualiserSettingsWrapper.setVisible(!fullScreen);
menuBar.setVisible(!fullScreen);
}

Wyświetl plik

@ -18,6 +18,7 @@ public:
void resized() override;
bool isInterestedInFileDrag(const juce::StringArray& files) override;
void filesDropped(const juce::StringArray& files, int x, int y) override;
void visualiserFullScreenChanged();
private:
SosciAudioProcessor& audioProcessor;

Wyświetl plik

@ -9,7 +9,7 @@ uniform float uSize;
uniform float uIntensity;
uniform vec2 uOffset;
uniform vec2 uScale;
uniform float uScreenType;
uniform float uScreenOverlay;
uniform float uFishEye;
uniform sampler2D uScreen;
varying float vSize;

Wyświetl plik

@ -74,7 +74,7 @@ VisualiserComponent::VisualiserComponent(
setMouseCursor(juce::MouseCursor::PointingHandCursor);
setWantsKeyboardFocus(true);
if (parent == nullptr && !visualiserOnly) {
if (parent == nullptr) {
addAndMakeVisible(fullScreenButton);
fullScreenButton.setTooltip("Toggles fullscreen mode.");
}
@ -116,8 +116,6 @@ VisualiserComponent::VisualiserComponent(
};
addAndMakeVisible(audioPlayer);
setFullScreen(false);
openGLContext.setRenderer(this);
openGLContext.attachTo(*this);
@ -283,8 +281,6 @@ bool VisualiserComponent::keyPressed(const juce::KeyPress& key) {
return false;
}
void VisualiserComponent::setFullScreen(bool fullScreen) {}
void VisualiserComponent::setRecording(bool recording) {
stopwatch.stop();
stopwatch.reset();
@ -418,7 +414,7 @@ void VisualiserComponent::resized() {
auto area = getLocalBounds();
buttonRow = area.removeFromBottom(25);
auto buttons = buttonRow;
if (parent == nullptr && !visualiserOnly) {
if (parent == nullptr) {
fullScreenButton.setBounds(buttons.removeFromRight(30));
}
if (child == nullptr && parent == nullptr && !visualiserOnly) {
@ -948,8 +944,8 @@ void VisualiserComponent::drawLine(const std::vector<float>& xPoints, const std:
setOffsetAndScale(lineShader.get());
#if SOSCI_FEATURES
lineShader->setUniform("uScreenType", (GLfloat) screenType);
lineShader->setUniform("uFishEye", screenType == ScreenType::VectorDisplay ? VECTOR_DISPLAY_FISH_EYE : 0.0f);
lineShader->setUniform("uScreenOverlay", (GLfloat) screenOverlay);
lineShader->setUniform("uFishEye", screenOverlay == ScreenOverlay::VectorDisplay ? VECTOR_DISPLAY_FISH_EYE : 0.0f);
#endif
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
@ -1017,7 +1013,7 @@ void VisualiserComponent::drawCRT() {
drawTexture({blur4Texture});
#if SOSCI_FEATURES
if (settings.parameters.screenType->isRealisticDisplay()) {
if (settings.parameters.screenOverlay->isRealisticDisplay()) {
// create glow texture
activateTargetTexture(glowTexture);
setShader(glowShader.get());
@ -1037,8 +1033,8 @@ void VisualiserComponent::drawCRT() {
outputShader->setUniform("uAmbient", (float) settings.getAmbient());
setOffsetAndScale(outputShader.get());
#if SOSCI_FEATURES
outputShader->setUniform("uFishEye", screenType == ScreenType::VectorDisplay ? VECTOR_DISPLAY_FISH_EYE : 0.0f);
outputShader->setUniform("uRealScreen", settings.parameters.screenType->isRealisticDisplay() ? 1.0f : 0.0f);
outputShader->setUniform("uFishEye", screenOverlay == ScreenOverlay::VectorDisplay ? VECTOR_DISPLAY_FISH_EYE : 0.0f);
outputShader->setUniform("uRealScreen", settings.parameters.screenOverlay->isRealisticDisplay() ? 1.0f : 0.0f);
#endif
outputShader->setUniform("uResizeForCanvas", lineTexture.width / 1024.0f);
juce::Colour colour = juce::Colour::fromHSV(settings.getHue() / 360.0f, 1.0, 1.0, 1.0);
@ -1059,10 +1055,10 @@ void VisualiserComponent::setOffsetAndScale(juce::OpenGLShaderProgram* shader) {
OsciPoint offset;
OsciPoint scale = { 1.0f };
#if SOSCI_FEATURES
if (settings.getScreenType() == ScreenType::Real) {
if (settings.getScreenOverlay() == ScreenOverlay::Real) {
offset = REAL_SCREEN_OFFSET;
scale = REAL_SCREEN_SCALE;
} else if (settings.getScreenType() == ScreenType::VectorDisplay) {
} else if (settings.getScreenOverlay() == ScreenOverlay::VectorDisplay) {
offset = VECTOR_DISPLAY_OFFSET;
scale = VECTOR_DISPLAY_SCALE;
}
@ -1075,9 +1071,9 @@ void VisualiserComponent::setOffsetAndScale(juce::OpenGLShaderProgram* shader) {
Texture VisualiserComponent::createReflectionTexture() {
using namespace juce::gl;
if (settings.getScreenType() == ScreenType::VectorDisplay) {
if (settings.getScreenOverlay() == ScreenOverlay::VectorDisplay) {
reflectionOpenGLTexture.loadImage(vectorDisplayReflectionImage);
} else if (settings.getScreenType() == ScreenType::Real) {
} else if (settings.getScreenOverlay() == ScreenOverlay::Real) {
reflectionOpenGLTexture.loadImage(oscilloscopeReflectionImage);
} else {
reflectionOpenGLTexture.loadImage(emptyReflectionImage);
@ -1092,12 +1088,12 @@ Texture VisualiserComponent::createReflectionTexture() {
Texture VisualiserComponent::createScreenTexture() {
using namespace juce::gl;
if (screenType == ScreenType::Smudged || screenType == ScreenType::SmudgedGraticule) {
if (screenOverlay == ScreenOverlay::Smudged || screenOverlay == ScreenOverlay::SmudgedGraticule) {
screenOpenGLTexture.loadImage(screenTextureImage);
#if SOSCI_FEATURES
} else if (screenType == ScreenType::Real) {
} else if (screenOverlay == ScreenOverlay::Real) {
screenOpenGLTexture.loadImage(oscilloscopeImage);
} else if (screenType == ScreenType::VectorDisplay) {
} else if (screenOverlay == ScreenOverlay::VectorDisplay) {
screenOpenGLTexture.loadImage(vectorDisplayImage);
#endif
} else {
@ -1105,7 +1101,7 @@ Texture VisualiserComponent::createScreenTexture() {
}
Texture texture = { screenOpenGLTexture.getTextureID(), screenTextureImage.getWidth(), screenTextureImage.getHeight() };
if (screenType == ScreenType::Graticule || screenType == ScreenType::SmudgedGraticule) {
if (screenOverlay == ScreenOverlay::Graticule || screenOverlay == ScreenOverlay::SmudgedGraticule) {
activateTargetTexture(texture);
setNormalBlending();
setShader(simpleShader.get());
@ -1201,8 +1197,8 @@ void VisualiserComponent::paint(juce::Graphics& g) {
}
void VisualiserComponent::renderScope(const std::vector<float>& xPoints, const std::vector<float>& yPoints, const std::vector<float>& zPoints) {
if (screenType != settings.getScreenType()) {
screenType = settings.getScreenType();
if (screenOverlay != settings.getScreenOverlay()) {
screenOverlay = settings.getScreenOverlay();
#if SOSCI_FEATURES
reflectionTexture = createReflectionTexture();
#endif

Wyświetl plik

@ -66,7 +66,6 @@ public:
void newOpenGLContextCreated() override;
void renderOpenGL() override;
void openGLContextClosing() override;
void setFullScreen(bool fullScreen);
void setRecording(bool recording);
void childUpdated();
@ -229,7 +228,7 @@ private:
juce::OpenGLShaderProgram* currentShader;
float fadeAmount;
ScreenType screenType = settings.getScreenType();
ScreenOverlay screenOverlay = settings.getScreenOverlay();
const double RESAMPLE_RATIO = 6.0;
double sampleRate = -1;

Wyświetl plik

@ -18,15 +18,15 @@ VisualiserSettings::VisualiserSettings(VisualiserParameters& p, int numChannels)
addAndMakeVisible(triggerValue);
addAndMakeVisible(upsamplingToggle);
addAndMakeVisible(sweepToggle);
addAndMakeVisible(screenTypeLabel);
addAndMakeVisible(screenType);
addAndMakeVisible(screenOverlayLabel);
addAndMakeVisible(screenOverlay);
for (int i = 1; i <= parameters.screenType->max; i++) {
screenType.addItem(parameters.screenType->getText(parameters.screenType->getNormalisedValue(i)), i);
for (int i = 1; i <= parameters.screenOverlay->max; i++) {
screenOverlay.addItem(parameters.screenOverlay->getText(parameters.screenOverlay->getNormalisedValue(i)), i);
}
screenType.setSelectedId(parameters.screenType->getValueUnnormalised());
screenType.onChange = [this] {
parameters.screenType->setUnnormalisedValueNotifyingHost(screenType.getSelectedId());
screenOverlay.setSelectedId(parameters.screenOverlay->getValueUnnormalised());
screenOverlay.onChange = [this] {
parameters.screenOverlay->setUnnormalisedValueNotifyingHost(screenOverlay.getSelectedId());
};
intensity.setSliderOnValueChange();
@ -64,10 +64,10 @@ void VisualiserSettings::resized() {
auto area = getLocalBounds().reduced(20, 0).withTrimmedBottom(20);
double rowHeight = 30;
auto screenTypeArea = area.removeFromTop(2 * rowHeight);
screenTypeArea = screenTypeArea.withSizeKeepingCentre(300, rowHeight);
screenTypeLabel.setBounds(screenTypeArea.removeFromLeft(120));
screenType.setBounds(screenTypeArea.removeFromRight(180));
auto screenOverlayArea = area.removeFromTop(2 * rowHeight);
screenOverlayArea = screenOverlayArea.withSizeKeepingCentre(300, rowHeight);
screenOverlayLabel.setBounds(screenOverlayArea.removeFromLeft(120));
screenOverlay.setBounds(screenOverlayArea.removeFromRight(180));
intensity.setBounds(area.removeFromTop(rowHeight));
persistence.setBounds(area.removeFromTop(rowHeight));

Wyświetl plik

@ -9,7 +9,7 @@
#include "../components/SwitchButton.h"
#include "../audio/SmoothEffect.h"
enum class ScreenType : int {
enum class ScreenOverlay : int {
Empty = 1,
Graticule = 2,
Smudged = 3,
@ -23,24 +23,24 @@ enum class ScreenType : int {
#endif
};
class ScreenTypeParameter : public IntParameter {
class ScreenOverlayParameter : public IntParameter {
public:
ScreenTypeParameter(juce::String name, juce::String id, int versionHint, ScreenType value) : IntParameter(name, id, versionHint, (int) value, 1, (int)ScreenType::MAX) {}
ScreenOverlayParameter(juce::String name, juce::String id, int versionHint, ScreenOverlay value) : IntParameter(name, id, versionHint, (int) value, 1, (int)ScreenOverlay::MAX) {}
juce::String getText(float value, int maximumStringLength = 100) const override {
switch ((ScreenType)(int)getUnnormalisedValue(value)) {
case ScreenType::Empty:
switch ((ScreenOverlay)(int)getUnnormalisedValue(value)) {
case ScreenOverlay::Empty:
return "Empty";
case ScreenType::Graticule:
case ScreenOverlay::Graticule:
return "Graticule";
case ScreenType::Smudged:
case ScreenOverlay::Smudged:
return "Smudged";
case ScreenType::SmudgedGraticule:
case ScreenOverlay::SmudgedGraticule:
return "Smudged Graticule";
#if SOSCI_FEATURES
case ScreenType::Real:
case ScreenOverlay::Real:
return "Real Oscilloscope";
case ScreenType::VectorDisplay:
case ScreenOverlay::VectorDisplay:
return "Vector Display";
#endif
default:
@ -51,44 +51,44 @@ public:
float getValueForText(const juce::String& text) const override {
int unnormalisedValue;
if (text == "Empty") {
unnormalisedValue = (int)ScreenType::Empty;
unnormalisedValue = (int)ScreenOverlay::Empty;
} else if (text == "Graticule") {
unnormalisedValue = (int)ScreenType::Graticule;
unnormalisedValue = (int)ScreenOverlay::Graticule;
} else if (text == "Smudged") {
unnormalisedValue = (int)ScreenType::Smudged;
unnormalisedValue = (int)ScreenOverlay::Smudged;
} else if (text == "Smudged Graticule") {
unnormalisedValue = (int)ScreenType::SmudgedGraticule;
unnormalisedValue = (int)ScreenOverlay::SmudgedGraticule;
#if SOSCI_FEATURES
} else if (text == "Real Oscilloscope") {
unnormalisedValue = (int)ScreenType::Real;
unnormalisedValue = (int)ScreenOverlay::Real;
} else if (text == "Vector Display") {
unnormalisedValue = (int)ScreenType::VectorDisplay;
unnormalisedValue = (int)ScreenOverlay::VectorDisplay;
#endif
} else {
unnormalisedValue = (int)ScreenType::Empty;
unnormalisedValue = (int)ScreenOverlay::Empty;
}
return getNormalisedValue(unnormalisedValue);
}
void save(juce::XmlElement* xml) {
xml->setAttribute("screenType", getText(getValue()));
xml->setAttribute("screenOverlay", getText(getValue()));
}
void load(juce::XmlElement* xml) {
setValueNotifyingHost(getValueForText(xml->getStringAttribute("screenType")));
setValueNotifyingHost(getValueForText(xml->getStringAttribute("screenOverlay")));
}
#if SOSCI_FEATURES
bool isRealisticDisplay() {
ScreenType type = (ScreenType)(int)getValueUnnormalised();
return type == ScreenType::Real || type == ScreenType::VectorDisplay;
ScreenOverlay type = (ScreenOverlay)(int)getValueUnnormalised();
return type == ScreenOverlay::Real || type == ScreenOverlay::VectorDisplay;
}
#endif
};
class VisualiserParameters {
public:
ScreenTypeParameter* screenType = new ScreenTypeParameter("Screen Type", "screenType", VERSION_HINT, ScreenType::SmudgedGraticule);
ScreenOverlayParameter* screenOverlay = new ScreenOverlayParameter("Screen Overlay", "screenOverlay", VERSION_HINT, ScreenOverlay::SmudgedGraticule);
BooleanParameter* upsamplingEnabled = new BooleanParameter("Upsample Audio", "upsamplingEnabled", VERSION_HINT, true, "Upsamples the audio before visualising it to make it appear more realistic, at the expense of performance.");
BooleanParameter* sweepEnabled = new BooleanParameter("Sweep", "sweepEnabled", VERSION_HINT, false, "Plots the audio signal over time, sweeping from left to right");
BooleanParameter* visualiserFullScreen = new BooleanParameter("Visualiser Fullscreen", "visualiserFullScreen", VERSION_HINT, false, "Makes the software visualiser fullscreen.");
@ -193,7 +193,7 @@ public:
std::vector<std::shared_ptr<Effect>> effects = {persistenceEffect, hueEffect, intensityEffect, lineSaturationEffect, screenSaturationEffect, focusEffect, noiseEffect, glowEffect, ambientEffect, sweepMsEffect, triggerValueEffect};
std::vector<BooleanParameter*> booleans = {upsamplingEnabled, visualiserFullScreen, sweepEnabled};
std::vector<IntParameter*> integers = {screenType};
std::vector<IntParameter*> integers = {screenOverlay};
};
class VisualiserSettings : public juce::Component {
@ -240,8 +240,8 @@ public:
return parameters.ambientEffect->getActualValue();
}
ScreenType getScreenType() {
return (ScreenType)parameters.screenType->getValueUnnormalised();
ScreenOverlay getScreenOverlay() {
return (ScreenOverlay)parameters.screenOverlay->getValueUnnormalised();
}
bool getUpsamplingEnabled() {
@ -277,8 +277,8 @@ private:
EffectComponent sweepMs{*parameters.sweepMsEffect};
EffectComponent triggerValue{*parameters.triggerValueEffect};
juce::Label screenTypeLabel{"Screen Type", "Screen Type"};
juce::ComboBox screenType;
juce::Label screenOverlayLabel{"Screen Overlay", "Screen Overlay"};
juce::ComboBox screenOverlay;
jux::SwitchButton upsamplingToggle{parameters.upsamplingEnabled};
jux::SwitchButton sweepToggle{parameters.sweepEnabled};