mirror of https://github.com/dcoredump/dexed.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
360 lines
12 KiB
360 lines
12 KiB
/**
|
|
*
|
|
* 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 <fstream>
|
|
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;
|
|
};
|
|
};
|
|
|
|
class FileTreeDrop : public FileTreeComponent {
|
|
public :
|
|
FileTreeDrop(DirectoryContentsList &listToShow) : FileTreeComponent(listToShow) {}
|
|
|
|
bool isInterestedInFileDrag (const StringArray &files) override {
|
|
bool found = false;
|
|
|
|
for(int i=0; i<files.size(); i++) {
|
|
String filename = files[i].toLowerCase();
|
|
found |= filename.endsWith(".syx");
|
|
}
|
|
return found;
|
|
}
|
|
|
|
void filesDropped(const StringArray &files, int x, int y) override {
|
|
File targetDir = getSelectedFile();
|
|
|
|
if ( ! targetDir.exists() )
|
|
targetDir = DexedAudioProcessor::dexedCartDir;
|
|
|
|
if ( ! targetDir.isDirectory() )
|
|
targetDir = targetDir.getParentDirectory();
|
|
|
|
for(int i=0; i<files.size(); i++) {
|
|
if ( files[i].toLowerCase().endsWith(".syx") ) {
|
|
File src(files[i]);
|
|
File target = targetDir.getChildFile(src.getFileName());
|
|
src.copyFileTo(target);
|
|
}
|
|
}
|
|
fileList.refresh();
|
|
}
|
|
};
|
|
|
|
CartManager::CartManager(DexedAudioProcessorEditor *editor) : Component("CartManager") {
|
|
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 FileTreeDrop(*cartBrowserList);
|
|
cartBrowser->addKeyListener(this);
|
|
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 {
|
|
uint8_t unpackPgm[161];
|
|
source->getCurrentCart().unpackProgram(unpackPgm, 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->currentCart);
|
|
}
|
|
|
|
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->currentCart);
|
|
}
|
|
|
|
void CartManager::selectionChanged() {
|
|
File file = cartBrowser->getSelectedFile();
|
|
|
|
if ( ! file.exists() )
|
|
return;
|
|
|
|
if ( file.isDirectory() )
|
|
return;
|
|
|
|
Cartridge browserSysex;
|
|
int rc = browserSysex.load(file);
|
|
if ( rc < 0 ) {
|
|
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Error", "Unable to open file");
|
|
return;
|
|
}
|
|
|
|
if ( rc != 0 ) {
|
|
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:
|
|
uint8_t unpackPgm[161];
|
|
|
|
if ( source == activeCart ) {
|
|
mainWindow->processor->currentCart.unpackProgram(unpackPgm, pos);
|
|
} else {
|
|
source->getCurrentCart().unpackProgram(unpackPgm, pos);
|
|
}
|
|
|
|
if ( mainWindow->processor->sysexComm.isOutputActive() ) {
|
|
uint8_t msg[163];
|
|
exportSysexPgm(msg, unpackPgm);
|
|
mainWindow->processor->sysexComm.send(MidiMessage(msg, 163));
|
|
}
|
|
break;
|
|
|
|
case 1010:
|
|
mainWindow->processor->sendCurrentSysexCartridge();
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void CartManager::programDragged(ProgramListBox *destListBox, int dest, char *packedPgm) {
|
|
if ( destListBox == activeCart ) {
|
|
char *sysex = mainWindow->processor->currentCart.getRawVoice();
|
|
memcpy(sysex+(dest*128), packedPgm, 128);
|
|
mainWindow->updateUI();
|
|
} else {
|
|
File file = cartBrowser->getSelectedFile();
|
|
|
|
if ( ! file.exists() )
|
|
return;
|
|
|
|
if ( file.isDirectory() )
|
|
return;
|
|
if ( file.getSize() != 4104 )
|
|
return;
|
|
|
|
Cartridge cart;
|
|
cart.load(file);
|
|
memcpy(cart.getRawVoice()+(dest*128), packedPgm, 128);
|
|
cart.saveVoice(file);
|
|
browserCart->setCartridge(cart);
|
|
}
|
|
}
|
|
|
|
void CartManager::initialFocus() {
|
|
cartBrowser->grabKeyboardFocus();
|
|
}
|
|
|
|
bool CartManager::keyPressed(const KeyPress& key, Component* originatingComponent) {
|
|
if ( key.getKeyCode() == 13 ) {
|
|
File file = cartBrowser->getSelectedFile();
|
|
if ( file.isDirectory() )
|
|
return true;
|
|
mainWindow->loadCart(file);
|
|
activeCart->setCartridge(mainWindow->processor->currentCart);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
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) {}
|
|
|
|
|
|
|