Skip to content

Commit

Permalink
Feature to re-order displays in multi-display mode (#1023)
Browse files Browse the repository at this point in the history
  • Loading branch information
awawa-dev authored Dec 26, 2024
1 parent 65b0718 commit c24549c
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 25 deletions.
3 changes: 3 additions & 0 deletions include/base/Grabber.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ class Grabber : public DetectionAutomatic, public DetectionManual, protected Lut

void setMonitorNits(int nits);

void setReorderDisplays(int order);

void setFpsSoftwareDecimation(int decimation) override;

int getFpsSoftwareDecimation() override;
Expand Down Expand Up @@ -269,6 +271,7 @@ public slots:
int _actualWidth, _actualHeight, _actualFPS;
QString _actualDeviceName;
uint _targetMonitorNits;
int _reorderDisplays;

int _lineLength;
int _frameByteSize;
Expand Down
2 changes: 1 addition & 1 deletion include/led-strip/ChannelCalibration.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class ChannelCalibration
public:
ChannelCalibration(quint8 instance, QString channelName, const QJsonObject& colorConfig, int defaultR, int defaultG, int defaultB);

void apply(uint8_t input, uint8_t brightness, uint8_t& red, uint8_t& green, uint8_t& blue);
void apply(uint64_t input, uint8_t brightness, uint64_t& red, uint64_t& green, uint64_t& blue) const;

ColorRgb getAdjustment() const;
void setAdjustment(const QJsonArray& value);
Expand Down
23 changes: 23 additions & 0 deletions sources/base/Grabber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Grabber::Grabber(const QString& configurationPath, const QString& grabberName)
, _actualFPS(0)
, _actualDeviceName("")
, _targetMonitorNits(200)
, _reorderDisplays(0)
, _lineLength(-1)
, _frameByteSize(-1)
, _signalDetectionEnabled(false)
Expand Down Expand Up @@ -184,6 +185,28 @@ void Grabber::setMonitorNits(int nits)
}
}

void Grabber::setReorderDisplays(int order)
{
if (_reorderDisplays != order)
{
_reorderDisplays = order;

Debug(_log, "Set re-order display permutation to %i", _reorderDisplays);

if (_initialized && !_blocked)
{
Debug(_log, "Restarting video grabber");
uninit();
start();
}
else
{
Info(_log, "Delayed restart of the grabber due to change of monitor display-order value");
_restartNeeded = true;
}
}
}

void Grabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom)
{
if (_width > 0 && _height > 0)
Expand Down
2 changes: 2 additions & 0 deletions sources/base/SystemWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ void SystemWrapper::handleSettingsUpdate(settings::type type, const QJsonDocumen

_grabber->setMonitorNits(obj["monitor_nits"].toInt(200));

_grabber->setReorderDisplays(obj["reorder_displays"].toInt(0));

_grabber->setSignalDetectionOffset(
obj["sDHOffsetMin"].toDouble(0.25),
obj["sDVOffsetMin"].toDouble(0.25),
Expand Down
16 changes: 16 additions & 0 deletions sources/base/schema/schema-systemGrabber.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,22 @@
},
"propertyOrder" : 25
},
"reorder_displays" :
{
"type" : "integer",
"format": "stepper",
"title" : "edt_conf_reorder_displays_title",
"default" : 0,
"minimum" : 0,
"maximum" : 255,
"required" : true,
"options": {
"dependencies": {
"hardware": true
}
},
"propertyOrder" : 26
},
"cropLeft" :
{
"type" : "integer",
Expand Down
30 changes: 28 additions & 2 deletions sources/grabber/windows/DX/DxGrabber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
*/
#define NOMINMAX

#include <algorithm>
#include <iostream>
#include <sstream>
#include <stdexcept>
Expand Down Expand Up @@ -779,6 +780,11 @@ void DxGrabber::grabFrame()
int targetSizeX = 0, targetSizeY = 0;
int divide = getTargetSystemFrameDimension(display->actualWidth, display->actualHeight, targetSizeX, targetSizeY);

if (_reorderDisplays > 0 && result == 0)
{
images.push_back(std::pair<int, Image<ColorRgb>>(width, Image<ColorRgb>(targetSizeX, 1)));
}

width += targetSizeX;
height = std::max(targetSizeY, height);
}
Expand All @@ -800,11 +806,31 @@ void DxGrabber::grabFrame()
memset(image.rawMem(), 0, image.size());
}

for (auto&& source : images)
if (_reorderDisplays > 0)
{
image.insertHorizontal(source.first, source.second);
for (int permutation = 0;
permutation < _reorderDisplays &&
std::next_permutation(images.begin(), images.end(),
[=](const std::pair<int, Image<ColorRgb>>& a, const std::pair<int, Image<ColorRgb>>& b)
{
return a.first < b.first;
});
permutation++);

int targetX = 0;
for (auto it = images.begin(); it != images.end(); ++it)
{
it->first = targetX;
targetX += it->second.width();
}
}

for (auto&& source : images)
if (_reorderDisplays == 0 || source.second.height() > 1)
{
image.insertHorizontal(source.first, source.second);
}

if (_signalDetectionEnabled)
{
if (checkSignalDetectionManual(image))
Expand Down
10 changes: 5 additions & 5 deletions sources/led-strip/ChannelCalibration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ bool ChannelCalibration::isEnabled() const
return _enabled;
}

void ChannelCalibration::apply(uint8_t input, uint8_t brightness, uint8_t& red, uint8_t& green, uint8_t& blue)
{
red = std::min(((brightness * input * _targetCalibration.red) / 65025), (int)UINT8_MAX);
green = std::min(((brightness * input * _targetCalibration.green) / 65025), (int)UINT8_MAX);
blue = std::min(((brightness * input * _targetCalibration.blue) / 65025), (int)UINT8_MAX);
void ChannelCalibration::apply(uint64_t input, uint8_t brightness, uint64_t& red, uint64_t& green, uint64_t& blue) const
{
red = (brightness * input * _targetCalibration.red + (65025 / 2)) / 65025;
green = (brightness * input * _targetCalibration.green + (65025 / 2)) / 65025;
blue = (brightness * input * _targetCalibration.blue + (65025 / 2)) / 65025;
}
32 changes: 16 additions & 16 deletions sources/led-strip/ColorCalibration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ void ColorCalibration::calibrate(ColorRgb& color)
{
if (B_RGB != 255)
{
color.red = ((uint32_t)color.red * B_RGB) / 255;
color.green = ((uint32_t)color.green * B_RGB) / 255;
color.blue = ((uint32_t)color.blue * B_RGB) / 255;
color.red = ((uint32_t)color.red * B_RGB + (255 / 2)) / 255;
color.green = ((uint32_t)color.green * B_RGB + (255 / 2)) / 255;
color.blue = ((uint32_t)color.blue * B_RGB + (255 / 2)) / 255;
}
}
else
Expand All @@ -121,17 +121,17 @@ void ColorCalibration::calibrate(ColorRgb& color)
uint32_t nrg = (uint32_t)(255 - ored) * (ogreen);
uint32_t rg = (uint32_t)(ored) * (ogreen);

uint8_t black = nrng * (255 - oblue) / 65025;
uint8_t red = rng * (255 - oblue) / 65025;
uint8_t green = nrg * (255 - oblue) / 65025;
uint8_t blue = nrng * (oblue) / 65025;
uint8_t cyan = nrg * (oblue) / 65025;
uint8_t magenta = rng * (oblue) / 65025;
uint8_t yellow = rg * (255 - oblue) / 65025;
uint8_t white = rg * (oblue) / 65025;
uint32_t black = nrng * (255 - oblue);
uint32_t red = rng * (255 - oblue);
uint32_t green = nrg * (255 - oblue);
uint32_t blue = nrng * (oblue);
uint32_t cyan = nrg * (oblue);
uint32_t magenta = rng * (oblue);
uint32_t yellow = rg * (255 - oblue);
uint32_t white = rg * (oblue);

uint8_t OR, OG, OB, RR, RG, RB, GR, GG, GB, BR, BG, BB;
uint8_t CR, CG, CB, MR, MG, MB, YR, YG, YB, WR, WG, WB;
uint64_t OR, OG, OB, RR, RG, RB, GR, GG, GB, BR, BG, BB;
uint64_t CR, CG, CB, MR, MG, MB, YR, YG, YB, WR, WG, WB;

_blackCalibration->apply(black, 255, OR, OG, OB);
_redCalibration->apply(red, B_RGB, RR, RG, RB);
Expand All @@ -142,9 +142,9 @@ void ColorCalibration::calibrate(ColorRgb& color)
_yellowCalibration->apply(yellow, B_CMY, YR, YG, YB);
_whiteCalibration->apply(white, B_W, WR, WG, WB);

color.red = OR + RR + GR + BR + CR + MR + YR + WR;
color.green = OG + RG + GG + BG + CG + MG + YG + WG;
color.blue = OB + RB + GB + BB + CB + MB + YB + WB;
color.red = std::min((OR + RR + GR + BR + CR + MR + YR + WR + (65025 / 2)) / 65025, (uint64_t) 255);
color.green = std::min((OG + RG + GG + BG + CG + MG + YG + WG + (65025 / 2)) / 65025, (uint64_t) 255);
color.blue = std::min((OB + RB + GB + BB + CB + MB + YB + WB + (65025 / 2)) / 65025, (uint64_t) 255);
}
}
_colorspaceCalibration->applyBacklight(ored, ogreen, oblue);
Expand Down
4 changes: 3 additions & 1 deletion www/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1267,5 +1267,7 @@
"wiz_home_assistant_title": "Home Assistant lights wizard",
"wiz_ha_intro": "Please select the address of the Home Assistant instance and enter the 'Long Lived Access Tokens' created there.",
"select_ha_intro": "Select Home Assistant",
"edt_dev_spec_constantBrightness_title": "Constant brightness"
"edt_dev_spec_constantBrightness_title": "Constant brightness",
"edt_conf_reorder_displays_title": "Reorder displays",
"edt_conf_reorder_displays_expl": "Manipulate the order (permutations) of the displays until you get the correct one in multi-display mode"
}

0 comments on commit c24549c

Please sign in to comment.