diff --git a/Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate b/Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate index 1de9aea..164dea0 100644 Binary files a/Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate and b/Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Source/CartManager.cpp b/Source/CartManager.cpp index 58ac6fd..c43238c 100644 --- a/Source/CartManager.cpp +++ b/Source/CartManager.cpp @@ -38,8 +38,7 @@ public: }; }; -CartManager::CartManager(DexedAudioProcessorEditor *editor) : TopLevelWindow("CartManager", false), - timeSliceThread("Cartridge Directory Scanner") { +CartManager::CartManager(DexedAudioProcessorEditor *editor) : TopLevelWindow("CartManager", false) { mainWindow = editor; cartDir = DexedAudioProcessor::dexedCartDir; @@ -55,9 +54,10 @@ CartManager::CartManager(DexedAudioProcessorEditor *editor) : TopLevelWindow("Ca // ------------------------- 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); - timeSliceThread.startThread(); cartBrowser = new FileTreeComponent(*cartBrowserList); addAndMakeVisible(cartBrowser); cartBrowser->setBounds(23, 18, 590, 384); @@ -91,7 +91,10 @@ CartManager::CartManager(DexedAudioProcessorEditor *editor) : TopLevelWindow("Ca } CartManager::~CartManager() { - timeSliceThread.stopThread(500); + timeSliceThread->stopThread(500); + delete cartBrowser; + delete cartBrowserList; + delete timeSliceThread; } void CartManager::paint(Graphics &g) { @@ -122,6 +125,7 @@ void CartManager::programSelected(ProgramListBox *source, int pos) { void CartManager::buttonClicked(juce::Button *buttonThatWasClicked) { if ( buttonThatWasClicked == closeButton ) { + mainWindow->startTimer(100); setVisible(false); return; } @@ -142,6 +146,22 @@ void CartManager::buttonClicked(juce::Button *buttonThatWasClicked) { cartDir.revealToUser(); 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) { @@ -167,9 +187,10 @@ void CartManager::fileClicked(const File& file, const MouseEvent& e) { file.revealToUser(); break; case 1010 : + mainWindow->processor->sendSysexCartridge(file); break; case 1020: - cartBrowser->refresh(); + cartBrowserList->refresh(); break; } return; @@ -227,6 +248,19 @@ void CartManager::programRightClicked(ProgramListBox *source, int pos) { 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: @@ -236,6 +270,10 @@ void CartManager::programRightClicked(ProgramListBox *source, int pos) { } +void CartManager::initialFocus() { + cartBrowser->grabKeyboardFocus(); +} + // unused stuff from FileBrowserListener void CartManager::browserRootChanged (const File& newRoot) {} diff --git a/Source/CartManager.h b/Source/CartManager.h index 4f8373f..0bd7a3c 100644 --- a/Source/CartManager.h +++ b/Source/CartManager.h @@ -34,15 +34,16 @@ class CartManager : public TopLevelWindow, public ButtonListener, public DragAn ScopedPointer fileMgrButton; ScopedPointer getDXPgmButton; ScopedPointer getDXCartButton; - ScopedPointer activeCart; ScopedPointer browserCart; - ScopedPointer cartBrowser; ScopedPointer syxFileFilter; - TimeSliceThread timeSliceThread; - ScopedPointer cartBrowserList; + + FileTreeComponent *cartBrowser; + TimeSliceThread *timeSliceThread; + DirectoryContentsList *cartBrowserList; + File cartDir; DexedAudioProcessorEditor *mainWindow; @@ -64,6 +65,8 @@ public: virtual void programSelected(ProgramListBox *source, int pos) override; virtual void programRightClicked(ProgramListBox *source, int pos) override; + + void initialFocus(); }; diff --git a/Source/PluginData.cpp b/Source/PluginData.cpp index 8aac694..93199f9 100644 --- a/Source/PluginData.cpp +++ b/Source/PluginData.cpp @@ -25,6 +25,9 @@ #include "PluginData.h" #include "Dexed.h" +#include +using namespace ::std; + uint8_t sysexChecksum(const char *sysex, int size) { int sum = 0; int i; @@ -221,7 +224,6 @@ void DexedAudioProcessor::unpackProgram(int idx) { unpackProgramFromSysex(data, sysex, idx); } - int DexedAudioProcessor::importSysex(const char *imported) { 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() { return clipboardContent != -1; } @@ -408,14 +428,14 @@ void DexedAudioProcessor::resolvAppDir() { #if JUCE_MAC || JUCE_IOS dexedAppDir = File("~/Library/Application Support/DigitalSuburban/Dexed"); #elif JUCE_WINDOWS - dexedAppDir = File::getSpecialLocation(File::userApplicationDataDirectory).getChildFile("DigitalSuburban").getChildFile("Dexed")); + dexedAppDir = File::getSpecialLocation(File::userApplicationDataDirectory).getChildFile("DigitalSuburban").getChildFile("Dexed"); #else - // char xdgHomeDefault[] = ; char *xdgHome = getenv("XDG_DATA_HOME"); 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 if ( ! dexedAppDir.exists() ) { @@ -425,7 +445,7 @@ void DexedAudioProcessor::resolvAppDir() { // This code will be removed in 0.9.0 File cfgFile = dexedAppDir.getParentDirectory().getChildFile("Dexed.xml"); 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;igetNumEntries();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;igetNumEntries() ) { - 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; -} diff --git a/Source/PluginData.h b/Source/PluginData.h index 166a810..b41b051 100644 --- a/Source/PluginData.h +++ b/Source/PluginData.h @@ -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 unpackProgramFromSysex(char *unpackPgm, char *sysexCart, int idx); -class CartridgeManager { - ScopedPointer 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 diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index dde92fc..f1c732a 100644 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -131,9 +131,11 @@ void DexedAudioProcessorEditor::paint (Graphics& g) { } void DexedAudioProcessorEditor::cartShow() { + stopTimer(); cartManager.resetActiveSysex(); cartManager.setBounds(4, 2, 859, 576); cartManager.setVisible(true); + cartManager.initialFocus(); } @@ -294,7 +296,7 @@ void DexedAudioProcessorEditor::storeProgram() { if ( externalFile == NULL ) { 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"); if ( activeCartridgeFound ) saveAction.add("Store program and overwrite current .syx cartridge"); @@ -367,10 +369,10 @@ void DexedAudioProcessorEditor::storeProgram() { } } } - break; } - if ( externalFile != NULL ) + if ( externalFile != NULL ) delete externalFile; + cartManager.resetActiveSysex(); } diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index 89cf7a9..bc72ca3 100644 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -176,6 +176,7 @@ public : void pasteEnvFromClipboard(int destOp); void sendCurrentSysexProgram(); void sendCurrentSysexCartridge(); + void sendSysexCartridge(File cart); bool hasClipboardContent(); //============================================================================== diff --git a/Source/ProgramListBox.cpp b/Source/ProgramListBox.cpp index 7cf1d78..e0b7e5c 100644 --- a/Source/ProgramListBox.cpp +++ b/Source/ProgramListBox.cpp @@ -80,6 +80,7 @@ void ProgramListBox::resized() { void ProgramListBox::setCartridge(char *sysex) { extractProgramNames((const char *)sysex, programNames); + memcpy(cartContent, sysex, 4104); hasContent = true; repaint(); } @@ -117,3 +118,9 @@ void ProgramListBox::mouseDown(const MouseEvent &event) { void ProgramListBox::setSelected(int idx) { selectedPgm = idx; } + +char* ProgramListBox::getCurrentCart() { + if ( ! hasContent ) + return nullptr; + return cartContent; +} diff --git a/Source/ProgramListBox.h b/Source/ProgramListBox.h index 9131263..a8c862a 100644 --- a/Source/ProgramListBox.h +++ b/Source/ProgramListBox.h @@ -40,6 +40,9 @@ class ProgramListBox : public Component { int programPosition(const MouseEvent &event); int selectedPgm; + // TODO: this should be a pointer + char cartContent[4104]; + public: StringArray programNames; @@ -51,6 +54,7 @@ public: void mouseDoubleClick(const MouseEvent &event); void mouseDown(const MouseEvent &event); void setSelected(int idx); + char* getCurrentCart(); };