Browse Source

Modify ports to support Component Library

tags/v0.3.0
Andrew Belt 7 years ago
parent
commit
4c891085fe
12 changed files with 170 additions and 123 deletions
  1. +3
    -0
      .gitmodules
  2. +1
    -0
      ext/nanosvg
  3. +4
    -4
      include/rack.hpp
  4. +37
    -6
      include/rackwidgets.hpp
  5. +38
    -29
      src/core/AudioInterface.cpp
  6. +10
    -7
      src/core/MidiInterface.cpp
  7. +0
    -2
      src/core/core.hpp
  8. +0
    -7
      src/widgets/InputPort.cpp
  9. +2
    -6
      src/widgets/ModulePanel.cpp
  10. +0
    -7
      src/widgets/OutputPort.cpp
  11. +0
    -16
      src/widgets/Port.cpp
  12. +75
    -39
      src/widgets/WireWidget.cpp

+ 3
- 0
.gitmodules View File

@@ -1,3 +1,6 @@
[submodule "ext/nanovg"]
path = ext/nanovg
url = https://github.com/memononen/nanovg.git
[submodule "ext/nanosvg"]
path = ext/nanosvg
url = https://github.com/memononen/nanosvg.git

+ 1
- 0
ext/nanosvg

@@ -0,0 +1 @@
Subproject commit dc12d90586a8ab99da0c575aafff999666aa5d55

+ 4
- 4
include/rack.hpp View File

@@ -166,18 +166,18 @@ ParamWidget *createParam(Vec pos, Module *module, int paramId, float minValue, f
return param;
}

inline
template <class TInputPort>
InputPort *createInput(Vec pos, Module *module, int inputId) {
InputPort *port = new InputPort();
InputPort *port = new TInputPort();
port->box.pos = pos;
port->module = module;
port->inputId = inputId;
return port;
}

inline
template <class TOutputPort>
OutputPort *createOutput(Vec pos, Module *module, int outputId) {
OutputPort *port = new OutputPort();
OutputPort *port = new TOutputPort();
port->box.pos = pos;
port->module = module;
port->outputId = outputId;


+ 37
- 6
include/rackwidgets.hpp View File

@@ -94,7 +94,6 @@ struct RackWidget : OpaqueWidget {

struct ModulePanel : TransparentWidget {
NVGcolor backgroundColor;
NVGcolor highlightColor;
std::string imageFilename;
void draw(NVGcontext *vg);
};
@@ -167,7 +166,7 @@ struct MomentarySwitch : virtual Switch {
// ports
////////////////////

struct Port : OpaqueWidget, SpriteWidget {
struct Port : OpaqueWidget {
Module *module = NULL;
WireWidget *connectedWire = NULL;

@@ -175,8 +174,6 @@ struct Port : OpaqueWidget, SpriteWidget {
~Port();
void disconnect();

int type;
void drawGlow(NVGcontext *vg);
void onMouseDown(int button);
void onDragEnd();
};
@@ -184,7 +181,6 @@ struct Port : OpaqueWidget, SpriteWidget {
struct InputPort : Port {
int inputId;

void draw(NVGcontext *vg);
void onDragStart();
void onDragDrop(Widget *origin);
};
@@ -192,7 +188,6 @@ struct InputPort : Port {
struct OutputPort : Port {
int outputId;

void draw(NVGcontext *vg);
void onDragStart();
void onDragDrop(Widget *origin);
};
@@ -220,5 +215,41 @@ struct Scene : OpaqueWidget {
void step();
};

////////////////////
// component library
////////////////////

struct PJ301M : SpriteWidget {
PJ301M() {
box.size = Vec(24, 24);
spriteOffset = Vec(-10, -10);
spriteSize = Vec(48, 48);
spriteFilename = "res/ComponentLibrary/PJ301M.png";
}
};
struct InputPortPJ301M : InputPort, PJ301M {};
struct OutputPortPJ301M: OutputPort, PJ301M {};

struct PJ3410 : SpriteWidget {
PJ3410() {
box.size = Vec(31, 31);
spriteOffset = Vec(-9, -9);
spriteSize = Vec(54, 54);
spriteFilename = "res/ComponentLibrary/PJ3410.png";
}
};
struct InputPortPJ3410 : InputPort, PJ3410 {};
struct OutputPortPJ3410: OutputPort, PJ3410 {};

struct CL1362 : SpriteWidget {
CL1362() {
box.size = Vec(33, 29);
spriteOffset = Vec(-10, -10);
spriteSize = Vec(57, 54);
spriteFilename = "res/ComponentLibrary/CL1362.png";
}
};
struct InputPortCL1362 : InputPort, CL1362 {};
struct OutputPortCL1362 : OutputPort, CL1362 {};

} // namespace rack

+ 38
- 29
src/core/AudioInterface.cpp View File

@@ -45,10 +45,11 @@ struct AudioInterface : Module {
SampleRateConverter<2> inputSrc;
SampleRateConverter<2> outputSrc;

// in device's sample rate
DoubleRingBuffer<Frame<2>, (1<<15)> inputBuffer;
// in rack's sample rate
DoubleRingBuffer<Frame<2>, 32> inputBuffer;
DoubleRingBuffer<Frame<2>, (1<<15)> outputBuffer;
// in device's sample rate
DoubleRingBuffer<Frame<2>, (1<<15)> inputSrcBuffer;

AudioInterface();
~AudioInterface();
@@ -89,29 +90,35 @@ void AudioInterface::step() {

// Get input and pass it through the sample rate converter
if (numOutputs > 0) {
Frame<2> f;
f.samples[0] = getf(inputs[AUDIO1_INPUT]) / 5.0;
f.samples[1] = getf(inputs[AUDIO2_INPUT]) / 5.0;

inputSrc.setRatio(sampleRate / gRack->sampleRate);
int inLen = 1;
int outLen = inputBuffer.capacity();
inputSrc.process((const float*) &f, &inLen, (float*) inputBuffer.endData(), &outLen);
inputBuffer.endIncr(outLen);
if (!inputBuffer.full()) {
Frame<2> f;
f.samples[0] = getf(inputs[AUDIO1_INPUT]) / 5.0;
f.samples[1] = getf(inputs[AUDIO2_INPUT]) / 5.0;
inputBuffer.push(f);
}

// Once full, sample rate convert the input
if (inputBuffer.full()) {
inputSrc.setRatio(sampleRate / gRack->sampleRate);
int inLen = inputBuffer.size();
int outLen = inputSrcBuffer.capacity();
inputSrc.process((const float*) inputBuffer.startData(), &inLen, (float*) inputSrcBuffer.endData(), &outLen);
inputBuffer.startIncr(inLen);
inputSrcBuffer.endIncr(outLen);
}
}

// Read/write stream if we have enough input
bool streamReady = (numOutputs > 0) ? (inputBuffer.size() >= blockSize) : (outputBuffer.empty());
// Read/write stream if we have enough input, OR the output buffer is empty if we have no input
bool streamReady = (numOutputs > 0) ? (inputSrcBuffer.size() >= blockSize) : (outputBuffer.empty());
if (streamReady) {
// printf("%p\t%d\t%d\n", this, inputSrcBuffer.size(), outputBuffer.size());
PaError err;

// Read output from input stream
// (for some reason, if you write the output stream before you read the input stream, PortAudio can segfault on Windows.)
if (numInputs > 0) {
Frame<2> *buf = new Frame<2>[blockSize];
printf("read %d\n", blockSize);
err = Pa_ReadStream(stream, (float*) buf, blockSize);
printf("read done\n");
if (err) {
// Ignore buffer underflows
if (err != paInputOverflowed) {
@@ -131,11 +138,9 @@ void AudioInterface::step() {

// Write input to output stream
if (numOutputs > 0) {
assert(inputBuffer.size() >= blockSize);
printf("write %d\n", blockSize);
err = Pa_WriteStream(stream, (const float*) inputBuffer.startData(), blockSize);
printf("write done\n");
inputBuffer.startIncr(blockSize);
assert(inputSrcBuffer.size() >= blockSize);
err = Pa_WriteStream(stream, (const float*) inputSrcBuffer.startData(), blockSize);
inputSrcBuffer.startIncr(blockSize);
if (err) {
// Ignore buffer underflows
if (err != paOutputUnderflowed) {
@@ -241,6 +246,7 @@ void AudioInterface::closeDevice() {
// Clear buffers
inputBuffer.clear();
outputBuffer.clear();
inputSrcBuffer.clear();
inputSrc.reset();
outputSrc.reset();
}
@@ -355,6 +361,14 @@ struct BlockSizeChoice : ChoiceButton {
AudioInterfaceWidget::AudioInterfaceWidget() : ModuleWidget(new AudioInterface()) {
box.size = Vec(15*8, 380);

{
ModulePanel *panel = new ModulePanel();
panel->box.size = box.size;
panel->backgroundColor = nvgRGBf(0.90, 0.90, 0.90);
// panel->imageFilename = "";
addChild(panel);
}

float margin = 5;
float yPos = margin;

@@ -420,8 +434,8 @@ AudioInterfaceWidget::AudioInterfaceWidget() : ModuleWidget(new AudioInterface()
}

yPos += 5;
addInput(createInput(Vec(25, yPos), module, AudioInterface::AUDIO1_INPUT));
addInput(createInput(Vec(75, yPos), module, AudioInterface::AUDIO2_INPUT));
addInput(createInput<InputPortPJ3410>(Vec(20, yPos), module, AudioInterface::AUDIO1_INPUT));
addInput(createInput<InputPortPJ3410>(Vec(70, yPos), module, AudioInterface::AUDIO2_INPUT));
yPos += 35 + margin;

{
@@ -433,12 +447,7 @@ AudioInterfaceWidget::AudioInterfaceWidget() : ModuleWidget(new AudioInterface()
}

yPos += 5;
addOutput(createOutput(Vec(25, yPos), module, AudioInterface::AUDIO1_OUTPUT));
addOutput(createOutput(Vec(75, yPos), module, AudioInterface::AUDIO2_OUTPUT));
addOutput(createOutput<OutputPortPJ3410>(Vec(20, yPos), module, AudioInterface::AUDIO1_OUTPUT));
addOutput(createOutput<OutputPortPJ3410>(Vec(70, yPos), module, AudioInterface::AUDIO2_OUTPUT));
yPos += 35 + margin;
}

void AudioInterfaceWidget::draw(NVGcontext *vg) {
bndBackground(vg, box.pos.x, box.pos.y, box.size.x, box.size.y);
ModuleWidget::draw(vg);
}

+ 10
- 7
src/core/MidiInterface.cpp View File

@@ -224,6 +224,14 @@ struct MidiChoice : ChoiceButton {
MidiInterfaceWidget::MidiInterfaceWidget() : ModuleWidget(new MidiInterface()) {
box.size = Vec(15*8, 380);

{
ModulePanel *panel = new ModulePanel();
panel->box.size = box.size;
panel->backgroundColor = nvgRGBf(0.90, 0.90, 0.90);
// panel->imageFilename = "";
addChild(panel);
}

float margin = 5;
float yPos = margin;

@@ -246,8 +254,8 @@ MidiInterfaceWidget::MidiInterfaceWidget() : ModuleWidget(new MidiInterface()) {
}

yPos += 5;
addOutput(createOutput(Vec(25, yPos), module, MidiInterface::PITCH_OUTPUT));
addOutput(createOutput(Vec(75, yPos), module, MidiInterface::GATE_OUTPUT));
addOutput(createOutput<OutputPortPJ3410>(Vec(20, yPos), module, MidiInterface::PITCH_OUTPUT));
addOutput(createOutput<OutputPortPJ3410>(Vec(70, yPos), module, MidiInterface::GATE_OUTPUT));
yPos += 25 + margin;

{
@@ -264,8 +272,3 @@ MidiInterfaceWidget::MidiInterfaceWidget() : ModuleWidget(new MidiInterface()) {
yPos += pitchLabel->box.size.y + margin;
}
}

void MidiInterfaceWidget::draw(NVGcontext *vg) {
bndBackground(vg, box.pos.x, box.pos.y, box.size.x, box.size.y);
ModuleWidget::draw(vg);
}

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

@@ -14,10 +14,8 @@ void midiInit();

struct AudioInterfaceWidget : ModuleWidget {
AudioInterfaceWidget();
void draw(NVGcontext *vg);
};

struct MidiInterfaceWidget : ModuleWidget {
MidiInterfaceWidget();
void draw(NVGcontext *vg);
};

+ 0
- 7
src/widgets/InputPort.cpp View File

@@ -3,13 +3,6 @@

namespace rack {

void InputPort::draw(NVGcontext *vg) {
SpriteWidget::draw(vg);
if (gRackWidget->activeWire && gRackWidget->activeWire->inputPort) {
Port::drawGlow(vg);
}
}

void InputPort::onDragStart() {
if (connectedWire) {
// Disconnect wire from this port, but set it as the active wire


+ 2
- 6
src/widgets/ModulePanel.cpp View File

@@ -8,12 +8,8 @@ void ModulePanel::draw(NVGcontext *vg) {
nvgRect(vg, box.pos.x, box.pos.y, box.size.x, box.size.y);
NVGpaint paint;

// Background gradient
Vec c = box.pos;
float length = box.size.norm();
paint = nvgRadialGradient(vg, c.x, c.y, 0.0, length, highlightColor, backgroundColor);
nvgFillPaint(vg, paint);
// nvgFillColor(vg, backgroundColor);
// Background color
nvgFillColor(vg, backgroundColor);
nvgFill(vg);

// Background image


+ 0
- 7
src/widgets/OutputPort.cpp View File

@@ -3,13 +3,6 @@

namespace rack {

void OutputPort::draw(NVGcontext *vg) {
SpriteWidget::draw(vg);
if (gRackWidget->activeWire && gRackWidget->activeWire->outputPort) {
Port::drawGlow(vg);
}
}

void OutputPort::onDragStart() {
if (connectedWire) {
// Disconnect wire from this port, but set it as the active wire


+ 0
- 16
src/widgets/Port.cpp View File

@@ -5,11 +5,6 @@ namespace rack {

Port::Port() {
box.size = Vec(20, 20);
spriteOffset = Vec(-18, -18);
spriteSize = Vec(56, 56);
spriteFilename = "res/port.png";

index = randomu32() % 5;
}

Port::~Port() {
@@ -24,17 +19,6 @@ void Port::disconnect() {
}
}

void Port::drawGlow(NVGcontext *vg) {
Vec c = box.getCenter();
NVGcolor icol = nvgRGBAf(1, 1, 1, 0.5);
NVGcolor ocol = nvgRGBAf(1, 1, 1, 0);
NVGpaint paint = nvgRadialGradient(vg, c.x, c.y, 0, 20, icol, ocol);
nvgFillPaint(vg, paint);
nvgBeginPath(vg);
nvgRect(vg, box.pos.x - 10, box.pos.y - 10, box.size.x + 20, box.size.y + 20);
nvgFill(vg);
}

void Port::onMouseDown(int button) {
if (button == 1) {
disconnect();


+ 75
- 39
src/widgets/WireWidget.cpp View File

@@ -3,37 +3,79 @@

namespace rack {

void drawWire(NVGcontext *vg, Vec pos1, Vec pos2, float tension, NVGcolor color) {
float dist = pos1.minus(pos2).norm();
Vec slump;
slump.y = (1.0 - tension) * (150.0 + 1.0*dist);
Vec pos3 = pos1.plus(pos2).div(2).plus(slump);
void drawWire(NVGcontext *vg, Vec pos1, Vec pos2, float tension, NVGcolor color, float opacity) {
NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.08);
NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5);


// Wire
if (opacity > 0.0) {
nvgSave(vg);
nvgGlobalAlpha(vg, opacity);

float dist = pos1.minus(pos2).norm();
Vec slump;
slump.y = (1.0 - tension) * (150.0 + 1.0*dist);
Vec pos3 = pos1.plus(pos2).div(2).plus(slump);

nvgLineJoin(vg, NVG_ROUND);

// Shadow
Vec pos4 = pos3.plus(slump.mult(0.08));
nvgBeginPath(vg);
nvgMoveTo(vg, pos1.x, pos1.y);
nvgQuadTo(vg, pos4.x, pos4.y, pos2.x, pos2.y);
nvgStrokeColor(vg, colorShadow);
nvgStrokeWidth(vg, 5);
nvgStroke(vg);

// Wire outline
nvgBeginPath(vg);
nvgMoveTo(vg, pos1.x, pos1.y);
nvgQuadTo(vg, pos3.x, pos3.y, pos2.x, pos2.y);
nvgStrokeColor(vg, colorOutline);
nvgStrokeWidth(vg, 6);
nvgStroke(vg);

// Wire solid
nvgStrokeColor(vg, color);
nvgStrokeWidth(vg, 4);
nvgStroke(vg);

nvgRestore(vg);
}

// First plug
nvgBeginPath(vg);
nvgCircle(vg, pos1.x, pos1.y, 21/2.0);
nvgFillColor(vg, colorOutline);
nvgFill(vg);

nvgLineJoin(vg, NVG_ROUND);
nvgBeginPath(vg);
nvgCircle(vg, pos1.x, pos1.y, 19/2.0);
nvgFillColor(vg, color);
nvgFill(vg);

// Shadow
Vec pos4 = pos3.plus(slump.mult(0.08));
NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.08);
nvgBeginPath(vg);
nvgMoveTo(vg, pos1.x, pos1.y);
nvgQuadTo(vg, pos4.x, pos4.y, pos2.x, pos2.y);
nvgStrokeColor(vg, colorShadow);
nvgStrokeWidth(vg, 5);
nvgStroke(vg);

// Wire outline
NVGcolor colorOutline = nvgRGBf(0, 0, 0);
nvgCircle(vg, pos1.x, pos1.y, 11/2.0);
nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0));
nvgFill(vg);

// Second plug
nvgBeginPath(vg);
nvgCircle(vg, pos2.x, pos2.y, 21/2.0);
nvgFillColor(vg, colorOutline);
nvgFill(vg);

nvgBeginPath(vg);
nvgMoveTo(vg, pos1.x, pos1.y);
nvgQuadTo(vg, pos3.x, pos3.y, pos2.x, pos2.y);
nvgStrokeColor(vg, colorOutline);
nvgStrokeWidth(vg, 4);
nvgStroke(vg);

// Wire solid
nvgStrokeColor(vg, color);
nvgStrokeWidth(vg, 2);
nvgStroke(vg);
nvgCircle(vg, pos2.x, pos2.y, 19/2.0);
nvgFillColor(vg, color);
nvgFill(vg);

nvgBeginPath(vg);
nvgCircle(vg, pos2.x, pos2.y, 11/2.0);
nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0));
nvgFill(vg);
}


@@ -87,35 +129,29 @@ void WireWidget::updateWire() {
void WireWidget::draw(NVGcontext *vg) {
Vec outputPos, inputPos;
Vec absolutePos = getAbsolutePos();
float wireOpacity = gScene->toolbar->wireOpacitySlider->value / 100.0;
float opacity = gScene->toolbar->wireOpacitySlider->value / 100.0;

// Compute location of pos1 and pos2
if (outputPort) {
outputPos = Rect(outputPort->getAbsolutePos(), outputPort->box.size).getCenter();
}
else {
outputPos = gMousePos;
wireOpacity = 1.0;
opacity = 1.0;
}
if (inputPort) {
inputPos = Rect(inputPort->getAbsolutePos(), inputPort->box.size).getCenter();
}
else {
inputPos = gMousePos;
wireOpacity = 1.0;
opacity = 1.0;
}

outputPos = outputPos.minus(absolutePos);
inputPos = inputPos.minus(absolutePos);

bndNodePort(vg, outputPos.x, outputPos.y, BND_DEFAULT, color);
bndNodePort(vg, inputPos.x, inputPos.y, BND_DEFAULT, color);
nvgSave(vg);
if (wireOpacity > 0.0) {
nvgGlobalAlpha(vg, wireOpacity);
float tension = gScene->toolbar->wireTensionSlider->value;
drawWire(vg, outputPos, inputPos, tension, color);
}
nvgRestore(vg);
float tension = gScene->toolbar->wireTensionSlider->value;
drawWire(vg, outputPos, inputPos, tension, color, opacity);
}




Loading…
Cancel
Save