kopia lustrzana https://github.com/jameshball/osci-render
Add support for recording oscilloscope visualiser
rodzic
925f2a7b80
commit
f30ac1823e
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: Sans-Serif;
|
font-family: Sans-Serif;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
@ -73,6 +73,10 @@
|
||||||
filter: brightness(50%);
|
filter: brightness(50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#download {
|
||||||
|
background: url(download.svg) no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
#fullscreen {
|
#fullscreen {
|
||||||
background: url(fullscreen.svg) no-repeat;
|
background: url(fullscreen.svg) no-repeat;
|
||||||
}
|
}
|
||||||
|
@ -84,18 +88,19 @@
|
||||||
#settings {
|
#settings {
|
||||||
background: url(cog.svg) no-repeat;
|
background: url(cog.svg) no-repeat;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body bgcolor="black" text="white" autocomplete="off" style="margin: 0px;">
|
<body bgcolor="black" text="white" autocomplete="off" style="margin: 0px;">
|
||||||
|
|
||||||
<div id="buttonRow">
|
<div id="buttonRow">
|
||||||
|
<button onClick="toggleRecording()" id="download"/>
|
||||||
<button id="fullscreen"/>
|
<button id="fullscreen"/>
|
||||||
<button id="popout"/>
|
<button id="popout"/>
|
||||||
<button id="settings"/>
|
<button id="settings"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var controls=
|
var controls=
|
||||||
{
|
{
|
||||||
swapXY : false,
|
swapXY : false,
|
||||||
|
@ -132,10 +137,38 @@
|
||||||
let openInAnotherWindow = false;
|
let openInAnotherWindow = false;
|
||||||
let externalSampleRate = 96000;
|
let externalSampleRate = 96000;
|
||||||
let externalBufferSize = 1920;
|
let externalBufferSize = 1920;
|
||||||
|
let recording = false;
|
||||||
|
let mediaRecorder = undefined;
|
||||||
|
let downloadCallback = undefined;
|
||||||
|
|
||||||
</script>
|
const toggleRecording = () => {
|
||||||
|
recording = !recording;
|
||||||
|
if (recording) {
|
||||||
|
const canvas = document.getElementById("crtCanvas");
|
||||||
|
const data = [];
|
||||||
|
const stream = canvas.captureStream(60);
|
||||||
|
mediaRecorder = new MediaRecorder(stream);
|
||||||
|
mediaRecorder.ondataavailable = (e) => data.push(e.data);
|
||||||
|
mediaRecorder.onstop = (e) => {
|
||||||
|
const div = document.getElementById("buttonRow");
|
||||||
|
var a = document.createElement("a");
|
||||||
|
const video = new Blob(data, { type: "video/webm;codecs=h264" });
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.readAsDataURL(video);
|
||||||
|
reader.onloadend = function() {
|
||||||
|
var dataUrl = reader.result;
|
||||||
|
var base64 = dataUrl.split(',')[1];
|
||||||
|
downloadCallback(base64);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mediaRecorder.start();
|
||||||
|
} else {
|
||||||
|
mediaRecorder.stop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import * as Juce from "./index.js";
|
import * as Juce from "./index.js";
|
||||||
|
|
||||||
const fullscreen = document.getElementById('fullscreen');
|
const fullscreen = document.getElementById('fullscreen');
|
||||||
|
@ -201,37 +234,45 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window.__JUCE__.backend.addEventListener("toggleRecording", hasChild => {
|
||||||
|
toggleRecording();
|
||||||
|
});
|
||||||
|
|
||||||
document.addEventListener("dblclick", function() {
|
document.addEventListener("dblclick", function() {
|
||||||
toggleFullscreen();
|
toggleFullscreen();
|
||||||
});
|
});
|
||||||
</script>
|
|
||||||
|
|
||||||
<div id="mainScreen">
|
downloadCallback = (base64) => {
|
||||||
|
Juce.getNativeFunction("downloadVideo")(base64);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="mainScreen">
|
||||||
<div id="overlay">Paused</div>
|
<div id="overlay">Paused</div>
|
||||||
<canvas id="crtCanvas" width="800" height="800"></canvas>
|
<canvas id="crtCanvas" width="800" height="800"></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script id="vertex" type="x-shader">
|
<script id="vertex" type="x-shader">
|
||||||
attribute vec2 vertexPosition;
|
attribute vec2 vertexPosition;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = vec4(vertexPosition, 0.0, 1.0);
|
gl_Position = vec4(vertexPosition, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id="fragment" type="x-shader">
|
<script id="fragment" type="x-shader">
|
||||||
precision highp float;
|
precision highp float;
|
||||||
uniform vec4 colour;
|
uniform vec4 colour;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_FragColor = colour;
|
gl_FragColor = colour;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- The Gaussian line-drawing code, the next two shaders, is adapted
|
<!-- The Gaussian line-drawing code, the next two shaders, is adapted
|
||||||
from woscope by e1ml : https://github.com/m1el/woscope -->
|
from woscope by e1ml : https://github.com/m1el/woscope -->
|
||||||
|
|
||||||
<script id="gaussianVertex" type="x-shader">
|
<script id="gaussianVertex" type="x-shader">
|
||||||
#define EPS 1E-6
|
#define EPS 1E-6
|
||||||
uniform float uInvert;
|
uniform float uInvert;
|
||||||
uniform float uSize;
|
uniform float uSize;
|
||||||
|
@ -298,9 +339,9 @@
|
||||||
//seed = mod(sin(seed*seed), 7.0);
|
//seed = mod(sin(seed*seed), 7.0);
|
||||||
//if (mod(seed/2.0, 1.0)<0.5) gl_Position = vec4(10.0);
|
//if (mod(seed/2.0, 1.0)<0.5) gl_Position = vec4(10.0);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id="gaussianFragment" type="x-shader">
|
<script id="gaussianFragment" type="x-shader">
|
||||||
#define EPS 1E-6
|
#define EPS 1E-6
|
||||||
#define TAU 6.283185307179586
|
#define TAU 6.283185307179586
|
||||||
#define TAUR 2.5066282746310002
|
#define TAUR 2.5066282746310002
|
||||||
|
@ -351,9 +392,9 @@
|
||||||
gl_FragColor = 2.0 * texture2D(uScreen, vTexCoord) * brightness;
|
gl_FragColor = 2.0 * texture2D(uScreen, vTexCoord) * brightness;
|
||||||
gl_FragColor.a = 1.0;
|
gl_FragColor.a = 1.0;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id="texturedVertex" type="x-shader">
|
<script id="texturedVertex" type="x-shader">
|
||||||
precision highp float;
|
precision highp float;
|
||||||
attribute vec2 aPos;
|
attribute vec2 aPos;
|
||||||
varying vec2 vTexCoord;
|
varying vec2 vTexCoord;
|
||||||
|
@ -362,9 +403,9 @@
|
||||||
gl_Position = vec4(aPos, 0.0, 1.0);
|
gl_Position = vec4(aPos, 0.0, 1.0);
|
||||||
vTexCoord = (0.5*aPos+0.5);
|
vTexCoord = (0.5*aPos+0.5);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id="texturedVertexWithResize" type="x-shader">
|
<script id="texturedVertexWithResize" type="x-shader">
|
||||||
precision highp float;
|
precision highp float;
|
||||||
attribute vec2 aPos;
|
attribute vec2 aPos;
|
||||||
varying vec2 vTexCoord;
|
varying vec2 vTexCoord;
|
||||||
|
@ -374,9 +415,9 @@
|
||||||
gl_Position = vec4(aPos, 0.0, 1.0);
|
gl_Position = vec4(aPos, 0.0, 1.0);
|
||||||
vTexCoord = (0.5*aPos+0.5)*uResizeForCanvas;
|
vTexCoord = (0.5*aPos+0.5)*uResizeForCanvas;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id="texturedFragment" type="x-shader">
|
<script id="texturedFragment" type="x-shader">
|
||||||
precision highp float;
|
precision highp float;
|
||||||
uniform sampler2D uTexture0;
|
uniform sampler2D uTexture0;
|
||||||
varying vec2 vTexCoord;
|
varying vec2 vTexCoord;
|
||||||
|
@ -385,9 +426,9 @@
|
||||||
gl_FragColor = texture2D(uTexture0, vTexCoord);
|
gl_FragColor = texture2D(uTexture0, vTexCoord);
|
||||||
gl_FragColor.a= 1.0;
|
gl_FragColor.a= 1.0;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id="blurFragment" type="x-shader">
|
<script id="blurFragment" type="x-shader">
|
||||||
precision highp float;
|
precision highp float;
|
||||||
uniform sampler2D uTexture0;
|
uniform sampler2D uTexture0;
|
||||||
uniform vec2 uOffset;
|
uniform vec2 uOffset;
|
||||||
|
@ -414,9 +455,9 @@
|
||||||
sum += texture2D(uTexture0, vTexCoord + uOffset*8.0) * 0.000078;
|
sum += texture2D(uTexture0, vTexCoord + uOffset*8.0) * 0.000078;
|
||||||
gl_FragColor = sum;
|
gl_FragColor = sum;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id="outputVertex" type="x-shader">
|
<script id="outputVertex" type="x-shader">
|
||||||
precision highp float;
|
precision highp float;
|
||||||
attribute vec2 aPos;
|
attribute vec2 aPos;
|
||||||
varying vec2 vTexCoord;
|
varying vec2 vTexCoord;
|
||||||
|
@ -428,9 +469,9 @@
|
||||||
vTexCoord = (0.5*aPos+0.5);
|
vTexCoord = (0.5*aPos+0.5);
|
||||||
vTexCoordCanvas = vTexCoord*uResizeForCanvas;
|
vTexCoordCanvas = vTexCoord*uResizeForCanvas;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id="outputFragment" type="x-shader">
|
<script id="outputFragment" type="x-shader">
|
||||||
precision highp float;
|
precision highp float;
|
||||||
uniform sampler2D uTexture0; //line
|
uniform sampler2D uTexture0; //line
|
||||||
uniform sampler2D uTexture1; //tight glow
|
uniform sampler2D uTexture1; //tight glow
|
||||||
|
@ -448,8 +489,13 @@
|
||||||
return vec3(mix(color, gray, factor));
|
return vec3(mix(color, gray, factor));
|
||||||
}
|
}
|
||||||
|
|
||||||
void main (void)
|
/* Gradient noise from Jorge Jimenez's presentation: */
|
||||||
{
|
/* http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare */
|
||||||
|
float gradientNoise(in vec2 uv) {
|
||||||
|
return fract(52.9829189 * fract(dot(uv, vec2(0.06711056, 0.00583715))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void main (void) {
|
||||||
vec4 line = texture2D(uTexture0, vTexCoordCanvas);
|
vec4 line = texture2D(uTexture0, vTexCoordCanvas);
|
||||||
// r components have grid; g components do not.
|
// r components have grid; g components do not.
|
||||||
vec4 screen = texture2D(uTexture3, vTexCoord);
|
vec4 screen = texture2D(uTexture3, vTexCoord);
|
||||||
|
@ -461,8 +507,9 @@
|
||||||
float tlight2 = tlight*tlight*tlight;
|
float tlight2 = tlight*tlight*tlight;
|
||||||
gl_FragColor.rgb = mix(uColour, vec3(1.0), 0.3+tlight2*tlight2*0.5)*tlight;
|
gl_FragColor.rgb = mix(uColour, vec3(1.0), 0.3+tlight2*tlight2*0.5)*tlight;
|
||||||
gl_FragColor.rgb = desaturate(gl_FragColor.rgb, 1.0 - uSaturation);
|
gl_FragColor.rgb = desaturate(gl_FragColor.rgb, 1.0 - uSaturation);
|
||||||
|
gl_FragColor.rgb += (1.0 / 255.0) * gradientNoise(gl_FragCoord.xy) - (0.5 / 255.0);
|
||||||
gl_FragColor.a = 1.0;
|
gl_FragColor.a = 1.0;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="oscilloscope.js" type="module"></script>
|
<script src="oscilloscope.js" type="module"></script>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M0,12a12,12 0 1,0 24,0a12,12 0 1,0 -24,0Z" /></svg>
|
Po Szerokość: | Wysokość: | Rozmiar: 120 B |
|
@ -39,6 +39,12 @@ SosciPluginEditor::SosciPluginEditor(SosciAudioProcessor& p)
|
||||||
openVisualiserSettings();
|
openVisualiserSettings();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
addAndMakeVisible(record);
|
||||||
|
record.setPulseAnimation(true);
|
||||||
|
record.onClick = [this] {
|
||||||
|
visualiser.toggleRecording();
|
||||||
|
};
|
||||||
|
|
||||||
addAndMakeVisible(visualiser);
|
addAndMakeVisible(visualiser);
|
||||||
|
|
||||||
visualiser.openSettings = [this] {
|
visualiser.openSettings = [this] {
|
||||||
|
@ -49,6 +55,10 @@ SosciPluginEditor::SosciPluginEditor(SosciAudioProcessor& p)
|
||||||
visualiserSettingsWindow.setVisible(false);
|
visualiserSettingsWindow.setVisible(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
visualiser.recordingHalted = [this] {
|
||||||
|
record.setToggleState(false, juce::NotificationType::dontSendNotification);
|
||||||
|
};
|
||||||
|
|
||||||
visualiserSettingsWindow.setResizable(false, false);
|
visualiserSettingsWindow.setResizable(false, false);
|
||||||
#if JUCE_WINDOWS
|
#if JUCE_WINDOWS
|
||||||
// if not standalone, use native title bar for compatibility with DAWs
|
// if not standalone, use native title bar for compatibility with DAWs
|
||||||
|
@ -80,6 +90,7 @@ void SosciPluginEditor::resized() {
|
||||||
|
|
||||||
auto topBar = area.removeFromTop(25);
|
auto topBar = area.removeFromTop(25);
|
||||||
settings.setBounds(topBar.removeFromRight(25));
|
settings.setBounds(topBar.removeFromRight(25));
|
||||||
|
record.setBounds(topBar.removeFromRight(25));
|
||||||
menuBar.setBounds(topBar);
|
menuBar.setBounds(topBar);
|
||||||
|
|
||||||
visualiser.setBounds(area);
|
visualiser.setBounds(area);
|
||||||
|
|
|
@ -39,6 +39,7 @@ public:
|
||||||
|
|
||||||
juce::TooltipWindow tooltipWindow{nullptr, 0};
|
juce::TooltipWindow tooltipWindow{nullptr, 0};
|
||||||
|
|
||||||
|
SvgButton record{"Record", BinaryData::record_2_svg, juce::Colours::red, juce::Colours::red.withAlpha(0.01f)};
|
||||||
SvgButton settings{"Settings", BinaryData::cog_svg, juce::Colours::white, juce::Colours::white};
|
SvgButton settings{"Settings", BinaryData::cog_svg, juce::Colours::white, juce::Colours::white};
|
||||||
|
|
||||||
bool usingNativeMenuBar = false;
|
bool usingNativeMenuBar = false;
|
||||||
|
|
|
@ -25,6 +25,8 @@ class SvgButton : public juce::DrawableButton, public juce::AudioProcessorParame
|
||||||
changeSvgColour(doc.get(), colourOn.withBrightness(0.3f));
|
changeSvgColour(doc.get(), colourOn.withBrightness(0.3f));
|
||||||
disabledImageOn = juce::Drawable::createFromSVG(*doc);
|
disabledImageOn = juce::Drawable::createFromSVG(*doc);
|
||||||
|
|
||||||
|
path = normalImage->getOutlineAsPath();
|
||||||
|
|
||||||
getLookAndFeel().setColour(juce::DrawableButton::backgroundOnColourId, juce::Colours::transparentWhite);
|
getLookAndFeel().setColour(juce::DrawableButton::backgroundOnColourId, juce::Colours::transparentWhite);
|
||||||
|
|
||||||
if (colour != colourOn) {
|
if (colour != colourOn) {
|
||||||
|
@ -37,6 +39,8 @@ class SvgButton : public juce::DrawableButton, public juce::AudioProcessorParame
|
||||||
setToggleState(toggle->getBoolValue(), juce::NotificationType::dontSendNotification);
|
setToggleState(toggle->getBoolValue(), juce::NotificationType::dontSendNotification);
|
||||||
setTooltip(toggle->getDescription());
|
setTooltip(toggle->getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updater.addAnimator(pulse);
|
||||||
}
|
}
|
||||||
|
|
||||||
SvgButton(juce::String name, juce::String svg, juce::Colour colour) : SvgButton(name, svg, colour, colour) {}
|
SvgButton(juce::String name, juce::String svg, juce::Colour colour) : SvgButton(name, svg, colour, colour) {}
|
||||||
|
@ -70,6 +74,30 @@ class SvgButton : public juce::DrawableButton, public juce::AudioProcessorParame
|
||||||
setMouseCursor(juce::MouseCursor::NormalCursor);
|
setMouseCursor(juce::MouseCursor::NormalCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setPulseAnimation(bool pulseUsed) {
|
||||||
|
this->pulseUsed = pulseUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void paintOverChildren(juce::Graphics& g) override {
|
||||||
|
if (pulseUsed && getToggleState()) {
|
||||||
|
g.setColour(juce::Colours::black.withAlpha(colourFade / 1.5f));
|
||||||
|
g.fillPath(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void buttonStateChanged() override {
|
||||||
|
juce::DrawableButton::buttonStateChanged();
|
||||||
|
if (pulseUsed && getToggleState() != prevToggleState) {
|
||||||
|
if (getToggleState()) {
|
||||||
|
pulse.start();
|
||||||
|
} else {
|
||||||
|
pulse.complete();
|
||||||
|
colourFade = 1.0;
|
||||||
|
}
|
||||||
|
prevToggleState = getToggleState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<juce::Drawable> normalImage;
|
std::unique_ptr<juce::Drawable> normalImage;
|
||||||
std::unique_ptr<juce::Drawable> overImage;
|
std::unique_ptr<juce::Drawable> overImage;
|
||||||
|
@ -83,6 +111,21 @@ private:
|
||||||
|
|
||||||
BooleanParameter* toggle;
|
BooleanParameter* toggle;
|
||||||
|
|
||||||
|
juce::VBlankAnimatorUpdater updater{this};
|
||||||
|
float colourFade = 0.0;
|
||||||
|
bool pulseUsed = false;
|
||||||
|
bool prevToggleState = false;
|
||||||
|
juce::Path path;
|
||||||
|
juce::Animator pulse = juce::ValueAnimatorBuilder {}
|
||||||
|
.withEasing([] (float t) { return std::sin(3.14159 * t) / 2 + 0.5; })
|
||||||
|
.withDurationMs(500)
|
||||||
|
.runningInfinitely()
|
||||||
|
.withValueChangedCallback([this] (auto value) {
|
||||||
|
colourFade = value;
|
||||||
|
repaint();
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
void changeSvgColour(juce::XmlElement* xml, juce::Colour colour) {
|
void changeSvgColour(juce::XmlElement* xml, juce::Colour colour) {
|
||||||
forEachXmlChildElement(*xml, xmlnode) {
|
forEachXmlChildElement(*xml, xmlnode) {
|
||||||
xmlnode->setAttribute("fill", '#' + colour.toDisplayString(false));
|
xmlnode->setAttribute("fill", '#' + colour.toDisplayString(false));
|
||||||
|
|
|
@ -270,6 +270,9 @@ void VisualiserComponent::paintXY(juce::Graphics& g, juce::Rectangle<float> area
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualiserComponent::initialiseBrowser() {
|
void VisualiserComponent::initialiseBrowser() {
|
||||||
|
if (recordingHalted != nullptr) {
|
||||||
|
recordingHalted();
|
||||||
|
}
|
||||||
oldBrowser = std::move(browser);
|
oldBrowser = std::move(browser);
|
||||||
if (oldBrowser != nullptr) {
|
if (oldBrowser != nullptr) {
|
||||||
removeChildComponent(oldBrowser.get());
|
removeChildComponent(oldBrowser.get());
|
||||||
|
@ -323,6 +326,21 @@ void VisualiserComponent::initialiseBrowser() {
|
||||||
.withNativeFunction("isVisualiserOnly", [this](auto& var, auto complete) {
|
.withNativeFunction("isVisualiserOnly", [this](auto& var, auto complete) {
|
||||||
complete(visualiserOnly);
|
complete(visualiserOnly);
|
||||||
})
|
})
|
||||||
|
.withNativeFunction("downloadVideo", [this](const juce::Array<juce::var>& args, auto complete) {
|
||||||
|
juce::String base64 = args[0].toString();
|
||||||
|
chooser = std::make_unique<juce::FileChooser>("Save video", juce::File::getSpecialLocation(juce::File::SpecialLocationType::userDesktopDirectory).getChildFile("osci-render.webm"), "*.webm");
|
||||||
|
chooser->launchAsync(juce::FileBrowserComponent::saveMode,
|
||||||
|
[base64](const juce::FileChooser& chooser) {
|
||||||
|
juce::File result = chooser.getResult();
|
||||||
|
if (result.getFullPathName().isNotEmpty()) {
|
||||||
|
juce::FileOutputStream stream(result);
|
||||||
|
stream.setPosition(0);
|
||||||
|
stream.truncate();
|
||||||
|
juce::Base64::convertFromBase64(stream, base64);
|
||||||
|
stream.flush();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
addAndMakeVisible(*browser);
|
addAndMakeVisible(*browser);
|
||||||
|
@ -366,6 +384,13 @@ void VisualiserComponent::handleAsyncUpdate() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VisualiserComponent::toggleRecording() {
|
||||||
|
if (oldVisualiser) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
browser->emitEventIfBrowserIsVisible("toggleRecording", juce::var());
|
||||||
|
}
|
||||||
|
|
||||||
void VisualiserComponent::resized() {
|
void VisualiserComponent::resized() {
|
||||||
if (!oldVisualiser) {
|
if (!oldVisualiser) {
|
||||||
browser->setBounds(getLocalBounds());
|
browser->setBounds(getLocalBounds());
|
||||||
|
@ -390,10 +415,14 @@ void VisualiserComponent::childChanged() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualiserComponent::popoutWindow() {
|
void VisualiserComponent::popoutWindow() {
|
||||||
|
if (recordingHalted != nullptr) {
|
||||||
|
recordingHalted();
|
||||||
|
}
|
||||||
auto visualiser = new VisualiserComponent(sampleRateManager, consumerManager, settings, this, oldVisualiser);
|
auto visualiser = new VisualiserComponent(sampleRateManager, consumerManager, settings, this, oldVisualiser);
|
||||||
visualiser->settings.setLookAndFeel(&getLookAndFeel());
|
visualiser->settings.setLookAndFeel(&getLookAndFeel());
|
||||||
visualiser->openSettings = openSettings;
|
visualiser->openSettings = openSettings;
|
||||||
visualiser->closeSettings = closeSettings;
|
visualiser->closeSettings = closeSettings;
|
||||||
|
visualiser->recordingHalted = recordingHalted;
|
||||||
child = visualiser;
|
child = visualiser;
|
||||||
childChanged();
|
childChanged();
|
||||||
popOutButton.setVisible(false);
|
popOutButton.setVisible(false);
|
||||||
|
|
|
@ -42,6 +42,7 @@ public:
|
||||||
void setFullScreen(bool fullScreen);
|
void setFullScreen(bool fullScreen);
|
||||||
void setVisualiserType(bool oldVisualiser);
|
void setVisualiserType(bool oldVisualiser);
|
||||||
void handleAsyncUpdate() override;
|
void handleAsyncUpdate() override;
|
||||||
|
void toggleRecording();
|
||||||
|
|
||||||
VisualiserComponent* parent = nullptr;
|
VisualiserComponent* parent = nullptr;
|
||||||
VisualiserComponent* child = nullptr;
|
VisualiserComponent* child = nullptr;
|
||||||
|
@ -49,6 +50,8 @@ public:
|
||||||
|
|
||||||
std::atomic<bool> active = true;
|
std::atomic<bool> active = true;
|
||||||
|
|
||||||
|
std::function<void()> recordingHalted;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// 60fps
|
// 60fps
|
||||||
const double BUFFER_LENGTH_SECS = 1/60.0;
|
const double BUFFER_LENGTH_SECS = 1/60.0;
|
||||||
|
@ -120,6 +123,8 @@ private:
|
||||||
// keeping this around for memory management reasons
|
// keeping this around for memory management reasons
|
||||||
std::unique_ptr<juce::WebBrowserComponent> oldBrowser = nullptr;
|
std::unique_ptr<juce::WebBrowserComponent> oldBrowser = nullptr;
|
||||||
|
|
||||||
|
std::unique_ptr<juce::FileChooser> chooser;
|
||||||
|
|
||||||
void initialiseBrowser();
|
void initialiseBrowser();
|
||||||
void resetBuffer();
|
void resetBuffer();
|
||||||
void popoutWindow();
|
void popoutWindow();
|
||||||
|
|
|
@ -658,6 +658,7 @@
|
||||||
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
||||||
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
||||||
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
||||||
|
<MODULEPATH id="juce_animation" path="../JUCE/modules"/>
|
||||||
</MODULEPATHS>
|
</MODULEPATHS>
|
||||||
</LINUX_MAKE>
|
</LINUX_MAKE>
|
||||||
<VS2022 targetFolder="Builds/VisualStudio2022" smallIcon="pSc1mq" bigIcon="pSc1mq">
|
<VS2022 targetFolder="Builds/VisualStudio2022" smallIcon="pSc1mq" bigIcon="pSc1mq">
|
||||||
|
@ -681,6 +682,7 @@
|
||||||
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
||||||
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
||||||
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
||||||
|
<MODULEPATH id="juce_animation" path="../JUCE/modules"/>
|
||||||
</MODULEPATHS>
|
</MODULEPATHS>
|
||||||
</VS2022>
|
</VS2022>
|
||||||
<XCODE_MAC targetFolder="Builds/MacOSX" extraLinkerFlags="-Wl,-weak_reference_mismatches,weak"
|
<XCODE_MAC targetFolder="Builds/MacOSX" extraLinkerFlags="-Wl,-weak_reference_mismatches,weak"
|
||||||
|
@ -705,10 +707,12 @@
|
||||||
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
||||||
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
||||||
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
||||||
|
<MODULEPATH id="juce_animation" path="../JUCE/modules"/>
|
||||||
</MODULEPATHS>
|
</MODULEPATHS>
|
||||||
</XCODE_MAC>
|
</XCODE_MAC>
|
||||||
</EXPORTFORMATS>
|
</EXPORTFORMATS>
|
||||||
<MODULES>
|
<MODULES>
|
||||||
|
<MODULE id="juce_animation" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||||
<MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
<MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||||
<MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
<MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||||
<MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
<MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
<FILE id="PFc2q2" name="random.svg" compile="0" resource="1" file="Resources/svg/random.svg"/>
|
<FILE id="PFc2q2" name="random.svg" compile="0" resource="1" file="Resources/svg/random.svg"/>
|
||||||
<FILE id="CE6di2" name="range.svg" compile="0" resource="1" file="Resources/svg/range.svg"/>
|
<FILE id="CE6di2" name="range.svg" compile="0" resource="1" file="Resources/svg/range.svg"/>
|
||||||
<FILE id="n79IAy" name="record.svg" compile="0" resource="1" file="Resources/svg/record.svg"/>
|
<FILE id="n79IAy" name="record.svg" compile="0" resource="1" file="Resources/svg/record.svg"/>
|
||||||
|
<FILE id="TWt5MY" name="record_2.svg" compile="0" resource="1" file="Resources/svg/record_2.svg"/>
|
||||||
<FILE id="OaqZb1" name="right_arrow.svg" compile="0" resource="1" file="Resources/svg/right_arrow.svg"/>
|
<FILE id="OaqZb1" name="right_arrow.svg" compile="0" resource="1" file="Resources/svg/right_arrow.svg"/>
|
||||||
<FILE id="rXjNlx" name="threshold.svg" compile="0" resource="1" file="Resources/svg/threshold.svg"/>
|
<FILE id="rXjNlx" name="threshold.svg" compile="0" resource="1" file="Resources/svg/threshold.svg"/>
|
||||||
<FILE id="rFYmV8" name="timer.svg" compile="0" resource="1" file="Resources/svg/timer.svg"/>
|
<FILE id="rFYmV8" name="timer.svg" compile="0" resource="1" file="Resources/svg/timer.svg"/>
|
||||||
|
@ -139,6 +140,7 @@
|
||||||
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
||||||
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
||||||
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
||||||
|
<MODULEPATH id="juce_animation" path="../../../JUCE/modules"/>
|
||||||
</MODULEPATHS>
|
</MODULEPATHS>
|
||||||
</LINUX_MAKE>
|
</LINUX_MAKE>
|
||||||
<VS2022 targetFolder="Builds/sosci/VisualStudio2022" smallIcon="pSc1mq"
|
<VS2022 targetFolder="Builds/sosci/VisualStudio2022" smallIcon="pSc1mq"
|
||||||
|
@ -163,6 +165,7 @@
|
||||||
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
||||||
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
||||||
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
||||||
|
<MODULEPATH id="juce_animation" path="../../../JUCE/modules"/>
|
||||||
</MODULEPATHS>
|
</MODULEPATHS>
|
||||||
</VS2022>
|
</VS2022>
|
||||||
<XCODE_MAC targetFolder="Builds/sosci/MacOSX" extraLinkerFlags="-Wl,-weak_reference_mismatches,weak"
|
<XCODE_MAC targetFolder="Builds/sosci/MacOSX" extraLinkerFlags="-Wl,-weak_reference_mismatches,weak"
|
||||||
|
@ -187,10 +190,12 @@
|
||||||
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
||||||
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
||||||
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
||||||
|
<MODULEPATH id="juce_animation" path="../../../JUCE/modules"/>
|
||||||
</MODULEPATHS>
|
</MODULEPATHS>
|
||||||
</XCODE_MAC>
|
</XCODE_MAC>
|
||||||
</EXPORTFORMATS>
|
</EXPORTFORMATS>
|
||||||
<MODULES>
|
<MODULES>
|
||||||
|
<MODULE id="juce_animation" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||||
<MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
<MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||||
<MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
<MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||||
<MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
<MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||||
|
|
Ładowanie…
Reference in New Issue