| @@ -38,7 +38,7 @@ LDFLAGS += \ | |||||
| -L$(HOME)/pkg/portaudio-r1891-build/lib/x64/ReleaseMinDependency -lportaudio_x64 \ | -L$(HOME)/pkg/portaudio-r1891-build/lib/x64/ReleaseMinDependency -lportaudio_x64 \ | ||||
| -Wl,--export-all-symbols,--out-implib,libRack.a -mwindows | -Wl,--export-all-symbols,--out-implib,libRack.a -mwindows | ||||
| TARGET = Rack.exe | TARGET = Rack.exe | ||||
| OBJECTS = Rack.res | |||||
| # OBJECTS = Rack.res | |||||
| %.res: %.rc | %.res: %.rc | ||||
| windres $^ -O coff -o $@ | windres $^ -O coff -o $@ | ||||
| @@ -4,6 +4,16 @@ | |||||
| namespace rack { | namespace rack { | ||||
| #define SCHEME_BLACK nvgRGB(0x00, 0x00, 0x00) | |||||
| #define SCHEME_WHITE nvgRGB(0xff, 0xff, 0xff) | |||||
| #define SCHEME_RED nvgRGB(0xed, 0x2c, 0x24) | |||||
| #define SCHEME_ORANGE nvgRGB(0xf2, 0xb1, 0x20) | |||||
| #define SCHEME_YELLOW nvgRGB(0xf9, 0xdf, 0x1c) | |||||
| #define SCHEME_GREEN nvgRGB(0x90, 0xc7, 0x3e) | |||||
| #define SCHEME_CYAN nvgRGB(0x22, 0xe6, 0xef) | |||||
| #define SCHEME_BLUE nvgRGB(0x29, 0xb2, 0xef) | |||||
| #define SCHEME_PURPLE nvgRGB(0xd5, 0x2b, 0xed) | |||||
| //////////////////// | //////////////////// | ||||
| // Knobs | // Knobs | ||||
| //////////////////// | //////////////////// | ||||
| @@ -113,6 +123,52 @@ struct CL1362 : BASE { | |||||
| typedef CL1362<InputPort> InputPortCL1362; | typedef CL1362<InputPort> InputPortCL1362; | ||||
| typedef CL1362<OutputPort> OutputPortCL1362; | typedef CL1362<OutputPort> OutputPortCL1362; | ||||
| //////////////////// | |||||
| // Lights | |||||
| //////////////////// | |||||
| struct ValueLight : Light { | |||||
| float *value; | |||||
| }; | |||||
| struct RedValueLight : ValueLight { | |||||
| void step() { | |||||
| float v = sqrtBipolar(getf(value)); | |||||
| color = nvgLerpRGBA(SCHEME_BLACK, SCHEME_RED, v); | |||||
| } | |||||
| }; | |||||
| struct GreenRedPolarityLight : ValueLight { | |||||
| void step() { | |||||
| float v = sqrtBipolar(getf(value)); | |||||
| if (v >= 0.0) | |||||
| color = nvgLerpRGBA(SCHEME_BLACK, SCHEME_GREEN, v); | |||||
| else | |||||
| color = nvgLerpRGBA(SCHEME_BLACK, SCHEME_RED, -v); | |||||
| } | |||||
| }; | |||||
| template <typename BASE> | |||||
| struct LargeLight : BASE { | |||||
| LargeLight() { | |||||
| this->box.size = Vec(20, 20); | |||||
| } | |||||
| }; | |||||
| template <typename BASE> | |||||
| struct MediumLight : BASE { | |||||
| MediumLight() { | |||||
| this->box.size = Vec(12, 12); | |||||
| } | |||||
| }; | |||||
| template <typename BASE> | |||||
| struct SmallLight : BASE { | |||||
| SmallLight() { | |||||
| this->box.size = Vec(8, 8); | |||||
| } | |||||
| }; | |||||
| //////////////////// | //////////////////// | ||||
| // Misc | // Misc | ||||
| //////////////////// | //////////////////// | ||||
| @@ -1,5 +1,6 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <vector> | #include <vector> | ||||
| #include "util.hpp" | |||||
| namespace rack { | namespace rack { | ||||
| @@ -45,14 +45,11 @@ inline float quadraticBipolar(float x) { | |||||
| } | } | ||||
| inline float cubic(float x) { | inline float cubic(float x) { | ||||
| // optimal with --fast-math | |||||
| return x*x*x; | return x*x*x; | ||||
| } | } | ||||
| inline float quarticBipolar(float x) { | inline float quarticBipolar(float x) { | ||||
| float x2 = x*x; | |||||
| float x4 = x2*x2; | |||||
| return x >= 0.0 ? x4 : -x4; | |||||
| return x >= 0.0 ? x*x*x*x : -x*x*x*x; | |||||
| } | } | ||||
| inline float quintic(float x) { | inline float quintic(float x) { | ||||
| @@ -60,6 +57,10 @@ inline float quintic(float x) { | |||||
| return x*x*x*x*x; | return x*x*x*x*x; | ||||
| } | } | ||||
| inline float sqrtBipolar(float x) { | |||||
| return x >= 0.0 ? sqrtf(x) : -sqrtf(-x); | |||||
| } | |||||
| inline float sincf(float x) { | inline float sincf(float x) { | ||||
| if (x == 0.0) | if (x == 0.0) | ||||
| return 1.0; | return 1.0; | ||||
| @@ -68,5 +68,13 @@ Screw *createScrew(Vec pos) { | |||||
| return screw; | return screw; | ||||
| } | } | ||||
| template <class TLight> | |||||
| ValueLight *createValueLight(Vec pos, float *value) { | |||||
| ValueLight *light = new TLight(); | |||||
| light->box.pos = pos; | |||||
| light->value = value; | |||||
| return light; | |||||
| } | |||||
| } // namespace rack | } // namespace rack | ||||
| @@ -24,16 +24,15 @@ struct Scene; | |||||
| struct Model; | struct Model; | ||||
| struct ModuleWidget : OpaqueWidget { | struct ModuleWidget : OpaqueWidget { | ||||
| Model *model = NULL; | Model *model = NULL; | ||||
| // Eventually this should be replaced with a `moduleId` which will be used for inter-process communication between the gui world and the audio world. | |||||
| /** Owns the module pointer */ | |||||
| Module *module = NULL; | Module *module = NULL; | ||||
| // int moduleId; | |||||
| std::vector<InputPort*> inputs; | std::vector<InputPort*> inputs; | ||||
| std::vector<OutputPort*> outputs; | std::vector<OutputPort*> outputs; | ||||
| std::vector<ParamWidget*> params; | std::vector<ParamWidget*> params; | ||||
| ModuleWidget(Module *module); | |||||
| ~ModuleWidget(); | ~ModuleWidget(); | ||||
| void setModule(Module *module); | |||||
| // Convenience functions for adding special widgets (calls addChild()) | // Convenience functions for adding special widgets (calls addChild()) | ||||
| void addInput(InputPort *input); | void addInput(InputPort *input); | ||||
| void addOutput(OutputPort *output); | void addOutput(OutputPort *output); | ||||
| @@ -1,7 +1,6 @@ | |||||
| #pragma once | #pragma once | ||||
| // Include most of the C standard library for convenience | // Include most of the C standard library for convenience | ||||
| // (C++ programmers will hate me) | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <stdint.h> | #include <stdint.h> | ||||
| @@ -256,7 +256,8 @@ void AudioInterface::closeDevice() { | |||||
| if (stream) { | if (stream) { | ||||
| PaError err; | PaError err; | ||||
| streamRunning = false; | streamRunning = false; | ||||
| err = Pa_StopStream(stream); | |||||
| err = Pa_AbortStream(stream); | |||||
| // err = Pa_StopStream(stream); | |||||
| if (err) { | if (err) { | ||||
| fprintf(stderr, "Failed to stop audio stream: %s\n", Pa_GetErrorText(err)); | fprintf(stderr, "Failed to stop audio stream: %s\n", Pa_GetErrorText(err)); | ||||
| } | } | ||||
| @@ -390,7 +391,9 @@ struct BlockSizeChoice : ChoiceButton { | |||||
| }; | }; | ||||
| AudioInterfaceWidget::AudioInterfaceWidget() : ModuleWidget(new AudioInterface()) { | |||||
| AudioInterfaceWidget::AudioInterfaceWidget() { | |||||
| AudioInterface *module = new AudioInterface(); | |||||
| setModule(module); | |||||
| box.size = Vec(15*8, 380); | box.size = Vec(15*8, 380); | ||||
| { | { | ||||
| @@ -221,7 +221,9 @@ struct MidiChoice : ChoiceButton { | |||||
| }; | }; | ||||
| MidiInterfaceWidget::MidiInterfaceWidget() : ModuleWidget(new MidiInterface()) { | |||||
| MidiInterfaceWidget::MidiInterfaceWidget() { | |||||
| MidiInterface *module = new MidiInterface(); | |||||
| setModule(module); | |||||
| box.size = Vec(15*8, 380); | box.size = Vec(15*8, 380); | ||||
| { | { | ||||
| @@ -180,12 +180,12 @@ void guiInit() { | |||||
| err = glfwInit(); | err = glfwInit(); | ||||
| assert(err); | assert(err); | ||||
| #ifndef WINDOWS | |||||
| // #ifndef WINDOWS | |||||
| glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | ||||
| glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); | ||||
| glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); | ||||
| glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | ||||
| #endif | |||||
| // #endif | |||||
| window = glfwCreateWindow(1000, 750, gApplicationName.c_str(), NULL, NULL); | window = glfwCreateWindow(1000, 750, gApplicationName.c_str(), NULL, NULL); | ||||
| assert(window); | assert(window); | ||||
| glfwMakeContextCurrent(window); | glfwMakeContextCurrent(window); | ||||
| @@ -4,7 +4,10 @@ | |||||
| #include <libgen.h> | #include <libgen.h> | ||||
| #endif | #endif | ||||
| #include "rack.hpp" | |||||
| #include "engine.hpp" | |||||
| #include "gui.hpp" | |||||
| #include "scene.hpp" | |||||
| #include "plugin.hpp" | |||||
| using namespace rack; | using namespace rack; | ||||
| @@ -6,10 +6,10 @@ namespace rack { | |||||
| void Light::draw(NVGcontext *vg) { | void Light::draw(NVGcontext *vg) { | ||||
| NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); | NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); | ||||
| Vec r = box.size.div(2.0); | |||||
| float radius = box.size.x / 2.0; | |||||
| nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
| nvgEllipse(vg, r.x, r.y, r.x - 1.0, r.y - 1.0); | |||||
| nvgCircle(vg, radius, radius, radius); | |||||
| nvgFillColor(vg, color); | nvgFillColor(vg, color); | ||||
| nvgFill(vg); | nvgFill(vg); | ||||
| @@ -17,18 +17,17 @@ void Light::draw(NVGcontext *vg) { | |||||
| nvgStrokeColor(vg, colorOutline); | nvgStrokeColor(vg, colorOutline); | ||||
| nvgStroke(vg); | nvgStroke(vg); | ||||
| // float radius = box.size.x / 2.0; | |||||
| // NVGcolor icol, ocol; | |||||
| // nvgGlobalCompositeOperation(vg, NVG_LIGHTER); | |||||
| // NVGpaint paint; | // NVGpaint paint; | ||||
| // icol = color; | |||||
| // icol.a = clampf(color.a / 10.0, 0.0, 1.0); | |||||
| // ocol = color; | |||||
| // NVGcolor icol = color; | |||||
| // icol.a = 0.2; | |||||
| // NVGcolor ocol = color; | |||||
| // ocol.a = 0.0; | // ocol.a = 0.0; | ||||
| // float oradius = radius + 20.0; | // float oradius = radius + 20.0; | ||||
| // paint = nvgRadialGradient(vg, c.x, c.y, radius, oradius, icol, ocol); | |||||
| // paint = nvgRadialGradient(vg, radius, radius, radius, oradius, icol, ocol); | |||||
| // nvgFillPaint(vg, paint); | // nvgFillPaint(vg, paint); | ||||
| // nvgBeginPath(vg); | // nvgBeginPath(vg); | ||||
| // nvgRect(vg, c.x - oradius, c.y - oradius, 2*oradius, 2*oradius); | |||||
| // nvgRect(vg, radius - oradius, radius - oradius, 2*oradius, 2*oradius); | |||||
| // nvgFill(vg); | // nvgFill(vg); | ||||
| } | } | ||||
| @@ -5,20 +5,21 @@ | |||||
| namespace rack { | namespace rack { | ||||
| ModuleWidget::ModuleWidget(Module *module) { | |||||
| this->module = module; | |||||
| if (module) { | |||||
| engineAddModule(module); | |||||
| } | |||||
| } | |||||
| ModuleWidget::~ModuleWidget() { | ModuleWidget::~ModuleWidget() { | ||||
| // Make sure WireWidget destructors are called *before* removing `module` from the rack. | // Make sure WireWidget destructors are called *before* removing `module` from the rack. | ||||
| disconnectPorts(); | disconnectPorts(); | ||||
| setModule(NULL); | |||||
| } | |||||
| void ModuleWidget::setModule(Module *module) { | |||||
| if (this->module) { | |||||
| engineRemoveModule(this->module); | |||||
| delete this->module; | |||||
| } | |||||
| if (module) { | if (module) { | ||||
| engineRemoveModule(module); | |||||
| delete module; | |||||
| engineAddModule(module); | |||||
| } | } | ||||
| this->module = module; | |||||
| } | } | ||||
| void ModuleWidget::addInput(InputPort *input) { | void ModuleWidget::addInput(InputPort *input) { | ||||