Browse Source

Added asset.hpp for managing paths, Plugin instance created by Rack instead of the shared library, attempt to load plugins from global and then local location

tags/v0.4.0
Andrew Belt 7 years ago
parent
commit
a16a9e1b5f
12 changed files with 250 additions and 236 deletions
  1. +1
    -1
      Makefile
  2. +21
    -0
      include/asset.hpp
  3. +61
    -60
      include/components.hpp
  4. +10
    -7
      include/plugin.hpp
  5. +1
    -0
      include/rack.hpp
  6. +10
    -2
      src/app/RackWidget.cpp
  7. +55
    -0
      src/asset.cpp
  8. +5
    -12
      src/core/core.cpp
  9. +1
    -0
      src/core/core.hpp
  10. +3
    -9
      src/gui.cpp
  11. +5
    -90
      src/main.cpp
  12. +77
    -55
      src/plugin.cpp

+ 1
- 1
Makefile View File

@@ -60,7 +60,7 @@ debug: $(TARGET)
ifeq ($(ARCH), mac) ifeq ($(ARCH), mac)
lldb ./Rack lldb ./Rack
else else
gdb -ex run ./Rack
LD_LIBRARY_PATH=dep/lib gdb -ex run ./Rack
endif endif


clean: clean:


+ 21
- 0
include/asset.hpp View File

@@ -0,0 +1,21 @@
#pragma once

#include <string>
#include "plugin.hpp"


namespace rack {


/** Searches for a global read-only resource and returns its path, or "" if not found
*/
std::string assetGlobal(std::string filename);
/** Searches for a local resource
*/
std::string assetLocal(std::string filename);
/** Searches for a plugin resource, given a Plugin object
*/
std::string assetPlugin(Plugin *plugin, std::string filename);


} // namespace rack

+ 61
- 60
include/components.hpp View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "app.hpp" #include "app.hpp"
#include "asset.hpp"




namespace rack { namespace rack {
@@ -90,163 +91,163 @@ struct Rogan1P : Rogan {


struct Rogan6PSWhite : Rogan6PS { struct Rogan6PSWhite : Rogan6PS {
Rogan6PSWhite() { Rogan6PSWhite() {
setSVG(SVG::load("res/ComponentLibrary/Rogan6PSWhite.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan6PSWhite.svg")));
} }
}; };


struct Rogan5PSGray : Rogan5PS { struct Rogan5PSGray : Rogan5PS {
Rogan5PSGray() { Rogan5PSGray() {
setSVG(SVG::load("res/ComponentLibrary/Rogan5PSGray.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan5PSGray.svg")));
} }
}; };


struct Rogan3PSBlue : Rogan3PS { struct Rogan3PSBlue : Rogan3PS {
Rogan3PSBlue() { Rogan3PSBlue() {
setSVG(SVG::load("res/ComponentLibrary/Rogan3PSBlue.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan3PSBlue.svg")));
} }
}; };


struct Rogan3PSRed : Rogan3PS { struct Rogan3PSRed : Rogan3PS {
Rogan3PSRed() { Rogan3PSRed() {
setSVG(SVG::load("res/ComponentLibrary/Rogan3PSRed.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan3PSRed.svg")));
} }
}; };


struct Rogan3PSGreen : Rogan3PS { struct Rogan3PSGreen : Rogan3PS {
Rogan3PSGreen() { Rogan3PSGreen() {
setSVG(SVG::load("res/ComponentLibrary/Rogan3PSGreen.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan3PSGreen.svg")));
} }
}; };


struct Rogan3PSWhite : Rogan3PS { struct Rogan3PSWhite : Rogan3PS {
Rogan3PSWhite() { Rogan3PSWhite() {
setSVG(SVG::load("res/ComponentLibrary/Rogan3PSWhite.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan3PSWhite.svg")));
} }
}; };


struct Rogan3PBlue : Rogan3P { struct Rogan3PBlue : Rogan3P {
Rogan3PBlue() { Rogan3PBlue() {
setSVG(SVG::load("res/ComponentLibrary/Rogan3PBlue.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan3PBlue.svg")));
} }
}; };


struct Rogan3PRed : Rogan3P { struct Rogan3PRed : Rogan3P {
Rogan3PRed() { Rogan3PRed() {
setSVG(SVG::load("res/ComponentLibrary/Rogan3PRed.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan3PRed.svg")));
} }
}; };


struct Rogan3PGreen : Rogan3P { struct Rogan3PGreen : Rogan3P {
Rogan3PGreen() { Rogan3PGreen() {
setSVG(SVG::load("res/ComponentLibrary/Rogan3PGreen.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan3PGreen.svg")));
} }
}; };


struct Rogan3PWhite : Rogan3P { struct Rogan3PWhite : Rogan3P {
Rogan3PWhite() { Rogan3PWhite() {
setSVG(SVG::load("res/ComponentLibrary/Rogan3PWhite.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan3PWhite.svg")));
} }
}; };


struct Rogan2SGray : Rogan2S { struct Rogan2SGray : Rogan2S {
Rogan2SGray() { Rogan2SGray() {
setSVG(SVG::load("res/ComponentLibrary/Rogan2SGray.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan2SGray.svg")));
} }
}; };


struct Rogan2PSBlue : Rogan2PS { struct Rogan2PSBlue : Rogan2PS {
Rogan2PSBlue() { Rogan2PSBlue() {
setSVG(SVG::load("res/ComponentLibrary/Rogan2PSBlue.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan2PSBlue.svg")));
} }
}; };


struct Rogan2PSRed : Rogan2PS { struct Rogan2PSRed : Rogan2PS {
Rogan2PSRed() { Rogan2PSRed() {
setSVG(SVG::load("res/ComponentLibrary/Rogan2PSRed.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan2PSRed.svg")));
} }
}; };


struct Rogan2PSGreen : Rogan2PS { struct Rogan2PSGreen : Rogan2PS {
Rogan2PSGreen() { Rogan2PSGreen() {
setSVG(SVG::load("res/ComponentLibrary/Rogan2PSGreen.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan2PSGreen.svg")));
} }
}; };


struct Rogan2PSWhite : Rogan2PS { struct Rogan2PSWhite : Rogan2PS {
Rogan2PSWhite() { Rogan2PSWhite() {
setSVG(SVG::load("res/ComponentLibrary/Rogan2PSWhite.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan2PSWhite.svg")));
} }
}; };


struct Rogan2PBlue : Rogan2P { struct Rogan2PBlue : Rogan2P {
Rogan2PBlue() { Rogan2PBlue() {
setSVG(SVG::load("res/ComponentLibrary/Rogan2PBlue.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan2PBlue.svg")));
} }
}; };


struct Rogan2PRed : Rogan2P { struct Rogan2PRed : Rogan2P {
Rogan2PRed() { Rogan2PRed() {
setSVG(SVG::load("res/ComponentLibrary/Rogan2PRed.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan2PRed.svg")));
} }
}; };


struct Rogan2PGreen : Rogan2P { struct Rogan2PGreen : Rogan2P {
Rogan2PGreen() { Rogan2PGreen() {
setSVG(SVG::load("res/ComponentLibrary/Rogan2PGreen.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan2PGreen.svg")));
} }
}; };


struct Rogan2PWhite : Rogan2P { struct Rogan2PWhite : Rogan2P {
Rogan2PWhite() { Rogan2PWhite() {
setSVG(SVG::load("res/ComponentLibrary/Rogan2PWhite.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan2PWhite.svg")));
} }
}; };


struct Rogan1PSBlue : Rogan1PS { struct Rogan1PSBlue : Rogan1PS {
Rogan1PSBlue() { Rogan1PSBlue() {
setSVG(SVG::load("res/ComponentLibrary/Rogan1PSBlue.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan1PSBlue.svg")));
} }
}; };


struct Rogan1PSRed : Rogan1PS { struct Rogan1PSRed : Rogan1PS {
Rogan1PSRed() { Rogan1PSRed() {
setSVG(SVG::load("res/ComponentLibrary/Rogan1PSRed.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan1PSRed.svg")));
} }
}; };


struct Rogan1PSGreen : Rogan1PS { struct Rogan1PSGreen : Rogan1PS {
Rogan1PSGreen() { Rogan1PSGreen() {
setSVG(SVG::load("res/ComponentLibrary/Rogan1PSGreen.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan1PSGreen.svg")));
} }
}; };


struct Rogan1PSWhite : Rogan1PS { struct Rogan1PSWhite : Rogan1PS {
Rogan1PSWhite() { Rogan1PSWhite() {
setSVG(SVG::load("res/ComponentLibrary/Rogan1PSWhite.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan1PSWhite.svg")));
} }
}; };


struct Rogan1PBlue : Rogan1P { struct Rogan1PBlue : Rogan1P {
Rogan1PBlue() { Rogan1PBlue() {
setSVG(SVG::load("res/ComponentLibrary/Rogan1PBlue.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan1PBlue.svg")));
} }
}; };


struct Rogan1PRed : Rogan1P { struct Rogan1PRed : Rogan1P {
Rogan1PRed() { Rogan1PRed() {
setSVG(SVG::load("res/ComponentLibrary/Rogan1PRed.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan1PRed.svg")));
} }
}; };


struct Rogan1PGreen : Rogan1P { struct Rogan1PGreen : Rogan1P {
Rogan1PGreen() { Rogan1PGreen() {
setSVG(SVG::load("res/ComponentLibrary/Rogan1PGreen.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan1PGreen.svg")));
} }
}; };


struct Rogan1PWhite : Rogan1P { struct Rogan1PWhite : Rogan1P {
Rogan1PWhite() { Rogan1PWhite() {
setSVG(SVG::load("res/ComponentLibrary/Rogan1PWhite.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Rogan1PWhite.svg")));
} }
}; };


@@ -256,7 +257,7 @@ struct SynthTechAlco : SVGKnob {
box.size = Vec(45, 45); box.size = Vec(45, 45);
minAngle = -0.82*M_PI; minAngle = -0.82*M_PI;
maxAngle = 0.82*M_PI; maxAngle = 0.82*M_PI;
setSVG(SVG::load("res/ComponentLibrary/SynthTechAlco.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/SynthTechAlco.svg")));
} }
}; };


@@ -270,43 +271,43 @@ struct Davies1900hKnob : SVGKnob {


struct Davies1900hWhiteKnob : Davies1900hKnob { struct Davies1900hWhiteKnob : Davies1900hKnob {
Davies1900hWhiteKnob() { Davies1900hWhiteKnob() {
setSVG(SVG::load("res/ComponentLibrary/Davies1900hWhite.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Davies1900hWhite.svg")));
} }
}; };


struct Davies1900hBlackKnob : Davies1900hKnob { struct Davies1900hBlackKnob : Davies1900hKnob {
Davies1900hBlackKnob() { Davies1900hBlackKnob() {
setSVG(SVG::load("res/ComponentLibrary/Davies1900hBlack.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Davies1900hBlack.svg")));
} }
}; };


struct Davies1900hRedKnob : Davies1900hKnob { struct Davies1900hRedKnob : Davies1900hKnob {
Davies1900hRedKnob() { Davies1900hRedKnob() {
setSVG(SVG::load("res/ComponentLibrary/Davies1900hRed.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Davies1900hRed.svg")));
} }
}; };


struct Davies1900hLargeWhiteKnob : Davies1900hKnob { struct Davies1900hLargeWhiteKnob : Davies1900hKnob {
Davies1900hLargeWhiteKnob() { Davies1900hLargeWhiteKnob() {
setSVG(SVG::load("res/ComponentLibrary/Davies1900hLargeWhite.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Davies1900hLargeWhite.svg")));
} }
}; };


struct Davies1900hLargeBlackKnob : Davies1900hKnob { struct Davies1900hLargeBlackKnob : Davies1900hKnob {
Davies1900hLargeBlackKnob() { Davies1900hLargeBlackKnob() {
setSVG(SVG::load("res/ComponentLibrary/Davies1900hLargeBlack.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Davies1900hLargeBlack.svg")));
} }
}; };


struct Davies1900hLargeRedKnob : Davies1900hKnob { struct Davies1900hLargeRedKnob : Davies1900hKnob {
Davies1900hLargeRedKnob() { Davies1900hLargeRedKnob() {
setSVG(SVG::load("res/ComponentLibrary/Davies1900hLargeRed.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Davies1900hLargeRed.svg")));
} }
}; };


struct Davies1900hSmallBlackKnob : Davies1900hKnob { struct Davies1900hSmallBlackKnob : Davies1900hKnob {
Davies1900hSmallBlackKnob() { Davies1900hSmallBlackKnob() {
setSVG(SVG::load("res/ComponentLibrary/Davies1900hSmallBlack.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Davies1900hSmallBlack.svg")));
} }
}; };


@@ -317,7 +318,7 @@ struct Trimpot : SVGKnob {
box.size = Vec(17, 17); box.size = Vec(17, 17);
minAngle = -0.75*M_PI; minAngle = -0.75*M_PI;
maxAngle = 0.75*M_PI; maxAngle = 0.75*M_PI;
setSVG(SVG::load("res/ComponentLibrary/Trimpot.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/Trimpot.svg")));
} }
}; };


@@ -326,7 +327,7 @@ struct BefacoBigKnob : SVGKnob {
box.size = Vec(75, 75); box.size = Vec(75, 75);
minAngle = -0.75*M_PI; minAngle = -0.75*M_PI;
maxAngle = 0.75*M_PI; maxAngle = 0.75*M_PI;
setSVG(SVG::load("res/ComponentLibrary/BefacoBigKnob.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/BefacoBigKnob.svg")));
} }
}; };


@@ -337,7 +338,7 @@ struct BefacoTinyKnob : SVGKnob {
box.size = Vec(26, 26); box.size = Vec(26, 26);
minAngle = -0.75*M_PI; minAngle = -0.75*M_PI;
maxAngle = 0.75*M_PI; maxAngle = 0.75*M_PI;
setSVG(SVG::load("res/ComponentLibrary/BefacoTinyKnob.svg"));
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/BefacoTinyKnob.svg")));
} }
}; };


@@ -346,11 +347,11 @@ struct BefacoSlidePot : SVGSlider {
Vec margin = Vec(3.5, 3.5); Vec margin = Vec(3.5, 3.5);
maxHandlePos = Vec(-1, -2).plus(margin); maxHandlePos = Vec(-1, -2).plus(margin);
minHandlePos = Vec(-1, 87).plus(margin); minHandlePos = Vec(-1, 87).plus(margin);
background->svg = SVG::load("res/ComponentLibrary/BefacoSlidePot.svg");
background->svg = SVG::load(assetGlobal("res/ComponentLibrary/BefacoSlidePot.svg"));
background->wrap(); background->wrap();
background->box.pos = margin; background->box.pos = margin;
box.size = background->box.size.plus(margin.mult(2)); box.size = background->box.size.plus(margin.mult(2));
handle->svg = SVG::load("res/ComponentLibrary/BefacoSlidePotHandle.svg");
handle->svg = SVG::load(assetGlobal("res/ComponentLibrary/BefacoSlidePotHandle.svg"));
handle->wrap(); handle->wrap();
} }
}; };
@@ -361,7 +362,7 @@ struct BefacoSlidePot : SVGSlider {


struct PJ301MPort : SVGPort { struct PJ301MPort : SVGPort {
PJ301MPort() { PJ301MPort() {
background->svg = SVG::load("res/ComponentLibrary/PJ301M.svg");
background->svg = SVG::load(assetGlobal("res/ComponentLibrary/PJ301M.svg"));
background->wrap(); background->wrap();
box.size = background->box.size; box.size = background->box.size;
} }
@@ -369,7 +370,7 @@ struct PJ301MPort : SVGPort {


struct PJ3410Port : SVGPort { struct PJ3410Port : SVGPort {
PJ3410Port() { PJ3410Port() {
background->svg = SVG::load("res/ComponentLibrary/PJ3410.svg");
background->svg = SVG::load(assetGlobal("res/ComponentLibrary/PJ3410.svg"));
background->wrap(); background->wrap();
box.size = background->box.size; box.size = background->box.size;
} }
@@ -377,7 +378,7 @@ struct PJ3410Port : SVGPort {


struct CL1362Port : SVGPort { struct CL1362Port : SVGPort {
CL1362Port() { CL1362Port() {
background->svg = SVG::load("res/ComponentLibrary/CL1362.svg");
background->svg = SVG::load(assetGlobal("res/ComponentLibrary/CL1362.svg"));
background->wrap(); background->wrap();
box.size = background->box.size; box.size = background->box.size;
} }
@@ -480,9 +481,9 @@ struct TinyLight : BASE {


struct NKK : SVGSwitch, ToggleSwitch { struct NKK : SVGSwitch, ToggleSwitch {
NKK() { NKK() {
addFrame(SVG::load("res/ComponentLibrary/NKK_0.svg"));
addFrame(SVG::load("res/ComponentLibrary/NKK_1.svg"));
addFrame(SVG::load("res/ComponentLibrary/NKK_2.svg"));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/NKK_0.svg")));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/NKK_1.svg")));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/NKK_2.svg")));
sw->wrap(); sw->wrap();
box.size = sw->box.size; box.size = sw->box.size;
} }
@@ -490,8 +491,8 @@ struct NKK : SVGSwitch, ToggleSwitch {


struct CKSS : SVGSwitch, ToggleSwitch { struct CKSS : SVGSwitch, ToggleSwitch {
CKSS() { CKSS() {
addFrame(SVG::load("res/ComponentLibrary/CKSS_0.svg"));
addFrame(SVG::load("res/ComponentLibrary/CKSS_1.svg"));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKSS_0.svg")));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKSS_1.svg")));
sw->wrap(); sw->wrap();
box.size = sw->box.size; box.size = sw->box.size;
} }
@@ -499,8 +500,8 @@ struct CKSS : SVGSwitch, ToggleSwitch {


struct CKD6 : SVGSwitch, MomentarySwitch { struct CKD6 : SVGSwitch, MomentarySwitch {
CKD6() { CKD6() {
addFrame(SVG::load("res/ComponentLibrary/CKD6_0.svg"));
addFrame(SVG::load("res/ComponentLibrary/CKD6_1.svg"));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKD6_0.svg")));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKD6_1.svg")));
sw->wrap(); sw->wrap();
box.size = sw->box.size; box.size = sw->box.size;
} }
@@ -508,8 +509,8 @@ struct CKD6 : SVGSwitch, MomentarySwitch {


struct TL1105 : SVGSwitch, MomentarySwitch { struct TL1105 : SVGSwitch, MomentarySwitch {
TL1105() { TL1105() {
addFrame(SVG::load("res/ComponentLibrary/TL1105_0.svg"));
addFrame(SVG::load("res/ComponentLibrary/TL1105_1.svg"));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/TL1105_0.svg")));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/TL1105_1.svg")));
sw->wrap(); sw->wrap();
box.size = sw->box.size; box.size = sw->box.size;
} }
@@ -517,7 +518,7 @@ struct TL1105 : SVGSwitch, MomentarySwitch {


struct LEDButton : SVGSwitch, MomentarySwitch { struct LEDButton : SVGSwitch, MomentarySwitch {
LEDButton() { LEDButton() {
addFrame(SVG::load("res/ComponentLibrary/LEDButton.svg"));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/LEDButton.svg")));
sw->wrap(); sw->wrap();
box.size = sw->box.size; box.size = sw->box.size;
} }
@@ -525,9 +526,9 @@ struct LEDButton : SVGSwitch, MomentarySwitch {


struct BefacoSwitch : SVGSwitch, ToggleSwitch { struct BefacoSwitch : SVGSwitch, ToggleSwitch {
BefacoSwitch() { BefacoSwitch() {
addFrame(SVG::load("res/ComponentLibrary/BefacoSwitch_0.svg"));
addFrame(SVG::load("res/ComponentLibrary/BefacoSwitch_1.svg"));
addFrame(SVG::load("res/ComponentLibrary/BefacoSwitch_2.svg"));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/BefacoSwitch_0.svg")));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/BefacoSwitch_1.svg")));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/BefacoSwitch_2.svg")));
sw->wrap(); sw->wrap();
box.size = sw->box.size; box.size = sw->box.size;
} }
@@ -535,8 +536,8 @@ struct BefacoSwitch : SVGSwitch, ToggleSwitch {


struct BefacoPush : SVGSwitch, MomentarySwitch { struct BefacoPush : SVGSwitch, MomentarySwitch {
BefacoPush() { BefacoPush() {
addFrame(SVG::load("res/ComponentLibrary/BefacoPush_0.svg"));
addFrame(SVG::load("res/ComponentLibrary/BefacoPush_1.svg"));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/BefacoPush_0.svg")));
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/BefacoPush_1.svg")));
sw->wrap(); sw->wrap();
box.size = sw->box.size; box.size = sw->box.size;
} }
@@ -549,7 +550,7 @@ struct BefacoPush : SVGSwitch, MomentarySwitch {


struct ScrewSilver : SVGScrew { struct ScrewSilver : SVGScrew {
ScrewSilver() { ScrewSilver() {
sw->svg = SVG::load("res/ComponentLibrary/ScrewSilver.svg");
sw->svg = SVG::load(assetGlobal("res/ComponentLibrary/ScrewSilver.svg"));
sw->wrap(); sw->wrap();
box.size = sw->box.size; box.size = sw->box.size;
} }
@@ -557,7 +558,7 @@ struct ScrewSilver : SVGScrew {


struct ScrewBlack : SVGScrew { struct ScrewBlack : SVGScrew {
ScrewBlack() { ScrewBlack() {
sw->svg = SVG::load("res/ComponentLibrary/ScrewBlack.svg");
sw->svg = SVG::load(assetGlobal("res/ComponentLibrary/ScrewBlack.svg"));
sw->wrap(); sw->wrap();
box.size = sw->box.size; box.size = sw->box.size;
} }


+ 10
- 7
include/plugin.hpp View File

@@ -13,21 +13,25 @@ struct Model;
struct Plugin { struct Plugin {
virtual ~Plugin(); virtual ~Plugin();


// A unique identifier for your plugin, e.g. "foo"
/** A unique identifier for your plugin, e.g. "foo" */
std::string slug; std::string slug;
// Human readable name for your plugin, e.g. "Foo Modular"
/** Human readable name for your plugin, e.g. "Foo Modular" */
std::string name; std::string name;
/** The file path of the plugins directory */
std::string path;
/** A list of the models made available by this plugin */ /** A list of the models made available by this plugin */
std::list<Model*> models; std::list<Model*> models;
/** OS-dependent library handle */
void *handle = NULL;
}; };


struct Model { struct Model {
virtual ~Model() {} virtual ~Model() {}


Plugin *plugin; Plugin *plugin;
// A unique identifier for the model in this plugin, e.g. "vco"
/** A unique identifier for the model in this plugin, e.g. "VCO" */
std::string slug; std::string slug;
// Human readable name for your model, e.g. "VCO"
/** Human readable name for your model, e.g. "Voltage Controlled Oscillator" */
std::string name; std::string name;
virtual ModuleWidget *createModuleWidget() { return NULL; } virtual ModuleWidget *createModuleWidget() { return NULL; }
}; };
@@ -54,8 +58,7 @@ std::string pluginGetLoginStatus();
// Implemented by plugin // Implemented by plugin
//////////////////// ////////////////////


/** Called once to initialize and return Plugin.
Plugin is destructed when Rack closes
/** Called once to initialize and return the Plugin instance.
*/ */
extern "C" extern "C"
rack::Plugin *init();
void init(rack::Plugin *plugin);

+ 1
- 0
include/rack.hpp View File

@@ -8,6 +8,7 @@
#include "app.hpp" #include "app.hpp"
#include "components.hpp" #include "components.hpp"
#include "dsp.hpp" #include "dsp.hpp"
#include "asset.hpp"




namespace rack { namespace rack {


+ 10
- 2
src/app/RackWidget.cpp View File

@@ -4,6 +4,8 @@
#include "engine.hpp" #include "engine.hpp"
#include "plugin.hpp" #include "plugin.hpp"
#include "gui.hpp" #include "gui.hpp"
#include "settings.hpp"
#include "asset.hpp"
#include "../ext/osdialog/osdialog.h" #include "../ext/osdialog/osdialog.h"




@@ -49,7 +51,7 @@ void RackWidget::clear() {
} }


void RackWidget::openDialog() { void RackWidget::openDialog() {
std::string dir = lastPath.empty() ? "." : extractDirectory(lastPath);
std::string dir = lastPath.empty() ? assetLocal("") : extractDirectory(lastPath);
char *path = osdialog_file(OSDIALOG_OPEN, dir.c_str(), NULL, NULL); char *path = osdialog_file(OSDIALOG_OPEN, dir.c_str(), NULL, NULL);
if (path) { if (path) {
loadPatch(path); loadPatch(path);
@@ -68,7 +70,7 @@ void RackWidget::saveDialog() {
} }


void RackWidget::saveAsDialog() { void RackWidget::saveAsDialog() {
std::string dir = lastPath.empty() ? "." : extractDirectory(lastPath);
std::string dir = lastPath.empty() ? assetLocal("") : extractDirectory(lastPath);
char *path = osdialog_file(OSDIALOG_SAVE, dir.c_str(), "Untitled.vcv", NULL); char *path = osdialog_file(OSDIALOG_SAVE, dir.c_str(), "Untitled.vcv", NULL);
if (path) { if (path) {
savePatch(path); savePatch(path);
@@ -333,6 +335,12 @@ void RackWidget::step() {
} }
} }


// Autosave every 15 seconds
if (gGuiFrame % (60*15) == 0) {
savePatch(assetLocal("autosave.vcv"));
settingsSave(assetLocal("settings.json"));
}

Widget::step(); Widget::step();
} }




+ 55
- 0
src/asset.cpp View File

@@ -0,0 +1,55 @@
#include "asset.hpp"
#include <stdlib.h> // for realpath
#include <assert.h>


namespace rack {


static std::string fileRealPath(std::string path) {
char *rpath = realpath(path.c_str(), NULL);
if (!rpath)
return "";

std::string rrpath = path;
free(rpath);
return rrpath;
}

std::string assetGlobal(std::string filename) {
std::string path;
#if ARCH_MAC
// TODO
#endif
#if ARCH_WIN
path = "./" + filename;
#endif
#if ARCH_LIN
path = "./" + filename;
#endif
return fileRealPath(path);
}

std::string assetLocal(std::string filename) {
std::string path;
#if ARCH_MAC
// TODO
#endif
#if ARCH_WIN
// TODO
#endif
#if ARCH_LIN
// TODO
// If Rack is "installed" (however that may be defined), look in ~/.Rack or something instead
path = "./" + filename;
#endif
return fileRealPath(path);
}

std::string assetPlugin(Plugin *plugin, std::string filename) {
assert(plugin);
return fileRealPath(plugin->path + "/" + filename);
}


} // namespace rack

+ 5
- 12
src/core/core.cpp View File

@@ -1,16 +1,9 @@
#include "core.hpp" #include "core.hpp"




struct CorePlugin : Plugin {
CorePlugin() {
slug = "Core";
name = "Core";
createModel<AudioInterfaceWidget>(this, "AudioInterface", "Audio Interface");
createModel<MidiInterfaceWidget>(this, "MidiInterface", "MIDI Interface");
}
};


Plugin *init() {
return new CorePlugin();
void init(rack::Plugin *plugin) {
plugin->slug = "Core";
plugin->name = "Core";
createModel<AudioInterfaceWidget>(plugin, "AudioInterface", "Audio Interface");
createModel<MidiInterfaceWidget>(plugin, "MidiInterface", "MIDI Interface");
} }

+ 1
- 0
src/core/core.hpp View File

@@ -3,6 +3,7 @@


using namespace rack; using namespace rack;



//////////////////// ////////////////////
// module widgets // module widgets
//////////////////// ////////////////////


+ 3
- 9
src/gui.cpp View File

@@ -2,7 +2,7 @@


#include "gui.hpp" #include "gui.hpp"
#include "app.hpp" #include "app.hpp"
#include "settings.hpp"
#include "asset.hpp"
#include "../ext/osdialog/osdialog.h" #include "../ext/osdialog/osdialog.h"


#define NANOVG_GL2_IMPLEMENTATION #define NANOVG_GL2_IMPLEMENTATION
@@ -255,9 +255,9 @@ void guiInit() {
assert(gVg); assert(gVg);


// Set up Blendish // Set up Blendish
gGuiFont = Font::load("res/DejaVuSans.ttf");
gGuiFont = Font::load(assetGlobal("res/DejaVuSans.ttf"));
bndSetFont(gGuiFont->handle); bndSetFont(gGuiFont->handle);
// bndSetIconImage(loadImage("res/icons.png"));
// bndSetIconImage(loadImage(assetGlobal("res/icons.png")));
} }


void guiDestroy() { void guiDestroy() {
@@ -302,12 +302,6 @@ void guiRun() {
// Render // Render
renderGui(); renderGui();


// Autosave every 15 seconds
if (gGuiFrame % (60*15) == 0) {
gRackWidget->savePatch("autosave.vcv");
settingsSave("settings.json");
}

double currTime = glfwGetTime(); double currTime = glfwGetTime();
// printf("%lf fps\n", 1.0/(currTime - lastTime)); // printf("%lf fps\n", 1.0/(currTime - lastTime));
lastTime = currTime; lastTime = currTime;


+ 5
- 90
src/main.cpp View File

@@ -3,116 +3,31 @@
#include "app.hpp" #include "app.hpp"
#include "plugin.hpp" #include "plugin.hpp"
#include "settings.hpp" #include "settings.hpp"


#if ARCH_MAC
#include <CoreFoundation/CoreFoundation.h>
#include <unistd.h> // for chdir and access
#include <libgen.h> // for dirname
// #include <string.h>
#include <mach-o/dyld.h> // for _NSGetExecutablePath
#include <limits.h> // for PATH_MAX?
#include <dirent.h> // for opendir

void alert(std::string header, std::string message, int level) {
CFStringRef headerRef = CFStringCreateWithCString(NULL, header.c_str(), header.size());
CFStringRef messageRef = CFStringCreateWithCString(NULL, message.c_str(), message.size());
CFOptionFlags result;

CFUserNotificationDisplayAlert(
0, // no timeout
level, // flags for alert level
NULL, // iconURL
NULL, // soundURL
NULL, // localizationURL
headerRef,
messageRef,
NULL, // default "OK"
NULL, // alternative button
NULL, // other button
&result
);

CFRelease(headerRef);
CFRelease(messageRef);
}

bool isCorrectCwd() {
DIR *dir = opendir("res");
if (dir) {
closedir(dir);
return true;
}
else {
return false;
}
}

/** macOS workaround for setting the working directory to the location of the .app */
void fixCwd() {
// Check if the cwd is already set correctly (e.g. launched from the command line or gdb)
if (isCorrectCwd())
return;

/*
// Get path of binary inside the app bundle
// It should be something like .../Rack.app/Contents/MacOS
char path[PATH_MAX];
uint32_t pathLen = sizeof(path);
int err = _NSGetExecutablePath(path, &pathLen);
assert(!err);
if (isCorrectCwd())
return;

// Switch to the directory of the actual binary
chdir(dirname(path));
if (isCorrectCwd())
return;

// and then go up three directories to get to the parent directory
chdir("../../../");
if (isCorrectCwd())
return;
*/

// Switch to a default absolute path
chdir("/Applications/Rack");
if (isCorrectCwd())
return;

alert("Install Rack", "To install Rack, please move the Rack directory (including the Rack app and plugins directory) to the /Applications folder.", 2);
exit(1);
}
#endif
#include "asset.hpp"




using namespace rack; using namespace rack;


int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
#if ARCH_MAC
fixCwd();
#endif

pluginInit(); pluginInit();
engineInit(); engineInit();
guiInit(); guiInit();
sceneInit(); sceneInit();
settingsLoad("settings.json");
settingsLoad(assetLocal("settings.json"));
if (argc >= 2) if (argc >= 2)
gRackWidget->loadPatch(argv[1]); gRackWidget->loadPatch(argv[1]);
else else
gRackWidget->loadPatch("autosave.vcv");
gRackWidget->loadPatch(assetLocal("autosave.vcv"));


engineStart(); engineStart();
guiRun(); guiRun();
engineStop(); engineStop();


gRackWidget->savePatch("autosave.vcv");
settingsSave("settings.json");
gRackWidget->savePatch(assetLocal("autosave.vcv"));
settingsSave(assetLocal("settings.json"));
sceneDestroy(); sceneDestroy();
guiDestroy(); guiDestroy();
engineDestroy(); engineDestroy();
pluginDestroy(); pluginDestroy();
return 0; return 0;
} }


+ 77
- 55
src/plugin.cpp View File

@@ -22,6 +22,7 @@


#include "plugin.hpp" #include "plugin.hpp"
#include "app.hpp" #include "app.hpp"
#include "asset.hpp"
#include "util/request.hpp" #include "util/request.hpp"




@@ -43,55 +44,70 @@ Plugin::~Plugin() {
} }
} }


static int loadPlugin(std::string slug) {
#if ARCH_LIN
std::string path = "./plugins/" + slug + "/plugin.so";
#elif ARCH_WIN
std::string path = "./plugins/" + slug + "/plugin.dll";
#elif ARCH_MAC
std::string path = "./plugins/" + slug + "/plugin.dylib";
#endif
static int loadPlugin(std::string path) {
std::string libraryFilename;
#if ARCH_LIN
libraryFilename = path + "/" + "plugin.so";
#elif ARCH_WIN
libraryFilename = path + "/" + "plugin.dll";
#elif ARCH_MAC
libraryFilename = path + "/" + "plugin.dylib";
#endif


// Load dynamic/shared library // Load dynamic/shared library
#if ARCH_WIN
HINSTANCE handle = LoadLibrary(path.c_str());
if (!handle) {
int error = GetLastError();
fprintf(stderr, "Failed to load library %s: %d\n", path.c_str(), error);
return -1;
}
#elif ARCH_LIN || ARCH_MAC
void *handle = dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL);
if (!handle) {
fprintf(stderr, "Failed to load library %s: %s\n", path.c_str(), dlerror());
return -1;
}
#endif
#if ARCH_WIN
HINSTANCE handle = LoadLibrary(libraryFilename.c_str());
if (!handle) {
int error = GetLastError();
fprintf(stderr, "Failed to load library %s: %d\n", libraryFilename.c_str(), error);
return -1;
}
#elif ARCH_LIN || ARCH_MAC
void *handle = dlopen(libraryFilename.c_str(), RTLD_NOW);
if (!handle) {
fprintf(stderr, "Failed to load library %s: %s\n", libraryFilename.c_str(), dlerror());
return -1;
}
#endif


// Call plugin init() function // Call plugin init() function
typedef Plugin *(*InitCallback)();
typedef void (*InitCallback)(Plugin *);
InitCallback initCallback; InitCallback initCallback;
#if ARCH_WIN
initCallback = (InitCallback) GetProcAddress(handle, "init");
#elif ARCH_LIN || ARCH_MAC
initCallback = (InitCallback) dlsym(handle, "init");
#endif
#if ARCH_WIN
initCallback = (InitCallback) GetProcAddress(handle, "init");
#elif ARCH_LIN || ARCH_MAC
initCallback = (InitCallback) dlsym(handle, "init");
#endif
if (!initCallback) { if (!initCallback) {
fprintf(stderr, "Failed to read init() symbol in %s\n", path.c_str());
fprintf(stderr, "Failed to read init() symbol in %s\n", libraryFilename.c_str());
return -2; return -2;
} }


// Add plugin to map
Plugin *plugin = initCallback();
if (!plugin) {
fprintf(stderr, "Library %s did not return a plugin\n", path.c_str());
return -3;
}
// Construct and initialize Plugin instance
Plugin *plugin = new Plugin();
plugin->path = path;
plugin->handle = handle;
initCallback(plugin);

// Add plugin to list
gPlugins.push_back(plugin); gPlugins.push_back(plugin);
fprintf(stderr, "Loaded plugin %s\n", path.c_str());
fprintf(stderr, "Loaded plugin %s\n", libraryFilename.c_str());
return 0; return 0;
} }


static void loadPlugins(std::string path) {
DIR *dir = opendir(path.c_str());
if (dir) {
struct dirent *d;
while ((d = readdir(dir))) {
if (d->d_name[0] == '.')
continue;
loadPlugin(path + "/" + d->d_name);
}
closedir(dir);
}
}

//////////////////// ////////////////////
// plugin helpers // plugin helpers
//////////////////// ////////////////////
@@ -178,14 +194,13 @@ static void refreshPurchase(json_t *pluginJ) {
downloadProgress = 0.0; downloadProgress = 0.0;


// Download zip // Download zip
std::string filename = "plugins/";
mkdir(filename.c_str(), 0755);
filename += slug;
filename += ".zip";
std::string pluginsDir = assetLocal("plugins");
mkdir(pluginsDir.c_str(), 0755);
std::string filename = pluginsDir + "/" + slug + ".zip";
bool success = requestDownload(download, filename, &downloadProgress); bool success = requestDownload(download, filename, &downloadProgress);
if (success) { if (success) {
// Unzip file // Unzip file
int err = extractZip(filename.c_str(), "plugins");
int err = extractZip(filename.c_str(), pluginsDir.c_str());
if (!err) { if (!err) {
// Load plugin // Load plugin
loadPlugin(slug); loadPlugin(slug);
@@ -204,26 +219,33 @@ static void refreshPurchase(json_t *pluginJ) {
void pluginInit() { void pluginInit() {
// Load core // Load core
// This function is defined in core.cpp // This function is defined in core.cpp
Plugin *corePlugin = init();
Plugin *corePlugin = new Plugin();
init(corePlugin);
gPlugins.push_back(corePlugin); gPlugins.push_back(corePlugin);


// Search for plugin libraries
DIR *dir = opendir("plugins");
if (dir) {
struct dirent *d;
while ((d = readdir(dir))) {
if (d->d_name[0] == '.')
continue;
loadPlugin(d->d_name);
}
closedir(dir);
}
// Load plugins from global directory
std::string globalPlugins = assetGlobal("plugins");
loadPlugins(globalPlugins);

// Load plugins from local directory
std::string localPlugins = assetLocal("plugins");
if (globalPlugins != localPlugins)
loadPlugins(localPlugins);
} }


void pluginDestroy() { void pluginDestroy() {
for (Plugin *plugin : gPlugins) { for (Plugin *plugin : gPlugins) {
// TODO free shared library handle with `dlclose` or `FreeLibrary`
delete plugin;
// Free library handle
#if ARCH_WIN
if (plugin->handle)
FreeLibrary(plugin->handle);
#elif ARCH_LIN || ARCH_MAC
if (plugin->handle)
dlclose(plugin->handle);
#endif

// For some reason this segfaults
// delete plugin;
} }
gPlugins.clear(); gPlugins.clear();
} }


Loading…
Cancel
Save