kopia lustrzana https://github.com/jameshball/osci-render
Add pop-up to download ffmpeg if not already downloaded
rodzic
157676439e
commit
7b98b34b04
|
@ -45,6 +45,9 @@ private:
|
|||
OscirenderAudioProcessor& audioProcessor;
|
||||
|
||||
juce::File applicationFolder = juce::File::getSpecialLocation(juce::File::SpecialLocationType::userApplicationDataDirectory)
|
||||
#if JUCE_MAC
|
||||
.getChildFile("Application Support")
|
||||
#endif
|
||||
.getChildFile("osci-render");
|
||||
public:
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@ private:
|
|||
SosciAudioProcessor& audioProcessor;
|
||||
|
||||
juce::File applicationFolder = juce::File::getSpecialLocation(juce::File::SpecialLocationType::userApplicationDataDirectory)
|
||||
#if JUCE_MAC
|
||||
.getChildFile("Application Support")
|
||||
#endif
|
||||
.getChildFile("osci-render");
|
||||
public:
|
||||
OscirenderLookAndFeel lookAndFeel;
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
#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) {
|
||||
if (url.toString(false).endsWithIgnoreCase(".gz")) {
|
||||
uncompressOnFinish = true;
|
||||
this->file = file.getSiblingFile(file.getFileName() + ".gz");
|
||||
}
|
||||
}
|
||||
|
||||
void DownloaderComponent::run() {
|
||||
downloader = std::make_unique<DownloaderThread>(url, file, this, taskLock, task);
|
||||
downloader->startThread();
|
||||
while (!threadShouldExit()) {
|
||||
{
|
||||
juce::CriticalSection::ScopedTryLockType lock(taskLock);
|
||||
if (lock.isLocked() && task != nullptr) {
|
||||
if (task->isFinished()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
wait(100);
|
||||
}
|
||||
}
|
||||
|
||||
void DownloaderComponent::threadComplete(bool userPressedCancel) {
|
||||
if (!userPressedCancel && uncompressOnFinish && task->isFinished() && !task->hadError()) {
|
||||
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();
|
||||
} else {
|
||||
uncompressedFile.setExecutePermission(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DownloaderComponent::finished(juce::URL::DownloadTask* task, bool success) {
|
||||
notify();
|
||||
}
|
||||
|
||||
void DownloaderComponent::progress(juce::URL::DownloadTask* task, juce::int64 bytesDownloaded, juce::int64 totalLength) {
|
||||
setProgress((float)bytesDownloaded / (float)totalLength);
|
||||
}
|
||||
|
||||
void DownloaderComponent::download() {
|
||||
launchThread();
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include <JuceHeader.h>
|
||||
|
||||
class DownloaderThread : public juce::Thread {
|
||||
public:
|
||||
DownloaderThread(juce::URL url, juce::File file, juce::URL::DownloadTaskListener* listener, juce::CriticalSection& taskLock, std::unique_ptr<juce::URL::DownloadTask>& task) : juce::Thread("Downloader Thread"), url(url), file(file), listener(listener), taskLock(taskLock), task(task) {};
|
||||
|
||||
void run() override {
|
||||
juce::CriticalSection::ScopedLockType lock(taskLock);
|
||||
task = url.downloadToFile(file, juce::URL::DownloadTaskOptions().withListener(listener));
|
||||
};
|
||||
|
||||
private:
|
||||
juce::URL url;
|
||||
juce::File file;
|
||||
juce::CriticalSection& taskLock;
|
||||
juce::URL::DownloadTaskListener* listener;
|
||||
std::unique_ptr<juce::URL::DownloadTask>& task;
|
||||
};
|
||||
|
||||
class DownloaderComponent : public juce::ThreadWithProgressWindow, public juce::URL::DownloadTaskListener {
|
||||
public:
|
||||
DownloaderComponent(juce::URL url, juce::File file, juce::String title, juce::Component* parent);
|
||||
|
||||
void download();
|
||||
void run() override;
|
||||
void threadComplete(bool userPressedCancel) override;
|
||||
void finished(juce::URL::DownloadTask* task, bool success) override;
|
||||
void progress(juce::URL::DownloadTask* task, juce::int64 bytesDownloaded, juce::int64 totalLength) override;
|
||||
|
||||
private:
|
||||
|
||||
juce::URL url;
|
||||
juce::File file;
|
||||
juce::CriticalSection taskLock;
|
||||
std::unique_ptr<juce::URL::DownloadTask> task;
|
||||
std::unique_ptr<DownloaderThread> downloader;
|
||||
|
||||
bool uncompressOnFinish = false;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DownloaderComponent)
|
||||
};
|
|
@ -11,7 +11,7 @@
|
|||
#include "TexturedFragmentShader.glsl"
|
||||
#include "TexturedVertexShader.glsl"
|
||||
|
||||
VisualiserComponent::VisualiserComponent(juce::File ffmpegPath, std::function<void()>& haltRecording, AudioBackgroundThreadManager& threadManager, VisualiserSettings& settings, VisualiserComponent* parent, bool visualiserOnly) : ffmpegPath(ffmpegPath), haltRecording(haltRecording), settings(settings), threadManager(threadManager), visualiserOnly(visualiserOnly), AudioBackgroundThread("VisualiserComponent" + juce::String(parent != nullptr ? " Child" : ""), threadManager), parent(parent) {
|
||||
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) {
|
||||
|
||||
haltRecording = [this] {
|
||||
setRecording(false);
|
||||
|
@ -170,20 +170,25 @@ void VisualiserComponent::setFullScreen(bool fullScreen) {}
|
|||
|
||||
void VisualiserComponent::setRecording(bool recording) {
|
||||
if (recording) {
|
||||
if (!ffmpegFile.exists()) {
|
||||
ffmpegDownloader.download();
|
||||
record.setToggleState(false, juce::NotificationType::sendNotification);
|
||||
return;
|
||||
}
|
||||
juce::TemporaryFile tempFile = juce::TemporaryFile(".mp4");
|
||||
juce::String resolution = std::to_string(renderTexture.width) + "x" + std::to_string(renderTexture.height);
|
||||
juce::String cmd = ffmpegPath.getFullPathName() +
|
||||
" -r " + juce::String(FRAME_RATE) + " -f rawvideo -pix_fmt rgba -s " + resolution + " -i - -threads 0 -preset fast -y -pix_fmt yuv420p -crf " + juce::String(21) + " -vf vflip " + tempFile.getFile().getFullPathName();
|
||||
juce::String cmd = "\"" + ffmpegFile.getFullPathName() +
|
||||
"\" -r " + juce::String(FRAME_RATE) + " -f rawvideo -pix_fmt rgba -s " + resolution + " -i - -threads 0 -preset fast -y -pix_fmt yuv420p -crf " + juce::String(21) + " -vf vflip \"" + tempFile.getFile().getFullPathName() + "\"";
|
||||
|
||||
// open pipe to ffmpeg's stdin in binary write mode
|
||||
#if JUCE_WINDOWS
|
||||
ffmpeg = _popen(cmd.toStdString().c_str(), "wb");
|
||||
#else
|
||||
ffmpeg = popen(cmd.toStdString().c_str(), "w");
|
||||
#endif
|
||||
if (ffmpeg == nullptr) {
|
||||
DBG("popen failed: " + juce::String(std::strerror(errno)));
|
||||
}
|
||||
#endif
|
||||
framePixels.resize(renderTexture.width * renderTexture.height * 4);
|
||||
setPaused(false);
|
||||
} else if (ffmpeg != nullptr) {
|
||||
|
@ -223,7 +228,7 @@ void VisualiserComponent::resized() {
|
|||
void VisualiserComponent::popoutWindow() {
|
||||
setRecording(false);
|
||||
record.setEnabled(false);
|
||||
auto visualiser = new VisualiserComponent(ffmpegPath, haltRecording, threadManager, settings, this);
|
||||
auto visualiser = new VisualiserComponent(ffmpegFile, haltRecording, threadManager, settings, this);
|
||||
visualiser->settings.setLookAndFeel(&getLookAndFeel());
|
||||
visualiser->openSettings = openSettings;
|
||||
visualiser->closeSettings = closeSettings;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "VisualiserSettings.h"
|
||||
#include "../components/StopwatchComponent.h"
|
||||
#include "../img/qoixx.hpp"
|
||||
#include "../components/DownloaderComponent.h"
|
||||
|
||||
#define FILE_RENDER_DUMMY 0
|
||||
#define FILE_RENDER_PNG 1
|
||||
|
@ -28,7 +29,7 @@ struct Texture {
|
|||
class VisualiserWindow;
|
||||
class VisualiserComponent : public juce::Component, public AudioBackgroundThread, public juce::MouseListener, public juce::OpenGLRenderer, public juce::AsyncUpdater {
|
||||
public:
|
||||
VisualiserComponent(juce::File ffmpegPath, std::function<void()>& haltRecording, AudioBackgroundThreadManager& threadManager, VisualiserSettings& settings, VisualiserComponent* parent = nullptr, bool visualiserOnly = false);
|
||||
VisualiserComponent(juce::File ffmpegFile, std::function<void()>& haltRecording, AudioBackgroundThreadManager& threadManager, VisualiserSettings& settings, VisualiserComponent* parent = nullptr, bool visualiserOnly = false);
|
||||
~VisualiserComponent() override;
|
||||
|
||||
std::function<void()> openSettings;
|
||||
|
@ -81,7 +82,37 @@ private:
|
|||
long numFrames = 0;
|
||||
std::vector<unsigned char> framePixels;
|
||||
FILE* ffmpeg = nullptr;
|
||||
juce::File ffmpegPath;
|
||||
juce::File ffmpegFile;
|
||||
juce::String ffmpegURL = juce::String("https://github.com/eugeneware/ffmpeg-static/releases/download/b6.0/") +
|
||||
#if JUCE_WINDOWS
|
||||
#if JUCE_64BIT
|
||||
"ffmpeg-win32-x64"
|
||||
#elif JUCE_32BIT
|
||||
"ffmpeg-win32-ia32"
|
||||
#endif
|
||||
#elif JUCE_MAC
|
||||
#if JUCE_ARM
|
||||
"ffmpeg-darwin-arm64"
|
||||
#elif JUCE_INTEL
|
||||
"ffmpeg-darwin-x64"
|
||||
#endif
|
||||
#elif JUCE_LINUX
|
||||
#if JUCE_ARM
|
||||
#if JUCE_64BIT
|
||||
"ffmpeg-linux-arm64"
|
||||
#elif JUCE_32BIT
|
||||
"ffmpeg-linux-arm"
|
||||
#endif
|
||||
#elif JUCE_INTEL
|
||||
#if JUCE_64BIT
|
||||
"ffmpeg-linux-x64"
|
||||
#elif JUCE_32BIT
|
||||
"ffmpeg-linux-ia32"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
+ ".gz";
|
||||
DownloaderComponent ffmpegDownloader{ffmpegURL, ffmpegFile, "Downloading ffmpeg...", this};
|
||||
|
||||
Semaphore renderingSemaphore{0};
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
pluginManufacturer="jameshball" aaxIdentifier="sh.ball.oscirender"
|
||||
cppLanguageStandard="20" projectLineFeed=" " headerPath="./include"
|
||||
version="2.3.0" companyName="James H Ball" companyWebsite="https://osci-render.com"
|
||||
companyEmail="james@ball.sh" defines="NOMINMAX=1" pluginAUMainType="'aumf'">
|
||||
companyEmail="james@ball.sh" defines="NOMINMAX=1 INTERNET_FLAG_NO_AUTO_REDIRECT=0"
|
||||
pluginAUMainType="'aumf'">
|
||||
<MAINGROUP id="j5Ge2T" name="osci-render">
|
||||
<GROUP id="{5ABCED88-0059-A7AF-9596-DBF91DDB0292}" name="Resources">
|
||||
<GROUP id="{8930EC48-30FD-646B-9DC5-0861171F8B2E}" name="fonts">
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
aaxIdentifier="sh.ball.sosci" cppLanguageStandard="20" projectLineFeed=" "
|
||||
headerPath="./include" version="1.0.0" companyName="James H Ball"
|
||||
companyWebsite="https://osci-render.com" companyEmail="james@ball.sh"
|
||||
defines="NOMINMAX=1" pluginManufacturerCode="Jhba" pluginCode="Sosc"
|
||||
pluginAUMainType="'aufx'">
|
||||
defines="NOMINMAX=1 INTERNET_FLAG_NO_AUTO_REDIRECT=0" pluginManufacturerCode="Jhba"
|
||||
pluginCode="Sosc" pluginAUMainType="'aufx'">
|
||||
<MAINGROUP id="j5Ge2T" name="sosci">
|
||||
<GROUP id="{5ABCED88-0059-A7AF-9596-DBF91DDB0292}" name="Resources">
|
||||
<GROUP id="{1C0FC3AA-01F6-8768-381C-200ED18AB5F2}" name="fonts">
|
||||
|
@ -67,6 +67,10 @@
|
|||
file="Source/components/AboutComponent.cpp"/>
|
||||
<FILE id="FtOv3F" name="AboutComponent.h" compile="0" resource="0"
|
||||
file="Source/components/AboutComponent.h"/>
|
||||
<FILE id="aihIvJ" name="DownloaderComponent.cpp" compile="1" resource="0"
|
||||
file="Source/components/DownloaderComponent.cpp"/>
|
||||
<FILE id="wBQEfb" name="DownloaderComponent.h" compile="0" resource="0"
|
||||
file="Source/components/DownloaderComponent.h"/>
|
||||
<FILE id="xLAEHK" name="EffectComponent.cpp" compile="1" resource="0"
|
||||
file="Source/components/EffectComponent.cpp"/>
|
||||
<FILE id="u4UCwb" name="EffectComponent.h" compile="0" resource="0"
|
||||
|
|
Ładowanie…
Reference in New Issue