diff --git a/Makefile b/Makefile index ba4c6d41..0555600f 100644 --- a/Makefile +++ b/Makefile @@ -74,6 +74,9 @@ include compile.mk dist: all +ifndef VERSION + $(error VERSION must be defined when calling make) +endif rm -rf dist $(MAKE) -C plugins/Fundamental dist @@ -144,7 +147,7 @@ ifeq ($(ARCH), lin) cp dep/lib/libcurl.so.4 dist/Rack/ cp dep/lib/libzip.so.5 dist/Rack/ cp dep/lib/libportaudio.so.2 dist/Rack/ - cp dep/lib/librtmidi.so dist/Rack/ + cp dep/lib/librtmidi.so.4 dist/Rack/ mkdir -p dist/Rack/plugins cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ endif diff --git a/README.md b/README.md index b9af12ba..eb7f4a0d 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Rack's dependencies (GLEW, glfw, etc) do not need to be installed on your system ### Mac Install [Xcode](https://developer.apple.com/xcode/). -Install [CMake](https://cmake.org/) and wget, preferably from [Homebrew](https://brew.sh/). +Install [CMake](https://cmake.org/) (for some of Rack's dependencies) and wget, preferably from [Homebrew](https://brew.sh/). ### Windows @@ -38,7 +38,7 @@ With your distro's package manager, make sure you have installed `gcc`, `make`, *If the build fails for you, please report the issue with a detailed error message to help the portability of Rack.* Clone this repository and `cd` into it. -If you would like to build a previous version instead of the master branch, run `git checkout v0.3.2` for example. +If you would like to build a previous version of Rack instead of the master branch, check out the desired tag with `git checkout v0.4.0` for example. Clone submodules. @@ -61,6 +61,8 @@ Run Rack. ## Building plugins +Be sure to check out and build the version of Rack you wish to build your plugins against. + Clone your favorite plugin in the `plugins/` directory. e.g.: cd plugins diff --git a/compile.mk b/compile.mk index acaf8a0e..1c794024 100644 --- a/compile.mk +++ b/compile.mk @@ -1,12 +1,14 @@ -VERSION ?= dev -FLAGS += -DVERSION=$(VERSION) -DVERSION_$(subst .,_,$(VERSION)) +ifdef VERSION +FLAGS += -DVERSION=$(VERSION) +endif # Generate dependency files alongside the object files FLAGS += -MMD +FLAGS += -g # Optimization FLAGS += -O3 -march=nocona -ffast-math -FLAGS += -Wall -FLAGS += -g +FLAGS += -Wall -Wextra -Wno-unused-parameter +CXXFLAGS += -Wsuggest-override CXXFLAGS += -std=c++11 diff --git a/include/app.hpp b/include/app.hpp index e0fd3f53..1e63ac83 100644 --- a/include/app.hpp +++ b/include/app.hpp @@ -50,22 +50,24 @@ struct ModuleWidget : OpaqueWidget { /** Resets the parameters of the module and calls the Module's randomize(). Called when the user clicks Initialize in the context menu. */ - virtual void initialize(); + virtual void reset(); + /** Deprecated */ + virtual void initialize() final {} /** Randomizes the parameters of the module and calls the Module's randomize(). Called when the user clicks Randomize in the context menu. */ virtual void randomize(); virtual Menu *createContextMenu(); - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; Vec dragPos; - Widget *onMouseMove(Vec pos, Vec mouseRel); - Widget *onHoverKey(Vec pos, int key); - void onDragStart(); - void onDragMove(Vec mouseRel); - void onDragEnd(); - void onMouseDownOpaque(int button); + Widget *onMouseMove(Vec pos, Vec mouseRel) override; + Widget *onHoverKey(Vec pos, int key) override; + void onDragStart() override; + void onDragMove(Vec mouseRel) override; + void onDragEnd() override; + void onMouseDownOpaque(int button) override; }; struct ValueLight; @@ -85,7 +87,7 @@ struct WireWidget : OpaqueWidget { void updateWire(); Vec getOutputPos(); Vec getInputPos(); - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; void drawPlugs(NVGcontext *vg); }; @@ -99,7 +101,7 @@ struct WireContainer : TransparentWidget { void removeAllWires(Port *port); /** Returns the most recently added wire connected to the given Port, i.e. the top of the stack */ WireWidget *getTopWire(Port *port); - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; struct RackWidget : OpaqueWidget { @@ -113,7 +115,10 @@ struct RackWidget : OpaqueWidget { RackWidget(); ~RackWidget(); + /** Completely clear the rack's modules and wires */ void clear(); + /** Clears the rack and loads the template patch */ + void reset(); void openDialog(); void saveDialog(); void saveAsDialog(); @@ -130,20 +135,20 @@ struct RackWidget : OpaqueWidget { bool requestModuleBox(ModuleWidget *m, Rect box); /** Moves a module to the closest non-colliding position */ bool requestModuleBoxNearest(ModuleWidget *m, Rect box); - void step(); - void draw(NVGcontext *vg); + void step() override; + void draw(NVGcontext *vg) override; - void onMouseDownOpaque(int button); + void onMouseDownOpaque(int button) override; }; struct RackRail : TransparentWidget { - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; struct Panel : TransparentWidget { NVGcolor backgroundColor; std::shared_ptr backgroundImage; - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; struct SVGPanel : FramebufferWidget { @@ -156,13 +161,13 @@ struct SVGPanel : FramebufferWidget { struct CircularShadow : TransparentWidget { float blur = 0.0; - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; struct Light : TransparentWidget { NVGcolor bgColor = nvgRGBf(0, 0, 0); NVGcolor color = nvgRGBf(1, 1, 1); - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; struct ParamWidget : OpaqueWidget, QuantityWidget { @@ -176,22 +181,25 @@ struct ParamWidget : OpaqueWidget, QuantityWidget { json_t *toJson(); void fromJson(json_t *rootJ); virtual void randomize(); - void onMouseDownOpaque(int button); - void onChange(); + void onMouseDownOpaque(int button) override; + void onChange() override; }; /** Implements vertical dragging behavior for ParamWidgets */ struct Knob : ParamWidget { - void onDragStart(); - void onDragMove(Vec mouseRel); - void onDragEnd(); + /** Snap to nearest integer while dragging */ + bool snap = false; + float dragValue; + void onDragStart() override; + void onDragMove(Vec mouseRel) override; + void onDragEnd() override; /** Tell engine to smoothly vary this parameter */ - void onChange(); + void onChange() override; }; struct SpriteKnob : virtual Knob, SpriteWidget { int minIndex, maxIndex, spriteCount; - void step(); + void step() override; }; /** A knob which rotates an SVG and caches it in a framebuffer */ @@ -204,16 +212,8 @@ struct SVGKnob : virtual Knob, FramebufferWidget { SVGKnob(); void setSVG(std::shared_ptr svg); - void step(); - void onChange(); -}; - -/** Snaps to the nearest integer value on mouse release */ -struct SnapKnob : virtual Knob { - void onDragEnd() { - setValue(roundf(value)); - Knob::onDragEnd(); - } + void step() override; + void onChange() override; }; struct SVGSlider : Knob, FramebufferWidget { @@ -224,8 +224,8 @@ struct SVGSlider : Knob, FramebufferWidget { SVGWidget *handle; SVGSlider(); - void step(); - void onChange(); + void step() override; + void onChange() override; }; struct Switch : ParamWidget { @@ -239,13 +239,13 @@ struct SVGSwitch : virtual Switch, FramebufferWidget { SVGSwitch(); /** Adds an SVG file to represent the next switch position */ void addFrame(std::shared_ptr svg); - void step(); - void onChange(); + void step() override; + void onChange() override; }; /** A switch that cycles through each mechanical position */ struct ToggleSwitch : virtual Switch { - void onDragStart() { + void onDragStart() override { // Cycle through values // e.g. a range of [0.0, 3.0] would have modes 0, 1, 2, and 3. if (value >= maxValue) @@ -258,11 +258,11 @@ struct ToggleSwitch : virtual Switch { /** A switch that is turned on when held */ struct MomentarySwitch : virtual Switch { /** Don't randomize state */ - void randomize() {} - void onDragStart() { + void randomize() override {} + void onDragStart() override { setValue(maxValue); } - void onDragEnd() { + void onDragEnd() override { setValue(minValue); } }; @@ -282,20 +282,20 @@ struct Port : OpaqueWidget { int portId; ~Port(); - void draw(NVGcontext *vg); - void onMouseDownOpaque(int button); - void onDragEnd(); - void onDragStart(); - void onDragDrop(Widget *origin); - void onDragEnter(Widget *origin); - void onDragLeave(Widget *origin); + void draw(NVGcontext *vg) override; + void onMouseDownOpaque(int button) override; + void onDragEnd() override; + void onDragStart() override; + void onDragDrop(Widget *origin) override; + void onDragEnter(Widget *origin) override; + void onDragLeave(Widget *origin) override; }; struct SVGPort : Port, FramebufferWidget { SVGWidget *background; SVGPort(); - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; /** If you don't add these to your ModuleWidget, they will fall out of the rack... */ @@ -316,7 +316,7 @@ struct Toolbar : OpaqueWidget { RadioButton *plugLightButton; Toolbar(); - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; struct PluginManagerWidget : Widget { @@ -324,7 +324,7 @@ struct PluginManagerWidget : Widget { Widget *manageWidget; Widget *downloadWidget; PluginManagerWidget(); - void step(); + void step() override; }; struct RackScene : Scene { @@ -332,9 +332,9 @@ struct RackScene : Scene { ZoomWidget *zoomWidget; RackScene(); - void step(); - void draw(NVGcontext *vg); - Widget *onHoverKey(Vec pos, int key); + void step() override; + void draw(NVGcontext *vg) override; + Widget *onHoverKey(Vec pos, int key) override; }; //////////////////// diff --git a/include/components.hpp b/include/components.hpp index ea8603ef..a9b02a22 100644 --- a/include/components.hpp +++ b/include/components.hpp @@ -57,7 +57,11 @@ struct RoundHugeBlackKnob : RoundBlackKnob { } }; -struct RoundSmallBlackSnapKnob : RoundSmallBlackKnob, SnapKnob {}; +struct RoundSmallBlackSnapKnob : RoundSmallBlackKnob { + RoundSmallBlackSnapKnob() { + snap = true; + } +}; struct Davies1900hKnob : SVGKnob { @@ -109,7 +113,11 @@ struct Davies1900hSmallBlackKnob : Davies1900hKnob { } }; -struct Davies1900hSmallBlackSnapKnob : Davies1900hSmallBlackKnob, SnapKnob {}; +struct Davies1900hSmallBlackSnapKnob : Davies1900hSmallBlackKnob { + Davies1900hSmallBlackSnapKnob() { + snap = true; + } +}; struct Rogan : SVGKnob { @@ -366,7 +374,11 @@ struct BefacoBigKnob : SVGKnob { } }; -struct BefacoBigSnapKnob : BefacoBigKnob, SnapKnob {}; +struct BefacoBigSnapKnob : BefacoBigKnob { + BefacoBigSnapKnob() { + snap = true; + } +}; struct BefacoTinyKnob : SVGKnob { BefacoTinyKnob() { @@ -426,7 +438,7 @@ struct CL1362Port : SVGPort { struct ValueLight : Light { float *value = NULL; virtual void setValue(float v) {} - void step() { + void step() override { if (value) setValue(*value); } @@ -434,7 +446,7 @@ struct ValueLight : Light { struct ColorValueLight : ValueLight { NVGcolor baseColor; - void setValue(float v) { + void setValue(float v) override { v = sqrtBipolar(v); color = baseColor; color.a *= clampf(v, 0.0, 1.0); @@ -462,7 +474,7 @@ struct GreenValueLight : ColorValueLight { struct PolarityLight : ValueLight { NVGcolor posColor; NVGcolor negColor; - void setValue(float v) { + void setValue(float v) override { v = sqrtBipolar(v); color = (v >= 0.0) ? posColor : negColor; color.a *= clampf(fabsf(v), 0.0, 1.0); @@ -478,7 +490,7 @@ struct GreenRedPolarityLight : PolarityLight { struct ModeValueLight : ValueLight { std::vector colors; - void setValue(float v) { + void setValue(float v) override { int mode = clampi((int)roundf(v), 0, colors.size()); color = colors[mode]; } @@ -615,8 +627,7 @@ struct ScrewBlack : SVGScrew { struct LightPanel : Panel { LightPanel() { - // backgroundColor = nvgRGB(0xe6, 0xe6, 0xe6); - backgroundColor = nvgRGB(0xf0, 0xf0, 0xf0); + backgroundColor = nvgRGB(0xe6, 0xe6, 0xe6); } }; diff --git a/include/engine.hpp b/include/engine.hpp index 50ceded7..b2f897b3 100644 --- a/include/engine.hpp +++ b/include/engine.hpp @@ -56,8 +56,10 @@ struct Module { virtual void fromJson(json_t *root) {} /** Override these to implement spacial behavior when user clicks Initialize and Randomize */ - virtual void initialize() {} + virtual void reset() {} virtual void randomize() {} + /** Deprecated */ + virtual void initialize() final {} }; struct Wire { @@ -82,8 +84,8 @@ void engineRemoveWire(Wire *wire); void engineSetParam(Module *module, int paramId, float value); void engineSetParamSmooth(Module *module, int paramId, float value); void engineSetSampleRate(float sampleRate); +float engineGetSampleRate(); -extern float gSampleRate; extern bool gPaused; diff --git a/include/rack.hpp b/include/rack.hpp index e6f398dc..abf27412 100644 --- a/include/rack.hpp +++ b/include/rack.hpp @@ -20,7 +20,7 @@ namespace rack { template Model *createModel(Plugin *plugin, std::string slug, std::string name) { struct TModel : Model { - ModuleWidget *createModuleWidget() { + ModuleWidget *createModuleWidget() override { ModuleWidget *moduleWidget = new TModuleWidget(); moduleWidget->model = this; return moduleWidget; diff --git a/include/widgets.hpp b/include/widgets.hpp index 7fafc368..16795064 100644 --- a/include/widgets.hpp +++ b/include/widgets.hpp @@ -141,7 +141,7 @@ struct TransformWidget : Widget { void translate(Vec delta); void rotate(float angle); void scale(Vec s); - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; @@ -151,33 +151,33 @@ struct TransformWidget : Widget { /** Widget that does not respond to events */ struct TransparentWidget : virtual Widget { - Widget *onMouseDown(Vec pos, int button) {return NULL;} - Widget *onMouseUp(Vec pos, int button) {return NULL;} - Widget *onMouseMove(Vec pos, Vec mouseRel) {return NULL;} - Widget *onScroll(Vec pos, Vec scrollRel) {return NULL;} + Widget *onMouseDown(Vec pos, int button) override {return NULL;} + Widget *onMouseUp(Vec pos, int button) override {return NULL;} + Widget *onMouseMove(Vec pos, Vec mouseRel) override {return NULL;} + Widget *onScroll(Vec pos, Vec scrollRel) override {return NULL;} }; /** Widget that automatically responds to all mouse events but gives a chance for children to respond instead */ struct OpaqueWidget : virtual Widget { - Widget *onMouseDown(Vec pos, int button) { + Widget *onMouseDown(Vec pos, int button) override { Widget *w = Widget::onMouseDown(pos, button); if (w) return w; onMouseDownOpaque(button); return this; } - Widget *onMouseUp(Vec pos, int button) { + Widget *onMouseUp(Vec pos, int button) override { Widget *w = Widget::onMouseUp(pos, button); if (w) return w; onMouseUpOpaque(button); return this; } - Widget *onMouseMove(Vec pos, Vec mouseRel) { + Widget *onMouseMove(Vec pos, Vec mouseRel) override { Widget *w = Widget::onMouseMove(pos, mouseRel); if (w) return w; onMouseMoveOpaque(mouseRel); return this; } - Widget *onScroll(Vec pos, Vec scrollRel) { + Widget *onScroll(Vec pos, Vec scrollRel) override { Widget *w = Widget::onScroll(pos, scrollRel); if (w) return w; if (onScrollOpaque(scrollRel)) @@ -199,22 +199,22 @@ struct SpriteWidget : virtual Widget { Vec spriteSize; std::shared_ptr spriteImage; int index = 0; - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; struct SVGWidget : virtual Widget { std::shared_ptr svg; /** Sets the box size to the svg image size */ void wrap(); - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; /** Caches a widget's draw() result to a framebuffer so it is called less frequently -When `dirty` is true, its children will be re-rendered on the next call to step(). +When `dirty` is true, its children will be re-rendered on the next call to step() override. Events are not passed to the underlying scene. */ struct FramebufferWidget : virtual Widget { - /** Set this to true to re-render the children to the framebuffer in the next step() */ + /** Set this to true to re-render the children to the framebuffer in the next step() override */ bool dirty = true; /** A margin in pixels around the children in the framebuffer This prevents cutting the rendered SVG off on the box edges. @@ -228,8 +228,8 @@ struct FramebufferWidget : virtual Widget { FramebufferWidget(); ~FramebufferWidget(); - void step(); - void draw(NVGcontext *vg); + void step() override; + void draw(NVGcontext *vg) override; int getImageHandle(); }; @@ -263,14 +263,14 @@ struct Label : Widget { Label() { box.size.y = BND_WIDGET_HEIGHT; } - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; // Deletes itself from parent when clicked struct MenuOverlay : OpaqueWidget { - void onDragDrop(Widget *origin); - bool onScrollOpaque(Vec scrollRel) {return true;} - Widget *onHoverKey(Vec pos, int key); + void onDragDrop(Widget *origin) override; + bool onScrollOpaque(Vec scrollRel) override {return true;} + Widget *onHoverKey(Vec pos, int key) override; }; struct MenuEntry; @@ -289,9 +289,9 @@ struct Menu : OpaqueWidget { void pushChild(Widget *child); void setChildMenu(Menu *menu); void fit(); - void step(); - void draw(NVGcontext *vg); - bool onScrollOpaque(Vec scrollRel); + void step() override; + void draw(NVGcontext *vg) override; + bool onScrollOpaque(Vec scrollRel) override; }; struct MenuEntry : OpaqueWidget { @@ -304,16 +304,16 @@ struct MenuEntry : OpaqueWidget { }; struct MenuLabel : MenuEntry { - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; struct MenuItem : MenuEntry { - float computeMinWidth(NVGcontext *vg); - void draw(NVGcontext *vg); + float computeMinWidth(NVGcontext *vg) override; + void draw(NVGcontext *vg) override; virtual Menu *createChildMenu() {return NULL;} - void onMouseEnter(); - void onDragDrop(Widget *origin); + void onMouseEnter() override; + void onDragDrop(Widget *origin) override; }; struct Button : OpaqueWidget { @@ -323,16 +323,16 @@ struct Button : OpaqueWidget { Button() { box.size.y = BND_WIDGET_HEIGHT; } - void draw(NVGcontext *vg); - void onMouseEnter(); - void onMouseLeave(); - void onDragStart(); - void onDragEnd(); - void onDragDrop(Widget *origin); + void draw(NVGcontext *vg) override; + void onMouseEnter() override; + void onMouseLeave() override; + void onDragStart() override; + void onDragEnd() override; + void onDragDrop(Widget *origin) override; }; struct ChoiceButton : Button { - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; struct RadioButton : OpaqueWidget, QuantityWidget { @@ -341,10 +341,10 @@ struct RadioButton : OpaqueWidget, QuantityWidget { RadioButton() { box.size.y = BND_WIDGET_HEIGHT; } - void draw(NVGcontext *vg); - void onMouseEnter(); - void onMouseLeave(); - void onDragDrop(Widget *origin); + void draw(NVGcontext *vg) override; + void onMouseEnter() override; + void onMouseLeave() override; + void onDragDrop(Widget *origin) override; }; struct Slider : OpaqueWidget, QuantityWidget { @@ -353,10 +353,10 @@ struct Slider : OpaqueWidget, QuantityWidget { Slider() { box.size.y = BND_WIDGET_HEIGHT; } - void draw(NVGcontext *vg); - void onDragStart(); - void onDragMove(Vec mouseRel); - void onDragEnd(); + void draw(NVGcontext *vg) override; + void onDragStart() override; + void onDragMove(Vec mouseRel) override; + void onDragEnd() override; }; /** Parent must be a ScrollWidget */ @@ -367,10 +367,10 @@ struct ScrollBar : OpaqueWidget { ScrollBar() { box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT); } - void draw(NVGcontext *vg); - void onDragStart(); - void onDragMove(Vec mouseRel); - void onDragEnd(); + void draw(NVGcontext *vg) override; + void onDragStart() override; + void onDragMove(Vec mouseRel) override; + void onDragEnd() override; }; /** Handles a container with ScrollBar */ @@ -381,19 +381,19 @@ struct ScrollWidget : OpaqueWidget { Vec offset; ScrollWidget(); - void step(); - Widget *onMouseMove(Vec pos, Vec mouseRel); - bool onScrollOpaque(Vec scrollRel); + void step() override; + Widget *onMouseMove(Vec pos, Vec mouseRel) override; + bool onScrollOpaque(Vec scrollRel) override; }; struct ZoomWidget : Widget { float zoom = 1.0; - void draw(NVGcontext *vg); - Widget *onMouseDown(Vec pos, int button); - Widget *onMouseUp(Vec pos, int button); - Widget *onMouseMove(Vec pos, Vec mouseRel); - Widget *onHoverKey(Vec pos, int key); - Widget *onScroll(Vec pos, Vec scrollRel); + void draw(NVGcontext *vg) override; + Widget *onMouseDown(Vec pos, int button) override; + Widget *onMouseUp(Vec pos, int button) override; + Widget *onMouseMove(Vec pos, Vec mouseRel) override; + Widget *onHoverKey(Vec pos, int key) override; + Widget *onScroll(Vec pos, Vec scrollRel) override; }; struct TextField : OpaqueWidget { @@ -405,36 +405,36 @@ struct TextField : OpaqueWidget { TextField() { box.size.y = BND_WIDGET_HEIGHT; } - void draw(NVGcontext *vg); - Widget *onMouseDown(Vec pos, int button); - bool onFocusText(int codepoint); - bool onFocusKey(int scancode); - bool onFocus(); + void draw(NVGcontext *vg) override; + Widget *onMouseDown(Vec pos, int button) override; + bool onFocusText(int codepoint) override; + bool onFocusKey(int key) override; + bool onFocus() override; void insertText(std::string newText); virtual void onTextChange() {} }; struct PasswordField : TextField { - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; struct ProgressBar : TransparentWidget, QuantityWidget { ProgressBar() { box.size.y = BND_WIDGET_HEIGHT; } - void draw(NVGcontext *vg); + void draw(NVGcontext *vg) override; }; struct Tooltip : Widget { - void step(); - void draw(NVGcontext *vg); + void step() override; + void draw(NVGcontext *vg) override; }; struct Scene : OpaqueWidget { Widget *overlay = NULL; void setOverlay(Widget *w); Menu *createMenu(); - void step(); + void step() override; }; diff --git a/src/app.cpp b/src/app.cpp index 98aec2cb..188b2471 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -4,7 +4,12 @@ namespace rack { std::string gApplicationName = "VCV Rack"; -std::string gApplicationVersion = TOSTRING(VERSION); +std::string gApplicationVersion = +#ifdef VERSION + TOSTRING(VERSION); +#else + "dev"; +#endif std::string gApiHost = "http://api.vcvrack.com"; RackWidget *gRackWidget = NULL; diff --git a/src/app/Knob.cpp b/src/app/Knob.cpp index d8961c53..01061ef6 100644 --- a/src/app/Knob.cpp +++ b/src/app/Knob.cpp @@ -12,6 +12,7 @@ namespace rack { void Knob::onDragStart() { guiCursorLock(); + dragValue = value; randomizable = false; } @@ -19,7 +20,11 @@ void Knob::onDragMove(Vec mouseRel) { // Drag slower if Mod if (guiIsModPressed()) mouseRel = mouseRel.mult(1/16.0); - setValue(value - KNOB_SENSITIVITY * (maxValue - minValue) * mouseRel.y); + dragValue += KNOB_SENSITIVITY * (maxValue - minValue) * -mouseRel.y; + if (snap) + setValue(roundf(dragValue)); + else + setValue(dragValue); } void Knob::onDragEnd() { @@ -31,7 +36,10 @@ void Knob::onChange() { if (!module) return; - engineSetParamSmooth(module, paramId, value); + if (snap) + engineSetParam(module, paramId, value); + else + engineSetParamSmooth(module, paramId, value); } diff --git a/src/app/Light.cpp b/src/app/Light.cpp index 55433943..aca594f9 100644 --- a/src/app/Light.cpp +++ b/src/app/Light.cpp @@ -6,7 +6,7 @@ namespace rack { void Light::draw(NVGcontext *vg) { float radius = box.size.x / 2.0; - float oradius = radius + 40.0; + float oradius = radius + 20.0; // Solid nvgBeginPath(vg); diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 3852eed6..1d768575 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -103,12 +103,12 @@ void ModuleWidget::disconnect() { } } -void ModuleWidget::initialize() { +void ModuleWidget::reset() { for (ParamWidget *param : params) { param->setValue(param->defaultValue); } if (module) { - module->initialize(); + module->reset(); } } @@ -170,7 +170,7 @@ Widget *ModuleWidget::onHoverKey(Vec pos, int key) { switch (key) { case GLFW_KEY_I: if (guiIsModPressed() && !guiIsShiftPressed()) { - initialize(); + reset(); return this; } break; @@ -206,35 +206,35 @@ void ModuleWidget::onDragEnd() { struct DisconnectMenuItem : MenuItem { ModuleWidget *moduleWidget; - void onAction() { + void onAction() override { moduleWidget->disconnect(); } }; -struct InitializeMenuItem : MenuItem { +struct ResetMenuItem : MenuItem { ModuleWidget *moduleWidget; - void onAction() { - moduleWidget->initialize(); + void onAction() override { + moduleWidget->reset(); } }; struct RandomizeMenuItem : MenuItem { ModuleWidget *moduleWidget; - void onAction() { + void onAction() override { moduleWidget->randomize(); } }; struct CloneMenuItem : MenuItem { ModuleWidget *moduleWidget; - void onAction() { + void onAction() override { gRackWidget->cloneModule(moduleWidget); } }; struct DeleteMenuItem : MenuItem { ModuleWidget *moduleWidget; - void onAction() { + void onAction() override { gRackWidget->deleteModule(moduleWidget); moduleWidget->finalizeEvents(); delete moduleWidget; @@ -248,7 +248,7 @@ Menu *ModuleWidget::createContextMenu() { menuLabel->text = model->plugin->name + ": " + model->name; menu->pushChild(menuLabel); - InitializeMenuItem *resetItem = new InitializeMenuItem(); + ResetMenuItem *resetItem = new ResetMenuItem(); resetItem->text = "Initialize"; resetItem->rightText = GUI_MOD_KEY_NAME "+I"; resetItem->moduleWidget = this; diff --git a/src/app/PluginManagerWidget.cpp b/src/app/PluginManagerWidget.cpp index ba8e74fc..8e4b6023 100644 --- a/src/app/PluginManagerWidget.cpp +++ b/src/app/PluginManagerWidget.cpp @@ -15,7 +15,7 @@ PluginManagerWidget::PluginManagerWidget() { Vec pos = Vec(0, 0); struct RegisterButton : Button { - void onAction() { + void onAction() override { std::thread t(openBrowser, "https://vcvrack.com/"); t.detach(); } @@ -46,7 +46,7 @@ PluginManagerWidget::PluginManagerWidget() { struct LogInButton : Button { TextField *emailField; TextField *passwordField; - void onAction() { + void onAction() override { std::thread t(pluginLogIn, emailField->text, passwordField->text); t.detach(); passwordField->text = ""; @@ -63,7 +63,7 @@ PluginManagerWidget::PluginManagerWidget() { pos.x += logInButton->box.size.x; struct StatusLabel : Label { - void step() { + void step() override { text = pluginGetLoginStatus(); } }; @@ -79,7 +79,7 @@ PluginManagerWidget::PluginManagerWidget() { Vec pos = Vec(0, 0); struct ManageButton : Button { - void onAction() { + void onAction() override { std::thread t(openBrowser, "https://vcvrack.com/"); t.detach(); } @@ -92,7 +92,7 @@ PluginManagerWidget::PluginManagerWidget() { pos.x += manageButton->box.size.x; struct RefreshButton : Button { - void onAction() { + void onAction() override { std::thread t(pluginRefresh); t.detach(); } @@ -106,7 +106,7 @@ PluginManagerWidget::PluginManagerWidget() { pos.x += refreshButton->box.size.x; struct LogOutButton : Button { - void onAction() { + void onAction() override { pluginLogOut(); } }; @@ -125,7 +125,7 @@ PluginManagerWidget::PluginManagerWidget() { Vec pos = Vec(0, 0); struct DownloadProgressBar : ProgressBar { - void step() { + void step() override { label = "Downloading"; std::string name = pluginGetDownloadName(); if (name != "") @@ -142,7 +142,7 @@ PluginManagerWidget::PluginManagerWidget() { pos.x += downloadProgress->box.size.x; // struct CancelButton : Button { - // void onAction() { + // void onAction() override { // pluginCancelDownload(); // } // }; diff --git a/src/app/RackScene.cpp b/src/app/RackScene.cpp index b02b5caa..a4c8bd81 100644 --- a/src/app/RackScene.cpp +++ b/src/app/RackScene.cpp @@ -86,7 +86,7 @@ Widget *RackScene::onHoverKey(Vec pos, int key) { switch (key) { case GLFW_KEY_N: if (guiIsModPressed() && !guiIsShiftPressed()) { - gRackWidget->clear(); + gRackWidget->reset(); return this; } break; diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index 0f01a597..74143770 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -38,6 +38,11 @@ void RackWidget::clear() { lastPath = ""; } +void RackWidget::reset() { + clear(); + loadPatch(assetLocal("template.vcv")); +} + void RackWidget::openDialog() { std::string dir = lastPath.empty() ? assetLocal("") : extractDirectory(lastPath); char *path = osdialog_file(OSDIALOG_OPEN, dir.c_str(), NULL, NULL); @@ -364,7 +369,7 @@ void RackWidget::draw(NVGcontext *vg) { struct AddModuleMenuItem : MenuItem { Model *model; Vec modulePos; - void onAction() { + void onAction() override { ModuleWidget *moduleWidget = model->createModuleWidget(); gRackWidget->moduleContainer->addChild(moduleWidget); // Move module nearest to the mouse position @@ -377,7 +382,7 @@ struct AddModuleMenuItem : MenuItem { struct UrlItem : MenuItem { std::string url; - void onAction() { + void onAction() override { std::thread t(openBrowser, url); t.detach(); } @@ -386,7 +391,7 @@ struct UrlItem : MenuItem { struct AddPluginMenuItem : MenuItem { Plugin *plugin; Vec modulePos; - Menu *createChildMenu() { + Menu *createChildMenu() override { // Model items Menu *menu = new Menu(); for (Model *model : plugin->models) { diff --git a/src/app/SVGPanel.cpp b/src/app/SVGPanel.cpp index a0419c4a..815a89fb 100644 --- a/src/app/SVGPanel.cpp +++ b/src/app/SVGPanel.cpp @@ -5,7 +5,7 @@ namespace rack { struct PanelBorder : TransparentWidget { - void draw(NVGcontext *vg) { + void draw(NVGcontext *vg) override { NVGcolor borderColor = nvgRGBAf(0.5, 0.5, 0.5, 0.5); nvgBeginPath(vg); nvgRect(vg, 0.5, 0.5, box.size.x - 1.0, box.size.y - 1.0); diff --git a/src/app/Toolbar.cpp b/src/app/Toolbar.cpp index 1c8b5cfe..d0def913 100644 --- a/src/app/Toolbar.cpp +++ b/src/app/Toolbar.cpp @@ -7,76 +7,68 @@ namespace rack { struct NewItem : MenuItem { - void onAction() { - gRackWidget->clear(); + void onAction() override { + gRackWidget->reset(); } }; struct OpenItem : MenuItem { - void onAction() { + void onAction() override { gRackWidget->openDialog(); } }; struct SaveItem : MenuItem { - void onAction() { + void onAction() override { gRackWidget->saveDialog(); } }; struct SaveAsItem : MenuItem { - void onAction() { + void onAction() override { gRackWidget->saveAsDialog(); } }; +struct QuitItem : MenuItem { + void onAction() override { + guiClose(); + } +}; + struct FileChoice : ChoiceButton { - void onAction() { + void onAction() override { Menu *menu = gScene->createMenu(); menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); menu->box.size.x = box.size.x; { - MenuItem *newItem = new NewItem(); - newItem->text = "New"; - newItem->rightText = GUI_MOD_KEY_NAME "+N"; - menu->pushChild(newItem); - - MenuItem *openItem = new OpenItem(); - openItem->text = "Open"; - openItem->rightText = GUI_MOD_KEY_NAME "+O"; - menu->pushChild(openItem); - - MenuItem *saveItem = new SaveItem(); - saveItem->text = "Save"; - saveItem->rightText = GUI_MOD_KEY_NAME "+S"; - menu->pushChild(saveItem); - - MenuItem *saveAsItem = new SaveAsItem(); - saveAsItem->text = "Save as"; - saveAsItem->rightText = GUI_MOD_KEY_NAME "+Shift+S"; - menu->pushChild(saveAsItem); + menu->pushChild(construct(&MenuItem::text, "New", &MenuItem::rightText, GUI_MOD_KEY_NAME "+N")); + menu->pushChild(construct(&MenuItem::text, "Open", &MenuItem::rightText, GUI_MOD_KEY_NAME "+O")); + menu->pushChild(construct(&MenuItem::text, "Save", &MenuItem::rightText, GUI_MOD_KEY_NAME "+S")); + menu->pushChild(construct(&MenuItem::text, "Save as", &MenuItem::rightText, GUI_MOD_KEY_NAME "+Shift+S")); + menu->pushChild(construct(&MenuItem::text, "Quit", &MenuItem::rightText, GUI_MOD_KEY_NAME "+Q")); } } }; struct PauseItem : MenuItem { - void onAction() { + void onAction() override { gPaused = !gPaused; } }; struct SampleRateItem : MenuItem { float sampleRate; - void onAction() { + void onAction() override { engineSetSampleRate(sampleRate); gPaused = false; } }; struct SampleRateChoice : ChoiceButton { - void onAction() { + void onAction() override { Menu *menu = gScene->createMenu(); menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); menu->box.size.x = box.size.x; @@ -94,11 +86,11 @@ struct SampleRateChoice : ChoiceButton { menu->pushChild(item); } } - void step() { + void step() override { if (gPaused) text = "Paused"; else - text = stringf("%.0f Hz", gSampleRate); + text = stringf("%.0f Hz", engineGetSampleRate()); } }; diff --git a/src/core/AudioInterface.cpp b/src/core/AudioInterface.cpp index b27aef41..69a28caa 100644 --- a/src/core/AudioInterface.cpp +++ b/src/core/AudioInterface.cpp @@ -65,7 +65,7 @@ struct AudioInterface : Module { closeDevice(); } - void step(); + void step() override; void stepStream(const float *input, float *output, int numFrames); int getDeviceCount(); @@ -84,7 +84,7 @@ struct AudioInterface : Module { openDevice(deviceId, sampleRate, blockSize); } - json_t *toJson() { + json_t *toJson() override { json_t *rootJ = json_object(); if (deviceId >= 0) { std::string deviceName = getDeviceName(deviceId); @@ -95,7 +95,7 @@ struct AudioInterface : Module { return rootJ; } - void fromJson(json_t *rootJ) { + void fromJson(json_t *rootJ) override { json_t *deviceNameJ = json_object_get(rootJ, "deviceName"); if (deviceNameJ) { std::string deviceName = json_string_value(deviceNameJ); @@ -118,7 +118,7 @@ struct AudioInterface : Module { } } - void initialize() { + void reset() override { closeDevice(); } }; @@ -155,7 +155,7 @@ void AudioInterface::step() { // Once full, sample rate convert the input // inputBuffer -> SRC -> inputSrcBuffer if (inputBuffer.full()) { - inputSrc.setRatio(sampleRate / gSampleRate); + inputSrc.setRatio(sampleRate / engineGetSampleRate()); int inLen = inputBuffer.size(); int outLen = inputSrcBuffer.capacity(); inputSrc.process(inputBuffer.startData(), &inLen, inputSrcBuffer.endData(), &outLen); @@ -194,7 +194,7 @@ void AudioInterface::stepStream(const float *input, float *output, int numFrames } // Pass output through sample rate converter - outputSrc.setRatio(gSampleRate / sampleRate); + outputSrc.setRatio(engineGetSampleRate() / sampleRate); int inLen = numFrames; int outLen = outputBuffer.capacity(); outputSrc.process(inputFrames, &inLen, outputBuffer.endData(), &outLen); @@ -326,14 +326,14 @@ void AudioInterface::closeDevice() { struct AudioItem : MenuItem { AudioInterface *audioInterface; int deviceId; - void onAction() { + void onAction() override { audioInterface->setDeviceId(deviceId); } }; struct AudioChoice : ChoiceButton { AudioInterface *audioInterface; - void onAction() { + void onAction() override { Menu *menu = gScene->createMenu(); menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); menu->box.size.x = box.size.x; @@ -354,7 +354,7 @@ struct AudioChoice : ChoiceButton { menu->pushChild(audioItem); } } - void step() { + void step() override { std::string name = audioInterface->getDeviceName(audioInterface->deviceId); text = ellipsize(name, 24); } @@ -364,14 +364,14 @@ struct AudioChoice : ChoiceButton { struct SampleRateItem : MenuItem { AudioInterface *audioInterface; float sampleRate; - void onAction() { + void onAction() override { audioInterface->setSampleRate(sampleRate); } }; struct SampleRateChoice : ChoiceButton { AudioInterface *audioInterface; - void onAction() { + void onAction() override { Menu *menu = gScene->createMenu(); menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); menu->box.size.x = box.size.x; @@ -386,7 +386,7 @@ struct SampleRateChoice : ChoiceButton { menu->pushChild(item); } } - void step() { + void step() override { this->text = stringf("%.0f Hz", audioInterface->sampleRate); } }; @@ -395,14 +395,14 @@ struct SampleRateChoice : ChoiceButton { struct BlockSizeItem : MenuItem { AudioInterface *audioInterface; int blockSize; - void onAction() { + void onAction() override { audioInterface->setBlockSize(blockSize); } }; struct BlockSizeChoice : ChoiceButton { AudioInterface *audioInterface; - void onAction() { + void onAction() override { Menu *menu = gScene->createMenu(); menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); menu->box.size.x = box.size.x; @@ -417,7 +417,7 @@ struct BlockSizeChoice : ChoiceButton { menu->pushChild(item); } } - void step() { + void step() override { this->text = stringf("%d", audioInterface->blockSize); } }; diff --git a/src/core/Blank.cpp b/src/core/Blank.cpp index 80a5fb7b..ca1db935 100644 --- a/src/core/Blank.cpp +++ b/src/core/Blank.cpp @@ -10,17 +10,17 @@ struct ModuleResizeHandle : Widget { ModuleResizeHandle() { box.size = Vec(RACK_GRID_WIDTH * 1, RACK_GRID_HEIGHT); } - Widget *onMouseDown(Vec pos, int button) { + Widget *onMouseDown(Vec pos, int button) override { if (button == 0) return this; return NULL; } - void onDragStart() { + void onDragStart() override { assert(parent); originalWidth = parent->box.size.x; totalX = 0.0; } - void onDragMove(Vec mouseRel) { + void onDragMove(Vec mouseRel) override { ModuleWidget *m = dynamic_cast(parent); assert(m); totalX += mouseRel.x; @@ -38,7 +38,7 @@ struct ModuleResizeHandle : Widget { } gRackWidget->requestModuleBox(m, newBox); } - void draw(NVGcontext *vg) { + void draw(NVGcontext *vg) override { for (float x = 5.0; x <= 10.0; x += 5.0) { nvgBeginPath(vg); const float margin = 5.0; diff --git a/src/core/Bridge.cpp b/src/core/Bridge.cpp index b5f6edb9..bb7ade53 100644 --- a/src/core/Bridge.cpp +++ b/src/core/Bridge.cpp @@ -18,7 +18,7 @@ struct Bridge : Module { } ~Bridge() { } - void step(); + void step() override; }; diff --git a/src/core/MidiInterface.cpp b/src/core/MidiIO.cpp similarity index 100% rename from src/core/MidiInterface.cpp rename to src/core/MidiIO.cpp diff --git a/src/core/MidiInterface.hpp b/src/core/MidiIO.hpp similarity index 100% rename from src/core/MidiInterface.hpp rename to src/core/MidiIO.hpp diff --git a/src/core/core.hpp b/src/core/core.hpp index 968576bb..661cd87b 100644 --- a/src/core/core.hpp +++ b/src/core/core.hpp @@ -22,7 +22,7 @@ struct BlankWidget : ModuleWidget { Widget *bottomRightScrew; Widget *rightHandle; BlankWidget(); - void step(); - json_t *toJson(); - void fromJson(json_t *rootJ); + void step() override; + json_t *toJson() override; + void fromJson(json_t *rootJ) override; }; diff --git a/src/engine.cpp b/src/engine.cpp index df7f77d0..4ce7ec17 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -14,7 +14,7 @@ namespace rack { -float gSampleRate; +float sampleRate; bool gPaused = false; @@ -60,7 +60,7 @@ static void engineStep() { smoothModule = NULL; } else { - value += delta * lambda / gSampleRate; + value += delta * lambda / sampleRate; smoothModule->params[smoothParamId].value = value; } } @@ -97,7 +97,7 @@ static void engineRun() { } } - float stepTime = mutexSteps / gSampleRate; + float stepTime = mutexSteps / sampleRate; ahead += stepTime; auto currTime = std::chrono::high_resolution_clock::now(); const float aheadFactor = 2.0; @@ -221,12 +221,16 @@ void engineSetParamSmooth(Module *module, int paramId, float value) { void engineSetSampleRate(float newSampleRate) { VIPLock vipLock(vipMutex); std::lock_guard lock(mutex); - gSampleRate = newSampleRate; + sampleRate = newSampleRate; // onSampleRateChange for (Module *module : modules) { module->onSampleRateChange(); } } +float engineGetSampleRate() { + return sampleRate; +} + } // namespace rack diff --git a/src/settings.cpp b/src/settings.cpp index 86e622b8..8f449489 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -32,8 +32,7 @@ static json_t *settingsToJson() { json_object_set_new(rootJ, "allowCursorLock", allowCursorLockJ); // sampleRate - float sampleRate = gSampleRate; - json_t *sampleRateJ = json_real(sampleRate); + json_t *sampleRateJ = json_real(engineGetSampleRate()); json_object_set_new(rootJ, "sampleRate", sampleRateJ); // plugLight