Browse Source

Move Widget class to header, wrap settings, keyboard, and gamepad in namespace

tags/v1.0.0
Andrew Belt 6 years ago
parent
commit
dd02ec52ad
17 changed files with 293 additions and 217 deletions
  1. +2
    -2
      include/dsp/vumeter.hpp
  2. +8
    -6
      include/gamepad.hpp
  3. +0
    -6
      include/helpers.hpp
  4. +8
    -6
      include/keyboard.hpp
  5. +18
    -3
      include/math.hpp
  6. +1
    -0
      include/rack.hpp
  7. +49
    -0
      include/rack0.hpp
  8. +4
    -2
      include/settings.hpp
  9. +2
    -150
      include/widgets.hpp
  10. +128
    -0
      include/widgets/Widget.hpp
  11. +27
    -1
      include/window.hpp
  12. +1
    -1
      src/app/RackWidget.cpp
  13. +15
    -13
      src/gamepad.cpp
  14. +15
    -13
      src/keyboard.cpp
  15. +8
    -8
      src/main.cpp
  16. +4
    -2
      src/settings.cpp
  17. +3
    -4
      src/window.cpp

+ 2
- 2
include/dsp/vumeter.hpp View File

@@ -1,6 +1,6 @@
#pragma once #pragma once


#include "util/math.hpp"
#include "math.hpp"




namespace rack { namespace rack {
@@ -23,7 +23,7 @@ struct VUMeter {
return (dBScaled >= 0.0) ? 1.0 : 0.0; return (dBScaled >= 0.0) ? 1.0 : 0.0;
} }
else { else {
return clamp(dBScaled + i, 0.0, 1.0);
return math::clamp(dBScaled + i, 0.0, 1.0);
} }
} }
}; };


+ 8
- 6
include/gamepad.hpp View File

@@ -4,9 +4,10 @@




namespace rack { namespace rack {
namespace gamepad {




struct GamepadInputDevice : MidiInputDevice {
struct InputDevice : MidiInputDevice {
int deviceId; int deviceId;
std::vector<uint8_t> ccs; std::vector<uint8_t> ccs;
std::vector<bool> states; std::vector<bool> states;
@@ -14,10 +15,10 @@ struct GamepadInputDevice : MidiInputDevice {
}; };




struct GamepadDriver : MidiDriver {
GamepadInputDevice devices[16];
struct Driver : MidiDriver {
InputDevice devices[16];


GamepadDriver();
Driver();
std::string getName() override {return "Gamepad";} std::string getName() override {return "Gamepad";}
std::vector<int> getInputDeviceIds() override; std::vector<int> getInputDeviceIds() override;
std::string getInputDeviceName(int deviceId) override; std::string getInputDeviceName(int deviceId) override;
@@ -26,8 +27,9 @@ struct GamepadDriver : MidiDriver {
}; };




void gamepadInit();
void gamepadStep();
void init();
void step();




} // namespace gamepad
} // namespace rack } // namespace rack

+ 0
- 6
include/helpers.hpp View File

@@ -40,12 +40,6 @@ TWidget *createWidget(math::Vec pos) {
return w; return w;
} }


/** Deprecated. Use createWidget<TScrew>() instead */
template <class TScrew>
DEPRECATED TScrew *createScrew(math::Vec pos) {
return createWidget<TScrew>(pos);
}

template <class TParamWidget> template <class TParamWidget>
TParamWidget *createParam(math::Vec pos, Module *module, int paramId, float minValue, float maxValue, float defaultValue) { TParamWidget *createParam(math::Vec pos, Module *module, int paramId, float minValue, float maxValue, float defaultValue) {
TParamWidget *param = new TParamWidget(); TParamWidget *param = new TParamWidget();


+ 8
- 6
include/keyboard.hpp View File

@@ -5,9 +5,10 @@




namespace rack { namespace rack {
namespace keyboard {




struct KeyboardInputDevice : MidiInputDevice {
struct InputDevice : MidiInputDevice {
int octave = 5; int octave = 5;
std::map<int, int> pressedNotes; std::map<int, int> pressedNotes;
void onKeyPress(int key); void onKeyPress(int key);
@@ -15,8 +16,8 @@ struct KeyboardInputDevice : MidiInputDevice {
}; };




struct KeyboardDriver : MidiDriver {
KeyboardInputDevice device;
struct Driver : MidiDriver {
InputDevice device;
std::string getName() override {return "Computer keyboard";} std::string getName() override {return "Computer keyboard";}


std::vector<int> getInputDeviceIds() override; std::vector<int> getInputDeviceIds() override;
@@ -26,9 +27,10 @@ struct KeyboardDriver : MidiDriver {
}; };




void keyboardInit();
void keyboardPress(int key);
void keyboardRelease(int key);
void init();
void press(int key);
void release(int key);




} // namespace keyboard
} // namespace rack } // namespace rack

+ 18
- 3
include/math.hpp View File

@@ -39,16 +39,31 @@ b must be positive.
*/ */
inline int eucMod(int a, int b) { inline int eucMod(int a, int b) {
int mod = a % b; int mod = a % b;
return (mod >= 0) ? mod : mod + b;
if (mod < 0) {
mod += b;
}
return mod;
} }


/** Euclidean division. /** Euclidean division.
b must be positive. b must be positive.
*/ */
inline int eucDiv(int a, int b) { inline int eucDiv(int a, int b) {
int mod = a % b;
int div = a / b; int div = a / b;
return (mod >= 0) ? div : div - 1;
int mod = a % b;
if (mod < 0) {
div -= 1;
}
return div;
}

inline void eucDivMod(int a, int b, int *div, int *mod) {
*div = a / b;
*mod = a % b;
if (*mod < 0) {
*div -= 1;
*mod += b;
}
} }


/** Returns floor(log_2(n)), or 0 if n == 1. /** Returns floor(log_2(n)), or 0 if n == 1.


+ 1
- 0
include/rack.hpp View File

@@ -21,6 +21,7 @@
namespace rack { namespace rack {




// Adopt some sub-namespaces into the main namespace for convenience
using namespace math; using namespace math;
using namespace string; using namespace string;




+ 49
- 0
include/rack0.hpp View File

@@ -1,6 +1,7 @@
#pragma once #pragma once


#include "rack.hpp" #include "rack.hpp"
#include "componentlibrary.hpp"




namespace rack { namespace rack {
@@ -71,5 +72,53 @@ using string::stringf;
#define warn(...) WARN(__VA_ARGS__) #define warn(...) WARN(__VA_ARGS__)
#define fatal(...) FATAL(__VA_ARGS__) #define fatal(...) FATAL(__VA_ARGS__)


////////////////////
// asset
////////////////////

DEPRECATED inline std::string assetGlobal(std::string filename) {return asset::global(filename);}
DEPRECATED inline std::string assetLocal(std::string filename) {return asset::local(filename);}
DEPRECATED inline std::string assetPlugin(Plugin *plugin, std::string filename) {return asset::plugin(plugin, filename);}

////////////////////
// color
////////////////////

DEPRECATED inline NVGcolor colorClip(NVGcolor a) {return color::clip(a);}
DEPRECATED inline NVGcolor colorMinus(NVGcolor a, NVGcolor b) {return color::minus(a, b);}
DEPRECATED inline NVGcolor colorPlus(NVGcolor a, NVGcolor b) {return color::plus(a, b);}
DEPRECATED inline NVGcolor colorMult(NVGcolor a, NVGcolor b) {return color::mult(a, b);}
DEPRECATED inline NVGcolor colorMult(NVGcolor a, float x) {return color::mult(a, x);}
DEPRECATED inline NVGcolor colorScreen(NVGcolor a, NVGcolor b) {return color::screen(a, b);}
DEPRECATED inline NVGcolor colorAlpha(NVGcolor a, float alpha) {return color::alpha(a, alpha);}
DEPRECATED inline NVGcolor colorFromHexString(std::string s) {return color::fromHexString(s);}
DEPRECATED inline std::string colorToHexString(NVGcolor c) {return color::toHexString(c);}

////////////////////
// componentlibrary
////////////////////

DEPRECATED static const NVGcolor COLOR_BLACK_TRANSPARENT = SCHEME_BLACK_TRANSPARENT;
DEPRECATED static const NVGcolor COLOR_BLACK = SCHEME_BLACK;
DEPRECATED static const NVGcolor COLOR_WHITE = SCHEME_WHITE;
DEPRECATED static const NVGcolor COLOR_RED = SCHEME_RED;
DEPRECATED static const NVGcolor COLOR_ORANGE = SCHEME_ORANGE;
DEPRECATED static const NVGcolor COLOR_YELLOW = SCHEME_YELLOW;
DEPRECATED static const NVGcolor COLOR_GREEN = SCHEME_GREEN;
DEPRECATED static const NVGcolor COLOR_CYAN = SCHEME_CYAN;
DEPRECATED static const NVGcolor COLOR_BLUE = SCHEME_BLUE;
DEPRECATED static const NVGcolor COLOR_PURPLE = SCHEME_PURPLE;
DEPRECATED static const NVGcolor COLOR_LIGHT_PANEL = SCHEME_LIGHT_PANEL;
DEPRECATED static const NVGcolor COLOR_DARK_PANEL = SCHEME_DARK_PANEL;

////////////////////
// helpers
////////////////////

template <class TScrew>
DEPRECATED TScrew *createScrew(math::Vec pos) {
return createWidget<TScrew>(pos);
}



} // namespace rack } // namespace rack

+ 4
- 2
include/settings.hpp View File

@@ -3,12 +3,14 @@




namespace rack { namespace rack {
namespace settings {




extern bool gSkipAutosaveOnLaunch; extern bool gSkipAutosaveOnLaunch;


void settingsSave(std::string filename);
void settingsLoad(std::string filename);
void save(std::string filename);
void load(std::string filename);




} // namespace settings
} // namespace rack } // namespace rack

+ 2
- 150
include/widgets.hpp View File

@@ -1,168 +1,20 @@
#pragma once #pragma once
#include <list> #include <list>
#include <memory>

#include "nanovg.h"
#include "nanosvg.h"


#include "common.hpp" #include "common.hpp"
#include "events.hpp" #include "events.hpp"
#include "color.hpp" #include "color.hpp"


#include "widgets/Widget.hpp"


namespace rack {

////////////////////
// resources
////////////////////


// Constructing these directly will load from the disk each time. Use the load() functions to load from disk and cache them as long as the shared_ptr is held.
// Implemented in window.cpp

struct Font {
int handle;
Font(const std::string &filename);
~Font();
static std::shared_ptr<Font> load(const std::string &filename);
};

struct Image {
int handle;
Image(const std::string &filename);
~Image();
static std::shared_ptr<Image> load(const std::string &filename);
};

struct SVG {
NSVGimage *handle;
SVG(const std::string &filename);
~SVG();
static std::shared_ptr<SVG> load(const std::string &filename);
};
namespace rack {




//////////////////// ////////////////////
// Base widget // Base widget
//////////////////// ////////////////////


/** A node in the 2D scene graph
Never inherit from Widget directly. Instead, inherit from VirtualWidget declared below.
*/
struct Widget {
/** Stores position and size */
math::Rect box = math::Rect(math::Vec(), math::Vec(INFINITY, INFINITY));
Widget *parent = NULL;
std::list<Widget*> children;
bool visible = true;

virtual ~Widget();

virtual math::Rect getChildrenBoundingBox();
/** Returns `v` transformed into the coordinate system of `relative` */
virtual math::Vec getRelativeOffset(math::Vec v, Widget *relative);
/** Returns `v` transformed into world coordinates */
math::Vec getAbsoluteOffset(math::Vec v) {
return getRelativeOffset(v, NULL);
}
/** Returns a subset of the given math::Rect bounded by the box of this widget and all ancestors */
virtual math::Rect getViewport(math::Rect r);

template <class T>
T *getAncestorOfType() {
if (!parent) return NULL;
T *p = dynamic_cast<T*>(parent);
if (p) return p;
return parent->getAncestorOfType<T>();
}

template <class T>
T *getFirstDescendantOfType() {
for (Widget *child : children) {
T *c = dynamic_cast<T*>(child);
if (c) return c;
c = child->getFirstDescendantOfType<T>();
if (c) return c;
}
return NULL;
}

/** Adds widget to list of children.
Gives ownership of widget to this widget instance.
*/
void addChild(Widget *widget);
/** Removes widget from list of children if it exists.
Does not delete widget but transfers ownership to caller
*/
void removeChild(Widget *widget);
/** Removes and deletes all children */
void clearChildren();
/** Recursively finalizes event start/end pairs as needed */
void finalizeEvents();

/** Advances the module by one frame */
virtual void step();
/** Draws to NanoVG context */
virtual void draw(NVGcontext *vg);

// Events

/** Called when a mouse button is pressed over this widget */
virtual void onMouseDown(EventMouseDown &e);
/** Called when a mouse button is released over this widget */
virtual void onMouseUp(EventMouseUp &e);
/** Called when the mouse moves over this widget.
Called on every frame, even if `mouseRel = math::Vec(0, 0)`.
*/
virtual void onMouseMove(EventMouseMove &e);
/** Called when a key is pressed while hovering over this widget */
virtual void onHoverKey(EventHoverKey &e);
/** Called when this widget begins responding to `onMouseMove` events */
virtual void onMouseEnter(EventMouseEnter &e) {}
/** Called when this widget no longer responds to `onMouseMove` events */
virtual void onMouseLeave(EventMouseLeave &e) {}
/** Called when this widget gains focus by responding to the `onMouseDown` event */
virtual void onFocus(EventFocus &e) {}
virtual void onDefocus(EventDefocus &e) {}
/** Called when a printable character is received while this widget is focused */
virtual void onText(EventText &e) {}
/** Called when a key is pressed while this widget is focused */
virtual void onKey(EventKey &e) {}
/** Called when the scroll wheel is moved while the mouse is hovering over this widget */
virtual void onScroll(EventScroll &e);

/** Called when a widget responds to `onMouseDown` for a left button press */
virtual void onDragStart(EventDragStart &e) {}
/** Called when the left button is released and this widget is being dragged */
virtual void onDragEnd(EventDragEnd &e) {}
/** Called when a widget responds to `onMouseMove` and is being dragged */
virtual void onDragMove(EventDragMove &e) {}
/** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */
virtual void onDragEnter(EventDragEnter &e) {}
virtual void onDragLeave(EventDragEnter &e) {}
/** Called when a drag action ends while hovering this widget */
virtual void onDragDrop(EventDragDrop &e) {}
/** Called when an OS selection of files is dragged-and-dropped on this widget */
virtual void onPathDrop(EventPathDrop &e);

/** Called when an event triggers an action */
virtual void onAction(EventAction &e) {}
/** For widgets with some concept of values, called when the value is changed */
virtual void onChange(EventChange &e) {}
/** Called when the zoom level is changed of this widget */
virtual void onZoom(EventZoom &e);

/** Helper function for creating and initializing a Widget with certain arguments (in this case just the position).
In this project, you will find this idiom everywhere, as an easier alternative to constructor arguments, for building a Widget (or a subclass) with a one-liner.
Example:
addChild(Widget::create<SVGWidget>(math::Vec(10, 10)))
*/
template <typename T = Widget>
static T *create(math::Vec pos = math::Vec()) {
T *o = new T();
o->box.pos = pos;
return o;
}
};


/** Instead of inheriting from Widget directly, inherit from VirtualWidget to guarantee that only one copy of Widget's member variables are used by each instance of the Widget hierarchy. /** Instead of inheriting from Widget directly, inherit from VirtualWidget to guarantee that only one copy of Widget's member variables are used by each instance of the Widget hierarchy.
*/ */


+ 128
- 0
include/widgets/Widget.hpp View File

@@ -0,0 +1,128 @@
#pragma once
#include "window.hpp"


namespace rack {


/** A node in the 2D scene graph
Never inherit from Widget directly. Instead, inherit from VirtualWidget declared below.
*/
struct Widget {
/** Stores position and size */
math::Rect box = math::Rect(math::Vec(), math::Vec(INFINITY, INFINITY));
Widget *parent = NULL;
std::list<Widget*> children;
bool visible = true;

virtual ~Widget();

virtual math::Rect getChildrenBoundingBox();
/** Returns `v` transformed into the coordinate system of `relative` */
virtual math::Vec getRelativeOffset(math::Vec v, Widget *relative);
/** Returns `v` transformed into world coordinates */
math::Vec getAbsoluteOffset(math::Vec v) {
return getRelativeOffset(v, NULL);
}
/** Returns a subset of the given math::Rect bounded by the box of this widget and all ancestors */
virtual math::Rect getViewport(math::Rect r);

template <class T>
T *getAncestorOfType() {
if (!parent) return NULL;
T *p = dynamic_cast<T*>(parent);
if (p) return p;
return parent->getAncestorOfType<T>();
}

template <class T>
T *getFirstDescendantOfType() {
for (Widget *child : children) {
T *c = dynamic_cast<T*>(child);
if (c) return c;
c = child->getFirstDescendantOfType<T>();
if (c) return c;
}
return NULL;
}

/** Adds widget to list of children.
Gives ownership of widget to this widget instance.
*/
void addChild(Widget *widget);
/** Removes widget from list of children if it exists.
Does not delete widget but transfers ownership to caller
*/
void removeChild(Widget *widget);
/** Removes and deletes all children */
void clearChildren();
/** Recursively finalizes event start/end pairs as needed */
void finalizeEvents();

/** Advances the module by one frame */
virtual void step();
/** Draws to NanoVG context */
virtual void draw(NVGcontext *vg);

// Events

/** Called when a mouse button is pressed over this widget */
virtual void onMouseDown(EventMouseDown &e);
/** Called when a mouse button is released over this widget */
virtual void onMouseUp(EventMouseUp &e);
/** Called when the mouse moves over this widget.
Called on every frame, even if `mouseRel = math::Vec(0, 0)`.
*/
virtual void onMouseMove(EventMouseMove &e);
/** Called when a key is pressed while hovering over this widget */
virtual void onHoverKey(EventHoverKey &e);
/** Called when this widget begins responding to `onMouseMove` events */
virtual void onMouseEnter(EventMouseEnter &e) {}
/** Called when this widget no longer responds to `onMouseMove` events */
virtual void onMouseLeave(EventMouseLeave &e) {}
/** Called when this widget gains focus by responding to the `onMouseDown` event */
virtual void onFocus(EventFocus &e) {}
virtual void onDefocus(EventDefocus &e) {}
/** Called when a printable character is received while this widget is focused */
virtual void onText(EventText &e) {}
/** Called when a key is pressed while this widget is focused */
virtual void onKey(EventKey &e) {}
/** Called when the scroll wheel is moved while the mouse is hovering over this widget */
virtual void onScroll(EventScroll &e);

/** Called when a widget responds to `onMouseDown` for a left button press */
virtual void onDragStart(EventDragStart &e) {}
/** Called when the left button is released and this widget is being dragged */
virtual void onDragEnd(EventDragEnd &e) {}
/** Called when a widget responds to `onMouseMove` and is being dragged */
virtual void onDragMove(EventDragMove &e) {}
/** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */
virtual void onDragEnter(EventDragEnter &e) {}
virtual void onDragLeave(EventDragEnter &e) {}
/** Called when a drag action ends while hovering this widget */
virtual void onDragDrop(EventDragDrop &e) {}
/** Called when an OS selection of files is dragged-and-dropped on this widget */
virtual void onPathDrop(EventPathDrop &e);

/** Called when an event triggers an action */
virtual void onAction(EventAction &e) {}
/** For widgets with some concept of values, called when the value is changed */
virtual void onChange(EventChange &e) {}
/** Called when the zoom level is changed of this widget */
virtual void onZoom(EventZoom &e);

/** Helper function for creating and initializing a Widget with certain arguments (in this case just the position).
In this project, you will find this idiom everywhere, as an easier alternative to constructor arguments, for building a Widget (or a subclass) with a one-liner.
Example:
addChild(Widget::create<SVGWidget>(math::Vec(10, 10)))
*/
template <typename T = Widget>
static T *create(math::Vec pos = math::Vec()) {
T *o = new T();
o->box.pos = pos;
return o;
}
};


} // namespace rack

+ 27
- 1
include/window.hpp View File

@@ -1,10 +1,12 @@
#pragma once #pragma once
#include <memory>
#define GLEW_STATIC #define GLEW_STATIC
#include <GL/glew.h> #include <GL/glew.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include "nanovg.h"
#include "nanosvg.h"


#include "common.hpp" #include "common.hpp"
#include "widgets.hpp"




#ifdef ARCH_MAC #ifdef ARCH_MAC
@@ -17,6 +19,30 @@
namespace rack { namespace rack {




// Constructing these directly will load from the disk each time. Use the load() functions to load from disk and cache them as long as the shared_ptr is held.

struct Font {
int handle;
Font(const std::string &filename);
~Font();
static std::shared_ptr<Font> load(const std::string &filename);
};

struct Image {
int handle;
Image(const std::string &filename);
~Image();
static std::shared_ptr<Image> load(const std::string &filename);
};

struct SVG {
NSVGimage *handle;
SVG(const std::string &filename);
~SVG();
static std::shared_ptr<SVG> load(const std::string &filename);
};


extern GLFWwindow *gWindow; extern GLFWwindow *gWindow;
extern NVGcontext *gVg; extern NVGcontext *gVg;
extern NVGcontext *gFramebufferVg; extern NVGcontext *gFramebufferVg;


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

@@ -487,7 +487,7 @@ void RackWidget::step() {
// Autosave every 15 seconds // Autosave every 15 seconds
if (gGuiFrame % (60 * 15) == 0) { if (gGuiFrame % (60 * 15) == 0) {
save(asset::local("autosave.vcv")); save(asset::local("autosave.vcv"));
settingsSave(asset::local("settings.json"));
settings::save(asset::local("settings.json"));
} }


Widget::step(); Widget::step();


+ 15
- 13
src/gamepad.cpp View File

@@ -3,13 +3,14 @@




namespace rack { namespace rack {
namespace gamepad {




static const int GAMEPAD_DRIVER = -10;
static GamepadDriver *driver = NULL;
static const int DRIVER = -10;
static Driver *driver = NULL;




void GamepadInputDevice::step() {
void InputDevice::step() {
if (!glfwJoystickPresent(deviceId)) if (!glfwJoystickPresent(deviceId))
return; return;
// Get gamepad state // Get gamepad state
@@ -53,13 +54,13 @@ void GamepadInputDevice::step() {
} }




GamepadDriver::GamepadDriver() {
Driver::Driver() {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
devices[i].deviceId = i; devices[i].deviceId = i;
} }
} }


std::vector<int> GamepadDriver::getInputDeviceIds() {
std::vector<int> Driver::getInputDeviceIds() {
std::vector<int> deviceIds; std::vector<int> deviceIds;
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
if (glfwJoystickPresent(i)) { if (glfwJoystickPresent(i)) {
@@ -69,7 +70,7 @@ std::vector<int> GamepadDriver::getInputDeviceIds() {
return deviceIds; return deviceIds;
} }


std::string GamepadDriver::getInputDeviceName(int deviceId) {
std::string Driver::getInputDeviceName(int deviceId) {
if (!(0 <= deviceId && deviceId < 16)) if (!(0 <= deviceId && deviceId < 16))
return ""; return "";


@@ -77,10 +78,10 @@ std::string GamepadDriver::getInputDeviceName(int deviceId) {
if (name) { if (name) {
return name; return name;
} }
return string::stringf("Gamepad %d (unavailable)", deviceId + 1);
return string::stringf(" %d (unavailable)", deviceId + 1);
} }


MidiInputDevice *GamepadDriver::subscribeInputDevice(int deviceId, MidiInput *midiInput) {
MidiInputDevice *Driver::subscribeInputDevice(int deviceId, MidiInput *midiInput) {
if (!(0 <= deviceId && deviceId < 16)) if (!(0 <= deviceId && deviceId < 16))
return NULL; return NULL;


@@ -88,7 +89,7 @@ MidiInputDevice *GamepadDriver::subscribeInputDevice(int deviceId, MidiInput *mi
return &devices[deviceId]; return &devices[deviceId];
} }


void GamepadDriver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput) {
void Driver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput) {
if (!(0 <= deviceId && deviceId < 16)) if (!(0 <= deviceId && deviceId < 16))
return; return;


@@ -96,12 +97,12 @@ void GamepadDriver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput) {
} }




void gamepadInit() {
driver = new GamepadDriver();
midiDriverAdd(GAMEPAD_DRIVER, driver);
void init() {
driver = new Driver();
midiDriverAdd(DRIVER, driver);
} }


void gamepadStep() {
void step() {
if (!driver) if (!driver)
return; return;
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
@@ -112,4 +113,5 @@ void gamepadStep() {
} }




} // namespace gamepad
} // namespace rack } // namespace rack

+ 15
- 13
src/keyboard.cpp View File

@@ -3,13 +3,14 @@




namespace rack { namespace rack {
namespace keyboard {




static const int KEYBOARD_DRIVER = -11;
static KeyboardDriver *driver = NULL;
static const int DRIVER = -11;
static Driver *driver = NULL;




void KeyboardInputDevice::onKeyPress(int key) {
void InputDevice::onKeyPress(int key) {
int note = -1; int note = -1;
switch (key) { switch (key) {
case GLFW_KEY_Z: note = 0; break; case GLFW_KEY_Z: note = 0; break;
@@ -77,7 +78,7 @@ void KeyboardInputDevice::onKeyPress(int key) {
pressedNotes[key] = note; pressedNotes[key] = note;
} }


void KeyboardInputDevice::onKeyRelease(int key) {
void InputDevice::onKeyRelease(int key) {
auto it = pressedNotes.find(key); auto it = pressedNotes.find(key);
if (it != pressedNotes.end()) { if (it != pressedNotes.end()) {
int note = it->second; int note = it->second;
@@ -92,17 +93,17 @@ void KeyboardInputDevice::onKeyRelease(int key) {
} }




std::vector<int> KeyboardDriver::getInputDeviceIds() {
std::vector<int> Driver::getInputDeviceIds() {
return {0}; return {0};
} }


std::string KeyboardDriver::getInputDeviceName(int deviceId) {
std::string Driver::getInputDeviceName(int deviceId) {
if (deviceId == 0) if (deviceId == 0)
return "QWERTY keyboard (US)"; return "QWERTY keyboard (US)";
return ""; return "";
} }


MidiInputDevice *KeyboardDriver::subscribeInputDevice(int deviceId, MidiInput *midiInput) {
MidiInputDevice *Driver::subscribeInputDevice(int deviceId, MidiInput *midiInput) {
if (deviceId != 0) if (deviceId != 0)
return NULL; return NULL;


@@ -110,7 +111,7 @@ MidiInputDevice *KeyboardDriver::subscribeInputDevice(int deviceId, MidiInput *m
return &device; return &device;
} }


void KeyboardDriver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput) {
void Driver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput) {
if (deviceId != 0) if (deviceId != 0)
return; return;


@@ -118,22 +119,23 @@ void KeyboardDriver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput)
} }




void keyboardInit() {
driver = new KeyboardDriver();
midiDriverAdd(KEYBOARD_DRIVER, driver);
void init() {
driver = new Driver();
midiDriverAdd(DRIVER, driver);
} }


void keyboardPress(int key) {
void press(int key) {
if (!driver) if (!driver)
return; return;
driver->device.onKeyPress(key); driver->device.onKeyPress(key);
} }


void keyboardRelease(int key) {
void release(int key) {
if (!driver) if (!driver)
return; return;
driver->device.onKeyRelease(key); driver->device.onKeyRelease(key);
} }




} // namespace keyboard
} // namespace rack } // namespace rack

+ 8
- 8
src/main.cpp View File

@@ -67,18 +67,18 @@ int main(int argc, char* argv[]) {
engineInit(); engineInit();
rtmidiInit(); rtmidiInit();
bridgeInit(); bridgeInit();
keyboardInit();
gamepadInit();
keyboard::init();
gamepad::init();
windowInit(); windowInit();
appInit(devMode); appInit(devMode);
settingsLoad(asset::local("settings.json"));
settings::load(asset::local("settings.json"));


if (patchFile.empty()) { if (patchFile.empty()) {
// To prevent launch crashes, if Rack crashes between now and 15 seconds from now, the "skipAutosaveOnLaunch" property will remain in settings.json, so that in the next launch, the broken autosave will not be loaded. // To prevent launch crashes, if Rack crashes between now and 15 seconds from now, the "skipAutosaveOnLaunch" property will remain in settings.json, so that in the next launch, the broken autosave will not be loaded.
bool oldSkipAutosaveOnLaunch = gSkipAutosaveOnLaunch;
gSkipAutosaveOnLaunch = true;
settingsSave(asset::local("settings.json"));
gSkipAutosaveOnLaunch = false;
bool oldSkipAutosaveOnLaunch = settings::gSkipAutosaveOnLaunch;
settings::gSkipAutosaveOnLaunch = true;
settings::save(asset::local("settings.json"));
settings::gSkipAutosaveOnLaunch = false;
if (oldSkipAutosaveOnLaunch && osdialog_message(OSDIALOG_INFO, OSDIALOG_YES_NO, "Rack has recovered from a crash, possibly caused by a faulty module in your patch. Clear your patch and start over?")) { if (oldSkipAutosaveOnLaunch && osdialog_message(OSDIALOG_INFO, OSDIALOG_YES_NO, "Rack has recovered from a crash, possibly caused by a faulty module in your patch. Clear your patch and start over?")) {
gRackWidget->lastPath = ""; gRackWidget->lastPath = "";
} }
@@ -101,7 +101,7 @@ int main(int argc, char* argv[]) {


// Destroy namespaces // Destroy namespaces
gRackWidget->save(asset::local("autosave.vcv")); gRackWidget->save(asset::local("autosave.vcv"));
settingsSave(asset::local("settings.json"));
settings::save(asset::local("settings.json"));
appDestroy(); appDestroy();
windowDestroy(); windowDestroy();
bridgeDestroy(); bridgeDestroy();


+ 4
- 2
src/settings.cpp View File

@@ -4,6 +4,7 @@




namespace rack { namespace rack {
namespace settings {




bool gSkipAutosaveOnLaunch = false; bool gSkipAutosaveOnLaunch = false;
@@ -151,7 +152,7 @@ static void settingsFromJson(json_t *rootJ) {
} }




void settingsSave(std::string filename) {
void save(std::string filename) {
INFO("Saving settings %s", filename.c_str()); INFO("Saving settings %s", filename.c_str());
json_t *rootJ = settingsToJson(); json_t *rootJ = settingsToJson();
if (rootJ) { if (rootJ) {
@@ -165,7 +166,7 @@ void settingsSave(std::string filename) {
} }
} }


void settingsLoad(std::string filename) {
void load(std::string filename) {
INFO("Loading settings %s", filename.c_str()); INFO("Loading settings %s", filename.c_str());
FILE *file = fopen(filename.c_str(), "r"); FILE *file = fopen(filename.c_str(), "r");
if (!file) if (!file)
@@ -185,4 +186,5 @@ void settingsLoad(std::string filename) {
} }




} // namespace settings
} // namespace rack } // namespace rack

+ 3
- 4
src/window.cpp View File

@@ -11,7 +11,6 @@
#include "osdialog.h" #include "osdialog.h"


#include "rack.hpp" #include "rack.hpp"
#include "window.hpp"
#include "keyboard.hpp" #include "keyboard.hpp"
#include "gamepad.hpp" #include "gamepad.hpp"


@@ -281,10 +280,10 @@ void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods
// Keyboard MIDI driver // Keyboard MIDI driver
if (!(mods & (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER))) { if (!(mods & (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER))) {
if (action == GLFW_PRESS) { if (action == GLFW_PRESS) {
keyboardPress(key);
keyboard::press(key);
} }
else if (action == GLFW_RELEASE) { else if (action == GLFW_RELEASE) {
keyboardRelease(key);
keyboard::release(key);
} }
} }
} }
@@ -444,7 +443,7 @@ void windowRun() {
cursorPosCallback(gWindow, xpos, ypos); cursorPosCallback(gWindow, xpos, ypos);
} }
mouseButtonStickyPop(); mouseButtonStickyPop();
gamepadStep();
gamepad::step();


// Set window title // Set window title
std::string windowTitle; std::string windowTitle;


Loading…
Cancel
Save