kopia lustrzana https://github.com/jameshball/osci-render
Add better error messages and add support for mp3/ogg/flac
rodzic
37f4252a00
commit
96049d3ea2
|
@ -10,7 +10,7 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
|
|||
fileButton.setButtonText("Choose File(s)");
|
||||
|
||||
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 |
|
||||
juce::FileBrowserComponent::canSelectFiles;
|
||||
|
||||
|
|
|
@ -109,6 +109,9 @@ bool OscirenderAudioProcessorEditor::isInterestedInFileDrag(const juce::StringAr
|
|||
return
|
||||
file.hasFileExtension("wav") ||
|
||||
file.hasFileExtension("aiff") ||
|
||||
file.hasFileExtension("ogg") ||
|
||||
file.hasFileExtension("flac") ||
|
||||
file.hasFileExtension("mp3") ||
|
||||
file.hasFileExtension("osci") ||
|
||||
file.hasFileExtension("txt") ||
|
||||
file.hasFileExtension("lua") ||
|
||||
|
@ -139,7 +142,8 @@ void OscirenderAudioProcessorEditor::filesDropped(const juce::StringArray& files
|
|||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -321,7 +321,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), 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ OsciMainMenuBarModel::OsciMainMenuBarModel(OscirenderAudioProcessor& p, Oscirend
|
|||
addTopLevelMenu("Audio");
|
||||
}
|
||||
|
||||
addMenuItem(0, "Open", [this] { editor.openProject(); });
|
||||
addMenuItem(0, "Save", [this] { editor.saveProject(); });
|
||||
addMenuItem(0, "Save As", [this] { editor.saveProjectAs(); });
|
||||
addMenuItem(0, "Open Project", [this] { editor.openProject(); });
|
||||
addMenuItem(0, "Save Project", [this] { editor.saveProject(); });
|
||||
addMenuItem(0, "Save Project As", [this] { editor.saveProjectAs(); });
|
||||
if (editor.processor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone) {
|
||||
addMenuItem(0, "Create New Project", [this] { editor.resetToDefault(); });
|
||||
}
|
||||
|
|
|
@ -12,6 +12,9 @@ ImageParser::ImageParser(OscirenderAudioProcessor& p, juce::String extension, ju
|
|||
if (output.openedOk()) {
|
||||
output.write(image.getData(), image.getSize());
|
||||
output.flush();
|
||||
} else {
|
||||
handleError("The image could not be loaded.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,38 +46,45 @@ ImageParser::ImageParser(OscirenderAudioProcessor& p, juce::String extension, ju
|
|||
}
|
||||
|
||||
gd_close_gif(gif);
|
||||
} else {
|
||||
handleError("The image could not be loaded. Please try optimising the GIF with https://ezgif.com/optimize.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
juce::Image image = juce::ImageFileFormat::loadFrom(file);
|
||||
image.desaturate();
|
||||
|
||||
width = image.getWidth();
|
||||
height = image.getHeight();
|
||||
int frameSize = width * height;
|
||||
|
||||
visited = std::vector<bool>(frameSize, false);
|
||||
frames.emplace_back(std::vector<uint8_t>(frameSize));
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
juce::Colour pixel = image.getPixelAt(x, y);
|
||||
int index = y * width + x;
|
||||
// RGB should be equal since we have desaturated
|
||||
int value = pixel.getRed();
|
||||
// value of 0 is reserved for transparent pixels
|
||||
frames[0][index] = pixel.isTransparent() ? 0 : juce::jmax(1, value);
|
||||
if (image.isValid()) {
|
||||
image.desaturate();
|
||||
|
||||
width = image.getWidth();
|
||||
height = image.getHeight();
|
||||
int frameSize = width * height;
|
||||
|
||||
visited = std::vector<bool>(frameSize, false);
|
||||
frames.emplace_back(std::vector<uint8_t>(frameSize));
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
juce::Colour pixel = image.getPixelAt(x, y);
|
||||
int index = y * width + x;
|
||||
// RGB should be equal since we have desaturated
|
||||
int value = pixel.getRed();
|
||||
// value of 0 is reserved for transparent pixels
|
||||
frames[0][index] = pixel.isTransparent() ? 0 : juce::jmax(1, value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handleError("The image could not be loaded.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (frames.size() == 0) {
|
||||
juce::MessageManager::callAsync([this] {
|
||||
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.");
|
||||
});
|
||||
|
||||
width = 1;
|
||||
height = 1;
|
||||
frames.emplace_back(std::vector<uint8_t>(1));
|
||||
if (extension.equalsIgnoreCase(".gif")) {
|
||||
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.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
setFrame(0);
|
||||
|
@ -82,6 +92,17 @@ ImageParser::ImageParser(OscirenderAudioProcessor& p, juce::String extension, ju
|
|||
|
||||
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) {
|
||||
// Ensure that the frame number is within the bounds of the number of frames
|
||||
// This weird modulo trick is to handle negative numbers
|
||||
|
|
|
@ -21,6 +21,7 @@ private:
|
|||
void findWhite(double thresholdPow, bool invert);
|
||||
bool isOverThreshold(double pixel, double thresholdValue);
|
||||
int jumpFrequency();
|
||||
void handleError(juce::String message);
|
||||
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
juce::Random rng;
|
||||
|
|
|
@ -41,8 +41,7 @@ void FileParser::parse(juce::String fileId, juce::String extension, std::unique_
|
|||
}
|
||||
if (isBinary) {
|
||||
gpla = std::make_shared<LineArtParser>(gplaData, bytesRead);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
stream->setPosition(0);
|
||||
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{};
|
||||
int bytesRead = stream->readIntoMemoryBlock(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->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");
|
||||
|
|
|
@ -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.
|
||||
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));
|
||||
|
|
Ładowanie…
Reference in New Issue