Skip to content

Commit

Permalink
Merge pull request #2028 from Wasted-Audio/feature/heavy_owl
Browse files Browse the repository at this point in the history
Feature/heavy owl
  • Loading branch information
timothyschoen authored Jan 10, 2025
2 parents 8e431d1 + fe1cec7 commit eb19226
Show file tree
Hide file tree
Showing 3 changed files with 240 additions and 4 deletions.
6 changes: 5 additions & 1 deletion Source/Heavy/HeavyExportDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "CppExporter.h"
#include "DPFExporter.h"
#include "DaisyExporter.h"
#include "OWLExporter.h"
#include "PdExporter.h"

class ExporterSettingsPanel final : public Component
Expand All @@ -39,6 +40,7 @@ class ExporterSettingsPanel final : public Component
"C++ Code",
"Electro-Smith Daisy",
"DPF Audio Plugin",
"OWL Platform",
"Pd External"
};

Expand All @@ -47,6 +49,7 @@ class ExporterSettingsPanel final : public Component
addChildComponent(views.add(new CppExporter(editor, exportingView)));
addChildComponent(views.add(new DaisyExporter(editor, exportingView)));
addChildComponent(views.add(new DPFExporter(editor, exportingView)));
addChildComponent(views.add(new OWLExporter(editor, exportingView)));
addChildComponent(views.add(new PdExporter(editor, exportingView)));

addAndMakeVisible(listBox);
Expand Down Expand Up @@ -84,7 +87,7 @@ class ExporterSettingsPanel final : public Component
auto heavyState = settingsTree.getChildWithName("HeavyState");
if (heavyState.isValid()) {
this->setState(heavyState);
for (int i = 0; i < 4; i++) {
for (int i = 0; i < views.size(); i++) {
views[i]->blockDialog = true;
views[i]->setState(heavyState);
views[i]->blockDialog = false;
Expand All @@ -100,6 +103,7 @@ class ExporterSettingsPanel final : public Component
state.appendChild(views[1]->getState(), nullptr);
state.appendChild(views[2]->getState(), nullptr);
state.appendChild(views[3]->getState(), nullptr);
state.appendChild(views[4]->getState(), nullptr);

auto settingsTree = SettingsFile::getInstance()->getValueTree();

Expand Down
231 changes: 231 additions & 0 deletions Source/Heavy/OWLExporter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
/*
// Copyright (c) 2024 Timothy Schoen and Wasted Audio
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*/

class OWLExporter : public ExporterBase {
public:
Value targetBoardValue = Value(var(2));
Value exportTypeValue = SynchronousValue(var(3));
Value storeSlotValue = SynchronousValue(var(1));

TextButton flashButton = TextButton("Flash");

PropertiesPanelProperty* storeSlotProperty;

OWLExporter(PluginEditor* editor, ExportingProgressView* exportingView)
: ExporterBase(editor, exportingView)
{
Array<PropertiesPanelProperty*> properties;
properties.add(new PropertiesPanel::ComboComponent("Target board", targetBoardValue, { "OWL1", "OWL2", "OWL3" }));
properties.add(new PropertiesPanel::ComboComponent("Export type", exportTypeValue, { "Source code", "Binary", "Load", "Store" }));
storeSlotProperty = new PropertiesPanel::ComboComponent(
"Store slot", storeSlotValue, {
"1", "2", "3", "4", "5", "6", "7", "8", "9",
"A", "B", "C", "D", "E", "F"
}
);
properties.add(storeSlotProperty);

for (auto* property : properties) {
property->setPreferredHeight(28);
}

panel.addSection("OWL", properties);

exportButton.setVisible(false);
addAndMakeVisible(flashButton);

auto const backgroundColour = findColour(PlugDataColour::panelBackgroundColourId);
flashButton.setColour(TextButton::buttonColourId, backgroundColour.contrasting(0.05f));
flashButton.setColour(TextButton::buttonOnColourId, backgroundColour.contrasting(0.1f));
flashButton.setColour(ComboBox::outlineColourId, Colours::transparentBlack);

targetBoardValue.addListener(this);
exportTypeValue.addListener(this);
storeSlotValue.addListener(this);

flashButton.onClick = [this, exportingView] {
auto const tempFolder = File::getSpecialLocation(File::tempDirectory).getChildFile("Heavy-" + Uuid().toString().substring(10));
Toolchain::deleteTempFileLater(tempFolder);
startExport(tempFolder);
};
}

ValueTree getState() override
{
ValueTree stateTree("OWL");
stateTree.setProperty("targetBoardValue", getValue<int>(targetBoardValue), nullptr);
stateTree.setProperty("exportTypeValue", getValue<int>(exportTypeValue), nullptr);
stateTree.setProperty("storeSlotValue", getValue<int>(storeSlotValue), nullptr);
return stateTree;
}

void setState(ValueTree& stateTree) override
{
auto tree = stateTree.getChildWithName("OWL");
targetBoardValue = tree.getProperty("targetBoardValue");
exportTypeValue = tree.getProperty("exportTypeValue");
storeSlotValue = tree.getProperty("storeSlotValue");
}

void resized() override
{
ExporterBase::resized();
flashButton.setBounds(exportButton.getBounds());
}

void valueChanged(Value& v) override
{
ExporterBase::valueChanged(v);

flashButton.setEnabled(validPatchSelected);

int const exportType = getValue<int>(exportTypeValue);
bool flash = exportType == 3 || exportType == 4;
exportButton.setVisible(!flash);
flashButton.setVisible(flash);

storeSlotProperty->setEnabled(exportType == 4);
}

bool performExport(String pdPatch, String outdir, String name, String copyright, StringArray searchPaths) override
{
auto target = getValue<int>(targetBoardValue);
bool compile = getValue<int>(exportTypeValue) - 1;
bool load = getValue<int>(exportTypeValue) == 3;
bool store = getValue<int>(exportTypeValue) == 4;
int slot = getValue<int>(storeSlotValue);

StringArray args = { heavyExecutable.getFullPathName(), pdPatch, "-o" + outdir };

name = name.replaceCharacter('-', '_');
args.add("-n" + name);

if (copyright.isNotEmpty()) {
args.add("--copyright");
args.add("\"" + copyright + "\"");
}

args.add("-v");
args.add("-gOWL");

String paths = "-p";
for (auto& path : searchPaths) {
paths += " " + path;
}

args.add(paths);

start(args.joinIntoString(" "));
waitForProcessToFinish(-1);
exportingView->flushConsole();

exportingView->logToConsole("Compiling...\n");

if (shouldQuit)
return true;

auto outputFile = File(outdir);
auto sourceDir = outputFile.getChildFile("Source");

bool heavyExitCode = getExitCode();

outputFile.getChildFile("ir").deleteRecursively();
outputFile.getChildFile("hv").deleteRecursively();
outputFile.getChildFile("c").deleteRecursively();

auto OWL = Toolchain::dir.getChildFile("lib").getChildFile("OwlProgram");
OWL.copyDirectoryTo(outputFile.getChildFile("OwlProgram"));

// Delay to get correct exit code
Time::waitForMillisecondCounter(Time::getMillisecondCounter() + 300);

if (compile) {
auto workingDir = File::getCurrentWorkingDirectory();

auto bin = Toolchain::dir.getChildFile("bin");
auto make = bin.getChildFile("make" + exeSuffix);
auto compiler = bin.getChildFile("arm-none-eabi-gcc" + exeSuffix);

auto OwlDir = outputFile.getChildFile("OwlProgram");
OwlDir.setAsCurrentWorkingDirectory();
OwlDir.getChildFile("Tools/FirmwareSender" + exeSuffix).setExecutePermission(1);

auto const& gccPath = bin.getFullPathName();

String buildScript;

#if JUCE_WINDOWS
buildScript += make.getFullPathName().replaceCharacter('\\', '/')
+ " -j4"
+ " TOOLROOT=" + gccPath.replaceCharacter('\\', '/') + "/"
+ " BUILD=../"
+ " PATCHNAME=" + name
+ " PATCHCLASS=HeavyPatch"
+ " PATCHFILE=HeavyOWL_" + name + ".hpp";
#else
buildScript += make.getFullPathName()
+ " -j4"
+ " TOOLROOT=" + gccPath + "/"
+ " BUILD=../"
+ " PATCHNAME=" + name
+ " PATCHCLASS=HeavyPatch"
+ " PATCHFILE=HeavyOWL_" + name + ".hpp";
#endif

buildScript += " PLATFORM=OWL" + String(target);

if (load) {
// load into flash memory
buildScript += " load";
} else if (store) {
// store into specific slot
buildScript += " store";
buildScript += " SLOT=" + String(slot);
} else {
// only build a binary
buildScript += " patch";
}

Toolchain::startShellScript(buildScript, this);

waitForProcessToFinish(-1);
exportingView->flushConsole();

// Restore original working directory
workingDir.setAsCurrentWorkingDirectory();

// Delay to get correct exit code
Time::waitForMillisecondCounter(Time::getMillisecondCounter() + 300);

auto compileExitCode = getExitCode();

// cleanup
outputFile.getChildFile("OwlProgram").deleteRecursively();
outputFile.getChildFile("web").deleteRecursively();
outputFile.getChildFile("Test").deleteRecursively();
outputFile.getChildFile("Source").deleteRecursively();
outputFile.getChildFile("patch.elf").deleteFile();

for (auto const& extension : StringArray("h", "cpp", "o", "d")) {
for (auto& file : outputFile.findChildFiles(2, false, "*." + extension)) {
file.deleteFile();
}
}

// rename binary
outputFile.getChildFile("patch.bin").moveFileTo(outputFile.getChildFile(name + ".bin"));

return heavyExitCode && compileExitCode;
} else {
auto outputFile = File(outdir);

outputFile.getChildFile("ir").deleteRecursively();
outputFile.getChildFile("hv").deleteRecursively();
outputFile.getChildFile("c").deleteRecursively();
return heavyExitCode;
}
}
};
7 changes: 4 additions & 3 deletions Source/Heavy/Toolchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ class ToolchainInstaller final : public Component
+ "\nchmod +x " + tcPath + "/lib/dpf/utils/generate-ttl.sh"
+ "\nchmod +x " + tcPath + "/arm-none-eabi/bin/*"
+ "\nchmod +x " + tcPath + "/lib/gcc/arm-none-eabi/*/*"
+ "\nchmod +x " + tcPath + "/lib/OwlProgram/Tools/*"
# if JUCE_LINUX
+ "\nchmod +x " + tcPath + "/x86_64-anywhere-linux-gnu/bin/*"
+ "\nchmod +x " + tcPath + "/x86_64-anywhere-linux-gnu/sysroot/sbin/*"
Expand Down Expand Up @@ -342,11 +343,11 @@ class ToolchainInstaller final : public Component
int statusCode;

#if JUCE_WINDOWS
String downloadSize = "720 MB";
String downloadSize = "1.2 GB";
#elif JUCE_MAC
String downloadSize = "650 MB";
String downloadSize = "457 MB";
#else
String downloadSize = "992 MB";
String downloadSize = "1.1 GB";
#endif

class ToolchainInstallerButton final : public Component {
Expand Down

0 comments on commit eb19226

Please sign in to comment.