Skip to content

Commit

Permalink
Prototype of virtual grid mirror mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Dewb committed Aug 2, 2023
1 parent 5db40d0 commit e94837a
Show file tree
Hide file tree
Showing 9 changed files with 270 additions and 3 deletions.
7 changes: 7 additions & 0 deletions src/common/core/ActionQueue.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

#include "rack.hpp"
#include <functional>

typedef std::function<void(void)> Action;
typedef rack::dsp::RingBuffer<Action, 4> ActionQueue;
3 changes: 3 additions & 0 deletions src/common/core/GridConnection/GridConnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ struct GridConsumer
{
virtual void gridConnected(Grid* grid) = 0;
virtual void gridDisconnected(bool ownerChanged) = 0;
virtual std::string gridGetCurrentDeviceId() = 0;
virtual std::string gridGetLastDeviceId(bool owned) = 0;
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
Expand Down
120 changes: 120 additions & 0 deletions src/common/core/GridConnection/GridConnectionMenu.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include "GridConnectionMenu.hpp"
#include "SerialOscInterface.hpp"

using namespace rack;

struct NewConnectGridItem : rack::ui::MenuItem
{
Grid* grid;
GridConsumer* consumer;
ActionQueue* actionQueue;

void onAction(const rack::event::Action& e) override
{
if (actionQueue)
{
auto thisGrid = grid;
auto thisConsumer = consumer;

actionQueue->push([thisGrid, thisConsumer]()
{ GridConnectionManager::get().connect(thisGrid, thisConsumer); });
}
}
};

void menuUserReacquireGrid(GridConsumer* consumer, std::string lastDeviceId, ActionQueue* actionQueue)
{
for (Grid* grid : GridConnectionManager::get().getGrids())
{
if (lastDeviceId == grid->getDevice().id)
{
if (actionQueue)
{
actionQueue->push([grid, consumer]()
{
GridConnectionManager::get().connect(grid, consumer);
}
);
}
return;
}
}
}

void appendDeviceConnectionMenu(rack::Menu* menu, GridConsumer* consumer, ActionQueue* actionQueue)
{
std::string currentConnectedDeviceId = consumer->gridGetCurrentDeviceId();
std::string lastConnectedDeviceId = consumer->gridGetLastDeviceId(false);

menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Device Connection"));

if (SerialOscInterface::get()->isServiceDetected())
{
menu->addChild(
construct<MenuLabel>(
&MenuLabel::text,
"serialosc version " + SerialOscInterface::get()->getServiceVersion()));
}
else
{
menu->addChild(
createMenuItem("└ serialosc service not detected, click here to install", "",
[=]()
{
system::openBrowser("https://monome.org/docs/serialosc/setup/");
}));
}

// enumerate registered grid devices
int deviceCount = 0;
bool preferredDeviceFound = false;
for (Grid* grid : GridConnectionManager::get().getGrids())
{
auto connectItem = new NewConnectGridItem();
connectItem->text = "" + grid->getDevice().type + " (" + grid->getDevice().id + ") ";

auto rightText = "";
if (currentConnectedDeviceId == grid->getDevice().id)
{
rightText = "";
preferredDeviceFound = true;
}
else if (currentConnectedDeviceId == "" && lastConnectedDeviceId == grid->getDevice().id)
{
rightText = "";
preferredDeviceFound = true;
}

connectItem->rightText = rightText;
connectItem->grid = grid;
connectItem->actionQueue = actionQueue;
connectItem->consumer = consumer;

menu->addChild(connectItem);
deviceCount++;
}

if (deviceCount == 0)
{
menu->addChild(construct<MenuLabel>(&MenuLabel::text, " (no physical or virtual devices found)"));
}

if (currentConnectedDeviceId == "" && lastConnectedDeviceId != "")
{
if (preferredDeviceFound)
{
menu->addChild(createMenuItem("Reacquire grid", "", [=]()
{
if (lastConnectedDeviceId != "")
{
menuUserReacquireGrid(consumer, lastConnectedDeviceId, actionQueue);
}
}
));
}
else
{
menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Can't reacquire grid (" + lastConnectedDeviceId + " not found)"));
}
}
}
7 changes: 7 additions & 0 deletions src/common/core/GridConnection/GridConnectionMenu.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

#include "rack.hpp"
#include "GridConnection.hpp"
#include "ActionQueue.hpp"

void appendDeviceConnectionMenu(rack::Menu* menu, GridConsumer* consumer, ActionQueue* queue);
10 changes: 10 additions & 0 deletions src/common/core/LibAVR32Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ void LibAVR32Module::encDeltaEvent(int n, int d)
}
}

std::string LibAVR32Module::gridGetCurrentDeviceId()
{
return currentConnectedDeviceId;
}

std::string LibAVR32Module::gridGetLastDeviceId(bool owned)
{
if (owned && !connectionOwned)
Expand All @@ -154,6 +159,11 @@ std::string LibAVR32Module::gridGetLastDeviceId(bool owned)
return lastConnectedDeviceId;
}

Grid* LibAVR32Module::gridGetDevice()
{
return gridConnection;
}

void LibAVR32Module::userReacquireGrid()
{
if (lastConnectedDeviceId != "" && gridConnection == nullptr)
Expand Down
6 changes: 3 additions & 3 deletions src/common/core/LibAVR32Module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include "GridConnection.hpp"
#include "VirtualGridTheme.hpp"
#include "rack.hpp"
#include <queue>
#include "ActionQueue.hpp"

#pragma once

Expand Down Expand Up @@ -52,7 +52,9 @@ struct LibAVR32Module : rack::engine::Module, GridConsumer
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;

void userReacquireGrid();
void userToggleGridConnection(Grid* grid);
Expand Down Expand Up @@ -91,8 +93,6 @@ struct LibAVR32Module : rack::engine::Module, GridConsumer

// Thread-safe for single-producer, single-consumer
friend struct TeletypeSceneIO;
typedef std::function<void(void)> Action;
typedef rack::dsp::RingBuffer<Action, 4> ActionQueue;
ActionQueue audioThreadActions;
};

Expand Down
113 changes: 113 additions & 0 deletions src/virtualgrid/VirtualGridModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,93 @@
#include <iomanip>
#include <sstream>

struct MirrorModeGridConsumer : GridConsumer
{
std::string lastConnectedDeviceId;
std::string currentConnectedDeviceId;
bool connectionOwned;

MirrorModeGridConsumer(VirtualGridModule* module)
: module(module)
{
}

~MirrorModeGridConsumer()
{
}

void gridConnected(Grid* newConnection) override
{
if (newConnection == module)
{ // don't mirror self
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;
}
}

void gridButtonEvent(int x, int y, bool state) override
{
if (module)
{
int w = module->device.width;
auto param = module->getParamQuantity((x + y * w) * 2);
if (param)
{
module->audioThreadActions.push([param, state]()
{ param->setImmediateValue(state ? 1 : 0); });
}
}
}

void encDeltaEvent(int n, int d) override
{

}

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;
};

std::string formatVirtualDeviceId(int64_t id)
{
std::ostringstream ss;
Expand Down Expand Up @@ -52,11 +139,14 @@ VirtualGridModule::VirtualGridModule(unsigned w, unsigned h)

theme = GridTheme::Yellow;

mirrorModeConsumer = new MirrorModeGridConsumer(this);

clearAll();
}

VirtualGridModule::~VirtualGridModule()
{
delete mirrorModeConsumer;
}

void VirtualGridModule::onAdd()
Expand All @@ -66,6 +156,11 @@ void VirtualGridModule::onAdd()

void VirtualGridModule::process(const ProcessArgs& args)
{
while (audioThreadActions.size())
{
audioThreadActions.shift()();
}

std::vector<std::tuple<int, int>> presses;
std::vector<std::tuple<int, int>> releases;

Expand Down Expand Up @@ -138,6 +233,15 @@ const MonomeDevice& VirtualGridModule::getDevice()

void VirtualGridModule::updateRow(int x_offset, int y, uint8_t bitfield)
{
if (mirrorModeConsumer)
{
auto mirroredGrid = mirrorModeConsumer->gridGetDevice();
if (mirroredGrid)
{
mirroredGrid->updateRow(x_offset, y, bitfield);
}
}

uint8_t* ptr = ledBuffer + y * 16 + x_offset;
for (int i = 0; i < 8; i++)
{
Expand All @@ -147,6 +251,15 @@ void VirtualGridModule::updateRow(int x_offset, int y, uint8_t bitfield)

void VirtualGridModule::updateQuadrant(int x_offset, int y_offset, uint8_t* leds)
{
if (mirrorModeConsumer)
{
auto mirroredGrid = mirrorModeConsumer->gridGetDevice();
if (mirroredGrid)
{
mirroredGrid->updateQuadrant(x_offset, y_offset, leds);
}
}

uint8_t* ptr = ledBuffer + y_offset * 16 + x_offset;
for (int i = 0; i < 8; i++)
{
Expand Down
4 changes: 4 additions & 0 deletions src/virtualgrid/VirtualGridModule.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "GridConnection.hpp"
#include "VirtualGridTheme.hpp"
#include "rack.hpp"
#include "ActionQueue.hpp"

#define GRID_MAX_SIZE 256

Expand Down Expand Up @@ -30,6 +31,9 @@ struct VirtualGridModule : rack::Module, Grid
void updateQuadrant(int x_offset, int y_offset, uint8_t* leds) override;
void updateRing(int n, uint8_t leds[64]) override {};
void clearAll() override;

GridConsumer* mirrorModeConsumer;
ActionQueue audioThreadActions;
};

template <unsigned width, unsigned height>
Expand Down
3 changes: 3 additions & 0 deletions src/virtualgrid/VirtualGridWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "VirtualGridKey.hpp"
#include "VirtualGridModule.hpp"
#include "VirtualGridTheme.hpp"
#include "GridConnectionMenu.hpp"

using namespace rack;

Expand Down Expand Up @@ -218,6 +219,8 @@ void VirtualGridWidget::appendContextMenu(Menu * menu)
screenshotModulePNG(this, "grid-screenshot.png");
}));

appendDeviceConnectionMenu(menu, grid->mirrorModeConsumer, &grid->audioThreadActions);

menu->addChild(new MenuSeparator());
menu->addChild(createIndexPtrSubmenuItem("Theme", { "Red", "Orange", "Yellow", "White" }, &grid->theme));
menu->addChild(createIndexSubmenuItem("Protocol", {"40h", "Series", "Mext (varibright)"},
Expand Down

0 comments on commit e94837a

Please sign in to comment.