Add better error messages and add support for mp3/ogg/flac

progress-bar
James H Ball 2025-02-03 18:30:14 +00:00
rodzic 37f4252a00
commit 96049d3ea2
8 zmienionych plików z 67 dodań i 34 usunięć

Wyświetl plik

@ -10,7 +10,7 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
fileButton.setButtonText("Choose File(s)"); fileButton.setButtonText("Choose File(s)");
fileButton.onClick = [this] { fileButton.onClick = [this] {
chooser = std::make_unique<juce::FileChooser>("Open", audioProcessor.lastOpenedDirectory, "*.obj;*.svg;*.lua;*.txt;*.gpla;*.gif;*.png;*.jpg;*.jpeg;*.wav;*.aiff"); chooser = std::make_unique<juce::FileChooser>("Open", audioProcessor.lastOpenedDirectory, "*.obj;*.svg;*.lua;*.txt;*.gpla;*.gif;*.png;*.jpg;*.jpeg;*.wav;*.aiff;*.ogg;*.flac;*.mp3");
auto flags = juce::FileBrowserComponent::openMode | juce::FileBrowserComponent::canSelectMultipleItems | auto flags = juce::FileBrowserComponent::openMode | juce::FileBrowserComponent::canSelectMultipleItems |
juce::FileBrowserComponent::canSelectFiles; juce::FileBrowserComponent::canSelectFiles;

Wyświetl plik

@ -109,6 +109,9 @@ bool OscirenderAudioProcessorEditor::isInterestedInFileDrag(const juce::StringAr
return return
file.hasFileExtension("wav") || file.hasFileExtension("wav") ||
file.hasFileExtension("aiff") || file.hasFileExtension("aiff") ||
file.hasFileExtension("ogg") ||
file.hasFileExtension("flac") ||
file.hasFileExtension("mp3") ||
file.hasFileExtension("osci") || file.hasFileExtension("osci") ||
file.hasFileExtension("txt") || file.hasFileExtension("txt") ||
file.hasFileExtension("lua") || file.hasFileExtension("lua") ||
@ -139,7 +142,8 @@ void OscirenderAudioProcessorEditor::filesDropped(const juce::StringArray& files
} }
bool OscirenderAudioProcessorEditor::isBinaryFile(juce::String name) { bool OscirenderAudioProcessorEditor::isBinaryFile(juce::String name) {
return name.endsWith(".gpla") || name.endsWith(".gif") || name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".wav") || name.endsWith(".aiff"); name = name.toLowerCase();
return name.endsWith(".gpla") || name.endsWith(".gif") || name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".wav") || name.endsWith(".aiff") || name.endsWith(".ogg") || name.endsWith(".mp3") || name.endsWith(".flac");
} }
// parsersLock must be held // parsersLock must be held

Wyświetl plik

@ -321,7 +321,7 @@ void OscirenderAudioProcessor::openFile(int index) {
if (index < 0 || index >= fileBlocks.size()) { if (index < 0 || index >= fileBlocks.size()) {
return; return;
} }
parsers[index]->parse(juce::String(fileIds[index]), fileNames[index].fromLastOccurrenceOf(".", true, false), std::make_unique<juce::MemoryInputStream>(*fileBlocks[index], false), font); parsers[index]->parse(juce::String(fileIds[index]), fileNames[index].fromLastOccurrenceOf(".", true, false).toLowerCase(), std::make_unique<juce::MemoryInputStream>(*fileBlocks[index], false), font);
changeCurrentFile(index); changeCurrentFile(index);
} }

Wyświetl plik

@ -10,9 +10,9 @@ OsciMainMenuBarModel::OsciMainMenuBarModel(OscirenderAudioProcessor& p, Oscirend
addTopLevelMenu("Audio"); addTopLevelMenu("Audio");
} }
addMenuItem(0, "Open", [this] { editor.openProject(); }); addMenuItem(0, "Open Project", [this] { editor.openProject(); });
addMenuItem(0, "Save", [this] { editor.saveProject(); }); addMenuItem(0, "Save Project", [this] { editor.saveProject(); });
addMenuItem(0, "Save As", [this] { editor.saveProjectAs(); }); addMenuItem(0, "Save Project As", [this] { editor.saveProjectAs(); });
if (editor.processor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone) { if (editor.processor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone) {
addMenuItem(0, "Create New Project", [this] { editor.resetToDefault(); }); addMenuItem(0, "Create New Project", [this] { editor.resetToDefault(); });
} }

Wyświetl plik

@ -12,6 +12,9 @@ ImageParser::ImageParser(OscirenderAudioProcessor& p, juce::String extension, ju
if (output.openedOk()) { if (output.openedOk()) {
output.write(image.getData(), image.getSize()); output.write(image.getData(), image.getSize());
output.flush(); output.flush();
} else {
handleError("The image could not be loaded.");
return;
} }
} }
@ -43,9 +46,13 @@ ImageParser::ImageParser(OscirenderAudioProcessor& p, juce::String extension, ju
} }
gd_close_gif(gif); gd_close_gif(gif);
} else {
handleError("The image could not be loaded. Please try optimising the GIF with https://ezgif.com/optimize.");
return;
} }
} else { } else {
juce::Image image = juce::ImageFileFormat::loadFrom(file); juce::Image image = juce::ImageFileFormat::loadFrom(file);
if (image.isValid()) {
image.desaturate(); image.desaturate();
width = image.getWidth(); width = image.getWidth();
@ -65,16 +72,19 @@ ImageParser::ImageParser(OscirenderAudioProcessor& p, juce::String extension, ju
frames[0][index] = pixel.isTransparent() ? 0 : juce::jmax(1, value); frames[0][index] = pixel.isTransparent() ? 0 : juce::jmax(1, value);
} }
} }
} else {
handleError("The image could not be loaded.");
return;
}
} }
if (frames.size() == 0) { if (frames.size() == 0) {
juce::MessageManager::callAsync([this] { if (extension.equalsIgnoreCase(".gif")) {
juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::AlertIconType::WarningIcon, "Invalid GIF", "The image could not be loaded. Please try optimising the GIF with https://ezgif.com/optimize."); handleError("The image could not be loaded. Please try optimising the GIF with https://ezgif.com/optimize.");
}); } else {
handleError("The image could not be loaded.");
width = 1; }
height = 1; return;
frames.emplace_back(std::vector<uint8_t>(1));
} }
setFrame(0); setFrame(0);
@ -82,6 +92,17 @@ ImageParser::ImageParser(OscirenderAudioProcessor& p, juce::String extension, ju
ImageParser::~ImageParser() {} ImageParser::~ImageParser() {}
void ImageParser::handleError(juce::String message) {
juce::MessageManager::callAsync([this, message] {
juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::AlertIconType::WarningIcon, "Error", message);
});
width = 1;
height = 1;
frames.emplace_back(std::vector<uint8_t>(1));
setFrame(0);
}
void ImageParser::setFrame(int index) { void ImageParser::setFrame(int index) {
// Ensure that the frame number is within the bounds of the number of frames // Ensure that the frame number is within the bounds of the number of frames
// This weird modulo trick is to handle negative numbers // This weird modulo trick is to handle negative numbers

Wyświetl plik

@ -21,6 +21,7 @@ private:
void findWhite(double thresholdPow, bool invert); void findWhite(double thresholdPow, bool invert);
bool isOverThreshold(double pixel, double thresholdValue); bool isOverThreshold(double pixel, double thresholdValue);
int jumpFrequency(); int jumpFrequency();
void handleError(juce::String message);
OscirenderAudioProcessor& audioProcessor; OscirenderAudioProcessor& audioProcessor;
juce::Random rng; juce::Random rng;

Wyświetl plik

@ -41,8 +41,7 @@ void FileParser::parse(juce::String fileId, juce::String extension, std::unique_
} }
if (isBinary) { if (isBinary) {
gpla = std::make_shared<LineArtParser>(gplaData, bytesRead); gpla = std::make_shared<LineArtParser>(gplaData, bytesRead);
} } else {
else {
stream->setPosition(0); stream->setPosition(0);
gpla = std::make_shared<LineArtParser>(stream->readEntireStreamAsString()); gpla = std::make_shared<LineArtParser>(stream->readEntireStreamAsString());
} }
@ -50,9 +49,13 @@ void FileParser::parse(juce::String fileId, juce::String extension, std::unique_
juce::MemoryBlock buffer{}; juce::MemoryBlock buffer{};
int bytesRead = stream->readIntoMemoryBlock(buffer); int bytesRead = stream->readIntoMemoryBlock(buffer);
img = std::make_shared<ImageParser>(audioProcessor, extension, buffer); img = std::make_shared<ImageParser>(audioProcessor, extension, buffer);
} else if (extension == ".wav" || extension == ".aiff") { } else if (extension == ".wav" || extension == ".aiff" || extension == ".flac" || extension == ".ogg" || extension == ".mp3") {
wav = std::make_shared<WavParser>(audioProcessor); wav = std::make_shared<WavParser>(audioProcessor);
wav->parse(std::move(stream)); 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.");
});
}
} }
isAnimatable = gpla != nullptr || (img != nullptr && extension == ".gif"); isAnimatable = gpla != nullptr || (img != nullptr && extension == ".gif");

Wyświetl plik

@ -22,6 +22,10 @@ SvgParser::SvgParser(juce::String svgFile) {
} }
} }
juce::MessageManager::callAsync([this] {
juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::AlertIconType::WarningIcon, "Error", "The SVG could not be loaded.");
});
// draw an X to indicate an error. // draw an X to indicate an error.
shapes.push_back(std::make_unique<Line>(-0.5, -0.5, 0.5, 0.5)); shapes.push_back(std::make_unique<Line>(-0.5, -0.5, 0.5, 0.5));
shapes.push_back(std::make_unique<Line>(-0.5, 0.5, 0.5, -0.5)); shapes.push_back(std::make_unique<Line>(-0.5, 0.5, 0.5, -0.5));