Browse Source

Remove Window::isModPressed() and isShiftPressed(). Add Window::getMods(). Add partial implementations of Core MIDI-CC and MIDI-Gate.

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
9ffb57edd0
19 changed files with 792 additions and 79 deletions
  1. +18
    -6
      include/window.hpp
  2. +249
    -0
      res/Core/CV-CC.svg
  3. +146
    -0
      res/Core/CV-Gate.svg
  4. +117
    -0
      src/Core/CV_CC.cpp
  5. +159
    -0
      src/Core/CV_Gate.cpp
  6. +15
    -5
      src/Core/CV_MIDI.cpp
  7. +11
    -1
      src/Core/Core.cpp
  8. +2
    -0
      src/Core/Core.hpp
  9. +1
    -1
      src/app/Knob.cpp
  10. +21
    -19
      src/app/ModuleWidget.cpp
  11. +2
    -2
      src/app/ParamWidget.cpp
  12. +4
    -1
      src/app/PortWidget.cpp
  13. +3
    -3
      src/app/RackWidget.cpp
  14. +9
    -9
      src/app/Scene.cpp
  15. +3
    -2
      src/app/Switch.cpp
  16. +5
    -5
      src/app/Toolbar.cpp
  17. +2
    -2
      src/rtmidi.cpp
  18. +8
    -8
      src/ui/TextField.cpp
  19. +17
    -15
      src/window.cpp

+ 18
- 6
include/window.hpp View File

@@ -10,14 +10,24 @@
#include <nanosvg.h>


/** Remaps Ctrl to Cmd on Mac
Use this instead of GLFW_MOD_CONTROL, since Cmd should be used on Mac in place of Ctrl on Linux/Windows.
*/
#ifdef ARCH_MAC
#define WINDOW_MOD GLFW_MOD_SUPER
#define WINDOW_MOD_KEY_NAME "Cmd"
#define WINDOW_MOD_CTRL GLFW_MOD_SUPER
#define WINDOW_MOD_CTRL_NAME "Cmd"
#else
#define WINDOW_MOD GLFW_MOD_CONTROL
#define WINDOW_MOD_KEY_NAME "Ctrl"
#define WINDOW_MOD_CTRL GLFW_MOD_CONTROL
#define WINDOW_MOD_CTRL_NAME "Ctrl"
#endif

/** Filters actual mod keys from the mod flags.
Use this if you don't care about GLFW_MOD_CAPS_LOCK and GLFW_MOD_NUM_LOCK.
Example usage:
if ((e.mod & WINDOW_MOD_MASK) == (WINDOW_MOD | GLFW_MOD_SHIFT)) ...
*/
#define WINDOW_MOD_MASK (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER)


namespace rack {

@@ -70,8 +80,10 @@ struct Window {
void close();
void cursorLock();
void cursorUnlock();
bool isModPressed();
bool isShiftPressed();
/** Gets the current keyboard mod state
Don't call this from a Key event. Simply use `e.mods` instead.
*/
int getMods();
math::Vec getWindowSize();
void setWindowSize(math::Vec size);
math::Vec getWindowPos();


+ 249
- 0
res/Core/CV-CC.svg View File

@@ -0,0 +1,249 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="50.799999mm"
height="128.50069mm"
viewBox="0 0 50.799999 128.50069"
version="1.1"
id="svg26618"
inkscape:version="0.92.2 2405546, 2018-03-11"
sodipodi:docname="CV-CC.svg">
<defs
id="defs26612" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="85.567542"
inkscape:cy="333.70852"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:snap-bbox="true"
inkscape:snap-nodes="false"
inkscape:snap-bbox-midpoints="true"
inkscape:bbox-nodes="true"
inkscape:window-width="1600"
inkscape:window-height="882"
inkscape:window-x="0"
inkscape:window-y="18"
inkscape:window-maximized="0" />
<metadata
id="metadata26615">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-362.22837,-118.49952)">
<path
inkscape:connector-curvature="0"
id="path9519"
d="m 362.32207,118.59323 h 50.61256 V 246.9065 h -50.61256 z m 0,0"
style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" />
<path
inkscape:connector-curvature="0"
id="path9521"
d="m 413.02837,118.49952 h -50.8 V 247.0002 h 50.8 z m -0.18743,128.31327 H 362.41439 V 118.68694 h 50.42655 z m 0,0"
style="fill:#ababab;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" />
<path
inkscape:connector-curvature="0"
id="path9555"
d="m 370.22785,195.95078 h 34.79962"
style="fill:none;stroke:#000000;stroke-width:0.35277775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path9557"
d="m 370.22785,207.55111 h 34.79962"
style="fill:none;stroke:#000000;stroke-width:0.35277775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path9559"
d="m 370.22785,219.15143 h 34.79962"
style="fill:none;stroke:#000000;stroke-width:0.35277775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path9561"
d="m 370.22785,230.75037 h 34.79962"
style="fill:none;stroke:#000000;stroke-width:0.35277775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path12881"
d="m 384.87504,242.85644 c -0.11715,0 -0.22323,-0.0661 -0.27562,-0.1695 l -1.00182,-2.00504 c -0.0772,-0.15296 -0.0152,-0.33762 0.13779,-0.41479 0.15159,-0.0758 0.33761,-0.0138 0.41342,0.13918 l 0.72623,1.45245 0.72623,-1.45245 c 0.0758,-0.15296 0.26183,-0.21497 0.41339,-0.13918 0.15296,0.0772 0.21498,0.26183 0.13783,0.41479 l -1.00186,2.00504 c -0.0523,0.10336 -0.15846,0.1695 -0.27559,0.1695"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" />
<path
inkscape:connector-curvature="0"
id="path12883"
d="m 390.38028,242.85644 c -0.11575,0 -0.22324,-0.0661 -0.27559,-0.1695 l -1.00182,-2.00504 c -0.0772,-0.15296 -0.0152,-0.33762 0.1378,-0.41479 0.15159,-0.0758 0.33761,-0.0138 0.41342,0.13918 l 0.72619,1.45245 0.72761,-1.45245 c 0.0758,-0.15296 0.26045,-0.21497 0.41341,-0.13918 0.1516,0.0772 0.21361,0.26183 0.1378,0.41479 l -1.00319,2.00504 c -0.051,0.10336 -0.15847,0.1695 -0.27563,0.1695"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" />
<path
inkscape:connector-curvature="0"
id="path12885"
d="m 387.77717,242.85644 c -0.72207,0 -1.3105,-0.58705 -1.3105,-1.31051 0,-0.72209 0.58843,-1.31052 1.3105,-1.31052 0.28663,0 0.55813,0.091 0.78687,0.26183 0.13642,0.10197 0.16401,0.29628 0.062,0.4327 -0.10336,0.13505 -0.2963,0.16261 -0.43272,0.0606 -0.11987,-0.091 -0.26458,-0.13919 -0.41617,-0.13919 -0.38308,0 -0.69314,0.31145 -0.69314,0.69454 0,0.38309 0.31006,0.69453 0.69314,0.69453 0.15159,0 0.2963,-0.0482 0.41617,-0.13918 0.13642,-0.10198 0.32936,-0.0744 0.43272,0.062 0.10199,0.13505 0.0744,0.32935 -0.062,0.43132 -0.22874,0.17088 -0.50024,0.26183 -0.78687,0.26183"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" />
<path
inkscape:connector-curvature="0"
id="path12887"
d="m 388.19888,241.53077 c 0,0.22186 -0.18055,0.40101 -0.40104,0.40101 -0.22186,0 -0.401,-0.17915 -0.401,-0.40101 0,-0.22186 0.17914,-0.40101 0.401,-0.40101 0.22049,0 0.40104,0.17915 0.40104,0.40101"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277775"
d="m 382.2781,128.11472 c 0.47407,0 0.78825,-0.1378 1.05834,-0.36931 0.0551,-0.0551 0.11024,-0.13229 0.11024,-0.23703 0,-0.16536 -0.1433,-0.29765 -0.30868,-0.29765 -0.0771,0 -0.1433,0.0276 -0.19293,0.0717 -0.1874,0.14882 -0.36929,0.23151 -0.64492,0.23151 -0.50711,0 -0.85989,-0.42444 -0.85989,-0.93156 v -0.005 c 0,-0.50711 0.36382,-0.92604 0.85989,-0.92604 0.23153,0 0.42443,0.0772 0.60636,0.21497 0.0496,0.0276 0.1047,0.0606 0.1929,0.0606 0.18192,0 0.32522,-0.13781 0.32522,-0.3142 0,-0.11575 -0.0606,-0.20946 -0.12679,-0.25907 -0.24803,-0.1819 -0.54567,-0.30317 -0.99218,-0.30317 -0.9095,0 -1.54341,0.68903 -1.54341,1.53238 v 0.011 c 0,0.84887 0.64495,1.52135 1.51585,1.52135 z m 0,0"
id="path24553" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277775"
d="m 385.20172,128.10921 h 0.0441 c 0.17638,0 0.29763,-0.0937 0.36378,-0.25356 l 0.97014,-2.32062 c 0.0166,-0.0386 0.0332,-0.0937 0.0332,-0.14331 0,-0.1819 -0.14334,-0.31419 -0.31972,-0.31419 -0.15434,0 -0.27009,0.0992 -0.31419,0.20395 l -0.74965,1.94027 -0.73861,-1.91823 c -0.0496,-0.13229 -0.15988,-0.22599 -0.33073,-0.22599 -0.18193,0 -0.32523,0.1378 -0.32523,0.3197 0,0.0551 0.0166,0.10473 0.0386,0.15985 l 0.9591,2.29857 c 0.0661,0.15985 0.19293,0.25356 0.36932,0.25356 z m 0,0"
id="path24545" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277775"
d="m 387.17918,127.0619 h 0.7331 c 0.17089,0 0.31419,-0.1378 0.31419,-0.30868 0,-0.17088 -0.1433,-0.30868 -0.31419,-0.30868 h -0.7331 c -0.17089,0 -0.30868,0.1378 -0.30868,0.30868 0,0.17088 0.13779,0.30868 0.30868,0.30868 z m 0,0"
id="path24549" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277775"
d="m 390.30112,128.11472 c 0.47406,0 0.78824,-0.1378 1.05833,-0.36931 0.0551,-0.0551 0.11025,-0.13229 0.11025,-0.23703 0,-0.16536 -0.1433,-0.29765 -0.30869,-0.29765 -0.0771,0 -0.14329,0.0276 -0.19293,0.0717 -0.1874,0.14882 -0.36929,0.23151 -0.64491,0.23151 -0.50712,0 -0.8599,-0.42444 -0.8599,-0.93156 v -0.005 c 0,-0.50711 0.36382,-0.92604 0.8599,-0.92604 0.23152,0 0.42442,0.0772 0.60635,0.21497 0.0496,0.0276 0.10471,0.0606 0.1929,0.0606 0.18193,0 0.32522,-0.13781 0.32522,-0.3142 0,-0.11575 -0.0606,-0.20946 -0.12678,-0.25907 -0.24804,-0.1819 -0.54568,-0.30317 -0.99219,-0.30317 -0.9095,0 -1.5434,0.68902 -1.5434,1.53238 v 0.011 c 0,0.84887 0.64495,1.52135 1.51585,1.52135 z m 0,0"
id="path24541" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277775"
d="m 393.37282,128.11472 c 0.47407,0 0.78825,-0.1378 1.05834,-0.36931 0.0551,-0.0551 0.11024,-0.13229 0.11024,-0.23703 0,-0.16536 -0.1433,-0.29765 -0.30868,-0.29765 -0.0771,0 -0.1433,0.0276 -0.19293,0.0717 -0.1874,0.14882 -0.36929,0.23151 -0.64492,0.23151 -0.50711,0 -0.85989,-0.42444 -0.85989,-0.93156 v -0.005 c 0,-0.50711 0.36382,-0.92604 0.85989,-0.92604 0.23153,0 0.42443,0.0772 0.60636,0.21497 0.0496,0.0276 0.1047,0.0606 0.1929,0.0606 0.18192,0 0.32522,-0.13781 0.32522,-0.3142 0,-0.11575 -0.0606,-0.20946 -0.12679,-0.25907 -0.24803,-0.1819 -0.54567,-0.30317 -0.99218,-0.30317 -0.9095,0 -1.54341,0.68903 -1.54341,1.53238 v 0.011 c 0,0.84887 0.64495,1.52135 1.51585,1.52135 z m 0,0"
id="path24537" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="widgets"
style="display:none">
<circle
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="path27377"
cx="7.9994998"
cy="77.451263"
r="2" />
<circle
r="2"
cy="77.451263"
cx="19.599819"
id="circle28184"
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle28186"
cx="31.199474"
cy="77.451263"
r="2" />
<circle
r="2"
cy="77.451263"
cx="42.799793"
id="circle28188"
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
r="2"
cy="89.050903"
cx="7.9994998"
id="circle28190"
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle28192"
cx="19.599819"
cy="89.050903"
r="2" />
<circle
r="2"
cy="89.050903"
cx="31.199474"
id="circle28194"
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle28196"
cx="42.799793"
cy="89.050903"
r="2" />
<circle
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle28198"
cx="7.9994998"
cy="100.65122"
r="2" />
<circle
r="2"
cy="100.65122"
cx="19.599819"
id="circle28200"
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle28202"
cx="31.199474"
cy="100.65122"
r="2" />
<circle
r="2"
cy="100.65122"
cx="42.799793"
id="circle28204"
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
r="2"
cy="112.25155"
cx="7.9994998"
id="circle28206"
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle28208"
cx="19.599819"
cy="112.25155"
r="2" />
<circle
r="2"
cy="112.25155"
cx="31.199474"
id="circle28210"
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
style="opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle28212"
cx="42.799793"
cy="112.25155"
r="2" />
<rect
style="opacity:1;vector-effect:none;fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.87907022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="rect28214"
width="44.00074"
height="54.666771"
x="3.39961"
y="14.83872" />
</g>
</svg>

+ 146
- 0
res/Core/CV-Gate.svg View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="50.799999mm"
height="128.50069mm"
viewBox="0 0 50.799999 128.50069"
version="1.1"
id="svg28661"
inkscape:version="0.92.2 2405546, 2018-03-11"
sodipodi:docname="CV-GATE.svg">
<defs
id="defs28655" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="299.51464"
inkscape:cy="255.96778"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1600"
inkscape:window-height="882"
inkscape:window-x="0"
inkscape:window-y="18"
inkscape:window-maximized="0" />
<metadata
id="metadata28658">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-423.18863,-118.49952)">
<path
inkscape:connector-curvature="0"
id="path9523"
d="m 423.28099,118.59323 h 50.61394 V 246.9065 h -50.61394 z m 0,0"
style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" />
<path
inkscape:connector-curvature="0"
id="path9525"
d="m 473.98863,118.49952 h -50.8 V 247.0002 h 50.8 z m -0.18739,128.31327 H 423.37469 V 118.68694 h 50.42655 z m 0,0"
style="fill:#ababab;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" />
<path
inkscape:connector-curvature="0"
id="path9547"
d="m 431.13717,195.95078 h 34.79959"
style="fill:none;stroke:#000000;stroke-width:0.35277775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path9549"
d="m 431.13717,207.55111 h 34.79959"
style="fill:none;stroke:#000000;stroke-width:0.35277775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path9551"
d="m 431.13717,219.15143 h 34.79959"
style="fill:none;stroke:#000000;stroke-width:0.35277775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path9553"
d="m 431.13717,230.75037 h 34.79959"
style="fill:none;stroke:#000000;stroke-width:0.35277775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path13127"
d="m 445.83534,242.85644 c -0.11715,0 -0.22465,-0.0661 -0.27562,-0.1695 l -1.0032,-2.00504 c -0.0758,-0.15296 -0.0138,-0.33762 0.1378,-0.41479 0.15296,-0.0758 0.33761,-0.0138 0.41342,0.13918 l 0.7276,1.45245 0.72623,-1.45245 c 0.0758,-0.15296 0.2618,-0.21497 0.41339,-0.13918 0.15296,0.0772 0.21498,0.26183 0.13783,0.41479 l -1.00186,2.00504 c -0.0523,0.10336 -0.15984,0.1695 -0.27559,0.1695"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" />
<path
inkscape:connector-curvature="0"
id="path13129"
d="m 451.34058,242.85644 c -0.11712,0 -0.22324,-0.0661 -0.27559,-0.1695 l -1.00185,-2.00504 c -0.0771,-0.15296 -0.0152,-0.33762 0.13783,-0.41479 0.15155,-0.0758 0.3376,-0.0138 0.41338,0.13918 l 0.72623,1.45245 0.72623,-1.45245 c 0.0758,-0.15296 0.26183,-0.21497 0.41342,-0.13918 0.15296,0.0772 0.21498,0.26183 0.13917,0.41479 l -1.00319,2.00504 c -0.051,0.10336 -0.15847,0.1695 -0.27563,0.1695"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" />
<path
inkscape:connector-curvature="0"
id="path13131"
d="m 448.73747,242.85644 c -0.72348,0 -1.3105,-0.58705 -1.3105,-1.31051 0,-0.72209 0.58702,-1.31052 1.3105,-1.31052 0.28663,0 0.55813,0.091 0.78687,0.26183 0.13642,0.10197 0.16397,0.29628 0.0606,0.4327 -0.10199,0.13505 -0.29492,0.16261 -0.43134,0.0606 -0.11988,-0.091 -0.26459,-0.13919 -0.41617,-0.13919 -0.38309,0 -0.69452,0.31145 -0.69452,0.69454 0,0.38309 0.31143,0.69453 0.69452,0.69453 0.15158,0 0.29629,-0.0482 0.41617,-0.13918 0.13642,-0.10198 0.32935,-0.0744 0.43134,0.062 0.10333,0.13505 0.0758,0.32935 -0.0606,0.43132 -0.22874,0.17088 -0.50024,0.26183 -0.78687,0.26183"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" />
<path
inkscape:connector-curvature="0"
id="path13133"
d="m 449.15914,241.53077 c 0,0.22186 -0.18051,0.40101 -0.40237,0.40101 -0.22049,0 -0.39963,-0.17915 -0.39963,-0.40101 0,-0.22186 0.17914,-0.40101 0.39963,-0.40101 0.22186,0 0.40237,0.17915 0.40237,0.40101"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277775"
d="m 440.45065,128.11472 c 0.47406,0 0.78825,-0.1378 1.05833,-0.36931 0.0551,-0.0551 0.11024,-0.13229 0.11024,-0.23703 0,-0.16536 -0.14329,-0.29765 -0.30868,-0.29765 -0.0772,0 -0.14329,0.0276 -0.19293,0.0717 -0.1874,0.14882 -0.36929,0.23151 -0.64491,0.23151 -0.50712,0 -0.8599,-0.42444 -0.8599,-0.93156 v -0.005 c 0,-0.50711 0.36382,-0.92604 0.8599,-0.92604 0.23153,0 0.42442,0.0772 0.60635,0.21497 0.0496,0.0276 0.10471,0.0606 0.1929,0.0606 0.18193,0 0.32523,-0.13781 0.32523,-0.3142 0,-0.11575 -0.0606,-0.20946 -0.12679,-0.25907 -0.24804,-0.1819 -0.54568,-0.30317 -0.99219,-0.30317 -0.9095,0 -1.5434,0.68903 -1.5434,1.53238 v 0.011 c 0,0.84887 0.64495,1.52135 1.51585,1.52135 z m 0,0"
id="path24277" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277775"
d="m 443.37426,128.10921 h 0.0441 c 0.17639,0 0.29764,-0.0937 0.36378,-0.25356 l 0.97014,-2.32062 c 0.0166,-0.0386 0.0332,-0.0937 0.0332,-0.14331 0,-0.1819 -0.14333,-0.31419 -0.31972,-0.31419 -0.15434,0 -0.27009,0.0992 -0.31418,0.20395 l -0.74966,1.94027 -0.73861,-1.91823 c -0.0496,-0.13229 -0.15988,-0.22599 -0.33073,-0.22599 -0.18193,0 -0.32522,0.1378 -0.32522,0.3197 0,0.0551 0.0166,0.10473 0.0386,0.15985 l 0.95909,2.29857 c 0.0661,0.15985 0.19294,0.25356 0.36933,0.25356 z m 0,0"
id="path24273" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277775"
d="m 445.35299,127.0619 h 0.73311 c 0.17088,0 0.31418,-0.1378 0.31418,-0.30868 0,-0.17088 -0.1433,-0.30868 -0.31418,-0.30868 h -0.73311 c -0.17089,0 -0.30868,0.1378 -0.30868,0.30868 0,0.17088 0.13779,0.30868 0.30868,0.30868 z m 0,0"
id="path24269" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277775"
d="m 448.51353,128.11472 c 0.44647,0 0.79925,-0.14882 1.03628,-0.29765 0.15984,-0.0882 0.23149,-0.22049 0.23149,-0.41341 v -0.71658 c 0,-0.18191 -0.1433,-0.33073 -0.32519,-0.33073 h -0.74415 c -0.15984,0 -0.28663,0.13229 -0.28663,0.28663 0,0.15434 0.12679,0.28112 0.28663,0.28112 h 0.44098 v 0.41892 c -0.16539,0.12127 -0.38033,0.1819 -0.61737,0.1819 -0.52366,0 -0.89849,-0.39687 -0.89849,-0.94258 v -0.005 c 0,-0.50711 0.38033,-0.92604 0.8544,-0.92604 0.27559,0 0.46852,0.0772 0.64491,0.20395 0.0496,0.0331 0.10474,0.0662 0.19844,0.0662 0.18189,0 0.32522,-0.14332 0.32522,-0.31971 0,-0.12678 -0.0717,-0.21497 -0.13779,-0.26458 -0.26459,-0.1819 -0.56226,-0.28663 -1.00873,-0.28663 -0.89849,0 -1.55445,0.68902 -1.55445,1.53237 v 0.011 c 0,0.87643 0.63391,1.52135 1.55445,1.52135 z m 0,0"
id="path24265" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277775"
d="m 450.19155,127.78399 c 0,0.17088 0.12679,0.30868 0.29767,0.30868 0.1378,0 0.24804,-0.0772 0.30314,-0.20394 l 0.20398,-0.49059 h 1.30637 l 0.19844,0.46854 c 0.0606,0.13229 0.15984,0.22599 0.31418,0.22599 0.17089,0 0.30868,-0.14331 0.30868,-0.31419 0,-0.0441 -0.0109,-0.0882 -0.0332,-0.13229 l -1.03628,-2.33164 c -0.0717,-0.15985 -0.19844,-0.25907 -0.37483,-0.25907 h -0.0386 c -0.17639,0 -0.30868,0.0992 -0.38033,0.25907 l -1.03078,2.33164 c -0.0219,0.0441 -0.0386,0.0937 -0.0386,0.1378 z m 1.04732,-0.95911 0.41339,-0.97565 0.40792,0.97565 z m 0,0"
id="path24261" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277775"
d="m 453.98691,127.76194 c 0,0.18191 0.1433,0.33073 0.32519,0.33073 0.18193,0 0.32522,-0.14882 0.32522,-0.33073 v -2.06154 h 0.62841 c 0.16534,0 0.29764,-0.13229 0.29764,-0.29766 0,-0.16536 -0.1323,-0.30316 -0.29764,-0.30316 h -1.90723 c -0.16534,0 -0.29763,0.1378 -0.29763,0.30316 0,0.16537 0.13229,0.29766 0.29763,0.29766 h 0.62841 z m 0,0"
id="path24257" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277775"
d="m 456.35147,128.06511 h 1.65915 c 0.16538,0 0.29217,-0.12678 0.29217,-0.28663 0,-0.15985 -0.12679,-0.29214 -0.29217,-0.29214 h -1.33943 v -0.62288 h 1.12999 c 0.15984,0 0.29213,-0.12678 0.29213,-0.28663 0,-0.16536 -0.13229,-0.29214 -0.29213,-0.29214 h -1.12999 v -0.60083 h 1.32292 c 0.15984,0 0.29214,-0.12678 0.29214,-0.29214 0,-0.15985 -0.1323,-0.29214 -0.29214,-0.29214 h -1.64264 c -0.18189,0 -0.32523,0.14882 -0.32523,0.33072 v 2.3096 c 0,0.1819 0.14334,0.32521 0.32523,0.32521 z m 0,0"
id="path24253" />
</g>
</svg>

+ 117
- 0
src/Core/CV_CC.cpp View File

@@ -0,0 +1,117 @@
#include "Core.hpp"


template <int N>
struct CCMidiOutput : midi::Output {
int ccs[N];
int lastValues[N];

CCMidiOutput() {
reset();
}

void reset() {
for (int n = 0; n < N; n++) {
ccs[n] = n;
lastValues[n] = -1;
}
}

void setCC(int cc, int n) {
ccs[n] = cc;
}

void setValue(int value, int n) {
if (value == lastValues[n])
return;
lastValues[n] = value;
// CC
midi::Message m;
m.setStatus(0xb);
m.setNote(ccs[n]);
m.setValue(value);
sendMessage(m);
}
};


struct CV_CC : Module {
enum ParamIds {
NUM_PARAMS
};
enum InputIds {
ENUMS(CC_INPUTS, 16),
NUM_INPUTS
};
enum OutputIds {
NUM_OUTPUTS
};
enum LightIds {
NUM_LIGHTS
};

CCMidiOutput<16> midiOutput;
float rateLimiterPhase = 0.f;

CV_CC() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
}

void step() override {
const float rateLimiterPeriod = 0.010f;
rateLimiterPhase += app()->engine->getSampleTime() / rateLimiterPeriod;
if (rateLimiterPhase >= 1.f) {
rateLimiterPhase -= 1.f;
}
else {
return;
}

for (int n = 0; n < 16; n++) {
int value = (int) std::round(inputs[CC_INPUTS + n].getVoltage() / 10.f * 127);
value = clamp(value, 0, 127);
midiOutput.setValue(value, n);
}
}
};


struct CV_CCWidget : ModuleWidget {
CV_CCWidget(CV_CC *module) {
setModule(module);
setPanel(SVG::load(asset::system("res/Core/CV-CC.svg")));

addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

addInput(createInputCentered<PJ301MPort>(mm2px(Vec(8, 77)), module, CV_CC::CC_INPUTS + 0));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20, 77)), module, CV_CC::CC_INPUTS + 1));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(31, 77)), module, CV_CC::CC_INPUTS + 2));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(43, 77)), module, CV_CC::CC_INPUTS + 3));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(8, 89)), module, CV_CC::CC_INPUTS + 4));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20, 89)), module, CV_CC::CC_INPUTS + 5));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(31, 89)), module, CV_CC::CC_INPUTS + 6));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(43, 89)), module, CV_CC::CC_INPUTS + 7));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(8, 101)), module, CV_CC::CC_INPUTS + 8));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20, 101)), module, CV_CC::CC_INPUTS + 9));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(31, 101)), module, CV_CC::CC_INPUTS + 10));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(43, 101)), module, CV_CC::CC_INPUTS + 11));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(8, 112)), module, CV_CC::CC_INPUTS + 12));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20, 112)), module, CV_CC::CC_INPUTS + 13));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(31, 112)), module, CV_CC::CC_INPUTS + 14));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(43, 112)), module, CV_CC::CC_INPUTS + 15));

MidiWidget *midiWidget = createWidget<MidiWidget>(mm2px(Vec(3.4, 14.839)));
midiWidget->box.size = mm2px(Vec(44, 54.667));
if (module)
midiWidget->midiIO = &module->midiOutput;
// midiWidget->createGridChoices();
addChild(midiWidget);
}
};


Model *modelCV_CC = createModel<CV_CC, CV_CCWidget>("CV-CC");


+ 159
- 0
src/Core/CV_Gate.cpp View File

@@ -0,0 +1,159 @@
#include "Core.hpp"


template <int N>
struct GateMidiOutput : midi::Output {
int vels[N];
bool lastGates[N];
int notes[N];

GateMidiOutput() {
reset();
}

void reset() {
for (int n = 0; n < N; n++) {
vels[n] = 100;
lastGates[n] = false;
notes[n] = 60 + n;
}
}

void panic() {
reset();
// Send all note off commands
for (int note = 0; note <= 127; note++) {
// Note off
midi::Message m;
m.setStatus(0x8);
m.setNote(note);
m.setValue(0);
sendMessage(m);
}
}

void setVelocity(int vel, int n) {
vels[n] = vel;
}

void setGate(bool gate, int n) {
if (gate && !lastGates[n]) {
// Note on
midi::Message m;
m.setStatus(0x9);
m.setNote(notes[n]);
m.setValue(vels[n]);
sendMessage(m);
}
else if (!gate && lastGates[n]) {
// Note off
midi::Message m;
m.setStatus(0x8);
m.setNote(notes[n]);
m.setValue(vels[n]);
sendMessage(m);
}
lastGates[n] = gate;
}

void setNote(int note, int n) {
if (note == notes[n])
return;
if (lastGates[n]) {
// Note off
midi::Message m1;
m1.setStatus(0x8);
m1.setNote(notes[n]);
m1.setValue(vels[n]);
sendMessage(m1);
// Note on
midi::Message m2;
m2.setStatus(0x9);
m2.setNote(note);
m2.setValue(vels[n]);
sendMessage(m2);
}
notes[n] = note;
}
};


struct CV_Gate : Module {
enum ParamIds {
NUM_PARAMS
};
enum InputIds {
ENUMS(GATE_INPUTS, 16),
NUM_INPUTS
};
enum OutputIds {
NUM_OUTPUTS
};
enum LightIds {
NUM_LIGHTS
};

GateMidiOutput<16> midiOutput;
bool velocityMode = false;

CV_Gate() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
}

void step() override {
for (int n = 0; n < 16; n++) {
if (velocityMode) {
int vel = (int) std::round(inputs[GATE_INPUTS + n].getVoltage() / 10.f * 127);
vel = clamp(vel, 0, 127);
midiOutput.setVelocity(vel, n);
midiOutput.setGate(vel > 0, n);
}
else {
bool gate = inputs[GATE_INPUTS + n].getVoltage() >= 1.f;
midiOutput.setVelocity(100, n);
midiOutput.setGate(gate, n);
}
}
}
};


struct CV_GateWidget : ModuleWidget {
CV_GateWidget(CV_Gate *module) {
setModule(module);
setPanel(SVG::load(asset::system("res/Core/CV-Gate.svg")));

addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

addInput(createInputCentered<PJ301MPort>(mm2px(Vec(8, 77)), module, CV_Gate::GATE_INPUTS + 0));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20, 77)), module, CV_Gate::GATE_INPUTS + 1));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(31, 77)), module, CV_Gate::GATE_INPUTS + 2));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(43, 77)), module, CV_Gate::GATE_INPUTS + 3));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(8, 89)), module, CV_Gate::GATE_INPUTS + 4));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20, 89)), module, CV_Gate::GATE_INPUTS + 5));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(31, 89)), module, CV_Gate::GATE_INPUTS + 6));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(43, 89)), module, CV_Gate::GATE_INPUTS + 7));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(8, 101)), module, CV_Gate::GATE_INPUTS + 8));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20, 101)), module, CV_Gate::GATE_INPUTS + 9));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(31, 101)), module, CV_Gate::GATE_INPUTS + 10));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(43, 101)), module, CV_Gate::GATE_INPUTS + 11));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(8, 112)), module, CV_Gate::GATE_INPUTS + 12));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20, 112)), module, CV_Gate::GATE_INPUTS + 13));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(31, 112)), module, CV_Gate::GATE_INPUTS + 14));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(43, 112)), module, CV_Gate::GATE_INPUTS + 15));

MidiWidget *midiWidget = createWidget<MidiWidget>(mm2px(Vec(3.4, 14.839)));
midiWidget->box.size = mm2px(Vec(44, 54.667));
if (module)
midiWidget->midiIO = &module->midiOutput;
// midiWidget->createGridChoices();
addChild(midiWidget);
}
};


Model *modelCV_Gate = createModel<CV_Gate, CV_GateWidget>("CV-Gate");


+ 15
- 5
src/Core/CV_MIDI.cpp View File

@@ -52,7 +52,7 @@ struct PolyphonicMidiOutput : midi::Output {
}
}

void setVel(int vel, int c) {
void setVelocity(int vel, int c) {
vels[c] = vel;
}

@@ -229,16 +229,26 @@ struct CV_MIDI : Module {
};

PolyphonicMidiOutput<PORT_MAX_CHANNELS> midiOutput;
float rateLimiterPhase = 0.f;

CV_MIDI() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
}

void step() override {
const float rateLimiterPeriod = 0.005f;
rateLimiterPhase += app()->engine->getSampleTime() / rateLimiterPeriod;
if (rateLimiterPhase >= 1.f) {
rateLimiterPhase -= 1.f;
}
else {
return;
}

for (int c = 0; c < inputs[PITCH_INPUT].getChannels(); c++) {
int vel = (int) std::round(inputs[VEL_INPUT].normalize(10.f * 100 / 127, c) / 10.f * 127);
vel = clamp(vel, 0, 127);
midiOutput.setVel(vel, c);
midiOutput.setVelocity(vel, c);

int note = (int) std::round(inputs[PITCH_INPUT].getVoltage(c) * 12.f + 60.f);
note = clamp(note, 0, 127);
@@ -262,9 +272,6 @@ struct CV_MIDI : Module {
mw = clamp(mw, 0, 127);
midiOutput.setModWheel(mw);

bool clk = inputs[CLK_INPUT].value >= 1.f;
midiOutput.setClock(clk);

int vol = (int) std::round(inputs[VOL_INPUT].normalize(10.f) / 10.f * 127);
vol = clamp(vol, 0, 127);
midiOutput.setVolume(vol);
@@ -273,6 +280,9 @@ struct CV_MIDI : Module {
pan = clamp(pan, 0, 127);
midiOutput.setPan(pan);

bool clk = inputs[CLK_INPUT].value >= 1.f;
midiOutput.setClock(clk);

bool start = inputs[START_INPUT].value >= 1.f;
midiOutput.setStart(start);



+ 11
- 1
src/Core/Core.cpp View File

@@ -14,7 +14,7 @@ void init(rack::Plugin *p) {
p->sourceUrl = "https://github.com/VCVRack/Rack";

modelAudioInterface->name = "Audio";
modelAudioInterface->description = "";
modelAudioInterface->description = "Sends audio and CV to/from an audio device";
modelAudioInterface->tags = {"External"};
p->addModel(modelAudioInterface);

@@ -43,6 +43,16 @@ void init(rack::Plugin *p) {
modelCV_MIDI->tags = {"External", "MIDI"};
p->addModel(modelCV_MIDI);

modelCV_CC->name = "CV-CC";
modelCV_CC->description = "";
modelCV_CC->tags = {"External", "MIDI"};
p->addModel(modelCV_CC);

modelCV_Gate->name = "CV-Gate";
modelCV_Gate->description = "";
modelCV_Gate->tags = {"External", "MIDI"};
p->addModel(modelCV_Gate);

modelBlank->name = "Blank";
modelBlank->description = "";
modelBlank->tags = {"Blank"};


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

@@ -11,6 +11,8 @@ extern Model *modelQuadMIDIToCVInterface;
extern Model *modelMIDICCToCVInterface;
extern Model *modelMIDITriggerToCVInterface;
extern Model *modelCV_MIDI;
extern Model *modelCV_CC;
extern Model *modelCV_Gate;
extern Model *modelBlank;
extern Model *modelNotes;



+ 1
- 1
src/app/Knob.cpp View File

@@ -67,7 +67,7 @@ void Knob::onDragMove(const event::DragMove &e) {
float delta = KNOB_SENSITIVITY * -e.mouseDelta.y * speed * range;

// Drag slower if Mod is held
if (app()->window->isModPressed())
if ((app()->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL)
delta /= 16.f;

if (snap) {


+ 21
- 19
src/app/ModuleWidget.cpp View File

@@ -16,12 +16,13 @@ namespace rack {


ModuleWidget::~ModuleWidget() {
if (module) {
delete module;
}
setModule(NULL);
}

void ModuleWidget::setModule(Module *module) {
if (this->module) {
delete this->module;
}
this->module = module;
}

@@ -338,7 +339,7 @@ void ModuleWidget::onHover(const event::Hover &e) {

// Instead of checking key-down events, delete the module even if key-repeat hasn't fired yet and the cursor is hovering over the widget.
if (glfwGetKey(app()->window->win, GLFW_KEY_DELETE) == GLFW_PRESS || glfwGetKey(app()->window->win, GLFW_KEY_BACKSPACE) == GLFW_PRESS) {
if (!app()->window->isModPressed() && !app()->window->isShiftPressed()) {
if ((app()->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
ModuleWidget_removeAction(this);
e.consume(NULL);
return;
@@ -348,8 +349,9 @@ void ModuleWidget::onHover(const event::Hover &e) {

void ModuleWidget::onButton(const event::Button &e) {
OpaqueWidget::onButton(e);

if (e.getConsumed() == this) {
if (e.button == 1) {
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
createContextMenu();
}
}
@@ -359,43 +361,43 @@ void ModuleWidget::onHoverKey(const event::HoverKey &e) {
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
switch (e.key) {
case GLFW_KEY_I: {
if (app()->window->isModPressed() && !app()->window->isShiftPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
reset();
e.consume(this);
}
} break;
case GLFW_KEY_R: {
if (app()->window->isModPressed() && !app()->window->isShiftPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
randomize();
e.consume(this);
}
} break;
case GLFW_KEY_C: {
if (app()->window->isModPressed() && !app()->window->isShiftPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
copyClipboard();
e.consume(this);
}
} break;
case GLFW_KEY_V: {
if (app()->window->isModPressed() && !app()->window->isShiftPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
pasteClipboard();
e.consume(this);
}
} break;
case GLFW_KEY_D: {
if (app()->window->isModPressed() && !app()->window->isShiftPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
app()->scene->rackWidget->cloneModule(this);
e.consume(this);
}
} break;
case GLFW_KEY_U: {
if (app()->window->isModPressed() && !app()->window->isShiftPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
disconnect();
e.consume(this);
}
} break;
case GLFW_KEY_E: {
if (app()->window->isModPressed() && !app()->window->isShiftPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
ModuleWidget_bypassAction(this);
e.consume(this);
}
@@ -436,7 +438,7 @@ struct ModuleDisconnectItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleDisconnectItem() {
text = "Disconnect cables";
rightText = WINDOW_MOD_KEY_NAME "+U";
rightText = WINDOW_MOD_CTRL_NAME "+U";
}
void onAction(const event::Action &e) override {
moduleWidget->disconnect();
@@ -447,7 +449,7 @@ struct ModuleResetItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleResetItem() {
text = "Initialize";
rightText = WINDOW_MOD_KEY_NAME "+I";
rightText = WINDOW_MOD_CTRL_NAME "+I";
}
void onAction(const event::Action &e) override {
moduleWidget->reset();
@@ -458,7 +460,7 @@ struct ModuleRandomizeItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleRandomizeItem() {
text = "Randomize";
rightText = WINDOW_MOD_KEY_NAME "+R";
rightText = WINDOW_MOD_CTRL_NAME "+R";
}
void onAction(const event::Action &e) override {
moduleWidget->randomize();
@@ -469,7 +471,7 @@ struct ModuleCopyItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleCopyItem() {
text = "Copy preset";
rightText = WINDOW_MOD_KEY_NAME "+C";
rightText = WINDOW_MOD_CTRL_NAME "+C";
}
void onAction(const event::Action &e) override {
moduleWidget->copyClipboard();
@@ -480,7 +482,7 @@ struct ModulePasteItem : MenuItem {
ModuleWidget *moduleWidget;
ModulePasteItem() {
text = "Paste preset";
rightText = WINDOW_MOD_KEY_NAME "+V";
rightText = WINDOW_MOD_CTRL_NAME "+V";
}
void onAction(const event::Action &e) override {
moduleWidget->pasteClipboard();
@@ -511,7 +513,7 @@ struct ModuleCloneItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleCloneItem() {
text = "Duplicate";
rightText = WINDOW_MOD_KEY_NAME "+D";
rightText = WINDOW_MOD_CTRL_NAME "+D";
}
void onAction(const event::Action &e) override {
app()->scene->rackWidget->cloneModule(moduleWidget);
@@ -524,7 +526,7 @@ struct ModuleBypassItem : MenuItem {
text = "Bypass";
}
void step() override {
rightText = WINDOW_MOD_KEY_NAME "+E";
rightText = WINDOW_MOD_CTRL_NAME "+E";
if (!moduleWidget->module)
return;
if (moduleWidget->module->bypass)


+ 2
- 2
src/app/ParamWidget.cpp View File

@@ -119,7 +119,7 @@ void ParamWidget::fromJson(json_t *rootJ) {

void ParamWidget::onButton(const event::Button &e) {
// Right click to reset
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT && !(e.mods & WINDOW_MOD) && !(e.mods & GLFW_MOD_SHIFT)) {
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT && (e.mods & WINDOW_MOD_MASK) == 0) {
if (paramQuantity && paramQuantity->isBounded()) {
float oldValue = paramQuantity->getValue();
paramQuantity->reset();
@@ -141,7 +141,7 @@ void ParamWidget::onButton(const event::Button &e) {
}

// Shift-click to open value entry
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && !(e.mods & WINDOW_MOD) && (e.mods & GLFW_MOD_SHIFT)) {
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && (e.mods & WINDOW_MOD_MASK) == GLFW_MOD_SHIFT) {
// Create ParamField
MenuOverlay *overlay = new MenuOverlay;
app()->scene->addChild(overlay);


+ 4
- 1
src/app/PortWidget.cpp View File

@@ -72,7 +72,10 @@ void PortWidget::onButton(const event::Button &e) {
void PortWidget::onDragStart(const event::DragStart &e) {
// Try to grab cable on top of stack
CableWidget *cable = NULL;
if (type == INPUT || !app()->window->isModPressed()) {
if (type == OUTPUT && (app()->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
// Keep cable NULL
}
else {
cable = app()->scene->rackWidget->cableContainer->getTopCable(this);
}



+ 3
- 3
src/app/RackWidget.cpp View File

@@ -591,11 +591,11 @@ void RackWidget::draw(NVGcontext *vg) {
void RackWidget::onHover(const event::Hover &e) {
// Scroll with arrow keys
float arrowSpeed = 30.0;
if (app()->window->isShiftPressed() && app()->window->isModPressed())
if ((app()->window->getMods() & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL |GLFW_MOD_SHIFT))
arrowSpeed /= 16.0;
else if (app()->window->isShiftPressed())
else if ((app()->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL)
arrowSpeed *= 4.0;
else if (app()->window->isModPressed())
else if ((app()->window->getMods() & WINDOW_MOD_MASK) == GLFW_MOD_SHIFT)
arrowSpeed /= 4.0;

ScrollWidget *scrollWidget = app()->scene->scrollWidget;


+ 9
- 9
src/app/Scene.cpp View File

@@ -84,49 +84,49 @@ void Scene::onHoverKey(const event::HoverKey &e) {
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
switch (e.key) {
case GLFW_KEY_N: {
if ((e.mods & WINDOW_MOD) && !(e.mods & GLFW_MOD_SHIFT)) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
rackWidget->reset();
e.consume(this);
}
} break;
case GLFW_KEY_Q: {
if ((e.mods & WINDOW_MOD) && !(e.mods & GLFW_MOD_SHIFT)) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
app()->window->close();
e.consume(this);
}
} break;
case GLFW_KEY_O: {
if ((e.mods & WINDOW_MOD) && !(e.mods & GLFW_MOD_SHIFT)) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
rackWidget->loadDialog();
e.consume(this);
}
if ((e.mods & WINDOW_MOD) && (e.mods & GLFW_MOD_SHIFT)) {
if ((e.mods & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL | GLFW_MOD_SHIFT)) {
rackWidget->revert();
e.consume(this);
}
} break;
case GLFW_KEY_S: {
if ((e.mods & WINDOW_MOD) && !(e.mods & GLFW_MOD_SHIFT)) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
rackWidget->saveDialog();
e.consume(this);
}
if ((e.mods & WINDOW_MOD) && (e.mods & GLFW_MOD_SHIFT)) {
if ((e.mods & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL | GLFW_MOD_SHIFT)) {
rackWidget->saveAsDialog();
e.consume(this);
}
} break;
case GLFW_KEY_V: {
if ((e.mods & WINDOW_MOD) && !(e.mods & GLFW_MOD_SHIFT)) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
rackWidget->pastePresetClipboard();
e.consume(this);
}
} break;
case GLFW_KEY_Z: {
if ((e.mods & WINDOW_MOD) && !(e.mods & GLFW_MOD_SHIFT)) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
app()->history->undo();
e.consume(this);
}
if ((e.mods & WINDOW_MOD) && (e.mods & GLFW_MOD_SHIFT)) {
if ((e.mods & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL | GLFW_MOD_SHIFT)) {
app()->history->redo();
e.consume(this);
}


+ 3
- 2
src/app/Switch.cpp View File

@@ -33,12 +33,13 @@ void Switch::onDragStart(const event::DragStart &e) {
else {
if (paramQuantity) {
float oldValue = paramQuantity->getValue();
// Increment value by 1, or reset back to minimum
if (paramQuantity->isMax()) {
// Reset value back to minimum
paramQuantity->setMin();
}
else {
paramQuantity->setValue(std::floor(paramQuantity->getValue() + 1));
// Increment value by 1
paramQuantity->setValue(std::round(paramQuantity->getValue()) + 1.f);
}

float newValue = paramQuantity->getValue();


+ 5
- 5
src/app/Toolbar.cpp View File

@@ -35,7 +35,7 @@ struct MenuButton : Button {
struct NewItem : MenuItem {
NewItem() {
text = "New";
rightText = "(" WINDOW_MOD_KEY_NAME "+N)";
rightText = "(" WINDOW_MOD_CTRL_NAME "+N)";
}
void onAction(const event::Action &e) override {
app()->scene->rackWidget->reset();
@@ -46,7 +46,7 @@ struct NewItem : MenuItem {
struct OpenItem : MenuItem {
OpenItem() {
text = "Open";
rightText = "(" WINDOW_MOD_KEY_NAME "+O)";
rightText = "(" WINDOW_MOD_CTRL_NAME "+O)";
}
void onAction(const event::Action &e) override {
app()->scene->rackWidget->loadDialog();
@@ -57,7 +57,7 @@ struct OpenItem : MenuItem {
struct SaveItem : MenuItem {
SaveItem() {
text = "Save";
rightText = "(" WINDOW_MOD_KEY_NAME "+S)";
rightText = "(" WINDOW_MOD_CTRL_NAME "+S)";
}
void onAction(const event::Action &e) override {
app()->scene->rackWidget->saveDialog();
@@ -68,7 +68,7 @@ struct SaveItem : MenuItem {
struct SaveAsItem : MenuItem {
SaveAsItem() {
text = "Save as";
rightText = "(" WINDOW_MOD_KEY_NAME "+Shift+S)";
rightText = "(" WINDOW_MOD_CTRL_NAME "+Shift+S)";
}
void onAction(const event::Action &e) override {
app()->scene->rackWidget->saveAsDialog();
@@ -109,7 +109,7 @@ struct DisconnectCablesItem : MenuItem {
struct QuitItem : MenuItem {
QuitItem() {
text = "Quit";
rightText = "(" WINDOW_MOD_KEY_NAME "+Q)";
rightText = "(" WINDOW_MOD_CTRL_NAME "+Q)";
}
void onAction(const event::Action &e) override {
app()->window->close();


+ 2
- 2
src/rtmidi.cpp View File

@@ -63,8 +63,8 @@ struct RtMidiOutputDevice : midi::OutputDevice {
void sendMessage(midi::Message message) override {
unsigned char msg[3];
msg[0] = message.cmd;
msg[0] = message.data1;
msg[0] = message.data2;
msg[1] = message.data1;
msg[2] = message.data2;
rtMidiOut->sendMessage(msg, 3);
}
};


+ 8
- 8
src/ui/TextField.cpp View File

@@ -94,7 +94,7 @@ void TextField::onSelectKey(const event::SelectKey &e) {
}
} break;
case GLFW_KEY_LEFT: {
if (app()->window->isModPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
while (--cursor > 0) {
if (text[cursor] == ' ')
break;
@@ -103,12 +103,12 @@ void TextField::onSelectKey(const event::SelectKey &e) {
else {
cursor--;
}
if (!app()->window->isShiftPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == 0) {
selection = cursor;
}
} break;
case GLFW_KEY_RIGHT: {
if (app()->window->isModPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
while (++cursor < (int) text.size()) {
if (text[cursor] == ' ')
break;
@@ -117,7 +117,7 @@ void TextField::onSelectKey(const event::SelectKey &e) {
else {
cursor++;
}
if (!app()->window->isShiftPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == 0) {
selection = cursor;
}
} break;
@@ -128,14 +128,14 @@ void TextField::onSelectKey(const event::SelectKey &e) {
selection = cursor = text.size();
} break;
case GLFW_KEY_V: {
if (app()->window->isModPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
const char *newText = glfwGetClipboardString(app()->window->win);
if (newText)
insertText(newText);
}
} break;
case GLFW_KEY_X: {
if (app()->window->isModPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if (cursor != selection) {
int begin = std::min(cursor, selection);
std::string selectedText = text.substr(begin, std::abs(selection - cursor));
@@ -145,7 +145,7 @@ void TextField::onSelectKey(const event::SelectKey &e) {
}
} break;
case GLFW_KEY_C: {
if (app()->window->isModPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if (cursor != selection) {
int begin = std::min(cursor, selection);
std::string selectedText = text.substr(begin, std::abs(selection - cursor));
@@ -154,7 +154,7 @@ void TextField::onSelectKey(const event::SelectKey &e) {
}
} break;
case GLFW_KEY_A: {
if (app()->window->isModPressed()) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
selectAll();
}
} break;


+ 17
- 15
src/window.cpp View File

@@ -66,6 +66,7 @@ static void mouseButtonCallback(GLFWwindow *win, int button, int action, int mod
if (button == GLFW_MOUSE_BUTTON_LEFT) {
if (mods & GLFW_MOD_CONTROL) {
button = GLFW_MOUSE_BUTTON_RIGHT;
mods &= ~GLFW_MOD_CONTROL;
}
}
#endif
@@ -123,12 +124,12 @@ static void cursorEnterCallback(GLFWwindow *win, int entered) {
static void scrollCallback(GLFWwindow *win, double x, double y) {
Window *window = (Window*) glfwGetWindowUserPointer(win);
math::Vec scrollDelta = math::Vec(x, y);
#if ARCH_LIN || ARCH_WIN
if (window->isShiftPressed())
scrollDelta = math::Vec(y, x);
#endif
scrollDelta = scrollDelta.mult(50.0);

// Flip coordinates if shift is held
if ((window->getMods() & WINDOW_MOD_MASK) == GLFW_MOD_SHIFT)
scrollDelta = scrollDelta.flip();

app()->event->handleScroll(window->mousePos, scrollDelta);
}

@@ -142,7 +143,7 @@ static void keyCallback(GLFWwindow *win, int key, int scancode, int action, int
app()->event->handleKey(window->mousePos, key, scancode, action, mods);

// Keyboard MIDI driver
if (!(mods & (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER))) {
if ((mods & WINDOW_MOD_MASK) == 0) {
if (action == GLFW_PRESS) {
keyboard::press(key);
}
@@ -380,16 +381,17 @@ void Window::cursorUnlock() {
}
}

bool Window::isModPressed() {
#ifdef ARCH_MAC
return glfwGetKey(win, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS;
#else
return glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS;
#endif
}

bool Window::isShiftPressed() {
return glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS;
int Window::getMods() {
int mods = 0;
if (glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS)
mods |= GLFW_MOD_SHIFT;
if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS)
mods |= GLFW_MOD_CONTROL;
if (glfwGetKey(win, GLFW_KEY_LEFT_ALT) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS)
mods |= GLFW_MOD_ALT;
if (glfwGetKey(win, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS)
mods |= GLFW_MOD_SUPER;
return mods;
}

math::Vec Window::getWindowSize() {


Loading…
Cancel
Save