kopia lustrzana https://github.com/jameshball/osci-render
Add pop-up for downloading ffmpeg and complete downloader implementation
rodzic
7b98b34b04
commit
f26ea1011a
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
|
@ -0,0 +1,93 @@
|
|||
Copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://openfontlicense.org
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@ -26,6 +26,8 @@ OscirenderLookAndFeel::OscirenderLookAndFeel() {
|
|||
setColour(juce::TooltipWindow::backgroundColourId, Colours::darker);
|
||||
setColour(juce::TooltipWindow::outlineColourId, juce::Colours::white);
|
||||
setColour(juce::TextButton::buttonOnColourId, Colours::darker);
|
||||
setColour(juce::AlertWindow::outlineColourId, Colours::darker);
|
||||
setColour(juce::AlertWindow::backgroundColourId, Colours::darker);
|
||||
|
||||
// combo box
|
||||
setColour(juce::ComboBox::backgroundColourId, Colours::veryDark);
|
||||
|
@ -79,13 +81,15 @@ OscirenderLookAndFeel::OscirenderLookAndFeel() {
|
|||
setColour(juce::MidiKeyboardComponent::shadowColourId, juce::Colours::transparentBlack);
|
||||
setColour(juce::MidiKeyboardComponent::upDownButtonBackgroundColourId, Colours::veryDark);
|
||||
setColour(juce::MidiKeyboardComponent::upDownButtonArrowColourId, juce::Colours::white);
|
||||
|
||||
// progress bar
|
||||
setColour(juce::ProgressBar::backgroundColourId, juce::Colours::transparentBlack);
|
||||
setColour(juce::ProgressBar::foregroundColourId, Colours::accentColor);
|
||||
|
||||
// UI colours
|
||||
getCurrentColourScheme().setUIColour(ColourScheme::widgetBackground, Colours::veryDark);
|
||||
getCurrentColourScheme().setUIColour(ColourScheme::UIColour::defaultFill, Colours::accentColor);
|
||||
|
||||
setDefaultSansSerifTypeface(juce::Typeface::createSystemTypefaceFor(BinaryData::font_ttf, BinaryData::font_ttfSize));
|
||||
|
||||
// I have to do this, otherwise components are initialised before the look and feel is set
|
||||
juce::LookAndFeel::setDefaultLookAndFeel(this);
|
||||
}
|
||||
|
@ -372,3 +376,88 @@ void OscirenderLookAndFeel::drawCallOutBoxBackground(juce::CallOutBox& box, juce
|
|||
g.setColour(juce::Colours::black);
|
||||
g.strokePath(path, juce::PathStrokeType(1.0f));
|
||||
}
|
||||
|
||||
void OscirenderLookAndFeel::drawProgressBar(juce::Graphics& g, juce::ProgressBar& progressBar, int width, int height, double progress, const juce::String& textToShow) {
|
||||
switch (progressBar.getResolvedStyle()) {
|
||||
case juce::ProgressBar::Style::linear:
|
||||
customDrawLinearProgressBar(g, progressBar, width, height, progress, textToShow);
|
||||
break;
|
||||
case juce::ProgressBar::Style::circular:
|
||||
juce::LookAndFeel_V4::drawProgressBar(g, progressBar, width, height, progress, textToShow);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OscirenderLookAndFeel::customDrawLinearProgressBar(juce::Graphics& g, const juce::ProgressBar& progressBar, int width, int height, double progress, const juce::String& textToShow) {
|
||||
auto background = progressBar.findColour(juce::ProgressBar::backgroundColourId);
|
||||
auto foreground = progressBar.findColour(juce::ProgressBar::foregroundColourId).withAlpha(0.5f);
|
||||
int rectRadius = 2;
|
||||
|
||||
auto barBounds = progressBar.getLocalBounds().toFloat();
|
||||
|
||||
g.setColour(background);
|
||||
g.fillRoundedRectangle(barBounds, rectRadius);
|
||||
|
||||
juce::String text = textToShow.isEmpty() ? "waiting..." : textToShow;
|
||||
|
||||
if (progress >= 0.0f && progress <= 1.0f) {
|
||||
juce::Path p;
|
||||
p.addRoundedRectangle(barBounds, rectRadius);
|
||||
g.reduceClipRegion(p);
|
||||
|
||||
barBounds.setWidth(barBounds.getWidth() * (float) progress);
|
||||
g.setColour(foreground);
|
||||
g.fillRoundedRectangle(barBounds, rectRadius);
|
||||
} else {
|
||||
if (progress == -2) {
|
||||
background = juce::Colours::red;
|
||||
text = "Error";
|
||||
}
|
||||
|
||||
// spinning bar..
|
||||
g.setColour(background);
|
||||
|
||||
auto stripeWidth = height * 2;
|
||||
auto position = static_cast<int>(juce::Time::getMillisecondCounter() / 15) % stripeWidth;
|
||||
|
||||
juce::Path p;
|
||||
|
||||
for (auto x = static_cast<float> (-position); x < (float) (width + stripeWidth); x += (float) stripeWidth) {
|
||||
p.addQuadrilateral (x, 0.0f,
|
||||
x + (float) stripeWidth * 0.5f, 0.0f,
|
||||
x, static_cast<float> (height),
|
||||
x - (float) stripeWidth * 0.5f, static_cast<float> (height));
|
||||
}
|
||||
|
||||
juce::Image im(juce::Image::ARGB, width, height, true);
|
||||
|
||||
{
|
||||
juce::Graphics g2(im);
|
||||
g2.setColour(foreground);
|
||||
g2.fillRoundedRectangle(barBounds, rectRadius);
|
||||
}
|
||||
|
||||
g.setTiledImageFill(im, 0, 0, 0.85f);
|
||||
g.fillPath(p);
|
||||
}
|
||||
|
||||
g.setColour(juce::Colours::white);
|
||||
juce::Font font = juce::Font(juce::FontOptions((float) height * 0.9f, juce::Font::bold));
|
||||
g.setFont(font);
|
||||
|
||||
g.drawText(text, 0, 0, width, height, juce::Justification::centred, false);
|
||||
}
|
||||
|
||||
juce::Typeface::Ptr OscirenderLookAndFeel::getTypefaceForFont(const juce::Font& font) {
|
||||
if (font.getTypefaceName() == juce::Font::getDefaultSansSerifFontName()) {
|
||||
if (font.getTypefaceStyle() == "Regular") {
|
||||
return regularTypeface;
|
||||
} else if (font.getTypefaceStyle() == "Bold") {
|
||||
return boldTypeface;
|
||||
} else if (font.getTypefaceStyle() == "Italic") {
|
||||
return italicTypeface;
|
||||
}
|
||||
}
|
||||
|
||||
return juce::Font::getDefaultTypefaceForFont(font);
|
||||
}
|
||||
|
|
|
@ -66,6 +66,9 @@ public:
|
|||
OscirenderLookAndFeel();
|
||||
|
||||
static const int RECT_RADIUS = 5;
|
||||
juce::Typeface::Ptr regularTypeface = juce::Typeface::createSystemTypefaceFor(BinaryData::FiraSansRegular_ttf, BinaryData::FiraSansRegular_ttfSize);
|
||||
juce::Typeface::Ptr boldTypeface = juce::Typeface::createSystemTypefaceFor(BinaryData::FiraSansBold_ttf, BinaryData::FiraSansBold_ttfSize);
|
||||
juce::Typeface::Ptr italicTypeface = juce::Typeface::createSystemTypefaceFor(BinaryData::FiraSansItalic_ttf, BinaryData::FiraSansItalic_ttfSize);
|
||||
|
||||
void drawLabel(juce::Graphics& g, juce::Label& label) override;
|
||||
void fillTextEditorBackground(juce::Graphics& g, int width, int height, juce::TextEditor& textEditor) override;
|
||||
|
@ -97,4 +100,7 @@ public:
|
|||
void drawToggleButton(juce::Graphics&, juce::ToggleButton&, bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) override;
|
||||
juce::MouseCursor getMouseCursorFor(juce::Component& component) override;
|
||||
void drawCallOutBoxBackground(juce::CallOutBox& box, juce::Graphics& g, const juce::Path& path, juce::Image& cachedImage) override;
|
||||
void drawProgressBar(juce::Graphics& g, juce::ProgressBar& progressBar, int width, int height, double progress, const juce::String& textToShow) override;
|
||||
void customDrawLinearProgressBar(juce::Graphics& g, const juce::ProgressBar& progressBar, int width, int height, double progress, const juce::String& textToShow);
|
||||
juce::Typeface::Ptr getTypefaceForFont(const juce::Font& font) override;
|
||||
};
|
||||
|
|
|
@ -131,6 +131,9 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
|
|||
}
|
||||
|
||||
OscirenderAudioProcessorEditor::~OscirenderAudioProcessorEditor() {
|
||||
if (audioProcessor.haltRecording != nullptr) {
|
||||
audioProcessor.haltRecording();
|
||||
}
|
||||
setLookAndFeel(nullptr);
|
||||
juce::Desktop::getInstance().setDefaultLookAndFeel(nullptr);
|
||||
juce::MessageManagerLock lock;
|
||||
|
|
|
@ -67,6 +67,9 @@ SosciPluginEditor::SosciPluginEditor(SosciAudioProcessor& p)
|
|||
}
|
||||
|
||||
SosciPluginEditor::~SosciPluginEditor() {
|
||||
if (audioProcessor.haltRecording != nullptr) {
|
||||
audioProcessor.haltRecording();
|
||||
}
|
||||
setLookAndFeel(nullptr);
|
||||
juce::Desktop::getInstance().setDefaultLookAndFeel(nullptr);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
#include "DownloaderComponent.h"
|
||||
|
||||
DownloaderComponent::DownloaderComponent(juce::URL url, juce::File file, juce::String title, juce::Component* parent) : juce::ThreadWithProgressWindow(title, true, true, 1000, juce::String(), parent), url(url), file(file) {
|
||||
DownloaderComponent::DownloaderComponent(juce::URL url, juce::File file) : juce::Thread("DownloaderComponent"), url(url), file(file) {
|
||||
addChildComponent(progressBar);
|
||||
addChildComponent(successLabel);
|
||||
|
||||
successLabel.setText(file.getFileName() + " downloaded!", juce::dontSendNotification);
|
||||
|
||||
if (url.toString(false).endsWithIgnoreCase(".gz")) {
|
||||
uncompressOnFinish = true;
|
||||
this->file = file.getSiblingFile(file.getFileName() + ".gz");
|
||||
|
@ -15,26 +20,52 @@ void DownloaderComponent::run() {
|
|||
juce::CriticalSection::ScopedTryLockType lock(taskLock);
|
||||
if (lock.isLocked() && task != nullptr) {
|
||||
if (task->isFinished()) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
wait(100);
|
||||
}
|
||||
threadComplete();
|
||||
}
|
||||
|
||||
void DownloaderComponent::threadComplete(bool userPressedCancel) {
|
||||
if (!userPressedCancel && uncompressOnFinish && task->isFinished() && !task->hadError()) {
|
||||
void DownloaderComponent::threadComplete() {
|
||||
bool error = task->hadError();
|
||||
if (uncompressOnFinish && task->isFinished() && !error) {
|
||||
juce::FileInputStream input(file);
|
||||
juce::GZIPDecompressorInputStream decompressedInput(&input, false, juce::GZIPDecompressorInputStream::gzipFormat);
|
||||
juce::File uncompressedFile = file.getSiblingFile(file.getFileNameWithoutExtension());
|
||||
juce::FileOutputStream output(uncompressedFile);
|
||||
if (output.writeFromInputStream(decompressedInput, -1) < 1) {
|
||||
uncompressedFile.deleteFile();
|
||||
error = true;
|
||||
} else {
|
||||
uncompressedFile.setExecutePermission(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
file.deleteFile();
|
||||
progressValue = -2;
|
||||
} else {
|
||||
progressValue = 1;
|
||||
if (onSuccessfulDownload != nullptr) {
|
||||
onSuccessfulDownload();
|
||||
}
|
||||
juce::MessageManager::callAsync([this]() {
|
||||
progressBar.setVisible(false);
|
||||
successLabel.setVisible(true);
|
||||
});
|
||||
|
||||
juce::Timer::callAfterDelay(3000, [this]() {
|
||||
successLabel.setVisible(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void DownloaderComponent::resized() {
|
||||
progressBar.setBounds(getLocalBounds());
|
||||
successLabel.setBounds(getLocalBounds());
|
||||
}
|
||||
|
||||
void DownloaderComponent::finished(juce::URL::DownloadTask* task, bool success) {
|
||||
|
@ -42,9 +73,16 @@ void DownloaderComponent::finished(juce::URL::DownloadTask* task, bool success)
|
|||
}
|
||||
|
||||
void DownloaderComponent::progress(juce::URL::DownloadTask* task, juce::int64 bytesDownloaded, juce::int64 totalLength) {
|
||||
setProgress((float)bytesDownloaded / (float)totalLength);
|
||||
if (uncompressOnFinish) {
|
||||
progressValue = ((double) bytesDownloaded / (double) totalLength) * 0.9;
|
||||
} else {
|
||||
progressValue = (double) bytesDownloaded / (double) totalLength;
|
||||
}
|
||||
}
|
||||
|
||||
void DownloaderComponent::download() {
|
||||
launchThread();
|
||||
progressValue = -1;
|
||||
successLabel.setVisible(false);
|
||||
progressBar.setVisible(true);
|
||||
startThread();
|
||||
}
|
||||
|
|
|
@ -19,20 +19,26 @@ private:
|
|||
std::unique_ptr<juce::URL::DownloadTask>& task;
|
||||
};
|
||||
|
||||
class DownloaderComponent : public juce::ThreadWithProgressWindow, public juce::URL::DownloadTaskListener {
|
||||
class DownloaderComponent : public juce::Component, public juce::Thread, public juce::URL::DownloadTaskListener {
|
||||
public:
|
||||
DownloaderComponent(juce::URL url, juce::File file, juce::String title, juce::Component* parent);
|
||||
DownloaderComponent(juce::URL url, juce::File file);
|
||||
|
||||
void download();
|
||||
void run() override;
|
||||
void threadComplete(bool userPressedCancel) override;
|
||||
void threadComplete();
|
||||
void resized() override;
|
||||
void finished(juce::URL::DownloadTask* task, bool success) override;
|
||||
void progress(juce::URL::DownloadTask* task, juce::int64 bytesDownloaded, juce::int64 totalLength) override;
|
||||
|
||||
std::function<void()> onSuccessfulDownload;
|
||||
|
||||
private:
|
||||
|
||||
juce::URL url;
|
||||
juce::File file;
|
||||
double progressValue = -1;
|
||||
juce::ProgressBar progressBar = juce::ProgressBar(progressValue);
|
||||
juce::Label successLabel;
|
||||
juce::CriticalSection taskLock;
|
||||
std::unique_ptr<juce::URL::DownloadTask> task;
|
||||
std::unique_ptr<DownloaderThread> downloader;
|
||||
|
|
|
@ -9,6 +9,7 @@ AudioBackgroundThread::AudioBackgroundThread(const juce::String& name, AudioBack
|
|||
}
|
||||
|
||||
AudioBackgroundThread::~AudioBackgroundThread() {
|
||||
deleting = true;
|
||||
setShouldBeRunning(false);
|
||||
manager.unregisterThread(this);
|
||||
}
|
||||
|
@ -69,7 +70,9 @@ void AudioBackgroundThread::start() {
|
|||
}
|
||||
|
||||
void AudioBackgroundThread::stop() {
|
||||
stopTask();
|
||||
if (!deleting) {
|
||||
stopTask();
|
||||
}
|
||||
consumer->forceNotify();
|
||||
stopThread(1000);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ private:
|
|||
std::unique_ptr<BufferConsumer> consumer = nullptr;
|
||||
bool shouldBeRunning = false;
|
||||
std::atomic<bool> isPrepared = false;
|
||||
std::atomic<bool> deleting = false;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -12,7 +12,14 @@
|
|||
#include "TexturedVertexShader.glsl"
|
||||
|
||||
VisualiserComponent::VisualiserComponent(juce::File ffmpegFile, std::function<void()>& haltRecording, AudioBackgroundThreadManager& threadManager, VisualiserSettings& settings, VisualiserComponent* parent, bool visualiserOnly) : ffmpegFile(ffmpegFile), haltRecording(haltRecording), settings(settings), threadManager(threadManager), visualiserOnly(visualiserOnly), AudioBackgroundThread("VisualiserComponent" + juce::String(parent != nullptr ? " Child" : ""), threadManager), parent(parent) {
|
||||
|
||||
addAndMakeVisible(ffmpegDownloader);
|
||||
|
||||
ffmpegDownloader.onSuccessfulDownload = [this] {
|
||||
juce::MessageManager::callAsync([this] {
|
||||
record.setEnabled(true);
|
||||
});
|
||||
};
|
||||
|
||||
haltRecording = [this] {
|
||||
setRecording(false);
|
||||
};
|
||||
|
@ -21,14 +28,6 @@ VisualiserComponent::VisualiserComponent(juce::File ffmpegFile, std::function<vo
|
|||
record.setPulseAnimation(true);
|
||||
record.onClick = [this] {
|
||||
setRecording(record.getToggleState());
|
||||
stopwatch.stop();
|
||||
stopwatch.reset();
|
||||
|
||||
if (record.getToggleState()) {
|
||||
stopwatch.start();
|
||||
}
|
||||
|
||||
resized();
|
||||
};
|
||||
|
||||
addAndMakeVisible(stopwatch);
|
||||
|
@ -169,10 +168,27 @@ bool VisualiserComponent::keyPressed(const juce::KeyPress& key) {
|
|||
void VisualiserComponent::setFullScreen(bool fullScreen) {}
|
||||
|
||||
void VisualiserComponent::setRecording(bool recording) {
|
||||
stopwatch.stop();
|
||||
stopwatch.reset();
|
||||
|
||||
if (recording) {
|
||||
if (!ffmpegFile.exists()) {
|
||||
ffmpegDownloader.download();
|
||||
record.setToggleState(false, juce::NotificationType::sendNotification);
|
||||
// ask the user if they want to download ffmpeg
|
||||
juce::MessageBoxOptions options = juce::MessageBoxOptions()
|
||||
.withTitle("FFmpeg not found")
|
||||
.withMessage("FFmpeg not found. This is required to record video to .mp4.\n\nWould you like to download it now?")
|
||||
.withButton("Yes")
|
||||
.withButton("No")
|
||||
.withIconType(juce::AlertWindow::WarningIcon)
|
||||
.withAssociatedComponent(this);
|
||||
|
||||
juce::AlertWindow::showAsync(options, [this](int result) {
|
||||
if (result == 1) {
|
||||
record.setEnabled(false);
|
||||
ffmpegDownloader.download();
|
||||
}
|
||||
});
|
||||
record.setToggleState(false, juce::NotificationType::dontSendNotification);
|
||||
return;
|
||||
}
|
||||
juce::TemporaryFile tempFile = juce::TemporaryFile(".mp4");
|
||||
|
@ -191,6 +207,7 @@ void VisualiserComponent::setRecording(bool recording) {
|
|||
}
|
||||
framePixels.resize(renderTexture.width * renderTexture.height * 4);
|
||||
setPaused(false);
|
||||
stopwatch.start();
|
||||
} else if (ffmpeg != nullptr) {
|
||||
#if JUCE_WINDOWS
|
||||
_pclose(ffmpeg);
|
||||
|
@ -202,6 +219,7 @@ void VisualiserComponent::setRecording(bool recording) {
|
|||
setBlockOnAudioThread(recording);
|
||||
numFrames = 0;
|
||||
record.setToggleState(recording, juce::NotificationType::dontSendNotification);
|
||||
resized();
|
||||
}
|
||||
|
||||
void VisualiserComponent::resized() {
|
||||
|
@ -221,13 +239,16 @@ void VisualiserComponent::resized() {
|
|||
} else {
|
||||
stopwatch.setVisible(false);
|
||||
}
|
||||
if (child == nullptr) {
|
||||
auto bounds = buttonRow.removeFromRight(160);
|
||||
ffmpegDownloader.setBounds(bounds.withSizeKeepingCentre(bounds.getWidth() - 10, bounds.getHeight() - 10));
|
||||
}
|
||||
viewportArea = area;
|
||||
viewportChanged(viewportArea);
|
||||
}
|
||||
|
||||
void VisualiserComponent::popoutWindow() {
|
||||
setRecording(false);
|
||||
record.setEnabled(false);
|
||||
auto visualiser = new VisualiserComponent(ffmpegFile, haltRecording, threadManager, settings, this);
|
||||
visualiser->settings.setLookAndFeel(&getLookAndFeel());
|
||||
visualiser->openSettings = openSettings;
|
||||
|
@ -247,7 +268,8 @@ void VisualiserComponent::popoutWindow() {
|
|||
|
||||
void VisualiserComponent::childUpdated() {
|
||||
popOutButton.setVisible(child == nullptr);
|
||||
record.setEnabled(child == nullptr);
|
||||
ffmpegDownloader.setVisible(child == nullptr);
|
||||
record.setVisible(child == nullptr);
|
||||
if (child != nullptr) {
|
||||
haltRecording = [this] {
|
||||
setRecording(false);
|
||||
|
@ -826,6 +848,10 @@ void VisualiserComponent::paint(juce::Graphics& g) {
|
|||
g.setColour(juce::Colours::black);
|
||||
g.fillRect(buttonRow);
|
||||
if (!active) {
|
||||
// draw a translucent overlay
|
||||
g.setColour(juce::Colours::black.withAlpha(0.5f));
|
||||
g.fillRect(viewportArea);
|
||||
|
||||
g.setColour(juce::Colours::white);
|
||||
g.setFont(30.0f);
|
||||
juce::String text = child == nullptr ? "Paused" : "Open in another window";
|
||||
|
|
|
@ -112,7 +112,7 @@ private:
|
|||
#endif
|
||||
#endif
|
||||
+ ".gz";
|
||||
DownloaderComponent ffmpegDownloader{ffmpegURL, ffmpegFile, "Downloading ffmpeg...", this};
|
||||
DownloaderComponent ffmpegDownloader{ffmpegURL, ffmpegFile};
|
||||
|
||||
Semaphore renderingSemaphore{0};
|
||||
|
||||
|
|
|
@ -10,7 +10,12 @@
|
|||
<MAINGROUP id="j5Ge2T" name="osci-render">
|
||||
<GROUP id="{5ABCED88-0059-A7AF-9596-DBF91DDB0292}" name="Resources">
|
||||
<GROUP id="{8930EC48-30FD-646B-9DC5-0861171F8B2E}" name="fonts">
|
||||
<FILE id="sqtSiu" name="font.ttf" compile="0" resource="1" file="Resources/fonts/font.ttf"/>
|
||||
<FILE id="GXGPCT" name="FiraSans-Bold.ttf" compile="0" resource="1"
|
||||
file="Resources/fonts/FiraSans-Bold.ttf"/>
|
||||
<FILE id="TvdkVI" name="FiraSans-Italic.ttf" compile="0" resource="1"
|
||||
file="Resources/fonts/FiraSans-Italic.ttf"/>
|
||||
<FILE id="uStS0H" name="FiraSans-Regular.ttf" compile="0" resource="1"
|
||||
file="Resources/fonts/FiraSans-Regular.ttf"/>
|
||||
</GROUP>
|
||||
<GROUP id="{F3815953-00C0-3876-5552-BDE98F3233D9}" name="gpla">
|
||||
<FILE id="euGQq0" name="fallback.gpla" compile="0" resource="1" file="Resources/gpla/fallback.gpla"/>
|
||||
|
@ -137,6 +142,10 @@
|
|||
file="Source/components/ComponentList.cpp"/>
|
||||
<FILE id="HGTPEW" name="ComponentList.h" compile="0" resource="0" file="Source/components/ComponentList.h"/>
|
||||
<FILE id="IvySRY" name="DoubleTextBox.h" compile="0" resource="0" file="Source/components/DoubleTextBox.h"/>
|
||||
<FILE id="Jh9JQ3" name="DownloaderComponent.cpp" compile="1" resource="0"
|
||||
file="Source/components/DownloaderComponent.cpp"/>
|
||||
<FILE id="rCLnwK" name="DownloaderComponent.h" compile="0" resource="0"
|
||||
file="Source/components/DownloaderComponent.h"/>
|
||||
<FILE id="poPVxL" name="DraggableListBox.cpp" compile="1" resource="0"
|
||||
file="Source/components/DraggableListBox.cpp"/>
|
||||
<FILE id="Y9NEGn" name="DraggableListBox.h" compile="0" resource="0"
|
||||
|
|
|
@ -10,7 +10,12 @@
|
|||
<MAINGROUP id="j5Ge2T" name="sosci">
|
||||
<GROUP id="{5ABCED88-0059-A7AF-9596-DBF91DDB0292}" name="Resources">
|
||||
<GROUP id="{1C0FC3AA-01F6-8768-381C-200ED18AB5F2}" name="fonts">
|
||||
<FILE id="sQn22Z" name="font.ttf" compile="0" resource="1" file="Resources/fonts/font.ttf"/>
|
||||
<FILE id="R0Gs1t" name="FiraSans-Bold.ttf" compile="0" resource="1"
|
||||
file="Resources/fonts/FiraSans-Bold.ttf"/>
|
||||
<FILE id="IueZb0" name="FiraSans-Italic.ttf" compile="0" resource="1"
|
||||
file="Resources/fonts/FiraSans-Italic.ttf"/>
|
||||
<FILE id="arLp4R" name="FiraSans-Regular.ttf" compile="0" resource="1"
|
||||
file="Resources/fonts/FiraSans-Regular.ttf"/>
|
||||
</GROUP>
|
||||
<GROUP id="{525C568C-29E9-D0A2-9773-8A04981C5575}" name="images">
|
||||
<FILE id="jI9VSZ" name="logo.png" compile="0" resource="1" file="Resources/images/logo.png"/>
|
||||
|
|
Ładowanie…
Reference in New Issue