From 2010b77f66020494f4afc1fe4451b82d91841135 Mon Sep 17 00:00:00 2001 From: Michael Dewberry Date: Sun, 17 Sep 2023 15:22:31 -0400 Subject: [PATCH] Create GridConsumerBase for shared implementation of IGridConsumer; persist virtual grid mirror settings in patch --- .../core/GridConnection/GridConnection.cpp | 18 ++- .../core/GridConnection/GridConnection.hpp | 22 ++-- .../GridConnection/GridConnectionMenu.cpp | 6 +- .../GridConnection/GridConnectionMenu.hpp | 2 +- .../core/GridConnection/GridConsumerBase.cpp | 106 ++++++++++++++++++ .../core/GridConnection/GridConsumerBase.hpp | 30 +++++ src/common/core/LibAVR32Module.cpp | 102 +++-------------- src/common/core/LibAVR32Module.hpp | 26 ++--- src/virtualgrid/VirtualGridModule.cpp | 69 ++++-------- src/virtualgrid/VirtualGridModule.hpp | 2 +- 10 files changed, 203 insertions(+), 180 deletions(-) create mode 100644 src/common/core/GridConnection/GridConsumerBase.cpp create mode 100644 src/common/core/GridConnection/GridConsumerBase.hpp diff --git a/src/common/core/GridConnection/GridConnection.cpp b/src/common/core/GridConnection/GridConnection.cpp index 09cc317..c3ad4ad 100644 --- a/src/common/core/GridConnection/GridConnection.cpp +++ b/src/common/core/GridConnection/GridConnection.cpp @@ -1,15 +1,11 @@ #include "GridConnection.hpp" -Grid::~Grid() -{ -} - void GridConnectionManager::registerGrid(Grid* grid) { grids.insert(grid); // Check if there's a consumer with a saved connection looking for this grid - GridConsumer* consumerToConnect = nullptr; + IGridConsumer* consumerToConnect = nullptr; for (auto consumer : consumers) { if (!isConnected(consumer) && grid->getDevice().id == consumer->gridGetLastDeviceId(true)) @@ -25,7 +21,7 @@ void GridConnectionManager::registerGrid(Grid* grid) } } -void GridConnectionManager::registerGridConsumer(GridConsumer* consumer) +void GridConnectionManager::registerGridConsumer(IGridConsumer* consumer) { consumers.insert(consumer); @@ -66,13 +62,13 @@ void GridConnectionManager::deregisterGrid(std::string id, bool deleteGrid) } } -void GridConnectionManager::deregisterGridConsumer(GridConsumer* consumer) +void GridConnectionManager::deregisterGridConsumer(IGridConsumer* consumer) { disconnect(consumer); consumers.erase(consumer); } -void GridConnectionManager::connect(Grid* grid, GridConsumer* consumer) +void GridConnectionManager::connect(Grid* grid, IGridConsumer* consumer) { disconnect(consumer, true); disconnect(grid, true); @@ -82,7 +78,7 @@ void GridConnectionManager::connect(Grid* grid, GridConsumer* consumer) consumer->gridConnected(grid); } -bool GridConnectionManager::isConnected(GridConsumer* consumer) +bool GridConnectionManager::isConnected(IGridConsumer* consumer) { return consumerToGridMap.find(consumer) != consumerToGridMap.end(); } @@ -100,7 +96,7 @@ void GridConnectionManager::disconnect(Grid* grid, bool ownerChanged) auto iter = idToConsumerMap.find(grid->getDevice().id); if (iter != idToConsumerMap.end()) { - GridConsumer* consumer = iter->second; + auto consumer = iter->second; consumer->gridDisconnected(ownerChanged); idToConsumerMap.erase(grid->getDevice().id); consumerToGridMap.erase(consumer); @@ -108,7 +104,7 @@ void GridConnectionManager::disconnect(Grid* grid, bool ownerChanged) } } -void GridConnectionManager::disconnect(GridConsumer* consumer, bool ownerChanged) +void GridConnectionManager::disconnect(IGridConsumer* consumer, bool ownerChanged) { if (consumer) { diff --git a/src/common/core/GridConnection/GridConnection.hpp b/src/common/core/GridConnection/GridConnection.hpp index aa411ac..d12b335 100644 --- a/src/common/core/GridConnection/GridConnection.hpp +++ b/src/common/core/GridConnection/GridConnection.hpp @@ -9,7 +9,7 @@ struct SerialOscInterface; struct Grid { - virtual ~Grid(); + virtual ~Grid() {} virtual const MonomeDevice& getDevice() = 0; virtual void updateRow(int x_offset, int y, uint8_t bitfield) = 0; virtual void updateQuadrant(int x, int y, uint8_t* leds) = 0; @@ -18,8 +18,9 @@ struct Grid virtual bool isHardware() = 0; }; -struct GridConsumer +struct IGridConsumer { + virtual ~IGridConsumer() {} virtual void gridConnected(Grid* grid) = 0; virtual void gridDisconnected(bool ownerChanged) = 0; virtual std::string gridGetCurrentDeviceId() = 0; @@ -27,22 +28,21 @@ struct GridConsumer virtual void gridButtonEvent(int x, int y, bool state) = 0; virtual void encDeltaEvent(int n, int d) = 0; virtual Grid* gridGetDevice() = 0; - virtual ~GridConsumer() {}; }; struct GridConnectionManager final { // Only call these from the UI thread void registerGrid(Grid* grid); - void registerGridConsumer(GridConsumer* consumer); + void registerGridConsumer(IGridConsumer* consumer); void deregisterGrid(std::string id, bool deleteGrid = false); - void deregisterGridConsumer(GridConsumer* consumer); + void deregisterGridConsumer(IGridConsumer* consumer); - void connect(Grid* grid, GridConsumer* consumer); - bool isConnected(GridConsumer* consumer); + void connect(Grid* grid, IGridConsumer* consumer); + bool isConnected(IGridConsumer* consumer); bool isConnected(std::string id); void disconnect(Grid* grid, bool ownerChanged = false); - void disconnect(GridConsumer* consumer, bool ownerChanged = false); + void disconnect(IGridConsumer* consumer, bool ownerChanged = false); void dispatchButtonMessage(MonomeDevice* device, int x, int y, bool state); void dispatchEncDeltaMessage(MonomeDevice* device, int n, int d); @@ -58,8 +58,8 @@ struct GridConnectionManager final GridConnectionManager(GridConnectionManager&&) = delete; GridConnectionManager&& operator=(const GridConnectionManager&&) = delete; - std::set consumers; + std::set consumers; std::set grids; - std::map idToConsumerMap; - std::map consumerToGridMap; + std::map idToConsumerMap; + std::map consumerToGridMap; }; \ No newline at end of file diff --git a/src/common/core/GridConnection/GridConnectionMenu.cpp b/src/common/core/GridConnection/GridConnectionMenu.cpp index 4a41ac8..7463f2b 100644 --- a/src/common/core/GridConnection/GridConnectionMenu.cpp +++ b/src/common/core/GridConnection/GridConnectionMenu.cpp @@ -6,7 +6,7 @@ using namespace rack; struct NewConnectGridItem : rack::ui::MenuItem { Grid* grid; - GridConsumer* consumer; + IGridConsumer* consumer; ActionQueue* actionQueue; void onAction(const rack::event::Action& e) override @@ -22,7 +22,7 @@ struct NewConnectGridItem : rack::ui::MenuItem } }; -void menuUserReacquireGrid(GridConsumer* consumer, std::string lastDeviceId, ActionQueue* actionQueue) +void menuUserReacquireGrid(IGridConsumer* consumer, std::string lastDeviceId, ActionQueue* actionQueue) { for (Grid* grid : GridConnectionManager::get().getGrids()) { @@ -41,7 +41,7 @@ void menuUserReacquireGrid(GridConsumer* consumer, std::string lastDeviceId, Act } } -void appendDeviceConnectionMenu(rack::Menu* menu, GridConsumer* consumer, ActionQueue* actionQueue, bool hardwareOnly) +void appendDeviceConnectionMenu(rack::Menu* menu, IGridConsumer* consumer, ActionQueue* actionQueue, bool hardwareOnly) { std::string currentConnectedDeviceId = consumer->gridGetCurrentDeviceId(); std::string lastConnectedDeviceId = consumer->gridGetLastDeviceId(false); diff --git a/src/common/core/GridConnection/GridConnectionMenu.hpp b/src/common/core/GridConnection/GridConnectionMenu.hpp index d4d3be1..b624214 100644 --- a/src/common/core/GridConnection/GridConnectionMenu.hpp +++ b/src/common/core/GridConnection/GridConnectionMenu.hpp @@ -4,4 +4,4 @@ #include "GridConnection.hpp" #include "ActionQueue.hpp" -void appendDeviceConnectionMenu(rack::Menu* menu, GridConsumer* consumer, ActionQueue* queue, bool hardwareOnly = false); \ No newline at end of file +void appendDeviceConnectionMenu(rack::Menu* menu, IGridConsumer* consumer, ActionQueue* queue, bool hardwareOnly = false); \ No newline at end of file diff --git a/src/common/core/GridConnection/GridConsumerBase.cpp b/src/common/core/GridConnection/GridConsumerBase.cpp new file mode 100644 index 0000000..e95e01c --- /dev/null +++ b/src/common/core/GridConnection/GridConsumerBase.cpp @@ -0,0 +1,106 @@ +#include "GridConsumerBase.hpp" + +GridConsumerBase::GridConsumerBase() + : lastConnectedDeviceId("") + , currentConnectedDeviceId("") + , gridConnection(nullptr) +{ + +} + +void GridConsumerBase::gridConnected(Grid* newConnection) +{ + gridConnection = newConnection; + if (gridConnection) + { + std::string id = gridConnection->getDevice().id; + lastConnectedDeviceId = id; + currentConnectedDeviceId = id; + connectionOwned = true; + } +} + +void GridConsumerBase::gridDisconnected(bool ownerChanged) +{ + gridConnection = nullptr; + currentConnectedDeviceId = ""; + + if (ownerChanged) + { + connectionOwned = false; + } +} + +std::string GridConsumerBase::gridGetCurrentDeviceId() +{ + return currentConnectedDeviceId; +} + +std::string GridConsumerBase::gridGetLastDeviceId(bool owned) +{ + if (owned && !connectionOwned) + { + return ""; + } + + return lastConnectedDeviceId; +} + +Grid* GridConsumerBase::gridGetDevice() +{ + return gridConnection; +} + +void GridConsumerBase::userReacquireGrid() +{ + if (lastConnectedDeviceId != "" && gridConnection == nullptr) + { + for (Grid* grid : GridConnectionManager::get().getGrids()) + { + if (gridGetLastDeviceId(false) == grid->getDevice().id) + { + GridConnectionManager::get().connect(grid, this); + return; + } + } + } +} + +void GridConsumerBase::toggleGridConnection(Grid* grid) +{ + if (gridConnection == grid) + { + GridConnectionManager::get().disconnect(this, true); + lastConnectedDeviceId = ""; + } + else + { + GridConnectionManager::get().connect(grid, this); + } +} + +void GridConsumerBase::saveGridConnectionToJson(json_t* rootJ) +{ + std::string deviceId = lastConnectedDeviceId; + if (gridConnection) + { + deviceId = gridConnection->getDevice().id; + } + json_object_set_new(rootJ, "connectedDeviceId", json_string(deviceId.c_str())); + json_object_set_new(rootJ, "connectionOwned", json_boolean(connectionOwned)); +} + +void GridConsumerBase::loadGridConnectionFromJson(json_t* rootJ) +{ + json_t* id = json_object_get(rootJ, "connectedDeviceId"); + if (id) + { + lastConnectedDeviceId = json_string_value(id); + } + + json_t* owned = json_object_get(rootJ, "connectionOwned"); + if (owned) + { + connectionOwned = json_boolean_value(owned); + } +} \ No newline at end of file diff --git a/src/common/core/GridConnection/GridConsumerBase.hpp b/src/common/core/GridConnection/GridConsumerBase.hpp new file mode 100644 index 0000000..828adbe --- /dev/null +++ b/src/common/core/GridConnection/GridConsumerBase.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "GridConnection.hpp" +#include "rack.hpp" + +struct GridConsumerBase : public IGridConsumer +{ + // IGridConsumer partial implementation; child classes implement gridButtonEvent/encDeltaEvent + void gridConnected(Grid* grid) override; + void gridDisconnected(bool ownerChanged) override; + std::string gridGetCurrentDeviceId() override; + std::string gridGetLastDeviceId(bool owned) override; + Grid* gridGetDevice() override; + + GridConsumerBase(); + virtual ~GridConsumerBase() {}; + + void userReacquireGrid(); + + void saveGridConnectionToJson(json_t* rootJ); + void loadGridConnectionFromJson(json_t* rootJ); + + std::string lastConnectedDeviceId; + std::string currentConnectedDeviceId; + bool connectionOwned; + +protected: + void toggleGridConnection(Grid* grid); + Grid* gridConnection; +}; \ No newline at end of file diff --git a/src/common/core/LibAVR32Module.cpp b/src/common/core/LibAVR32Module.cpp index 81bf3e4..1de510a 100644 --- a/src/common/core/LibAVR32Module.cpp +++ b/src/common/core/LibAVR32Module.cpp @@ -4,16 +4,12 @@ #include LibAVR32Module::LibAVR32Module(std::string firmwarePrefix, std::string defaultFirmwareName) -: lastConnectedDeviceId("") -, currentConnectedDeviceId("") -, firmwarePrefix(firmwarePrefix) -, firmwareName(defaultFirmwareName) -, defaultFirmwareName(defaultFirmwareName) -, usbParamId(-1) -, theme(GridTheme::Yellow) + : firmwarePrefix(firmwarePrefix) + , firmwareName(defaultFirmwareName) + , defaultFirmwareName(defaultFirmwareName) + , theme(GridTheme::Yellow) + , usbParamId(-1) { - gridConnection = nullptr; - // make sure serialosc is fully initialized by the time // the user needs to interact with it SerialOscInterface::get(); @@ -44,14 +40,10 @@ void LibAVR32Module::gridConnected(Grid* newConnection) firmware.serialConnectionChange(false, 0, 0, 0, 0); } - gridConnection = newConnection; + GridConsumerBase::gridConnected(newConnection); + if (gridConnection) { - std::string id = gridConnection->getDevice().id; - lastConnectedDeviceId = id; - currentConnectedDeviceId = id; - connectionOwned = true; - auto d = gridConnection->getDevice(); if (d.type == "monome arc 2") { @@ -75,13 +67,9 @@ void LibAVR32Module::gridConnected(Grid* newConnection) void LibAVR32Module::gridDisconnected(bool ownerChanged) { - gridConnection = nullptr; - currentConnectedDeviceId = ""; + GridConsumerBase::gridDisconnected(ownerChanged); + firmware.serialConnectionChange(false, 0, 0, 0, 0); - if (ownerChanged) - { - connectionOwned = false; - } if (usbParamId >= 0) { @@ -151,59 +139,11 @@ void LibAVR32Module::encDeltaEvent(int n, int d) } } -std::string LibAVR32Module::gridGetCurrentDeviceId() -{ - return currentConnectedDeviceId; -} - -std::string LibAVR32Module::gridGetLastDeviceId(bool owned) -{ - if (owned && !connectionOwned) - { - return ""; - } - - return lastConnectedDeviceId; -} - -Grid* LibAVR32Module::gridGetDevice() -{ - return gridConnection; -} - -void LibAVR32Module::userReacquireGrid() -{ - if (lastConnectedDeviceId != "" && gridConnection == nullptr) - { - for (Grid* grid : GridConnectionManager::get().getGrids()) - { - if (gridGetLastDeviceId(false) == grid->getDevice().id) - { - GridConnectionManager::get().connect(grid, this); - return; - } - } - } -} - void LibAVR32Module::userToggleGridConnection(Grid* grid) { audioThreadActions.push([this, grid]() { this->toggleGridConnection(grid); }); } -void LibAVR32Module::toggleGridConnection(Grid* grid) -{ - if (gridConnection == grid) - { - GridConnectionManager::get().disconnect(this, true); - lastConnectedDeviceId = ""; - } - else - { - GridConnectionManager::get().connect(grid, this); - } -} - void LibAVR32Module::readSerialMessages() { uint8_t* msg; @@ -361,19 +301,13 @@ void LibAVR32Module::process(const ProcessArgs& args) json_t* LibAVR32Module::dataToJson() { - std::string deviceId = lastConnectedDeviceId; - if (gridConnection) - { - deviceId = gridConnection->getDevice().id; - } - json_t* rootJ = json_object(); json_object_set_new(rootJ, "firmwareName", json_string(firmwareName.c_str())); - json_object_set_new(rootJ, "connectedDeviceId", json_string(deviceId.c_str())); - json_object_set_new(rootJ, "connectionOwned", json_boolean(connectionOwned)); json_object_set_new(rootJ, "inputRate", json_integer(inputRate)); json_object_set_new(rootJ, "outputRate", json_integer(outputRate)); + saveGridConnectionToJson(rootJ); + void* data = 0; uint32_t size = 0; @@ -394,6 +328,8 @@ json_t* LibAVR32Module::dataToJson() void LibAVR32Module::dataFromJson(json_t* rootJ) { + loadGridConnectionFromJson(rootJ); + json_t* jsonFirmwareName = json_object_get(rootJ, "firmwareName"); std::string newFirmwareName = jsonFirmwareName ? json_string_value(jsonFirmwareName) : defaultFirmwareName; @@ -402,18 +338,6 @@ void LibAVR32Module::dataFromJson(json_t* rootJ) reloadFirmware(false, newFirmwareName); } - json_t* id = json_object_get(rootJ, "connectedDeviceId"); - if (id) - { - lastConnectedDeviceId = json_string_value(id); - } - - json_t* owned = json_object_get(rootJ, "connectionOwned"); - if (owned) - { - connectionOwned = json_boolean_value(owned); - } - void* data = 0; uint32_t size = 0; json_t* jd; diff --git a/src/common/core/LibAVR32Module.hpp b/src/common/core/LibAVR32Module.hpp index dc5186b..25813be 100644 --- a/src/common/core/LibAVR32Module.hpp +++ b/src/common/core/LibAVR32Module.hpp @@ -1,5 +1,6 @@ #include "FirmwareManager.hpp" #include "GridConnection.hpp" +#include "GridConsumerBase.hpp" #include "VirtualGridTheme.hpp" #include "rack.hpp" #include "ActionQueue.hpp" @@ -30,7 +31,7 @@ struct GridConnection; -struct LibAVR32Module : rack::engine::Module, GridConsumer +struct LibAVR32Module : rack::engine::Module, GridConsumerBase { FirmwareManager firmware; @@ -47,28 +48,21 @@ struct LibAVR32Module : rack::engine::Module, GridConsumer virtual void processInputs(const ProcessArgs& args) = 0; virtual void processOutputs(const ProcessArgs& args) = 0; - // GridConsumer methods - void gridConnected(Grid* grid) override; - void gridDisconnected(bool ownerChanged) override; - void gridButtonEvent(int x, int y, bool state) override; - void encDeltaEvent(int n, int d) override; - std::string gridGetCurrentDeviceId() override; - std::string gridGetLastDeviceId(bool owned) override; - Grid* gridGetDevice() override; + // Override IGridConsumer methods implemented by GridConsumerBase (and call base impl) + // TODO: replace this with an event hook system + virtual void gridConnected(Grid* newConnection) override; + virtual void gridDisconnected(bool ownerChanged) override; + // Implement remaining IGridConsumer methods + virtual void gridButtonEvent(int x, int y, bool state) override; + virtual void encDeltaEvent(int n, int d) override; - void userReacquireGrid(); void userToggleGridConnection(Grid* grid); virtual void readSerialMessages(); - void requestReloadFirmware(bool preserveMemory, const std::string& firmwareName = ""); float dacToVolts(uint16_t adc); uint16_t voltsToAdc(float volts); - std::string lastConnectedDeviceId; - std::string currentConnectedDeviceId; - bool connectionOwned; - std::string firmwarePrefix; std::string firmwareName; std::string defaultFirmwareName; @@ -82,9 +76,7 @@ struct LibAVR32Module : rack::engine::Module, GridConsumer protected: void reloadFirmware(bool preserveMemory, const std::string& newFirmware = ""); - void toggleGridConnection(Grid* grid); - Grid* gridConnection; int usbParamId; void setDeviceConnectionParam(int paramId) { usbParamId = paramId; } void processDeviceConnectionParam(); diff --git a/src/virtualgrid/VirtualGridModule.cpp b/src/virtualgrid/VirtualGridModule.cpp index 84a946f..eec57d7 100644 --- a/src/virtualgrid/VirtualGridModule.cpp +++ b/src/virtualgrid/VirtualGridModule.cpp @@ -1,22 +1,18 @@ #include "VirtualGridModule.hpp" #include "LibAVR32Module.hpp" +#include "GridConsumerBase.hpp" #include #include -struct MirrorModeGridConsumer : GridConsumer +struct MirrorModeGridConsumer : GridConsumerBase { - std::string lastConnectedDeviceId; - std::string currentConnectedDeviceId; - bool connectionOwned; - MirrorModeGridConsumer(VirtualGridModule* module) : module(module) - , gridConnection(nullptr) { } - ~MirrorModeGridConsumer() + virtual ~MirrorModeGridConsumer() { } @@ -27,24 +23,7 @@ struct MirrorModeGridConsumer : GridConsumer return; } - gridConnection = newConnection; - if (gridConnection) - { - std::string id = gridConnection->getDevice().id; - lastConnectedDeviceId = id; - currentConnectedDeviceId = id; - connectionOwned = true; - } - } - - void gridDisconnected(bool ownerChanged) override - { - gridConnection = nullptr; - currentConnectedDeviceId = ""; - if (ownerChanged) - { - connectionOwned = false; - } + GridConsumerBase::gridConnected(newConnection); } void gridButtonEvent(int x, int y, bool state) override @@ -66,29 +45,7 @@ struct MirrorModeGridConsumer : GridConsumer } - std::string gridGetLastDeviceId(bool owned) override - { - if (owned && !connectionOwned) - { - return ""; - } - - return lastConnectedDeviceId; - } - - std::string gridGetCurrentDeviceId() override - { - return currentConnectedDeviceId; - } - - Grid* gridGetDevice() override - { - return gridConnection; - } - protected: - - Grid* gridConnection; VirtualGridModule* module; }; @@ -147,6 +104,7 @@ VirtualGridModule::VirtualGridModule(unsigned w, unsigned h) VirtualGridModule::~VirtualGridModule() { + GridConnectionManager::get().deregisterGridConsumer(mirrorModeConsumer); delete mirrorModeConsumer; } @@ -202,6 +160,15 @@ json_t* VirtualGridModule::dataToJson() json_t* rootJ = json_object(); json_object_set_new(rootJ, "protocol", json_integer(device.protocol)); json_object_set_new(rootJ, "theme", json_integer(theme)); + + auto consumer = dynamic_cast(mirrorModeConsumer); + if (consumer) + { + json_t* mirrorJ = json_object(); + consumer->saveGridConnectionToJson(mirrorJ); + json_object_set_new(rootJ, "mirror", mirrorJ); + } + return rootJ; } @@ -225,6 +192,14 @@ void VirtualGridModule::dataFromJson(json_t* rootJ) { theme = static_cast(json_integer_value(json_theme)); } + + auto consumer = dynamic_cast(mirrorModeConsumer); + if (consumer) + { + auto json_mirror = json_object_get(rootJ, "mirror"); + consumer->loadGridConnectionFromJson(json_mirror); + GridConnectionManager::get().registerGridConsumer(consumer); + } } const MonomeDevice& VirtualGridModule::getDevice() diff --git a/src/virtualgrid/VirtualGridModule.hpp b/src/virtualgrid/VirtualGridModule.hpp index 0419882..0a79516 100644 --- a/src/virtualgrid/VirtualGridModule.hpp +++ b/src/virtualgrid/VirtualGridModule.hpp @@ -33,7 +33,7 @@ struct VirtualGridModule : rack::Module, Grid void clearAll() override; bool isHardware() override { return false; } - GridConsumer* mirrorModeConsumer; + IGridConsumer* mirrorModeConsumer; ActionQueue audioThreadActions; };