From a208fb48157d25b26aea7bf8cef8d0826862b9ad Mon Sep 17 00:00:00 2001 From: Christoph Hart Date: Thu, 23 Jan 2025 13:53:49 +0100 Subject: [PATCH] - added new plugin export window --- .../backend/BackendApplicationCommands.cpp | 17 +- .../backend/BackendApplicationCommands.h | 3 + hi_backend/backend/BackendComponents.cpp | 8 + hi_backend/backend/BackendComponents.h | 25 +- hi_backend/backend/BackendEditor.cpp | 11 +- hi_backend/backend/BackendEditor.h | 82 ++++ hi_backend/backend/CompileExporter.cpp | 42 +- hi_backend/backend/CompileExporter.h | 20 +- .../backend/dialog_library/dialog_library.cpp | 367 +++++++++++++++++- .../backend/dialog_library/dialog_library.h | 179 +++++++-- .../snex_workbench/WorkbenchProcessor.cpp | 12 +- .../snex_workbench/WorkbenchProcessor.h | 8 + hi_core/hi_core/BackgroundThreads.h | 20 + hi_core/hi_core/Console.cpp | 2 +- hi_core/hi_core/Console.h | 4 +- hi_core/hi_core/HiseSettings.cpp | 12 +- hi_core/hi_core/HiseSettings.h | 1 + hi_tools/hi_multipage/MultiPageDialog.cpp | 22 +- hi_tools/hi_multipage/MultiPageDialog.h | 1 + .../compile_networks/compile_networks.json | 99 +++-- .../plugin_export/plugin_export.json | 193 +++++++++ 21 files changed, 1025 insertions(+), 103 deletions(-) create mode 100644 tools/json_dialog/plugin_export/plugin_export.json diff --git a/hi_backend/backend/BackendApplicationCommands.cpp b/hi_backend/backend/BackendApplicationCommands.cpp index e8ea4b5413..91ded05de3 100644 --- a/hi_backend/backend/BackendApplicationCommands.cpp +++ b/hi_backend/backend/BackendApplicationCommands.cpp @@ -105,6 +105,7 @@ void BackendCommandTarget::getAllCommands(Array& commands) MenuFileExtractEmbeddeSnippetFiles, MenuFileImportSnippet, MenuExportSetupWizard, + MenuExportCompileProject, MenuExportFileAsPlugin, MenuExportFileAsEffectPlugin, MenuExportFileAsMidiFXPlugin, @@ -328,6 +329,10 @@ void BackendCommandTarget::getCommandInfo(CommandID commandID, ApplicationComman setCommandTarget(result, "Setup Export Wizard", true, false, 'X', false); result.categoryName = "Export"; break; + case MenuExportCompileProject: + setCommandTarget(result, "Compile project", true, false, 'X', false); + result.categoryName = "Export"; + break; case MenuExportFileAsPlugin: setCommandTarget(result, "Export as Instrument (VSTi / AUi) plugin", true, false, 'X', false); result.categoryName = "Export"; @@ -687,6 +692,7 @@ bool BackendCommandTarget::perform(const InvocationInfo &info) case MenuToolsRecompile: Actions::recompileAllScripts(bpe); return true; case MenuToolsCheckCyclicReferences:Actions::checkCyclicReferences(bpe); return true; case MenuToolsCreateExternalScriptFile: Actions::createExternalScriptFile(bpe); updateCommands(); return true; + case MenuExportCompileProject: Actions::compileProject(bpe); return true; case MenuExportValidateUserPresets: Actions::validateUserPresets(bpe); return true; case MenuExportRestoreToDefault: Actions::restoreToDefault(bpe); return true; case MenuExportCheckUnusedImages: Actions::checkUnusedImages(bpe); return true; @@ -974,7 +980,10 @@ PopupMenu BackendCommandTarget::getMenuForIndex(int topLevelMenuIndex, const Str { ADD_MENU_ITEM(MenuExportSetupWizard); + ADD_MENU_ITEM(MenuExportCompileProject); + p.addSectionHeader("Export As"); + ADD_MENU_ITEM(MenuExportFileAsPlugin); ADD_MENU_ITEM(MenuExportFileAsEffectPlugin); ADD_MENU_ITEM(MenuExportFileAsMidiFXPlugin); @@ -2074,8 +2083,14 @@ DialogWindowWithBackgroundThread* BackendCommandTarget::Actions::importProject(B return nullptr; } +void BackendCommandTarget::Actions::compileProject(BackendRootWindow* bpe) +{ + auto cw = new multipage::library::CompileProjectDialog(bpe); + cw->setModalBaseWindowComponent(bpe); +} + struct HeadlessImporter: public ImporterBase, - public Thread + public Thread { HeadlessImporter(BackendRootWindow* bpe, const File& projectRoot): ImporterBase(bpe), diff --git a/hi_backend/backend/BackendApplicationCommands.h b/hi_backend/backend/BackendApplicationCommands.h index 302f47b729..92e76c7151 100644 --- a/hi_backend/backend/BackendApplicationCommands.h +++ b/hi_backend/backend/BackendApplicationCommands.h @@ -113,6 +113,7 @@ class BackendCommandTarget: public ApplicationCommandTarget, // Export Menu MenuExportSetupWizard, + MenuExportCompileProject, MenuExportFileAsPlugin, MenuExportFileAsEffectPlugin, MenuExportFileAsMidiFXPlugin, @@ -319,6 +320,8 @@ class BackendCommandTarget: public ApplicationCommandTarget, static void loadProject(BackendRootWindow *bpe); static DialogWindowWithBackgroundThread* importProject(BackendRootWindow* bpe); + static void compileProject(BackendRootWindow* bpe); + static void extractProject(BackendRootWindow* bpe, const File& newProjectRoot, const File& sourceFile); static void createRnboTemplate(BackendRootWindow* bpe); diff --git a/hi_backend/backend/BackendComponents.cpp b/hi_backend/backend/BackendComponents.cpp index 5246ef5bfc..d37d2db98c 100644 --- a/hi_backend/backend/BackendComponents.cpp +++ b/hi_backend/backend/BackendComponents.cpp @@ -354,6 +354,7 @@ multipage::EncodedDialogBase::EncodedDialogBase(BackendRootWindow* bpe_, bool ad ControlledObject(bpe_->getBackendProcessor()), rootWindow(bpe_), closeButton("close", nullptr, factory), + minimizeButton("minimize", nullptr, factory), addBorder(addBorder_) { addAndMakeVisible(closeButton); @@ -366,6 +367,13 @@ multipage::EncodedDialogBase::EncodedDialogBase(BackendRootWindow* bpe_, bool ad } }; + addChildComponent(minimizeButton); + + minimizeButton.onClick = [this]() + { + findParentComponentOfClass()->minimizeModalComponent(true, state.get()); + }; + closeButton.setVisible(addBorder); } diff --git a/hi_backend/backend/BackendComponents.h b/hi_backend/backend/BackendComponents.h index ee59bb1d17..e79ec937b3 100644 --- a/hi_backend/backend/BackendComponents.h +++ b/hi_backend/backend/BackendComponents.h @@ -681,6 +681,16 @@ struct EncodedDialogBase: public Component, { Path p; LOAD_EPATH_IF_URL("close", HiBinaryData::ProcessorEditorHeaderIcons::closeIcon); + + if(url == "minimize") + { + static const unsigned char pathData[] = { 110,109,47,128,38,68,0,0,64,67,98,2,156,55,68,0,0,64,67,0,128,69,68,248,143,119,67,0,128,69,68,216,255,157,67,98,0,128,69,68,176,55,192,67,2,156,55,68,254,255,219,67,47,128,38,68,254,255,219,67,98,254,99,21,68,254,255,219,67,0,128,7,68,176,55,192,67, + 0,128,7,68,216,255,157,67,98,0,128,7,68,248,143,119,67,254,99,21,68,0,0,64,67,47,128,38,68,0,0,64,67,99,109,157,219,60,68,16,109,125,67,108,147,36,54,68,80,145,98,67,108,167,136,45,68,48,128,130,67,108,74,76,39,68,196,15,108,67,108,74,76,39,68,118,102, + 156,67,108,14,124,58,68,118,102,156,67,108,177,63,52,68,42,238,143,67,108,157,219,60,68,16,109,125,67,99,109,67,219,22,68,4,183,202,67,108,47,119,31,68,98,127,185,67,108,5,179,37,68,176,247,197,67,108,5,179,37,68,28,153,159,67,108,241,131,18,68,28,153, + 159,67,108,24,192,24,68,106,17,172,67,108,84,36,16,68,12,73,189,67,108,67,219,22,68,4,183,202,67,99,101,0,0 }; + p.loadPathFromData (pathData, sizeof (pathData)); + } + return p; } } factory; @@ -803,6 +813,12 @@ struct EncodedDialogBase: public Component, closeButton.setBounds(b.removeFromRight(34).removeFromTop(34).reduced(8)); closeButton.toFront(false); + + if(minimizeButton.isVisible()) + { + minimizeButton.toFront(false); + minimizeButton.setBounds(b.removeFromLeft(34).removeFromTop(34).reduced(8)); + } } void navigate(int pageIndex, bool shouldSubmit) @@ -821,13 +837,20 @@ struct EncodedDialogBase: public Component, } }); } - + + void setMinimizable(bool isMinimizable) + { + minimizeButton.setVisible(isMinimizable); + resized(); + } + protected: ScopedPointer state; ScopedPointer dialog; HiseShapeButton closeButton; + HiseShapeButton minimizeButton; bool closeOnEscape = true; diff --git a/hi_backend/backend/BackendEditor.cpp b/hi_backend/backend/BackendEditor.cpp index 3bf667e69b..dedfd95fbd 100644 --- a/hi_backend/backend/BackendEditor.cpp +++ b/hi_backend/backend/BackendEditor.cpp @@ -357,8 +357,11 @@ MainTopBar::MainTopBar(FloatingTile* parent) : SimpleTimer(parent->getMainController()->getGlobalUIUpdater()), PreloadListener(parent->getMainController()->getSampleManager()), ComponentWithHelp(parent->getBackendRootWindow()), - quickPlayButton(parent->getMainController()) + quickPlayButton(parent->getMainController()), + minimizeBar() { + addChildComponent(minimizeBar); + parent->getMainController()->getScriptComponentEditBroadcaster()->getLearnBroadcaster().addListener(*this, updateLearnConnection); { @@ -617,6 +620,7 @@ void MainTopBar::buttonClicked(Button* b) void MainTopBar::resized() { + minimizeBar.initialise(); hiseButton->setVisible(false); layoutButton->setVisible(false); @@ -628,7 +632,10 @@ void MainTopBar::resized() auto b = getLocalBounds(); customPopupButton->setBounds(b.removeFromLeft(getHeight()).reduced(8)); - + + if(minimizeBar.isVisible()) + minimizeBar.setBounds(b.removeFromLeft(getWidth() / 4).reduced(8)); + macroButton->setBounds(frontendArea.removeFromLeft(bWidth).reduced(7)); pluginPreviewButton->setBounds(frontendArea.removeFromLeft(bWidth).reduced(7)); presetBrowserButton->setBounds(frontendArea.removeFromLeft(bWidth).reduced(7)); diff --git a/hi_backend/backend/BackendEditor.h b/hi_backend/backend/BackendEditor.h index d6c0c6f69f..029ca99cc7 100644 --- a/hi_backend/backend/BackendEditor.h +++ b/hi_backend/backend/BackendEditor.h @@ -307,6 +307,88 @@ class MainTopBar : public FloatingTileContent, numPopupTypes }; + struct MinimizeBar: public Component + { + MinimizeBar() + { + setMouseCursor(MouseCursor::PointingHandCursor); + } + + bool initialised = false; + + void initialise() + { + if(!initialised) + { + if(auto mbw = findParentComponentOfClass()) + { + initialised = true; + mbw->minimizeBroadcaster.addListener(*this, onMinimize); + } + } + } + + static void onMinimize(MinimizeBar& b, bool shouldBeVisible, multipage::State* state) + { + b.setVisible(shouldBeVisible); + b.state = state; + + if(shouldBeVisible) + { + b.text = state->getFirstDialog()->getGlobalProperty(multipage::mpid::Header).toString(); + if(auto j = state->currentJob) + { + b.addAndMakeVisible(b.bar = new ProgressBar(j->getProgress())); + b.resized(); + } + } + + + if(auto mb = b.findParentComponentOfClass()) + mb->resized(); + } + + void mouseDown(const MouseEvent& e) override + { + findParentComponentOfClass()->minimizeModalComponent(false, state); + } + + void resized() override + { + if(bar != nullptr) + { + auto f = GLOBAL_BOLD_FONT(); + auto w = f.getStringWidth(text) + 20; + auto b = getLocalBounds(); + b.removeFromLeft(w); + bar->setBounds(b.reduced(4)); + } + } + + void paint(Graphics& g) override + { + if(isMouseOver(true)) + { + g.setColour(Colours::white.withAlpha(0.1f)); + g.fillRoundedRectangle(getLocalBounds().toFloat(), 3.0f); + } + + + g.setColour(Colours::white.withAlpha(0.8f)); + + g.setFont(GLOBAL_BOLD_FONT()); + g.drawText(text, getLocalBounds().toFloat().reduced(5.0f), Justification::left); + } + + String text; + + ScopedPointer bar; + + WeakReference state; + + JUCE_DECLARE_WEAK_REFERENCEABLE(MinimizeBar); + } minimizeBar; + MainTopBar(FloatingTile* parent); ~MainTopBar(); diff --git a/hi_backend/backend/CompileExporter.cpp b/hi_backend/backend/CompileExporter.cpp index 35662addbf..d54a414e92 100644 --- a/hi_backend/backend/CompileExporter.cpp +++ b/hi_backend/backend/CompileExporter.cpp @@ -495,8 +495,9 @@ CompileExporter::BuildOption CompileExporter::getBuildOptionFromCommandLine(Stri CompileExporter::ErrorCodes CompileExporter::exportInternal(TargetTypes type, BuildOption option) { + setProgress(0.1); - + logMessage("> Perform sanity checks"); const auto& data = dynamic_cast(chainToExport->getMainController())->getSettingsObject(); @@ -558,6 +559,8 @@ CompileExporter::ErrorCodes CompileExporter::exportInternal(TargetTypes type, Bu solutionDirectory = GET_PROJECT_HANDLER(chainToExport).getSubDirectory(ProjectHandler::SubDirectories::Binaries).getFullPathName(); + logMessage("> Create C++ autogenerated files"); + if (option != Cancelled) { // Use plugin mode for iOS Standalone AUv3 apps... @@ -574,6 +577,8 @@ CompileExporter::ErrorCodes CompileExporter::exportInternal(TargetTypes type, Bu if (result != ErrorCodes::OK) return result; } + logMessage("> Create binary data files"); + result = copyHISEImageFiles(); if (result != ErrorCodes::OK) return result; @@ -631,6 +636,8 @@ CompileExporter::ErrorCodes CompileExporter::exportInternal(TargetTypes type, Bu bool alreadyExported = iof.existsAsFile() || sof.existsAsFile() || smof.existsAsFile() || mof.existsAsFile(); + setProgress(0.3); + if (rawMode || (alreadyExported && data.getSetting(HiseSettings::Compiler::RebuildPoolFiles))) { iof.deleteFile(); @@ -638,20 +645,25 @@ CompileExporter::ErrorCodes CompileExporter::exportInternal(TargetTypes type, Bu smof.deleteFile(); mof.deleteFile(); + logMessage("> Exporting the pooled resources"); + std::cout << "Exporting the pooled resources..."; - handler.exportAllPoolsToTemporaryDirectory(chainToExport, nullptr); + DialogWindowWithBackgroundThread::LogData d; + d.logFunction = BIND_MEMBER_FUNCTION_1(CompileExporter::logMessage); + + handler.exportAllPoolsToTemporaryDirectory(chainToExport, &d); - std::cout << "DONE\n" ; + logMessage("DONE"); if (rawMode) { - auto printExportedFiles = [](MainController* mc, const Array& files, ProjectHandler::SubDirectories d) + auto printExportedFiles = [this](MainController* mc, const Array& files, ProjectHandler::SubDirectories d) { String name = ProjectHandler::getIdentifier(d); NewLine nl; - std::cout << "Exported " << name << " resources: " << nl; + logMessage("Exported " + name + " resources: "); auto& handler = mc->getCurrentFileHandler(); @@ -659,11 +671,9 @@ CompileExporter::ErrorCodes CompileExporter::exportInternal(TargetTypes type, Bu auto folder = handler.getSubDirectory(d); for (const auto& ref : files) - { - std::cout << ref.getFile().getRelativePathFrom(folder) << nl; - } + logMessage(ref.getFile().getRelativePathFrom(folder)); - std::cout << "============================================="; + logMessage("============================================="); }; auto mc = chainToExport->getMainController(); @@ -690,6 +700,8 @@ CompileExporter::ErrorCodes CompileExporter::exportInternal(TargetTypes type, Bu handler.exportAllPoolsToTemporaryDirectory(chainToExport, nullptr); } + setProgress(0.4); + File imageOutputFile, sampleOutputFile, samplemapFile, midiFile; if (embedFiles) @@ -786,6 +798,8 @@ CompileExporter::ErrorCodes CompileExporter::exportInternal(TargetTypes type, Bu mof.copyFileTo(midiFile); } + logMessage("> Create embedded data files"); + String presetDataString("PresetData"); String sourceDirectory = solutionDirectory + "/Source"; @@ -802,7 +816,13 @@ CompileExporter::ErrorCodes CompileExporter::exportInternal(TargetTypes type, Bu if (result != ErrorCodes::OK) return result; } - result = compileSolution(option, type); + setProgress(0.5); + + logMessage("> Launch system compi"); + + result = compileSolution(option, type, manager); + + setProgress(1.0); return result; } @@ -2555,7 +2575,7 @@ void CompileExporter::BatchFileCreator::createBatchFile(CompileExporter* exporte if (!exporter->rawMode && BuildOptionHelpers::is64Bit(buildOption)) { - ADD_LINE("echo Compiling 64bit " << projectType << " %project% ..."); + ADD_LINE("echo > Compiling 64bit " << projectType << " %project% ..."); ADD_LINE("set Platform=X64"); ADD_LINE("%msbuild% \"%build_path%\\Builds\\" << vsFolder << "\\%project%.sln\" %vs_args%"); diff --git a/hi_backend/backend/CompileExporter.h b/hi_backend/backend/CompileExporter.h index 1e308f75ec..20e03337ca 100644 --- a/hi_backend/backend/CompileExporter.h +++ b/hi_backend/backend/CompileExporter.h @@ -235,6 +235,8 @@ class CompileExporter: public BaseExporter return compressor.compress(v, target); } + ChildProcessManager* manager = nullptr; + int getBuildOptionPart(const String& argument); static void setExportingFromCommandLine() @@ -251,7 +253,7 @@ class CompileExporter: public BaseExporter static bool isExportingFromCommandLine() { return globalCommandLineExport; } - bool shouldBeSilent() const { return isExportingFromCommandLine() || silentMode; } + bool shouldBeSilent() const { return isExportingFromCommandLine() || silentMode || manager != nullptr; } struct BatchFileCreator { @@ -259,8 +261,24 @@ class CompileExporter: public BaseExporter static File getBatchFile(CompileExporter* exporter, ChildProcessManager* m=nullptr); }; + void setSilent(bool shouldBeSilent) { silentMode = shouldBeSilent; } + protected: + void setProgress(double d) + { + if(manager != nullptr) + manager->setProgress(d); + } + + void logMessage(const String& m) + { + if(isExportingFromCommandLine()) + std::cout << m << "\n"; + else if (manager != nullptr) + manager->logMessage(m); + } + bool noLto = false; bool silentMode = false; diff --git a/hi_backend/backend/dialog_library/dialog_library.cpp b/hi_backend/backend/dialog_library/dialog_library.cpp index 97f50b703c..3a67508da2 100644 --- a/hi_backend/backend/dialog_library/dialog_library.cpp +++ b/hi_backend/backend/dialog_library/dialog_library.cpp @@ -901,10 +901,314 @@ void NewProjectCreator::threadFinished() } } +CompileProjectDialog::CompileProjectDialog(BackendRootWindow* bpe_): + EncodedDialogBase(bpe_, false), + bpe(bpe_) +{ + setMinimizable(true); + setWantsBackdrop(true); + loadFrom("1439.sNB..D...............35H...oi...yU.........J09R+fE8DMsB.1hOpm.uz1F.pzjUdAato4DZeNh5VnqnrSsqwodTd1zBh87MxZVfmApbvqIJ.ZBPm.DQFKwEm4oc5iJpVMQs5N11ewreyz1ll8iJ63KoXZjcCnmNOx4mUGq5oETpfohFCv3NtwZ36CUkKZtPIaG2OztHlhQiELEnIyEMUrngBRSwXfFLVz3A74WxbwhAYXncuUAUtbwxEJYpXYaSx56+lKQTSxPYaScHupDF8jckjIjqPv4OCDLIYud0UrOk+LssIJ76Ls6tAHx1lXJyo8RzpocCPjbPlJBrMGr9xKOrXQzZjVmnhD3Ka.JJJaCi5djdz3SZMa2D+0wQ5wlB3sH12NVBDU9QPZfNp8sAudNK4fl9vHsM46uE7ozpHIsec8zIM7gaqD6w4yMms75kQINSe5HvPGjYAIRUv1tfOmiiTQfgnvlJ.LDLDASwZ7ovY2S6FqhV+R7mIqXbAmE8tCSaIICeTSnlPA9uorunDjKUDvPwMiNvPyrl5IBJrypR5Lts06w1vAGb.I8NOjbDSw3BaCemcPlVAhBU04KF4cUcJXnEepD36RxY61n8kjAsTPZPsGydUSiPevViiDdXPj18abd3XAqc3OXHlOMZoyeXanxfA650OPQgw067iiBwc9vnq09zkBYRa8KsOm4rinmuuIS9FA6pjtsIR86hLYxHPksMqOGKkHam7uPgR.LR.azoxsjdrJZ6SRM7B9fP1ZtvFizFqK8sdX8hSLVfibz19aj0VxctBe51evXq6upIr3rENwlvDuNZNaKq5bmLIqsw.ssHeY4wjAwNQY7mKV1F1Kam+Xs0Fx955I8VD+4k3RAOnMNI+hhuRwI6aZW+mkgYU+2rAH8jRd.qcBEeu+n4DJTaSagglYxeDkcJV2yXAKV.FBT0Ed33IA9BpQGhLEMi.MA.AAEPPL..GLGDZcGfbnxRhyQAgwoT...IvPn.HX...IJoBwBvfFXHnwfzMstpqZd0rxG6vpNKPeYYIAc4xDVFQIZeBpiiCafx31AEYBhKliMnF3PYgM.0vLUppq+3EdQhn0RK+cYAOSw5bOW.MOR0aij3K.OSLS.dIPz.ilEhLupjmvCESyJWPSvkJgi0JmdlJZT2sxzHXcbA6g0CBViGJS6JiUvtBO05BkM8ljvQ9PssqjNqIymBpsXSp40ZBGX5JnR+JDSw201fESZHPKxbKK92NPNhDVhQ55EIxTp350dquLH0NWyoa0NpBKVxrjWgDzoSjb0KWABMDfiThnfKROrdERSHe1vl2922UXbr9GhMabAEgZf+Smoqr9Upv4aesMI0YrvFr6fjwlH9ymMcXEtgyB0aljLhJDzpcH.lRWTvGteiKG2iPn4gKEuTHJ83CJhQMfJtMSFinQ7mW0Xx1HXFXNne.lIOOLAJTy6QNVUhQhwRs2fGku8jkP7rbIGsoC1ySfsskekaw.KeugZfqSKIxXqm7iakTIE5s2fYRfIAY8RBzgXOebquwhtGz6gzjrNlz2roJef8djCpNzaSLdgNKuAC7BYfMJi0ZlPW0zOIE1Gjh+j682s4jBr2bkrAIvfMDMaI7a8sbkIyqObUYctepEO.UBPXBTBrqFoX5oa+eBYFHWIkKvtBnpcoUGHUm0C1kkMozWzgOrVdP1rBHr+7GD27br5GhMYeGn2WPbcdmc3vnnQJ+lvdGu+bpYDRRvgsLCY0ws.OroyBjsmmwV3CfXY4ESDOtAYSJ8mKUDHdqQLFgLHnbBMyes+JwPF+paWEZxumu0nyHmYRveDTiLhB88+OLjfpw.jviUL8X46KsWDDEnvmaNYS3v8xn8CQmxA3xyVDWawCNYBJt0oD6EOtFNe726Beoi...lNB..v5H..."); + + state.get()->dynamicComponentFactory = [this](const String& id) + { + return new CompileLogger(this); + }; + + dialog->setFinishCallback([this]() + { + //dynamic_cast(compileExporter.get())->threadFinished(); + findParentComponentOfClass()->clearModalComponent(); + }); +} + +CompileProjectDialog::~CompileProjectDialog() +{ + if(killFunction) + killFunction(); + + state->clearCompletedJobs(); + +} + + /** 0xABCD + * + * A = OS (0 = Linux / 1 = Windows / 2 = OSX / 4 = iPad, 8=iPhone, 12 = iPad/iPhone) + * B = type (1 = Standalone, 2 = Instrument, 4 = Effect, 8 = MidiFX) + * C = platform (0 = void, 1 = VST, 2 = AU, 4 = VST / AU, 8 = AAX); + * D = bit (1 = 32bit, 2 = 64bit, 4 = both) + */ + +#if JUCE_WINDOWS +#define OS_FLAG 0x1000 +#elif JUCE_MAC +#define OS_FLAG 0x2000 +#else +#define OS_FLAG 0x0000 +#endif + +#define IS_FLAG(functionName) CompileExporter::BuildOptionHelpers::functionName((CompileExporter::BuildOption)flags) +#define TEST_FLAG(functionName) jassert(IS_FLAG(functionName)) + + + +int CompileProjectDialog::getBuildFlag() const +{ + auto exportType = (int)readState("ExportType"); + auto pluginType = readState("pluginType").toString(); + + if(pluginType.isEmpty()) + pluginType = "VST"; + + auto projectType = readState("projectType").toString(); + + int flags = OS_FLAG; + + flags |= 0x0002; // always 64 bit now + + if(exportType == 1) // plugin + { + flags |= 0x0100; + TEST_FLAG(isStandalone); + } + else + { + if(projectType == "Instrument") + { + flags |= 0x0200; + TEST_FLAG(isInstrument); + } + + if(projectType == "FX plugin") + { + flags |= 0x0400; + TEST_FLAG(isEffect); + } + + if(projectType == "MIDI plugin") + { + flags |= 0x0800; + TEST_FLAG(isMidiEffect); + } + + if(pluginType == "VST") + { + flags |= 0x0010; + TEST_FLAG(isVST); + } + if(pluginType == "AU") + { + flags |= 0x0020; + TEST_FLAG(isAU); + } + if(pluginType == "AAX") + { + flags |= 0x0080; + TEST_FLAG(isAAX); + } + if(pluginType == "All Platforms") + { + flags |= 0x10000; + TEST_FLAG(isVST); + TEST_FLAG(isAU); + TEST_FLAG(isAAX); + } + } + + return flags; +} + + +var CompileProjectDialog::onInit(const var::NativeFunctionArgs& args) +{ + auto type = GET_HISE_SETTING(getMainController()->getMainSynthChain(), HiseSettings::Project::ProjectType).toString(); + + if(type.isNotEmpty()) + writeState("projectType", type); + + setElementProperty("OutputFile", mpid::Text, getTargetFile().getFullPathName()); + + return var(); +} + +var CompileProjectDialog::compileTask(const var::NativeFunctionArgs& args) +{ + CompileExporter ep(bpe->getBackendProcessor()->getMainSynthChain()); + + ep.manager = this; + + CompileExporter::ErrorCodes ok; + + auto flags = getBuildFlag(); + + if(IS_FLAG(isStandalone)) + ok = ep.exportMainSynthChainAsStandaloneApp((CompileExporter::BuildOption)flags); + if(IS_FLAG(isInstrument)) + ok = ep.exportMainSynthChainAsInstrument((CompileExporter::BuildOption)flags); + if(IS_FLAG(isEffect)) + ok = ep.exportMainSynthChainAsFX((CompileExporter::BuildOption)flags); + if(IS_FLAG(isMidiEffect)) + ok = ep.exportMainSynthChainAsMidiFx((CompileExporter::BuildOption)flags); + + if(ok != CompileExporter::OK) + { + auto error = CompileExporter::getCompileResult(ok); + throw Result::fail(error); + } + + return var(); +} + +var CompileProjectDialog::onPluginType(const var::NativeFunctionArgs& args) +{ + auto flags = getBuildFlag(); + + setElementProperty("OutputFile", mpid::Text, getTargetFile().getFullPathName()); + + if(IS_FLAG(isAAX)) + { + auto hiseDirectory = GET_HISE_SETTING(getMainController()->getMainSynthChain(), HiseSettings::Compiler::HisePath).toString(); + const File aaxSDK = File(hiseDirectory).getChildFile("tools/SDK/AAX/Libs"); + + if(!aaxSDK.isDirectory()) + throw Result::fail("AAX SDK not found. \n> You need to get the AAX SDK from Avid and copy it to '%HISE_SDK%/tools/SDK/AAX/'"); + } + +#if JUCE_WINDOWS || JUCE_LINUX + if(IS_FLAG(isAU) && !(flags & 0x10000)) + { + throw Result::fail("The AU plugin format is only supported on macOS. \n> You need to compile this project on a macOS system to support this plugin format."); + } +#endif + + return var(); +} + +var CompileProjectDialog::onComplete(const var::NativeFunctionArgs& args) +{ + auto flags = getBuildFlag(); + + auto enabled = IS_FLAG(isStandalone); + + setElementProperty("showPluginFolder", mpid::Enabled, enabled); + return var(); +} + +var CompileProjectDialog::onShowPluginFolder(const var::NativeFunctionArgs& args) +{ + auto flags = getBuildFlag(); + + File folder; + + if(IS_FLAG(isVST)) + { + auto isVST3 = (bool)GET_HISE_SETTING(getMainController()->getMainSynthChain(), HiseSettings::Project::VST3Support); + + folder = File::getSpecialLocation(File::SpecialLocationType::globalApplicationsDirectory); + + if(isVST3) + { + folder = folder.getChildFile("Common Files").getChildFile("VST3"); + } + else + { + // not a real default folder, but hey... + folder = folder.getChildFile("VSTPlugins"); + } + } + if(IS_FLAG(isAAX)) + { + folder = File::getSpecialLocation(File::SpecialLocationType::globalApplicationsDirectory); + folder = folder.getChildFile("Common Files").getChildFile("Avid").getChildFile("Audio").getChildFile("Plug-Ins"); + } + + if(folder.isDirectory()) + { + auto firstChild = folder.findChildFiles(File::findFilesAndDirectories, false, "*").getFirst(); + + if(firstChild.exists()) + firstChild.revealToUser(); + else + folder.revealToUser(); + } + + else + throw Result::fail("Can't find default plugin folder `" + folder.getFullPathName() + "`"); + + return var(); +} + +var CompileProjectDialog::onShowCompiledFile(const var::NativeFunctionArgs& args) +{ + auto compiledFile = getTargetFile(); + + if(compiledFile.exists()) + compiledFile.revealToUser(); + else + throw Result::fail("Can't find file `" + compiledFile.getFullPathName() + "`"); + + return var(); +} + +var CompileProjectDialog::onCopyToClipboard(const var::NativeFunctionArgs& args) +{ + SystemClipboard::copyTextToClipboard(log.getAllContent()); + PresetHandler::showMessageWindow("Copied", "The console output was copied to the clipboard"); + return var(); +} + +File CompileProjectDialog::getTargetFile() const +{ + auto flags = getBuildFlag(); + + auto binaries = getMainController()->getCurrentFileHandler().getSubDirectory(FileHandlerBase::SubDirectories::Binaries); + + auto filename = GET_HISE_SETTING(getMainController()->getMainSynthChain(), HiseSettings::Project::Name).toString(); + + if(IS_FLAG(isStandalone)) + { + auto compiledFile = binaries.getChildFile("Compiled").getChildFile("App"); + return compiledFile.getChildFile(filename).withFileExtension(".exe"); + } + if(IS_FLAG(isVST)) + { + auto isVST3 = (bool)GET_HISE_SETTING(getMainController()->getMainSynthChain(), HiseSettings::Project::VST3Support); + + auto compiledFile = binaries.getChildFile("Compiled").getChildFile(isVST3 ? "VST3" : "VST"); + return compiledFile.getChildFile(filename).withFileExtension(isVST3 ? ".vst3" : ".dll"); + } + if(IS_FLAG(isAAX)) + { + auto compiledFile = binaries.getChildFile("Compiled").getChildFile("AAX"); + return compiledFile.getChildFile(filename).withFileExtension(".aaxplugin"); + } + + return File(); +} + +#undef OS_FLAG +#undef IS_FLAG +#undef TEST_FLAG + +var CompileProjectDialog::onExportType(const var::NativeFunctionArgs& args) +{ + auto enabled = (bool)readState("ExportType"); + + setElementProperty("projectType", mpid::Enabled, !enabled); + setElementProperty("pluginType", mpid::Enabled, !enabled); + + setElementProperty("OutputFile", mpid::Text, getTargetFile().getFullPathName()); + + return var(); +} + + + NetworkCompiler::NetworkCompiler(BackendRootWindow* bpe_): EncodedDialogBase(bpe_, false), - bpe(bpe_) + bpe(bpe_) { + setMinimizable(true); + auto dn = new DspNetworkCompileExporter(bpe, bpe->getBackendProcessor()); dn->setAdditionalLogFunction(BIND_MEMBER_FUNCTION_1(NetworkCompiler::logMessage)); dn->managerToUse = this; @@ -912,7 +1216,13 @@ NetworkCompiler::NetworkCompiler(BackendRootWindow* bpe_): compileExporter = dn; setWantsBackdrop(true); - loadFrom("996.sNB..D...............35H...oi...3N.........J09R+f8DB00A.V5Bim.Ns3F.UIVatD1rdEVRZLKsOI3hUR9Fo65ifX.E3Xv.NYIILCmwXfcH.9APf.zue1RedQzI6FPSgbFjeWsrpoZX4RlKaPHCDi6sN99HcYZyjzrw3VhFZwSY1fIyAazLs4BlMOI8mAgMYvrAT7AmzLgAAMNzX90AWllvLYQyELypCcNZVRUzXoK4UsP1a1UFPibkBXP2AJQSFV0ZLV+4OQKUzGcHh1c2.LYoh3m6zvtuJZ2.LIzWrj5QmC933LC9nmUe9oUncziKUGCkzGFk1SMeJM.xu+CDOg.IIKK01i8Bkvm0vkJp8frA+GwOLI9Qzeu7MunMVEJQflbmu6spu5c7mnKorAHa4vHh1tIGeRUjpXI5O5r2nKxcTvwU7WsHZLmmH3+dqZEEzzC8cEaCeRNmCMHidnTFRU0PI2qpw7XH80yiKkeqifxgVJcfBYWXWJR5LhgbLPSlhnSnn5TgGGLowbN+K5I5cthUH3Q3InuV1kgG8DC913HoIyl1qkPRhCMGxuNLHqRWtz21uWq+6G4Pa06VuCk1TzTGxga9xhcc9SWFpea.5hgVK0zg9EIxKcIOZBAvIA.h.Xc206YN+q71VKD9Bszp+FomRNelsz+pyx5EB4kROcttHuOT4Qh8m7Sw5NteAQGaqdGU97oyuXrC64F8EePrTZOuXq.qYTZecUoK2aY.BmUsJZgl1alwG6Qd.Dkyfwr33Oc7AeOrRgjFKQv1h+3Uf0PKN9vWs3qAfmhZbYFDDQ0HjDPPpH..LFAPwppL.xBNFJQNGBh.FZ.HfBFj.PX4wIL7vnvn7VgO4wZUmTGQEWdEdGjMKsG0Fmab0q2Be2B+ds0GWBtNz1D4gFqcClQtC.VKOnoHb12r.X1y2z2yJEqrAYVhsnmKIhpqqZwFlds5rUsLp+eV.B00Il9L19CLuQajY3xDA1HJdPNeSOSSDLXB7RI6qJPiOG3nRXwYhU4AqSi0K0aplHMn+T.ZhSbGIQjLW4AE3949zq4mU.2zfwPLQyCXYBInz98759CjBd0YcrCFLOJJhZ0f5MYtVvsaJVvTOYHFfLZK5lqITttvn7fV7ADRqlncNheAfpsoaFSY+OEZLUXm9CYs0PNFmj..s0TltQ9DvIkcz40jRn0ZiiP0.CFjr9vflCL31kpr2lkTcmpCBwUjpF2O10PNjhd87WH4SCRGwxsX5rX3M00AU2r+QjSMCHWYUcsntoEXSBTfyKOlzautIdxPQIgdv3.Qnea78kNB..X5H...qi..."); + + loadFrom("1048.sNB..D...............35H...oi...rO.........J09R+fQcCU7A.Fs5fm.Nk5F.kAXzIouY2zs7srMdeccSSVqdo658jLCc6XFxHLQLFKBgAQvG.1A.b.rwLdhw0LlnpPYcPEVFa3xaXYLiDUkUkDkgKCA2Z1pJVTpXfkkJKJJVuG9qbfUEJVbjwtxREkCrz.C8LCnppnTMYghBsya+xlFoIVldWP7HQLEzhTFKpJWrDfs2PAPzs613Kd9uYfdWPuzc.58du.H4cAs+hg6OOFz6E.Iw6ZSFgvc9R9kdl.xRFPRZ5cs4gwNH7Zb+tjawdidOjdPhzCoG+YjlUY3jBflcS2hdg9y7Fruy+rYfxlSF5Ui2O.89PWYrAoIRSljdrRYM9H2OSvsT7YbHaKWDP8GeMcXUNTuyyT73NN47KUN9Td5TKfJgq8p0AuZby+xd9+d41404edNlZkmfqdegiF0jbG8o9rCG03o6Wi7vs16Rq4ZjjqC1tlNTdW+lsHuoYMaG80XyIaaMuKp2dlmI0z6hGIVQfy1Y0kNWG4VsnW5Zc+90IUV5x20msm0HrVY5lSmQ899a44YJYP.PIA7AEm5hwB0vsYp15leWELkgsugy11hqMOyaK45BCEQz.ILz+nLBoK83mI6pqHqDSuq4tEf1W6VGlyLtiZOBH3xGLzkXhXhCGvjd.Ry4YBmEcJ.4EI63PNzcBnZc6KWdXL3dxEwtTiYlevnClB63lKRVp.gjzFaduQLKLC.nynFaHAgPDMBM..5.LF.TrppJ.RhKHFQOFjTATJA.PS.MgvfIp.BPIBhCfH.gaIUyM3O5nYqXsgeG0ilMAYdXNbziz3lZmbK4.nNEXfC+olUz1+okCABVoVZI0M.ZvXPyLWnUadVXHQB6tcfN7NdtLDvXYE2a7FNyOirxlksbjPBiGWPpwVova1Q8orAoG4e6oy6OaB+vkWMlOdOCC.4XM8tPjkhMhlMqg2dXd7kyBYvbm.tM9c5i1KhGo0jjaPwkYAjPPFOQl3sX3uh735PLuBjBsSiUicfD5bsbajERmyhi0LTXBrdvqErKPqW.IAn5CrJkc6+EtmelKWF.HQyLf3DhUkDQ.eTKObPKKkc9Uyi2m4cJEzgHV1Maz3KaFm1CsWF1Grt88XsQRwA1C6MpixNFGl7.w03aCSrKXbIgkDfn7OBFmSR8NKiEAHY5QhayeZOF1JfAu9JLg0Qnhp9yxVmMY7tNePaRSGiTJ.Zx5QSikOV4jVA89EskzBmrC9seCSZ+FPjicrKtZVOMVJ4tPIVDWwqZe9QOB4xhL8W.+GlABSikYg7yB2cZ.BH9yU.EmGFnOXJzEucWA.e+AwJhw+emCkMgkYT35n+AmF+wm4U5H..foi...rNB..."); + + state.get()->dynamicComponentFactory = [this](const String& id) + { + return new CompileLogger(this); + }; dialog->setFinishCallback([this]() { @@ -927,7 +1237,7 @@ NetworkCompiler::~NetworkCompiler() killFunction(); state->clearCompletedJobs(); - + dialog = nullptr; dynamic_cast(compileExporter.get())->managerToUse = nullptr; compileExporter = nullptr; @@ -936,34 +1246,47 @@ NetworkCompiler::~NetworkCompiler() var NetworkCompiler::onInit(const var::NativeFunctionArgs& args) { - String s; + String ns, cs, fs; const auto& nodes = dynamic_cast(compileExporter.get())->nodesToCompile; const auto& cpp = dynamic_cast(compileExporter.get())->cppFilesToCompile; + auto faustDir = BackendDllManager::getSubFolder(getMainController(), BackendDllManager::FolderSubType::FaustCode); + auto faust = faustDir.findChildFiles(File::findFiles, false, "*.dsp"); + if(!nodes.isEmpty()) { - s << "DSP Networks to compile: \n> `"; - for(auto& n: nodes) - s << n << ", "; - - s = s.upToLastOccurrenceOf(", ", false, false); - s << "`\n"; + ns << "- `" << n << "`\n"; + } + else + { + ns << "No networks"; } - if(!cpp.isEmpty()) + if(!faust.isEmpty()) + { + for(auto& n: faust) + fs << "- `" << n.getFileNameWithoutExtension() << "`\n"; + } + else { - s << "\nC++ files to compile: \n> `"; + fs << "No faust files"; + } + if(!cpp.isEmpty()) + { for(auto& n: cpp) - s << n << ", "; - - s = s.upToLastOccurrenceOf(", ", false, false); - s << "`\n"; + cs << "- `" << n << "`\n"; + } + else + { + cs << "No C++ files"; } - setElementProperty("nodeList", mpid::Text, s); + setElementProperty("nodeList", mpid::Text, ns); + setElementProperty("cppList", mpid::Text, cs); + setElementProperty("faustList", mpid::Text, fs); return var(); @@ -972,9 +1295,15 @@ var NetworkCompiler::onInit(const var::NativeFunctionArgs& args) var NetworkCompiler::compileTask(const var::NativeFunctionArgs& args) { auto nc = dynamic_cast(compileExporter.get()); - + nc->run(); + { + MessageManagerLock mm; + findParentComponentOfClass()->minimizeModalComponent(false, state.get()); + } + + auto ok = nc->getErrorCode(); if(ok != CompileExporter::OK) @@ -985,6 +1314,8 @@ var NetworkCompiler::compileTask(const var::NativeFunctionArgs& args) return var(); } + + } } } diff --git a/hi_backend/backend/dialog_library/dialog_library.h b/hi_backend/backend/dialog_library/dialog_library.h index 8fe9494a7c..51393a8510 100644 --- a/hi_backend/backend/dialog_library/dialog_library.h +++ b/hi_backend/backend/dialog_library/dialog_library.h @@ -4,16 +4,63 @@ namespace hise { -class ChildProcessManager +class ChildProcessManager: public AsyncUpdater { public: - virtual ~ChildProcessManager() {}; + ChildProcessManager() + { + log.setDisableUndo(true); + } - virtual void logMessage(const String& message) = 0; + virtual ~ChildProcessManager() {}; virtual void setProgress(double progress) = 0; + void handleAsyncUpdate() override + { + CodeDocument::Position pos(log, log.getNumCharacters()); + + log.insertText(pos, currentMessage); + + SimpleReadWriteLock::ScopedReadLock sl(logLock); + currentMessage = {}; + } + + void logMessage(const String& message) + { + { + SimpleReadWriteLock::ScopedWriteLock sl(logLock); + + if(message.contains("error")) + currentMessage << "!"; + + auto isLinkerMessage = message.contains("Generating code") || + message.contains("Linking "); + + if(isLinkerMessage) + { + currentMessage << "> "; + setProgress(0.8); + } + + if(message.contains("warning")) + currentMessage << "\t"; + + currentMessage << message; + if(!message.containsChar('\n')) + currentMessage << '\n'; + } + + triggerAsyncUpdate(); + } + + SimpleReadWriteLock logLock; + String currentMessage; + + CodeDocument log; + + //std::function logFunction; std::function killFunction; }; @@ -283,9 +330,61 @@ class NewProjectCreator: public ImporterBase, DialogWindowWithBackgroundThread::LogData logData; }; +struct CompileLogger: public Component, + public CodeDocument::Listener +{ + Console::ConsoleTokeniser tokeniser; + + CompileLogger(ChildProcessManager* manager): + parent(manager), + console(manager->log, &tokeniser) + { + tokeniser.errorIsWholeLine = true; + + parent->log.addListener(this); + + console.setReadOnly(true); + console.setLineNumbersShown(false); + console.setColour(CodeEditorComponent::ColourIds::defaultTextColourId, Colour(0xFF999999)); + console.setColour(CodeEditorComponent::ColourIds::backgroundColourId, Colour(0xFF222222)); + console.setColour(CodeEditorComponent::ColourIds::highlightColourId, Colour(SIGNAL_COLOUR).withAlpha(0.5f)); + addAndMakeVisible(console); + } + + ~CompileLogger() + { + parent->log.removeListener(this); + } + + void codeDocumentTextDeleted(int startIndex, int endIndex) override {}; + + void codeDocumentTextInserted(const String& newText, int insertIndex) override + { + auto numLines = parent->log.getNumLines(); + console.scrollToKeepLinesOnScreen({numLines - 1, numLines}); + } + + void resized() override + { + console.setBounds(getLocalBounds()); + } + + void paint(Graphics& g) override + { + + } + + + + ChildProcessManager* parent; + + CodeEditorComponent console; + + +}; + struct NetworkCompiler: public EncodedDialogBase, - public ChildProcessManager, - public AsyncUpdater + public ChildProcessManager { NetworkCompiler(BackendRootWindow* bpe_); @@ -305,41 +404,63 @@ struct NetworkCompiler: public EncodedDialogBase, } } - void handleAsyncUpdate() override - { - auto m = readState("CompileOutput").toString(); - - { - SimpleReadWriteLock::ScopedReadLock sl(logLock); - m << "\n" << currentMessage; - currentMessage = {}; - } - - writeState("CompileOutput", m); + var onInit(const var::NativeFunctionArgs& args); + var compileTask(const var::NativeFunctionArgs& args); - if(auto md = dialog->findPageBaseForID("CompileOutput")) - { - md->postInit(); - } - } - - void logMessage(const String& message) override + + BackendRootWindow* bpe; + ScopedPointer compileExporter; +}; + +struct CompileProjectDialog: public EncodedDialogBase, + public ChildProcessManager +{ + CompileProjectDialog(BackendRootWindow* bpe_); + + ~CompileProjectDialog(); + + void bindCallbacks() override { - SimpleReadWriteLock::ScopedWriteLock sl(logLock); - currentMessage << message; - triggerAsyncUpdate(); + MULTIPAGE_BIND_CPP(CompileProjectDialog, compileTask); + MULTIPAGE_BIND_CPP(CompileProjectDialog, onInit); + MULTIPAGE_BIND_CPP(CompileProjectDialog, onExportType); + MULTIPAGE_BIND_CPP(CompileProjectDialog, onPluginType); + + MULTIPAGE_BIND_CPP(CompileProjectDialog, onComplete); + MULTIPAGE_BIND_CPP(CompileProjectDialog, onShowPluginFolder); + MULTIPAGE_BIND_CPP(CompileProjectDialog, onShowCompiledFile); + + MULTIPAGE_BIND_CPP(CompileProjectDialog, onCopyToClipboard); + } + + void setProgress(double progress) override + { + if(auto j = state->currentJob.get()) + { + j->getProgress() = progress; + } } - - SimpleReadWriteLock logLock; - String currentMessage; var onInit(const var::NativeFunctionArgs& args); var compileTask(const var::NativeFunctionArgs& args); + var onExportType(const var::NativeFunctionArgs& args); + var onPluginType(const var::NativeFunctionArgs& args); + + var onComplete(const var::NativeFunctionArgs& args); + var onShowPluginFolder(const var::NativeFunctionArgs& args); + var onShowCompiledFile(const var::NativeFunctionArgs& args); + var onCopyToClipboard(const var::NativeFunctionArgs& args); + + File getTargetFile() const; + + int getBuildFlag() const; BackendRootWindow* bpe; ScopedPointer compileExporter; }; + + struct SnippetBrowser: public EncodedDialogBase { SnippetBrowser(BackendRootWindow* bpe_): diff --git a/hi_backend/snex_workbench/WorkbenchProcessor.cpp b/hi_backend/snex_workbench/WorkbenchProcessor.cpp index df297488e9..82ed8b1f78 100644 --- a/hi_backend/snex_workbench/WorkbenchProcessor.cpp +++ b/hi_backend/snex_workbench/WorkbenchProcessor.cpp @@ -311,7 +311,7 @@ void DspNetworkCompileExporter::run() //showStatusMessage("Unload DLL"); //getDllManager()->unloadDll(); - showStatusMessage("Create files"); + logMessage("Create files"); auto buildFolder = getFolder(BackendDllManager::FolderSubType::Binaries); @@ -325,7 +325,7 @@ void DspNetworkCompileExporter::run() for (auto s : unsortedList) unsortedListU.removeAllInstancesOf(s); - showStatusMessage("Sorting include dependencies"); + logMessage("Sorting include dependencies"); Array list, ulist; @@ -410,7 +410,7 @@ void DspNetworkCompileExporter::run() return; } - showStatusMessage("Creating C++ file for Network " + id); + logMessage("Creating C++ file for Network " + id); scriptnode::routing::LocalCableHelpers::replaceAllLocalCables(v); @@ -531,7 +531,7 @@ void DspNetworkCompileExporter::run() if (!thirdPartyFiles.isEmpty()) { - showStatusMessage("Copying third party files"); + logMessage("Copying third party files"); for (auto tpf : thirdPartyFiles) { @@ -541,7 +541,7 @@ void DspNetworkCompileExporter::run() if (!externalSamples.isEmpty()) { - showStatusMessage("Writing embedded audio data file"); + logMessage("Writing embedded audio data file"); auto eadFile = getSourceDirectory(true).getChildFile("embedded_audiodata.h"); eadFile.deleteFile(); @@ -680,7 +680,7 @@ void DspNetworkCompileExporter::run() BuildOption o = CompileExporter::VSTLinux; #endif - showStatusMessage("Compiling dll plugin"); + logMessage("Compiling dll plugin"); configurationName = getComboBoxComponent("build")->getText(); diff --git a/hi_backend/snex_workbench/WorkbenchProcessor.h b/hi_backend/snex_workbench/WorkbenchProcessor.h index dd6c6e75aa..985c2820d3 100644 --- a/hi_backend/snex_workbench/WorkbenchProcessor.h +++ b/hi_backend/snex_workbench/WorkbenchProcessor.h @@ -154,6 +154,14 @@ class DspNetworkCompileExporter : public hise::DialogWindowWithBackgroundThread, static bool isInterpretedDataFile(const File& f); + void logMessage(const String& m) + { + if(managerToUse != nullptr) + managerToUse->logMessage("> " + m + "\n"); + else + showStatusMessage(m); + } + void createIncludeFile(const File& sourceDir); void createProjucerFile(); diff --git a/hi_core/hi_core/BackgroundThreads.h b/hi_core/hi_core/BackgroundThreads.h index cbbb57fc3a..65afac009d 100644 --- a/hi_core/hi_core/BackgroundThreads.h +++ b/hi_core/hi_core/BackgroundThreads.h @@ -78,6 +78,26 @@ class ModalBaseWindow bool isCurrentlyModal() const; void clearModalComponent(); + bool isMinimized = false; + + void minimizeModalComponent(bool shouldBeMinimized, multipage::State* state) + { + if(isMinimized != shouldBeMinimized) + { + isMinimized = shouldBeMinimized; + + if(backdrop != nullptr) + backdrop->setVisible(!isMinimized); + + if(modalComponent != nullptr) + modalComponent->setVisible(!isMinimized); + + minimizeBroadcaster.sendMessage(sendNotificationSync, isMinimized, state); + } + } + + LambdaBroadcaster minimizeBroadcaster; + /** This returns the main controller depending on the project type. */ const MainController* getMainController() const; diff --git a/hi_core/hi_core/Console.cpp b/hi_core/hi_core/Console.cpp index 429c1a2b00..d68e761311 100644 --- a/hi_core/hi_core/Console.cpp +++ b/hi_core/hi_core/Console.cpp @@ -297,7 +297,7 @@ int Console::ConsoleTokeniser::readNextToken(CodeDocument::Iterator& source) } - if(tokenIndex == 5) + if(tokenIndex == 5 || ((tokenIndex == 2 || tokenIndex == 4) && errorIsWholeLine)) { source.skipToEndOfLine(); return tokenIndex; diff --git a/hi_core/hi_core/Console.h b/hi_core/hi_core/Console.h index 0a25197687..956af0bd15 100644 --- a/hi_core/hi_core/Console.h +++ b/hi_core/hi_core/Console.h @@ -85,8 +85,6 @@ class Console: public Component, static void updateFontSize(Console& c, float newSize); -private: - class ConsoleTokeniser : public CodeTokeniser { public: @@ -97,6 +95,8 @@ class Console: public Component, CodeEditorComponent::ColourScheme getDefaultColourScheme() override; + bool errorIsWholeLine = false; + private: int state = 0; diff --git a/hi_core/hi_core/HiseSettings.cpp b/hi_core/hi_core/HiseSettings.cpp index e3787dd8d1..9c4a6ab401 100644 --- a/hi_core/hi_core/HiseSettings.cpp +++ b/hi_core/hi_core/HiseSettings.cpp @@ -110,6 +110,7 @@ Array HiseSettings::Project::getAllIds() ids.add(CompileWithPerfetto); ids.add(CompileWithDebugSymbols); ids.add(IncludeLorisInFrontend); + ids.add(ProjectType); return ids; } @@ -295,6 +296,11 @@ Array HiseSettings::SnexWorkbench::getAllIds() D("the compiler will crash with an **out of heap space** error, so in this case you're better off not embedding them."); P_(); + P(HiseSettings::Project::ProjectType); + D("The plugin type that this project should be compiled as. Can be either an instrument, an effect plugin or a MIDI FX plugin."); + D("> This setting is used (and can be changed) in the new compile dialog but has been added as project setting to keep the flag persistent for projects."); + P_(); + P(HiseSettings::Project::SupportFullDynamicsHLAC); D("If enabled, the user can extract the sample monolith files to support the full dynamic range of 24 bit."); D("The HLAC codec is 16bit only, but with this feature enabled, it normalises the audio data in chunks of 1024 samples in order to recreate higher bit depths. This results in a lower compression ratio, but removes the quantisation noise that can occur under certain circumstances:"); @@ -976,7 +982,10 @@ juce::StringArray HiseSettings::Data::getOptionsFor(const Identifier& id) { return { "75%", "85%", "100%", "125%", "150%" }; } - + if (id == Project::ProjectType) + { + return { "Instrument", "FX plugin", "MIDI plugin" }; + } if (id == Project::ExpansionType) { return { "Disabled", "FilesOnly", "Encrypted", "Full", "Custom" }; @@ -1184,6 +1193,7 @@ var HiseSettings::Data::getDefaultSetting(const Identifier& id) const else if (id == Project::CompileWithPerfetto) return "No"; else if (id == Compiler::ExportSetup) return "No"; else if (id == Project::CompileWithDebugSymbols) return "No"; + else if (id == Project::ProjectType) return "Instrument"; else if (id == Project::ExpansionType) return "Disabled"; else if (id == Project::LinkExpansionsToProject) return "No"; else if (id == Project::EnableGlobalPreprocessor) return "No"; diff --git a/hi_core/hi_core/HiseSettings.h b/hi_core/hi_core/HiseSettings.h index 2434b2b83c..59b857365e 100644 --- a/hi_core/hi_core/HiseSettings.h +++ b/hi_core/hi_core/HiseSettings.h @@ -102,6 +102,7 @@ DECLARE_ID(DefaultUserPreset); DECLARE_ID(CompileWithPerfetto); DECLARE_ID(CompileWithDebugSymbols); DECLARE_ID(IncludeLorisInFrontend); +DECLARE_ID(ProjectType); Array getAllIds(); diff --git a/hi_tools/hi_multipage/MultiPageDialog.cpp b/hi_tools/hi_multipage/MultiPageDialog.cpp index 845e519764..af47f0db29 100644 --- a/hi_tools/hi_multipage/MultiPageDialog.cpp +++ b/hi_tools/hi_multipage/MultiPageDialog.cpp @@ -540,7 +540,16 @@ void Dialog::PageBase::callOnValueChange(const String& eventType, DynamicObject: var::NativeFunctionArgs args(state->globalState, a, 2); - state->callNativeFunction(callbackName, args, nullptr); + try + { + rootDialog.clearIfCurrentErrorPage(this); + state->callNativeFunction(callbackName, args, nullptr); + } + catch(Result& r) + { + setModalHelp(r.getErrorMessage()); + rootDialog.setCurrentErrorPage(this); + } return; } @@ -1368,6 +1377,17 @@ void Dialog::setCurrentErrorPage(PageBase* b) repaint(); } +void Dialog::clearIfCurrentErrorPage(PageBase* b) +{ + if(currentErrorElement == b) + { + setCurrentErrorPage(nullptr); + + if(b != nullptr) + b->setModalHelp({}); + } +} + bool Dialog::keyPressed(const KeyPress& k) { if(k.getKeyCode() == KeyPress::F5Key) diff --git a/hi_tools/hi_multipage/MultiPageDialog.h b/hi_tools/hi_multipage/MultiPageDialog.h index be13946886..7058b206c3 100644 --- a/hi_tools/hi_multipage/MultiPageDialog.h +++ b/hi_tools/hi_multipage/MultiPageDialog.h @@ -707,6 +707,7 @@ class Dialog: public simple_css::HeaderContentFooter, void showModalPopup(bool addButtons, PageInfo::Ptr p); Result checkCurrentPage(); void setCurrentErrorPage(PageBase* b); + void clearIfCurrentErrorPage(PageBase* b); bool keyPressed(const KeyPress& k) override; var exportAsJSON() const; void scrollBarMoved (ScrollBar*, double) override { repaint(); } diff --git a/tools/json_dialog/compile_networks/compile_networks.json b/tools/json_dialog/compile_networks/compile_networks.json index 75ea3bda6a..bbc421436d 100644 --- a/tools/json_dialog/compile_networks/compile_networks.json +++ b/tools/json_dialog/compile_networks/compile_networks.json @@ -27,8 +27,8 @@ "Icon": "" }, "LayoutData": { - "StyleSheet": "Dark", - "Style": ".description\n{\n\ttext-align: left;\n\twidth: 100%;\n}\n\n#total-progress\n{\n\tdisplay: none;\n}\n\n#subtitle\n{\n\tdisplay: none;\n}\n\n.status\n{\n\tfont-family: monospace;\n\tfont-size: 12px;\n\tcolor: black;\n\t\n}", + "StyleSheet": "ModalPopup", + "Style": ".description\n{\n\ttext-align: left;\n\twidth: 100%;\n}\n\n#content\n{\n\tpadding: 30px 80px;\n}\n\n#total-progress\n{\n\tdisplay: none;\n}\n\n#subtitle\n{\n\tdisplay: none;\n}\n\n.status\n{\n\tfont-family: monospace;\n\tfont-size: 12px;\n\tcolor: black;\n\t\n}\n\n.list-label\n{\n\twidth: 100%;\n\t\n\theight: 40px;\n\ttext-align: left;\n\tfont-weight: bold;\n}\n\n.column\n{\n\talign-self: flex-start;\n}", "UseViewport": true, "ConfirmClose": true, "CloseMessage": "Do you want to close this popup?", @@ -36,56 +36,97 @@ "DialogHeight": 780 }, "GlobalState": { - "CompileOutput": "asdasdasd\nasda\nsasd\nasd\nas\nd\nasd", - "NetworkList": "Funky, wasGeht, noice" + "clearDLL": "true" }, "Children": [ { "Type": "List", "Children": [ + { + "Type": "Column", + "Children": [ + { + "Type": "List", + "Children": [ + { + "Type": "SimpleText", + "Text": "Networks to compile:", + "Class": ".list-label" + }, + { + "Type": "MarkdownText", + "Text": "- `Noice.xml`\n- `ScriptFX1.xml`\n- `Noice.xml`\n- `ScriptFX1.xml`\n- `Noice.xml`\n- `ScriptFX1.xml`\n- `Noice.xml`\n- `ScriptFX1.xml`\n- `Noice.xml`\n- `ScriptFX1.xml`", + "ID": "nodeList" + } + ], + "Class": ".column" + }, + { + "Type": "List", + "Children": [ + { + "Type": "SimpleText", + "Text": "C++ files to compile:", + "Class": ".list-label" + }, + { + "Type": "MarkdownText", + "Text": "- `Noice.cpp`\n- `ScriptFX1.cpp`", + "ID": "cppList" + } + ], + "Class": ".column" + }, + { + "Type": "List", + "Children": [ + { + "Type": "SimpleText", + "Text": "Faust files to compile:", + "Class": ".list-label" + }, + { + "Type": "MarkdownText", + "Text": "- `Noice.cpp`\n- `ScriptFX1.cpp`", + "ID": "faustList" + } + ], + "Class": ".column" + } + ], + "Style": "gap: 10px;" + }, { "Type": "JavascriptFunction", "ID": "onInit", "Code": "{BIND::onInit}" - }, - { - "Type": "MarkdownText", - "Text": "Networks to compile: \n\n> `Funky, wasGeht, noice`", - "ID": "nodeList" - }, + } + ], + "Text": "" + }, + { + "Type": "List", + "Children": [ { "Type": "SimpleText", - "Text": "Status:", + "Text": "Compilation Log:", "Class": ".description" }, { - "Type": "TextInput", + "Type": "Placeholder", "ID": "CompileOutput", - "Enabled": false, - "Class": ".status", - "NoLabel": true, - "Height": "180", - "Multiline": true + "ContentType": "Logger", + "Style": "height: 450px;" }, { "Type": "LambdaTask", "Text": "", "ID": "compileTask", - "EventTrigger": "OnSubmit", "Function": "compileTask" } ], - "Text": "" - }, - { - "Type": "List", - "Children": [ - { - "Type": "MarkdownText", - "Text": "The compilation was successful. Press Finish to reload the DLL.\n\n> You don't need to restart HISE anymore, all effects from the previous DLL will be automatically reloaded!\n\n" - } - ], - "Text": "" + "Text": "", + "Style": "gap: 20px;" } ], "Assets": [] diff --git a/tools/json_dialog/plugin_export/plugin_export.json b/tools/json_dialog/plugin_export/plugin_export.json new file mode 100644 index 0000000000..ebb750bda4 --- /dev/null +++ b/tools/json_dialog/plugin_export/plugin_export.json @@ -0,0 +1,193 @@ +{ + "StyleData": { + "Font": "Lato Regular", + "BoldFont": "", + "FontSize": 18.0, + "bgColour": 4281545523, + "codeBgColour": 864585864, + "linkBgColour": 8947967, + "textColour": 4294967295, + "codeColour": 4294967295, + "linkColour": 4289374975, + "tableHeaderBgColour": 864059520, + "tableLineColour": 864059520, + "tableBgColour": 864059520, + "headlineColour": 4287692721, + "UseSpecialBoldFont": false + }, + "Properties": { + "Header": "Compile Project", + "Subtitle": "", + "Image": "", + "ProjectName": "MyProject", + "Company": "MyCompany", + "Version": "1.0.0", + "BinaryName": "My Binary", + "UseGlobalAppData": false, + "Icon": "" + }, + "LayoutData": { + "StyleSheet": "ModalPopup", + "Style": "\n\n#content\n{\n\tpadding: 30px 80px;\n}\n\n#total-progress\n{\n\tdisplay: none;\n}\n\n.toggle-button\n{\n\tcolor: white;\n\ttext-align: left;\n}\n\n#ExportType label\n{\n\tdisplay: none;\n}\n\n#showCompiledFile label\n{\n\tdisplay: none;\n}\n\n.description\n{\n\twidth: 100%;\n\ttext-align: left;\n}\n\nlabel\n{\n\tmin-width: 120px;\n}\n\n#OutputFile\n{\n\twidth: 100%;\n\ttext-align: left;\n\n\tbackground: #282828;\n\tpadding: 10px 15px;\n\tborder-radius: 2px;\n\tcolor: #888;\n}", + "UseViewport": true, + "ConfirmClose": true, + "CloseMessage": "Do you want to close this popup?", + "DialogWidth": 800, + "DialogHeight": 780 + }, + "GlobalState": { + "showCompiledFile": true, + "showPluginFolder": true, + "ExportType": 0, + "projectType": "Instrument", + "pluginType": "VST", + "Clipboard": true + }, + "Children": [ + { + "Type": "List", + "Children": [ + { + "Type": "JavascriptFunction", + "ID": "JavascriptFunctionId", + "Code": "{BIND::onInit}" + }, + { + "Type": "SimpleText", + "Text": "Export Target:", + "Style": "width: 100%; text-align: left; margin-top: 80px;" + }, + { + "Type": "Button", + "Text": "Plugin", + "ID": "ExportType", + "Code": "{BIND::onExportType}", + "InitValue": "0", + "UseInitValue": true, + "Style": "margin-top: 10px;", + "ButtonType": "Toggle" + }, + { + "Type": "Button", + "Text": "Standalone App", + "ID": "ExportType", + "Code": "{BIND::onExportType}", + "UseInitValue": "" + }, + { + "Type": "MarkdownText", + "Text": "___" + }, + { + "Type": "Choice", + "Text": "Project Type", + "ID": "projectType", + "InitValue": "Instrument", + "UseInitValue": true, + "ValueMode": "Text", + "Items": "Instrument\nFX plugin\nMIDI plugin" + }, + { + "Type": "Choice", + "Text": "Plugin Type", + "ID": "pluginType", + "InitValue": "VST", + "UseInitValue": true, + "ValueMode": "Text", + "Items": "VST\nAU\nAAX\nAll Platforms", + "Code": "{BIND::onPluginType}" + }, + { + "Type": "MarkdownText", + "Text": "___\nOutput File:" + }, + { + "Type": "SimpleText", + "Text": "C:\\Development\\Funky.exe", + "ID": "OutputFile" + } + ], + "Text": "" + }, + { + "Type": "List", + "Children": [ + { + "Type": "Column", + "Children": [ + { + "Type": "SimpleText", + "Text": "Compilation Log:", + "Class": ".description" + }, + { + "Type": "Button", + "Text": "Copy to clipboard", + "ID": "Clipboard", + "Code": "{BIND::onCopyToClipboard}", + "Style": "width: 350px;", + "NoLabel": true, + "ButtonType": "Text", + "Trigger": true + } + ] + }, + { + "Type": "Placeholder", + "ID": "CompileOutput", + "ContentType": "Logger", + "Style": "height: 450px;" + }, + { + "Type": "LambdaTask", + "Text": "", + "ID": "compileTask", + "Function": "compileTask" + } + ], + "Text": "", + "Style": "gap: 20px;" + }, + { + "Type": "List", + "Children": [ + { + "Type": "MarkdownText", + "Text": "The compilation was successful.\n\n> On macOS you will have to manually copy this file to the plugin folder for the DAWs to pick it up when scanning for new plugins.\n\n___\n" + }, + { + "Type": "JavascriptFunction", + "ID": "JavascriptFunctionId", + "Code": "{BIND::onComplete}" + }, + { + "Type": "Column", + "Children": [ + { + "Type": "Button", + "Text": "Show compiled file", + "ID": "showCompiledFile", + "Code": "{BIND::onShowCompiledFile}", + "InitValue": "true", + "UseInitValue": true, + "Trigger": true, + "ButtonType": "Text" + }, + { + "Type": "Button", + "Text": "Show plugin folder", + "ID": "showPluginFolder", + "UseInitValue": "", + "NoLabel": true, + "ButtonType": "Text", + "Trigger": true, + "Code": "{BIND::onShowPluginFolder}" + } + ] + } + ], + "Text": "" + } + ], + "Assets": [] +} \ No newline at end of file