Sprint 3 Cart Manager

pull/1/head
asb2m10 10 years ago
parent eea6ca7cb9
commit 50828bcc70
  1. BIN
      Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate
  2. 50
      Source/CartManager.cpp
  3. 11
      Source/CartManager.h
  4. 170
      Source/PluginData.cpp
  5. 20
      Source/PluginData.h
  6. 6
      Source/PluginEditor.cpp
  7. 1
      Source/PluginProcessor.h
  8. 7
      Source/ProgramListBox.cpp
  9. 4
      Source/ProgramListBox.h

@ -38,8 +38,7 @@ public:
}; };
}; };
CartManager::CartManager(DexedAudioProcessorEditor *editor) : TopLevelWindow("CartManager", false), CartManager::CartManager(DexedAudioProcessorEditor *editor) : TopLevelWindow("CartManager", false) {
timeSliceThread("Cartridge Directory Scanner") {
mainWindow = editor; mainWindow = editor;
cartDir = DexedAudioProcessor::dexedCartDir; cartDir = DexedAudioProcessor::dexedCartDir;
@ -55,9 +54,10 @@ CartManager::CartManager(DexedAudioProcessorEditor *editor) : TopLevelWindow("Ca
// ------------------------- // -------------------------
syxFileFilter = new SyxFileFilter(); syxFileFilter = new SyxFileFilter();
cartBrowserList = new DirectoryContentsList(syxFileFilter, timeSliceThread); timeSliceThread = new TimeSliceThread("Cartridge Directory Scanner");
timeSliceThread->startThread();
cartBrowserList = new DirectoryContentsList(syxFileFilter, *timeSliceThread);
cartBrowserList->setDirectory(cartDir, true, true); cartBrowserList->setDirectory(cartDir, true, true);
timeSliceThread.startThread();
cartBrowser = new FileTreeComponent(*cartBrowserList); cartBrowser = new FileTreeComponent(*cartBrowserList);
addAndMakeVisible(cartBrowser); addAndMakeVisible(cartBrowser);
cartBrowser->setBounds(23, 18, 590, 384); cartBrowser->setBounds(23, 18, 590, 384);
@ -91,7 +91,10 @@ CartManager::CartManager(DexedAudioProcessorEditor *editor) : TopLevelWindow("Ca
} }
CartManager::~CartManager() { CartManager::~CartManager() {
timeSliceThread.stopThread(500); timeSliceThread->stopThread(500);
delete cartBrowser;
delete cartBrowserList;
delete timeSliceThread;
} }
void CartManager::paint(Graphics &g) { void CartManager::paint(Graphics &g) {
@ -122,6 +125,7 @@ void CartManager::programSelected(ProgramListBox *source, int pos) {
void CartManager::buttonClicked(juce::Button *buttonThatWasClicked) { void CartManager::buttonClicked(juce::Button *buttonThatWasClicked) {
if ( buttonThatWasClicked == closeButton ) { if ( buttonThatWasClicked == closeButton ) {
mainWindow->startTimer(100);
setVisible(false); setVisible(false);
return; return;
} }
@ -142,6 +146,22 @@ void CartManager::buttonClicked(juce::Button *buttonThatWasClicked) {
cartDir.revealToUser(); cartDir.revealToUser();
return; return;
} }
if ( buttonThatWasClicked == getDXPgmButton ) {
if ( mainWindow->processor->sysexComm.isOutputActive() ) {
unsigned char msg[] = { 0xF0, 0x43, 0x20, 0x00, 0xF7 };
mainWindow->processor->sysexComm.send(MidiMessage(msg, 5));
}
return;
}
if ( buttonThatWasClicked == getDXCartButton ) {
if ( mainWindow->processor->sysexComm.isOutputActive() ) {
unsigned char msg[] = { 0xF0, 0x43, 0x20, 0x01, 0xF7 };
mainWindow->processor->sysexComm.send(MidiMessage(msg, 5));
}
return;
}
} }
void CartManager::fileDoubleClicked(const File& file) { void CartManager::fileDoubleClicked(const File& file) {
@ -167,9 +187,10 @@ void CartManager::fileClicked(const File& file, const MouseEvent& e) {
file.revealToUser(); file.revealToUser();
break; break;
case 1010 : case 1010 :
mainWindow->processor->sendSysexCartridge(file);
break; break;
case 1020: case 1020:
cartBrowser->refresh(); cartBrowserList->refresh();
break; break;
} }
return; return;
@ -227,6 +248,19 @@ void CartManager::programRightClicked(ProgramListBox *source, int pos) {
switch(menu.show()) { switch(menu.show()) {
case 1000: 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; break;
case 1010: case 1010:
@ -236,6 +270,10 @@ void CartManager::programRightClicked(ProgramListBox *source, int pos) {
} }
void CartManager::initialFocus() {
cartBrowser->grabKeyboardFocus();
}
// unused stuff from FileBrowserListener // unused stuff from FileBrowserListener
void CartManager::browserRootChanged (const File& newRoot) {} void CartManager::browserRootChanged (const File& newRoot) {}

@ -35,14 +35,15 @@ class CartManager : public TopLevelWindow, public ButtonListener, public DragAn
ScopedPointer<TextButton> getDXPgmButton; ScopedPointer<TextButton> getDXPgmButton;
ScopedPointer<TextButton> getDXCartButton; ScopedPointer<TextButton> getDXCartButton;
ScopedPointer<ProgramListBox> activeCart; ScopedPointer<ProgramListBox> activeCart;
ScopedPointer<ProgramListBox> browserCart; ScopedPointer<ProgramListBox> browserCart;
ScopedPointer<FileTreeComponent> cartBrowser;
ScopedPointer<FileFilter> syxFileFilter; ScopedPointer<FileFilter> syxFileFilter;
TimeSliceThread timeSliceThread;
ScopedPointer<DirectoryContentsList> cartBrowserList; FileTreeComponent *cartBrowser;
TimeSliceThread *timeSliceThread;
DirectoryContentsList *cartBrowserList;
File cartDir; File cartDir;
DexedAudioProcessorEditor *mainWindow; DexedAudioProcessorEditor *mainWindow;
@ -64,6 +65,8 @@ public:
virtual void programSelected(ProgramListBox *source, int pos) override; virtual void programSelected(ProgramListBox *source, int pos) override;
virtual void programRightClicked(ProgramListBox *source, int pos) override; virtual void programRightClicked(ProgramListBox *source, int pos) override;
void initialFocus();
}; };

@ -25,6 +25,9 @@
#include "PluginData.h" #include "PluginData.h"
#include "Dexed.h" #include "Dexed.h"
#include <fstream>
using namespace ::std;
uint8_t sysexChecksum(const char *sysex, int size) { uint8_t sysexChecksum(const char *sysex, int size) {
int sum = 0; int sum = 0;
int i; int i;
@ -221,7 +224,6 @@ void DexedAudioProcessor::unpackProgram(int idx) {
unpackProgramFromSysex(data, sysex, idx); unpackProgramFromSysex(data, sysex, idx);
} }
int DexedAudioProcessor::importSysex(const char *imported) { int DexedAudioProcessor::importSysex(const char *imported) {
memcpy(sysex, imported + 6, 4096); memcpy(sysex, imported + 6, 4096);
@ -315,6 +317,24 @@ void DexedAudioProcessor::sendCurrentSysexCartridge() {
} }
} }
void DexedAudioProcessor::sendSysexCartridge(File cart) {
if ( ! sysexComm.isOutputActive() )
return;
String f = cart.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();
sysexComm.send(MidiMessage(syx_data, 4104));
}
bool DexedAudioProcessor::hasClipboardContent() { bool DexedAudioProcessor::hasClipboardContent() {
return clipboardContent != -1; return clipboardContent != -1;
} }
@ -408,14 +428,14 @@ void DexedAudioProcessor::resolvAppDir() {
#if JUCE_MAC || JUCE_IOS #if JUCE_MAC || JUCE_IOS
dexedAppDir = File("~/Library/Application Support/DigitalSuburban/Dexed"); dexedAppDir = File("~/Library/Application Support/DigitalSuburban/Dexed");
#elif JUCE_WINDOWS #elif JUCE_WINDOWS
dexedAppDir = File::getSpecialLocation(File::userApplicationDataDirectory).getChildFile("DigitalSuburban").getChildFile("Dexed")); dexedAppDir = File::getSpecialLocation(File::userApplicationDataDirectory).getChildFile("DigitalSuburban").getChildFile("Dexed");
#else #else
// char xdgHomeDefault[] = ;
char *xdgHome = getenv("XDG_DATA_HOME"); char *xdgHome = getenv("XDG_DATA_HOME");
if ( xdgHome == nullptr ) { if ( xdgHome == nullptr ) {
xdgHome = "~/.local/share"; dexedAppDir = File("~/.local/share").getChildFile("DigitalSuburban").getChildFile("Dexed");
} else {
dexedAppDir = File(xdgHome).getChildFile("DigitalSuburban").getChildFile("Dexed");
} }
dexedAppDir = File(xdgHome).getChildFile("DigitalSuburban").getChildFile("Dexed");
#endif #endif
if ( ! dexedAppDir.exists() ) { if ( ! dexedAppDir.exists() ) {
@ -425,7 +445,7 @@ void DexedAudioProcessor::resolvAppDir() {
// This code will be removed in 0.9.0 // This code will be removed in 0.9.0
File cfgFile = dexedAppDir.getParentDirectory().getChildFile("Dexed.xml"); File cfgFile = dexedAppDir.getParentDirectory().getChildFile("Dexed.xml");
if ( cfgFile.exists() ) if ( cfgFile.exists() )
cfgFile.copyFileTo(dexedAppDir); cfgFile.moveFileTo(dexedAppDir.getChildFile("Dexed.xml"));
// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
// ========================================================================== // ==========================================================================
} }
@ -450,141 +470,3 @@ void DexedAudioProcessor::resolvAppDir() {
} }
} }
} }
#define IDX_USER 1000
CartridgeManager::CartridgeManager() {
MemoryInputStream *mis = new MemoryInputStream(BinaryData::builtin_pgm_zip, BinaryData::builtin_pgm_zipSize, false);
builtin_pgm = new ZipFile(mis, true);
builtin_pgm->sortEntriesByFilename();
for(int i=0;i<builtin_pgm->getNumEntries();i++) {
const ZipFile::ZipEntry *e = builtin_pgm->getEntry(i);
cartNames.add(e->filename.dropLastCharacters(4));
}
userCartFile = File(File::getSpecialLocation(File::currentApplicationFile).getParentDirectory().getFullPathName() + File::separator + "Dexed_cart.zip");
}
CartridgeManager::~CartridgeManager() {
}
void CartridgeManager::getSysex(int idx, char *dest) {
if ( idx < IDX_USER ) {
InputStream *is = builtin_pgm->createStreamForEntry(idx);
if ( is == NULL ) {
TRACE("ENTRY IN ZIP NOT FOUND");
return;
}
is->read(dest, 4104);
delete is;
return;
}
idx -= IDX_USER;
if ( ! userCartFile.exists() )
return;
ZipFile userZip(userCartFile);
userZip.sortEntriesByFilename();
if ( idx < userZip.getNumEntries() ) {
InputStream *is = userZip.createStreamForEntry(idx);
if ( is != NULL ) {
is->read(dest, 4104);
delete is;
} else {
TRACE("USER ENTRY %d NULL ?", idx);
}
}
}
void CartridgeManager::rebuildMenu() {
TRACE("rebuild menu zip");
completeCarts.clear();
completeCarts.addItem(1, cartNames[0]);
PopupMenu synprez;
for(int i=1;i<cartNames.size();i++) {
synprez.addItem(i+1, cartNames[i]);
}
completeCarts.addSubMenu("SynprezFM", synprez, true);
if ( userCartFile.exists() ) {
zipIdx = 0;
ZipFile userZip(userCartFile);
userZip.sortEntriesByFilename();
PopupMenu *user = fillContent("", &userZip);
if ( user != NULL ) {
completeCarts.addSubMenu("User", *user);
delete user;
}
lastModifiedUserCartFile = userCartFile.getLastModificationTime();
} else {
lastModifiedUserCartFile = Time(0);
}
}
PopupMenu *CartridgeManager::getCarts() {
Time t = userCartFile.getLastModificationTime();
if ( t != lastModifiedUserCartFile || completeCarts.getNumItems() == 0 ) {
rebuildMenu();
}
return &completeCarts;
}
PopupMenu *CartridgeManager::fillContent(String root, ZipFile *userZip) {
PopupMenu *current = NULL;
while(zipIdx < userZip->getNumEntries() ) {
String path = userZip->getEntry(zipIdx)->filename;
if ( path.endsWith(".DS_Store") || path.startsWith("__MACOSX") ) {
zipIdx++;
continue;
}
if ( ! path.endsWithIgnoreCase(".syx") ) {
zipIdx++;
continue;
}
if ( ( ! path.startsWith(root) ) && root.length() != 0 )
return current;
String tail = path.substring(root.length());
if ( tail.containsChar('/') ) {
String target = tail.upToFirstOccurrenceOf("/", true, false);
PopupMenu *child = fillContent(root + target, userZip);
if ( child == NULL )
continue;
if ( current == NULL )
current = new PopupMenu();
current->addSubMenu(tail.upToFirstOccurrenceOf("/", false, false), *child);
delete child;
} else {
zipIdx++;
if ( tail.length() == 0 )
continue;
if ( current == NULL )
current = new PopupMenu();
// remove the .syx extension
tail = tail.substring(0, tail.length()-4);
current->addItem(zipIdx + IDX_USER, tail);
}
}
return current;
}

@ -67,24 +67,4 @@ void exportSysexPgm(char *dest, char *src, char sysexChl);
void packProgram(uint8_t *dest, uint8_t *src, int idx, String name); void packProgram(uint8_t *dest, uint8_t *src, int idx, String name);
void unpackProgramFromSysex(char *unpackPgm, char *sysexCart, int idx); void unpackProgramFromSysex(char *unpackPgm, char *sysexCart, int idx);
class CartridgeManager {
ScopedPointer<ZipFile> builtin_pgm;
Time lastModifiedUserCartFile;
File userCartFile;
StringArray cartNames;
int zipIdx;
PopupMenu *fillContent(String root, ZipFile *userZip);
PopupMenu completeCarts;
void rebuildMenu();
public:
PopupMenu *getCarts();
CartridgeManager();
~CartridgeManager();
void getSysex(int idx, char *data);
};
#endif // PLUGINDATA_H_INCLUDED #endif // PLUGINDATA_H_INCLUDED

@ -131,9 +131,11 @@ void DexedAudioProcessorEditor::paint (Graphics& g) {
} }
void DexedAudioProcessorEditor::cartShow() { void DexedAudioProcessorEditor::cartShow() {
stopTimer();
cartManager.resetActiveSysex(); cartManager.resetActiveSysex();
cartManager.setBounds(4, 2, 859, 576); cartManager.setBounds(4, 2, 859, 576);
cartManager.setVisible(true); cartManager.setVisible(true);
cartManager.initialFocus();
} }
@ -294,7 +296,7 @@ void DexedAudioProcessorEditor::storeProgram() {
if ( externalFile == NULL ) { if ( externalFile == NULL ) {
StringArray saveAction; StringArray saveAction;
saveAction.add("Store program to DAW plugin state"); saveAction.add("Store program to DAW plugin song state");
saveAction.add("Store program and create a new copy of the .syx cartridge"); saveAction.add("Store program and create a new copy of the .syx cartridge");
if ( activeCartridgeFound ) if ( activeCartridgeFound )
saveAction.add("Store program and overwrite current .syx cartridge"); saveAction.add("Store program and overwrite current .syx cartridge");
@ -367,10 +369,10 @@ void DexedAudioProcessorEditor::storeProgram() {
} }
} }
} }
break; break;
} }
if ( externalFile != NULL ) if ( externalFile != NULL )
delete externalFile; delete externalFile;
cartManager.resetActiveSysex();
} }

@ -176,6 +176,7 @@ public :
void pasteEnvFromClipboard(int destOp); void pasteEnvFromClipboard(int destOp);
void sendCurrentSysexProgram(); void sendCurrentSysexProgram();
void sendCurrentSysexCartridge(); void sendCurrentSysexCartridge();
void sendSysexCartridge(File cart);
bool hasClipboardContent(); bool hasClipboardContent();
//============================================================================== //==============================================================================

@ -80,6 +80,7 @@ void ProgramListBox::resized() {
void ProgramListBox::setCartridge(char *sysex) { void ProgramListBox::setCartridge(char *sysex) {
extractProgramNames((const char *)sysex, programNames); extractProgramNames((const char *)sysex, programNames);
memcpy(cartContent, sysex, 4104);
hasContent = true; hasContent = true;
repaint(); repaint();
} }
@ -117,3 +118,9 @@ void ProgramListBox::mouseDown(const MouseEvent &event) {
void ProgramListBox::setSelected(int idx) { void ProgramListBox::setSelected(int idx) {
selectedPgm = idx; selectedPgm = idx;
} }
char* ProgramListBox::getCurrentCart() {
if ( ! hasContent )
return nullptr;
return cartContent;
}

@ -40,6 +40,9 @@ class ProgramListBox : public Component {
int programPosition(const MouseEvent &event); int programPosition(const MouseEvent &event);
int selectedPgm; int selectedPgm;
// TODO: this should be a pointer
char cartContent[4104];
public: public:
StringArray programNames; StringArray programNames;
@ -51,6 +54,7 @@ public:
void mouseDoubleClick(const MouseEvent &event); void mouseDoubleClick(const MouseEvent &event);
void mouseDown(const MouseEvent &event); void mouseDown(const MouseEvent &event);
void setSelected(int idx); void setSelected(int idx);
char* getCurrentCart();
}; };

Loading…
Cancel
Save