| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * This file is part of the Falcon Player (FPP) and is Copyright (C) | ||
| 3 | * 2013-2022 by the Falcon Player Developers. | ||
| 4 | * | ||
| 5 | * The Falcon Player (FPP) is free software, and is covered under | ||
| 6 | * multiple Open Source licenses. Please see the included 'LICENSES' | ||
| 7 | * file for descriptions of what files are covered by each license. | ||
| 8 | * | ||
| 9 | * This source file is covered under the GPL v2 as described in the | ||
| 10 | * included LICENSE.GPL file. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include "fpp-pch.h" | ||
| 14 | |||
| 15 | #include "fpp-json.h" | ||
| 16 | |||
| 17 | #include <cmath> | ||
| 18 | |||
| 19 | #include <X11/Xutil.h> | ||
| 20 | |||
| 21 | #include "../log.h" | ||
| 22 | |||
| 23 | #include "GammaLUT.h" | ||
| 24 | #include "X11PanelMatrix.h" | ||
| 25 | |||
| 26 | #include "Plugin.h" | ||
| 27 | class X11PanelMatrixPlugin : public FPPPlugins::Plugin, public FPPPlugins::ChannelOutputPlugin { | ||
| 28 | public: | ||
| 29 | 3 | X11PanelMatrixPlugin() : | |
| 30 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
9 | FPPPlugins::Plugin("X11PanelMatrix") { |
| 31 | 3 | } | |
| 32 | 3 | virtual ChannelOutput* createChannelOutput(unsigned int startChannel, unsigned int channelCount) override { | |
| 33 |
2/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
6 | return new X11PanelMatrixOutput(startChannel, channelCount); |
| 34 | } | ||
| 35 | }; | ||
| 36 | |||
| 37 | extern "C" { | ||
| 38 | 3 | FPPPlugins::Plugin* createPlugin() { | |
| 39 |
2/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
6 | return new X11PanelMatrixPlugin(); |
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | ///////////////////////////////////////////////////////////////////////////// | ||
| 44 | |||
| 45 | /* | ||
| 46 | * | ||
| 47 | */ | ||
| 48 | 3 | X11PanelMatrixOutput::X11PanelMatrixOutput(unsigned int startChannel, | |
| 49 | 3 | unsigned int channelCount) : | |
| 50 | ThreadedChannelOutput(startChannel, channelCount), | ||
| 51 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
6 | m_colorOrder("RGB"), |
| 52 | 3 | m_panelWidth(32), | |
| 53 | 3 | m_panelHeight(16), | |
| 54 | 3 | m_panels(0), | |
| 55 | 3 | m_width(0), | |
| 56 | 3 | m_height(0), | |
| 57 | 3 | m_rows(0), | |
| 58 | 3 | m_outputs(0), | |
| 59 | 3 | m_longestChain(0), | |
| 60 | 6 | m_invertedData(0) { | |
| 61 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | LogDebug(VB_CHANNELOUT, "X11PanelMatrixOutput::X11PanelMatrixOutput(%u, %u)\n", |
| 62 | startChannel, channelCount); | ||
| 63 | |||
| 64 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | XInitThreads(); |
| 65 | |||
| 66 | 3 | m_useDoubleBuffer = 1; | |
| 67 | 3 | } | |
| 68 | |||
| 69 | /* | ||
| 70 | * | ||
| 71 | */ | ||
| 72 | 12 | X11PanelMatrixOutput::~X11PanelMatrixOutput() { | |
| 73 | 6 | LogDebug(VB_CHANNELOUT, "X11PanelMatrixOutput::~X11PanelMatrixOutput()\n"); | |
| 74 | |||
| 75 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
6 | delete m_matrix; |
| 76 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
6 | delete m_panelMatrix; |
| 77 | 12 | } | |
| 78 | |||
| 79 | /* | ||
| 80 | * | ||
| 81 | */ | ||
| 82 | 3 | int X11PanelMatrixOutput::Init(Json::Value config) { | |
| 83 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | LogDebug(VB_CHANNELOUT, "X11PanelMatrixOutput::Init(JSON)\n"); |
| 84 | |||
| 85 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | m_panelWidth = config["panelWidth"].asInt(); |
| 86 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | m_panelHeight = config["panelHeight"].asInt(); |
| 87 | |||
| 88 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!m_panelWidth) |
| 89 | ✗ | m_panelWidth = 32; | |
| 90 | |||
| 91 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!m_panelHeight) |
| 92 | ✗ | m_panelHeight = 16; | |
| 93 | |||
| 94 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | m_invertedData = config["invertedData"].asInt(); |
| 95 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | m_colorOrder = config["colorOrder"].asString(); |
| 96 | |||
| 97 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
3 | m_panelMatrix = |
| 98 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | new PanelMatrix(m_panelWidth, m_panelHeight, m_invertedData); |
| 99 | |||
| 100 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!m_panelMatrix) { |
| 101 | ✗ | LogErr(VB_CHANNELOUT, "Unable to create PanelMatrix\n"); | |
| 102 | |||
| 103 | ✗ | return 0; | |
| 104 | } | ||
| 105 | |||
| 106 |
4/6✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3 times.
|
6 | for (int i = 0; i < config["panels"].size(); i++) { |
| 107 |
3/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | Json::Value p = config["panels"][i]; |
| 108 | 3 | char orientation = 'N'; | |
| 109 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | std::string o = p["orientation"].asString(); |
| 110 | |||
| 111 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!o.empty()) |
| 112 | 3 | orientation = o[0]; | |
| 113 | |||
| 114 |
4/8✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
3 | if (p["colorOrder"].asString() == "") |
| 115 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | p["colorOrder"] = m_colorOrder; |
| 116 | |||
| 117 | // a refused panel (out of range) must not count toward the outputs or chains below | ||
| 118 |
4/8✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
6 | if (!m_panelMatrix->AddPanel(p["outputNumber"].asInt(), |
| 119 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | p["panelNumber"].asInt(), orientation, |
| 120 |
4/8✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
3 | p["xOffset"].asInt(), p["yOffset"].asInt(), |
| 121 |
3/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
|
6 | ColorOrderFromString(p["colorOrder"].asString()))) { |
| 122 | ✗ | continue; | |
| 123 | } | ||
| 124 | |||
| 125 |
3/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
|
3 | if (p["outputNumber"].asInt() > m_outputs) |
| 126 | ✗ | m_outputs = p["outputNumber"].asInt(); | |
| 127 | |||
| 128 |
3/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
|
3 | if (p["panelNumber"].asInt() > m_longestChain) |
| 129 | ✗ | m_longestChain = p["panelNumber"].asInt(); | |
| 130 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | } |
| 131 | |||
| 132 | // Both of these are 0-based, so bump them up by 1 for comparisons | ||
| 133 | 3 | m_outputs++; | |
| 134 | 3 | m_longestChain++; | |
| 135 | |||
| 136 | 3 | m_panels = m_panelMatrix->PanelCount(); | |
| 137 | |||
| 138 | 3 | m_rows = m_panelHeight; | |
| 139 | |||
| 140 | 3 | m_width = m_panelMatrix->Width(); | |
| 141 | 3 | m_height = m_panelMatrix->Height(); | |
| 142 | |||
| 143 | 3 | m_channelCount = m_width * m_height * 3; | |
| 144 | |||
| 145 | 3 | int colorDepth = 8; | |
| 146 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (config.isMember("panelColorDepth")) { |
| 147 | ✗ | colorDepth = config["panelColorDepth"].asInt(); | |
| 148 | } | ||
| 149 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (colorDepth > 11 || colorDepth < 6) { |
| 150 | ✗ | colorDepth = 11; | |
| 151 | } | ||
| 152 | |||
| 153 |
3/8✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
3 | m_matrix = new Matrix(m_startChannel, m_width, m_height); |
| 154 | |||
| 155 |
3/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
|
3 | if (config.isMember("subMatrices")) { |
| 156 |
4/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2 times.
|
3 | for (int i = 0; i < config["subMatrices"].size(); i++) { |
| 157 |
3/6✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | Json::Value sm = config["subMatrices"][i]; |
| 158 | |||
| 159 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | m_matrix->AddSubMatrix( |
| 160 |
1/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | sm["enabled"].asInt(), |
| 161 |
3/6✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | sm["startChannel"].asInt() - 1, |
| 162 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | sm["width"].asInt(), |
| 163 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | sm["height"].asInt(), |
| 164 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | sm["xOffset"].asInt(), |
| 165 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | sm["yOffset"].asInt()); |
| 166 | 1 | } | |
| 167 | } | ||
| 168 | |||
| 169 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | GammaLUT::Build(m_gammaCurve, GammaLUT::ParseConfig(config, 2.2f)); |
| 170 | |||
| 171 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | if (config.isMember("scale")) |
| 172 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | m_scale = config["scale"].asInt(); |
| 173 | else | ||
| 174 | ✗ | m_scale = 10; | |
| 175 | |||
| 176 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | if (config.isMember("title")) |
| 177 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | m_title = config["title"].asString(); |
| 178 | else | ||
| 179 | ✗ | m_title = "X11PanelMatrix"; | |
| 180 | |||
| 181 | 3 | m_scaleWidth = m_width * m_scale; | |
| 182 | 3 | m_scaleHeight = m_height * m_scale; | |
| 183 | 3 | m_imageData = (char*)calloc(m_scaleWidth * m_scaleHeight * 4, 1); | |
| 184 | |||
| 185 | // Initialize X11 Window here | ||
| 186 | 3 | const char* dsp = getenv("DISPLAY"); | |
| 187 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (dsp == nullptr) { |
| 188 | 3 | dsp = ":0"; | |
| 189 | } | ||
| 190 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | m_display = XOpenDisplay(dsp); |
| 191 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!m_display) { |
| 192 | ✗ | LogErr(VB_CHANNELOUT, "Unable to connect to X Server: %s\n", dsp); | |
| 193 | ✗ | return 0; | |
| 194 | } | ||
| 195 | |||
| 196 | 3 | m_screen = DefaultScreen(m_display); | |
| 197 | |||
| 198 | 6 | m_image = XCreateImage(m_display, CopyFromParent, 24, ZPixmap, 0, | |
| 199 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | m_imageData, m_scaleWidth, m_scaleHeight, 32, m_scaleWidth * 4); |
| 200 | |||
| 201 | 3 | int win_x = 100; | |
| 202 | 3 | int win_y = 100; | |
| 203 | XSetWindowAttributes attributes; | ||
| 204 | |||
| 205 | 3 | attributes.background_pixel = BlackPixel(m_display, m_screen); | |
| 206 | |||
| 207 | XGCValues values; | ||
| 208 | |||
| 209 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | m_pixmap = XCreatePixmap(m_display, XDefaultRootWindow(m_display), |
| 210 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | m_scaleWidth, m_scaleHeight, 24); |
| 211 | |||
| 212 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | m_gc = XCreateGC(m_display, m_pixmap, 0, &values); |
| 213 | 3 | int32_t tgc = reinterpret_cast<uintptr_t>(m_gc); | |
| 214 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (tgc < 0) { |
| 215 | ✗ | LogErr(VB_CHANNELOUT, "Unable to create GC\n"); | |
| 216 | ✗ | return 0; | |
| 217 | } | ||
| 218 | |||
| 219 | 6 | m_window = XCreateWindow( | |
| 220 | 3 | m_display, RootWindow(m_display, m_screen), win_x, win_y, | |
| 221 | 3 | m_scaleWidth, m_scaleHeight, 5, 24, InputOutput, | |
| 222 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DefaultVisual(m_display, m_screen), CWBackPixel, &attributes); |
| 223 | |||
| 224 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | XMapWindow(m_display, m_window); |
| 225 | |||
| 226 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | XStoreName(m_display, m_window, m_title.c_str()); |
| 227 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | XSetIconName(m_display, m_window, m_title.c_str()); |
| 228 | |||
| 229 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | XFlush(m_display); |
| 230 | |||
| 231 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | return ThreadedChannelOutput::Init(config); |
| 232 | } | ||
| 233 | |||
| 234 | 6 | void X11PanelMatrixOutput::GetRequiredChannelRanges(const std::function<void(int, int)>& addRange) { | |
| 235 | 6 | addRange(m_startChannel, m_startChannel + m_channelCount - 1); | |
| 236 | 6 | } | |
| 237 | |||
| 238 | /* | ||
| 239 | * | ||
| 240 | */ | ||
| 241 | 3 | int X11PanelMatrixOutput::Close(void) { | |
| 242 | 3 | LogDebug(VB_CHANNELOUT, "X11PanelMatrixOutput::Close()\n"); | |
| 243 | |||
| 244 | // Close X11 Window here | ||
| 245 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (m_display) { |
| 246 | 3 | XLockDisplay(m_display); | |
| 247 | 3 | XDestroyWindow(m_display, m_window); | |
| 248 | 3 | XFreePixmap(m_display, m_pixmap); | |
| 249 | 3 | XFreeGC(m_display, m_gc); | |
| 250 | 3 | XDestroyImage(m_image); | |
| 251 | 3 | XUnlockDisplay(m_display); | |
| 252 | 3 | XCloseDisplay(m_display); | |
| 253 | } | ||
| 254 | 3 | m_display = nullptr; | |
| 255 | |||
| 256 | 3 | return ThreadedChannelOutput::Close(); | |
| 257 | } | ||
| 258 | |||
| 259 | // The submatrix overlay has to see the whole sequence buffer: a submatrix | ||
| 260 | // names its source and its enable flag by absolute channel, and those live | ||
| 261 | // outside this output's own range. RawSendData only ever gets the double | ||
| 262 | // buffered copy of this output's channels, so the overlay belongs here, on the | ||
| 263 | // absolute buffer, which is where the other Matrix users do it too. | ||
| 264 | 27 | void X11PanelMatrixOutput::PrepData(unsigned char* channelData) { | |
| 265 | 27 | LogExcess(VB_CHANNELOUT, "X11PanelMatrixOutput::PrepData(%p)\n", channelData); | |
| 266 | 27 | m_matrix->OverlaySubMatrices(channelData); | |
| 267 | 27 | } | |
| 268 | |||
| 269 | /* | ||
| 270 | * | ||
| 271 | */ | ||
| 272 | 21 | int X11PanelMatrixOutput::RawSendData(unsigned char* channelData) { | |
| 273 | 21 | LogExcess(VB_CHANNELOUT, "X11PanelMatrixOutput::RawSendData(%p)\n", | |
| 274 | channelData); | ||
| 275 | |||
| 276 | unsigned char r; | ||
| 277 | unsigned char g; | ||
| 278 | unsigned char b; | ||
| 279 | unsigned char* c; | ||
| 280 | 21 | unsigned int stride = m_scaleWidth * 4; | |
| 281 | |||
| 282 | // channelData is this output's channels only, already based at its start | ||
| 283 | // channel, and the panel pixel maps are relative to that same base | ||
| 284 | |||
| 285 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 21 times.
|
42 | for (int output = 0; output < m_outputs; output++) { |
| 286 | 21 | int panelsOnOutput = m_panelMatrix->m_outputPanels[output].size(); | |
| 287 | |||
| 288 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 21 times.
|
42 | for (int i = 0; i < panelsOnOutput; i++) { |
| 289 | 21 | int panel = m_panelMatrix->m_outputPanels[output][i]; | |
| 290 | 21 | int chain = m_panelMatrix->m_panels[panel].chain; | |
| 291 | 21 | int py = m_panelMatrix->m_panels[panel].yOffset; | |
| 292 | 21 | int px = m_panelMatrix->m_panels[panel].xOffset; | |
| 293 |
2/2✓ Branch 0 taken 336 times.
✓ Branch 1 taken 21 times.
|
357 | for (int y = 0; y < m_panelHeight; y++) { |
| 294 | 336 | int yw = y * m_panelWidth; | |
| 295 |
2/2✓ Branch 0 taken 10752 times.
✓ Branch 1 taken 336 times.
|
11088 | for (int x = 0; x < m_panelWidth; x++) { |
| 296 | 10752 | r = m_gammaCurve[channelData[m_panelMatrix->m_panels[panel].pixelMap[(yw + x) * 3]]]; | |
| 297 | 10752 | g = m_gammaCurve[channelData[m_panelMatrix->m_panels[panel].pixelMap[(yw + x) * 3 + 1]]]; | |
| 298 | 10752 | b = m_gammaCurve[channelData[m_panelMatrix->m_panels[panel].pixelMap[(yw + x) * 3 + 2]]]; | |
| 299 | |||
| 300 | 10752 | c = (unsigned char*)m_imageData + ((py + y) * m_scale * stride) + ((px + x) * 4 * m_scale); | |
| 301 | |||
| 302 |
2/2✓ Branch 0 taken 10752 times.
✓ Branch 1 taken 10752 times.
|
21504 | for (unsigned int t = 0; t < m_scale; t++) { |
| 303 |
2/2✓ Branch 0 taken 10752 times.
✓ Branch 1 taken 10752 times.
|
21504 | for (unsigned int s = 0; s < m_scale; s++) { |
| 304 | 10752 | *(c++) = b; | |
| 305 | 10752 | *(c++) = g; | |
| 306 | 10752 | *(c++) = r; | |
| 307 | 10752 | c++; | |
| 308 | } | ||
| 309 | 10752 | c += stride - (m_scale * 4); | |
| 310 | } | ||
| 311 | } | ||
| 312 | } | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | 21 | XLockDisplay(m_display); | |
| 317 | |||
| 318 | 21 | XPutImage(m_display, m_window, m_gc, m_image, 0, 0, 0, 0, m_scaleWidth, m_scaleHeight); | |
| 319 | |||
| 320 | 21 | XSync(m_display, True); | |
| 321 | 21 | XFlush(m_display); | |
| 322 | |||
| 323 | 21 | XUnlockDisplay(m_display); | |
| 324 | |||
| 325 | 21 | return m_channelCount; | |
| 326 | } | ||
| 327 | |||
| 328 | /* | ||
| 329 | * | ||
| 330 | */ | ||
| 331 | 6 | void X11PanelMatrixOutput::DumpConfig(void) { | |
| 332 | 6 | LogDebug(VB_CHANNELOUT, "X11PanelMatrixOutput::DumpConfig()\n"); | |
| 333 | 6 | LogDebug(VB_CHANNELOUT, " Panels : %d\n", m_panels); | |
| 334 | 6 | LogDebug(VB_CHANNELOUT, " Width : %d\n", m_width); | |
| 335 | 6 | LogDebug(VB_CHANNELOUT, " Height : %d\n", m_height); | |
| 336 | 6 | LogDebug(VB_CHANNELOUT, " Scale : %d\n", m_scale); | |
| 337 | 6 | LogDebug(VB_CHANNELOUT, " Scaled Width : %d\n", m_scaleWidth); | |
| 338 | 6 | LogDebug(VB_CHANNELOUT, " Scaled Height : %d\n", m_scaleHeight); | |
| 339 | 6 | } | |
| 340 |