diff --git a/Resources/oscilloscope/oscilloscope.html b/Resources/oscilloscope/oscilloscope.html index eec572c..c174373 100644 --- a/Resources/oscilloscope/oscilloscope.html +++ b/Resources/oscilloscope/oscilloscope.html @@ -139,7 +139,8 @@ let externalBufferSize = 1920; let recording = false; let mediaRecorder = undefined; - let downloadCallback = undefined; + let sendVideoDataCallback = undefined; + let finishRecordingCallback = undefined; const toggleRecording = () => { recording = !recording; @@ -148,19 +149,16 @@ 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" }); + mediaRecorder.ondataavailable = (e) => { var reader = new FileReader(); - reader.readAsDataURL(video); + reader.readAsDataURL(e.data); reader.onloadend = function() { var dataUrl = reader.result; var base64 = dataUrl.split(',')[1]; - downloadCallback(base64); + sendVideoDataCallback(base64); } }; + mediaRecorder.onstop = (e) => finishRecordingCallback(); mediaRecorder.start(); } else { mediaRecorder.stop(); @@ -242,8 +240,12 @@ toggleFullscreen(); }); - downloadCallback = (base64) => { - Juce.getNativeFunction("downloadVideo")(base64); + finishRecordingCallback = () => { + Juce.getNativeFunction("finishRecording")(); + }; + + sendVideoDataCallback = (base64) => { + Juce.getNativeFunction("sendVideoData")(base64); }; diff --git a/Source/components/VisualiserComponent.cpp b/Source/components/VisualiserComponent.cpp index 6845ec8..422c813 100644 --- a/Source/components/VisualiserComponent.cpp +++ b/Source/components/VisualiserComponent.cpp @@ -270,9 +270,7 @@ void VisualiserComponent::paintXY(juce::Graphics& g, juce::Rectangle area } void VisualiserComponent::initialiseBrowser() { - if (recordingHalted != nullptr) { - recordingHalted(); - } + haltRecording(); oldBrowser = std::move(browser); if (oldBrowser != nullptr) { removeChildComponent(oldBrowser.get()); @@ -326,18 +324,18 @@ void VisualiserComponent::initialiseBrowser() { .withNativeFunction("isVisualiserOnly", [this](auto& var, auto complete) { complete(visualiserOnly); }) - .withNativeFunction("downloadVideo", [this](const juce::Array& args, auto complete) { - juce::String base64 = args[0].toString(); + .withNativeFunction("sendVideoData", [this](const juce::Array& args, auto complete) { + juce::FileOutputStream stream{tempVideoFile}; + juce::Base64::convertFromBase64(stream, args[0].toString()); + stream.flush(); + }) + .withNativeFunction("finishRecording", [this](auto& var, auto complete) { chooser = std::make_unique("Save video", juce::File::getSpecialLocation(juce::File::SpecialLocationType::userDesktopDirectory).getChildFile("osci-render.webm"), "*.webm"); chooser->launchAsync(juce::FileBrowserComponent::saveMode, - [base64](const juce::FileChooser& chooser) { + [this](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(); + tempVideoFile.moveFileTo(result); } }); }) @@ -388,9 +386,19 @@ void VisualiserComponent::toggleRecording() { if (oldVisualiser) { return; } + tempVideoFile = juce::File::createTempFile(".webm"); browser->emitEventIfBrowserIsVisible("toggleRecording", juce::var()); } +void VisualiserComponent::haltRecording() { + if (oldVisualiser) { + return; + } + if (recordingHalted != nullptr) { + recordingHalted(); + } +} + void VisualiserComponent::resized() { if (!oldVisualiser) { browser->setBounds(getLocalBounds()); @@ -415,9 +423,7 @@ void VisualiserComponent::childChanged() { } void VisualiserComponent::popoutWindow() { - if (recordingHalted != nullptr) { - recordingHalted(); - } + haltRecording(); auto visualiser = new VisualiserComponent(sampleRateManager, consumerManager, settings, this, oldVisualiser); visualiser->settings.setLookAndFeel(&getLookAndFeel()); visualiser->openSettings = openSettings; diff --git a/Source/components/VisualiserComponent.h b/Source/components/VisualiserComponent.h index 572233c..f521d4b 100644 --- a/Source/components/VisualiserComponent.h +++ b/Source/components/VisualiserComponent.h @@ -43,6 +43,7 @@ public: void setVisualiserType(bool oldVisualiser); void handleAsyncUpdate() override; void toggleRecording(); + void haltRecording(); VisualiserComponent* parent = nullptr; VisualiserComponent* child = nullptr; @@ -124,6 +125,7 @@ private: std::unique_ptr oldBrowser = nullptr; std::unique_ptr chooser; + juce::File tempVideoFile; void initialiseBrowser(); void resetBuffer();