@@ -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) { | ||||