2023-01-09 21:58:49 +00:00
|
|
|
#include "PluginProcessor.h"
|
|
|
|
#include "PluginEditor.h"
|
2023-12-20 20:58:08 +00:00
|
|
|
#include <juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h>
|
2023-01-09 21:58:49 +00:00
|
|
|
|
2023-03-29 16:19:16 +00:00
|
|
|
OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioProcessor& p)
|
2023-07-10 12:17:04 +00:00
|
|
|
: AudioProcessorEditor(&p), audioProcessor(p), collapseButton("Collapse", juce::Colours::white, juce::Colours::white, juce::Colours::white)
|
2023-01-09 21:58:49 +00:00
|
|
|
{
|
2023-12-10 21:57:34 +00:00
|
|
|
juce::Desktop::getInstance().setDefaultLookAndFeel(&lookAndFeel);
|
|
|
|
setLookAndFeel(&lookAndFeel);
|
2023-07-10 12:17:04 +00:00
|
|
|
addAndMakeVisible(volume);
|
2023-03-29 11:51:22 +00:00
|
|
|
|
2023-12-20 20:58:08 +00:00
|
|
|
#if JUCE_MAC
|
|
|
|
if (audioProcessor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone) {
|
|
|
|
usingNativeMenuBar = true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!usingNativeMenuBar) {
|
|
|
|
menuBar.setModel(&menuBarModel);
|
|
|
|
addAndMakeVisible(menuBar);
|
|
|
|
}
|
2023-07-25 19:44:18 +00:00
|
|
|
|
2023-03-29 14:02:29 +00:00
|
|
|
addAndMakeVisible(collapseButton);
|
|
|
|
collapseButton.onClick = [this] {
|
2023-07-04 19:47:54 +00:00
|
|
|
juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock);
|
2023-07-22 21:00:59 +00:00
|
|
|
int originalIndex = audioProcessor.getCurrentFileIndex();
|
|
|
|
int index = editingPerspective ? 0 : audioProcessor.getCurrentFileIndex() + 1;
|
|
|
|
if (originalIndex != -1 || editingPerspective) {
|
2023-07-02 12:09:24 +00:00
|
|
|
if (codeEditors[index]->isVisible()) {
|
|
|
|
codeEditors[index]->setVisible(false);
|
|
|
|
} else {
|
|
|
|
codeEditors[index]->setVisible(true);
|
|
|
|
updateCodeEditor();
|
|
|
|
}
|
2023-07-22 17:42:30 +00:00
|
|
|
triggerAsyncUpdate();
|
2023-07-02 12:09:24 +00:00
|
|
|
}
|
2023-03-29 14:02:29 +00:00
|
|
|
};
|
|
|
|
juce::Path path;
|
2023-07-02 12:09:24 +00:00
|
|
|
path.addTriangle(0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f);
|
2023-03-29 14:02:29 +00:00
|
|
|
collapseButton.setShape(path, false, true, true);
|
2023-12-18 13:41:56 +00:00
|
|
|
collapseButton.setMouseCursor(juce::MouseCursor::PointingHandCursor);
|
2023-07-05 16:57:41 +00:00
|
|
|
|
2023-08-27 16:47:30 +00:00
|
|
|
colourScheme = lookAndFeel.getDefaultColourScheme();
|
|
|
|
|
2023-07-22 21:00:59 +00:00
|
|
|
{
|
|
|
|
juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock);
|
2023-07-28 12:55:44 +00:00
|
|
|
initialiseCodeEditors();
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
juce::MessageManagerLock lock;
|
2023-09-10 16:43:37 +00:00
|
|
|
audioProcessor.fileChangeBroadcaster.addChangeListener(this);
|
2023-07-28 12:55:44 +00:00
|
|
|
audioProcessor.broadcaster.addChangeListener(this);
|
2023-07-05 16:57:41 +00:00
|
|
|
}
|
|
|
|
|
2023-07-28 20:10:21 +00:00
|
|
|
if (audioProcessor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone) {
|
|
|
|
if (juce::TopLevelWindow::getNumTopLevelWindows() == 1) {
|
|
|
|
juce::TopLevelWindow* w = juce::TopLevelWindow::getTopLevelWindow(0);
|
|
|
|
w->setColour(juce::ResizableWindow::backgroundColourId, Colours::veryDark);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-05 16:57:41 +00:00
|
|
|
setSize(1100, 750);
|
|
|
|
setResizable(true, true);
|
2023-07-10 17:04:24 +00:00
|
|
|
setResizeLimits(500, 400, 999999, 999999);
|
2023-11-25 22:10:36 +00:00
|
|
|
|
|
|
|
layout.setItemLayout(0, -0.3, -1.0, -0.7);
|
2023-12-10 21:57:34 +00:00
|
|
|
layout.setItemLayout(1, 7, 7, 7);
|
2023-11-25 22:10:36 +00:00
|
|
|
layout.setItemLayout(2, -0.1, -1.0, -0.3);
|
|
|
|
|
2023-12-18 13:41:56 +00:00
|
|
|
addAndMakeVisible(settings);
|
2023-11-25 22:10:36 +00:00
|
|
|
addAndMakeVisible(resizerBar);
|
2023-01-09 21:58:49 +00:00
|
|
|
}
|
|
|
|
|
2023-07-28 12:55:44 +00:00
|
|
|
OscirenderAudioProcessorEditor::~OscirenderAudioProcessorEditor() {
|
2023-07-28 20:10:21 +00:00
|
|
|
setLookAndFeel(nullptr);
|
|
|
|
juce::Desktop::getInstance().setDefaultLookAndFeel(nullptr);
|
2023-07-28 12:55:44 +00:00
|
|
|
juce::MessageManagerLock lock;
|
|
|
|
audioProcessor.broadcaster.removeChangeListener(this);
|
2023-09-10 16:43:37 +00:00
|
|
|
audioProcessor.fileChangeBroadcaster.removeChangeListener(this);
|
2023-07-28 12:55:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// parsersLock must be held
|
|
|
|
void OscirenderAudioProcessorEditor::initialiseCodeEditors() {
|
|
|
|
codeEditors.clear();
|
2023-08-27 21:01:37 +00:00
|
|
|
codeDocuments.clear();
|
2023-07-28 12:55:44 +00:00
|
|
|
// -1 is the perspective function
|
|
|
|
addCodeEditor(-1);
|
|
|
|
for (int i = 0; i < audioProcessor.numFiles(); i++) {
|
|
|
|
addCodeEditor(i);
|
|
|
|
}
|
|
|
|
fileUpdated(audioProcessor.getCurrentFileName());
|
|
|
|
}
|
2023-01-09 21:58:49 +00:00
|
|
|
|
2023-07-25 19:44:18 +00:00
|
|
|
void OscirenderAudioProcessorEditor::paint(juce::Graphics& g) {
|
2023-03-29 14:02:29 +00:00
|
|
|
g.fillAll(getLookAndFeel().findColour(juce::ResizableWindow::backgroundColourId));
|
2023-01-09 21:58:49 +00:00
|
|
|
|
2023-03-29 14:02:29 +00:00
|
|
|
g.setColour(juce::Colours::white);
|
|
|
|
g.setFont(15.0f);
|
2023-01-09 21:58:49 +00:00
|
|
|
}
|
|
|
|
|
2023-01-15 17:01:27 +00:00
|
|
|
void OscirenderAudioProcessorEditor::resized() {
|
2023-03-29 14:02:29 +00:00
|
|
|
auto area = getLocalBounds();
|
2023-12-20 20:58:08 +00:00
|
|
|
if (!usingNativeMenuBar) {
|
|
|
|
menuBar.setBounds(area.removeFromTop(25));
|
|
|
|
}
|
|
|
|
|
2023-07-25 19:44:18 +00:00
|
|
|
area.removeFromTop(2);
|
2023-07-10 17:04:24 +00:00
|
|
|
area.removeFromLeft(3);
|
2023-07-10 16:42:22 +00:00
|
|
|
auto volumeArea = area.removeFromLeft(30);
|
2023-07-10 21:00:36 +00:00
|
|
|
volume.setBounds(volumeArea.withSizeKeepingCentre(volumeArea.getWidth(), juce::jmin(volumeArea.getHeight(), 300)));
|
2023-07-10 17:04:24 +00:00
|
|
|
area.removeFromLeft(3);
|
2023-07-22 21:00:59 +00:00
|
|
|
bool editorVisible = false;
|
2023-11-25 22:10:36 +00:00
|
|
|
|
|
|
|
juce::Component dummy;
|
|
|
|
|
2023-07-22 21:00:59 +00:00
|
|
|
{
|
|
|
|
juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock);
|
2023-11-25 22:10:36 +00:00
|
|
|
|
2023-07-22 21:00:59 +00:00
|
|
|
int originalIndex = audioProcessor.getCurrentFileIndex();
|
|
|
|
int index = editingPerspective ? 0 : audioProcessor.getCurrentFileIndex() + 1;
|
|
|
|
if (originalIndex != -1 || editingPerspective) {
|
|
|
|
if (codeEditors[index]->isVisible()) {
|
|
|
|
editorVisible = true;
|
2023-11-25 22:10:36 +00:00
|
|
|
|
|
|
|
juce::Component* columns[] = { &dummy, &resizerBar, codeEditors[index].get() };
|
2023-12-18 13:41:56 +00:00
|
|
|
|
2023-11-25 22:10:36 +00:00
|
|
|
layout.layOutComponents(columns, 3, area.getX(), area.getY(), area.getWidth(), area.getHeight(), false, true);
|
|
|
|
auto dummyBounds = dummy.getBounds();
|
|
|
|
collapseButton.setBounds(dummyBounds.removeFromRight(20));
|
|
|
|
|
|
|
|
area = dummyBounds;
|
|
|
|
|
2023-07-22 21:00:59 +00:00
|
|
|
} else {
|
|
|
|
codeEditors[index]->setBounds(0, 0, 0, 0);
|
2023-12-18 13:41:56 +00:00
|
|
|
resizerBar.setBounds(0, 0, 0, 0);
|
2023-11-25 22:10:36 +00:00
|
|
|
collapseButton.setBounds(area.removeFromRight(20));
|
2023-07-22 21:00:59 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
collapseButton.setBounds(0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (editorVisible) {
|
|
|
|
juce::Path path;
|
|
|
|
path.addTriangle(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f);
|
|
|
|
collapseButton.setShape(path, false, true, true);
|
2023-07-02 12:09:24 +00:00
|
|
|
} else {
|
2023-07-22 21:00:59 +00:00
|
|
|
juce::Path path;
|
|
|
|
path.addTriangle(0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f);
|
|
|
|
collapseButton.setShape(path, false, true, true);
|
|
|
|
}
|
2023-07-28 20:10:21 +00:00
|
|
|
|
2023-12-18 13:41:56 +00:00
|
|
|
settings.setBounds(area);
|
2023-07-28 20:10:21 +00:00
|
|
|
repaint();
|
2023-03-29 16:19:16 +00:00
|
|
|
}
|
|
|
|
|
2023-07-02 12:09:24 +00:00
|
|
|
void OscirenderAudioProcessorEditor::addCodeEditor(int index) {
|
2023-07-22 21:00:59 +00:00
|
|
|
int originalIndex = index;
|
|
|
|
index++;
|
|
|
|
std::shared_ptr<juce::CodeDocument> codeDocument;
|
2023-12-20 17:13:38 +00:00
|
|
|
std::shared_ptr<ErrorCodeEditorComponent> editor;
|
2023-07-22 21:00:59 +00:00
|
|
|
|
|
|
|
if (index == 0) {
|
|
|
|
codeDocument = perspectiveCodeDocument;
|
|
|
|
editor = perspectiveCodeEditor;
|
|
|
|
} else {
|
|
|
|
codeDocument = std::make_shared<juce::CodeDocument>();
|
|
|
|
juce::String extension = audioProcessor.getFileName(originalIndex).fromLastOccurrenceOf(".", true, false);
|
|
|
|
juce::CodeTokeniser* tokeniser = nullptr;
|
|
|
|
if (extension == ".lua") {
|
|
|
|
tokeniser = &luaTokeniser;
|
|
|
|
} else if (extension == ".svg") {
|
|
|
|
tokeniser = &xmlTokeniser;
|
|
|
|
}
|
2023-12-20 18:43:03 +00:00
|
|
|
editor = std::make_shared<ErrorCodeEditorComponent>(*codeDocument, tokeniser, audioProcessor, audioProcessor.getFileId(originalIndex));
|
2023-07-22 21:00:59 +00:00
|
|
|
}
|
|
|
|
|
2023-07-02 12:09:24 +00:00
|
|
|
codeDocuments.insert(codeDocuments.begin() + index, codeDocument);
|
2023-07-22 21:00:59 +00:00
|
|
|
codeEditors.insert(codeEditors.begin() + index, editor);
|
|
|
|
addChildComponent(*editor);
|
2023-07-02 12:09:24 +00:00
|
|
|
// I need to disable accessibility otherwise it doesn't work! Appears to be a JUCE issue, very annoying!
|
|
|
|
editor->setAccessible(false);
|
|
|
|
// listen for changes to the code editor
|
|
|
|
codeDocument->addListener(this);
|
2023-08-27 16:47:30 +00:00
|
|
|
editor->setColourScheme(colourScheme);
|
2023-07-02 12:09:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderAudioProcessorEditor::removeCodeEditor(int index) {
|
2023-07-22 21:00:59 +00:00
|
|
|
index++;
|
2023-07-02 12:09:24 +00:00
|
|
|
codeEditors.erase(codeEditors.begin() + index);
|
|
|
|
codeDocuments.erase(codeDocuments.begin() + index);
|
|
|
|
}
|
|
|
|
|
2023-07-04 19:47:54 +00:00
|
|
|
|
2023-07-05 14:17:17 +00:00
|
|
|
// parsersLock AND effectsLock must be locked before calling this function
|
2023-03-30 16:28:47 +00:00
|
|
|
void OscirenderAudioProcessorEditor::updateCodeEditor() {
|
2023-07-02 12:09:24 +00:00
|
|
|
// check if any code editors are visible
|
|
|
|
bool visible = false;
|
|
|
|
for (int i = 0; i < codeEditors.size(); i++) {
|
|
|
|
if (codeEditors[i]->isVisible()) {
|
2023-07-22 21:00:59 +00:00
|
|
|
visible = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int originalIndex = audioProcessor.getCurrentFileIndex();
|
|
|
|
int index = editingPerspective ? 0 : audioProcessor.getCurrentFileIndex() + 1;
|
|
|
|
if ((originalIndex != -1 || editingPerspective) && visible) {
|
2023-07-02 12:09:24 +00:00
|
|
|
for (int i = 0; i < codeEditors.size(); i++) {
|
2023-07-04 19:47:54 +00:00
|
|
|
codeEditors[i]->setVisible(false);
|
|
|
|
}
|
2023-07-02 12:09:24 +00:00
|
|
|
codeEditors[index]->setVisible(true);
|
2023-09-11 20:28:34 +00:00
|
|
|
// used so that codeDocumentTextInserted and codeDocumentTextDeleted know whether the parserLock
|
|
|
|
// is held by the message thread or not. We hold the lock in this function, but not when the
|
|
|
|
// code document is updated by the user editing text. Since both functions are called by the
|
|
|
|
// message thread, this is safe.
|
|
|
|
updatingDocumentsWithParserLock = true;
|
2023-07-22 21:00:59 +00:00
|
|
|
if (index == 0) {
|
|
|
|
codeEditors[index]->loadContent(audioProcessor.perspectiveEffect->getCode());
|
|
|
|
} else {
|
|
|
|
codeEditors[index]->loadContent(juce::MemoryInputStream(*audioProcessor.getFileBlock(originalIndex), false).readEntireStreamAsString());
|
|
|
|
}
|
2023-09-11 20:28:34 +00:00
|
|
|
updatingDocumentsWithParserLock = false;
|
2023-03-30 20:09:53 +00:00
|
|
|
}
|
2023-07-22 17:42:30 +00:00
|
|
|
triggerAsyncUpdate();
|
2023-03-29 16:19:16 +00:00
|
|
|
}
|
2023-07-04 19:47:54 +00:00
|
|
|
|
2023-07-05 16:57:41 +00:00
|
|
|
// parsersLock MUST be locked before calling this function
|
2023-07-05 21:45:51 +00:00
|
|
|
void OscirenderAudioProcessorEditor::fileUpdated(juce::String fileName) {
|
2023-08-29 19:47:13 +00:00
|
|
|
settings.fileUpdated(fileName);
|
2023-07-05 21:45:51 +00:00
|
|
|
updateCodeEditor();
|
2023-07-04 19:47:54 +00:00
|
|
|
}
|
2023-07-04 19:59:47 +00:00
|
|
|
|
2023-07-22 17:42:30 +00:00
|
|
|
void OscirenderAudioProcessorEditor::handleAsyncUpdate() {
|
|
|
|
resized();
|
|
|
|
}
|
|
|
|
|
2023-07-28 12:55:44 +00:00
|
|
|
void OscirenderAudioProcessorEditor::changeListenerCallback(juce::ChangeBroadcaster* source) {
|
|
|
|
juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock);
|
2023-09-10 16:43:37 +00:00
|
|
|
if (source == &audioProcessor.broadcaster) {
|
|
|
|
initialiseCodeEditors();
|
|
|
|
settings.update();
|
|
|
|
} else if (source == &audioProcessor.fileChangeBroadcaster) {
|
|
|
|
// triggered when the audioProcessor changes the current file (e.g. to Blender)
|
|
|
|
settings.fileUpdated(audioProcessor.getCurrentFileName());
|
|
|
|
}
|
2023-07-28 12:55:44 +00:00
|
|
|
}
|
|
|
|
|
2023-07-22 21:00:59 +00:00
|
|
|
void OscirenderAudioProcessorEditor::editPerspectiveFunction(bool enable) {
|
|
|
|
editingPerspective = enable;
|
|
|
|
juce::SpinLock::ScopedLockType lock1(audioProcessor.parsersLock);
|
|
|
|
juce::SpinLock::ScopedLockType lock2(audioProcessor.effectsLock);
|
|
|
|
codeEditors[0]->setVisible(enable);
|
|
|
|
updateCodeEditor();
|
|
|
|
}
|
|
|
|
|
2023-07-05 14:17:17 +00:00
|
|
|
// parsersLock AND effectsLock must be locked before calling this function
|
2023-03-30 16:28:47 +00:00
|
|
|
void OscirenderAudioProcessorEditor::codeDocumentTextInserted(const juce::String& newText, int insertIndex) {
|
2023-09-11 20:28:34 +00:00
|
|
|
if (updatingDocumentsWithParserLock) {
|
|
|
|
updateCodeDocument();
|
|
|
|
} else {
|
|
|
|
juce::SpinLock::ScopedLockType parserLock(audioProcessor.parsersLock);
|
|
|
|
updateCodeDocument();
|
|
|
|
}
|
2023-03-29 16:19:16 +00:00
|
|
|
}
|
|
|
|
|
2023-07-05 14:17:17 +00:00
|
|
|
// parsersLock AND effectsLock must be locked before calling this function
|
2023-03-30 16:28:47 +00:00
|
|
|
void OscirenderAudioProcessorEditor::codeDocumentTextDeleted(int startIndex, int endIndex) {
|
2023-09-11 20:28:34 +00:00
|
|
|
if (updatingDocumentsWithParserLock) {
|
|
|
|
updateCodeDocument();
|
|
|
|
} else {
|
|
|
|
juce::SpinLock::ScopedLockType parserLock(audioProcessor.parsersLock);
|
|
|
|
updateCodeDocument();
|
|
|
|
}
|
2023-07-04 19:59:47 +00:00
|
|
|
}
|
|
|
|
|
2023-07-22 21:00:59 +00:00
|
|
|
// parsersLock AND effectsLock must be locked before calling this function
|
2023-07-04 19:59:47 +00:00
|
|
|
void OscirenderAudioProcessorEditor::updateCodeDocument() {
|
2023-07-22 21:00:59 +00:00
|
|
|
if (editingPerspective) {
|
|
|
|
juce::String file = codeDocuments[0]->getAllContent();
|
|
|
|
audioProcessor.perspectiveEffect->updateCode(file);
|
2023-10-19 11:20:24 +00:00
|
|
|
audioProcessor.updateLuaValues();
|
2023-07-22 21:00:59 +00:00
|
|
|
} else {
|
|
|
|
int originalIndex = audioProcessor.getCurrentFileIndex();
|
|
|
|
int index = audioProcessor.getCurrentFileIndex();
|
|
|
|
index++;
|
|
|
|
juce::String file = codeDocuments[index]->getAllContent();
|
|
|
|
audioProcessor.updateFileBlock(originalIndex, std::make_shared<juce::MemoryBlock>(file.toRawUTF8(), file.getNumBytesAsUTF8() + 1));
|
|
|
|
}
|
2023-03-30 20:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OscirenderAudioProcessorEditor::keyPressed(const juce::KeyPress& key) {
|
2023-07-25 19:44:18 +00:00
|
|
|
bool consumeKey1 = true;
|
|
|
|
{
|
|
|
|
juce::SpinLock::ScopedLockType parserLock(audioProcessor.parsersLock);
|
|
|
|
juce::SpinLock::ScopedLockType effectsLock(audioProcessor.effectsLock);
|
|
|
|
|
|
|
|
int numFiles = audioProcessor.numFiles();
|
|
|
|
int currentFile = audioProcessor.getCurrentFileIndex();
|
|
|
|
bool changedFile = false;
|
|
|
|
|
|
|
|
if (key.getTextCharacter() == 'j') {
|
|
|
|
if (numFiles > 1) {
|
|
|
|
currentFile++;
|
|
|
|
if (currentFile == numFiles) {
|
|
|
|
currentFile = 0;
|
|
|
|
}
|
|
|
|
changedFile = true;
|
|
|
|
}
|
|
|
|
} else if (key.getTextCharacter() == 'k') {
|
|
|
|
if (numFiles > 1) {
|
|
|
|
currentFile--;
|
|
|
|
if (currentFile < 0) {
|
|
|
|
currentFile = numFiles - 1;
|
|
|
|
}
|
|
|
|
changedFile = true;
|
2023-07-05 14:17:17 +00:00
|
|
|
}
|
2023-07-25 19:44:18 +00:00
|
|
|
} else {
|
|
|
|
consumeKey1 = false;
|
2023-03-30 20:09:53 +00:00
|
|
|
}
|
2023-07-25 19:44:18 +00:00
|
|
|
|
|
|
|
if (changedFile) {
|
|
|
|
audioProcessor.changeCurrentFile(currentFile);
|
|
|
|
fileUpdated(audioProcessor.getCurrentFileName());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool consumeKey2 = true;
|
|
|
|
if (key.isKeyCode(juce::KeyPress::escapeKey)) {
|
2023-08-29 19:47:13 +00:00
|
|
|
settings.disableMouseRotation();
|
2023-07-25 19:44:18 +00:00
|
|
|
} else if (key.getModifiers().isCommandDown() && key.getModifiers().isShiftDown() && key.getKeyCode() == 'S') {
|
|
|
|
saveProjectAs();
|
|
|
|
} else if (key.getModifiers().isCommandDown() && key.getKeyCode() == 'S') {
|
|
|
|
saveProject();
|
|
|
|
} else if (key.getModifiers().isCommandDown() && key.getKeyCode() == 'O') {
|
|
|
|
openProject();
|
2023-07-05 14:17:17 +00:00
|
|
|
} else {
|
2023-07-25 19:44:18 +00:00
|
|
|
consumeKey2 = false;
|
2023-07-05 14:17:17 +00:00
|
|
|
}
|
2023-07-02 12:09:24 +00:00
|
|
|
|
2023-07-25 19:44:18 +00:00
|
|
|
return consumeKey1 || consumeKey2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderAudioProcessorEditor::newProject() {
|
|
|
|
// TODO: open a default project
|
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderAudioProcessorEditor::openProject() {
|
|
|
|
chooser = std::make_unique<juce::FileChooser>("Load osci-render Project", juce::File::getSpecialLocation(juce::File::userHomeDirectory), "*.osci");
|
2023-09-09 09:02:16 +00:00
|
|
|
auto flags = juce::FileBrowserComponent::openMode |
|
|
|
|
juce::FileBrowserComponent::canSelectFiles;
|
2023-07-25 19:44:18 +00:00
|
|
|
|
|
|
|
chooser->launchAsync(flags, [this](const juce::FileChooser& chooser) {
|
|
|
|
auto file = chooser.getResult();
|
|
|
|
if (file != juce::File()) {
|
|
|
|
auto data = juce::MemoryBlock();
|
|
|
|
if (file.loadFileAsData(data)) {
|
|
|
|
audioProcessor.setStateInformation(data.getData(), data.getSize());
|
|
|
|
}
|
|
|
|
audioProcessor.currentProjectFile = file.getFullPathName();
|
|
|
|
updateTitle();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderAudioProcessorEditor::saveProject() {
|
|
|
|
if (audioProcessor.currentProjectFile.isEmpty()) {
|
|
|
|
saveProjectAs();
|
|
|
|
} else {
|
|
|
|
auto data = juce::MemoryBlock();
|
|
|
|
audioProcessor.getStateInformation(data);
|
|
|
|
auto file = juce::File(audioProcessor.currentProjectFile);
|
|
|
|
file.create();
|
|
|
|
file.replaceWithData(data.getData(), data.getSize());
|
|
|
|
updateTitle();
|
2023-03-30 20:09:53 +00:00
|
|
|
}
|
2023-07-25 19:44:18 +00:00
|
|
|
}
|
2023-07-02 12:09:24 +00:00
|
|
|
|
2023-07-25 19:44:18 +00:00
|
|
|
void OscirenderAudioProcessorEditor::saveProjectAs() {
|
|
|
|
chooser = std::make_unique<juce::FileChooser>("Save osci-render Project", juce::File::getSpecialLocation(juce::File::userHomeDirectory), "*.osci");
|
|
|
|
auto flags = juce::FileBrowserComponent::saveMode;
|
|
|
|
|
|
|
|
chooser->launchAsync(flags, [this](const juce::FileChooser& chooser) {
|
|
|
|
auto file = chooser.getResult();
|
|
|
|
if (file != juce::File()) {
|
|
|
|
audioProcessor.currentProjectFile = file.getFullPathName();
|
|
|
|
saveProject();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderAudioProcessorEditor::updateTitle() {
|
|
|
|
juce::String title = "osci-render";
|
|
|
|
if (!audioProcessor.currentProjectFile.isEmpty()) {
|
|
|
|
title += " - " + audioProcessor.currentProjectFile;
|
|
|
|
}
|
|
|
|
getTopLevelComponent()->setName(title);
|
2023-01-09 21:58:49 +00:00
|
|
|
}
|
2023-12-20 20:58:08 +00:00
|
|
|
|
|
|
|
void OscirenderAudioProcessorEditor::openAudioSettings() {
|
|
|
|
juce::StandalonePluginHolder* standalone = juce::StandalonePluginHolder::getInstance();
|
|
|
|
standalone->showAudioSettingsDialog();
|
|
|
|
}
|