kopia lustrzana https://github.com/jameshball/osci-render
Flip gionometer and add warning message if opening an obj file that is too large
rodzic
02095d3a15
commit
c205de10b7
|
@ -41,9 +41,7 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
|
|||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
pluginEditor.removeCodeEditor(audioProcessor.getCurrentFileIndex());
|
||||
audioProcessor.removeFile(audioProcessor.getCurrentFileIndex());
|
||||
pluginEditor.fileUpdated(audioProcessor.getCurrentFileName());
|
||||
};
|
||||
|
||||
closeFileButton.setTooltip("Close the currently open file.");
|
||||
|
|
|
@ -2,7 +2,20 @@
|
|||
#include "PluginEditor.h"
|
||||
#include "CustomStandaloneFilterWindow.h"
|
||||
|
||||
void OscirenderAudioProcessorEditor::registerFileRemovedCallback() {
|
||||
audioProcessor.setFileRemovedCallback([this](int index) {
|
||||
removeCodeEditor(index);
|
||||
fileUpdated(audioProcessor.getCurrentFileName());
|
||||
juce::MessageManager::callAsync([this] {
|
||||
resized();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioProcessor& p) : CommonPluginEditor(p, "osci-render", "osci", 1100, 750), audioProcessor(p), collapseButton("Collapse", juce::Colours::white, juce::Colours::white, juce::Colours::white) {
|
||||
// Register the file removal callback
|
||||
registerFileRemovedCallback();
|
||||
|
||||
#if !SOSCI_FEATURES
|
||||
addAndMakeVisible(upgradeButton);
|
||||
upgradeButton.onClick = [this] {
|
||||
|
@ -85,6 +98,9 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
|
|||
}
|
||||
|
||||
OscirenderAudioProcessorEditor::~OscirenderAudioProcessorEditor() {
|
||||
// Clear the file removal callback
|
||||
audioProcessor.setFileRemovedCallback(nullptr);
|
||||
|
||||
menuBar.setModel(nullptr);
|
||||
juce::MessageManagerLock lock;
|
||||
audioProcessor.broadcaster.removeChangeListener(this);
|
||||
|
|
|
@ -34,6 +34,8 @@ public:
|
|||
void editCustomFunction(bool enabled);
|
||||
|
||||
private:
|
||||
void registerFileRemovedCallback();
|
||||
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
public:
|
||||
|
||||
|
|
|
@ -293,6 +293,11 @@ void OscirenderAudioProcessor::addFile(juce::String fileName, std::shared_ptr<ju
|
|||
openFile(fileBlocks.size() - 1);
|
||||
}
|
||||
|
||||
// Setter for the callback
|
||||
void OscirenderAudioProcessor::setFileRemovedCallback(std::function<void(int)> callback) {
|
||||
fileRemovedCallback = std::move(callback);
|
||||
}
|
||||
|
||||
// parsersLock AND effectsLock must be locked before calling this function
|
||||
void OscirenderAudioProcessor::removeFile(int index) {
|
||||
if (index < 0 || index >= fileBlocks.size()) {
|
||||
|
@ -303,11 +308,32 @@ void OscirenderAudioProcessor::removeFile(int index) {
|
|||
fileIds.erase(fileIds.begin() + index);
|
||||
parsers.erase(parsers.begin() + index);
|
||||
sounds.erase(sounds.begin() + index);
|
||||
|
||||
auto newFileIndex = index;
|
||||
if (newFileIndex >= fileBlocks.size()) {
|
||||
newFileIndex = fileBlocks.size() - 1;
|
||||
}
|
||||
changeCurrentFile(newFileIndex);
|
||||
|
||||
// Notify the editor about the file removal
|
||||
if (fileRemovedCallback) {
|
||||
fileRemovedCallback(index);
|
||||
}
|
||||
}
|
||||
|
||||
// parsersLock AND effectsLock must be locked before calling this function
|
||||
void OscirenderAudioProcessor::removeParser(FileParser* parser) {
|
||||
int parserIndex = -1;
|
||||
for (int i = 0; i < parsers.size(); i++) {
|
||||
if (parsers[i].get() == parser) {
|
||||
parserIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (parserIndex >= 0) {
|
||||
removeFile(parserIndex);
|
||||
}
|
||||
}
|
||||
|
||||
int OscirenderAudioProcessor::numFiles() {
|
||||
|
@ -321,7 +347,7 @@ void OscirenderAudioProcessor::openFile(int index) {
|
|||
if (index < 0 || index >= fileBlocks.size()) {
|
||||
return;
|
||||
}
|
||||
parsers[index]->parse(juce::String(fileIds[index]), fileNames[index].fromLastOccurrenceOf(".", true, false).toLowerCase(), std::make_unique<juce::MemoryInputStream>(*fileBlocks[index], false), font);
|
||||
parsers[index]->parse(juce::String(fileIds[index]), fileNames[index], fileNames[index].fromLastOccurrenceOf(".", true, false).toLowerCase(), std::make_unique<juce::MemoryInputStream>(*fileBlocks[index], false), font);
|
||||
changeCurrentFile(index);
|
||||
}
|
||||
|
||||
|
|
|
@ -184,6 +184,9 @@ public:
|
|||
|
||||
std::function<void()> haltRecording;
|
||||
|
||||
// Add a callback to notify the editor when a file is removed
|
||||
std::function<void(int)> fileRemovedCallback;
|
||||
|
||||
void addLuaSlider();
|
||||
void updateEffectPrecedence();
|
||||
void updateFileBlock(int index, std::shared_ptr<juce::MemoryBlock> block);
|
||||
|
@ -205,6 +208,13 @@ public:
|
|||
void addErrorListener(ErrorListener* listener);
|
||||
void removeErrorListener(ErrorListener* listener);
|
||||
void notifyErrorListeners(int lineNumber, juce::String id, juce::String error);
|
||||
|
||||
// Setter for the callback
|
||||
void setFileRemovedCallback(std::function<void(int)> callback);
|
||||
|
||||
// Added declaration for the new `removeParser` method.
|
||||
void removeParser(FileParser* parser);
|
||||
|
||||
private:
|
||||
|
||||
std::atomic<bool> prevMidiEnabled = !midiEnabled->getBoolValue();
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
#include <numbers>
|
||||
#include "../PluginProcessor.h"
|
||||
|
||||
FileParser::FileParser(OscirenderAudioProcessor &p, std::function<void(int, juce::String, juce::String)> errorCallback) : errorCallback(errorCallback), audioProcessor(p) {}
|
||||
FileParser::FileParser(OscirenderAudioProcessor &p, std::function<void(int, juce::String, juce::String)> errorCallback)
|
||||
: errorCallback(errorCallback), audioProcessor(p) {}
|
||||
|
||||
void FileParser::parse(juce::String fileId, juce::String extension, std::unique_ptr<juce::InputStream> stream, juce::Font font) {
|
||||
void FileParser::parse(juce::String fileId, juce::String fileName, juce::String extension, std::unique_ptr<juce::InputStream> stream, juce::Font font) {
|
||||
juce::SpinLock::ScopedLockType scope(lock);
|
||||
|
||||
if (extension == ".lua" && lua != nullptr && lua->isFunctionValid()) {
|
||||
|
@ -22,7 +23,54 @@ void FileParser::parse(juce::String fileId, juce::String extension, std::unique_
|
|||
wav = nullptr;
|
||||
|
||||
if (extension == ".obj") {
|
||||
object = std::make_shared<WorldObject>(stream->readEntireStreamAsString().toStdString());
|
||||
// Check file size before parsing
|
||||
const int64_t fileSize = stream->getTotalLength();
|
||||
const int64_t oneMB = 1024 * 1024; // 1MB in bytes
|
||||
|
||||
// Save the file content to avoid losing it after the async operation
|
||||
juce::String objContent = stream->readEntireStreamAsString();
|
||||
|
||||
if (fileSize > oneMB) {
|
||||
// For large files, show an async warning dialog
|
||||
const double fileSizeMB = fileSize / (1024.0 * 1024.0);
|
||||
|
||||
juce::MessageManager::callAsync([this, objContent, fileSizeMB, fileName]() {
|
||||
juce::String message = juce::String::formatted(
|
||||
"The OBJ file '%s' you're trying to open is %.2f MB in size, which may cause performance issues. "
|
||||
"Would you like to continue loading it?", fileName.toRawUTF8(), fileSizeMB);
|
||||
|
||||
// Show async dialog with callbacks for user response
|
||||
juce::AlertWindow::showOkCancelBox(
|
||||
juce::AlertWindow::WarningIcon,
|
||||
"Large OBJ File",
|
||||
message,
|
||||
"Continue",
|
||||
"Cancel",
|
||||
nullptr,
|
||||
juce::ModalCallbackFunction::create([this, objContent](int result) {
|
||||
if (result == 1) { // 1 = OK button pressed
|
||||
juce::SpinLock::ScopedLockType scope(lock);
|
||||
// User chose to continue, load the file
|
||||
object = std::make_shared<WorldObject>(objContent.toStdString());
|
||||
} else {
|
||||
// User canceled, fully close this file parser
|
||||
juce::SpinLock::ScopedLockType scope(lock);
|
||||
disable(); // Mark this parser as inactive
|
||||
|
||||
// Notify the processor to remove this parser
|
||||
juce::MessageManager::callAsync([this] {
|
||||
juce::SpinLock::ScopedLockType lock1(audioProcessor.parsersLock);
|
||||
juce::SpinLock::ScopedLockType lock2(audioProcessor.effectsLock);
|
||||
audioProcessor.removeParser(this);
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// For small files, load immediately
|
||||
object = std::make_shared<WorldObject>(objContent.toStdString());
|
||||
}
|
||||
} else if (extension == ".svg") {
|
||||
svg = std::make_shared<SvgParser>(stream->readEntireStreamAsString());
|
||||
} else if (extension == ".txt") {
|
||||
|
@ -52,8 +100,10 @@ void FileParser::parse(juce::String fileId, juce::String extension, std::unique_
|
|||
} else if (extension == ".wav" || extension == ".aiff" || extension == ".flac" || extension == ".ogg" || extension == ".mp3") {
|
||||
wav = std::make_shared<WavParser>(audioProcessor);
|
||||
if (!wav->parse(std::move(stream))) {
|
||||
juce::MessageManager::callAsync([this] {
|
||||
juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::AlertIconType::WarningIcon, "Error", "The audio file could not be loaded.");
|
||||
juce::MessageManager::callAsync([this, fileName] {
|
||||
juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::AlertIconType::WarningIcon,
|
||||
"Error Loading " + fileName,
|
||||
"The audio file '" + fileName + "' could not be loaded.");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ class FileParser {
|
|||
public:
|
||||
FileParser(OscirenderAudioProcessor &p, std::function<void(int, juce::String, juce::String)> errorCallback = nullptr);
|
||||
|
||||
void parse(juce::String fileName, juce::String extension, std::unique_ptr<juce::InputStream> stream, juce::Font font);
|
||||
void parse(juce::String fileId, juce::String fileName, juce::String extension, std::unique_ptr<juce::InputStream> stream, juce::Font font);
|
||||
std::vector<std::unique_ptr<Shape>> nextFrame();
|
||||
OsciPoint nextSample(lua_State*& L, LuaVariables& vars);
|
||||
void closeLua(lua_State*& L);
|
||||
|
@ -39,7 +39,6 @@ private:
|
|||
|
||||
bool active = true;
|
||||
bool sampleSource = false;
|
||||
|
||||
juce::SpinLock lock;
|
||||
|
||||
std::shared_ptr<WorldObject> object;
|
||||
|
|
|
@ -243,7 +243,7 @@ void VisualiserComponent::runTask(const std::vector<OsciPoint>& points) {
|
|||
if (settings.isGoniometer()) {
|
||||
// x and y go to a diagonal currently, so we need to scale them down, and rotate them
|
||||
point.scale(1.0 / std::sqrt(2.0), 1.0 / std::sqrt(2.0), 1.0);
|
||||
point.rotate(0, 0, juce::MathConstants<double>::pi / 4);
|
||||
point.rotate(0, 0, -juce::MathConstants<double>::pi / 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue