gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

commit 22cba1ac1ec3503461d6587a554debb1c2b5f996
parent 672b4831b9f04a0bdf398937368329954106ad1c
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Fri, 28 Feb 2025 19:04:47 +0100

support import of files with multiple waves/tables

Diffstat:
Msource/xtJucePlugin/weTablesTreeItem.cpp | 29+++++++++--------------------
Msource/xtJucePlugin/weWaveTreeItem.cpp | 29+++++++++--------------------
Msource/xtJucePlugin/xtWaveEditor.cpp | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msource/xtJucePlugin/xtWaveEditor.h | 2++
4 files changed, 106 insertions(+), 40 deletions(-)

diff --git a/source/xtJucePlugin/weTablesTreeItem.cpp b/source/xtJucePlugin/weTablesTreeItem.cpp @@ -77,7 +77,7 @@ namespace xtJucePlugin if(xt::wave::isReadOnly(getTableId())) return false; - if(files.size() == 1 && files[0].endsWithIgnoreCase(".mid") || files[1].endsWithIgnoreCase(".syx")) + if(files.size() == 1 && (files[0].endsWithIgnoreCase(".mid") || files[0].endsWithIgnoreCase(".syx"))) return true; return TreeItem::isInterestedInFileDrag(files); @@ -90,30 +90,19 @@ namespace xtJucePlugin const auto errorTitle = m_editor.getEditor().getProcessor().getProperties().name + " - Error"; - const auto sysex = WaveTreeItem::getSysexFromFiles(files); + std::map<xt::WaveId, xt::WaveData> waves; + std::map<xt::TableId, xt::TableData> tables; + m_editor.filesDropped(waves, tables, files); - if(sysex.empty()) + if (tables.empty()) { - genericUI::MessageBox::showOk(juce::AlertWindow::WarningIcon, errorTitle, "No Sysex data found in file"); + if (waves.size() == 1) + genericUI::MessageBox::showOk(juce::AlertWindow::WarningIcon, errorTitle, "This file doesn't contain a Control Table but a Wave. Please drop on a User Wave slot."); return; } - std::vector<xt::TableData> tables; - - for (const auto& s : sysex) - { - xt::TableData table; - if (xt::State::parseTableData(table, s)) - tables.push_back(table); - } - - if(tables.size() == 1) - { - m_editor.getData().setTable(m_index, tables.front()); - return; - } - - genericUI::MessageBox::showOk(juce::AlertWindow::WarningIcon, errorTitle, tables.empty() ? "No Control Table found in files" : "Multiple control tables found in file"); + m_editor.getData().setTable(m_index, tables.begin()->second); + m_editor.getData().sendTableToDevice(m_index); } void TablesTreeItem::itemClicked(const juce::MouseEvent& _mouseEvent) diff --git a/source/xtJucePlugin/weWaveTreeItem.cpp b/source/xtJucePlugin/weWaveTreeItem.cpp @@ -114,7 +114,7 @@ namespace xtJucePlugin if(xt::wave::isReadOnly(m_waveIndex)) return false; - if(files.size() == 1 && files[0].endsWithIgnoreCase(".mid") || files[1].endsWithIgnoreCase(".syx")) + if(files.size() == 1 && files[0].endsWithIgnoreCase(".mid") || files[0].endsWithIgnoreCase(".syx")) return true; return TreeItem::isInterestedInFileDrag(files); @@ -125,32 +125,21 @@ namespace xtJucePlugin if(xt::wave::isReadOnly(m_waveIndex)) return; - const auto sysex = getSysexFromFiles(files); - const auto errorTitle = m_editor.getEditor().getProcessor().getProperties().name + " - Error"; - if(sysex.empty()) - { - genericUI::MessageBox::showOk(juce::AlertWindow::WarningIcon, errorTitle, "No sysex data found in file"); - return; - } - - std::vector<xt::WaveData> waves; - - for (const auto& s : sysex) - { - xt::WaveData wave; - if(xt::State::parseWaveData(wave, sysex.front())) - waves.push_back(wave); - } + std::map<xt::WaveId, xt::WaveData> waves; + std::map<xt::TableId, xt::TableData> tables; + m_editor.filesDropped(waves, tables, files); - if(waves.size() == 1) + if (waves.empty()) { - m_editor.getData().setWave(m_waveIndex, waves.front()); + if (tables.size() == 1) + genericUI::MessageBox::showOk(juce::AlertWindow::WarningIcon, errorTitle, "This file doesn't contain a Wave but a Control Table, please drop on a User Table slot."); return; } - genericUI::MessageBox::showOk(juce::AlertWindow::WarningIcon, errorTitle, waves.empty() ? "No wave data found in file" : "Multiple waves found in file"); + m_editor.getData().setWave(m_waveIndex, waves.begin()->second); + m_editor.getData().sendWaveToDevice(m_waveIndex); } std::vector<std::vector<uint8_t>> WaveTreeItem::getSysexFromFiles(const juce::StringArray& _files) diff --git a/source/xtJucePlugin/xtWaveEditor.cpp b/source/xtJucePlugin/xtWaveEditor.cpp @@ -10,6 +10,11 @@ #include "xtController.h" #include "xtEditor.h" + +#include "jucePluginEditorLib/pluginProcessor.h" + +#include "juceUiLib/messageBox.h" + #include "xtLib/xtState.h" namespace xtJucePlugin @@ -261,4 +266,85 @@ namespace xtJucePlugin } return controlTableSlotsMenu; } + + void WaveEditor::filesDropped(std::map<xt::WaveId, xt::WaveData>& _waves, std::map<xt::TableId, xt::TableData>& _tables, const juce::StringArray& _files) + { + _waves.clear(); + _tables.clear(); + + const auto title = getEditor().getProcessor().getProperties().name + " - "; + + const auto sysex = WaveTreeItem::getSysexFromFiles(_files); + + if(sysex.empty()) + { + genericUI::MessageBox::showOk(juce::AlertWindow::WarningIcon, title + "Error", "No Sysex data found in file"); + return; + } + + for (const auto& s : sysex) + { + xt::TableData table; + xt::WaveData wave; + if (xt::State::parseTableData(table, s)) + { + const auto tableId = xt::State::getTableId(s); + _tables.emplace(tableId, table); + } + else if (xt::State::parseWaveData(wave, s)) + { + const auto waveId = xt::State::getWaveId(s); + _waves.emplace(waveId, wave); + } + } + + if (_tables.size() + _waves.size() > 1) + { + std::stringstream ss; + ss << "The imported file contains\n\n"; + if (!_tables.empty()) + { + ss << "Control Tables:\n"; + size_t c = 0; + for (const auto& it : _tables) + { + ss << getTableName(it.first); + if (++c < _tables.size()) + ss << ", "; + } + ss << "\n\n"; + } + + if (!_waves.empty()) + { + ss << "Waves:\n"; + size_t c = 0; + for (const auto& it : _waves) + { + ss << WaveTreeItem::getWaveName(it.first); + if (++c < _waves.size()) + ss << ", "; + } + ss << "\n\n"; + } + ss << "Do you want to import all of them? This will replace existing data."; + genericUI::MessageBox::showYesNo(juce::AlertWindow::QuestionIcon, title + "Question", ss.str(), [this, t = std::move(_tables), w = std::move(_waves)](genericUI::MessageBox::Result _result) + { + if (_result != genericUI::MessageBox::Result::Yes) + return; + + for (const auto& it : w) + { + m_data.setWave(it.first, it.second); + m_data.sendWaveToDevice(it.first); + } + + for (const auto& it : t) + { + m_data.setTable(it.first, it.second); + m_data.sendTableToDevice(it.first); + } + }); + } + } } diff --git a/source/xtJucePlugin/xtWaveEditor.h b/source/xtJucePlugin/xtWaveEditor.h @@ -55,6 +55,8 @@ namespace xtJucePlugin juce::PopupMenu createCopyToSelectedTableMenu(xt::WaveId _id); + void filesDropped(std::map<xt::WaveId, xt::WaveData>& _waves, std::map<xt::TableId, xt::TableData>& _tables, const juce::StringArray& _files); + private: // ComponentMovementWatcher void componentVisibilityChanged() override { checkFirstTimeVisible(); }