diff --git a/include/gamepad.hpp b/include/gamepad.hpp index cf1e06e6..410225bc 100644 --- a/include/gamepad.hpp +++ b/include/gamepad.hpp @@ -1,5 +1,7 @@ #pragma once +#include "util/common.hpp" +#include "midi.hpp" namespace rack { @@ -7,7 +9,24 @@ namespace rack { const int GAMEPAD_DRIVER = -10; + +struct GamepadInputDevice : MidiInputDevice { + int device; +}; + + +struct GamepadInputDriver : MidiInputDriver { + GamepadInputDevice gamepadInputDevices[16]; + + GamepadInputDriver(); + int getDeviceCount() override; + std::string getDeviceName(int device) override; + MidiInputDevice *getDevice(int device) override; +}; + + void gamepadStep(); +MidiInputDriver *gamepadGetInputDriver(); } // namespace rack diff --git a/include/midi.hpp b/include/midi.hpp index 6800ca07..bb573ad7 100644 --- a/include/midi.hpp +++ b/include/midi.hpp @@ -30,14 +30,47 @@ struct MidiMessage { }; //////////////////// -// MidiIO +// MidiIODevice +//////////////////// + +struct MidiIODevice { + virtual ~MidiIODevice() {} +}; + +struct MidiInput; + +struct MidiInputDevice : MidiIODevice { + std::set subscribed; + void subscribe(MidiInput *midiInput); + void unsubscribe(MidiInput *midiInput); + void onMessage(MidiMessage message); +}; + +struct MidiOutputDevice : MidiIODevice { + // TODO +}; + +//////////////////// +// MidiIODriver //////////////////// -struct MidiInputDriver; -struct MidiOutputDriver; -struct MidiInputDevice; -struct MidiOutputDevice; +struct MidiIODriver { + virtual ~MidiIODriver() {} + virtual int getDeviceCount() = 0; + virtual std::string getDeviceName(int device) = 0; +}; +struct MidiInputDriver : MidiIODriver { + virtual MidiInputDevice *getDevice(int device) = 0; +}; + +struct MidiOutputDriver : MidiIODriver { + virtual MidiOutputDevice *getDevice(int device) = 0; +}; + +//////////////////// +// MidiIO +//////////////////// struct MidiIO { int driver = -1; @@ -104,43 +137,5 @@ struct MidiOutput : MidiIO { void setDevice(int device) override; }; -//////////////////// -// MidiIODriver -//////////////////// - -struct MidiIODriver { - virtual ~MidiIODriver() {} - virtual int getDeviceCount() = 0; - virtual std::string getDeviceName(int device) = 0; -}; - -struct MidiInputDriver : MidiIODriver { - virtual MidiInputDevice *getDevice(int device) = 0; -}; - -struct MidiOutputDriver : MidiIODriver { - virtual MidiOutputDevice *getDevice(int device) = 0; -}; - -//////////////////// -// MidiIODevice -//////////////////// - -struct MidiIODevice { - virtual ~MidiIODevice() {} -}; - -struct MidiInputDevice : MidiIODevice { - std::set subscribed; - void subscribe(MidiInput *midiInput); - /** Deletes itself if nothing is subscribed */ - void unsubscribe(MidiInput *midiInput); - void onMessage(MidiMessage message); -}; - -struct MidiOutputDevice : MidiIODevice { - // TODO -}; - } // namespace rack diff --git a/include/util/common.hpp b/include/util/common.hpp index c3168478..f09f18b5 100644 --- a/include/util/common.hpp +++ b/include/util/common.hpp @@ -162,10 +162,17 @@ void systemOpenBrowser(std::string url); void loggerInit(); void loggerDestroy(); -void debug(const char *format, ...); -void info(const char *format, ...); -void warn(const char *format, ...); -void fatal(const char *format, ...); +/** Do not use this function directly. Use the macros below. */ +void loggerLog(const char *level, const char *file, int line, const char *format, ...); +/** Example usage: + debug("error: %d", errno); +will print something like + [0.123 debug myfile.cpp:45] error: 67 +*/ +#define debug(format, ...) loggerLog("debug", __FILE__, __LINE__, format, ##__VA_ARGS__) +#define info(format, ...) loggerLog("info", __FILE__, __LINE__, format, ##__VA_ARGS__) +#define warn(format, ...) loggerLog("warn", __FILE__, __LINE__, format, ##__VA_ARGS__) +#define fatal(format, ...) loggerLog("fatal", __FILE__, __LINE__, format, ##__VA_ARGS__) //////////////////// // Thread functions diff --git a/src/engine.cpp b/src/engine.cpp index e2da89ea..6fbeef34 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -17,7 +17,7 @@ namespace rack { bool gPaused = false; std::vector gModules; std::vector gWires; -bool gCpuMeters = true; +bool gCpuMeters = false; static bool running = false; static float sampleRate; @@ -87,7 +87,10 @@ static void engineStep() { // Step modules for (Module *module : gModules) { - auto startTime = std::chrono::high_resolution_clock::now(); + std::chrono::high_resolution_clock::time_point startTime; + if (gCpuMeters) { + startTime = std::chrono::high_resolution_clock::now(); + } module->step(); diff --git a/src/gamepad.cpp b/src/gamepad.cpp index 0c1ea1c6..e30ade2b 100644 --- a/src/gamepad.cpp +++ b/src/gamepad.cpp @@ -6,6 +6,34 @@ namespace rack { +GamepadInputDriver::GamepadInputDriver() { + for (int i = 0; i < 16; i++) { + gamepadInputDevices[i].device = i; + } +} + +int GamepadInputDriver::getDeviceCount() { + return 16; +} + +std::string GamepadInputDriver::getDeviceName(int device) { + assert(0 <= device && device < 16); + const char *name = glfwGetJoystickName(device); + if (name) { + return name; + } + return stringf("Gamepad %d (unavailable)", device + 1); +} + +MidiInputDevice *GamepadInputDriver::getDevice(int device) { + assert(0 <= device && device < 16); + return &gamepadInputDevices[device]; +} + + +static GamepadInputDriver *gamepadInputDriver = NULL; + + void gamepadStep() { for (int i = 0; i < 16; i++) { if (glfwJoystickPresent(i)) { @@ -19,5 +47,12 @@ void gamepadStep() { } } +MidiInputDriver *gamepadGetInputDriver() { + if (!gamepadInputDriver) { + gamepadInputDriver = new GamepadInputDriver(); + } + return gamepadInputDriver; +} + } // namespace rack diff --git a/src/midi.cpp b/src/midi.cpp index c62125f4..5c6ec348 100644 --- a/src/midi.cpp +++ b/src/midi.cpp @@ -7,6 +7,35 @@ namespace rack { +//////////////////// +// MidiIODevice +//////////////////// + +void MidiInputDevice::subscribe(MidiInput *midiInput) { + subscribed.insert(midiInput); +} + +void MidiInputDevice::unsubscribe(MidiInput *midiInput) { + auto it = subscribed.find(midiInput); + if (it != subscribed.end()) + subscribed.erase(it); + + if (subscribed.size() == 0) { + warn("TODO: Fix memory leak"); + } +} + +void MidiInputDevice::onMessage(MidiMessage message) { + for (MidiInput *midiInput : subscribed) { + midiInput->onMessage(message); + } +} + +//////////////////// +// MidiIODriver +//////////////////// + + //////////////////// // MidiIO //////////////////// @@ -94,6 +123,12 @@ void MidiInput::setDriver(int driver) { if (driver >= 0) { midiInputDriver = rtmidiGetInputDriver(driver); } + else if (driver == BRIDGE_DRIVER) { + // TODO + } + else if (driver == GAMEPAD_DRIVER) { + midiInputDriver = gamepadGetInputDriver(); + } this->driver = driver; } @@ -165,30 +200,5 @@ void MidiOutput::setDevice(int device) { // TODO } -//////////////////// -// MidiIODevice -//////////////////// - -void MidiInputDevice::subscribe(MidiInput *midiInput) { - subscribed.insert(midiInput); -} - -void MidiInputDevice::unsubscribe(MidiInput *midiInput) { - auto it = subscribed.find(midiInput); - if (it != subscribed.end()) - subscribed.erase(it); - - // Delete self if nothing is subscribed - if (subscribed.size() == 0) { - delete this; - } -} - -void MidiInputDevice::onMessage(MidiMessage message) { - for (MidiInput *midiInput : subscribed) { - midiInput->onMessage(message); - } -} - } // namespace rack diff --git a/src/util/logger.cpp b/src/util/logger.cpp index e1e362b2..893e3146 100644 --- a/src/util/logger.cpp +++ b/src/util/logger.cpp @@ -7,10 +7,11 @@ namespace rack { static FILE *logFile = stderr; -static auto startTime = std::chrono::high_resolution_clock::now(); +static std::chrono::high_resolution_clock::time_point startTime; void loggerInit() { + startTime = std::chrono::high_resolution_clock::now(); #ifdef RELEASE std::string logFilename = assetLocal("log.txt"); logFile = fopen(logFilename.c_str(), "w"); @@ -23,44 +24,55 @@ void loggerDestroy() { #endif } -static void printTimestamp() { -} +static void loggerLogVa(const char *level, const char *file, int line, const char *format, va_list args) { -static void printLog(const char *type, const char *format, va_list args) { auto nowTime = std::chrono::high_resolution_clock::now(); int duration = std::chrono::duration_cast(nowTime - startTime).count(); - printTimestamp(); - fprintf(logFile, "[%.03f %s] ", duration / 1000.0, type); + fprintf(logFile, "[%.03f %s %s:%d] ", duration / 1000.0, level, file, line); vfprintf(logFile, format, args); fprintf(logFile, "\n"); fflush(logFile); } +void loggerLog(const char *level, const char *file, int line, const char *format, ...) { + va_list args; + va_start(args, format); + loggerLogVa(level, file, line, format, args); + va_end(args); +} + +/** Deprecated. Included for ABI compatibility */ + +#undef debug +#undef info +#undef warn +#undef fatal + void debug(const char *format, ...) { va_list args; va_start(args, format); - printLog("debug", format, args); + loggerLogVa("debug", "", 0, format, args); va_end(args); } void info(const char *format, ...) { va_list args; va_start(args, format); - printLog("info", format, args); + loggerLogVa("info", "", 0, format, args); va_end(args); } void warn(const char *format, ...) { va_list args; va_start(args, format); - printLog("warn", format, args); + loggerLogVa("warn", "", 0, format, args); va_end(args); } void fatal(const char *format, ...) { va_list args; va_start(args, format); - printLog("fatal", format, args); + loggerLogVa("fatal", "", 0, format, args); va_end(args); }