diff --git a/include/engine.hpp b/include/engine.hpp index e91bb81e..af054216 100644 --- a/include/engine.hpp +++ b/include/engine.hpp @@ -135,7 +135,7 @@ Your plugin needs to have a clear purpose for manipulating other modules and wir */ extern std::vector gModules; extern std::vector gWires; -extern bool gCpuMeters; +extern bool gPowerMeter; } // namespace rack diff --git a/include/util/common.hpp b/include/util/common.hpp index ffa16c2f..73c51300 100644 --- a/include/util/common.hpp +++ b/include/util/common.hpp @@ -146,7 +146,6 @@ struct StringCaseInsensitiveCompare { } }; - //////////////////// // Operating-system specific utilities // system.cpp diff --git a/src/Core/MidiIO.cpp b/src/Core/MidiIO.cpp deleted file mode 100644 index 1a2f726e..00000000 --- a/src/Core/MidiIO.cpp +++ /dev/null @@ -1,264 +0,0 @@ -#if 0 -#include -#include -#include "core.hpp" -#include "MidiIO.hpp" - - -using namespace rack; - - -/** - * MidiIO implements the shared functionality of all midi modules, namely: - * + Channel Selection (including helper for storing json) - * + Interface Selection (including helper for storing json) - * + rtMidi initialisation (input or output) - */ -MidiIO::MidiIO(bool isOut) { - channel = -1; - this->isOut = isOut; - - // TODO - // Support MIDI out - assert(!isOut); -}; - -void MidiIO::setChannel(int channel) { - this->channel = channel; -} - -std::unordered_map MidiIO::midiInMap = {}; - -json_t *MidiIO::addBaseJson(json_t *rootJ) { - if (deviceName != "") { - json_object_set_new(rootJ, "interfaceName", json_string(deviceName.c_str())); - json_object_set_new(rootJ, "channel", json_integer(channel)); - } - return rootJ; -} - -void MidiIO::baseFromJson(json_t *rootJ) { - json_t *portNameJ = json_object_get(rootJ, "interfaceName"); - if (portNameJ) { - openDevice(json_string_value(portNameJ)); - } - - json_t *channelJ = json_object_get(rootJ, "channel"); - if (channelJ) { - setChannel(json_integer_value(channelJ)); - } -} - -std::vector MidiIO::getDevices() { - std::vector names = {}; - - if (isOut) { - // TODO - return names; - } - - RtMidiIn *m; - try { - m = new RtMidiIn(); - } - catch (RtMidiError &error) { - warn("Failed to create RtMidiIn: %s", error.getMessage().c_str()); - return names; - } - - for (unsigned int i = 0; i < m->getPortCount(); i++) { - names.push_back(m->getPortName(i)); - } - - if (!isPortOpen()) - delete (m); - - return names; -} - -void MidiIO::openDevice(std::string deviceName) { - - if (this->id > 0 || this->deviceName != "") { - close(); - } - - MidiInWrapper *mw = midiInMap[deviceName]; - - if (!mw) { - try { - mw = new MidiInWrapper(); - midiInMap[deviceName] = mw; - - - for (unsigned int i = 0; i < mw->getPortCount(); i++) { - if (deviceName == mw->getPortName(i)) { - mw->openPort(i); - break; - } - } - - if (!mw->isPortOpen()) { - warn("Failed to create RtMidiIn: No such device %s", deviceName.c_str()); - this->deviceName = ""; - this->id = -1; - return; - } - } - catch (RtMidiError &error) { - warn("Failed to create RtMidiIn: %s", error.getMessage().c_str()); - this->deviceName = ""; - this->id = -1; - return; - } - } - - this->deviceName = deviceName; - - id = midiInMap[deviceName]->add(); - onDeviceChange(); -} - -void MidiIO::setIgnores(bool ignoreSysex, bool ignoreTime, bool ignoreSense) { - bool sy = true, ti = true, se = true; - - midiInMap[deviceName]->ignoresMap[id].midiSysex = ignoreSysex; - midiInMap[deviceName]->ignoresMap[id].midiTime = ignoreTime; - midiInMap[deviceName]->ignoresMap[id].midiSense = ignoreSense; - - for (auto kv : midiInMap[deviceName]->ignoresMap) { - sy = sy && kv.second.midiSysex; - ti = ti && kv.second.midiTime; - se = se && kv.second.midiSense; - } - - midiInMap[deviceName]->ignoreTypes(se, ti, se); - - -} - -std::string MidiIO::getDeviceName() { - return deviceName; -} - -double MidiIO::getMessage(std::vector *msg) { - MidiMessage next_msg = MidiMessage(); - - MidiInWrapper *mw = midiInMap[deviceName]; - - if (!mw) { - warn("Device not opened!: %s", deviceName.c_str()); - return 0; - } - - next_msg.timeStamp = mw->getMessage(&next_msg.bytes); - if (next_msg.bytes.size() > 0) { - for (auto &kv : mw->idMessagesMap) { - - kv.second.push_back(next_msg); - } - } - - - if (mw->idMessagesMap[id].size() > 0) { - next_msg = mw->idMessagesMap[id].front(); - mw->idMessagesMap[id].pop_front(); - } - - *msg = next_msg.bytes; - - return next_msg.timeStamp; -} - -bool MidiIO::isPortOpen() { - return id > 0; -} - -void MidiIO::close() { - - MidiInWrapper *mw = midiInMap[deviceName]; - - if (!mw || id < 0) { - //warn("Trying to close already closed device!"); - return; - } - - setIgnores(); // reset ignore types for this instance - - mw->erase(id); - - if (mw->idMessagesMap.size() == 0) { - mw->closePort(); - midiInMap.erase(deviceName); - delete (mw); - } - - id = -1; - deviceName = ""; -} - - -void MidiItem::onAction(EventAction &e) { - midiModule->resetMidi(); // reset Midi values - midiModule->openDevice(text); -} - -void MidiChoice::onAction(EventAction &e) { - Menu *menu = gScene->createMenu(); - menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round(); - menu->box.size.x = box.size.x; - - { - MidiItem *midiItem = new MidiItem(); - midiItem->midiModule = midiModule; - midiItem->text = ""; - menu->addChild(midiItem); - } - - std::vector deviceNames = midiModule->getDevices(); - for (unsigned int i = 0; i < deviceNames.size(); i++) { - MidiItem *midiItem = new MidiItem(); - midiItem->midiModule = midiModule; - midiItem->text = deviceNames[i]; - menu->addChild(midiItem); - } -} - -void MidiChoice::step() { - if (midiModule->getDeviceName() == "") { - text = "No Device"; - return; - } - std::string name = midiModule->getDeviceName(); - text = ellipsize(name, 15); -} - -void ChannelItem::onAction(EventAction &e) { - midiModule->resetMidi(); // reset Midi values - midiModule->setChannel(channel); -} - -void ChannelChoice::onAction(EventAction &e) { - Menu *menu = gScene->createMenu(); - menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round(); - menu->box.size.x = box.size.x; - - { - ChannelItem *channelItem = new ChannelItem(); - channelItem->midiModule = midiModule; - channelItem->channel = -1; - channelItem->text = "All"; - menu->addChild(channelItem); - } - for (int channel = 0; channel < 16; channel++) { - ChannelItem *channelItem = new ChannelItem(); - channelItem->midiModule = midiModule; - channelItem->channel = channel; - channelItem->text = stringf("%d", channel + 1); - menu->addChild(channelItem); - } -} - -void ChannelChoice::step() { - text = (midiModule->channel >= 0) ? stringf("%d", midiModule->channel + 1) : "All"; -} -#endif \ No newline at end of file diff --git a/src/Core/MidiIO.hpp b/src/Core/MidiIO.hpp deleted file mode 100644 index ed4db49e..00000000 --- a/src/Core/MidiIO.hpp +++ /dev/null @@ -1,206 +0,0 @@ -#if 0 -#include -#include "rack.hpp" - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wsuggest-override" -#include "rtmidi/RtMidi.h" -#pragma GCC diagnostic pop - - -using namespace rack; - - -struct IgnoreFlags { - bool midiSysex = true; - bool midiTime = true; - bool midiSense = true; -}; - -struct MidiMessage { - std::vector bytes; - double timeStamp; - - MidiMessage() : bytes(0), timeStamp(0.0) {}; -}; - -/** - * This class allows to use one instance of rtMidiIn with - * multiple modules. A MidiIn port will be opened only once while multiple - * instances can use it simultaniously, each receiving all its incoming messages. - */ -struct MidiInWrapper : RtMidiIn { - - std::unordered_map> idMessagesMap; - std::unordered_map ignoresMap; - - int uid_c = 0; - - MidiInWrapper() : RtMidiIn() { - idMessagesMap = {}; - }; - - int add() { - int id = ++uid_c; - idMessagesMap[id] = {}; - ignoresMap[id] = IgnoreFlags(); - return id; - } - - void erase(int id) { - idMessagesMap.erase(id); - ignoresMap.erase(id); - } -}; - -/** - * Note: MidiIO is not thread safe which might become - * important in the future - */ -struct MidiIO { -private: - static std::unordered_map midiInMap; - /* TODO: add for midi out*/ - int id = -1; - std::string deviceName = ""; - bool isOut = false; - -public: - int channel; - - - MidiIO(bool isOut = false); - - ~MidiIO() { - close(); - } - - std::vector getDevices(); - - void openDevice(std::string deviceName); - - void setIgnores(bool ignoreSysex = true, bool ignoreTime = true, bool ignoreSense = true); - - std::string getDeviceName(); - - void setChannel(int channel); - - double getMessage(std::vector *msg); - - json_t *addBaseJson(json_t *rootJ); - - void baseFromJson(json_t *rootJ); - - bool isPortOpen(); - - void close(); - - /* called when midi port is set */ - virtual void resetMidi() {} - - /* called if a user switches or sets the device (and after this device is initialised)*/ - virtual void onDeviceChange() {} -}; - - -struct TransitionSmoother { - enum TransitionFunction { - SMOOTHSTEP, - EXP, - LIN, - }; - - enum TransitionMode { - DELTA, - CONST, - }; - - float start; - float end; - float x; - float delta; - float step; - TransitionFunction t; - - - void set(float start, float end, int l = 1500, TransitionFunction t = LIN, TransitionMode m = DELTA, bool reset = true) { - this->start = start; - this->end = end; - this->delta = end - start; - this->t = t; - - if (reset || x >= 1) { - this->x = 0; - } - - switch (m) { - case DELTA: - /* If the change is smaller, the transition phase is longer */ - this->step = delta > 0 ? delta / l : -delta / l; - break; - case CONST: - this->step = 1.0 / l; - break; - } - - } - - float next() { - float next = start; - - x += step; - if (x >= 1) - return end; - - switch (t) { - case SMOOTHSTEP: - next += delta * x * x * (3 - 2 * x); - break; - case EXP: - next += delta * x * x; - break; - case LIN: - next += delta * x; - break; - } - - if ((delta > 0 && next > end) || (delta <= 0 && next < end)) - return end; - - return next;; - } -}; - - -////////////////////// -// MIDI module widgets -////////////////////// - -struct MidiItem : MenuItem { - MidiIO *midiModule; - - void onAction(EventAction &e) override; -}; - -struct MidiChoice : ChoiceButton { - MidiIO *midiModule; - - void step() override; - void onAction(EventAction &e) override; -}; - -struct ChannelItem : MenuItem { - MidiIO *midiModule; - int channel; - - void onAction(EventAction &e) override; -}; - -struct ChannelChoice : ChoiceButton { - MidiIO *midiModule; - - void step() override; - void onAction(EventAction &e) override; -}; - -#endif \ No newline at end of file diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 861a099f..d27f8a2a 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -190,7 +190,7 @@ void ModuleWidget::draw(NVGcontext *vg) { Widget::draw(vg); // CPU meter - if (module && gCpuMeters) { + if (module && gPowerMeter) { nvgBeginPath(vg); nvgRect(vg, 0, box.size.y - 20, diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index f68e630d..4173a33a 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -165,7 +165,7 @@ void RackWidget::revert() { } void RackWidget::disconnect() { - if (!osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK_CANCEL, "Clear all patch cables?")) + if (!osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK_CANCEL, "Remove all patch cables?")) return; for (Widget *w : moduleContainer->children) { diff --git a/src/app/Toolbar.cpp b/src/app/Toolbar.cpp index e42b9d7f..c4d45e98 100644 --- a/src/app/Toolbar.cpp +++ b/src/app/Toolbar.cpp @@ -89,13 +89,13 @@ struct DisconnectCablesButton : TooltipIconButton { } }; -struct MeterButton : TooltipIconButton { - MeterButton() { +struct PowerMeterButton : TooltipIconButton { + PowerMeterButton() { setSVG(SVG::load(assetGlobal("res/icons/noun_305536_cc.svg"))); tooltipText = "Toggle power meter (see manual for explanation)"; } void onAction(EventAction &e) override { - gCpuMeters ^= true; + gPowerMeter ^= true; } }; @@ -175,7 +175,7 @@ Toolbar::Toolbar() { layout->addChild(wireTensionSlider); layout->addChild(new SampleRateButton()); - layout->addChild(new MeterButton()); + layout->addChild(new PowerMeterButton()); struct ZoomSlider : Slider { void onAction(EventAction &e) override { diff --git a/src/engine.cpp b/src/engine.cpp index e383a433..08b850b3 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 = false; +bool gPowerMeter = false; static bool running = false; static float sampleRate = 44100.f; @@ -90,7 +90,7 @@ static void engineStep() { // Step modules for (Module *module : gModules) { std::chrono::high_resolution_clock::time_point startTime; - if (gCpuMeters) { + if (gPowerMeter) { startTime = std::chrono::high_resolution_clock::now(); module->step(); diff --git a/src/settings.cpp b/src/settings.cpp index 1c29c334..5f02195f 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -67,6 +67,9 @@ static json_t *settingsToJson() { // moduleBrowser json_object_set_new(rootJ, "moduleBrowser", appModuleBrowserToJson()); + // powerMeter + json_object_set_new(rootJ, "powerMeter", json_boolean(gPowerMeter)); + return rootJ; } @@ -132,9 +135,14 @@ static void settingsFromJson(json_t *rootJ) { skipAutosaveOnLaunch = json_boolean_value(skipAutosaveOnLaunchJ); // moduleBrowser - json_t * moduleBrowserJ = json_object_get(rootJ, "moduleBrowser"); + json_t *moduleBrowserJ = json_object_get(rootJ, "moduleBrowser"); if (moduleBrowserJ) appModuleBrowserFromJson(moduleBrowserJ); + + // powerMeter + json_t *powerMeterJ = json_object_get(rootJ, "powerMeter"); + if (powerMeterJ) + gPowerMeter = json_boolean_value(powerMeterJ); }