/** * * Copyright (c) 2015 Pascal Gauthier. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "PluginProcessor.h" #include "PluginEditor.h" #include "CartManager.h" #include "DXLookNFeel.h" #include "PluginData.h" #include using namespace ::std; class SyxFileFilter : public FileFilter { public: SyxFileFilter() : FileFilter(".syx") {} bool isFileSuitable(const File &file) const { return file.getFileExtension().toLowerCase() == ".syx" && file.getSize() == 4104; } bool isDirectorySuitable(const File &file) const { return true; }; }; CartManager::CartManager(DexedAudioProcessorEditor *editor) : TopLevelWindow("CartManager", false) { mainWindow = editor; cartDir = DexedAudioProcessor::dexedCartDir; addAndMakeVisible(activeCart = new ProgramListBox("activepgm", 8)); activeCart->setBounds(28, 441, 800, 96); activeCart->addListener(this); addAndMakeVisible(browserCart = new ProgramListBox("browserpgm", 2)); browserCart->setBounds(635, 18, 200, 384); browserCart->addListener(this); // ------------------------- syxFileFilter = new SyxFileFilter(); timeSliceThread = new TimeSliceThread("Cartridge Directory Scanner"); timeSliceThread->startThread(); cartBrowserList = new DirectoryContentsList(syxFileFilter, *timeSliceThread); cartBrowserList->setDirectory(cartDir, true, true); cartBrowser = new FileTreeComponent(*cartBrowserList); addAndMakeVisible(cartBrowser); cartBrowser->setBounds(23, 18, 590, 384); cartBrowser->setDragAndDropDescription("Sysex Browser"); cartBrowser->addListener(this); addAndMakeVisible(closeButton = new TextButton("CLOSE")); closeButton->setBounds(4, 545, 50, 30); closeButton->addListener(this); addAndMakeVisible(loadButton = new TextButton("LOAD")); loadButton->setBounds(52, 545, 50, 30); loadButton->addListener(this); addAndMakeVisible(saveButton = new TextButton("SAVE")); saveButton->setBounds(100, 545, 50, 30); saveButton->addListener(this); addAndMakeVisible(fileMgrButton = new TextButton("SHOW DIR")); fileMgrButton->setBounds(148, 545, 70, 30); fileMgrButton->addListener(this); /* * * I've removed this since it only works on the DX7 II. TBC. * addAndMakeVisible(getDXPgmButton = new TextButton("GET DX7 PGM")); getDXPgmButton->setBounds(656, 545, 100, 30); getDXPgmButton->addListener(this); addAndMakeVisible(getDXCartButton = new TextButton("GET DX7 CART")); getDXCartButton->setBounds(755, 545, 100, 30); getDXCartButton->addListener(this); */ } CartManager::~CartManager() { timeSliceThread->stopThread(500); delete cartBrowser; delete cartBrowserList; delete timeSliceThread; } void CartManager::paint(Graphics &g) { g.fillAll(DXLookNFeel::lightBackground); g.setColour(DXLookNFeel::roundBackground); g.fillRoundedRectangle(8, 418, 843, 126, 15); g.setColour(Colours::whitesmoke); g.drawText("currently loaded cartridge", 38, 410, 150, 40, Justification::left); } void CartManager::programSelected(ProgramListBox *source, int pos) { if ( source == activeCart ) { browserCart->setSelected(-1); mainWindow->processor->setCurrentProgram(pos); mainWindow->processor->updateHostDisplay(); } else { if ( source->getCurrentCart() == nullptr ) return; char unpackPgm[161]; unpackProgramFromSysex(unpackPgm, source->getCurrentCart(), pos); activeCart->setSelected(-1); browserCart->setSelected(pos); repaint(); mainWindow->processor->updateProgramFromSysex((uint8_t *) unpackPgm); mainWindow->processor->updateHostDisplay(); } } void CartManager::buttonClicked(juce::Button *buttonThatWasClicked) { if ( buttonThatWasClicked == closeButton ) { mainWindow->startTimer(100); setVisible(false); return; } if ( buttonThatWasClicked == loadButton ) { FileChooser fc ("Import original DX sysex...", File::nonexistent, "*.syx;*.SYX;*.*", 1); if ( fc.browseForFileToOpen()) mainWindow->loadCart(fc.getResult()); return; } if ( buttonThatWasClicked == saveButton ) { mainWindow->saveCart(); } if ( buttonThatWasClicked == fileMgrButton ) { cartDir.revealToUser(); return; } // THIS IS NOT USED if ( buttonThatWasClicked == getDXPgmButton ) { if ( mainWindow->processor->sysexComm.isInputActive() && mainWindow->processor->sysexComm.isOutputActive() ) { unsigned char msg[] = { 0xF0, 0x43, 0x20, 0x09, 0xF7 }; mainWindow->processor->sysexComm.send(MidiMessage(msg, 5)); } else { showSysexConfigMsg(); } return; } if ( buttonThatWasClicked == getDXCartButton ) { if ( mainWindow->processor->sysexComm.isInputActive() && mainWindow->processor->sysexComm.isOutputActive() ) { unsigned char msg[] = { 0xF0, 0x43, 0x20, 0x00, 0xF7 }; mainWindow->processor->sysexComm.send(MidiMessage(msg, 5)); } else { showSysexConfigMsg(); } return; } } void CartManager::fileDoubleClicked(const File& file) { if ( file.isDirectory() ) return; mainWindow->loadCart(file); activeCart->setCartridge(mainWindow->processor->sysex); } void CartManager::fileClicked(const File& file, const MouseEvent& e) { if ( e.mods.isRightButtonDown() ) { PopupMenu menu; menu.addItem(1000, "Open location"); if ( ! file.isDirectory() ) { menu.addItem(1010, "Send sysex cartridge to DX7"); } menu.addSeparator(); menu.addItem(1020, "Refresh"); switch(menu.show()) { case 1000: file.revealToUser(); break; case 1010 : mainWindow->processor->sendSysexCartridge(file); break; case 1020: cartBrowserList->refresh(); break; } return; } } void CartManager::setActiveProgram(int idx, String activeName) { if ( activeCart->programNames[idx] == activeName ) { activeCart->setSelected(idx); browserCart->setSelected(-1); } activeCart->repaint(); } void CartManager::resetActiveSysex() { activeCart->setCartridge(mainWindow->processor->sysex); } void CartManager::selectionChanged() { File file = cartBrowser->getSelectedFile(); if ( ! file.exists() ) return; if ( file.isDirectory() ) return; String f = file.getFullPathName(); uint8_t syx_data[4104]; ifstream fp_in(f.toRawUTF8(), ios::binary); if (fp_in.fail()) { AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Error", "Unable to open: " + f); return; } fp_in.read((char *)syx_data, 4104); fp_in.close(); char browserSysex[4104]; memcpy(browserSysex, syx_data+6, 4096); int checksum = sysexChecksum(((char *) &browserSysex), 4096); if ( checksum != syx_data[4102] ) { browserCart->readOnly = true; } else { browserCart->readOnly = false; } browserCart->setSelected(-1); browserCart->setCartridge(browserSysex); } void CartManager::programRightClicked(ProgramListBox *source, int pos) { PopupMenu menu; menu.addItem(1000, "Send program '" + source->programNames[pos] + "' to DX7"); if ( source == activeCart ) menu.addItem(1010, "Send current sysex cartridge to DX7"); switch(menu.show()) { case 1000: char unpackPgm[161]; if ( source == activeCart ) { unpackProgramFromSysex(unpackPgm, mainWindow->processor->sysex, pos); } else { char *sysex = source->getCurrentCart(); if ( sysex == nullptr ) return; unpackProgramFromSysex(unpackPgm, sysex, pos); } if ( mainWindow->processor->sysexComm.isOutputActive() ) mainWindow->processor->sysexComm.send(MidiMessage(unpackPgm, 161)); break; case 1010: mainWindow->processor->sendCurrentSysexCartridge(); break; } } void CartManager::programDragged(ProgramListBox *destListBox, int dest, char *packedPgm) { if ( destListBox == activeCart ) { char *sysex = mainWindow->processor->sysex; memcpy(sysex+(dest*128), packedPgm, 128); mainWindow->updateUI(); } else { File file = cartBrowser->getSelectedFile(); if ( ! file.exists() ) return; if ( file.isDirectory() ) return; if ( file.getSize() > 5000 ) return; MemoryBlock block; file.loadFileAsData(block); if ( block.getSize() < 4104 ) return; char *sysex = ((char *) block.getData()) + 6; memcpy(sysex+(dest*128), packedPgm, 128); char exported[4104]; exportSysexCart(exported, sysex, 0); file.replaceWithData(exported, 4104); browserCart->setCartridge(sysex); } } void CartManager::initialFocus() { cartBrowser->grabKeyboardFocus(); } void CartManager::showSysexConfigMsg() { AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Warning", "The DX7 midi interface is not configured correctly.\n\n" "These buttons are used to 'ask' the DX7 to send the current program/cartridge.\n\n" "In order to use this correctly, you need to connect your midi in and midi out of your DX7 to a midi interface and configure this midi interface with the [PARM] dialog. THIS ONLY WORKS ON A DX7-II"); } // unused stuff from FileBrowserListener void CartManager::browserRootChanged (const File& newRoot) {}