From fb8c10876b6cc9ebe0a49521342292371ad8ce26 Mon Sep 17 00:00:00 2001 From: jm-github Date: Thu, 30 Oct 2014 16:02:30 +0000 Subject: [PATCH 01/96] 5 more effects Former-commit-id: e6a826299ad48143cb155e7113a34bd6d3b20246 --- effects/loop.json | 7 +++++++ effects/loop.py | 34 ++++++++++++++++++++++++++++++++++ effects/loop2.json | 7 +++++++ effects/loop2.py | 33 +++++++++++++++++++++++++++++++++ effects/random.json | 7 +++++++ effects/random.py | 25 +++++++++++++++++++++++++ effects/sparks-color.json | 7 +++++++ effects/sparks-color.py | 35 +++++++++++++++++++++++++++++++++++ effects/sparks.json | 7 +++++++ effects/sparks.py | 33 +++++++++++++++++++++++++++++++++ 10 files changed, 195 insertions(+) create mode 100644 effects/loop.json create mode 100644 effects/loop.py create mode 100644 effects/loop2.json create mode 100644 effects/loop2.py create mode 100644 effects/random.json create mode 100644 effects/random.py create mode 100644 effects/sparks-color.json create mode 100644 effects/sparks-color.py create mode 100644 effects/sparks.json create mode 100644 effects/sparks.py diff --git a/effects/loop.json b/effects/loop.json new file mode 100644 index 00000000..9415f8b1 --- /dev/null +++ b/effects/loop.json @@ -0,0 +1,7 @@ +{ + "name" : "Loop", + "script" : "loop.py", + "args" : + { + } +} diff --git a/effects/loop.py b/effects/loop.py new file mode 100644 index 00000000..93011e97 --- /dev/null +++ b/effects/loop.py @@ -0,0 +1,34 @@ +import hyperion +import time +import colorsys +import random + +# Initialize the led data +ledData = bytearray() +for i in range(hyperion.ledCount): + ledData += bytearray((0,0,0)) + +sleepTime = 0.002 + +runners = [ +{ "i":0, "pos":0, "c":0, "step":9 , "lvl":255}, +{ "i":1, "pos":0, "c":0, "step":8 , "lvl":255}, +{ "i":2, "pos":0, "c":0, "step":7 , "lvl":255}, +{ "i":0, "pos":0, "c":0, "step":6 , "lvl":0}, +{ "i":1, "pos":0, "c":0, "step":5 , "lvl":0}, +{ "i":2, "pos":0, "c":0, "step":4, "lvl":0}, +] + +# Start the write data loop +while not hyperion.abort(): + for r in runners: + if r["c"] == 0: + #ledData[r["pos"]*3+r["i"]] = 0 + r["c"] = r["step"] + r["pos"] = (r["pos"]+1)%hyperion.ledCount + ledData[r["pos"]*3+r["i"]] = int(r["lvl"]*(0.2+0.8*random.random())) + else: + r["c"] -= 1 + + hyperion.setColor(ledData) + time.sleep(sleepTime) diff --git a/effects/loop2.json b/effects/loop2.json new file mode 100644 index 00000000..77f2c438 --- /dev/null +++ b/effects/loop2.json @@ -0,0 +1,7 @@ +{ + "name" : "Loop2", + "script" : "loop2.py", + "args" : + { + } +} diff --git a/effects/loop2.py b/effects/loop2.py new file mode 100644 index 00000000..3498ac4e --- /dev/null +++ b/effects/loop2.py @@ -0,0 +1,33 @@ +import hyperion +import time +import colorsys +import random + +# Initialize the led data +ledData = bytearray() +for i in range(hyperion.ledCount): + ledData += bytearray((0,0,0)) + +sleepTime = 0.005 + +runners = [ +{ "pos":0, "step":4 , "lvl":255}, +{ "pos":1, "step":5 , "lvl":255}, +{ "pos":2, "step":6 , "lvl":255}, +{ "pos":0, "step":7 , "lvl":255}, +{ "pos":1, "step":8 , "lvl":255}, +{ "pos":2, "step":9, "lvl":255}, +] + +# Start the write data loop +count = 0 +while not hyperion.abort(): + count += 1 + for r in runners: + if count%r["step"] == 0: + ledData[r["pos"]] = 0 + r["pos"] = (r["pos"]+3)%(hyperion.ledCount*3) + ledData[r["pos"]] = r["lvl"] + + hyperion.setColor(ledData) + time.sleep(sleepTime) diff --git a/effects/random.json b/effects/random.json new file mode 100644 index 00000000..dc1d79ae --- /dev/null +++ b/effects/random.json @@ -0,0 +1,7 @@ +{ + "name" : "Random", + "script" : "random.py", + "args" : + { + } +} diff --git a/effects/random.py b/effects/random.py new file mode 100644 index 00000000..0f5406b1 --- /dev/null +++ b/effects/random.py @@ -0,0 +1,25 @@ +import hyperion +import time +import colorsys +import random + +# Initialize the led data +ledData = bytearray() +for i in range(hyperion.ledCount): + ledData += bytearray((0,0,0)) + +sleepTime = 0.001 + +# Start the write data loop +while not hyperion.abort(): + hyperion.setColor(ledData) + for i in range(hyperion.ledCount): + if random.randrange(10) == 1: + hue = random.random() + sat = 1.0 + val = random.random() + rgb = colorsys.hsv_to_rgb(hue, sat, val) + ledData[i*3 ] = int(255*rgb[0]) + ledData[i*3+1] = int(255*rgb[1]) + ledData[i*3+2] = int(255*rgb[2]) + time.sleep(sleepTime) diff --git a/effects/sparks-color.json b/effects/sparks-color.json new file mode 100644 index 00000000..1c3e8146 --- /dev/null +++ b/effects/sparks-color.json @@ -0,0 +1,7 @@ +{ + "name" : "Sparks color", + "script" : "sparks-color.py", + "args" : + { + } +} diff --git a/effects/sparks-color.py b/effects/sparks-color.py new file mode 100644 index 00000000..34b5acf5 --- /dev/null +++ b/effects/sparks-color.py @@ -0,0 +1,35 @@ +import hyperion +import time +import colorsys +import random + +# Get the parameters +rotationTime = float(hyperion.args.get('rotation-time', 3.0)) +brightness = float(hyperion.args.get('brightness', 1.0)) +saturation = float(hyperion.args.get('saturation', 1.0)) +reverse = bool(hyperion.args.get('reverse', False)) + +# Check parameters +rotationTime = max(0.1, rotationTime) +brightness = max(0.0, min(brightness, 1.0)) +saturation = max(0.0, min(saturation, 1.0)) + +# Initialize the led data +ledData = bytearray() + +sleepTime = 0.05 + +# Start the write data loop +while not hyperion.abort(): + ledData[:] = bytearray(3*hyperion.ledCount) + for i in range(hyperion.ledCount): + if random.random() < 0.005: + hue = random.random() + sat = 1 + val = 1 + rgb = colorsys.hsv_to_rgb(hue, sat, val) + ledData[i*3] = int(255*rgb[0]) + ledData[i*3+1] = int(255*rgb[1]) + ledData[i*3+2] = int(255*rgb[2]) + hyperion.setColor(ledData) + time.sleep(sleepTime) diff --git a/effects/sparks.json b/effects/sparks.json new file mode 100644 index 00000000..d4040309 --- /dev/null +++ b/effects/sparks.json @@ -0,0 +1,7 @@ +{ + "name" : "Sparks", + "script" : "sparks.py", + "args" : + { + } +} diff --git a/effects/sparks.py b/effects/sparks.py new file mode 100644 index 00000000..821719e2 --- /dev/null +++ b/effects/sparks.py @@ -0,0 +1,33 @@ +import hyperion +import time +import colorsys +import random + +# Get the parameters +rotationTime = float(hyperion.args.get('rotation-time', 3.0)) +brightness = float(hyperion.args.get('brightness', 1.0)) +saturation = float(hyperion.args.get('saturation', 1.0)) +reverse = bool(hyperion.args.get('reverse', False)) + +# Check parameters +rotationTime = max(0.1, rotationTime) +brightness = max(0.0, min(brightness, 1.0)) +saturation = max(0.0, min(saturation, 1.0)) + +# Initialize the led data +ledData = bytearray() +for i in range(hyperion.ledCount): + ledData += bytearray((0, 0, 0)) + +sleepTime = 0.05 + +# Start the write data loop +while not hyperion.abort(): + ledData[:] = bytearray(3*hyperion.ledCount) + for i in range(hyperion.ledCount): + if random.random() < 0.005: + ledData[i*3] = 255 + ledData[i*3+1] = 255 + ledData[i*3+2] = 255 + hyperion.setColor(ledData) + time.sleep(sleepTime) From 2eea311dcef21d6dedc3f1712238b7d1b69c89be Mon Sep 17 00:00:00 2001 From: pcaffardi Date: Sun, 9 Aug 2015 16:15:25 +0200 Subject: [PATCH 02/96] Update LedDeviceAPA102.cpp This fix the previous limit of 64 APA102 leds, because of too short end frame. Now the end frame is computed accordling to this documentation: https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled/. Tested on my 98 leds, it works fine. I suggest to modify hyperion to allow LED drivers to apply the brightness parameter because APA102 has a parameter for that, without the need to elaborate RGB color to simulate it (result is wrong colors!). Is it possible to introduce such parameter in LED drivers and let the driver apply that? Former-commit-id: 2d714e6eb075ec57e0973839fe96d2d7a051c57f --- libsrc/leddevice/LedDeviceAPA102.cpp | 48 ++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/libsrc/leddevice/LedDeviceAPA102.cpp b/libsrc/leddevice/LedDeviceAPA102.cpp index 2af01acf..00eba4bd 100644 --- a/libsrc/leddevice/LedDeviceAPA102.cpp +++ b/libsrc/leddevice/LedDeviceAPA102.cpp @@ -1,4 +1,3 @@ - // STL includes #include #include @@ -18,22 +17,45 @@ LedDeviceAPA102::LedDeviceAPA102(const std::string& outputDevice, const unsigned // empty } +#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MAX(a,b) ((a)>(b)?(a):(b)) + +#define APA102_START_FRAME_BYTES 4 +#define APA102_LED_BYTES 4 +#define APA102_END_FRAME_BITS_MIN 32 +#define APA102_END_FRAME_BITS(leds) MAX((((leds-1)/2)+1),APA102_END_FRAME_BITS_MIN) +#define APA102_END_FRAME_BYTES(leds) (((APA102_END_FRAME_BITS(leds)-1)/8)+1) +#define APA102_LED_HEADER 0xe0 +#define APA102_LED_MAX_INTENSITY 0x1f + int LedDeviceAPA102::write(const std::vector &ledValues) { - const unsigned int startFrameSize = 4; - const unsigned int endFrameSize = (ledValues.size() + 63) / 64 * 4; - const unsigned int mLedCount = (ledValues.size() * 4) + startFrameSize + endFrameSize; - if(_ledBuffer.size() != mLedCount){ - _ledBuffer.resize(mLedCount, 0x00); + const unsigned int startFrameSize = APA102_START_FRAME_BYTES; + const unsigned int ledsCount = ledValues.size() ; + const unsigned int ledsSize = ledsCount * APA102_LED_BYTES ; + const unsigned int endFrameBits = APA102_END_FRAME_BITS(ledsCount) ; + const unsigned int endFrameSize = APA102_END_FRAME_BYTES(ledsCount) ; + const unsigned int transferSize = startFrameSize + ledsSize + endFrameSize ; + + if(_ledBuffer.size() != transferSize){ + _ledBuffer.resize(transferSize, 0x00); + } + + unsigned idx = 0, i; + for (i=0; i &ledValues) int LedDeviceAPA102::switchOff() { return write(std::vector(_ledBuffer.size(), ColorRgb{0,0,0})); -} +} From 7551a06cf4b800b51b284bbf42afbbc92d9015fd Mon Sep 17 00:00:00 2001 From: tociek Date: Thu, 12 Nov 2015 00:22:11 +0100 Subject: [PATCH 03/96] Corrected APA102 USB (adalight) led device I have removed the 'hack' that allowed to use APA102 with original version of adalight. I have modified adalight code and placed it into dependencies folder. This change is not backward compatible, so it won't work with original adalight code. The reason for the change is that last leds were not acting as they should (last led red). Additionally with this change and new arduino code, performance is lot better and lights change much smoother. I have also changed switchOff method that requires different data sent to apa102 to turn all leds off. Enjoy :) Jacek Former-commit-id: 624fe6c429aee896b150d23289f0be19e040474d --- dependencies/LightberryHDUSBAPA1021.1.zip | Bin 0 -> 4443 bytes libsrc/leddevice/LedDeviceAdalightApa102.cpp | 35 ++++++++++++++----- libsrc/leddevice/LedDeviceAdalightApa102.h | 8 +++-- 3 files changed, 32 insertions(+), 11 deletions(-) create mode 100644 dependencies/LightberryHDUSBAPA1021.1.zip diff --git a/dependencies/LightberryHDUSBAPA1021.1.zip b/dependencies/LightberryHDUSBAPA1021.1.zip new file mode 100644 index 0000000000000000000000000000000000000000..13c743a080b77d837e04beb6a62e7e210ae984bc GIT binary patch literal 4443 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 PdnNi~9{quczdrXr;VLB$ literal 0 HcmV?d00001 diff --git a/libsrc/leddevice/LedDeviceAdalightApa102.cpp b/libsrc/leddevice/LedDeviceAdalightApa102.cpp index 07732080..5f5cc42e 100644 --- a/libsrc/leddevice/LedDeviceAdalightApa102.cpp +++ b/libsrc/leddevice/LedDeviceAdalightApa102.cpp @@ -3,7 +3,6 @@ #include #include #include -#include // Linux includes #include @@ -18,24 +17,23 @@ LedDeviceAdalightApa102::LedDeviceAdalightApa102(const std::string& outputDevice _timer() { } -//comparing to ws2801 adalight, the following changes were needed: -// 1- differnt data frame (4 bytes instead of 3) -// 2 - in order to accomodate point 1 above, number of leds sent to adalight is increased by 1/3rd +// see dependencies folder for arduino sketch for APA102 int LedDeviceAdalightApa102::write(const std::vector & ledValues) { + ledCount = ledValues.size(); const unsigned int startFrameSize = 4; const unsigned int endFrameSize = std::max(((ledValues.size() + 15) / 16), 4); const unsigned int mLedCount = (ledValues.size() * 4) + startFrameSize + endFrameSize; - if(_ledBuffer.size() != mLedCount){ - _ledBuffer.resize(mLedCount, 0xFF); + if(_ledBuffer.size() != mLedCount+6){ + _ledBuffer.resize(mLedCount+6, 0x00); _ledBuffer[0] = 'A'; _ledBuffer[1] = 'd'; _ledBuffer[2] = 'a'; - _ledBuffer[3] = (((unsigned int)(ledValues.size() * 1.33) - 1) >> 8) & 0xFF; // LED count high byte - _ledBuffer[4] = ((unsigned int)(ledValues.size() * 1.33) - 1) & 0xFF; // LED count low byte + _ledBuffer[3] = (((unsigned int)(ledValues.size())) >> 8) & 0xFF; // LED count high byte + _ledBuffer[4] = ((unsigned int)(ledValues.size())) & 0xFF; // LED count low byte _ledBuffer[5] = _ledBuffer[3] ^ _ledBuffer[4] ^ 0x55; // Checksum } - + for (unsigned iLed=1; iLed<=ledValues.size(); iLed++) { const ColorRgb& rgb = ledValues[iLed-1]; _ledBuffer[iLed*4+6] = 0xFF; @@ -51,4 +49,23 @@ int LedDeviceAdalightApa102::write(const std::vector & ledValues) return writeBytes(_ledBuffer.size(), _ledBuffer.data()); } +int LedDeviceAdalightApa102::switchOff() +{ + for (unsigned iLed=1; iLed<=ledCount; iLed++) { + _ledBuffer[iLed*4+6] = 0xFF; + _ledBuffer[iLed*4+1+6] = 0x00; + _ledBuffer[iLed*4+2+6] = 0x00; + _ledBuffer[iLed*4+3+6] = 0x00; + } + // restart the timer + _timer.start(); + + // write data + return writeBytes(_ledBuffer.size(), _ledBuffer.data()); +} + +void LedDeviceAdalightApa102::rewriteLeds() +{ + writeBytes(_ledBuffer.size(), _ledBuffer.data()); +} diff --git a/libsrc/leddevice/LedDeviceAdalightApa102.h b/libsrc/leddevice/LedDeviceAdalightApa102.h index a0a7c89c..0c4b502a 100644 --- a/libsrc/leddevice/LedDeviceAdalightApa102.h +++ b/libsrc/leddevice/LedDeviceAdalightApa102.h @@ -32,13 +32,17 @@ public: /// @return Zero on succes else negative /// virtual int write(const std::vector & ledValues); + virtual int switchOff(); - +private slots: + /// Write the last data to the leds again + void rewriteLeds(); + private: /// The buffer containing the packed RGB values std::vector _ledBuffer; - + unsigned int ledCount; /// Timer object which makes sure that led data is written at a minimum rate /// The Adalight device will switch off when it does not receive data at least /// every 15 seconds From fa0b8db1314dd8edd5513d88cee9b5f4b928b5ec Mon Sep 17 00:00:00 2001 From: tociek Date: Mon, 23 Nov 2015 21:47:04 +0100 Subject: [PATCH 04/96] Fix to the adalightapa102 firmware Fix to the firmware when converter would require reconnect after 15 seconds of hyperion inactivity Former-commit-id: 1952eaad1ddbea3ce23252bb1d9c96ba29d72184 --- dependencies/LightberryHDUSBAPA1021.1.zip | Bin 4443 -> 4555 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/dependencies/LightberryHDUSBAPA1021.1.zip b/dependencies/LightberryHDUSBAPA1021.1.zip index 13c743a080b77d837e04beb6a62e7e210ae984bc..45d92c04034381b43ff720b959060fccd2bb4217 100644 GIT binary patch delta 4348 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 Date: Thu, 26 Nov 2015 18:04:43 +0100 Subject: [PATCH 05/96] added the LightberryHDUSBAPA102.1.ino as a source file Former-commit-id: 4923f654cefc5a08df5424e6a2553111e6914b10 --- .../LightberryHDUSBAPA1021.1.ino | 271 ++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino diff --git a/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino b/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino new file mode 100644 index 00000000..e4eca0a4 --- /dev/null +++ b/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino @@ -0,0 +1,271 @@ +// Arduino "bridge" code between host computer and WS2801-based digital +// RGB LED pixels (e.g. Adafruit product ID #322). Intended for use +// with USB-native boards such as Teensy or Adafruit 32u4 Breakout; +// works on normal serial Arduinos, but throughput is severely limited. +// LED data is streamed, not buffered, making this suitable for larger +// installations (e.g. video wall, etc.) than could otherwise be held +// in the Arduino's limited RAM. + +// Some effort is put into avoiding buffer underruns (where the output +// side becomes starved of data). The WS2801 latch protocol, being +// delay-based, could be inadvertently triggered if the USB bus or CPU +// is swamped with other tasks. This code buffers incoming serial data +// and introduces intentional pauses if there's a threat of the buffer +// draining prematurely. The cost of this complexity is somewhat +// reduced throughput, the gain is that most visual glitches are +// avoided (though ultimately a function of the load on the USB bus and +// host CPU, and out of our control). + +// LED data and clock lines are connected to the Arduino's SPI output. +// On traditional Arduino boards, SPI data out is digital pin 11 and +// clock is digital pin 13. On both Teensy and the 32u4 Breakout, +// data out is pin B2, clock is B1. LEDs should be externally +// powered -- trying to run any more than just a few off the Arduino's +// 5V line is generally a Bad Idea. LED ground should also be +// connected to Arduino ground. + +// -------------------------------------------------------------------- +// This file is part of Adalight. + +// Adalight is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. + +// Adalight is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with Adalight. If not, see +// . +// -------------------------------------------------------------------- + +#include + +// LED pin for Adafruit 32u4 Breakout Board: +//#define LED_DDR DDRE +//#define LED_PORT PORTE +//#define LED_PIN _BV(PORTE6) +// LED pin for Teensy: +//#define LED_DDR DDRD +//#define LED_PORT PORTD +//#define LED_PIN _BV(PORTD6) +// LED pin for Arduino: +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN _BV(PORTB5) + +// A 'magic word' (along with LED count & checksum) precedes each block +// of LED data; this assists the microcontroller in syncing up with the +// host-side software and properly issuing the latch (host I/O is +// likely buffered, making usleep() unreliable for latch). You may see +// an initial glitchy frame or two until the two come into alignment. +// The magic word can be whatever sequence you like, but each character +// should be unique, and frequent pixel values like 0 and 255 are +// avoided -- fewer false positives. The host software will need to +// generate a compatible header: immediately following the magic word +// are three bytes: a 16-bit count of the number of LEDs (high byte +// first) followed by a simple checksum value (high byte XOR low byte +// XOR 0x55). LED data follows, 3 bytes per LED, in order R, G, B, +// where 0 = off and 255 = max brightness. + +static const uint8_t magic[] = {'A','d','a'}; +#define MAGICSIZE sizeof(magic) +#define HEADERSIZE (MAGICSIZE + 3) + +#define MODE_HEADER 0 +#define MODE_HOLD 1 +#define MODE_DATA 2 + +#define DATA_LED A5 +#define SPI_LED A3 + +// If no serial data is received for a while, the LEDs are shut off +// automatically. This avoids the annoying "stuck pixel" look when +// quitting LED display programs on the host computer. +static const unsigned long serialTimeout = 15000; // 15 seconds + +void setup() +{ + // Dirty trick: the circular buffer for serial data is 256 bytes, + // and the "in" and "out" indices are unsigned 8-bit types -- this + // much simplifies the cases where in/out need to "wrap around" the + // beginning/end of the buffer. Otherwise there'd be a ton of bit- + // masking and/or conditional code every time one of these indices + // needs to change, slowing things down tremendously. + uint8_t + buffer[256], + indexIn = 0, + indexOut = 0, + mode = MODE_HEADER, + hi, lo, chk, i, spiFlag; + int16_t + bytesBuffered = 0, + hold = 0, + c; + int32_t + bytesRemaining; + unsigned long + startTime, + lastByteTime, + lastAckTime, + t; + bool + data_in_led = false, + spi_out_led = false; + + LED_DDR |= LED_PIN; // Enable output for LED + LED_PORT &= ~LED_PIN; // LED off + pinMode(DATA_LED, OUTPUT); //data in led + pinMode(SPI_LED, OUTPUT); //data out led + + Serial.begin(115200); // Teensy/32u4 disregards baud rate; is OK! + + SPI.begin(); + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + SPI.setClockDivider(SPI_CLOCK_DIV16); // 1 MHz max, else flicker + + // Issue test pattern to LEDs on startup. This helps verify that + // wiring between the Arduino and LEDs is correct. Not knowing the + // actual number of LEDs connected, this sets all of them (well, up + // to the first 25,000, so as not to be TOO time consuming) to red, + // green, blue, then off. Once you're confident everything is working + // end-to-end, it's OK to comment this out and reprogram the Arduino. + uint8_t testcolor[] = { 0, 0, 0, 255, 0, 0 }; + for(int i=0; i<5; i++){ + for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + } + for(char n=3; n>=0; n--) { + for(c=0; c<25000; c++) { + for(i=0; i<3; i++) { + for(SPDR = testcolor[n + i]; !(SPSR & _BV(SPIF)); ); + } + for(i=0; i<1; i++) { + for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); + } + } + for(int i=0; i<16; i++){ + for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + } + delay(1); // One millisecond pause = latch + digitalWrite(SPI_LED, spi_out_led = !spi_out_led); + } + + Serial.print("Ada\n"); // Send ACK string to host + + startTime = micros(); + lastByteTime = lastAckTime = millis(); + + // loop() is avoided as even that small bit of function overhead + // has a measurable impact on this code's overall throughput. + + for(;;) { + digitalWrite(DATA_LED, LOW); + digitalWrite(SPI_LED, LOW); + // Implementation is a simple finite-state machine. + // Regardless of mode, check for serial input each time: + t = millis(); + if((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) { + buffer[indexIn++] = c; + bytesBuffered++; + lastByteTime = lastAckTime = t; // Reset timeout counters + } else { + // No data received. If this persists, send an ACK packet + // to host once every second to alert it to our presence. + if((t - lastAckTime) > 1000) { + Serial.print("Ada\n"); // Send ACK string to host + lastAckTime = t; // Reset counter + } + // If no data received for an extended time, turn off all LEDs. + if((t - lastByteTime) > serialTimeout) { + for(c=0; c<25000; c++) { + for(i=0; i<3; i++) { + for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + } + for(i=0; i<1; i++) { + for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); + } + } + delay(1); // One millisecond pause = latch + lastByteTime = t; // Reset counter + } + } + + switch(mode) { + + case MODE_HEADER: + + // In header-seeking mode. Is there enough data to check? + if(bytesBuffered >= HEADERSIZE) { + // Indeed. Check for a 'magic word' match. + for(i=0; (i 0) and multiply by 3 for R,G,B. + bytesRemaining = 4L * (256L * (long)hi + (long)lo) +4L + (256L *(long)hi + (long)lo +15)/16; + bytesBuffered -= 3; + spiFlag = 0; // No data out yet + mode = MODE_HOLD; // Proceed to latch wait mode + digitalWrite(DATA_LED, data_in_led = !data_in_led); + } else { + // Checksum didn't match; search resumes after magic word. + indexOut -= 3; // Rewind + } + } // else no header match. Resume at first mismatched byte. + bytesBuffered -= i; + } + break; + + case MODE_HOLD: + + // Ostensibly "waiting for the latch from the prior frame + // to complete" mode, but may also revert to this mode when + // underrun prevention necessitates a delay. + + if((micros() - startTime) < hold) break; // Still holding; keep buffering + + // Latch/delay complete. Advance to data-issuing mode... + LED_PORT &= ~LED_PIN; // LED off + mode = MODE_DATA; // ...and fall through (no break): + + case MODE_DATA: + digitalWrite(SPI_LED, spi_out_led = !spi_out_led); + while(spiFlag && !(SPSR & _BV(SPIF))); // Wait for prior byte + if(bytesRemaining > 0) { + if(bytesBuffered > 0) { + SPDR = buffer[indexOut++]; // Issue next byte + bytesBuffered--; + bytesRemaining--; + spiFlag = 1; + } + // If serial buffer is threatening to underrun, start + // introducing progressively longer pauses to allow more + // data to arrive (up to a point). + // if((bytesBuffered < 32) && (bytesRemaining > bytesBuffered)) { + // startTime = micros(); + // hold = 100 + (32 - bytesBuffered) * 10; + // mode = MODE_HOLD; +//} + } else { + // End of data -- issue latch: + startTime = micros(); + hold = 1000; // Latch duration = 1000 uS + LED_PORT |= LED_PIN; // LED on + mode = MODE_HEADER; // Begin next header search + } + } // end switch + } // end for(;;) +} + +void loop() +{ + // Not used. See note in setup() function. +} From cf359e51821ecba664b7cf43e66b2b10288c9955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6ck=2C=20Florian?= Date: Thu, 26 Nov 2015 18:21:20 +0100 Subject: [PATCH 06/96] corrected the source to exactly match the protocol of the APA 102 LED's Former-commit-id: 10d097ff4bbcfa3c717c72138ea0cb1d9e629565 --- dependencies/LightberryHDUSBAPA1021.1.zip | Bin 4555 -> 4567 bytes .../LightberryHDUSBAPA1021.1.ino | 30 ++++++++++-------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/dependencies/LightberryHDUSBAPA1021.1.zip b/dependencies/LightberryHDUSBAPA1021.1.zip index 45d92c04034381b43ff720b959060fccd2bb4217..7a9e6cb1202ba4dc6c24628541a91c3284ab6cb6 100644 GIT binary patch delta 4368 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 n--) { for(c=0; c<25000; c++) { + for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); //Brightness byte for(i=0; i<3; i++) { - for(SPDR = testcolor[n + i]; !(SPSR & _BV(SPIF)); ); - } - for(i=0; i<1; i++) { - for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); + for(SPDR = testcolor[n + i]; !(SPSR & _BV(SPIF)); ); //BGR } } - for(int i=0; i<16; i++){ - for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + for(int i=0; i<4; i++){ //Stop Frame + for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); } delay(1); // One millisecond pause = latch digitalWrite(SPI_LED, spi_out_led = !spi_out_led); @@ -181,14 +179,18 @@ void setup() } // If no data received for an extended time, turn off all LEDs. if((t - lastByteTime) > serialTimeout) { - for(c=0; c<25000; c++) { - for(i=0; i<3; i++) { - for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); - } - for(i=0; i<1; i++) { - for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); - } + for(i=0;i<4;i++) { //Start Frame + for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + } + for(c=0; c<25000; c++) { + for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); //Brightness Byte + for(i=0; i<3; i++) { + for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); //BGR } + } + for(i=0;i<4;i++) { //Stop Frame + for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); + } delay(1); // One millisecond pause = latch lastByteTime = t; // Reset counter } From e7c9d9decd9b77a9e9ffdfc168ae9501814ff128 Mon Sep 17 00:00:00 2001 From: tociek Date: Sat, 28 Nov 2015 22:58:58 +0100 Subject: [PATCH 07/96] Performance fixes for adalightapa102 Adalightapa102 now inherits from RS232Device. Due to bad initialization, previous CPU usage on RPI1 could reach 60%. ON RPi2 20%. Now its about 3% with grabber in use. Former-commit-id: 7ebb72f503ad74a7768deedf648b9e84c0a7cf3c --- libsrc/leddevice/LedDeviceAdalightApa102.cpp | 21 +++++++++++++++----- libsrc/leddevice/LedDeviceAdalightApa102.h | 4 ++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/libsrc/leddevice/LedDeviceAdalightApa102.cpp b/libsrc/leddevice/LedDeviceAdalightApa102.cpp index 5f5cc42e..9cbd3603 100644 --- a/libsrc/leddevice/LedDeviceAdalightApa102.cpp +++ b/libsrc/leddevice/LedDeviceAdalightApa102.cpp @@ -12,18 +12,27 @@ #include "LedDeviceAdalightApa102.h" LedDeviceAdalightApa102::LedDeviceAdalightApa102(const std::string& outputDevice, const unsigned baudrate, int delayAfterConnect_ms) : - LedDeviceAdalight(outputDevice, baudrate, delayAfterConnect_ms), + LedRs232Device(outputDevice, baudrate, delayAfterConnect_ms), _ledBuffer(0), _timer() { + // setup the timer + _timer.setSingleShot(false); + _timer.setInterval(5000); + connect(&_timer, SIGNAL(timeout()), this, SLOT(rewriteLeds())); + + // start the timer + _timer.start(); } -// see dependencies folder for arduino sketch for APA102 +//comparing to ws2801 adalight, the following changes were needed: +// 1- differnt data frame (4 bytes instead of 3) +// 2 - in order to accomodate point 1 above, number of leds sent to adalight is increased by 1/3rd int LedDeviceAdalightApa102::write(const std::vector & ledValues) { ledCount = ledValues.size(); const unsigned int startFrameSize = 4; - const unsigned int endFrameSize = std::max(((ledValues.size() + 15) / 16), 4); - const unsigned int mLedCount = (ledValues.size() * 4) + startFrameSize + endFrameSize; + const unsigned int endFrameSize = std::max(((ledCount + 15) / 16), 4); + const unsigned int mLedCount = (ledCount * 4) + startFrameSize + endFrameSize; if(_ledBuffer.size() != mLedCount+6){ _ledBuffer.resize(mLedCount+6, 0x00); _ledBuffer[0] = 'A'; @@ -34,7 +43,7 @@ int LedDeviceAdalightApa102::write(const std::vector & ledValues) _ledBuffer[5] = _ledBuffer[3] ^ _ledBuffer[4] ^ 0x55; // Checksum } - for (unsigned iLed=1; iLed<=ledValues.size(); iLed++) { + for (unsigned iLed=1; iLed<=ledCount; iLed++) { const ColorRgb& rgb = ledValues[iLed-1]; _ledBuffer[iLed*4+6] = 0xFF; _ledBuffer[iLed*4+1+6] = rgb.red; @@ -57,11 +66,13 @@ int LedDeviceAdalightApa102::switchOff() _ledBuffer[iLed*4+2+6] = 0x00; _ledBuffer[iLed*4+3+6] = 0x00; } + // restart the timer _timer.start(); // write data return writeBytes(_ledBuffer.size(), _ledBuffer.data()); + } void LedDeviceAdalightApa102::rewriteLeds() diff --git a/libsrc/leddevice/LedDeviceAdalightApa102.h b/libsrc/leddevice/LedDeviceAdalightApa102.h index 0c4b502a..eef37662 100644 --- a/libsrc/leddevice/LedDeviceAdalightApa102.h +++ b/libsrc/leddevice/LedDeviceAdalightApa102.h @@ -7,12 +7,12 @@ #include // hyperion incluse -#include "LedDeviceAdalight.h" +#include "LedRs232Device.h" /// /// Implementation of the LedDevice interface for writing to an Adalight led device for APA102. /// -class LedDeviceAdalightApa102 : public LedDeviceAdalight +class LedDeviceAdalightApa102 : public LedRs232Device { Q_OBJECT From f910c717bbf022458049df92ec10da09429dc2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6ck=2C=20Florian?= Date: Sun, 29 Nov 2015 19:24:01 +0100 Subject: [PATCH 08/96] reformated code (Arduino IDE auto-reformat) Former-commit-id: 8f94b2bb865337ba7b0538617857432ea0376aea --- .../LightberryHDUSBAPA1021.1.ino | 208 +++++++++--------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino b/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino index 5d67cedf..7df0e0d9 100644 --- a/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino +++ b/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino @@ -71,7 +71,7 @@ // XOR 0x55). LED data follows, 3 bytes per LED, in order R, G, B, // where 0 = off and 255 = max brightness. -static const uint8_t magic[] = {'A','d','a'}; +static const uint8_t magic[] = {'A', 'd', 'a'}; #define MAGICSIZE sizeof(magic) #define HEADERSIZE (MAGICSIZE + 3) @@ -96,31 +96,31 @@ void setup() // masking and/or conditional code every time one of these indices // needs to change, slowing things down tremendously. uint8_t - buffer[256], - indexIn = 0, - indexOut = 0, - mode = MODE_HEADER, - hi, lo, chk, i, spiFlag; + buffer[256], + indexIn = 0, + indexOut = 0, + mode = MODE_HEADER, + hi, lo, chk, i, spiFlag; int16_t - bytesBuffered = 0, - hold = 0, - c; + bytesBuffered = 0, + hold = 0, + c; int32_t - bytesRemaining; + bytesRemaining; unsigned long - startTime, - lastByteTime, - lastAckTime, - t; - bool - data_in_led = false, - spi_out_led = false; - + startTime, + lastByteTime, + lastAckTime, + t; + bool + data_in_led = false, + spi_out_led = false; + LED_DDR |= LED_PIN; // Enable output for LED LED_PORT &= ~LED_PIN; // LED off pinMode(DATA_LED, OUTPUT); //data in led pinMode(SPI_LED, OUTPUT); //data out led - + Serial.begin(115200); // Teensy/32u4 disregards baud rate; is OK! SPI.begin(); @@ -135,18 +135,18 @@ void setup() // green, blue, then off. Once you're confident everything is working // end-to-end, it's OK to comment this out and reprogram the Arduino. uint8_t testcolor[] = { 0, 0, 0, 255, 0, 0 }; - for(int i=0; i<4; i++){ //Start Frame - for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + for (int i = 0; i < 4; i++) { //Start Frame + for (SPDR = 0x00; !(SPSR & _BV(SPIF)); ); } - for(char n=3; n>=0; n--) { - for(c=0; c<25000; c++) { - for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); //Brightness byte - for(i=0; i<3; i++) { - for(SPDR = testcolor[n + i]; !(SPSR & _BV(SPIF)); ); //BGR + for (char n = 3; n >= 0; n--) { + for (c = 0; c < 25000; c++) { + for (SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); //Brightness byte + for (i = 0; i < 3; i++) { + for (SPDR = testcolor[n + i]; !(SPSR & _BV(SPIF)); ); //BGR } } - for(int i=0; i<4; i++){ //Stop Frame - for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); + for (int i = 0; i < 4; i++) { //Stop Frame + for (SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); } delay(1); // One millisecond pause = latch digitalWrite(SPI_LED, spi_out_led = !spi_out_led); @@ -160,109 +160,109 @@ void setup() // loop() is avoided as even that small bit of function overhead // has a measurable impact on this code's overall throughput. - for(;;) { + for (;;) { digitalWrite(DATA_LED, LOW); digitalWrite(SPI_LED, LOW); // Implementation is a simple finite-state machine. // Regardless of mode, check for serial input each time: t = millis(); - if((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) { + if ((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) { buffer[indexIn++] = c; bytesBuffered++; lastByteTime = lastAckTime = t; // Reset timeout counters } else { // No data received. If this persists, send an ACK packet // to host once every second to alert it to our presence. - if((t - lastAckTime) > 1000) { + if ((t - lastAckTime) > 1000) { Serial.print("Ada\n"); // Send ACK string to host lastAckTime = t; // Reset counter } // If no data received for an extended time, turn off all LEDs. - if((t - lastByteTime) > serialTimeout) { - for(i=0;i<4;i++) { //Start Frame - for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + if ((t - lastByteTime) > serialTimeout) { + for (i = 0; i < 4; i++) { //Start Frame + for (SPDR = 0x00; !(SPSR & _BV(SPIF)); ); } - for(c=0; c<25000; c++) { - for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); //Brightness Byte - for(i=0; i<3; i++) { - for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); //BGR + for (c = 0; c < 25000; c++) { + for (SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); //Brightness Byte + for (i = 0; i < 3; i++) { + for (SPDR = 0x00; !(SPSR & _BV(SPIF)); ); //BGR } } - for(i=0;i<4;i++) { //Stop Frame - for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); + for (i = 0; i < 4; i++) { //Stop Frame + for (SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); } delay(1); // One millisecond pause = latch lastByteTime = t; // Reset counter } } - switch(mode) { + switch (mode) { - case MODE_HEADER: + case MODE_HEADER: - // In header-seeking mode. Is there enough data to check? - if(bytesBuffered >= HEADERSIZE) { - // Indeed. Check for a 'magic word' match. - for(i=0; (i 0) and multiply by 3 for R,G,B. - bytesRemaining = 4L * (256L * (long)hi + (long)lo) +4L + (256L *(long)hi + (long)lo +15)/16; - bytesBuffered -= 3; - spiFlag = 0; // No data out yet - mode = MODE_HOLD; // Proceed to latch wait mode - digitalWrite(DATA_LED, data_in_led = !data_in_led); - } else { - // Checksum didn't match; search resumes after magic word. - indexOut -= 3; // Rewind - } - } // else no header match. Resume at first mismatched byte. - bytesBuffered -= i; - } - break; - - case MODE_HOLD: - - // Ostensibly "waiting for the latch from the prior frame - // to complete" mode, but may also revert to this mode when - // underrun prevention necessitates a delay. - - if((micros() - startTime) < hold) break; // Still holding; keep buffering - - // Latch/delay complete. Advance to data-issuing mode... - LED_PORT &= ~LED_PIN; // LED off - mode = MODE_DATA; // ...and fall through (no break): - - case MODE_DATA: - digitalWrite(SPI_LED, spi_out_led = !spi_out_led); - while(spiFlag && !(SPSR & _BV(SPIF))); // Wait for prior byte - if(bytesRemaining > 0) { - if(bytesBuffered > 0) { - SPDR = buffer[indexOut++]; // Issue next byte - bytesBuffered--; - bytesRemaining--; - spiFlag = 1; + // In header-seeking mode. Is there enough data to check? + if (bytesBuffered >= HEADERSIZE) { + // Indeed. Check for a 'magic word' match. + for (i = 0; (i < MAGICSIZE) && (buffer[indexOut++] == magic[i++]);); + if (i == MAGICSIZE) { + // Magic word matches. Now how about the checksum? + hi = buffer[indexOut++]; + lo = buffer[indexOut++]; + chk = buffer[indexOut++]; + if (chk == (hi ^ lo ^ 0x55)) { + // Checksum looks valid. Get 16-bit LED count, add 1 + // (# LEDs is always > 0) and multiply by 3 for R,G,B. + bytesRemaining = 4L * (256L * (long)hi + (long)lo) + 4L + (256L * (long)hi + (long)lo + 15) / 16; + bytesBuffered -= 3; + spiFlag = 0; // No data out yet + mode = MODE_HOLD; // Proceed to latch wait mode + digitalWrite(DATA_LED, data_in_led = !data_in_led); + } else { + // Checksum didn't match; search resumes after magic word. + indexOut -= 3; // Rewind + } + } // else no header match. Resume at first mismatched byte. + bytesBuffered -= i; + } + break; + + case MODE_HOLD: + + // Ostensibly "waiting for the latch from the prior frame + // to complete" mode, but may also revert to this mode when + // underrun prevention necessitates a delay. + + if ((micros() - startTime) < hold) break; // Still holding; keep buffering + + // Latch/delay complete. Advance to data-issuing mode... + LED_PORT &= ~LED_PIN; // LED off + mode = MODE_DATA; // ...and fall through (no break): + + case MODE_DATA: + digitalWrite(SPI_LED, spi_out_led = !spi_out_led); + while (spiFlag && !(SPSR & _BV(SPIF))); // Wait for prior byte + if (bytesRemaining > 0) { + if (bytesBuffered > 0) { + SPDR = buffer[indexOut++]; // Issue next byte + bytesBuffered--; + bytesRemaining--; + spiFlag = 1; + } + // If serial buffer is threatening to underrun, start + // introducing progressively longer pauses to allow more + // data to arrive (up to a point). + // if((bytesBuffered < 32) && (bytesRemaining > bytesBuffered)) { + // startTime = micros(); + // hold = 100 + (32 - bytesBuffered) * 10; + // mode = MODE_HOLD; + //} + } else { + // End of data -- issue latch: + startTime = micros(); + hold = 1000; // Latch duration = 1000 uS + LED_PORT |= LED_PIN; // LED on + mode = MODE_HEADER; // Begin next header search } - // If serial buffer is threatening to underrun, start - // introducing progressively longer pauses to allow more - // data to arrive (up to a point). - // if((bytesBuffered < 32) && (bytesRemaining > bytesBuffered)) { - // startTime = micros(); - // hold = 100 + (32 - bytesBuffered) * 10; - // mode = MODE_HOLD; -//} - } else { - // End of data -- issue latch: - startTime = micros(); - hold = 1000; // Latch duration = 1000 uS - LED_PORT |= LED_PIN; // LED on - mode = MODE_HEADER; // Begin next header search - } } // end switch } // end for(;;) } From 4cdba8cdb689cf158074b179136c3f5a75d98f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6ck=2C=20Florian?= Date: Sun, 29 Nov 2015 19:31:51 +0100 Subject: [PATCH 09/96] fixed boot animation Former-commit-id: 418ed83a4bd4ddaae79bf41de7fd9fb0794f8239 --- .../LightberryHDUSBAPA1021.1.ino | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino b/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino index 7df0e0d9..e10c8c3b 100644 --- a/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino +++ b/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino @@ -135,10 +135,10 @@ void setup() // green, blue, then off. Once you're confident everything is working // end-to-end, it's OK to comment this out and reprogram the Arduino. uint8_t testcolor[] = { 0, 0, 0, 255, 0, 0 }; - for (int i = 0; i < 4; i++) { //Start Frame - for (SPDR = 0x00; !(SPSR & _BV(SPIF)); ); - } for (char n = 3; n >= 0; n--) { + for (int i = 0; i < 4; i++) { //Start Frame + for (SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + } for (c = 0; c < 25000; c++) { for (SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); //Brightness byte for (i = 0; i < 3; i++) { @@ -148,9 +148,10 @@ void setup() for (int i = 0; i < 4; i++) { //Stop Frame for (SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); } + delay(1); // One millisecond pause = latch - digitalWrite(SPI_LED, spi_out_led = !spi_out_led); } + digitalWrite(SPI_LED, spi_out_led = !spi_out_led); Serial.print("Ada\n"); // Send ACK string to host From f950ec7df6dbd5627bd6870616736f725a2dbb00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6ck=2C=20Florian?= Date: Sun, 29 Nov 2015 19:35:26 +0100 Subject: [PATCH 10/96] changed the SPI frequency to 2 Mhz. APA102 can handle MUCH higher frequencies than WS2801, so 2Mhz is no big deal for them Former-commit-id: 814faa648e4f39d7105710ff872bde00aaeaada9 --- .../LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino b/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino index e10c8c3b..4a02d71a 100644 --- a/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino +++ b/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino @@ -126,7 +126,7 @@ void setup() SPI.begin(); SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE0); - SPI.setClockDivider(SPI_CLOCK_DIV16); // 1 MHz max, else flicker + SPI.setClockDivider(SPI_CLOCK_DIV8); // 2Mhz // Issue test pattern to LEDs on startup. This helps verify that // wiring between the Arduino and LEDs is correct. Not knowing the From 8d52466acdaa180651db17eb818c77606075e3c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6ck=2C=20Florian?= Date: Sun, 29 Nov 2015 19:38:40 +0100 Subject: [PATCH 11/96] re-added buffer underrun handling should not be necessary because the number of LED's in a usual Lightberry setup is to low, but it's nice to have implemented. Former-commit-id: def3c46687670439be572e6b9c2dd1de5be2f1b5 --- .../LightberryHDUSBAPA1021.1.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino b/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino index 4a02d71a..603599c9 100644 --- a/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino +++ b/dependencies/LightberryHDUSBAPA1021.1/LightberryHDUSBAPA1021.1.ino @@ -252,11 +252,11 @@ void setup() // If serial buffer is threatening to underrun, start // introducing progressively longer pauses to allow more // data to arrive (up to a point). - // if((bytesBuffered < 32) && (bytesRemaining > bytesBuffered)) { - // startTime = micros(); - // hold = 100 + (32 - bytesBuffered) * 10; - // mode = MODE_HOLD; - //} + if ((bytesBuffered < 32) && (bytesRemaining > bytesBuffered)) { + startTime = micros(); + hold = 100 + (32 - bytesBuffered) * 10; + mode = MODE_HOLD; + } } else { // End of data -- issue latch: startTime = micros(); From b898f25f980f804df4fff6aa555f3c386b456d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6ck=2C=20Florian?= Date: Sun, 29 Nov 2015 19:56:33 +0100 Subject: [PATCH 12/96] updated zip to match newest source Former-commit-id: 2e54f40d48a993a66f07f5b655965847a9bf7d14 --- dependencies/LightberryHDUSBAPA1021.1.zip | Bin 4567 -> 4548 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/dependencies/LightberryHDUSBAPA1021.1.zip b/dependencies/LightberryHDUSBAPA1021.1.zip index 7a9e6cb1202ba4dc6c24628541a91c3284ab6cb6..af1527aecae1ce355ffcfb87ef4cbd813a79f5fa 100644 GIT binary patch delta 4318 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 M0002I5C8xG06yM4nE(I) delta 4367 zcmY+I^;Z;(wub30=^S!MrE!K~NJ&8&9J&!k1f(S#Lb|)Vq*F>7l_6Zc=0uTcS(PI63JmdV6$tB5sQ~cGa188|vsIai0$=Y&= z*KT%FRQCl|VzkjuxnBG!5<=qW&wKfDue?bw>krl4`+mg33qlQCy*_t6AA}wt1{XqHwR4cu-P}% zxYA=hjjYezzh3DJaVl$yN#RpQk#G9@d^E-$IA9NHqiwUw<tdOD0Qq z|G)^~&Z9B^-VmAlX^jLyRaM)#Oy>Mj)f3i=G}+u)V(66aI4X}zQR)gO*WTm3fsU20 zxJI=)H8nBPRLN(4R1VEs7&lI&m`!7E*#*swm!P{Zaz#V)Wg|mCVIvV~Z%4X^xyQKA+@9Q80=q zJvbg(a6mhb_pA;0oj_tPgd~tm&1XR7i2C)}y3fzZyGB{pUf$Cxi+$JzZ}3zM&em=P zs6Iv&FBlxO!P48)!>)h37VxKc4b#3szF|dl^LC{~Lj@s<8!FcSwKGp}2yXWftFm+wa3XEt-r4Fc1gV1>K(zVaT8 zt{)J7gX>R(>#Okm27~bR6R!$#U&`<@i`oZ?qR{4exXnZ~Yf!F-a*r5jli*$cv0d$@y$l>$=#gua)Pxxh=!Bm9e&|0RFw1tTQzkEH7EA&_p z2u2_WwP+?C>0u%EVo@Frk>&VWqWG(vI?&egVoH32X>S2?m}**GSa|Ay95nsxJE=vV zao41zL_SQIyZM@4?xnVaB5%=~S060HWX0wBIhNVCcXbl0KejTkLa0MhTUr=!$>1q0 zJYI=&E0U%)ASmV*tfPU|*2~cK_){x17*W>7L`9qZssG^kYn8DR#}5v*$pc;r6+7h> zVW8oRc|X5GhMrET1>VU_h|k@jyS>tQyYfp1DR$>f{R!?_Yp&%1M!TKBk9<;1=lmC1 zGybV{bDT0P2ZXv}yD0vPz)LTmh-0eAQc`su4Gqyml~7!5?z}g`$MZLQHSQ?Q1oW{OW2V#%>LtmA&o) zKdl1Vn*5u?H`58P^ln{R2;>qp5tT~3^ISd+SoU`n3>r-WeiO8&j&9M_yP<{SjF0mT zjRvNdb)b3WpH(N<)PdEH>$HLcht&v{kBQ=;E8AXV6KNKUrm7CAPkgICwZ#H#L4>v=Tt{&>e;G9J+$g3c`eeA(oY}sc z&Y-R<_a%KyqV)oIc_BDR;*8+fEDIH$V~%7LXYG6Ls9q*h_3{m3tFmp>cWc2Tqph&u z*cEfsX`aY*_wF!;Oneo8dOb>ypB=Jv6)kYc;qPj@WlbDi2SrN#;qP3Pe{XK^PIIcYRj2eQyF$2x0MT^-wNX*g(DBfl2jRe+MN^* zuRh<}*o+cQdXGsOI=Kr3N;9{;2-zdE6oH2(+mK93 z2GNK}QzZebeh@!w2BTJ)3H4cM46oEusT|Oi;+}{DzDsK?jW$i)3pB6_ivs#rAahd_ zn~zFX)UF#%l@;CFkV4uFvdyF;QL zDbu^5T&*4Q^tF8X^pB6ORZ@maswSn5UR4GpW$#?@%Nyp^tL_;>M9)@o3+&%2qdV^U`q`xqkwiAvjq!s=*f9ej=wBvCHo1BG2 zk1HGbYlw_(^c7MkhyvBPYq@dR%{7lc(ji0)vWvyTKL~1iCs%(>VM+Ww&QFoDNX)ve z78AM0rCH|5gT4}K$cw~F%pr004{)I zOP;bV8Hh7Zgb`A!RPJMZdOom}f-{2f9JNI7;=Z0|ZBZ#G4bJW`4ROjpO!T5?a)`_` za*i|cnRh`1vMmW_SPoFL-O` zP4kci7Wy!M{;+Bl>skZX$e-4TCmK!!-8?e=LYRtGR>1E~)4!7MofQ+JYNGekw1I{S zJLo5Q(hQwWCZ@vkv`)m$ZuFpu(SP;k?Nlk)&qq!*jcn{bWLBH2kZ3i2C^XqZFwj4qAyn+3 z*Phbg2s6p9m^l=yhb@L&@zY9_97)feh9@GQhGLg=LkEILD{>qns2W)MwN~M~;r`a& zSDB+PdQ|s0pih@ZY^VC&4qMY%G277_gcc6;TGlOiWUEkyO4HF3+9&O6D~kBb4%ZKn+_aACP(_#>`r>7Wm-GpNg?`lbC*96j z`@fG3I3vaLZgU7w6$ALz zQI%cMQDzQHT*9ujaATZh#x&x2YznK9-12X8x6ZIJxS(zWgaP|9G+x%O2Y8<@SXIrm zM(n1~+MC$Pc4U~P8*xw&R>ctaCYy1ho)>3bSWm2y^Ze(u@P(rOwi&(hb#XOor)PYe zyMeG{o2<5HwKf?xxm+Iu+lQ6RV9-^IS-ZstuT5TLhC;G{!X5aWdGtB;(kFta%Zn=F zQS%lBTQ_{~5G7{mC7?dXRJyW`7sv!gL>PJtT_dxves9iwlWB?Je{ckLK38$2z+M!t z3|nT&NXh^fq&jsr`Zj0T?K3KlyazGJe@@K)9`JeoaMXO{t*OVW%3+7dwhqX*6@`Vd zQ#%dF(D*aS2ukt&+m1vQLjUf>Nu*4!$lEI3hLPz3#G}&Q9`t(2edv8mcKzUvaErs( zd^(%`O|%Z7+DaJ=QTC+}&Xv{P*x%_yEl3#}5Ox*zLt zZDXEmft5w4uIq@5E)6fN);>xq4f?qU`JNH#YGUKaWBreYQ2Q?*@!uzPi3%jf1GV>e z;-AC*PvYTKS^vBLFGz&-|HMVA!XsnhGL@S$*Z)KPht}1^C;0bwoPYM>pPczebzour E3nIf=oB#j- From 8a6414b2509877202abdaa32c12ae2b68f21807b Mon Sep 17 00:00:00 2001 From: snoerenberg Date: Wed, 9 Dec 2015 16:08:26 +0100 Subject: [PATCH 13/96] New X-Mas Effect added Former-commit-id: d34644b1cab491b4f5c326d77098d9ee198f0b11 --- effects/x-mas.json | 8 ++++++++ effects/x-mas.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 effects/x-mas.json create mode 100644 effects/x-mas.py diff --git a/effects/x-mas.json b/effects/x-mas.json new file mode 100644 index 00000000..99bece03 --- /dev/null +++ b/effects/x-mas.json @@ -0,0 +1,8 @@ +{ + "name" : "X-Mas", + "script" : "x-mas.py", + "args" : + { + "frequency" : 50.0 + } +} diff --git a/effects/x-mas.py b/effects/x-mas.py new file mode 100644 index 00000000..bdeda2e7 --- /dev/null +++ b/effects/x-mas.py @@ -0,0 +1,34 @@ +import hyperion +import time +import colorsys + +# Get the parameters +frequency = float(hyperion.args.get('frequency', 10.0)) + +# Check parameters +frequency = min(100.0, frequency) + +# Compute the strobe interval +sleepTime = 1.0 / frequency + +# Initialize the led data +ledDataOdd = bytearray() +for i in range(hyperion.ledCount): + if i%2 == 0: + ledDataOdd += bytearray((int(255), int(0), int(0))) + else: + ledDataOdd += bytearray((int(255), int(255), int(255))) + +ledDataEven = bytearray() +for i in range(hyperion.ledCount): + if i%2 == 0: + ledDataEven += bytearray((int(255), int(255), int(255))) + else: + ledDataEven += bytearray((int(255), int(0), int(0))) + +# Start the write data loop +while not hyperion.abort(): + hyperion.setColor(ledDataOdd) + time.sleep(0.75) + hyperion.setColor(ledDataEven) + time.sleep(0.75) \ No newline at end of file From d3b3ce7630d524e82ff212cf658e99f1a6ea3064 Mon Sep 17 00:00:00 2001 From: snoerenberg Date: Wed, 9 Dec 2015 16:18:08 +0100 Subject: [PATCH 14/96] New X-Mas Effect added Former-commit-id: b5fb724f5b07f1cd55fef620c02f285522680cf6 --- effects/x-mas.json | 2 +- effects/x-mas.py | 12 +++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/effects/x-mas.json b/effects/x-mas.json index 99bece03..72892a52 100644 --- a/effects/x-mas.json +++ b/effects/x-mas.json @@ -3,6 +3,6 @@ "script" : "x-mas.py", "args" : { - "frequency" : 50.0 + "sleepTime" : 0.75 } } diff --git a/effects/x-mas.py b/effects/x-mas.py index bdeda2e7..697d6f71 100644 --- a/effects/x-mas.py +++ b/effects/x-mas.py @@ -3,13 +3,7 @@ import time import colorsys # Get the parameters -frequency = float(hyperion.args.get('frequency', 10.0)) - -# Check parameters -frequency = min(100.0, frequency) - -# Compute the strobe interval -sleepTime = 1.0 / frequency +sleepTime = float(hyperion.args.get('sleepTime', 1.0)) # Initialize the led data ledDataOdd = bytearray() @@ -29,6 +23,6 @@ for i in range(hyperion.ledCount): # Start the write data loop while not hyperion.abort(): hyperion.setColor(ledDataOdd) - time.sleep(0.75) + time.sleep(sleepTime) hyperion.setColor(ledDataEven) - time.sleep(0.75) \ No newline at end of file + time.sleep(sleepTime) \ No newline at end of file From 45d3572df166da712825e6d3fbe430b92fd78da7 Mon Sep 17 00:00:00 2001 From: guddimon- Date: Mon, 14 Dec 2015 00:15:15 +0100 Subject: [PATCH 15/96] always work with trimmed messages Former-commit-id: a2b3236d22cd935c03a13dfe579c411c648c7dfd --- libsrc/boblightserver/BoblightClientConnection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/boblightserver/BoblightClientConnection.cpp b/libsrc/boblightserver/BoblightClientConnection.cpp index f78d6784..7599220a 100644 --- a/libsrc/boblightserver/BoblightClientConnection.cpp +++ b/libsrc/boblightserver/BoblightClientConnection.cpp @@ -64,8 +64,8 @@ void BoblightClientConnection::readData() // remove message data from buffer _receiveBuffer = _receiveBuffer.mid(bytes); - // handle message - handleMessage(message); + // handle trimmed message + handleMessage(message.trimmed()); // drop messages if the buffer is too full if (_receiveBuffer.size() > 100*1024) From 87f2883f565d5e5287fe44feba90f7fd54a14e15 Mon Sep 17 00:00:00 2001 From: guddimon- Date: Mon, 14 Dec 2015 00:23:53 +0100 Subject: [PATCH 16/96] replace decimal comma with decimal point Former-commit-id: ec4b3c264fb06143b2e4d635358f259fb7099ed9 --- libsrc/boblightserver/BoblightClientConnection.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libsrc/boblightserver/BoblightClientConnection.cpp b/libsrc/boblightserver/BoblightClientConnection.cpp index 7599220a..e70a8f17 100644 --- a/libsrc/boblightserver/BoblightClientConnection.cpp +++ b/libsrc/boblightserver/BoblightClientConnection.cpp @@ -132,9 +132,15 @@ void BoblightClientConnection::handleMessage(const QString & message) { if (messageParts[3] == "rgb" && messageParts.size() == 7) { + // replace decimal comma with decimal point + messageParts[4].replace(',', '.'); + messageParts[5].replace(',', '.'); + messageParts[6].replace(',', '.'); + bool rc1, rc2, rc3; uint8_t red = qMax(0, qMin(255, int(255 * messageParts[4].toFloat(&rc1)))); + // check for correct locale should not be needed anymore - please check! if (!rc1) { // maybe a locale issue. switch to a locale with a comma instead of a dot as decimal seperator (or vice versa) From 469ea42f49dc986d0bc507c5d6b1fa4adca0156d Mon Sep 17 00:00:00 2001 From: wisc Date: Sat, 2 Jan 2016 02:31:13 +0100 Subject: [PATCH 17/96] check for black pixel at center x/y Former-commit-id: d91f422f55638418d2517d91b1c925880d7ca448 --- include/blackborder/BlackBorderDetector.h | 41 +++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/include/blackborder/BlackBorderDetector.h b/include/blackborder/BlackBorderDetector.h index c5ee91e7..3f190c5c 100644 --- a/include/blackborder/BlackBorderDetector.h +++ b/include/blackborder/BlackBorderDetector.h @@ -61,11 +61,51 @@ namespace hyperion template BlackBorder process(const Image & image) { + + // only test the topleft third of the image + int width = image.width() / 3; + int height = image.height() / 3; + int xCenter = image.width() / 2; + int yCenter = image.height() / 2; +// int maxSize = std::max(width, height); + + + + int firstNonBlackXPixelIndex = -1; + int firstNonBlackYPixelIndex = -1; + + // find first X pixel of the image + for (int x = 0; x < width; ++x) + { + const Pixel_T & color = image(x, yCenter); + if (!isBlack(color)) + { + firstNonBlackXPixelIndex = x; + break; + } + } + + // find first Y pixel of the image + for (int y = 0; y < height; ++y) + { + const Pixel_T & color = image(xCenter, y); + if (!isBlack(color)) + { + firstNonBlackYPixelIndex = y; + break; + } + } + + + +/* // only test the topleft third of the image int width = image.width() /3; int height = image.height() / 3; int maxSize = std::max(width, height); + + int firstNonBlackXPixelIndex = -1; int firstNonBlackYPixelIndex = -1; @@ -103,6 +143,7 @@ namespace hyperion break; } } +*/ // Construct result BlackBorder detectedBorder; From 633985930b8ba55e001656d06f81b0034613e37c Mon Sep 17 00:00:00 2001 From: wisc Date: Mon, 4 Jan 2016 00:20:47 +0100 Subject: [PATCH 18/96] 3line detection Former-commit-id: a63c03bc276ef218981213fbb9743a3d6d12d8b6 --- include/blackborder/BlackBorderDetector.h | 14 ++++++++++---- libsrc/blackborder/BlackBorderProcessor.cpp | 21 +++++++++++++++------ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/include/blackborder/BlackBorderDetector.h b/include/blackborder/BlackBorderDetector.h index 3f190c5c..cd955b8a 100644 --- a/include/blackborder/BlackBorderDetector.h +++ b/include/blackborder/BlackBorderDetector.h @@ -65,6 +65,8 @@ namespace hyperion // only test the topleft third of the image int width = image.width() / 3; int height = image.height() / 3; + int width2 = width * 2; + int height2 = height * 2; int xCenter = image.width() / 2; int yCenter = image.height() / 2; // int maxSize = std::max(width, height); @@ -77,8 +79,10 @@ namespace hyperion // find first X pixel of the image for (int x = 0; x < width; ++x) { - const Pixel_T & color = image(x, yCenter); - if (!isBlack(color)) + const Pixel_T & color1 = image(x, yCenter); + const Pixel_T & color2 = image(x, height); + const Pixel_T & color3 = image(x, height2); + if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3)) { firstNonBlackXPixelIndex = x; break; @@ -88,8 +92,10 @@ namespace hyperion // find first Y pixel of the image for (int y = 0; y < height; ++y) { - const Pixel_T & color = image(xCenter, y); - if (!isBlack(color)) + const Pixel_T & color1 = image(xCenter, y); + const Pixel_T & color2 = image(width, y); + const Pixel_T & color3 = image(width2, y); + if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3)) { firstNonBlackYPixelIndex = y; break; diff --git a/libsrc/blackborder/BlackBorderProcessor.cpp b/libsrc/blackborder/BlackBorderProcessor.cpp index ee78efb9..b9c21eea 100644 --- a/libsrc/blackborder/BlackBorderProcessor.cpp +++ b/libsrc/blackborder/BlackBorderProcessor.cpp @@ -1,4 +1,4 @@ - +//#include // Blackborder includes #include @@ -29,7 +29,10 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) // set the consistency counter if (newDetectedBorder == _previousDetectedBorder) { - ++_consistentCnt; + if (_consistentCnt < 100000) + { + ++_consistentCnt; + } } else { @@ -37,6 +40,8 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) _consistentCnt = 0; } +// std::cout << "new: " << newDetectedBorder.verticalSize << " " << newDetectedBorder.horizontalSize << " cur: " << _currentBorder.verticalSize << " " << _currentBorder.horizontalSize << " cc " << _consistentCnt << std::endl; + // check if there is a change if (_currentBorder == newDetectedBorder) { @@ -48,7 +53,8 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) if (newDetectedBorder.unknown) { // apply the unknown border if we consistently can't determine a border - if (_consistentCnt == _unknownSwitchCnt) +// if (_consistentCnt == _unknownSwitchCnt) + if (_consistentCnt >= _unknownSwitchCnt) { _currentBorder = newDetectedBorder; borderChanged = true; @@ -57,7 +63,8 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) else { // apply the detected border if it has been detected consistently - if (_currentBorder.unknown || _consistentCnt == _borderSwitchCnt) +// if (_currentBorder.unknown || _consistentCnt == _borderSwitchCnt) + if (_currentBorder.unknown || _consistentCnt >= _borderSwitchCnt) { _currentBorder = newDetectedBorder; borderChanged = true; @@ -65,13 +72,15 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) else { // apply smaller borders immediately - if (newDetectedBorder.verticalSize < _currentBorder.verticalSize) +// if (newDetectedBorder.verticalSize < _currentBorder.verticalSize) + if ( (newDetectedBorder.verticalSize < _currentBorder.verticalSize) && (_consistentCnt >= 1) )// almost immediatly - avoid switching for "abnormal" frames { _currentBorder.verticalSize = newDetectedBorder.verticalSize; borderChanged = true; } - if (newDetectedBorder.horizontalSize < _currentBorder.horizontalSize) +// if (newDetectedBorder.horizontalSize < _currentBorder.horizontalSize) + if ( (newDetectedBorder.horizontalSize < _currentBorder.horizontalSize) && (_consistentCnt >= 1) ) { _currentBorder.horizontalSize = newDetectedBorder.horizontalSize; borderChanged = true; From 0dcacede815f8dc31adfc87496f17a806cdc5bd7 Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 4 Jan 2016 12:06:56 +0100 Subject: [PATCH 19/96] add fadecandy led device Former-commit-id: 4076e6ec2860ceaa53fdd07c47c40e45f2329de9 --- libsrc/leddevice/LedDeviceFadeCandy.cpp | 89 +++++++++++++++++++++++++ libsrc/leddevice/LedDeviceFadeCandy.h | 55 +++++++++++++++ 2 files changed, 144 insertions(+) create mode 100755 libsrc/leddevice/LedDeviceFadeCandy.cpp create mode 100755 libsrc/leddevice/LedDeviceFadeCandy.h diff --git a/libsrc/leddevice/LedDeviceFadeCandy.cpp b/libsrc/leddevice/LedDeviceFadeCandy.cpp new file mode 100755 index 00000000..ec6da6a2 --- /dev/null +++ b/libsrc/leddevice/LedDeviceFadeCandy.cpp @@ -0,0 +1,89 @@ + +// Local-Hyperion includes +#include "LedDeviceFadeCandy.h" +#include +#include +#include + +static const unsigned MAX_NUM_LEDS = 512; + +/* OPC broadcast channel */ +static const unsigned OPC_BROADCAST = 0; + +/* OPC command codes */ +static const unsigned OPC_SET_PIXELS = 0; + +LedDeviceFadeCandy::LedDeviceFadeCandy(const std::string& host, const uint16_t port) + : _host(host), _port(port) +{ + _opc_data.resize(4); + _opc_data[0] = OPC_BROADCAST; + _opc_data[1] = OPC_SET_PIXELS; + _opc_data[2] = 0; + _opc_data[3] = 0; + + qDebug("connect to %s %i",_host.c_str(),_port); +} + +LedDeviceFadeCandy::~LedDeviceFadeCandy() +{ + _client.close(); +} + +bool LedDeviceFadeCandy::isConnected() +{ + return _client.state() == QAbstractSocket::ConnectedState; +} + +bool LedDeviceFadeCandy::tryConnect() +{ + if ( _client.state() == QAbstractSocket::UnconnectedState ) { + qDebug("connecting"); + QHostAddress addr(_host.c_str()); + _client.connectToHost(addr, _port); + if (_client.waitForConnected(1000)) + qDebug("connected"); + } + + return isConnected(); +} + + +int LedDeviceFadeCandy::write(const std::vector & ledValues) +{ + ssize_t nrLedValues = ledValues.size(); + ssize_t led_data_size = nrLedValues*3; // 3 color bytes + ssize_t opc_data_size = led_data_size +4; // + 4 byte header + + if (nrLedValues > MAX_NUM_LEDS) + { + std::cerr << "Invalid attempt to write led values. Not more than " << MAX_NUM_LEDS << " leds are allowed." << std::endl; + return -1; + } + + if ( opc_data_size != _opc_data.size()) + _opc_data.resize(opc_data_size); + + _opc_data[2] = led_data_size >> 8; + _opc_data[3] = led_data_size & 0xff; + + if ( isConnected() || tryConnect() ) { + u_int16_t idx = 4; + for (const ColorRgb& color : ledValues) + { + _opc_data[idx] = unsigned(color.red); + _opc_data[idx+1] = unsigned(color.green); + _opc_data[idx+2] = unsigned(color.blue); + idx += 3; + } + _client.write(_opc_data, opc_data_size); + } + + return 0; +} + + +int LedDeviceFadeCandy::switchOff() +{ + return 0; +} diff --git a/libsrc/leddevice/LedDeviceFadeCandy.h b/libsrc/leddevice/LedDeviceFadeCandy.h new file mode 100755 index 00000000..0973368b --- /dev/null +++ b/libsrc/leddevice/LedDeviceFadeCandy.h @@ -0,0 +1,55 @@ +#pragma once + +// STL includes0 +#include +#include +#include +#include +#include +#include + +// Leddevice includes +#include + + +/// +/// Implementation of the LedDevice that write the led-colors to an +/// ASCII-textfile('/home/pi/LedDevice.out') +/// +class LedDeviceFadeCandy : public QObject,public LedDevice +{ + Q_OBJECT +public: + /// + /// Constructs the test-device, which opens an output stream to the file + /// + LedDeviceFadeCandy(const std::string& host, const uint16_t port); + + /// + /// Destructor of this test-device + /// + virtual ~LedDeviceFadeCandy(); + + /// + /// Writes the given led-color values to the output stream + /// + /// @param ledValues The color-value per led + /// + /// @return Zero on success else negative + /// + virtual int write(const std::vector & ledValues); + + /// Switch the leds off + virtual int switchOff(); + + bool tryConnect(); + bool isConnected(); + +//public slots: + +private: + QTcpSocket _client; + const std::string _host; + const uint16_t _port; + QByteArray _opc_data; +}; From 13715202d8e25d2fca75dbe0b721dcdae6917bc8 Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 4 Jan 2016 12:16:44 +0100 Subject: [PATCH 20/96] add fadecandy led device Former-commit-id: 490fd3ee66041b35b95d2c7ec110cc70e4c01d8d --- libsrc/leddevice/CMakeLists.txt | 6 +++++- libsrc/leddevice/LedDeviceFactory.cpp | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/libsrc/leddevice/CMakeLists.txt b/libsrc/leddevice/CMakeLists.txt index d6d4682c..3f4fb983 100755 --- a/libsrc/leddevice/CMakeLists.txt +++ b/libsrc/leddevice/CMakeLists.txt @@ -20,6 +20,8 @@ SET(Leddevice_QT_HEADERS ${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.h ${CURRENT_SOURCE_DIR}/LedHIDDevice.h ${CURRENT_SOURCE_DIR}/LedDeviceRawHID.h + ${CURRENT_SOURCE_DIR}/LedDeviceTest.h + ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h ) SET(Leddevice_HEADERS @@ -32,6 +34,7 @@ SET(Leddevice_HEADERS ${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.h ${CURRENT_SOURCE_DIR}/LedDeviceSedu.h ${CURRENT_SOURCE_DIR}/LedDeviceTest.h + ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.h ${CURRENT_SOURCE_DIR}/LedDeviceAtmo.h @@ -53,6 +56,7 @@ SET(Leddevice_SOURCES ${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.cpp ${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp ${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.cpp ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp ${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.cpp @@ -114,7 +118,7 @@ add_library(leddevice target_link_libraries(leddevice hyperion-utils - serialport + serialport ${LIBUSB_1_LIBRARIES} #apt-get install libusb-1.0-0-dev ${CMAKE_THREAD_LIBS_INIT} ${QT_LIBRARIES} diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 85f665a5..f6f3acf3 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -30,6 +30,7 @@ #include "LedDevicePiBlaster.h" #include "LedDeviceSedu.h" #include "LedDeviceTest.h" +#include "LedDeviceFadeCandy.h" #include "LedDeviceHyperionUsbasp.h" #include "LedDevicePhilipsHue.h" #include "LedDeviceTpm2.h" @@ -243,6 +244,12 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) const std::string output = deviceConfig["output"].asString(); device = new LedDeviceTest(output); } + else if (type == "fadecandy") + { + const std::string host = deviceConfig.get("output", "127.0.0.1").asString(); + const uint16_t port = deviceConfig.get("port", 8080).asInt(); + device = new LedDeviceFadeCandy(host,port); + } else if (type == "tpm2") { const std::string output = deviceConfig["output"].asString(); From 7f5a664864f3c402c97027f6290fef5b0dfbef25 Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 4 Jan 2016 12:26:06 +0100 Subject: [PATCH 21/96] set fadecandy default port to original fcserver port number tune debug output of fadecandy device Former-commit-id: 651459e5294ce5721ebe3bb2a6acdc1d096d9cfb --- libsrc/leddevice/LedDeviceFactory.cpp | 2 +- libsrc/leddevice/LedDeviceFadeCandy.cpp | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index f6f3acf3..b0fd064f 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -247,7 +247,7 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) else if (type == "fadecandy") { const std::string host = deviceConfig.get("output", "127.0.0.1").asString(); - const uint16_t port = deviceConfig.get("port", 8080).asInt(); + const uint16_t port = deviceConfig.get("port", 7890).asInt(); device = new LedDeviceFadeCandy(host,port); } else if (type == "tpm2") diff --git a/libsrc/leddevice/LedDeviceFadeCandy.cpp b/libsrc/leddevice/LedDeviceFadeCandy.cpp index ec6da6a2..a0d2e32d 100755 --- a/libsrc/leddevice/LedDeviceFadeCandy.cpp +++ b/libsrc/leddevice/LedDeviceFadeCandy.cpp @@ -21,8 +21,6 @@ LedDeviceFadeCandy::LedDeviceFadeCandy(const std::string& host, const uint16_t p _opc_data[1] = OPC_SET_PIXELS; _opc_data[2] = 0; _opc_data[3] = 0; - - qDebug("connect to %s %i",_host.c_str(),_port); } LedDeviceFadeCandy::~LedDeviceFadeCandy() @@ -38,7 +36,7 @@ bool LedDeviceFadeCandy::isConnected() bool LedDeviceFadeCandy::tryConnect() { if ( _client.state() == QAbstractSocket::UnconnectedState ) { - qDebug("connecting"); + qDebug("connecting to %s %i",_host.c_str(),_port); QHostAddress addr(_host.c_str()); _client.connectToHost(addr, _port); if (_client.waitForConnected(1000)) From 9182dd5af706cb748b53061e04189b32f9613067 Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 4 Jan 2016 14:29:47 +0100 Subject: [PATCH 22/96] fadecandy led device: implement switchOff methode tidy up code and add doxy comments Former-commit-id: a162e2aae756f8b74b8e65f08740c00f3c820e50 --- libsrc/leddevice/LedDeviceFadeCandy.cpp | 114 +++++++++++++----------- libsrc/leddevice/LedDeviceFadeCandy.h | 59 +++++++----- 2 files changed, 97 insertions(+), 76 deletions(-) diff --git a/libsrc/leddevice/LedDeviceFadeCandy.cpp b/libsrc/leddevice/LedDeviceFadeCandy.cpp index a0d2e32d..e8c178d1 100755 --- a/libsrc/leddevice/LedDeviceFadeCandy.cpp +++ b/libsrc/leddevice/LedDeviceFadeCandy.cpp @@ -1,87 +1,93 @@ - -// Local-Hyperion includes #include "LedDeviceFadeCandy.h" -#include -#include -#include -static const unsigned MAX_NUM_LEDS = 512; +static const unsigned MAX_NUM_LEDS = 512; +static const unsigned OPC_BROADCAST = 0; // OPC broadcast channel +static const unsigned OPC_SET_PIXELS = 0; // OPC command codes +static const unsigned OPC_HEADER_SIZE = 4; // OPC header size -/* OPC broadcast channel */ -static const unsigned OPC_BROADCAST = 0; -/* OPC command codes */ -static const unsigned OPC_SET_PIXELS = 0; - -LedDeviceFadeCandy::LedDeviceFadeCandy(const std::string& host, const uint16_t port) - : _host(host), _port(port) +LedDeviceFadeCandy::LedDeviceFadeCandy(const std::string& host, const uint16_t port) : + _host(host), _port(port) { - _opc_data.resize(4); - _opc_data[0] = OPC_BROADCAST; - _opc_data[1] = OPC_SET_PIXELS; - _opc_data[2] = 0; - _opc_data[3] = 0; + _opc_data.resize( OPC_HEADER_SIZE ); + _opc_data[0] = OPC_BROADCAST; + _opc_data[1] = OPC_SET_PIXELS; + _opc_data[2] = 0; + _opc_data[3] = 0; } + LedDeviceFadeCandy::~LedDeviceFadeCandy() { - _client.close(); + _client.close(); } + bool LedDeviceFadeCandy::isConnected() { - return _client.state() == QAbstractSocket::ConnectedState; + return _client.state() == QAbstractSocket::ConnectedState; } + bool LedDeviceFadeCandy::tryConnect() { - if ( _client.state() == QAbstractSocket::UnconnectedState ) { - qDebug("connecting to %s %i",_host.c_str(),_port); - QHostAddress addr(_host.c_str()); - _client.connectToHost(addr, _port); - if (_client.waitForConnected(1000)) - qDebug("connected"); - } + if ( _client.state() == QAbstractSocket::UnconnectedState ) { + qDebug("connecting to %s %i",_host.c_str(),_port); - return isConnected(); + _client.connectToHost( _host.c_str(), _port); + if ( _client.waitForConnected(1000) ) + qDebug("connected"); + } + + return isConnected(); } -int LedDeviceFadeCandy::write(const std::vector & ledValues) +int LedDeviceFadeCandy::write( const std::vector & ledValues ) { - ssize_t nrLedValues = ledValues.size(); - ssize_t led_data_size = nrLedValues*3; // 3 color bytes - ssize_t opc_data_size = led_data_size +4; // + 4 byte header + ssize_t nrLedValues = ledValues.size(); + ssize_t led_data_size = nrLedValues * 3; // 3 color bytes + ssize_t opc_data_size = led_data_size + OPC_HEADER_SIZE; - if (nrLedValues > MAX_NUM_LEDS) - { - std::cerr << "Invalid attempt to write led values. Not more than " << MAX_NUM_LEDS << " leds are allowed." << std::endl; - return -1; - } + if (nrLedValues > MAX_NUM_LEDS) + { + std::cerr << "Invalid attempt to write led values. Not more than " << MAX_NUM_LEDS << " leds are allowed." << std::endl; + return -1; + } - if ( opc_data_size != _opc_data.size()) - _opc_data.resize(opc_data_size); + if ( opc_data_size != _opc_data.size() ) + _opc_data.resize( opc_data_size ); - _opc_data[2] = led_data_size >> 8; - _opc_data[3] = led_data_size & 0xff; + _opc_data[2] = led_data_size >> 8; + _opc_data[3] = led_data_size & 0xff; - if ( isConnected() || tryConnect() ) { - u_int16_t idx = 4; - for (const ColorRgb& color : ledValues) - { - _opc_data[idx] = unsigned(color.red); - _opc_data[idx+1] = unsigned(color.green); - _opc_data[idx+2] = unsigned(color.blue); - idx += 3; - } - _client.write(_opc_data, opc_data_size); - } + uint idx = OPC_HEADER_SIZE; + for (const ColorRgb& color : ledValues) + { + _opc_data[idx ] = unsigned( color.red ); + _opc_data[idx+1] = unsigned( color.green ); + _opc_data[idx+2] = unsigned( color.blue ); + idx += 3; + } - return 0; + return ( transferData()<0 ? -1 : 0 ); +} + + +int LedDeviceFadeCandy::transferData() +{ + if ( isConnected() || tryConnect() ) + return _client.write( _opc_data, _opc_data.size() ); + + return -2; } int LedDeviceFadeCandy::switchOff() { - return 0; + for ( int idx=OPC_HEADER_SIZE; idx < _opc_data.size(); idx++ ) + _opc_data[idx] = 0; + + return ( transferData()<0 ? -1 : 0 ); } + diff --git a/libsrc/leddevice/LedDeviceFadeCandy.h b/libsrc/leddevice/LedDeviceFadeCandy.h index 0973368b..0b894e88 100755 --- a/libsrc/leddevice/LedDeviceFadeCandy.h +++ b/libsrc/leddevice/LedDeviceFadeCandy.h @@ -1,55 +1,70 @@ #pragma once -// STL includes0 +// STL/Qt includes #include #include -#include -#include -#include #include // Leddevice includes #include - /// -/// Implementation of the LedDevice that write the led-colors to an -/// ASCII-textfile('/home/pi/LedDevice.out') +/// Implementation of the LedDevice interface for sending to +/// fadecandy/opc-server via network by using the 'open pixel control' protocol. /// -class LedDeviceFadeCandy : public QObject,public LedDevice +class LedDeviceFadeCandy : public QObject, public LedDevice { - Q_OBJECT + Q_OBJECT + public: /// - /// Constructs the test-device, which opens an output stream to the file + /// Constructs the LedDevice for fadecandy/opc server + /// + /// @param host The ip address/host name of fadecandy/opc server + /// @param port The port to use (fadecandy default is 7890) /// LedDeviceFadeCandy(const std::string& host, const uint16_t port); /// - /// Destructor of this test-device + /// Destructor of the LedDevice; closes the tcp client /// virtual ~LedDeviceFadeCandy(); /// - /// Writes the given led-color values to the output stream + /// Writes the led color values to the led-device /// /// @param ledValues The color-value per led - /// - /// @return Zero on success else negative + /// @return Zero on succes else negative /// virtual int write(const std::vector & ledValues); /// Switch the leds off virtual int switchOff(); - bool tryConnect(); - bool isConnected(); - -//public slots: private: - QTcpSocket _client; - const std::string _host; - const uint16_t _port; - QByteArray _opc_data; + QTcpSocket _client; + const std::string _host; + const uint16_t _port; + QByteArray _opc_data; + + /// try to establish connection to opc server, if not connected yet + /// + /// @return true if connection is established + /// + bool tryConnect(); + + /// return the conenction state + /// + /// @return True if connection established + /// + bool isConnected(); + + + /// transfer current opc_data buffer to opc server + /// + /// @return amount of transfered bytes. -1 error while transfering, -2 error while connecting + /// + int transferData(); + }; From 382f22f23ce5e8a0ae01ad5c3be019be3bf553d6 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Wed, 6 Jan 2016 20:40:48 +1100 Subject: [PATCH 23/96] add udp protocol support Former-commit-id: a92810f14cf2af15710a38246a742ca2b94fd3bd --- libsrc/leddevice/CMakeLists.txt | 2 + libsrc/leddevice/LedDeviceFactory.cpp | 9 ++ libsrc/leddevice/LedDeviceUdp.cpp | 165 ++++++++++++++++++++++++++ libsrc/leddevice/LedDeviceUdp.h | 44 +++++++ 4 files changed, 220 insertions(+) create mode 100644 libsrc/leddevice/LedDeviceUdp.cpp create mode 100644 libsrc/leddevice/LedDeviceUdp.h diff --git a/libsrc/leddevice/CMakeLists.txt b/libsrc/leddevice/CMakeLists.txt index d6d4682c..edbf1ba1 100755 --- a/libsrc/leddevice/CMakeLists.txt +++ b/libsrc/leddevice/CMakeLists.txt @@ -32,6 +32,7 @@ SET(Leddevice_HEADERS ${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.h ${CURRENT_SOURCE_DIR}/LedDeviceSedu.h ${CURRENT_SOURCE_DIR}/LedDeviceTest.h + ${CURRENT_SOURCE_DIR}/LedDeviceUdp.h ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.h ${CURRENT_SOURCE_DIR}/LedDeviceAtmo.h @@ -53,6 +54,7 @@ SET(Leddevice_SOURCES ${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.cpp ${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp ${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp ${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.cpp diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 85f665a5..6e7b3da8 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -30,6 +30,7 @@ #include "LedDevicePiBlaster.h" #include "LedDeviceSedu.h" #include "LedDeviceTest.h" +#include "LedDeviceUdp.h" #include "LedDeviceHyperionUsbasp.h" #include "LedDevicePhilipsHue.h" #include "LedDeviceTpm2.h" @@ -243,6 +244,14 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) const std::string output = deviceConfig["output"].asString(); device = new LedDeviceTest(output); } + else if (type == "udp") + { + const std::string output = deviceConfig["output"].asString(); + const unsigned rate = deviceConfig["rate"].asInt(); + const unsigned protocol = deviceConfig["protocol"].asInt(); + const unsigned maxPacket = deviceConfig["maxpacket"].asInt(); + device = new LedDeviceUdp(output, rate, protocol, maxPacket); + } else if (type == "tpm2") { const std::string output = deviceConfig["output"].asString(); diff --git a/libsrc/leddevice/LedDeviceUdp.cpp b/libsrc/leddevice/LedDeviceUdp.cpp new file mode 100644 index 00000000..129eb47f --- /dev/null +++ b/libsrc/leddevice/LedDeviceUdp.cpp @@ -0,0 +1,165 @@ + +// Local-Hyperion includes +#include "LedDeviceUdp.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct addrinfo hints, *servinfo, *p; +//char udpbuffer[1024]; +int sockfd; +int ledprotocol; +int leds_per_pkt; +int update_number; +int fragment_number; + +LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate, const unsigned protocol, const unsigned maxPacket) +//LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate) : +// _ofs(output.empty()?"/home/pi/LedDevice.out":output.c_str()) +{ + + std::string hostname; + std::string port; + ledprotocol = protocol; + leds_per_pkt = ((maxPacket-4)/3); + if (leds_per_pkt <= 0) { + leds_per_pkt = 200; + } + +//printf ("leds_per_pkt is %d\n", leds_per_pkt); + int got_colon=0; + for (unsigned int i=0; iai_next) { + if ((sockfd = socket(p->ai_family, p->ai_socktype, + p->ai_protocol)) == -1) { + perror("talker: socket"); + continue; + } + + break; + } + + if (p == NULL) { + fprintf(stderr, "talker: failed to create socket\n"); + assert(p!=NULL); + } +} + +LedDeviceUdp::~LedDeviceUdp() +{ + // empty +} + +int LedDeviceUdp::write(const std::vector & ledValues) +{ + + char udpbuffer[4096]; + int udpPtr=0; + + update_number++; + update_number &= 0xf; + + if (ledprotocol == 0) { + int i=0; + for (const ColorRgb& color : ledValues) + { + if (i<4090) { + udpbuffer[i++] = color.red; + udpbuffer[i++] = color.green; + udpbuffer[i++] = color.blue; + } + //printf ("c.red %d sz c.red %d\n", color.red, sizeof(color.red)); + } + sendto(sockfd, udpbuffer, i, 0, p->ai_addr, p->ai_addrlen); + } + if (ledprotocol == 1) { +#define MAXLEDperFRAG 450 + int mLedCount = ledValues.size(); + + for (int frag=0; frag<4; frag++) { + udpPtr=0; + udpbuffer[udpPtr++] = 0; + udpbuffer[udpPtr++] = 0; + udpbuffer[udpPtr++] = (frag*MAXLEDperFRAG)/256; // high byte + udpbuffer[udpPtr++] = (frag*MAXLEDperFRAG)%256; // low byte + int ct=0; + for (int this_led = frag*300; ((this_led 7) + sendto(sockfd, udpbuffer, udpPtr, 0, p->ai_addr, p->ai_addrlen); + } + } + if (ledprotocol == 2) { + udpPtr = 0; + unsigned int ledCtr = 0; + fragment_number = 0; + udpbuffer[udpPtr++] = update_number & 0xf; + udpbuffer[udpPtr++] = fragment_number++; + udpbuffer[udpPtr++] = ledCtr/256; // high byte + udpbuffer[udpPtr++] = ledCtr%256; // low byte + + for (const ColorRgb& color : ledValues) + { + if (udpPtr<4090) { + udpbuffer[udpPtr++] = color.red; + udpbuffer[udpPtr++] = color.green; + udpbuffer[udpPtr++] = color.blue; + } + ledCtr++; + if ( (ledCtr % leds_per_pkt == 0) || (ledCtr == ledValues.size()) ) { + sendto(sockfd, udpbuffer, udpPtr, 0, p->ai_addr, p->ai_addrlen); + memset(udpbuffer, 0, sizeof udpbuffer); + udpPtr = 0; + udpbuffer[udpPtr++] = update_number & 0xf; + udpbuffer[udpPtr++] = fragment_number++; + udpbuffer[udpPtr++] = ledCtr/256; // high byte + udpbuffer[udpPtr++] = ledCtr%256; // low byte + } + } + + } + return 0; +} + +int LedDeviceUdp::switchOff() +{ +// return write(std::vector(mLedCount, ColorRgb{0,0,0})); + return 0; +} diff --git a/libsrc/leddevice/LedDeviceUdp.h b/libsrc/leddevice/LedDeviceUdp.h new file mode 100644 index 00000000..c8e2f119 --- /dev/null +++ b/libsrc/leddevice/LedDeviceUdp.h @@ -0,0 +1,44 @@ +#pragma once + +// STL includes0 +#include + +// Leddevice includes +#include + +/// +/// Implementation of the LedDevice that write the led-colors to an +/// ASCII-textfile('/home/pi/LedDevice.out') +/// +class LedDeviceUdp : public LedDevice +{ +public: + /// + /// Constructs the test-device, which opens an output stream to the file + /// + LedDeviceUdp(const std::string& output, const unsigned baudrate, const unsigned protocol, const unsigned maxPacket); + + /// + /// Destructor of this test-device + /// + virtual ~LedDeviceUdp(); + + /// + /// Writes the given led-color values to the output stream + /// + /// @param ledValues The color-value per led + /// + /// @return Zero on success else negative + /// + virtual int write(const std::vector & ledValues); + + /// Switch the leds off + virtual int switchOff(); + +private: + /// The outputstream +// std::ofstream _ofs; + + /// the number of leds (needed when switching off) + size_t mLedCount; +}; From defe217c899a0258eda2ef9672ff3c8f83dc0038 Mon Sep 17 00:00:00 2001 From: frostworx Date: Wed, 6 Jan 2016 17:31:23 +0100 Subject: [PATCH 24/96] added optional QT5 support - LedDevicePhilipsHue needs proper fixes Former-commit-id: 7f0971ccda221933da4be836628532e7cfc7c085 --- CMakeLists.txt | 27 ++++++++++++++++- .../BoblightClientConnection.cpp | 5 +++- libsrc/boblightserver/CMakeLists.txt | 8 +++++ libsrc/effectengine/CMakeLists.txt | 10 ++++++- libsrc/effectengine/EffectEngine.cpp | 8 +++++ libsrc/grabber/amlogic/CMakeLists.txt | 4 +++ libsrc/grabber/dispmanx/CMakeLists.txt | 4 +++ libsrc/grabber/framebuffer/CMakeLists.txt | 4 +++ libsrc/grabber/osx/CMakeLists.txt | 4 +++ libsrc/grabber/v4l2/CMakeLists.txt | 8 +++++ libsrc/grabber/x11/CMakeLists.txt | 4 +++ libsrc/hyperion/CMakeLists.txt | 10 ++++++- libsrc/jsonserver/CMakeLists.txt | 11 +++++-- libsrc/leddevice/CMakeLists.txt | 10 ++++++- libsrc/leddevice/LedDevicePhilipsHue.cpp | 29 +++++++++++++++++++ libsrc/leddevice/LedDevicePhilipsHue.h | 10 ++++++- libsrc/protoserver/CMakeLists.txt | 7 +++++ libsrc/xbmcvideochecker/CMakeLists.txt | 8 +++++ src/hyperion-aml/CMakeLists.txt | 4 +++ src/hyperion-remote/CMakeLists.txt | 10 +++++++ src/hyperion-remote/hyperion-remote.cpp | 5 ++++ src/hyperion-v4l2/CMakeLists.txt | 12 +++++++- src/hyperion-x11/CMakeLists.txt | 12 ++++++++ test/CMakeLists.txt | 5 ++++ 24 files changed, 210 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b89af70..81479cb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,9 @@ message(STATUS "ENABLE_WS2812BPWM = " ${ENABLE_WS2812BPWM}) option(ENABLE_X11 "Enable the X11 grabber" OFF) message(STATUS "ENABLE_X11 = " ${ENABLE_X11}) +option(ENABLE_QT5 "Enable QT5" OFF) +message(STATUS "ENABLE_QT5 = " ${ENABLE_QT5}) + if(ENABLE_V4L2 AND NOT ENABLE_PROTOBUF) message(FATAL_ERROR "V4L2 grabber requires PROTOBUF. Disable V4L2 or enable PROTOBUF") endif(ENABLE_V4L2 AND NOT ENABLE_PROTOBUF) @@ -53,6 +56,10 @@ if(ENABLE_OSX AND ENABLE_DISPMANX) message(FATAL_ERROR "dispmanx grabber and osx grabber cannot be used at the same time") endif(ENABLE_OSX AND ENABLE_DISPMANX) +#if(ENABLE_QT5) +# TODO vs ENABLE_QT4? +#endif(ENABLE_QT5) + # Createt the configuration file # configure a header file to pass some of the CMake settings # to the source code @@ -61,8 +68,14 @@ include_directories("${PROJECT_BINARY_DIR}") # Add project specific cmake modules (find, etc) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) + +if(ENABLE_QT5) +ADD_DEFINITIONS ( -DENABLE_QT5 ) +#find_package(Qt5Widgets) +else(ENABLE_QT5) # Add specific cmake modules to find qt4 (default version finds first available QT which might not be qt4) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/qt4) +endif(ENABLE_QT5) # Define the global output path of binaries SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) @@ -85,15 +98,27 @@ set(CMAKE_BUILD_TYPE "Debug") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -std=c++11 -Wall") +if(ENABLE_QT5) +#find_package(Qt5Core REQUIRED) +find_package(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") +# set(CMAKE_CXX_FLAGS "-fPIC") +else(ENABLE_QT5) # Configure the use of QT4 find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED QUIET) +endif(ENABLE_QT5) #add libusb and pthreads find_package(libusb-1.0 REQUIRED) find_package(Threads REQUIRED) - +if(ENABLE_QT5) +#include(${QT_USE_FILE}) +add_definitions(${QT_DEFINITIONS}) +else(ENABLE_QT5) include(${QT_USE_FILE}) add_definitions(${QT_DEFINITIONS}) +endif(ENABLE_QT5) + # TODO[TvdZ]: This linking directory should only be added if we are cross compiling if(NOT APPLE) link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf) diff --git a/libsrc/boblightserver/BoblightClientConnection.cpp b/libsrc/boblightserver/BoblightClientConnection.cpp index f78d6784..105b8d1a 100644 --- a/libsrc/boblightserver/BoblightClientConnection.cpp +++ b/libsrc/boblightserver/BoblightClientConnection.cpp @@ -59,8 +59,11 @@ void BoblightClientConnection::readData() while(bytes > 0) { // create message string (strip the newline) +#ifdef ENABLE_QT5 + QString message = QString::fromLatin1(_receiveBuffer.data(), bytes-1); +#else QString message = QString::fromAscii(_receiveBuffer.data(), bytes-1); - +#endif // remove message data from buffer _receiveBuffer = _receiveBuffer.mid(bytes); diff --git a/libsrc/boblightserver/CMakeLists.txt b/libsrc/boblightserver/CMakeLists.txt index 1bb30cdb..33be4d17 100644 --- a/libsrc/boblightserver/CMakeLists.txt +++ b/libsrc/boblightserver/CMakeLists.txt @@ -17,7 +17,11 @@ set(BoblightServer_SOURCES ${CURRENT_SOURCE_DIR}/BoblightClientConnection.cpp ) +if(ENABLE_QT5) +qt5_wrap_cpp(BoblightServer_HEADERS_MOC ${BoblightServer_QT_HEADERS}) +else(ENABLE_QT5) qt4_wrap_cpp(BoblightServer_HEADERS_MOC ${BoblightServer_QT_HEADERS}) +endif(ENABLE_QT5) add_library(boblightserver ${BoblightServer_HEADERS} @@ -26,6 +30,10 @@ add_library(boblightserver ${BoblightServer_HEADERS_MOC} ) +if(ENABLE_QT5) +qt5_use_modules(boblightserver Widgets) +endif(ENABLE_QT5) + target_link_libraries(boblightserver hyperion hyperion-utils diff --git a/libsrc/effectengine/CMakeLists.txt b/libsrc/effectengine/CMakeLists.txt index c7c77236..619b691d 100644 --- a/libsrc/effectengine/CMakeLists.txt +++ b/libsrc/effectengine/CMakeLists.txt @@ -27,9 +27,13 @@ SET(EffectEngineSOURCES set(EffectEngine_RESOURCES ${CURRENT_SOURCE_DIR}/EffectEngine.qrc) +if(ENABLE_QT5) +QT5_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS}) +qt5_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress") +else(ENABLE_QT5) QT4_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS}) - qt4_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress") +endif(ENABLE_QT5) add_library(effectengine ${EffectEngineHEADERS} @@ -39,6 +43,10 @@ add_library(effectengine ${EffectEngineSOURCES} ) +if(ENABLE_QT5) +qt5_use_modules(effectengine Widgets) +endif(ENABLE_QT5) + target_link_libraries(effectengine hyperion jsoncpp diff --git a/libsrc/effectengine/EffectEngine.cpp b/libsrc/effectengine/EffectEngine.cpp index f7057e21..b9379fad 100644 --- a/libsrc/effectengine/EffectEngine.cpp +++ b/libsrc/effectengine/EffectEngine.cpp @@ -75,7 +75,11 @@ const std::list &EffectEngine::getEffects() const bool EffectEngine::loadEffectDefinition(const std::string &path, const std::string &effectConfigFile, EffectDefinition & effectDefinition) { +#ifdef ENABLE_QT5 + std::string fileName = path + QDir::separator().toLatin1() + effectConfigFile; +#else std::string fileName = path + QDir::separator().toAscii() + effectConfigFile; +#endif std::ifstream file(fileName.c_str()); if (!file.is_open()) @@ -110,7 +114,11 @@ bool EffectEngine::loadEffectDefinition(const std::string &path, const std::stri // setup the definition effectDefinition.name = config["name"].asString(); +#ifdef ENABLE_QT5 + effectDefinition.script = path + QDir::separator().toLatin1() + config["script"].asString(); +#else effectDefinition.script = path + QDir::separator().toAscii() + config["script"].asString(); +#endif effectDefinition.args = config["args"]; // return succes diff --git a/libsrc/grabber/amlogic/CMakeLists.txt b/libsrc/grabber/amlogic/CMakeLists.txt index 447a873d..be6cb97d 100644 --- a/libsrc/grabber/amlogic/CMakeLists.txt +++ b/libsrc/grabber/amlogic/CMakeLists.txt @@ -15,7 +15,11 @@ SET(AmlogicSOURCES ${CURRENT_SOURCE_DIR}/AmlogicGrabber.cpp ) +if(ENABLE_QT5) +QT5_WRAP_CPP(AmlogicHEADERS_MOC ${AmlogicQT_HEADERS}) +else(ENABLE_QT5) QT4_WRAP_CPP(AmlogicHEADERS_MOC ${AmlogicQT_HEADERS}) +endif(ENABLE_QT5) add_library(amlogic-grabber ${AmlogicHEADERS} diff --git a/libsrc/grabber/dispmanx/CMakeLists.txt b/libsrc/grabber/dispmanx/CMakeLists.txt index 20714dba..d4d64b72 100644 --- a/libsrc/grabber/dispmanx/CMakeLists.txt +++ b/libsrc/grabber/dispmanx/CMakeLists.txt @@ -21,7 +21,11 @@ SET(DispmanxGrabberSOURCES ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp ) +if(ENABLE_QT5) +QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) +else(ENABLE_QT5) QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) +endif(ENABLE_QT5) add_library(dispmanx-grabber ${DispmanxGrabberHEADERS} diff --git a/libsrc/grabber/framebuffer/CMakeLists.txt b/libsrc/grabber/framebuffer/CMakeLists.txt index 9a6a12be..dc585f42 100644 --- a/libsrc/grabber/framebuffer/CMakeLists.txt +++ b/libsrc/grabber/framebuffer/CMakeLists.txt @@ -21,7 +21,11 @@ SET(FramebufferGrabberSOURCES ${CURRENT_SOURCE_DIR}/FramebufferFrameGrabber.cpp ) +if(ENABLE_QT5) +QT5_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS}) +else(ENABLE_QT5) QT4_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS}) +endif(ENABLE_QT5) add_library(framebuffer-grabber ${FramebufferGrabberHEADERS} diff --git a/libsrc/grabber/osx/CMakeLists.txt b/libsrc/grabber/osx/CMakeLists.txt index 05c67b3b..03868eeb 100644 --- a/libsrc/grabber/osx/CMakeLists.txt +++ b/libsrc/grabber/osx/CMakeLists.txt @@ -16,7 +16,11 @@ SET(OsxGrabberSOURCES ${CURRENT_SOURCE_DIR}/OsxFrameGrabber.cpp ) +if(ENABLE_QT5) +QT5_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS}) +else(ENABLE_QT5) QT4_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS}) +endif(ENABLE_QT5) add_library(osx-grabber ${OsxGrabberHEADERS} diff --git a/libsrc/grabber/v4l2/CMakeLists.txt b/libsrc/grabber/v4l2/CMakeLists.txt index 5c7844e0..71de7806 100644 --- a/libsrc/grabber/v4l2/CMakeLists.txt +++ b/libsrc/grabber/v4l2/CMakeLists.txt @@ -16,7 +16,11 @@ SET(V4L2_SOURCES ${CURRENT_SOURCE_DIR}/V4L2Wrapper.cpp ) +if(ENABLE_QT5) +QT5_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS}) +else(ENABLE_QT5) QT4_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS}) +endif(ENABLE_QT5) add_library(v4l2-grabber ${V4L2_HEADERS} @@ -25,6 +29,10 @@ add_library(v4l2-grabber ${V4L2_HEADERS_MOC} ) +if(ENABLE_QT5) +qt5_use_modules(v4l2-grabber Widgets) +endif(ENABLE_QT5) + target_link_libraries(v4l2-grabber hyperion ${QT_LIBRARIES} diff --git a/libsrc/grabber/x11/CMakeLists.txt b/libsrc/grabber/x11/CMakeLists.txt index 869fb4bf..4d8ead6d 100644 --- a/libsrc/grabber/x11/CMakeLists.txt +++ b/libsrc/grabber/x11/CMakeLists.txt @@ -22,7 +22,11 @@ SET(X11_SOURCES ${CURRENT_SOURCE_DIR}/X11Grabber.cpp ) +if(ENABLE_QT5) +QT5_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS}) +else(ENABLE_QT5) QT4_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS}) +endif(ENABLE_QT5) add_library(x11-grabber ${X11_HEADERS} diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 8f6a227d..1434f105 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -36,9 +36,13 @@ set(Hyperion_RESOURCES ${CURRENT_SOURCE_DIR}/resource.qrc ) +if(ENABLE_QT5) +QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) +QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") +else(ENABLE_QT5) QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) - QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") +endif(ENABLE_QT5) add_library(hyperion ${Hyperion_HEADERS} @@ -48,6 +52,10 @@ add_library(hyperion ${Hyperion_RESOURCES_RCC} ) +if(ENABLE_QT5) +qt5_use_modules(hyperion Widgets) +endif(ENABLE_QT5) + target_link_libraries(hyperion blackborder hyperion-utils diff --git a/libsrc/jsonserver/CMakeLists.txt b/libsrc/jsonserver/CMakeLists.txt index 208c1ed9..d03ed1ea 100644 --- a/libsrc/jsonserver/CMakeLists.txt +++ b/libsrc/jsonserver/CMakeLists.txt @@ -20,10 +20,13 @@ set(JsonServer_SOURCES set(JsonServer_RESOURCES ${CURRENT_SOURCE_DIR}/JsonSchemas.qrc ) - +if(ENABLE_QT5) +qt5_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS}) +qt5_add_resources(JsonServer_RESOURCES_RCC ${JsonServer_RESOURCES} OPTIONS "-no-compress") +else(ENABLE_QT5) qt4_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS}) - qt4_add_resources(JsonServer_RESOURCES_RCC ${JsonServer_RESOURCES} OPTIONS "-no-compress") +endif(ENABLE_QT5) add_library(jsonserver ${JsonServer_HEADERS} @@ -34,6 +37,10 @@ add_library(jsonserver ${JsonServer_RESOURCES_RCC} ) +if(ENABLE_QT5) +qt5_use_modules(jsonserver Widgets Network) +endif(ENABLE_QT5) + target_link_libraries(jsonserver hyperion hyperion-utils diff --git a/libsrc/leddevice/CMakeLists.txt b/libsrc/leddevice/CMakeLists.txt index d6d4682c..ddb8a0de 100755 --- a/libsrc/leddevice/CMakeLists.txt +++ b/libsrc/leddevice/CMakeLists.txt @@ -102,8 +102,12 @@ if(ENABLE_TINKERFORGE) ) endif(ENABLE_TINKERFORGE) - +if(ENABLE_QT5) +QT5_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS}) +else(ENABLE_QT5) QT4_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS}) +endif(ENABLE_QT5) + add_library(leddevice ${Leddevice_HEADERS} @@ -112,6 +116,10 @@ add_library(leddevice ${Leddevice_SOURCES} ) +if(ENABLE_QT5) +qt5_use_modules(leddevice Widgets Network) +endif(ENABLE_QT5) + target_link_libraries(leddevice hyperion-utils serialport diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index 056e9ead..449f8307 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -7,7 +7,12 @@ // qt includes #include #include +#ifdef ENABLE_QT5 + +#else #include +#endif + #include #include @@ -144,14 +149,22 @@ LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::s int transitiontime, std::vector lightIds) : host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime( transitiontime), lightIds(lightIds) { +#ifdef ENABLE_QT5 + +#else http = new QHttp(host); timer.setInterval(3000); timer.setSingleShot(true); connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates())); +#endif } LedDevicePhilipsHue::~LedDevicePhilipsHue() { +#ifdef ENABLE_QT5 + +#else delete http; +#endif } int LedDevicePhilipsHue::write(const std::vector & ledValues) { @@ -201,21 +214,32 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { // Next light id. idx++; } +#ifdef ENABLE_QT5 + +#else timer.start(); +#endif return 0; } int LedDevicePhilipsHue::switchOff() { +#ifdef ENABLE_QT5 + +#else timer.stop(); // If light states have been saved before, ... if (areStatesSaved()) { // ... restore them. restoreStates(); } +#endif return 0; } void LedDevicePhilipsHue::put(QString route, QString content) { +#ifdef ENABLE_QT5 + +#else QString url = QString("/api/%1/%2").arg(username).arg(route); QHttpRequestHeader header("PUT", url); header.setValue("Host", host); @@ -229,9 +253,13 @@ void LedDevicePhilipsHue::put(QString route, QString content) { http->request(header, content.toAscii()); // Go into the loop until the request is finished. loop.exec(); +#endif } QByteArray LedDevicePhilipsHue::get(QString route) { +#ifdef ENABLE_QT5 + return 0; +#else QString url = QString("/api/%1/%2").arg(username).arg(route); // Event loop to block until request finished. QEventLoop loop; @@ -243,6 +271,7 @@ QByteArray LedDevicePhilipsHue::get(QString route) { loop.exec(); // Read all data of the response. return http->readAll(); +#endif } QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) { diff --git a/libsrc/leddevice/LedDevicePhilipsHue.h b/libsrc/leddevice/LedDevicePhilipsHue.h index 59c0383d..65c5a3b6 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/LedDevicePhilipsHue.h @@ -4,11 +4,14 @@ #include // Qt includes +#ifdef ENABLE_QT5 +#include +#else #include #include #include #include - +#endif // Leddevice includes #include @@ -165,9 +168,14 @@ private: /// User name for the API ("newdeveloper") QString username; /// Qhttp object for sending requests. +#ifdef ENABLE_QT5 +// TODO QNetworkAcessManager stuff +#else QHttp* http; + /// Use timer to reset lights when we got into "GRABBINGMODE_OFF". QTimer timer; +#endif /// bool switchOffOnBlack; /// Transition time in multiples of 100 ms. diff --git a/libsrc/protoserver/CMakeLists.txt b/libsrc/protoserver/CMakeLists.txt index 6a9b6d1e..769cc807 100644 --- a/libsrc/protoserver/CMakeLists.txt +++ b/libsrc/protoserver/CMakeLists.txt @@ -34,7 +34,11 @@ protobuf_generate_cpp(ProtoServer_PROTO_SRCS ProtoServer_PROTO_HDRS ${ProtoServer_PROTOS} ) +if(ENABLE_QT5) +qt5_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS}) +else(ENABLE_QT5) qt4_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS}) +endif(ENABLE_QT5) add_library(protoserver ${ProtoServer_HEADERS} @@ -45,6 +49,9 @@ add_library(protoserver ${ProtoServer_PROTO_SRCS} ${ProtoServer_PROTO_HDRS} ) +if(ENABLE_QT5) +qt5_use_modules(protoserver Widgets) +endif(ENABLE_QT5) target_link_libraries(protoserver hyperion diff --git a/libsrc/xbmcvideochecker/CMakeLists.txt b/libsrc/xbmcvideochecker/CMakeLists.txt index 77ee2f34..f6e71b00 100644 --- a/libsrc/xbmcvideochecker/CMakeLists.txt +++ b/libsrc/xbmcvideochecker/CMakeLists.txt @@ -15,7 +15,11 @@ SET(XBMCVideoChecker_SOURCES ${CURRENT_SOURCE_DIR}/XBMCVideoChecker.cpp ) +if(ENABLE_QT5) +QT5_WRAP_CPP(XBMCVideoChecker_HEADERS_MOC ${XBMCVideoChecker_QT_HEADERS}) +else(ENABLE_QT5) QT4_WRAP_CPP(XBMCVideoChecker_HEADERS_MOC ${XBMCVideoChecker_QT_HEADERS}) +endif(ENABLE_QT5) add_library(xbmcvideochecker ${XBMCVideoChecker_HEADERS} @@ -24,6 +28,10 @@ add_library(xbmcvideochecker ${XBMCVideoChecker_SOURCES} ) +if(ENABLE_QT5) +qt5_use_modules(xbmcvideochecker Widgets) +endif(ENABLE_QT5) + target_link_libraries(xbmcvideochecker hyperion ${QT_LIBRARIES}) diff --git a/src/hyperion-aml/CMakeLists.txt b/src/hyperion-aml/CMakeLists.txt index d6f88a90..5d45222a 100644 --- a/src/hyperion-aml/CMakeLists.txt +++ b/src/hyperion-aml/CMakeLists.txt @@ -23,7 +23,11 @@ set(Hyperion_AML_SOURCES hyperion-aml.cpp ) +if(ENABLE_QT5) +QT5_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) +else(ENABLE_QT5) QT4_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) +endif(ENABLE_QT5) add_executable(hyperion-amlogic ${Hyperion_AML_HEADERS} diff --git a/src/hyperion-remote/CMakeLists.txt b/src/hyperion-remote/CMakeLists.txt index c934be21..b8c73a59 100644 --- a/src/hyperion-remote/CMakeLists.txt +++ b/src/hyperion-remote/CMakeLists.txt @@ -3,7 +3,13 @@ cmake_minimum_required(VERSION 2.8) project(hyperion-remote) # find Qt4 +if(ENABLE_QT5) +find_package(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED) +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") +# set(CMAKE_CXX_FLAGS "-fPIC") +else(ENABLE_QT5) find_package(Qt4 REQUIRED QtCore QtGui QtNetwork) +endif(ENABLE_QT5) # The following I do not undrstand completely... # libQtCore.so uses some hardcoded library path inside which are incorrect after copying the file RPi file system @@ -25,6 +31,10 @@ add_executable(hyperion-remote ${hyperion-remote_HEADERS} ${hyperion-remote_SOURCES}) +if(ENABLE_QT5) +qt5_use_modules(hyperion-remote Widgets Network) +endif(ENABLE_QT5) + target_link_libraries(hyperion-remote jsoncpp getoptPlusPlus diff --git a/src/hyperion-remote/hyperion-remote.cpp b/src/hyperion-remote/hyperion-remote.cpp index da9d4b00..3636721f 100644 --- a/src/hyperion-remote/hyperion-remote.cpp +++ b/src/hyperion-remote/hyperion-remote.cpp @@ -43,8 +43,13 @@ int main(int argc, char * argv[]) // create the option parser and initialize all parameters OptionsParser optionParser("Simple application to send a command to hyperion using the Json interface"); ParameterSet & parameters = optionParser.getParameters(); +#ifdef ENABLE_QT5 + StringParameter & argAddress = parameters.add ('a', "address" , QString("Set the address of the hyperion server [default: %1]").arg(defaultServerAddress).toLatin1().constData()); + IntParameter & argPriority = parameters.add ('p', "priority" , QString("Use to the provided priority channel (the lower the number, the higher the priority) [default: %1]").arg(defaultPriority).toLatin1().constData()); +#else StringParameter & argAddress = parameters.add ('a', "address" , QString("Set the address of the hyperion server [default: %1]").arg(defaultServerAddress).toAscii().constData()); IntParameter & argPriority = parameters.add ('p', "priority" , QString("Use to the provided priority channel (the lower the number, the higher the priority) [default: %1]").arg(defaultPriority).toAscii().constData()); +#endif IntParameter & argDuration = parameters.add ('d', "duration" , "Specify how long the leds should be switched on in millseconds [default: infinity]"); ColorParameter & argColor = parameters.add ('c', "color" , "Set all leds to a constant color (either RRGGBB hex value or a color name. The color may be repeated multiple time like: RRGGBBRRGGBB)"); ImageParameter & argImage = parameters.add ('i', "image" , "Set the leds to the colors according to the given image file"); diff --git a/src/hyperion-v4l2/CMakeLists.txt b/src/hyperion-v4l2/CMakeLists.txt index 6607c04f..ef051e2d 100644 --- a/src/hyperion-v4l2/CMakeLists.txt +++ b/src/hyperion-v4l2/CMakeLists.txt @@ -3,7 +3,14 @@ cmake_minimum_required(VERSION 2.8) project(hyperion-v4l2) # find Qt4 +if(ENABLE_QT5) +find_package(Qt5Widgets REQUIRED) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") +# set(CMAKE_CXX_FLAGS "-fPIC") +else(ENABLE_QT5) find_package(Qt4 REQUIRED QtCore QtGui QtNetwork) +endif(ENABLE_QT5) + include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver @@ -24,8 +31,11 @@ set(Hyperion_V4L2_SOURCES hyperion-v4l2.cpp ScreenshotHandler.cpp ) - +if(ENABLE_QT5) +QT5_WRAP_CPP(Hyperion_V4L2_MOC_SOURCES ${Hyperion_V4L2_QT_HEADERS}) +else(ENABLE_QT5) QT4_WRAP_CPP(Hyperion_V4L2_MOC_SOURCES ${Hyperion_V4L2_QT_HEADERS}) +endif(ENABLE_QT5) add_executable(hyperion-v4l2 ${Hyperion_V4L2_HEADERS} diff --git a/src/hyperion-x11/CMakeLists.txt b/src/hyperion-x11/CMakeLists.txt index 89912f66..626781f9 100644 --- a/src/hyperion-x11/CMakeLists.txt +++ b/src/hyperion-x11/CMakeLists.txt @@ -4,8 +4,12 @@ cmake_minimum_required(VERSION 2.8) # Set the project name project(hyperion-x11) +if(ENABLE_QT5) +find_package(Qt5Widgets REQUIRED) +else(ENABLE_QT5) # find Qt4 find_package(Qt4 REQUIRED QtCore QtGui QtNetwork) +endif(ENABLE_QT5) # Find X11 find_package(X11 REQUIRED) @@ -28,7 +32,11 @@ set(Hyperion_X11_SOURCES X11Wrapper.cpp ) +if(ENABLE_QT5) +QT5_WRAP_CPP(Hyperion_X11_HEADERS_MOC ${Hyperion_X11_QT_HEADERS}) +else(ENABLE_QT5) QT4_WRAP_CPP(Hyperion_X11_HEADERS_MOC ${Hyperion_X11_QT_HEADERS}) +endif(ENABLE_QT5) add_executable(hyperion-x11 ${Hyperion_X11_HEADERS} @@ -46,7 +54,11 @@ target_link_libraries(hyperion-x11 pthread ) +if(ENABLE_QT5) +qt5_use_modules(hyperion-x11 Widgets Core Gui Network) +else(ENABLE_QT5) qt4_use_modules(hyperion-x11 Core Gui Network) +endif(ENABLE_QT5) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bf40cebb..482d066a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -53,6 +53,11 @@ add_executable(test_qtscreenshot TestQtScreenshot.cpp) target_link_libraries(test_qtscreenshot ${QT_LIBRARIES}) +if(ENABLE_QT5) +qt5_use_modules(test_qregexp Widgets) +qt5_use_modules(test_qtscreenshot Widgets) +endif(ENABLE_QT5) + if(ENABLE_X11) # Find X11 find_package(X11 REQUIRED) From 5a69b4e6a2d82074e8d78ad3a0fcd48ce49ee2d8 Mon Sep 17 00:00:00 2001 From: frostworx Date: Wed, 6 Jan 2016 18:13:44 +0100 Subject: [PATCH 25/96] added QT5 X11 check Former-commit-id: ff7ff4f353381409efbdfcf346b6a4817f7dc7e1 --- test/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 482d066a..76cbb5dc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -64,4 +64,8 @@ if(ENABLE_X11) add_executable(test_x11performance TestX11Performance.cpp) target_link_libraries(test_x11performance ${X11_LIBRARIES} ${QT_LIBRARIES}) +if(ENABLE_QT5) +qt5_use_modules(test_x11performance Widgets) +endif(ENABLE_QT5) + endif(ENABLE_X11) From 6d062adc354784a8de311ce23865df0a0f185321 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Fri, 8 Jan 2016 14:11:57 +1100 Subject: [PATCH 26/96] Added a "udp" effect that listens for UDP packets and then sets the LEDs. A good companion for the UDP led driver i also commited Former-commit-id: f9c43eab8fe1c805c32de3e3612b238b33d1d153 --- effects/udp.json | 8 ++++++++ effects/udp.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 effects/udp.json create mode 100644 effects/udp.py diff --git a/effects/udp.json b/effects/udp.json new file mode 100644 index 00000000..defd4f89 --- /dev/null +++ b/effects/udp.json @@ -0,0 +1,8 @@ +{ + "name" : "UDP listener", + "script" : "udp.py", + "args" : + { + "udpPort" : 2391 + } +} diff --git a/effects/udp.py b/effects/udp.py new file mode 100644 index 00000000..f8317a20 --- /dev/null +++ b/effects/udp.py @@ -0,0 +1,47 @@ +import hyperion +import time +import colorsys +import socket +import errno + +# Get the parameters +udpPort = int(hyperion.args.get('udpPort', 2812)) + +UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) +UDPSock.setblocking(False) + +listen_addr = ("",udpPort) +print "udp.py: bind socket port:",udpPort +UDPSock.bind(listen_addr) + +hyperion.setColor(hyperion.ledCount * bytearray((int(0), int(0), int(0))) ) + +# Start the write data loop +while not hyperion.abort(): + try: + data,addr = UDPSock.recvfrom(4500) +# print data.strip(),len(data),addr + if (len(data)%3 == 0): +# print "numleds ",len(data)/3 + ledData = bytearray() + for i in range(hyperion.ledCount): + if (i<(len(data)/3)): + ledData += data[i*3+0] + ledData += data[i*3+1] + ledData += data[i*3+2] + else: + ledData += bytearray((int(0), int(0), int(0))) + + hyperion.setColor(ledData) + + else: + print "not div 3" + except IOError as e: + if e.errno == errno.EWOULDBLOCK: + pass + else: + print "errno:", e.errno + +print "udp.py: closing socket" +UDPSock.close() + From 6b0bf2ac90519d93e39b2fc4b05f3353471e6688 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Fri, 8 Jan 2016 14:14:55 +1100 Subject: [PATCH 27/96] Basic documentation for the UDP led driver Former-commit-id: e5725b467e3960f84e2c4c6d5dd8e6e117f7188d --- doc/UDP_led_driver.txt | 57 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 doc/UDP_led_driver.txt diff --git a/doc/UDP_led_driver.txt b/doc/UDP_led_driver.txt new file mode 100644 index 00000000..646abe21 --- /dev/null +++ b/doc/UDP_led_driver.txt @@ -0,0 +1,57 @@ +BACKGROUND +--------------------------------------------------------- +The UDP led device type can be used to send LED data over UDP packets. +It was originally designed to support an ESP8266 Wifi module based WS2812 +LED strip controller. + +I've used this to support : +- A string of 600 LEDs as xmas decorations + The effects development kit is great for these scenarios + +- a 61 LED collection of concentric circles + This has been used as a "night light" and a super lo-res + TV + +In each of these cases, the hyperion-remote iOS app is a great way to +control the effects. + + +CONFIG +--------------------------------------------------------- +Simple example for devices that support a raw binary protocol. + "device" : + { + "name" : "MyPi", + "type" : "udp", + "output" : "esp201-0.home:2391", "protocol" : 0, + "rate" : 1000000, + "colorOrder" : "grb" + }, + + + +If you are using an ESP8266/Arduino device with a long LED strip, you chould use this alternate protocol. +The ESP8266/Arduino doesnt support datagram re-assembly so will never see any udp packets greater than 1450. + "device" : + { + "name" : "MyPi", + "type" : "udp", +// "output" : "esp201-0.home:2392", "protocol" : 2, "maxpacket" : 1450, + "rate" : 1000000, + "colorOrder" : "rgb" + }, + +PROTOCOL +--------------------------------------------------------- +Simple UDP packets are sent. + +Packet Format protocol 0: +3 bytes per LED as R, G, B + +Packet Format protocol 2: +0: update number & 0xf; +1: fragment of this update +2: 1st led# of this update - high byte +3: 1st led# of this update - low byte +4..n 3 bytes per LED as R, G, B + From 544ae68429cf8e7eb026d912a508e6905d76e404 Mon Sep 17 00:00:00 2001 From: wisc Date: Sun, 10 Jan 2016 14:41:47 +0100 Subject: [PATCH 28/96] test old v1+ vs new v2 Former-commit-id: 5217ac135cd0c7a6907be0097df72506ca7f2d71 --- include/blackborder/BlackBorderProcessor.h | 8 ++ libsrc/blackborder/BlackBorderProcessor.cpp | 107 ++++++++++++++++++-- 2 files changed, 105 insertions(+), 10 deletions(-) diff --git a/include/blackborder/BlackBorderProcessor.h b/include/blackborder/BlackBorderProcessor.h index 4d0c4fca..19f90d3d 100644 --- a/include/blackborder/BlackBorderProcessor.h +++ b/include/blackborder/BlackBorderProcessor.h @@ -73,6 +73,8 @@ namespace hyperion /// @return True if the current border changed else false /// bool updateBorder(const BlackBorder & newDetectedBorder); + bool updateBorder1(const BlackBorder & newDetectedBorder); + bool updateBorder2(const BlackBorder & newDetectedBorder); /// The number of unknown-borders detected before it becomes the current border const unsigned _unknownSwitchCnt; @@ -87,12 +89,18 @@ namespace hyperion BlackBorderDetector _detector; /// The current detected border + BlackBorder _currentBorder1; BlackBorder _currentBorder; /// The border detected in the previous frame + BlackBorder _previousDetectedBorder1; BlackBorder _previousDetectedBorder; /// The number of frame the previous detected border matched the incomming border + unsigned _consistentCnt1; unsigned _consistentCnt; + /// The number of frame the previous detected border NOT matched the incomming border + unsigned _inconsistentCnt1; + unsigned _inconsistentCnt; }; } // end namespace hyperion diff --git a/libsrc/blackborder/BlackBorderProcessor.cpp b/libsrc/blackborder/BlackBorderProcessor.cpp index b9c21eea..b3f1824f 100644 --- a/libsrc/blackborder/BlackBorderProcessor.cpp +++ b/libsrc/blackborder/BlackBorderProcessor.cpp @@ -1,4 +1,4 @@ -//#include +#include // Blackborder includes #include @@ -12,9 +12,14 @@ BlackBorderProcessor::BlackBorderProcessor(const unsigned unknownFrameCnt, _borderSwitchCnt(borderFrameCnt), _blurRemoveCnt(blurRemoveCnt), _detector(blackborderThreshold), + _currentBorder1({true, -1, -1}), _currentBorder({true, -1, -1}), + _previousDetectedBorder1({true, -1, -1}), _previousDetectedBorder({true, -1, -1}), - _consistentCnt(0) + _consistentCnt1(0), + _consistentCnt(0), + _inconsistentCnt1(0), + _inconsistentCnt(0) { // empty } @@ -24,23 +29,102 @@ BlackBorder BlackBorderProcessor::getCurrentBorder() const return _currentBorder; } + bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) +{ +bool result1 = updateBorder1(newDetectedBorder); +if (result1) +{ + std::cout << "border change v1 " << _currentBorder1.horizontalSize << ":" << _currentBorder1.verticalSize << std::endl; +} + +bool result2 = updateBorder2(newDetectedBorder); +if (result2) +{ + std::cout << "border change v2 " << _currentBorder.horizontalSize << ":" << _currentBorder.verticalSize << std::endl; +} + +return result2; +} + + +bool BlackBorderProcessor::updateBorder1(const BlackBorder & newDetectedBorder) +{ + // set the consistency counter + if (newDetectedBorder == _previousDetectedBorder1) + { + ++_consistentCnt1; + } + else + { + _previousDetectedBorder1 = newDetectedBorder; + _consistentCnt1 = 0; + } + +// std::cout << "cur: " << _currentBorder1.verticalSize << " " << _currentBorder1.horizontalSize << " new: " << newDetectedBorder.verticalSize << " " << newDetectedBorder.horizontalSize << " c:i " << _consistentCnt1 << ":" << _inconsistentCnt1 << std::endl; + + // check if there is a change + if (_currentBorder1 == newDetectedBorder) + { + // No change required + return false; + } + + bool borderChanged = false; + if (newDetectedBorder.unknown) + { + // apply the unknown border if we consistently can't determine a border + if (_consistentCnt1 == _unknownSwitchCnt) + { + _currentBorder1 = newDetectedBorder; + borderChanged = true; + } + } + else + { + // apply the detected border if it has been detected consistently + if (_currentBorder1.unknown || _consistentCnt1 == _borderSwitchCnt) + { + _currentBorder1 = newDetectedBorder; + borderChanged = true; + } + else + { + bool stable = (_consistentCnt >= 10) || (_inconsistentCnt >=30 ); + // apply smaller borders immediately + if ((newDetectedBorder.verticalSize < _currentBorder1.verticalSize) && (stable)) + { + _currentBorder1.verticalSize = newDetectedBorder.verticalSize; + borderChanged = true; + } + + if ((newDetectedBorder.horizontalSize < _currentBorder1.horizontalSize) && (stable)) + { + _currentBorder1.horizontalSize = newDetectedBorder.horizontalSize; + borderChanged = true; + } + } + } + + return borderChanged; +} + +bool BlackBorderProcessor::updateBorder2(const BlackBorder & newDetectedBorder) { // set the consistency counter if (newDetectedBorder == _previousDetectedBorder) { - if (_consistentCnt < 100000) - { - ++_consistentCnt; - } + ++_consistentCnt; + _inconsistentCnt = 0; } else { _previousDetectedBorder = newDetectedBorder; _consistentCnt = 0; + ++_inconsistentCnt; } -// std::cout << "new: " << newDetectedBorder.verticalSize << " " << newDetectedBorder.horizontalSize << " cur: " << _currentBorder.verticalSize << " " << _currentBorder.horizontalSize << " cc " << _consistentCnt << std::endl; +// std::cout << "cur: " << _currentBorder.verticalSize << " " << _currentBorder.horizontalSize << " new: " << newDetectedBorder.verticalSize << " " << newDetectedBorder.horizontalSize << " c:i " << _consistentCnt << ":" << _inconsistentCnt << std::endl; // check if there is a change if (_currentBorder == newDetectedBorder) @@ -71,16 +155,19 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) } else { + bool stable = (_consistentCnt >= 10) || (_inconsistentCnt >=30 ); + //more then A consistent seems like a new size not only a short flicker + //more then B inconsistent seems like the image is changing a lot and we need to set smaller border // apply smaller borders immediately // if (newDetectedBorder.verticalSize < _currentBorder.verticalSize) - if ( (newDetectedBorder.verticalSize < _currentBorder.verticalSize) && (_consistentCnt >= 1) )// almost immediatly - avoid switching for "abnormal" frames + if ( (newDetectedBorder.verticalSize < _currentBorder.verticalSize) && (stable) )// almost immediatly - avoid switching for "abnormal" frames { _currentBorder.verticalSize = newDetectedBorder.verticalSize; borderChanged = true; } // if (newDetectedBorder.horizontalSize < _currentBorder.horizontalSize) - if ( (newDetectedBorder.horizontalSize < _currentBorder.horizontalSize) && (_consistentCnt >= 1) ) + if ( (newDetectedBorder.horizontalSize < _currentBorder.horizontalSize) && (stable) ) { _currentBorder.horizontalSize = newDetectedBorder.horizontalSize; borderChanged = true; @@ -89,4 +176,4 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) } return borderChanged; -} +} \ No newline at end of file From ac86a779b076ff7f7b37a055b1ad2e7650f76ec2 Mon Sep 17 00:00:00 2001 From: wisc Date: Sun, 10 Jan 2016 14:55:23 +0100 Subject: [PATCH 29/96] cleanup Former-commit-id: 39cb3f76379990085407791ec391732c986790e6 --- include/blackborder/BlackBorderProcessor.h | 4 - libsrc/blackborder/BlackBorderProcessor.cpp | 88 +-------------------- 2 files changed, 1 insertion(+), 91 deletions(-) diff --git a/include/blackborder/BlackBorderProcessor.h b/include/blackborder/BlackBorderProcessor.h index 19f90d3d..ad8c7b83 100644 --- a/include/blackborder/BlackBorderProcessor.h +++ b/include/blackborder/BlackBorderProcessor.h @@ -89,18 +89,14 @@ namespace hyperion BlackBorderDetector _detector; /// The current detected border - BlackBorder _currentBorder1; BlackBorder _currentBorder; /// The border detected in the previous frame - BlackBorder _previousDetectedBorder1; BlackBorder _previousDetectedBorder; /// The number of frame the previous detected border matched the incomming border - unsigned _consistentCnt1; unsigned _consistentCnt; /// The number of frame the previous detected border NOT matched the incomming border - unsigned _inconsistentCnt1; unsigned _inconsistentCnt; }; } // end namespace hyperion diff --git a/libsrc/blackborder/BlackBorderProcessor.cpp b/libsrc/blackborder/BlackBorderProcessor.cpp index b3f1824f..28262229 100644 --- a/libsrc/blackborder/BlackBorderProcessor.cpp +++ b/libsrc/blackborder/BlackBorderProcessor.cpp @@ -1,4 +1,4 @@ -#include + // Blackborder includes #include @@ -12,13 +12,9 @@ BlackBorderProcessor::BlackBorderProcessor(const unsigned unknownFrameCnt, _borderSwitchCnt(borderFrameCnt), _blurRemoveCnt(blurRemoveCnt), _detector(blackborderThreshold), - _currentBorder1({true, -1, -1}), _currentBorder({true, -1, -1}), - _previousDetectedBorder1({true, -1, -1}), _previousDetectedBorder({true, -1, -1}), - _consistentCnt1(0), _consistentCnt(0), - _inconsistentCnt1(0), _inconsistentCnt(0) { // empty @@ -29,87 +25,7 @@ BlackBorder BlackBorderProcessor::getCurrentBorder() const return _currentBorder; } - bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) -{ -bool result1 = updateBorder1(newDetectedBorder); -if (result1) -{ - std::cout << "border change v1 " << _currentBorder1.horizontalSize << ":" << _currentBorder1.verticalSize << std::endl; -} - -bool result2 = updateBorder2(newDetectedBorder); -if (result2) -{ - std::cout << "border change v2 " << _currentBorder.horizontalSize << ":" << _currentBorder.verticalSize << std::endl; -} - -return result2; -} - - -bool BlackBorderProcessor::updateBorder1(const BlackBorder & newDetectedBorder) -{ - // set the consistency counter - if (newDetectedBorder == _previousDetectedBorder1) - { - ++_consistentCnt1; - } - else - { - _previousDetectedBorder1 = newDetectedBorder; - _consistentCnt1 = 0; - } - -// std::cout << "cur: " << _currentBorder1.verticalSize << " " << _currentBorder1.horizontalSize << " new: " << newDetectedBorder.verticalSize << " " << newDetectedBorder.horizontalSize << " c:i " << _consistentCnt1 << ":" << _inconsistentCnt1 << std::endl; - - // check if there is a change - if (_currentBorder1 == newDetectedBorder) - { - // No change required - return false; - } - - bool borderChanged = false; - if (newDetectedBorder.unknown) - { - // apply the unknown border if we consistently can't determine a border - if (_consistentCnt1 == _unknownSwitchCnt) - { - _currentBorder1 = newDetectedBorder; - borderChanged = true; - } - } - else - { - // apply the detected border if it has been detected consistently - if (_currentBorder1.unknown || _consistentCnt1 == _borderSwitchCnt) - { - _currentBorder1 = newDetectedBorder; - borderChanged = true; - } - else - { - bool stable = (_consistentCnt >= 10) || (_inconsistentCnt >=30 ); - // apply smaller borders immediately - if ((newDetectedBorder.verticalSize < _currentBorder1.verticalSize) && (stable)) - { - _currentBorder1.verticalSize = newDetectedBorder.verticalSize; - borderChanged = true; - } - - if ((newDetectedBorder.horizontalSize < _currentBorder1.horizontalSize) && (stable)) - { - _currentBorder1.horizontalSize = newDetectedBorder.horizontalSize; - borderChanged = true; - } - } - } - - return borderChanged; -} - -bool BlackBorderProcessor::updateBorder2(const BlackBorder & newDetectedBorder) { // set the consistency counter if (newDetectedBorder == _previousDetectedBorder) @@ -124,8 +40,6 @@ bool BlackBorderProcessor::updateBorder2(const BlackBorder & newDetectedBorder) ++_inconsistentCnt; } -// std::cout << "cur: " << _currentBorder.verticalSize << " " << _currentBorder.horizontalSize << " new: " << newDetectedBorder.verticalSize << " " << newDetectedBorder.horizontalSize << " c:i " << _consistentCnt << ":" << _inconsistentCnt << std::endl; - // check if there is a change if (_currentBorder == newDetectedBorder) { From 4bc11548b4584f93b4e0b3fa83cf221d78e2edba Mon Sep 17 00:00:00 2001 From: wisc Date: Sun, 10 Jan 2016 18:42:55 +0100 Subject: [PATCH 30/96] faster detection less false positive Former-commit-id: 501de9bca4c20600fe1e6250e82143f0b0d6ade3 --- include/blackborder/BlackBorderDetector.h | 53 +-------------------- include/blackborder/BlackBorderProcessor.h | 2 - libsrc/blackborder/BlackBorderProcessor.cpp | 17 +++---- 3 files changed, 8 insertions(+), 64 deletions(-) diff --git a/include/blackborder/BlackBorderDetector.h b/include/blackborder/BlackBorderDetector.h index cd955b8a..14cf051c 100644 --- a/include/blackborder/BlackBorderDetector.h +++ b/include/blackborder/BlackBorderDetector.h @@ -62,15 +62,13 @@ namespace hyperion BlackBorder process(const Image & image) { - // only test the topleft third of the image + // test center and 1/3, 2/3 of width/heigth int width = image.width() / 3; int height = image.height() / 3; int width2 = width * 2; int height2 = height * 2; int xCenter = image.width() / 2; int yCenter = image.height() / 2; -// int maxSize = std::max(width, height); - int firstNonBlackXPixelIndex = -1; @@ -102,55 +100,6 @@ namespace hyperion } } - - -/* - // only test the topleft third of the image - int width = image.width() /3; - int height = image.height() / 3; - int maxSize = std::max(width, height); - - - - int firstNonBlackXPixelIndex = -1; - int firstNonBlackYPixelIndex = -1; - - // find some pixel of the image - for (int i = 0; i < maxSize; ++i) - { - int x = std::min(i, width); - int y = std::min(i, height); - - const Pixel_T & color = image(x, y); - if (!isBlack(color)) - { - firstNonBlackXPixelIndex = x; - firstNonBlackYPixelIndex = y; - break; - } - } - - // expand image to the left - for(; firstNonBlackXPixelIndex > 0; --firstNonBlackXPixelIndex) - { - const Pixel_T & color = image(firstNonBlackXPixelIndex-1, firstNonBlackYPixelIndex); - if (isBlack(color)) - { - break; - } - } - - // expand image to the top - for(; firstNonBlackYPixelIndex > 0; --firstNonBlackYPixelIndex) - { - const Pixel_T & color = image(firstNonBlackXPixelIndex, firstNonBlackYPixelIndex-1); - if (isBlack(color)) - { - break; - } - } -*/ - // Construct result BlackBorder detectedBorder; detectedBorder.unknown = firstNonBlackXPixelIndex == -1 || firstNonBlackYPixelIndex == -1; diff --git a/include/blackborder/BlackBorderProcessor.h b/include/blackborder/BlackBorderProcessor.h index ad8c7b83..14be0585 100644 --- a/include/blackborder/BlackBorderProcessor.h +++ b/include/blackborder/BlackBorderProcessor.h @@ -73,8 +73,6 @@ namespace hyperion /// @return True if the current border changed else false /// bool updateBorder(const BlackBorder & newDetectedBorder); - bool updateBorder1(const BlackBorder & newDetectedBorder); - bool updateBorder2(const BlackBorder & newDetectedBorder); /// The number of unknown-borders detected before it becomes the current border const unsigned _unknownSwitchCnt; diff --git a/libsrc/blackborder/BlackBorderProcessor.cpp b/libsrc/blackborder/BlackBorderProcessor.cpp index 28262229..2312da31 100644 --- a/libsrc/blackborder/BlackBorderProcessor.cpp +++ b/libsrc/blackborder/BlackBorderProcessor.cpp @@ -51,8 +51,7 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) if (newDetectedBorder.unknown) { // apply the unknown border if we consistently can't determine a border -// if (_consistentCnt == _unknownSwitchCnt) - if (_consistentCnt >= _unknownSwitchCnt) + if (_consistentCnt == _unknownSwitchCnt) { _currentBorder = newDetectedBorder; borderChanged = true; @@ -61,8 +60,7 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) else { // apply the detected border if it has been detected consistently -// if (_currentBorder.unknown || _consistentCnt == _borderSwitchCnt) - if (_currentBorder.unknown || _consistentCnt >= _borderSwitchCnt) + if (_currentBorder.unknown || _consistentCnt == _borderSwitchCnt) { _currentBorder = newDetectedBorder; borderChanged = true; @@ -70,17 +68,16 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) else { bool stable = (_consistentCnt >= 10) || (_inconsistentCnt >=30 ); - //more then A consistent seems like a new size not only a short flicker - //more then B inconsistent seems like the image is changing a lot and we need to set smaller border - // apply smaller borders immediately -// if (newDetectedBorder.verticalSize < _currentBorder.verticalSize) - if ( (newDetectedBorder.verticalSize < _currentBorder.verticalSize) && (stable) )// almost immediatly - avoid switching for "abnormal" frames + //more then 10 consistent seems like a new size not only a short flicker + //more then 30 inconsistent seems like the image is changing a lot and we need to set smaller border + + // apply smaller borders (almost) immediately -> avoid switching for "abnormal" frames + if ( (newDetectedBorder.verticalSize < _currentBorder.verticalSize) && (stable) ) { _currentBorder.verticalSize = newDetectedBorder.verticalSize; borderChanged = true; } -// if (newDetectedBorder.horizontalSize < _currentBorder.horizontalSize) if ( (newDetectedBorder.horizontalSize < _currentBorder.horizontalSize) && (stable) ) { _currentBorder.horizontalSize = newDetectedBorder.horizontalSize; From 9c1e565d33e72cd1f2cfcde11d2a6e190cdc91f0 Mon Sep 17 00:00:00 2001 From: ntim Date: Sun, 10 Jan 2016 22:17:59 +0100 Subject: [PATCH 31/96] Transition to QNetworkAccessManager for compatibility to QT5 Former-commit-id: 6e65da9338d131d1017051e505db8c28696adf4f --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 37 ++++++++++-------------- libsrc/leddevice/LedDevicePhilipsHue.h | 6 ++-- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index 056e9ead..dc95d421 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -6,9 +6,8 @@ // qt includes #include -#include -#include #include +#include #include @@ -144,14 +143,14 @@ LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::s int transitiontime, std::vector lightIds) : host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime( transitiontime), lightIds(lightIds) { - http = new QHttp(host); + manager = new QNetworkAccessManager(); timer.setInterval(3000); timer.setSingleShot(true); connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates())); } LedDevicePhilipsHue::~LedDevicePhilipsHue() { - delete http; + delete manager; } int LedDevicePhilipsHue::write(const std::vector & ledValues) { @@ -216,33 +215,29 @@ int LedDevicePhilipsHue::switchOff() { } void LedDevicePhilipsHue::put(QString route, QString content) { - QString url = QString("/api/%1/%2").arg(username).arg(route); - QHttpRequestHeader header("PUT", url); - header.setValue("Host", host); - header.setValue("Accept-Encoding", "identity"); - header.setValue("Connection", "keep-alive"); - header.setValue("Content-Length", QString("%1").arg(content.size())); - QEventLoop loop; - // Connect requestFinished signal to quit slot of the loop. - loop.connect(http, SIGNAL(requestFinished(int, bool)), SLOT(quit())); + QString url = QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route); // Perfrom request - http->request(header, content.toAscii()); + QNetworkRequest request(url); + QNetworkReply* reply = manager->put(request, content.toAscii()); + // Connect finished signal to quit slot of the loop. + QEventLoop loop; + loop.connect(reply, SIGNAL(finished()), SLOT(quit())); // Go into the loop until the request is finished. loop.exec(); } QByteArray LedDevicePhilipsHue::get(QString route) { - QString url = QString("/api/%1/%2").arg(username).arg(route); - // Event loop to block until request finished. - QEventLoop loop; - // Connect requestFinished signal to quit slot of the loop. - loop.connect(http, SIGNAL(requestFinished(int, bool)), SLOT(quit())); + QString url = QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route); // Perfrom request - http->get(url); + QNetworkRequest request(url); + QNetworkReply* reply = manager->get(request); + // Connect requestFinished signal to quit slot of the loop. + QEventLoop loop; + loop.connect(reply, SIGNAL(finished()), SLOT(quit())); // Go into the loop until the request is finished. loop.exec(); // Read all data of the response. - return http->readAll(); + return reply->readAll(); } QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) { diff --git a/libsrc/leddevice/LedDevicePhilipsHue.h b/libsrc/leddevice/LedDevicePhilipsHue.h index 59c0383d..2d6f9056 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/LedDevicePhilipsHue.h @@ -6,7 +6,7 @@ // Qt includes #include #include -#include +#include #include // Leddevice includes @@ -164,8 +164,8 @@ private: QString host; /// User name for the API ("newdeveloper") QString username; - /// Qhttp object for sending requests. - QHttp* http; + /// QNetworkAccessManager object for sending requests. + QNetworkAccessManager* manager; /// Use timer to reset lights when we got into "GRABBINGMODE_OFF". QTimer timer; /// From e0d04d606c56e6d7a43d4a29843d01bb4aa69349 Mon Sep 17 00:00:00 2001 From: "T.van der Zwan" Date: Wed, 13 Jan 2016 22:52:50 +0100 Subject: [PATCH 32/96] Updated releases with latest pulls Former-commit-id: 1734e9a6010789b31120f9630745b731da5109cd --- deploy/hyperion_imx6.tar.gz.REMOVED.git-id | 2 +- deploy/hyperion_rpi.tar.gz.REMOVED.git-id | 2 +- deploy/hyperion_wetek.tar.gz.REMOVED.git-id | 2 +- deploy/hyperion_x32.tar.gz.REMOVED.git-id | 2 +- deploy/hyperion_x64.tar.gz.REMOVED.git-id | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy/hyperion_imx6.tar.gz.REMOVED.git-id b/deploy/hyperion_imx6.tar.gz.REMOVED.git-id index 294f2909..99536c87 100644 --- a/deploy/hyperion_imx6.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_imx6.tar.gz.REMOVED.git-id @@ -1 +1 @@ -3785db40d7232275fbc00b20e627280e0e057f99 \ No newline at end of file +471d676fb66aa53e3b10d887a1d9e6d3b4afea90 \ No newline at end of file diff --git a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id index 0f6903ba..44bbdc58 100644 --- a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id @@ -1 +1 @@ -0769228a95e4a0d4b2ed6649f21ddf70b43773d6 \ No newline at end of file +5c164e4ff52076a530461cdf6966943d52cd39df \ No newline at end of file diff --git a/deploy/hyperion_wetek.tar.gz.REMOVED.git-id b/deploy/hyperion_wetek.tar.gz.REMOVED.git-id index 4a4621a7..668065d1 100644 --- a/deploy/hyperion_wetek.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_wetek.tar.gz.REMOVED.git-id @@ -1 +1 @@ -7e53ee35b7258e7d58d96514701a50014a98da31 \ No newline at end of file +d2bf44cca4e7753b53acc2ebbdb933ba8f74f93f \ No newline at end of file diff --git a/deploy/hyperion_x32.tar.gz.REMOVED.git-id b/deploy/hyperion_x32.tar.gz.REMOVED.git-id index 24239241..89355ddf 100644 --- a/deploy/hyperion_x32.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_x32.tar.gz.REMOVED.git-id @@ -1 +1 @@ -36d03bb18626fa0faea8aabf6426e571eab4f719 \ No newline at end of file +7936b39302bec31b18f11a321ba6904c12b5c3ec \ No newline at end of file diff --git a/deploy/hyperion_x64.tar.gz.REMOVED.git-id b/deploy/hyperion_x64.tar.gz.REMOVED.git-id index f6368736..38e3e0b0 100644 --- a/deploy/hyperion_x64.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_x64.tar.gz.REMOVED.git-id @@ -1 +1 @@ -6f86ceeb6650e527d179cf7153e0beada3b73889 \ No newline at end of file +774c67bd8e4e46d2ebf9c223a38fdfd93cae1100 \ No newline at end of file From 9156742aaa45b4ed130e590b984e65b17d2894f2 Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Sun, 17 Jan 2016 18:00:38 +0100 Subject: [PATCH 33/96] Update X11Grabber.h Former-commit-id: 7b3ba3f760ba4b403061642549164ef2e1768b32 --- include/grabber/X11Grabber.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/grabber/X11Grabber.h b/include/grabber/X11Grabber.h index ee857b01..61c2d103 100644 --- a/include/grabber/X11Grabber.h +++ b/include/grabber/X11Grabber.h @@ -26,6 +26,11 @@ private: int _cropRight; int _cropTop; int _cropBottom; + + Screen *Xscreen; + XImage *xImage; + XShmSegmentInfo shminfo; + int screen; /// Reference to the X11 display (nullptr if not opened) Display * _x11Display; From 2a1673d8c37ed0e491253f50724d64814e066150 Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Sun, 17 Jan 2016 18:04:08 +0100 Subject: [PATCH 34/96] Update X11Grabber.cpp Former-commit-id: 849f1a2b6217b76739f84f6c9fb5645cab584f98 --- libsrc/grabber/x11/X11Grabber.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libsrc/grabber/x11/X11Grabber.cpp b/libsrc/grabber/x11/X11Grabber.cpp index 0787e056..494af111 100644 --- a/libsrc/grabber/x11/X11Grabber.cpp +++ b/libsrc/grabber/x11/X11Grabber.cpp @@ -54,12 +54,25 @@ Image & X11Grabber::grab() } updateScreenDimensions(); + + Xscreen = DefaultScreenOfDisplay(_x11Display); const unsigned croppedWidth = _screenWidth - _cropLeft - _cropRight; const unsigned croppedHeight = _screenHeight - _cropTop - _cropBottom; + + xImage = XShmCreateImage(_x11Display, DefaultVisualOfScreen(Xscreen), + DefaultDepthOfScreen(Xscreen), + ZPixmap, NULL, &shminfo, + croppedWidth, croppedHeight); + + shminfo.shmid = shmget(IPC_PRIVATE, xImage->bytes_per_line * xImage->height, IPC_CREAT|0777); + shminfo.shmaddr = xImage->data = (char*)shmat(shminfo.shmid,0,0); + shminfo.readOnly = False; + + XShmAttach(_x11Display, &shminfo); // Capture the current screen - XImage * xImage = XGetImage(_x11Display, DefaultRootWindow(_x11Display), _cropLeft, _cropTop, croppedWidth, croppedHeight, AllPlanes, ZPixmap); + XShmGetImage(_x11Display, DefaultRootWindow(_x11Display), xImage, _cropLeft, _cropTop, 0x00FFFFFF); if (xImage == nullptr) { std::cerr << "Grab failed" << std::endl; @@ -69,7 +82,10 @@ Image & X11Grabber::grab() _imageResampler.processImage(reinterpret_cast(xImage->data), xImage->width, xImage->height, xImage->bytes_per_line, PIXELFORMAT_BGR32, _image); // Cleanup allocated resources of the X11 grab + XShmDetach(_x11Display, &shminfo); XDestroyImage(xImage); + shmdt (shminfo.shmaddr); + shmctl(shminfo.shmid, IPC_RMID, 0); return _image; } From 641e8ba6e0591c1d2ec2e78dd1a362b30acd6072 Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Sun, 17 Jan 2016 18:18:12 +0100 Subject: [PATCH 35/96] Create police-lights-single.json Former-commit-id: 1503be1ff3092af365cfb3479e2911e1c3b8dd97 --- effects/police-lights-single.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 effects/police-lights-single.json diff --git a/effects/police-lights-single.json b/effects/police-lights-single.json new file mode 100644 index 00000000..9f171139 --- /dev/null +++ b/effects/police-lights-single.json @@ -0,0 +1,12 @@ +{ + "name" : "Police Lights Single", + "script" : "police.py", + "args" : + { + "rotation-time" : 1.5, + "color_one" : [ 255, 0, 0 ], + "color_two" : [ 0, 0, 255 ], + "colors_count" : 10, + "reverse" : false + } +} From da914e0135b61581a64be775d260b6adc7a0bf76 Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Sun, 17 Jan 2016 18:18:49 +0100 Subject: [PATCH 36/96] Create police-lights-solid.json Former-commit-id: d3f433361bb305b3d367754fc4c4818092a6c74b --- effects/police-lights-solid.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 effects/police-lights-solid.json diff --git a/effects/police-lights-solid.json b/effects/police-lights-solid.json new file mode 100644 index 00000000..5eee1f58 --- /dev/null +++ b/effects/police-lights-solid.json @@ -0,0 +1,11 @@ +{ + "name" : "Police Lights Solid", + "script" : "police.py", + "args" : + { + "rotation-time" : 1.0, + "color_one" : [ 255, 0, 0 ], + "color_two" : [ 0, 0, 255 ], + "reverse" : false + } +} From 7d9de67449ba62b5bffb1bf60c308ea4c6b8577a Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Sun, 17 Jan 2016 18:19:33 +0100 Subject: [PATCH 37/96] Create police.py Former-commit-id: 97f31beef808c6b4950d598affc5259bbc8edee4 --- effects/police.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 effects/police.py diff --git a/effects/police.py b/effects/police.py new file mode 100644 index 00000000..2f4133d2 --- /dev/null +++ b/effects/police.py @@ -0,0 +1,46 @@ +import hyperion +import time +import colorsys + +# Get the parameters +rotationTime = float(hyperion.args.get('rotation-time', 2.0)) +colorOne = hyperion.args.get('color_one', (255,0,0)) +colorTwo = hyperion.args.get('color_two', (0,0,255)) +colorsCount = hyperion.args.get('colors_count', hyperion.ledCount/2) +reverse = bool(hyperion.args.get('reverse', False)) + +# Check parameters +rotationTime = max(0.1, rotationTime) +colorsCount = min(hyperion.ledCount/2, colorsCount) + +# Initialize the led data +hsv1 = colorsys.rgb_to_hsv(colorOne[0]/255.0, colorOne[1]/255.0, colorOne[2]/255.0) +hsv2 = colorsys.rgb_to_hsv(colorTwo[0]/255.0, colorTwo[1]/255.0, colorTwo[2]/255.0) +colorBlack = (0,0,0) +ledData = bytearray() +for i in range(hyperion.ledCount): + if i <= colorsCount: + rgb = colorsys.hsv_to_rgb(hsv1[0], hsv1[1], hsv1[2]) + elif (i >= hyperion.ledCount/2-1) & (i < (hyperion.ledCount/2) + colorsCount): + rgb = colorsys.hsv_to_rgb(hsv2[0], hsv2[1], hsv2[2]) + else: + rgb = colorBlack + ledData += bytearray((int(255*rgb[0]), int(255*rgb[1]), int(255*rgb[2]))) + +# Calculate the sleep time and rotation increment +increment = 3 +sleepTime = rotationTime / hyperion.ledCount +while sleepTime < 0.05: + increment *= 2 + sleepTime *= 2 +increment %= hyperion.ledCount + +# Switch direction if needed +if reverse: + increment = -increment + +# Start the write data loop +while not hyperion.abort(): + hyperion.setColor(ledData) + ledData = ledData[-increment:] + ledData[:-increment] + time.sleep(sleepTime) From 538775928731246116afd7b42cb37ea5fd3dd7ce Mon Sep 17 00:00:00 2001 From: penfold42 Date: Mon, 18 Jan 2016 17:31:17 +1100 Subject: [PATCH 38/96] updated URLs in the installation script to reference current builds Former-commit-id: 014c31531dbc5cce74870d8f3c112fcf10f9460d --- bin/install_hyperion.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/install_hyperion.sh b/bin/install_hyperion.sh index 4d3e9a2c..4c06e696 100755 --- a/bin/install_hyperion.sh +++ b/bin/install_hyperion.sh @@ -40,7 +40,7 @@ if [ $IS_OPENELEC -eq 1 ]; then if [ $IS_IMX6 -eq 1 ]; then curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_imx6.tar.gz | tar -C /storage -xz else - curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.tar.gz | tar -C /storage -xz + curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_rpi.tar.gz | tar -C /storage -xz fi curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.deps.openelec-rpi.tar.gz | tar -C /storage/hyperion/bin -xz # modify the default config to have a correct effect path @@ -49,7 +49,7 @@ else if [ $IS_IMX6 -eq 1 ]; then wget https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_imx6.tar.gz -O - | tar -C /opt -xz else - wget https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.tar.gz -O - | tar -C /opt -xz + wget https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_rpi.tar.gz -O - | tar -C /opt -xz fi fi From 6b860a7e244d87e0e6202012d9c2d2f4a7585d11 Mon Sep 17 00:00:00 2001 From: ntim Date: Mon, 18 Jan 2016 10:41:45 +0100 Subject: [PATCH 39/96] Removed all QT5 switches Former-commit-id: 7a481a921d572e4c0eccebfb1ba3abbab61d25fc --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index b1d138e9..21d397a6 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -200,25 +200,17 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { // Next light id. idx++; } -#ifdef ENABLE_QT5 - -#else timer.start(); -#endif return 0; } int LedDevicePhilipsHue::switchOff() { -#ifdef ENABLE_QT5 - -#else timer.stop(); // If light states have been saved before, ... if (areStatesSaved()) { // ... restore them. restoreStates(); } -#endif return 0; } From 391e2e552c1909ba682d4d52ba2ae299b3c8a054 Mon Sep 17 00:00:00 2001 From: wisc Date: Tue, 19 Jan 2016 23:43:00 +0100 Subject: [PATCH 40/96] release candidate Former-commit-id: e81f58386ce64f836561faf30ef2c3fb154358b5 --- include/blackborder/BlackBorderDetector.h | 30 ++++++++------ libsrc/blackborder/BlackBorderProcessor.cpp | 45 +++++++++++---------- test/TestBlackBorderProcessor.cpp | 42 ++++++++++++++----- 3 files changed, 74 insertions(+), 43 deletions(-) diff --git a/include/blackborder/BlackBorderDetector.h b/include/blackborder/BlackBorderDetector.h index 14cf051c..d3764ced 100644 --- a/include/blackborder/BlackBorderDetector.h +++ b/include/blackborder/BlackBorderDetector.h @@ -62,13 +62,17 @@ namespace hyperion BlackBorder process(const Image & image) { - // test center and 1/3, 2/3 of width/heigth - int width = image.width() / 3; - int height = image.height() / 3; - int width2 = width * 2; - int height2 = height * 2; - int xCenter = image.width() / 2; - int yCenter = image.height() / 2; + // test center and 33%, 66% of width/heigth + // 33 and 66 will check left and top + // center ill check right and bottom sids + int width = image.width(); + int height = image.height(); + int width33percent = width / 3; + int height33percent = height / 3; + int width66percent = width33percent * 2; + int height66percent = height33percent * 2; + int xCenter = width / 2; + int yCenter = height / 2; int firstNonBlackXPixelIndex = -1; @@ -77,9 +81,9 @@ namespace hyperion // find first X pixel of the image for (int x = 0; x < width; ++x) { - const Pixel_T & color1 = image(x, yCenter); - const Pixel_T & color2 = image(x, height); - const Pixel_T & color3 = image(x, height2); + const Pixel_T & color1 = image( (width - x), yCenter); // right side center line check + const Pixel_T & color2 = image(x, height33percent); + const Pixel_T & color3 = image(x, height66percent); if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3)) { firstNonBlackXPixelIndex = x; @@ -90,9 +94,9 @@ namespace hyperion // find first Y pixel of the image for (int y = 0; y < height; ++y) { - const Pixel_T & color1 = image(xCenter, y); - const Pixel_T & color2 = image(width, y); - const Pixel_T & color3 = image(width2, y); + const Pixel_T & color1 = image(xCenter, (height - y)); // bottom center line check + const Pixel_T & color2 = image(width33percent, y ); + const Pixel_T & color3 = image(width66percent, y); if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3)) { firstNonBlackYPixelIndex = y; diff --git a/libsrc/blackborder/BlackBorderProcessor.cpp b/libsrc/blackborder/BlackBorderProcessor.cpp index 2312da31..93cbbcff 100644 --- a/libsrc/blackborder/BlackBorderProcessor.cpp +++ b/libsrc/blackborder/BlackBorderProcessor.cpp @@ -1,3 +1,4 @@ +#include // Blackborder includes #include @@ -15,7 +16,7 @@ BlackBorderProcessor::BlackBorderProcessor(const unsigned unknownFrameCnt, _currentBorder({true, -1, -1}), _previousDetectedBorder({true, -1, -1}), _consistentCnt(0), - _inconsistentCnt(0) + _inconsistentCnt(10) { // empty } @@ -27,6 +28,19 @@ BlackBorder BlackBorderProcessor::getCurrentBorder() const bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) { +// the new changes ignore false small borders (no reset of consistance) +// as long as the previous stable state returns within 10 frames +// and will only switch to a new border if it is realy detected stable >50 frames + +// sometimes the grabber delivers "bad" frames with a smaller black border (looks like random number every few frames and even when freezing the image) +// maybe some interferences of the power supply or bad signal causing this effect - not exactly sure what causes it but changing the power supply of the converter significantly increased that "random" effect on my system +// (you can check with the debug output below or if you want i can provide some output logs) +// this "random effect" caused the old algorithm to switch to that smaller border immediatly, resulting in a too small border being detected +// makes it look like the border detectionn is not working - since the new 3 line detection algorithm is more precise this became a problem specialy in dark scenes +// wisc + + std::cout << "cur: " << _currentBorder.verticalSize << " " << _currentBorder.horizontalSize << " new: " << newDetectedBorder.verticalSize << " " << newDetectedBorder.horizontalSize << " c:i " << _consistentCnt << ":" << _inconsistentCnt << std::endl; + // set the consistency counter if (newDetectedBorder == _previousDetectedBorder) { @@ -35,15 +49,23 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) } else { + ++_inconsistentCnt; + if (_inconsistentCnt <= 10)// few inconsistent frames + { + //discard the newDetectedBorder -> keep the consistent count for previousDetectedBorder + return false; + } + // the inconsistency threshold is reached + // -> give the newDetectedBorder a chance to proof that its consistent _previousDetectedBorder = newDetectedBorder; _consistentCnt = 0; - ++_inconsistentCnt; } // check if there is a change if (_currentBorder == newDetectedBorder) { // No change required + _inconsistentCnt = 0; // we have found a consistent border -> reset _inconsistentCnt return false; } @@ -65,25 +87,6 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) _currentBorder = newDetectedBorder; borderChanged = true; } - else - { - bool stable = (_consistentCnt >= 10) || (_inconsistentCnt >=30 ); - //more then 10 consistent seems like a new size not only a short flicker - //more then 30 inconsistent seems like the image is changing a lot and we need to set smaller border - - // apply smaller borders (almost) immediately -> avoid switching for "abnormal" frames - if ( (newDetectedBorder.verticalSize < _currentBorder.verticalSize) && (stable) ) - { - _currentBorder.verticalSize = newDetectedBorder.verticalSize; - borderChanged = true; - } - - if ( (newDetectedBorder.horizontalSize < _currentBorder.horizontalSize) && (stable) ) - { - _currentBorder.horizontalSize = newDetectedBorder.horizontalSize; - borderChanged = true; - } - } } return borderChanged; diff --git a/test/TestBlackBorderProcessor.cpp b/test/TestBlackBorderProcessor.cpp index 4aceaa81..e05c630f 100644 --- a/test/TestBlackBorderProcessor.cpp +++ b/test/TestBlackBorderProcessor.cpp @@ -29,7 +29,7 @@ Image createImage(unsigned width, unsigned height, unsigned topBorder, { for (unsigned y=0; y ( height - topBorder ) || x < leftBorder || x > (width - leftBorder) ) { image(x,y) = ColorRgb::BLACK; } @@ -86,7 +86,7 @@ int main() for (unsigned i=0; i vertImage = createImage(64, 64, 0, borderSize); for (unsigned i=0; i Date: Wed, 20 Jan 2016 14:45:17 +0100 Subject: [PATCH 41/96] all effects has same lineendings Former-commit-id: c2586f57ce03c20a7a1083a5d62c8ddde7359b84 --- effects/knight-rider.json | 20 ++++++++++---------- effects/loop.json | 14 +++++++------- effects/loop2.json | 14 +++++++------- effects/mood-blobs-blue.json | 24 ++++++++++++------------ effects/mood-blobs-green.json | 24 ++++++++++++------------ effects/mood-blobs-red.json | 24 ++++++++++++------------ effects/rainbow-mood.json | 20 ++++++++++---------- effects/rainbow-swirl-fast.json | 20 ++++++++++---------- effects/rainbow-swirl.json | 20 ++++++++++---------- effects/random.json | 14 +++++++------- effects/snake.json | 20 ++++++++++---------- effects/sparks-color.json | 14 +++++++------- effects/sparks.json | 14 +++++++------- effects/x-mas.json | 16 ++++++++-------- 14 files changed, 129 insertions(+), 129 deletions(-) diff --git a/effects/knight-rider.json b/effects/knight-rider.json index b4644387..9801d491 100644 --- a/effects/knight-rider.json +++ b/effects/knight-rider.json @@ -1,10 +1,10 @@ -{ - "name" : "Knight rider", - "script" : "knight-rider.py", - "args" : - { - "speed" : 1.0, - "fadeFactor" : 0.7, - "color" : [255,0,0] - } -} +{ + "name" : "Knight rider", + "script" : "knight-rider.py", + "args" : + { + "speed" : 1.0, + "fadeFactor" : 0.7, + "color" : [255,0,0] + } +} diff --git a/effects/loop.json b/effects/loop.json index 9415f8b1..c4e58803 100644 --- a/effects/loop.json +++ b/effects/loop.json @@ -1,7 +1,7 @@ -{ - "name" : "Loop", - "script" : "loop.py", - "args" : - { - } -} +{ + "name" : "Loop", + "script" : "loop.py", + "args" : + { + } +} diff --git a/effects/loop2.json b/effects/loop2.json index 77f2c438..ebedbe34 100644 --- a/effects/loop2.json +++ b/effects/loop2.json @@ -1,7 +1,7 @@ -{ - "name" : "Loop2", - "script" : "loop2.py", - "args" : - { - } -} +{ + "name" : "Loop2", + "script" : "loop2.py", + "args" : + { + } +} diff --git a/effects/mood-blobs-blue.json b/effects/mood-blobs-blue.json index 1aa188ab..32280b46 100644 --- a/effects/mood-blobs-blue.json +++ b/effects/mood-blobs-blue.json @@ -1,12 +1,12 @@ -{ - "name" : "Blue mood blobs", - "script" : "mood-blobs.py", - "args" : - { - "rotationTime" : 60.0, - "color" : [0,0,255], - "hueChange" : 60.0, - "blobs" : 5, - "reverse" : false - } -} +{ + "name" : "Blue mood blobs", + "script" : "mood-blobs.py", + "args" : + { + "rotationTime" : 60.0, + "color" : [0,0,255], + "hueChange" : 60.0, + "blobs" : 5, + "reverse" : false + } +} diff --git a/effects/mood-blobs-green.json b/effects/mood-blobs-green.json index c0c104fe..aabd536c 100644 --- a/effects/mood-blobs-green.json +++ b/effects/mood-blobs-green.json @@ -1,12 +1,12 @@ -{ - "name" : "Green mood blobs", - "script" : "mood-blobs.py", - "args" : - { - "rotationTime" : 60.0, - "color" : [0,255,0], - "hueChange" : 60.0, - "blobs" : 5, - "reverse" : false - } -} +{ + "name" : "Green mood blobs", + "script" : "mood-blobs.py", + "args" : + { + "rotationTime" : 60.0, + "color" : [0,255,0], + "hueChange" : 60.0, + "blobs" : 5, + "reverse" : false + } +} diff --git a/effects/mood-blobs-red.json b/effects/mood-blobs-red.json index 3272dded..ac47af53 100644 --- a/effects/mood-blobs-red.json +++ b/effects/mood-blobs-red.json @@ -1,12 +1,12 @@ -{ - "name" : "Red mood blobs", - "script" : "mood-blobs.py", - "args" : - { - "rotationTime" : 60.0, - "color" : [255,0,0], - "hueChange" : 60.0, - "blobs" : 5, - "reverse" : false - } -} +{ + "name" : "Red mood blobs", + "script" : "mood-blobs.py", + "args" : + { + "rotationTime" : 60.0, + "color" : [255,0,0], + "hueChange" : 60.0, + "blobs" : 5, + "reverse" : false + } +} diff --git a/effects/rainbow-mood.json b/effects/rainbow-mood.json index fe754287..c9208b60 100644 --- a/effects/rainbow-mood.json +++ b/effects/rainbow-mood.json @@ -1,10 +1,10 @@ -{ - "name" : "Rainbow mood", - "script" : "rainbow-mood.py", - "args" : - { - "rotation-time" : 60.0, - "brightness" : 1.0, - "reverse" : false - } -} +{ + "name" : "Rainbow mood", + "script" : "rainbow-mood.py", + "args" : + { + "rotation-time" : 60.0, + "brightness" : 1.0, + "reverse" : false + } +} diff --git a/effects/rainbow-swirl-fast.json b/effects/rainbow-swirl-fast.json index 19fec89c..88e8d79d 100644 --- a/effects/rainbow-swirl-fast.json +++ b/effects/rainbow-swirl-fast.json @@ -1,10 +1,10 @@ -{ - "name" : "Rainbow swirl fast", - "script" : "rainbow-swirl.py", - "args" : - { - "rotation-time" : 3.0, - "brightness" : 1.0, - "reverse" : false - } -} +{ + "name" : "Rainbow swirl fast", + "script" : "rainbow-swirl.py", + "args" : + { + "rotation-time" : 3.0, + "brightness" : 1.0, + "reverse" : false + } +} diff --git a/effects/rainbow-swirl.json b/effects/rainbow-swirl.json index 3f7b7243..43a80a8d 100644 --- a/effects/rainbow-swirl.json +++ b/effects/rainbow-swirl.json @@ -1,10 +1,10 @@ -{ - "name" : "Rainbow swirl", - "script" : "rainbow-swirl.py", - "args" : - { - "rotation-time" : 20.0, - "brightness" : 1.0, - "reverse" : false - } -} +{ + "name" : "Rainbow swirl", + "script" : "rainbow-swirl.py", + "args" : + { + "rotation-time" : 20.0, + "brightness" : 1.0, + "reverse" : false + } +} diff --git a/effects/random.json b/effects/random.json index dc1d79ae..3dbc26d4 100644 --- a/effects/random.json +++ b/effects/random.json @@ -1,7 +1,7 @@ -{ - "name" : "Random", - "script" : "random.py", - "args" : - { - } -} +{ + "name" : "Random", + "script" : "random.py", + "args" : + { + } +} diff --git a/effects/snake.json b/effects/snake.json index 2c7ba395..eb914c89 100644 --- a/effects/snake.json +++ b/effects/snake.json @@ -1,10 +1,10 @@ -{ - "name" : "Snake", - "script" : "snake.py", - "args" : - { - "rotation-time" : 10.0, - "color" : [255, 0, 0], - "percentage" : 25 - } -} +{ + "name" : "Snake", + "script" : "snake.py", + "args" : + { + "rotation-time" : 10.0, + "color" : [255, 0, 0], + "percentage" : 25 + } +} diff --git a/effects/sparks-color.json b/effects/sparks-color.json index 1c3e8146..641b7d8d 100644 --- a/effects/sparks-color.json +++ b/effects/sparks-color.json @@ -1,7 +1,7 @@ -{ - "name" : "Sparks color", - "script" : "sparks-color.py", - "args" : - { - } -} +{ + "name" : "Sparks color", + "script" : "sparks-color.py", + "args" : + { + } +} diff --git a/effects/sparks.json b/effects/sparks.json index d4040309..f00c01ae 100644 --- a/effects/sparks.json +++ b/effects/sparks.json @@ -1,7 +1,7 @@ -{ - "name" : "Sparks", - "script" : "sparks.py", - "args" : - { - } -} +{ + "name" : "Sparks", + "script" : "sparks.py", + "args" : + { + } +} diff --git a/effects/x-mas.json b/effects/x-mas.json index 72892a52..6c73b645 100644 --- a/effects/x-mas.json +++ b/effects/x-mas.json @@ -1,8 +1,8 @@ -{ - "name" : "X-Mas", - "script" : "x-mas.py", - "args" : - { - "sleepTime" : 0.75 - } -} +{ + "name" : "X-Mas", + "script" : "x-mas.py", + "args" : + { + "sleepTime" : 0.75 + } +} From de5b2849751537a334ab684d3d22591cc9ed8fd9 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 20 Jan 2016 22:36:21 +0100 Subject: [PATCH 42/96] modify effects - snake has a nice tail - random is not so fast anymore - merge sparks and sparks-color - make more params available in json files Former-commit-id: fc2a4f6f6ce2b44a35a75a9c0dbe36504b790be9 --- effects/random.json | 6 ++++-- effects/random.py | 18 +++++++----------- effects/snake.json | 8 ++++---- effects/snake.py | 2 +- effects/sparks-color.json | 11 +++++++++-- effects/sparks-color.py | 35 ----------------------------------- effects/sparks.json | 7 +++++++ effects/sparks.py | 32 ++++++++++++++++++-------------- 8 files changed, 50 insertions(+), 69 deletions(-) delete mode 100644 effects/sparks-color.py diff --git a/effects/random.json b/effects/random.json index 3dbc26d4..4a85b133 100644 --- a/effects/random.json +++ b/effects/random.json @@ -1,7 +1,9 @@ { - "name" : "Random", + "name" : "Random", "script" : "random.py", - "args" : + "args" : { + "speed" : 1.0, + "saturation" : 1.0 } } diff --git a/effects/random.py b/effects/random.py index 0f5406b1..63b56dca 100644 --- a/effects/random.py +++ b/effects/random.py @@ -1,24 +1,20 @@ -import hyperion -import time -import colorsys -import random +import hyperion, time, colorsys, random + +# get args +sleepTime = float(hyperion.args.get('speed', 1.0)) +saturation = float(hyperion.args.get('saturation', 1.0)) +ledData = bytearray() # Initialize the led data -ledData = bytearray() for i in range(hyperion.ledCount): ledData += bytearray((0,0,0)) -sleepTime = 0.001 - # Start the write data loop while not hyperion.abort(): hyperion.setColor(ledData) for i in range(hyperion.ledCount): if random.randrange(10) == 1: - hue = random.random() - sat = 1.0 - val = random.random() - rgb = colorsys.hsv_to_rgb(hue, sat, val) + rgb = colorsys.hsv_to_rgb(random.random(), saturation, random.random()) ledData[i*3 ] = int(255*rgb[0]) ledData[i*3+1] = int(255*rgb[1]) ledData[i*3+2] = int(255*rgb[2]) diff --git a/effects/snake.json b/effects/snake.json index eb914c89..d5a7674f 100644 --- a/effects/snake.json +++ b/effects/snake.json @@ -1,10 +1,10 @@ { - "name" : "Snake", + "name" : "Snake", "script" : "snake.py", "args" : { - "rotation-time" : 10.0, - "color" : [255, 0, 0], - "percentage" : 25 + "rotation-time" : 12.0, + "color" : [255, 0, 0], + "percentage" : 10 } } diff --git a/effects/snake.py b/effects/snake.py index 2ae5cb37..d8d16561 100644 --- a/effects/snake.py +++ b/effects/snake.py @@ -23,7 +23,7 @@ for i in range(hyperion.ledCount-snakeLeds): ledData += bytearray((0, 0, 0)) for i in range(1,snakeLeds+1): - rgb = colorsys.hsv_to_rgb(hsv[0], hsv[1], hsv[2]/i) + rgb = colorsys.hsv_to_rgb(hsv[0], hsv[1], hsv[2]*(snakeLeds-i)/snakeLeds) ledData += bytearray((int(rgb[0]*255), int(rgb[1]*255), int(rgb[2]*255))) # Calculate the sleep time and rotation increment diff --git a/effects/sparks-color.json b/effects/sparks-color.json index 641b7d8d..e4d3649e 100644 --- a/effects/sparks-color.json +++ b/effects/sparks-color.json @@ -1,7 +1,14 @@ { - "name" : "Sparks color", - "script" : "sparks-color.py", + "name" : "Sparks Color", + "script" : "sparks.py", "args" : { + "rotation-time" : 3.0, + "sleep-time" : 0.05, + "brightness" : 1.0, + "saturation" : 1.0, + "reverse" : false, + "color" : [255,255,255], + "random-color" : true } } diff --git a/effects/sparks-color.py b/effects/sparks-color.py deleted file mode 100644 index 34b5acf5..00000000 --- a/effects/sparks-color.py +++ /dev/null @@ -1,35 +0,0 @@ -import hyperion -import time -import colorsys -import random - -# Get the parameters -rotationTime = float(hyperion.args.get('rotation-time', 3.0)) -brightness = float(hyperion.args.get('brightness', 1.0)) -saturation = float(hyperion.args.get('saturation', 1.0)) -reverse = bool(hyperion.args.get('reverse', False)) - -# Check parameters -rotationTime = max(0.1, rotationTime) -brightness = max(0.0, min(brightness, 1.0)) -saturation = max(0.0, min(saturation, 1.0)) - -# Initialize the led data -ledData = bytearray() - -sleepTime = 0.05 - -# Start the write data loop -while not hyperion.abort(): - ledData[:] = bytearray(3*hyperion.ledCount) - for i in range(hyperion.ledCount): - if random.random() < 0.005: - hue = random.random() - sat = 1 - val = 1 - rgb = colorsys.hsv_to_rgb(hue, sat, val) - ledData[i*3] = int(255*rgb[0]) - ledData[i*3+1] = int(255*rgb[1]) - ledData[i*3+2] = int(255*rgb[2]) - hyperion.setColor(ledData) - time.sleep(sleepTime) diff --git a/effects/sparks.json b/effects/sparks.json index f00c01ae..0860987e 100644 --- a/effects/sparks.json +++ b/effects/sparks.json @@ -3,5 +3,12 @@ "script" : "sparks.py", "args" : { + "rotation-time" : 3.0, + "sleep-time" : 0.05, + "brightness" : 1.0, + "saturation" : 1.0, + "reverse" : false, + "color" : [255,255,255], + "random-color" : false } } diff --git a/effects/sparks.py b/effects/sparks.py index 821719e2..f215ba9a 100644 --- a/effects/sparks.py +++ b/effects/sparks.py @@ -1,33 +1,37 @@ -import hyperion -import time -import colorsys -import random +import hyperion, time, colorsys, random # Get the parameters rotationTime = float(hyperion.args.get('rotation-time', 3.0)) -brightness = float(hyperion.args.get('brightness', 1.0)) -saturation = float(hyperion.args.get('saturation', 1.0)) -reverse = bool(hyperion.args.get('reverse', False)) +sleepTime = float(hyperion.args.get('sleep-time', 0.05)) +brightness = float(hyperion.args.get('brightness', 1.0)) +saturation = float(hyperion.args.get('saturation', 1.0)) +reverse = bool(hyperion.args.get('reverse', False)) +color = list(hyperion.args.get('color', (255,255,255))) +randomColor = bool(hyperion.args.get('random-color', False)) # Check parameters rotationTime = max(0.1, rotationTime) -brightness = max(0.0, min(brightness, 1.0)) -saturation = max(0.0, min(saturation, 1.0)) +brightness = max(0.0, min(brightness, 1.0)) +saturation = max(0.0, min(saturation, 1.0)) # Initialize the led data ledData = bytearray() for i in range(hyperion.ledCount): ledData += bytearray((0, 0, 0)) -sleepTime = 0.05 - # Start the write data loop while not hyperion.abort(): ledData[:] = bytearray(3*hyperion.ledCount) for i in range(hyperion.ledCount): if random.random() < 0.005: - ledData[i*3] = 255 - ledData[i*3+1] = 255 - ledData[i*3+2] = 255 + + if randomColor: + rgb = colorsys.hsv_to_rgb(random.random(), 1, 1) + for n in range(3): + color[n] = int(rgb[n]*255) + + for n in range(3): + ledData[i*3+n] = color[n] + hyperion.setColor(ledData) time.sleep(sleepTime) From b9a9c3126fef91dddbab839322a93d382dc77be0 Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Thu, 21 Jan 2016 16:39:52 +0100 Subject: [PATCH 43/96] Update X11Grabber.h Former-commit-id: 895bc985c0e732ec5d8e064068cb6f3e0920d09a --- include/grabber/X11Grabber.h | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/include/grabber/X11Grabber.h b/include/grabber/X11Grabber.h index 61c2d103..b35031cf 100644 --- a/include/grabber/X11Grabber.h +++ b/include/grabber/X11Grabber.h @@ -7,6 +7,11 @@ // X11 includes #include +#include +#include +#include +#include + class X11Grabber { public: @@ -16,6 +21,8 @@ public: virtual ~X11Grabber(); int open(); + + bool Setup(); Image & grab(); @@ -27,18 +34,23 @@ private: int _cropTop; int _cropBottom; - Screen *Xscreen; - XImage *xImage; - XShmSegmentInfo shminfo; - int screen; + XImage* _xImage; + XShmSegmentInfo _shminfo; /// Reference to the X11 display (nullptr if not opened) - Display * _x11Display; + Display* _x11Display; + Window _window; + XWindowAttributes _windowAttr; unsigned _screenWidth; unsigned _screenHeight; + unsigned _croppedWidth; + unsigned _croppedHeight; Image _image; - + + void freeResources(); + void setupResources(); + int updateScreenDimensions(); }; From a53f65f3a0c6548f491618e91e0b55ead130c1c2 Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Thu, 21 Jan 2016 16:40:46 +0100 Subject: [PATCH 44/96] Update X11Grabber.cpp Former-commit-id: 08b227fba33ca0f6974f10b085cf57c18e716428 --- libsrc/grabber/x11/X11Grabber.cpp | 110 +++++++++++++++++------------- 1 file changed, 63 insertions(+), 47 deletions(-) diff --git a/libsrc/grabber/x11/X11Grabber.cpp b/libsrc/grabber/x11/X11Grabber.cpp index 494af111..c817fadc 100644 --- a/libsrc/grabber/x11/X11Grabber.cpp +++ b/libsrc/grabber/x11/X11Grabber.cpp @@ -17,98 +17,114 @@ X11Grabber::X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom, _x11Display(nullptr), _screenWidth(0), _screenHeight(0), + _croppedWidth(0), + _croppedHeight(0), _image(0,0) { _imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation); _imageResampler.setVerticalPixelDecimation(verticalPixelDecimation); - _imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XGetImage + _imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XShmGetImage } X11Grabber::~X11Grabber() { if (_x11Display != nullptr) { + freeResources(); XCloseDisplay(_x11Display); } } -int X11Grabber::open() +void X11Grabber::freeResources() { - const char * display_name = nullptr; - _x11Display = XOpenDisplay(display_name); + // Cleanup allocated resources of the X11 grab + XShmDetach(_x11Display, &_shminfo); + XDestroyImage(_xImage); + shmdt(_shminfo.shmaddr); + shmctl(_shminfo.shmid, IPC_RMID, 0); +} +void X11Grabber::setupResources() +{ + _xImage = XShmCreateImage(_x11Display, _windowAttr.visual, + _windowAttr.depth, ZPixmap, NULL, &_shminfo, + _croppedWidth, _croppedHeight); + + _shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777); + _shminfo.shmaddr = _xImage->data = (char*)shmat(_shminfo.shmid,0,0); + _shminfo.readOnly = False; + + XShmAttach(_x11Display, &_shminfo); +} + +bool X11Grabber::Setup() +{ + _x11Display = XOpenDisplay(NULL); if (_x11Display == nullptr) { - std::cerr << "Failed to open the default X11-display" << std::endl; - return -1; - } + std::cerr << "Unable to open display"; + if (getenv("DISPLAY")) + std::cerr << " " << std::string(getenv("DISPLAY")) << std::endl; + else + std::cerr << ". DISPLAY environment variable not set" << std::endl; + return false; + } + + _window = DefaultRootWindow(_x11Display); - return 0; -} + return true; + } Image & X11Grabber::grab() { - if (_x11Display == nullptr) - { - open(); - } - - updateScreenDimensions(); - - Xscreen = DefaultScreenOfDisplay(_x11Display); - - const unsigned croppedWidth = _screenWidth - _cropLeft - _cropRight; - const unsigned croppedHeight = _screenHeight - _cropTop - _cropBottom; - - xImage = XShmCreateImage(_x11Display, DefaultVisualOfScreen(Xscreen), - DefaultDepthOfScreen(Xscreen), - ZPixmap, NULL, &shminfo, - croppedWidth, croppedHeight); - - shminfo.shmid = shmget(IPC_PRIVATE, xImage->bytes_per_line * xImage->height, IPC_CREAT|0777); - shminfo.shmaddr = xImage->data = (char*)shmat(shminfo.shmid,0,0); - shminfo.readOnly = False; - - XShmAttach(_x11Display, &shminfo); - - // Capture the current screen - XShmGetImage(_x11Display, DefaultRootWindow(_x11Display), xImage, _cropLeft, _cropTop, 0x00FFFFFF); - if (xImage == nullptr) + XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, 0x00FFFFFF); + if (_xImage == nullptr) { std::cerr << "Grab failed" << std::endl; return _image; } - _imageResampler.processImage(reinterpret_cast(xImage->data), xImage->width, xImage->height, xImage->bytes_per_line, PIXELFORMAT_BGR32, _image); - - // Cleanup allocated resources of the X11 grab - XShmDetach(_x11Display, &shminfo); - XDestroyImage(xImage); - shmdt (shminfo.shmaddr); - shmctl(shminfo.shmid, IPC_RMID, 0); + _imageResampler.processImage(reinterpret_cast(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, _image); return _image; } int X11Grabber::updateScreenDimensions() { - XWindowAttributes window_attributes_return; - const Status status = XGetWindowAttributes(_x11Display, DefaultRootWindow(_x11Display), &window_attributes_return); + const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr); if (status == 0) { std::cerr << "Failed to obtain window attributes" << std::endl; return -1; } - if (_screenWidth == unsigned(window_attributes_return.width) && _screenHeight == unsigned(window_attributes_return.height)) + if (_screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height)) { // No update required return 0; } + std::cout << "Update of screen resolution: [" << _screenWidth << "x" << _screenHeight <<"] => "; - _screenWidth = window_attributes_return.width; - _screenHeight = window_attributes_return.height; + + if (_screenWidth || _screenHeight) + freeResources(); + + _screenWidth = _windowAttr.width; + _screenHeight = _windowAttr.height; + std::cout << "[" << _screenWidth << "x" << _screenHeight <<"]" << std::endl; + + if (_screenWidth > unsigned(_cropLeft + _cropRight)) + _croppedWidth = _screenWidth - _cropLeft - _cropRight; + else + _croppedWidth = _screenWidth; + + if (_screenHeight > unsigned(_cropTop + _cropBottom)) + _croppedHeight = _screenHeight - _cropTop - _cropBottom; + else + _croppedHeight = _screenHeight; + + setupResources(); return 0; } From 66609a03a0457f5271e2556ffca35f496e29efc2 Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Thu, 21 Jan 2016 16:41:37 +0100 Subject: [PATCH 45/96] Update X11Wrapper.cpp Former-commit-id: f644a24c77db18feb34526aa937f12700865f5be --- src/hyperion-x11/X11Wrapper.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/hyperion-x11/X11Wrapper.cpp b/src/hyperion-x11/X11Wrapper.cpp index 6f33cc61..a0489fdf 100644 --- a/src/hyperion-x11/X11Wrapper.cpp +++ b/src/hyperion-x11/X11Wrapper.cpp @@ -29,6 +29,11 @@ void X11Wrapper::stop() _timer.stop(); } +bool X11Wrapper::displayInit() +{ + return _grabber.Setup(); +} + void X11Wrapper::capture() { const Image & screenshot = _grabber.grab(); From 3e078b2e154c22ddc653f7a83031d89dcf186f9b Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Thu, 21 Jan 2016 16:42:02 +0100 Subject: [PATCH 46/96] Update X11Wrapper.h Former-commit-id: 231123e1dee2dacf6d5225a3833f51544ca6f99c --- src/hyperion-x11/X11Wrapper.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hyperion-x11/X11Wrapper.h b/src/hyperion-x11/X11Wrapper.h index 211dfe18..18fab407 100644 --- a/src/hyperion-x11/X11Wrapper.h +++ b/src/hyperion-x11/X11Wrapper.h @@ -19,6 +19,8 @@ public: void start(); void stop(); + + bool displayInit(); signals: void sig_screenshot(const Image & screenshot); From bfa4185b9adbe877d55430bba4b3afa3152383af Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Thu, 21 Jan 2016 16:42:30 +0100 Subject: [PATCH 47/96] Update hyperion-x11.cpp Former-commit-id: 6fa337290c285d32a2fcc1b180c80d2849334bb8 --- src/hyperion-x11/hyperion-x11.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hyperion-x11/hyperion-x11.cpp b/src/hyperion-x11/hyperion-x11.cpp index 449f3990..7815aa34 100644 --- a/src/hyperion-x11/hyperion-x11.cpp +++ b/src/hyperion-x11/hyperion-x11.cpp @@ -77,6 +77,9 @@ int main(int argc, char ** argv) argCropBottom.getValue(), argSizeDecimation.getValue(), // horizontal decimation argSizeDecimation.getValue()); // vertical decimation + + if (!x11Wrapper.displayInit()) + return -1; if (argScreenshot.isSet()) { From 93f2b8b65f908fc82fe0190e97ee687e01115bb7 Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Thu, 21 Jan 2016 16:51:20 +0100 Subject: [PATCH 48/96] Update X11Grabber.cpp Former-commit-id: ab34a0615e2233322bc2260f297130e30857ac24 --- libsrc/grabber/x11/X11Grabber.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libsrc/grabber/x11/X11Grabber.cpp b/libsrc/grabber/x11/X11Grabber.cpp index c817fadc..b051fe82 100644 --- a/libsrc/grabber/x11/X11Grabber.cpp +++ b/libsrc/grabber/x11/X11Grabber.cpp @@ -77,6 +77,8 @@ bool X11Grabber::Setup() Image & X11Grabber::grab() { + updateScreenDimensions(); + XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, 0x00FFFFFF); if (_xImage == nullptr) { From 8f0e1f11993777f94e3f73c5279c13fda4427a33 Mon Sep 17 00:00:00 2001 From: wisc Date: Thu, 21 Jan 2016 20:25:08 +0100 Subject: [PATCH 49/96] switch on consistent detection only and also check right side and bottom pixel Former-commit-id: 4da53a39918a3676c707215daa66d8ae263ed92a --- libsrc/blackborder/BlackBorderProcessor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/blackborder/BlackBorderProcessor.cpp b/libsrc/blackborder/BlackBorderProcessor.cpp index 93cbbcff..78e718fe 100644 --- a/libsrc/blackborder/BlackBorderProcessor.cpp +++ b/libsrc/blackborder/BlackBorderProcessor.cpp @@ -1,4 +1,4 @@ -#include +//#include // Blackborder includes #include @@ -39,7 +39,7 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) // makes it look like the border detectionn is not working - since the new 3 line detection algorithm is more precise this became a problem specialy in dark scenes // wisc - std::cout << "cur: " << _currentBorder.verticalSize << " " << _currentBorder.horizontalSize << " new: " << newDetectedBorder.verticalSize << " " << newDetectedBorder.horizontalSize << " c:i " << _consistentCnt << ":" << _inconsistentCnt << std::endl; +// std::cout << "cur: " << _currentBorder.verticalSize << " " << _currentBorder.horizontalSize << " new: " << newDetectedBorder.verticalSize << " " << newDetectedBorder.horizontalSize << " c:i " << _consistentCnt << ":" << _inconsistentCnt << std::endl; // set the consistency counter if (newDetectedBorder == _previousDetectedBorder) From bbfded147e216bc6fe147ef82aef5bc9a02fe10d Mon Sep 17 00:00:00 2001 From: frostworx Date: Fri, 22 Jan 2016 17:17:45 +0100 Subject: [PATCH 50/96] minor qt5 fix Former-commit-id: 65ab3bb14d6a7ab52e6ab1e8eaa85321dc5fa543 --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index 21d397a6..ee019e18 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -218,7 +218,7 @@ void LedDevicePhilipsHue::put(QString route, QString content) { QString url = QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route); // Perfrom request QNetworkRequest request(url); - QNetworkReply* reply = manager->put(request, content.toAscii()); + QNetworkReply* reply = manager->put(request, content.toLatin1()); // Connect finished signal to quit slot of the loop. QEventLoop loop; loop.connect(reply, SIGNAL(finished()), SLOT(quit())); From 2555c5071053c5f5112893d7bc11a525e234c0f3 Mon Sep 17 00:00:00 2001 From: redpanther Date: Sat, 23 Jan 2016 13:09:23 +0100 Subject: [PATCH 51/96] add shutdown effect: system shutdown is disabled by default. enable it in json (set false to true) the shutdown is abortable. simply select another effect before shutdown time reached this effect is made for linux and did not workl on windows without modifications Former-commit-id: 32f92246fbc87de576e4b1059dd319646917ec74 --- effects/shutdown.json | 11 ++++++++++ effects/shutdown.py | 51 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 effects/shutdown.json create mode 100644 effects/shutdown.py diff --git a/effects/shutdown.json b/effects/shutdown.json new file mode 100644 index 00000000..7e09a13b --- /dev/null +++ b/effects/shutdown.json @@ -0,0 +1,11 @@ +{ + "name" : "System Shutdown", + "script" : "shutdown.py", + "args" : + { + "speed" : 1.2, + "alarm-color" : [255,0,0], + "post-color" : [255,174,11], + "shutdown-enabled" : false + } +} diff --git a/effects/shutdown.py b/effects/shutdown.py new file mode 100644 index 00000000..469443d0 --- /dev/null +++ b/effects/shutdown.py @@ -0,0 +1,51 @@ +import hyperion, time, colorsys, random, subprocess + +def setPixel(x,y,rgb): + global imageData, width + offset = y*width*3 + x*3 + if offset+2 < len(imageData): + imageData[offset] = rgb[0] + imageData[offset+1] = rgb[1] + imageData[offset+2] = rgb[2] + +# Initialize the led data and args +sleepTime = float(hyperion.args.get('speed', 1.0))*0.5 +alarmColor = hyperion.args.get('alarm-color', (255,0,0)) +postColor = hyperion.args.get('post-color', (255,174,11)) +off = bool(hyperion.args.get('shutdown-enabled', False)) +width = 12 +height = 10 + +imageData = bytearray(height * width * (0,0,0)) +imageDataBlack = bytearray(height * width * (0,0,0)) +imageDataRed = bytearray(height * width * alarmColor) + +# Start the write data loop +for i in range(6): + if hyperion.abort(): + off = False + break + if i % 2: + hyperion.setImage(width, height, imageDataRed) + else: + hyperion.setImage(width, height, imageDataBlack) + time.sleep(sleepTime) + +for y in range(height,0,-1): + if hyperion.abort(): + off = False + break + for x in range(width): + setPixel(x, y-1, alarmColor) + hyperion.setImage(width, height, imageData) + time.sleep(sleepTime) +time.sleep(1) + +for y in range(height): + for x in range(width): + setPixel(x, y, postColor) +hyperion.setImage(width, height, imageData) +time.sleep(2) + +if off and not hyperion.abort(): + subprocess.call("halt") From e7c7e05f88e18ade798a7278c01fee57ef5b7311 Mon Sep 17 00:00:00 2001 From: redpanther Date: Sun, 24 Jan 2016 08:10:36 +0100 Subject: [PATCH 52/96] add fading effect like in a cinema. sped start and end color are selectable in json file rename loop effects to more meaningfull names Former-commit-id: bed033e19d7cb38b0d5f11313a9f927ac8121194 --- effects/cinema-fade-in.json | 10 ++++++++ effects/cinema-fade-off.json | 10 ++++++++ effects/fade.py | 34 +++++++++++++++++++++++++++ effects/loop.json | 7 ------ effects/loop2.json | 7 ------ effects/loop2.py | 33 -------------------------- effects/running_dots.json | 10 ++++++++ effects/running_dots.py | 43 ++++++++++++++++++++++++++++++++++ effects/traces.json | 8 +++++++ effects/{loop.py => traces.py} | 8 +++---- 10 files changed, 119 insertions(+), 51 deletions(-) create mode 100644 effects/cinema-fade-in.json create mode 100644 effects/cinema-fade-off.json create mode 100644 effects/fade.py delete mode 100644 effects/loop.json delete mode 100644 effects/loop2.json delete mode 100644 effects/loop2.py create mode 100644 effects/running_dots.json create mode 100644 effects/running_dots.py create mode 100644 effects/traces.json rename effects/{loop.py => traces.py} (76%) diff --git a/effects/cinema-fade-in.json b/effects/cinema-fade-in.json new file mode 100644 index 00000000..2730c568 --- /dev/null +++ b/effects/cinema-fade-in.json @@ -0,0 +1,10 @@ +{ + "name" : "Cinema brighten lights", + "script" : "fade.py", + "args" : + { + "fade-time" : 5.0, + "color-start" : [ 136, 97, 7 ], + "color-end" : [ 238, 173, 47 ] + } +} diff --git a/effects/cinema-fade-off.json b/effects/cinema-fade-off.json new file mode 100644 index 00000000..7d7c20f8 --- /dev/null +++ b/effects/cinema-fade-off.json @@ -0,0 +1,10 @@ +{ + "name" : "Cinema dim lights", + "script" : "fade.py", + "args" : + { + "fade-time" : 5.0, + "color-start" : [ 238, 173, 47 ], + "color-end" : [ 136, 97, 7 ] + } +} diff --git a/effects/fade.py b/effects/fade.py new file mode 100644 index 00000000..950605d1 --- /dev/null +++ b/effects/fade.py @@ -0,0 +1,34 @@ +import hyperion, time + +def setColor(rgb): + hyperion.setColor( bytearray( hyperion.ledCount * rgb)) + +# Get the parameters +fadeTime = float(hyperion.args.get('fade-time', 5.0)) +colorStart = hyperion.args.get('color-start', (255,174,11)) +colorEnd = hyperion.args.get('color-end', (100,100,100)) + +color_step = ( + (colorEnd[0] - colorStart[0]) / 256.0, + (colorEnd[1] - colorStart[1]) / 256.0, + (colorEnd[2] - colorStart[2]) / 256.0 +) + +# fade color +for step in range(256): + if hyperion.abort(): + break + + setColor( ( + int( min(max(0, colorStart[0] + color_step[0]*step), 255) ), + int( min(max(0, colorStart[1] + color_step[1]*step), 255) ), + int( min(max(0, colorStart[2] + color_step[2]*step), 255) ) + ) ) + + time.sleep( fadeTime / 256 ) + +# maintain color until effect end +setColor(colorEnd) +while not hyperion.abort(): + time.sleep(1) + diff --git a/effects/loop.json b/effects/loop.json deleted file mode 100644 index c4e58803..00000000 --- a/effects/loop.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name" : "Loop", - "script" : "loop.py", - "args" : - { - } -} diff --git a/effects/loop2.json b/effects/loop2.json deleted file mode 100644 index ebedbe34..00000000 --- a/effects/loop2.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name" : "Loop2", - "script" : "loop2.py", - "args" : - { - } -} diff --git a/effects/loop2.py b/effects/loop2.py deleted file mode 100644 index 3498ac4e..00000000 --- a/effects/loop2.py +++ /dev/null @@ -1,33 +0,0 @@ -import hyperion -import time -import colorsys -import random - -# Initialize the led data -ledData = bytearray() -for i in range(hyperion.ledCount): - ledData += bytearray((0,0,0)) - -sleepTime = 0.005 - -runners = [ -{ "pos":0, "step":4 , "lvl":255}, -{ "pos":1, "step":5 , "lvl":255}, -{ "pos":2, "step":6 , "lvl":255}, -{ "pos":0, "step":7 , "lvl":255}, -{ "pos":1, "step":8 , "lvl":255}, -{ "pos":2, "step":9, "lvl":255}, -] - -# Start the write data loop -count = 0 -while not hyperion.abort(): - count += 1 - for r in runners: - if count%r["step"] == 0: - ledData[r["pos"]] = 0 - r["pos"] = (r["pos"]+3)%(hyperion.ledCount*3) - ledData[r["pos"]] = r["lvl"] - - hyperion.setColor(ledData) - time.sleep(sleepTime) diff --git a/effects/running_dots.json b/effects/running_dots.json new file mode 100644 index 00000000..8accd451 --- /dev/null +++ b/effects/running_dots.json @@ -0,0 +1,10 @@ +{ + "name" : "Running dots", + "script" : "running_dots.py", + "args" : + { + "speed" : 1.5, + "whiteLevel" : 100, + "colorLevel" : 230 + } +} diff --git a/effects/running_dots.py b/effects/running_dots.py new file mode 100644 index 00000000..16d8d039 --- /dev/null +++ b/effects/running_dots.py @@ -0,0 +1,43 @@ +import hyperion, time, colorsys, random + +# get options from args +sleepTime = float(hyperion.args.get('speed', 1.5)) * 0.005 +whiteLevel = int(hyperion.args.get('whiteLevel', 0)) +lvl = int(hyperion.args.get('colorLevel', 220)) + +# check value +whiteLevel = min( whiteLevel, 254 ) +lvl = min( lvl, 255 ) + +if whiteLevel >= lvl: + lvl = 255 + +# Initialize the led data +ledData = bytearray() +for i in range(hyperion.ledCount): + ledData += bytearray((0,0,0)) + +runners = [ + { "pos":0, "step": 4, "lvl":lvl}, + { "pos":1, "step": 5, "lvl":lvl}, + { "pos":2, "step": 6, "lvl":lvl}, + { "pos":0, "step": 7, "lvl":lvl}, + { "pos":1, "step": 8, "lvl":lvl}, + { "pos":2, "step": 9, "lvl":lvl}, + #{ "pos":0, "step":10, "lvl":lvl}, + #{ "pos":1, "step":11, "lvl":lvl}, + #{ "pos":2, "step":12, "lvl":lvl}, +] + +# Start the write data loop +counter = 0 +while not hyperion.abort(): + counter += 1 + for r in runners: + if counter % r["step"] == 0: + ledData[r["pos"]] = whiteLevel + r["pos"] = (r["pos"]+3) % (hyperion.ledCount*3) + ledData[r["pos"]] = r["lvl"] + + hyperion.setColor(ledData) + time.sleep(sleepTime) diff --git a/effects/traces.json b/effects/traces.json new file mode 100644 index 00000000..a2bfdabb --- /dev/null +++ b/effects/traces.json @@ -0,0 +1,8 @@ +{ + "name" : "Color traces", + "script" : "traces.py", + "args" : + { + "speed" : 1.0 + } +} diff --git a/effects/loop.py b/effects/traces.py similarity index 76% rename from effects/loop.py rename to effects/traces.py index 93011e97..7f6a8dfe 100644 --- a/effects/loop.py +++ b/effects/traces.py @@ -8,15 +8,15 @@ ledData = bytearray() for i in range(hyperion.ledCount): ledData += bytearray((0,0,0)) -sleepTime = 0.002 +sleepTime = float(hyperion.args.get('speed', 1.0)) * 0.004 runners = [ { "i":0, "pos":0, "c":0, "step":9 , "lvl":255}, { "i":1, "pos":0, "c":0, "step":8 , "lvl":255}, { "i":2, "pos":0, "c":0, "step":7 , "lvl":255}, -{ "i":0, "pos":0, "c":0, "step":6 , "lvl":0}, -{ "i":1, "pos":0, "c":0, "step":5 , "lvl":0}, -{ "i":2, "pos":0, "c":0, "step":4, "lvl":0}, +{ "i":0, "pos":0, "c":0, "step":6 , "lvl":100}, +{ "i":1, "pos":0, "c":0, "step":5 , "lvl":100}, +{ "i":2, "pos":0, "c":0, "step":4, "lvl":100}, ] # Start the write data loop From a257f185c93ff304e6ed1b358ed3266bf211c971 Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 26 Jan 2016 15:08:21 +0100 Subject: [PATCH 53/96] increase fadecandy maximum amount of leds remove debug code Former-commit-id: d74025128978e4e26d49fb57215f660bd824895b --- libsrc/leddevice/LedDeviceFadeCandy.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libsrc/leddevice/LedDeviceFadeCandy.cpp b/libsrc/leddevice/LedDeviceFadeCandy.cpp index e8c178d1..a9548842 100755 --- a/libsrc/leddevice/LedDeviceFadeCandy.cpp +++ b/libsrc/leddevice/LedDeviceFadeCandy.cpp @@ -1,6 +1,6 @@ #include "LedDeviceFadeCandy.h" -static const unsigned MAX_NUM_LEDS = 512; +static const unsigned MAX_NUM_LEDS = 10000; static const unsigned OPC_BROADCAST = 0; // OPC broadcast channel static const unsigned OPC_SET_PIXELS = 0; // OPC command codes static const unsigned OPC_HEADER_SIZE = 4; // OPC header size @@ -32,11 +32,8 @@ bool LedDeviceFadeCandy::isConnected() bool LedDeviceFadeCandy::tryConnect() { if ( _client.state() == QAbstractSocket::UnconnectedState ) { - qDebug("connecting to %s %i",_host.c_str(),_port); - _client.connectToHost( _host.c_str(), _port); - if ( _client.waitForConnected(1000) ) - qDebug("connected"); + _client.waitForConnected(1000); } return isConnected(); From b6060d392efb289eec74ac93e6eeaec422920c29 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 27 Jan 2016 10:44:51 +0100 Subject: [PATCH 54/96] make opc channel available in via config. Former-commit-id: 6a065cd049e29d7184a3aa1454de0fe1855e9941 --- libsrc/leddevice/LedDeviceFactory.cpp | 7 ++++--- libsrc/leddevice/LedDeviceFadeCandy.cpp | 18 +++++++++--------- libsrc/leddevice/LedDeviceFadeCandy.h | 3 ++- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index b0fd064f..f692b03c 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -246,9 +246,10 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) } else if (type == "fadecandy") { - const std::string host = deviceConfig.get("output", "127.0.0.1").asString(); - const uint16_t port = deviceConfig.get("port", 7890).asInt(); - device = new LedDeviceFadeCandy(host,port); + const std::string host = deviceConfig.get("output", "127.0.0.1").asString(); + const uint16_t port = deviceConfig.get("port", 7890).asInt(); + const uint16_t channel = deviceConfig.get("channel", 0).asInt(); + device = new LedDeviceFadeCandy(host, port, channel); } else if (type == "tpm2") { diff --git a/libsrc/leddevice/LedDeviceFadeCandy.cpp b/libsrc/leddevice/LedDeviceFadeCandy.cpp index a9548842..685795a9 100755 --- a/libsrc/leddevice/LedDeviceFadeCandy.cpp +++ b/libsrc/leddevice/LedDeviceFadeCandy.cpp @@ -1,16 +1,15 @@ #include "LedDeviceFadeCandy.h" -static const unsigned MAX_NUM_LEDS = 10000; -static const unsigned OPC_BROADCAST = 0; // OPC broadcast channel -static const unsigned OPC_SET_PIXELS = 0; // OPC command codes -static const unsigned OPC_HEADER_SIZE = 4; // OPC header size +static const unsigned MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds +static const unsigned OPC_SET_PIXELS = 0; // OPC command codes +static const unsigned OPC_HEADER_SIZE = 4; // OPC header size -LedDeviceFadeCandy::LedDeviceFadeCandy(const std::string& host, const uint16_t port) : - _host(host), _port(port) +LedDeviceFadeCandy::LedDeviceFadeCandy(const std::string& host, const uint16_t port, const unsigned channel) : + _host(host), _port(port), _channel(channel) { _opc_data.resize( OPC_HEADER_SIZE ); - _opc_data[0] = OPC_BROADCAST; + _opc_data[0] = channel; _opc_data[1] = OPC_SET_PIXELS; _opc_data[2] = 0; _opc_data[3] = 0; @@ -33,7 +32,8 @@ bool LedDeviceFadeCandy::tryConnect() { if ( _client.state() == QAbstractSocket::UnconnectedState ) { _client.connectToHost( _host.c_str(), _port); - _client.waitForConnected(1000); + if ( _client.waitForConnected(1000) ) + qDebug("fadecandy/opc: connected to %s:%i on channel %i", _host.c_str(), _port, _channel); } return isConnected(); @@ -48,7 +48,7 @@ int LedDeviceFadeCandy::write( const std::vector & ledValues ) if (nrLedValues > MAX_NUM_LEDS) { - std::cerr << "Invalid attempt to write led values. Not more than " << MAX_NUM_LEDS << " leds are allowed." << std::endl; + std::cerr << "fadecandy/opc: Invalid attempt to write led values. Not more than " << MAX_NUM_LEDS << " leds are allowed." << std::endl; return -1; } diff --git a/libsrc/leddevice/LedDeviceFadeCandy.h b/libsrc/leddevice/LedDeviceFadeCandy.h index 0b894e88..ebcd85d9 100755 --- a/libsrc/leddevice/LedDeviceFadeCandy.h +++ b/libsrc/leddevice/LedDeviceFadeCandy.h @@ -23,7 +23,7 @@ public: /// @param host The ip address/host name of fadecandy/opc server /// @param port The port to use (fadecandy default is 7890) /// - LedDeviceFadeCandy(const std::string& host, const uint16_t port); + LedDeviceFadeCandy(const std::string& host, const uint16_t port, const unsigned channel); /// /// Destructor of the LedDevice; closes the tcp client @@ -46,6 +46,7 @@ private: QTcpSocket _client; const std::string _host; const uint16_t _port; + const unsigned _channel; QByteArray _opc_data; /// try to establish connection to opc server, if not connected yet From 8732ffacf4a03690c27c142317b394aeb602864b Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 28 Jan 2016 05:50:32 +0100 Subject: [PATCH 55/96] simplify code of effect fade.py Former-commit-id: 3c7c633e764d14c9e11c6e145289894954695c65 --- effects/fade.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/effects/fade.py b/effects/fade.py index 950605d1..eb233a38 100644 --- a/effects/fade.py +++ b/effects/fade.py @@ -1,8 +1,5 @@ import hyperion, time -def setColor(rgb): - hyperion.setColor( bytearray( hyperion.ledCount * rgb)) - # Get the parameters fadeTime = float(hyperion.args.get('fade-time', 5.0)) colorStart = hyperion.args.get('color-start', (255,174,11)) @@ -15,20 +12,16 @@ color_step = ( ) # fade color +calcChannel = lambda i: min(max(int(colorStart[i] + color_step[i]*step),0),255) for step in range(256): if hyperion.abort(): break - setColor( ( - int( min(max(0, colorStart[0] + color_step[0]*step), 255) ), - int( min(max(0, colorStart[1] + color_step[1]*step), 255) ), - int( min(max(0, colorStart[2] + color_step[2]*step), 255) ) - ) ) - + hyperion.setColor( calcChannel(0),calcChannel(1),calcChannel(2) ) time.sleep( fadeTime / 256 ) # maintain color until effect end -setColor(colorEnd) +hyperion.setColor(colorEnd[0],colorEnd[1],colorEnd[2]) while not hyperion.abort(): time.sleep(1) From e5b802c01d928aeda2eb19056723faa4feeeb0f9 Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 28 Jan 2016 06:12:28 +0100 Subject: [PATCH 56/96] simplify effects Former-commit-id: bbb8dc4c3852d0651eb2f4e9999e426db4a905d0 --- effects/shutdown.py | 8 +++----- effects/strobe.py | 12 +++--------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/effects/shutdown.py b/effects/shutdown.py index 469443d0..214af60e 100644 --- a/effects/shutdown.py +++ b/effects/shutdown.py @@ -1,4 +1,4 @@ -import hyperion, time, colorsys, random, subprocess +import hyperion, time, subprocess def setPixel(x,y,rgb): global imageData, width @@ -17,8 +17,6 @@ width = 12 height = 10 imageData = bytearray(height * width * (0,0,0)) -imageDataBlack = bytearray(height * width * (0,0,0)) -imageDataRed = bytearray(height * width * alarmColor) # Start the write data loop for i in range(6): @@ -26,9 +24,9 @@ for i in range(6): off = False break if i % 2: - hyperion.setImage(width, height, imageDataRed) + hyperion.setColor(alarmColor[0], alarmColor[1], alarmColor[2]) else: - hyperion.setImage(width, height, imageDataBlack) + hyperion.setColor(0, 0, 0) time.sleep(sleepTime) for y in range(height,0,-1): diff --git a/effects/strobe.py b/effects/strobe.py index 007e6133..39a3a558 100644 --- a/effects/strobe.py +++ b/effects/strobe.py @@ -1,6 +1,4 @@ -import hyperion -import time -import colorsys +import hyperion, time # Get the rotation time color = hyperion.args.get('color', (255,255,255)) @@ -12,13 +10,9 @@ frequency = min(100.0, frequency) # Compute the strobe interval sleepTime = 1.0 / frequency -# Initialize the led data -blackLedsData = bytearray(hyperion.ledCount * ( 0, 0, 0)) -whiteLedsData = bytearray(hyperion.ledCount * color) - # Start the write data loop while not hyperion.abort(): - hyperion.setColor(blackLedsData) + hyperion.setColor(0, 0, 0) time.sleep(sleepTime) - hyperion.setColor(whiteLedsData) + hyperion.setColor(color[0], color[1], color[2]) time.sleep(sleepTime) From 8a906b9d01c247895ceb60f2206b8136b7efa5b5 Mon Sep 17 00:00:00 2001 From: redpanther Date: Sun, 31 Jan 2016 04:34:13 +0100 Subject: [PATCH 57/96] make priority of boot effect adjustable. It is set to 0 to not alter to current behaciour. A value of 900 could be more feasable, because boot effect with prio 0 isn't overwritable by other effects Former-commit-id: 1852339e6ade62c86719cfbb47faa46eb8f8d4ed --- config/hyperion.config.json | 6 ++++-- config/hyperion_x86.config.json | 6 ++++-- src/hyperiond/hyperiond.cpp | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/config/hyperion.config.json b/config/hyperion.config.json index 44931ac4..b16b845e 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -364,6 +364,7 @@ /// The configuration of the effect engine, contains the following items: /// * paths : An array with absolute location(s) of directories with effects /// * bootsequence : The effect selected as 'boot sequence' + /// * duration_ms : duration of boot effect in ms. 0 means effect stays forever "effects" : { "paths" : @@ -374,8 +375,9 @@ "bootsequence" : { - "effect" : "Rainbow swirl fast", - "duration_ms" : 3000 + "effect" : "Rainbow swirl fast", + "duration_ms" : 3000, + "priority" : 0 }, /// The configuration for the frame-grabber, contains the following items: diff --git a/config/hyperion_x86.config.json b/config/hyperion_x86.config.json index 4abd64db..06e35136 100644 --- a/config/hyperion_x86.config.json +++ b/config/hyperion_x86.config.json @@ -359,6 +359,7 @@ /// The configuration of the effect engine, contains the following items: /// * paths : An array with absolute location(s) of directories with effects /// * bootsequence : The effect selected as 'boot sequence' + /// * duration_ms : duration of boot effect in ms. 0 means effect stays forever "effects" : { "paths" : @@ -369,8 +370,9 @@ "bootsequence" : { - "effect" : "Rainbow swirl fast", - "duration_ms" : 3000 + "effect" : "Rainbow swirl fast", + "duration_ms" : 3000, + "priority" : 0 }, /// The configuration for the frame-grabber, contains the following items: diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 7357d55f..b6289fe2 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -126,7 +126,7 @@ int main(int argc, char** argv) // Get the parameters for the bootsequence const std::string effectName = effectConfig["effect"].asString(); const unsigned duration_ms = effectConfig["duration_ms"].asUInt(); - const int priority = 0; + const int priority = effectConfig["priority"].asUInt(); hyperion.setColor(priority+1, ColorRgb::BLACK, duration_ms, false); From 4decb05348fa80c65c26f8f857f57f860d2964ac Mon Sep 17 00:00:00 2001 From: redpanther Date: Sun, 31 Jan 2016 22:38:30 +0100 Subject: [PATCH 58/96] adds ability to set static color on boot. Former-commit-id: 41ca5ba73fde698d73380fac3dcee5e33b310d76 --- config/hyperion.config.json | 4 ++++ config/hyperion_x86.config.json | 6 +++++- src/hyperiond/hyperiond.cpp | 20 +++++++++++++++++--- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/config/hyperion.config.json b/config/hyperion.config.json index b16b845e..34f485cf 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -364,7 +364,10 @@ /// The configuration of the effect engine, contains the following items: /// * paths : An array with absolute location(s) of directories with effects /// * bootsequence : The effect selected as 'boot sequence' + /// * effect : name of the effect you want to start. Set to empty if no effect wanted + /// * color : switch to static color after effect is done /// * duration_ms : duration of boot effect in ms. 0 means effect stays forever + /// * priority : priority of boot effect and static color "effects" : { "paths" : @@ -375,6 +378,7 @@ "bootsequence" : { + "color" : [0,0,0], "effect" : "Rainbow swirl fast", "duration_ms" : 3000, "priority" : 0 diff --git a/config/hyperion_x86.config.json b/config/hyperion_x86.config.json index 06e35136..4121c499 100644 --- a/config/hyperion_x86.config.json +++ b/config/hyperion_x86.config.json @@ -359,7 +359,10 @@ /// The configuration of the effect engine, contains the following items: /// * paths : An array with absolute location(s) of directories with effects /// * bootsequence : The effect selected as 'boot sequence' + /// * effect : name of the effect you want to start. Set to empty if no effect wanted + /// * color : switch to static color after effect is done /// * duration_ms : duration of boot effect in ms. 0 means effect stays forever + /// * priority : priority of boot effect and static color "effects" : { "paths" : @@ -370,9 +373,10 @@ "bootsequence" : { + "color" : [0,0,0], "effect" : "Rainbow swirl fast", "duration_ms" : 3000, - "priority" : 0 + "priority" : 900 }, /// The configuration for the frame-grabber, contains the following items: diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index b6289fe2..032d44db 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -127,19 +127,33 @@ int main(int argc, char** argv) const std::string effectName = effectConfig["effect"].asString(); const unsigned duration_ms = effectConfig["duration_ms"].asUInt(); const int priority = effectConfig["priority"].asUInt(); + const int bootcolor_priority = (priority > 990) ? priority+1 : 990; - hyperion.setColor(priority+1, ColorRgb::BLACK, duration_ms, false); + if ( ! effectConfig["color"].isNull() && effectConfig["color"].isArray() && effectConfig["color"].size() == 3 ) + { + ColorRgb boot_color = { + (uint8_t)effectConfig["color"][0].asUInt(), + (uint8_t)effectConfig["color"][1].asUInt(), + (uint8_t)effectConfig["color"][2].asUInt() + }; + + hyperion.setColor(bootcolor_priority, boot_color, 0, false); + } + else + { + hyperion.setColor(bootcolor_priority, ColorRgb::BLACK, duration_ms, false); + } if (effectConfig.isMember("args")) { const Json::Value effectConfigArgs = effectConfig["args"]; if (hyperion.setEffect(effectName, effectConfigArgs, priority, duration_ms) == 0) { - std::cout << "Boot sequence(" << effectName << ") with user-defined arguments created and started" << std::endl; + std::cout << "Boot sequence(" << effectName << ") with user-defined arguments created and started" << std::endl; } else { - std::cout << "Failed to start boot sequence: " << effectName << " with user-defined arguments" << std::endl; + std::cout << "Failed to start boot sequence: " << effectName << " with user-defined arguments" << std::endl; } } else From e8a441ca987b9049bf115c78a4c477a02f738451 Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 4 Feb 2016 13:17:40 +0100 Subject: [PATCH 59/96] add fadecandy/opc specs Former-commit-id: 287fa1501e569df439eed8aac6dd44077ecb0994 --- doc/datasheets/fadecandy_opc_protocol.md | 79 ++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 doc/datasheets/fadecandy_opc_protocol.md diff --git a/doc/datasheets/fadecandy_opc_protocol.md b/doc/datasheets/fadecandy_opc_protocol.md new file mode 100644 index 00000000..53cec6a5 --- /dev/null +++ b/doc/datasheets/fadecandy_opc_protocol.md @@ -0,0 +1,79 @@ +Fadecandy: Open Pixel Control Protocol +====================================== + +The Fadecandy Server (`fcserver`) operates as a bridge between LED controllers attached over USB, and visual effects that communicate via a TCP socket. + +The primary protocol supported by `fcserver` is [Open Pixel Control](http://openpixelcontrol.org), a super simple way to send RGB values over a socket. We support the standard Open Pixel Control commands, as well as some Fadecandy extensions. + +Socket +------ + +Open Pixel Control uses a TCP socket, by default on port 7890. For the best performance, remember to set TCP_NODELAY socket option. + +Command Format +-------------- + +All OPC commands follow the same general format. All multi-byte values in Open Pixel Control are in network byte order, high byte followed by low byte. + +Channel | Command | Length (N) | Data +---------- | --------- | ---------- | -------------------------- +1 byte | 1 byte | 2 bytes | N bytes of message data + +Set Pixel Colors +---------------- + +Video data arrives in a **Set Pixel Colors** command: + +Byte | **Set Pixel Colors** command +------ | -------------------------------- +0 | Channel Number +1 | Command (0x00) +2 - 3 | Data length +4 | Pixel #0, Red +5 | Pixel #0, Green +6 | Pixel #0, Blue +7 | Pixel #1, Red +8 | Pixel #1, Green +9 | Pixel #1, Blue +â€Ķ | â€Ķ + +As soon as a complete Set Pixel Colors command is received, a new frame of video will be broadcast simultaneously to all attached Fadecandy devices. + +Set Global Color Correction +--------------------------- + +The color correction data (from the 'color' configuration key) can also be changed at runtime, by sending a new blob of JSON text in a Fadecandy-specific command. Fadecandy's 16-bit System ID for Open Pixel Control's System Exclusive (0xFF) command is **0x0001**. + +Byte | **Set Global Color Correction** command +------ | ------------------------------------------ +0 | Channel Number (0x00, reserved) +1 | Command (0xFF, System Exclusive) +2 - 3 | Data length (JSON Length + 4) +4 - 5 | System ID (0x0001, Fadecandy) +6 - 7 | SysEx ID (0x0001, Set Global Color Correction) +8 - â€Ķ | JSON Text + +Set Firmware Configuration +-------------------------- + +The firmware supports some runtime configuration options. Any OPC client can send a new firmware configuration packet using this command. If the supplied data is shorter than the firmware's configuration buffer, only the provided bytes will be changed. + +Byte | **Set Firmware Configuration** command +------ | ------------------------------------------ +0 | Channel Number (0x00, reserved) +1 | Command (0xFF, System Exclusive) +2 - 3 | Data length (Configuration Length + 4) +4 - 5 | System ID (0x0001, Fadecandy) +6 - 7 | SysEx ID (0x0002, Set Firmware Configuration) +8 - â€Ķ | Configuration Data + +Current firmwares support the following configuration options: + +Byte Offset | Bits | Description +----------- | ------ | ------------ +0 | 7 â€Ķ 4 | (reserved) +0 | 3 | Manual LED control bit +0 | 2 | 0 = LED shows USB activity, 1 = LED under manual control +0 | 1 | Disable keyframe interpolation +0 | 0 | Disable dithering +1 â€Ķ 62 | 7 â€Ķ 0 | (reserved) From 2b703de669d838743250d422293756caea51c518 Mon Sep 17 00:00:00 2001 From: wisc Date: Sun, 7 Feb 2016 13:26:40 +0100 Subject: [PATCH 60/96] bugfix, config enhancement and 3 detection modes Former-commit-id: edfc3e7ccf7b7d727e73a8563acb521045026d5b --- config/hyperion.config.json | 15 ++- include/blackborder/BlackBorderDetector.h | 133 ++++++++++++++++++-- include/blackborder/BlackBorderProcessor.h | 24 +++- include/hyperion/ImageProcessor.h | 2 +- include/hyperion/ImageProcessorFactory.h | 9 +- libsrc/blackborder/BlackBorderDetector.cpp | 21 +++- libsrc/blackborder/BlackBorderProcessor.cpp | 32 +++-- libsrc/hyperion/Hyperion.cpp | 4 +- libsrc/hyperion/ImageProcessor.cpp | 7 +- libsrc/hyperion/ImageProcessorFactory.cpp | 18 +-- test/TestBlackBorderProcessor.cpp | 8 +- 11 files changed, 213 insertions(+), 60 deletions(-) diff --git a/config/hyperion.config.json b/config/hyperion.config.json index 44931ac4..9827ba44 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -355,10 +355,21 @@ /// The black border configuration, contains the following items: /// * enable : true if the detector should be activated /// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0) - "blackborderdetector" : + /// * unknownFrameCnt : Number of frames without any detection before the border is set to 0 (default 600) - optional + /// * borderFrameCnt : Number of frames before a consistent detected border gets set (default 50) - optional + /// * maxInconsistentCnt : Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency - optional + /// * blurRemoveCnt : Number of pixels that get removed from the detected border to cut away blur (default 1) - optional + /// * mode : Border detection mode (values "default","classic","osd") - optional + + "blackborderdetector" : { "enable" : true, - "threshold" : 0.01 + "threshold" : 0.01, + "unknownFrameCnt": 600, + "borderFrameCnt" : 50, + "maxInconsistentCnt" : 10, + "blurRemoveCnt": 1, + "mode" : "default" }, /// The configuration of the effect engine, contains the following items: diff --git a/include/blackborder/BlackBorderDetector.h b/include/blackborder/BlackBorderDetector.h index d3764ced..a3a1c32b 100644 --- a/include/blackborder/BlackBorderDetector.h +++ b/include/blackborder/BlackBorderDetector.h @@ -49,7 +49,7 @@ namespace hyperion /// Constructs a black-border detector /// @param[in] blackborderThreshold The threshold which the blackborder detector should use /// - BlackBorderDetector(uint8_t blackborderThreshold); + BlackBorderDetector(double threshold); /// /// Performs the actual black-border detection on the given image @@ -58,13 +58,17 @@ namespace hyperion /// /// @return The detected (or not detected) black border info /// + + uint8_t calculateThreshold(double blackborderThreshold); + + /// + /// default detection mode (3lines 4side detection) template BlackBorder process(const Image & image) { - // test center and 33%, 66% of width/heigth // 33 and 66 will check left and top - // center ill check right and bottom sids + // center will check right and bottom sids int width = image.width(); int height = image.height(); int width33percent = width / 3; @@ -79,9 +83,9 @@ namespace hyperion int firstNonBlackYPixelIndex = -1; // find first X pixel of the image - for (int x = 0; x < width; ++x) + for (int x = 0; x < width33percent; ++x) { - const Pixel_T & color1 = image( (width - x), yCenter); // right side center line check + const Pixel_T & color1 = image( (width - 1 - x), yCenter); // right side center line check const Pixel_T & color2 = image(x, height33percent); const Pixel_T & color3 = image(x, height66percent); if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3)) @@ -92,9 +96,9 @@ namespace hyperion } // find first Y pixel of the image - for (int y = 0; y < height; ++y) + for (int y = 0; y < height33percent; ++y) { - const Pixel_T & color1 = image(xCenter, (height - y)); // bottom center line check + const Pixel_T & color1 = image(xCenter, (height - 1 - y)); // bottom center line check const Pixel_T & color2 = image(width33percent, y ); const Pixel_T & color3 = image(width66percent, y); if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3)) @@ -112,6 +116,120 @@ namespace hyperion return detectedBorder; } + + /// + /// classic detection mode (topleft single line mode) + template + BlackBorder process_classic(const Image & image) + { + // only test the topleft third of the image + int width = image.width() /3; + int height = image.height() / 3; + int maxSize = std::max(width, height); + + int firstNonBlackXPixelIndex = -1; + int firstNonBlackYPixelIndex = -1; + + // find some pixel of the image + for (int i = 0; i < maxSize; ++i) + { + int x = std::min(i, width); + int y = std::min(i, height); + + const Pixel_T & color = image(x, y); + if (!isBlack(color)) + { + firstNonBlackXPixelIndex = x; + firstNonBlackYPixelIndex = y; + break; + } + } + + // expand image to the left + for(; firstNonBlackXPixelIndex > 0; --firstNonBlackXPixelIndex) + { + const Pixel_T & color = image(firstNonBlackXPixelIndex-1, firstNonBlackYPixelIndex); + if (isBlack(color)) + { + break; + } + } + + // expand image to the top + for(; firstNonBlackYPixelIndex > 0; --firstNonBlackYPixelIndex) + { + const Pixel_T & color = image(firstNonBlackXPixelIndex, firstNonBlackYPixelIndex-1); + if (isBlack(color)) + { + break; + } + } + + // Construct result + BlackBorder detectedBorder; + detectedBorder.unknown = firstNonBlackXPixelIndex == -1 || firstNonBlackYPixelIndex == -1; + detectedBorder.horizontalSize = firstNonBlackYPixelIndex; + detectedBorder.verticalSize = firstNonBlackXPixelIndex; + return detectedBorder; + } + + +// osd detection mode (find x then y at detected x to avoid changes by osd overlays) + template + BlackBorder process_osd(const Image & image) + { + // find X position at height33 and height66 we check from the left side, Ycenter will check from right side + // then we try to find a pixel at this X position from top and bottom and right side from top + int width = image.width(); + int height = image.height(); + int width33percent = width / 3; + int height33percent = height / 3; +// int width66percent = width33percent * 2; + int height66percent = height33percent * 2; +// int xCenter = width / 2; + int yCenter = height / 2; + + + int firstNonBlackXPixelIndex = -1; + int firstNonBlackYPixelIndex = -1; + + // find first X pixel of the image + int x; + for (x = 0; x < width33percent; ++x) + { + const Pixel_T & color1 = image( (width - 1 - x), yCenter); // right side center line check + const Pixel_T & color2 = image(x, height33percent); + const Pixel_T & color3 = image(x, height66percent); + if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3)) + { + firstNonBlackXPixelIndex = x; + break; + } + } + + // find first Y pixel of the image + for (int y = 0; y < height33percent; ++y) + { + const Pixel_T & color1 = image(x, (height - 1 - y)); // left side bottom check + const Pixel_T & color2 = image(x, y );// left side top check + const Pixel_T & color3 = image( (width - 1 - x), y); // right side top check + if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3)) + { + firstNonBlackYPixelIndex = y; + break; + } + } + + // Construct result + BlackBorder detectedBorder; + detectedBorder.unknown = firstNonBlackXPixelIndex == -1 || firstNonBlackYPixelIndex == -1; + detectedBorder.horizontalSize = firstNonBlackYPixelIndex; + detectedBorder.verticalSize = firstNonBlackXPixelIndex; + return detectedBorder; + } + + + private: /// @@ -131,5 +249,6 @@ namespace hyperion private: /// Threshold for the blackborder detector [0 .. 255] const uint8_t _blackborderThreshold; + }; } // end namespace hyperion diff --git a/include/blackborder/BlackBorderProcessor.h b/include/blackborder/BlackBorderProcessor.h index 14be0585..443b1789 100644 --- a/include/blackborder/BlackBorderProcessor.h +++ b/include/blackborder/BlackBorderProcessor.h @@ -1,6 +1,8 @@ #pragma once +// Jsoncpp includes +#include // Local Hyperion includes #include "BlackBorderDetector.h" @@ -23,11 +25,7 @@ namespace hyperion /// outer pixels is blurred (black and color combined due to image scaling)) /// @param[in] blackborderThreshold The threshold which the blackborder detector should use /// - BlackBorderProcessor( - const unsigned unknownFrameCnt, - const unsigned borderFrameCnt, - const unsigned blurRemoveCnt, - uint8_t blackborderThreshold); + BlackBorderProcessor(const Json::Value &blackborderConfig); /// /// Return the current (detected) border @@ -48,7 +46,14 @@ namespace hyperion bool process(const Image & image) { // get the border for the single image - BlackBorder imageBorder = _detector.process(image); + BlackBorder imageBorder; + if (_detectionMode == "default") { + imageBorder = _detector.process(image); + } else if (_detectionMode == "classic") { + imageBorder = _detector.process_classic(image); + } else if (_detectionMode == "osd") { + imageBorder = _detector.process_osd(image); + } // add blur to the border if (imageBorder.horizontalSize > 0) { @@ -80,9 +85,15 @@ namespace hyperion /// The number of horizontal/vertical borders detected before it becomes the current border const unsigned _borderSwitchCnt; + // The number of frames that are "ignored" before a new border gets set as _previousDetectedBorder + const unsigned _maxInconsistentCnt; + /// The number of pixels to increase a detected border for removing blury pixels unsigned _blurRemoveCnt; + /// The border detection mode + const std::string _detectionMode; + /// The blackborder detector BlackBorderDetector _detector; @@ -96,5 +107,6 @@ namespace hyperion unsigned _consistentCnt; /// The number of frame the previous detected border NOT matched the incomming border unsigned _inconsistentCnt; + }; } // end namespace hyperion diff --git a/include/hyperion/ImageProcessor.h b/include/hyperion/ImageProcessor.h index 5049ac03..338c18e7 100644 --- a/include/hyperion/ImageProcessor.h +++ b/include/hyperion/ImageProcessor.h @@ -106,7 +106,7 @@ private: /// @param[in] enableBlackBorderDetector Flag indicating if the blacborder detector should be enabled /// @param[in] blackborderThreshold The threshold which the blackborder detector should use /// - ImageProcessor(const LedString &ledString, bool enableBlackBorderDetector, uint8_t blackborderThreshold); + ImageProcessor(const LedString &ledString, const Json::Value &blackborderConfig); /// /// Performs black-border detection (if enabled) on the given image diff --git a/include/hyperion/ImageProcessorFactory.h b/include/hyperion/ImageProcessorFactory.h index cde64440..e988e283 100644 --- a/include/hyperion/ImageProcessorFactory.h +++ b/include/hyperion/ImageProcessorFactory.h @@ -33,7 +33,7 @@ public: /// @param[in] enableBlackBorderDetector Flag indicating if the blacborder detector should be enabled /// @param[in] blackborderThreshold The threshold which the blackborder detector should use /// - void init(const LedString& ledString, bool enableBlackBorderDetector, double blackborderThreshold); + void init(const LedString& ledString, const Json::Value &blackborderConfig); /// /// Creates a new ImageProcessor. The onwership of the processor is transferred to the caller. @@ -46,9 +46,6 @@ private: /// The Led-string specification LedString _ledString; - /// Flag indicating if the black border detector should be used - bool _enableBlackBorderDetector; - - /// Threshold for the blackborder detector [0 .. 255] - uint8_t _blackborderThreshold; + // Reference to the blackborder json configuration values + Json::Value _blackborderConfig; }; diff --git a/libsrc/blackborder/BlackBorderDetector.cpp b/libsrc/blackborder/BlackBorderDetector.cpp index 6164f920..60a57c30 100644 --- a/libsrc/blackborder/BlackBorderDetector.cpp +++ b/libsrc/blackborder/BlackBorderDetector.cpp @@ -1,11 +1,26 @@ - +#include // BlackBorders includes #include using namespace hyperion; -BlackBorderDetector::BlackBorderDetector(uint8_t blackborderThreshold) : - _blackborderThreshold(blackborderThreshold) +BlackBorderDetector::BlackBorderDetector(double threshold) : + _blackborderThreshold(calculateThreshold(threshold)) { // empty } + +uint8_t BlackBorderDetector::calculateThreshold(double threshold) +{ + int rgbThreshold = int(std::ceil(threshold * 255)); + if (rgbThreshold < 0) + rgbThreshold = 0; + else if (rgbThreshold > 255) + rgbThreshold = 255; + + uint8_t blackborderThreshold = uint8_t(rgbThreshold); + + std::cout << "Black border threshold set to " << threshold << " (" << int(blackborderThreshold) << ")" << std::endl; + + return blackborderThreshold; +} diff --git a/libsrc/blackborder/BlackBorderProcessor.cpp b/libsrc/blackborder/BlackBorderProcessor.cpp index 78e718fe..d6678d51 100644 --- a/libsrc/blackborder/BlackBorderProcessor.cpp +++ b/libsrc/blackborder/BlackBorderProcessor.cpp @@ -1,23 +1,31 @@ -//#include - +//* +#include +/* +#include +using std::cout; +using std::endl; +using std::setw; +using std::left; +//*/ // Blackborder includes #include + using namespace hyperion; -BlackBorderProcessor::BlackBorderProcessor(const unsigned unknownFrameCnt, - const unsigned borderFrameCnt, - const unsigned blurRemoveCnt, - uint8_t blackborderThreshold) : - _unknownSwitchCnt(unknownFrameCnt), - _borderSwitchCnt(borderFrameCnt), - _blurRemoveCnt(blurRemoveCnt), - _detector(blackborderThreshold), +BlackBorderProcessor::BlackBorderProcessor(const Json::Value &blackborderConfig) : + _unknownSwitchCnt(blackborderConfig.get("unknownFrameCnt", 600).asUInt()), + _borderSwitchCnt(blackborderConfig.get("borderFrameCnt", 50).asUInt()), + _maxInconsistentCnt(blackborderConfig.get("maxInconsistentCnt", 10).asUInt()), + _blurRemoveCnt(blackborderConfig.get("blurRemoveCnt", 1).asUInt()), + _detectionMode(blackborderConfig.get("mode", "default").asString()), + _detector(blackborderConfig.get("threshold", 0.01).asDouble()), _currentBorder({true, -1, -1}), _previousDetectedBorder({true, -1, -1}), _consistentCnt(0), _inconsistentCnt(10) { + std::cout << "DETECTION MODE:" << _detectionMode << std::endl; // empty } @@ -39,7 +47,7 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) // makes it look like the border detectionn is not working - since the new 3 line detection algorithm is more precise this became a problem specialy in dark scenes // wisc -// std::cout << "cur: " << _currentBorder.verticalSize << " " << _currentBorder.horizontalSize << " new: " << newDetectedBorder.verticalSize << " " << newDetectedBorder.horizontalSize << " c:i " << _consistentCnt << ":" << _inconsistentCnt << std::endl; +// std::cout << "c: " << setw(2) << _currentBorder.verticalSize << " " << setw(2) << _currentBorder.horizontalSize << " p: " << setw(2) << _previousDetectedBorder.verticalSize << " " << setw(2) << _previousDetectedBorder.horizontalSize << " n: " << setw(2) << newDetectedBorder.verticalSize << " " << setw(2) << newDetectedBorder.horizontalSize << " c:i " << setw(2) << _consistentCnt << ":" << setw(2) << _inconsistentCnt << std::endl; // set the consistency counter if (newDetectedBorder == _previousDetectedBorder) @@ -50,7 +58,7 @@ bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder) else { ++_inconsistentCnt; - if (_inconsistentCnt <= 10)// few inconsistent frames + if (_inconsistentCnt <= _maxInconsistentCnt)// only few inconsistent frames { //discard the newDetectedBorder -> keep the consistent count for previousDetectedBorder return false; diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index d6657046..37c77927 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -282,8 +282,8 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) : // initialize the image processor factory ImageProcessorFactory::getInstance().init( _ledString, - jsonConfig["blackborderdetector"].get("enable", true).asBool(), - jsonConfig["blackborderdetector"].get("threshold", 0.01).asDouble()); + jsonConfig["blackborderdetector"] + ); // initialize the color smoothing filter _device = createColorSmoothing(jsonConfig["color"]["smoothing"], _device); diff --git a/libsrc/hyperion/ImageProcessor.cpp b/libsrc/hyperion/ImageProcessor.cpp index 25784d0a..f83dcc27 100644 --- a/libsrc/hyperion/ImageProcessor.cpp +++ b/libsrc/hyperion/ImageProcessor.cpp @@ -8,10 +8,11 @@ using namespace hyperion; -ImageProcessor::ImageProcessor(const LedString& ledString, bool enableBlackBorderDetector, uint8_t blackborderThreshold) : +//ImageProcessor::ImageProcessor(const LedString& ledString, bool enableBlackBorderDetector, uint8_t blackborderThreshold) : +ImageProcessor::ImageProcessor(const LedString& ledString, const Json::Value & blackborderConfig) : _ledString(ledString), - _enableBlackBorderRemoval(enableBlackBorderDetector), - _borderProcessor(new BlackBorderProcessor(600, 50, 1, blackborderThreshold)), + _enableBlackBorderRemoval(blackborderConfig.get("enable", true).asBool()), + _borderProcessor(new BlackBorderProcessor(blackborderConfig) ), _imageToLeds(nullptr) { // empty diff --git a/libsrc/hyperion/ImageProcessorFactory.cpp b/libsrc/hyperion/ImageProcessorFactory.cpp index a47e532f..c85b35cd 100644 --- a/libsrc/hyperion/ImageProcessorFactory.cpp +++ b/libsrc/hyperion/ImageProcessorFactory.cpp @@ -13,25 +13,13 @@ ImageProcessorFactory& ImageProcessorFactory::getInstance() return instance; } -void ImageProcessorFactory::init(const LedString& ledString, bool enableBlackBorderDetector, double blackborderThreshold) +void ImageProcessorFactory::init(const LedString& ledString, const Json::Value & blackborderConfig) { _ledString = ledString; - _enableBlackBorderDetector = enableBlackBorderDetector; - - int threshold = int(std::ceil(blackborderThreshold * 255)); - if (threshold < 0) - threshold = 0; - else if (threshold > 255) - threshold = 255; - _blackborderThreshold = uint8_t(threshold); - - if (_enableBlackBorderDetector) - { - std::cout << "Black border threshold set to " << blackborderThreshold << " (" << int(_blackborderThreshold) << ")" << std::endl; - } + _blackborderConfig = blackborderConfig; } ImageProcessor* ImageProcessorFactory::newImageProcessor() const { - return new ImageProcessor(_ledString, _enableBlackBorderDetector, _blackborderThreshold); + return new ImageProcessor(_ledString, _blackborderConfig); } diff --git a/test/TestBlackBorderProcessor.cpp b/test/TestBlackBorderProcessor.cpp index e05c630f..88879398 100644 --- a/test/TestBlackBorderProcessor.cpp +++ b/test/TestBlackBorderProcessor.cpp @@ -44,11 +44,13 @@ Image createImage(unsigned width, unsigned height, unsigned topBorder, int main() { - unsigned unknownCnt = 600; +// unsigned unknownCnt = 600; unsigned borderCnt = 50; - unsigned blurCnt = 0; +// unsigned blurCnt = 0; + Json::Value config; - BlackBorderProcessor processor(unknownCnt, borderCnt, blurCnt, 3); +// BlackBorderProcessor processor(unknownCnt, borderCnt, blurCnt, 3, config); + BlackBorderProcessor processor(config); // Start with 'no border' detection Image noBorderImage = createImage(64, 64, 0, 0); From 79dda5e8402219c9e78c9711bb59e1a29b428944 Mon Sep 17 00:00:00 2001 From: wisc Date: Sun, 7 Feb 2016 17:40:24 +0100 Subject: [PATCH 61/96] Update LedDeviceAPA102.cpp by pcaffardi Former-commit-id: e7efe8917fc10ceb860e44bbb37442cffa3512db --- libsrc/leddevice/LedDeviceAPA102.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/libsrc/leddevice/LedDeviceAPA102.cpp b/libsrc/leddevice/LedDeviceAPA102.cpp index fb016229..17bec4fc 100644 --- a/libsrc/leddevice/LedDeviceAPA102.cpp +++ b/libsrc/leddevice/LedDeviceAPA102.cpp @@ -2,7 +2,6 @@ #include #include #include -#include // Linux includes #include @@ -32,15 +31,15 @@ LedDeviceAPA102::LedDeviceAPA102(const std::string& outputDevice, const unsigned int LedDeviceAPA102::write(const std::vector &ledValues) { const unsigned int startFrameSize = APA102_START_FRAME_BYTES; - const unsigned int ledsCount = ledValues.size() ; - const unsigned int ledsSize = ledsCount * APA102_LED_BYTES ; - const unsigned int endFrameBits = APA102_END_FRAME_BITS(ledsCount) ; - const unsigned int endFrameSize = APA102_END_FRAME_BYTES(ledsCount) ; - const unsigned int transferSize = startFrameSize + ledsSize + endFrameSize ; + const unsigned int ledsCount = ledValues.size() ; + const unsigned int ledsSize = ledsCount * APA102_LED_BYTES ; + const unsigned int endFrameBits = APA102_END_FRAME_BITS(ledsCount) ; + const unsigned int endFrameSize = APA102_END_FRAME_BYTES(ledsCount) ; + const unsigned int transferSize = startFrameSize + ledsSize + endFrameSize ; if(_ledBuffer.size() != transferSize){ _ledBuffer.resize(transferSize, 0x00); - } + } unsigned idx = 0, i; for (i=0; i &ledValues) _ledBuffer[idx++] = rgb.blue; } for(i=0; i &ledValues) int LedDeviceAPA102::switchOff() { return write(std::vector(_ledBuffer.size(), ColorRgb{0,0,0})); -} +} From 5dc59344c4553dd6e34b401b7b7afa986ee6a26b Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 8 Feb 2016 16:56:23 +0100 Subject: [PATCH 62/96] forward protobuf messages. configure (send proto messages to two other hyperiond): "protoServer" : { "port" : 19446, "forward" : [ "192.168.0.10:19445", "192.168.0.11:19445" ] }, Former-commit-id: 33af219cfce99609ca7245d662dc0f0561013bbd --- include/protoserver/ProtoConnection.h | 8 ++++---- include/protoserver/ProtoServer.h | 4 +++- libsrc/protoserver/ProtoClientConnection.cpp | 17 ++++++++++++++++- libsrc/protoserver/ProtoClientConnection.h | 8 +++++++- libsrc/protoserver/ProtoServer.cpp | 7 +++++-- src/hyperiond/hyperiond.cpp | 14 +++++++++++++- 6 files changed, 48 insertions(+), 10 deletions(-) diff --git a/include/protoserver/ProtoConnection.h b/include/protoserver/ProtoConnection.h index bb41e1b7..a61947fe 100644 --- a/include/protoserver/ProtoConnection.h +++ b/include/protoserver/ProtoConnection.h @@ -67,10 +67,6 @@ public: /// void clearAll(); -private: - /// Try to connect to the Hyperion host - void connectToHost(); - /// /// Send a command message and receive its reply /// @@ -78,6 +74,10 @@ private: /// void sendMessage(const proto::HyperionRequest & message); +private: + /// Try to connect to the Hyperion host + void connectToHost(); + /// /// Parse a reply message /// diff --git a/include/protoserver/ProtoServer.h b/include/protoserver/ProtoServer.h index dae57481..c18b38fb 100644 --- a/include/protoserver/ProtoServer.h +++ b/include/protoserver/ProtoServer.h @@ -6,6 +6,7 @@ // Qt includes #include #include +#include // Hyperion includes #include @@ -27,7 +28,7 @@ public: /// @param hyperion Hyperion instance /// @param port port number on which to start listening for connections /// - ProtoServer(Hyperion * hyperion, uint16_t port = 19445); + ProtoServer(Hyperion * hyperion, uint16_t port = 19445, QStringList * forwardClientList = new QStringList() ); ~ProtoServer(); /// @@ -56,4 +57,5 @@ private: /// List with open connections QSet _openConnections; + QStringList _forwardClients; }; diff --git a/libsrc/protoserver/ProtoClientConnection.cpp b/libsrc/protoserver/ProtoClientConnection.cpp index 165315f7..2f0cc8d3 100644 --- a/libsrc/protoserver/ProtoClientConnection.cpp +++ b/libsrc/protoserver/ProtoClientConnection.cpp @@ -20,7 +20,7 @@ // project includes #include "ProtoClientConnection.h" -ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion) : +ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion, QStringList forwardClientList) : QObject(), _socket(socket), _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()), @@ -30,11 +30,22 @@ ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hype // connect internal signals and slots connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed())); connect(_socket, SIGNAL(readyRead()), this, SLOT(readData())); + + for (int i = 0; i < forwardClientList.size(); ++i) { + std::cout << "Proto forward to " << forwardClientList.at(i).toLocal8Bit().constData() << std::endl; + ProtoConnection* p = new ProtoConnection("127.0.0.1:19445"); + p->setSkipReply(true); + _proxy_connections << p; + } + } ProtoClientConnection::~ProtoClientConnection() { delete _socket; + + while (!_proxy_connections.isEmpty()) + delete _proxy_connections.takeFirst(); } void ProtoClientConnection::readData() @@ -81,6 +92,10 @@ void ProtoClientConnection::socketClosed() void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message) { + // forward messages + for (int i = 0; i < _proxy_connections.size(); ++i) + _proxy_connections.at(i)->sendMessage(message); + switch (message.command()) { case proto::HyperionRequest::COLOR: diff --git a/libsrc/protoserver/ProtoClientConnection.h b/libsrc/protoserver/ProtoClientConnection.h index ec7d2e1c..a0c1186e 100644 --- a/libsrc/protoserver/ProtoClientConnection.h +++ b/libsrc/protoserver/ProtoClientConnection.h @@ -6,12 +6,14 @@ // Qt includes #include #include +#include // Hyperion includes #include // proto includes #include "message.pb.h" +#include "protoserver/ProtoConnection.h" class ImageProcessor; @@ -28,7 +30,7 @@ public: /// @param socket The Socket object for this connection /// @param hyperion The Hyperion server /// - ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion); + ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion, QStringList forwardClientList); /// /// Destructor @@ -123,4 +125,8 @@ private: /// The buffer used for reading data from the socket QByteArray _receiveBuffer; + + /// Hyperion proto connection object for forwarding + QList _proxy_connections; + }; diff --git a/libsrc/protoserver/ProtoServer.cpp b/libsrc/protoserver/ProtoServer.cpp index a1afa30c..54d8611b 100644 --- a/libsrc/protoserver/ProtoServer.cpp +++ b/libsrc/protoserver/ProtoServer.cpp @@ -5,12 +5,15 @@ #include #include "ProtoClientConnection.h" -ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port) : +ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port, QStringList * forwardClientList) : QObject(), _hyperion(hyperion), _server(), _openConnections() { + for (int i = 0; i < forwardClientList->size(); ++i) + _forwardClients << forwardClientList->at(i); + if (!_server.listen(QHostAddress::Any, port)) { throw std::runtime_error("Proto server could not bind to port"); @@ -39,7 +42,7 @@ void ProtoServer::newConnection() if (socket != nullptr) { std::cout << "New proto connection" << std::endl; - ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion); + ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion, _forwardClients); _openConnections.insert(connection); // register slot for cleaning up after the connection closed diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 032d44db..d96b345a 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -1,6 +1,7 @@ // C++ includes #include #include +#include // QT includes #include @@ -368,7 +369,18 @@ int main(int argc, char** argv) if (config.isMember("protoServer")) { const Json::Value & protoServerConfig = config["protoServer"]; - protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt()); + QStringList forwardClientList; + + if ( ! protoServerConfig["forward"].isNull() && protoServerConfig["forward"].isArray() ) + { + for (const Json::Value& client : protoServerConfig["forward"]) + { + forwardClientList << client.asString().c_str(); + std::cout << client.asString() << std::endl; + } + } + + protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt(), &forwardClientList ); std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl; } #endif From d6b5dc7ae65a4ce59aa1bed4fc54c1086502530f Mon Sep 17 00:00:00 2001 From: wisc17 Date: Tue, 9 Feb 2016 20:21:49 +0100 Subject: [PATCH 63/96] Revert "Update LedDeviceAPA102.cpp by pcaffardi" Former-commit-id: 493b32c03f922cc26d9fb4fce4778636f6a96e84 --- libsrc/leddevice/LedDeviceAPA102.cpp | 53 ++++++++++------------------ 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/libsrc/leddevice/LedDeviceAPA102.cpp b/libsrc/leddevice/LedDeviceAPA102.cpp index 17bec4fc..26a21f72 100644 --- a/libsrc/leddevice/LedDeviceAPA102.cpp +++ b/libsrc/leddevice/LedDeviceAPA102.cpp @@ -1,7 +1,9 @@ + // STL includes #include #include #include +#include // Linux includes #include @@ -17,46 +19,27 @@ LedDeviceAPA102::LedDeviceAPA102(const std::string& outputDevice, const unsigned // empty } -#define MIN(a,b) ((a)<(b)?(a):(b)) -#define MAX(a,b) ((a)>(b)?(a):(b)) - -#define APA102_START_FRAME_BYTES 4 -#define APA102_LED_BYTES 4 -#define APA102_END_FRAME_BITS_MIN 32 -#define APA102_END_FRAME_BITS(leds) MAX((((leds-1)/2)+1),APA102_END_FRAME_BITS_MIN) -#define APA102_END_FRAME_BYTES(leds) (((APA102_END_FRAME_BITS(leds)-1)/8)+1) -#define APA102_LED_HEADER 0xe0 -#define APA102_LED_MAX_INTENSITY 0x1f - int LedDeviceAPA102::write(const std::vector &ledValues) { - const unsigned int startFrameSize = APA102_START_FRAME_BYTES; - const unsigned int ledsCount = ledValues.size() ; - const unsigned int ledsSize = ledsCount * APA102_LED_BYTES ; - const unsigned int endFrameBits = APA102_END_FRAME_BITS(ledsCount) ; - const unsigned int endFrameSize = APA102_END_FRAME_BYTES(ledsCount) ; - const unsigned int transferSize = startFrameSize + ledsSize + endFrameSize ; - - if(_ledBuffer.size() != transferSize){ - _ledBuffer.resize(transferSize, 0x00); + const unsigned int startFrameSize = 4; + const unsigned int endFrameSize = std::max(((ledValues.size() + 15) / 16), 4); + const unsigned int mLedCount = (ledValues.size() * 4) + startFrameSize + endFrameSize; + if(_ledBuffer.size() != mLedCount){ + _ledBuffer.resize(mLedCount, 0xFF); + _ledBuffer[0] = 0x00; + _ledBuffer[1] = 0x00; + _ledBuffer[2] = 0x00; + _ledBuffer[3] = 0x00; } - - unsigned idx = 0, i; - for (i=0; i Date: Wed, 10 Feb 2016 16:25:08 +0100 Subject: [PATCH 64/96] corrected rpi binary filename Former-commit-id: 6e476fa8252dde2495f2808f7c76f22f09ed1e4e --- bin/install_hyperion.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/install_hyperion.sh b/bin/install_hyperion.sh index 4d3e9a2c..4c06e696 100755 --- a/bin/install_hyperion.sh +++ b/bin/install_hyperion.sh @@ -40,7 +40,7 @@ if [ $IS_OPENELEC -eq 1 ]; then if [ $IS_IMX6 -eq 1 ]; then curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_imx6.tar.gz | tar -C /storage -xz else - curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.tar.gz | tar -C /storage -xz + curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_rpi.tar.gz | tar -C /storage -xz fi curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.deps.openelec-rpi.tar.gz | tar -C /storage/hyperion/bin -xz # modify the default config to have a correct effect path @@ -49,7 +49,7 @@ else if [ $IS_IMX6 -eq 1 ]; then wget https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_imx6.tar.gz -O - | tar -C /opt -xz else - wget https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.tar.gz -O - | tar -C /opt -xz + wget https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_rpi.tar.gz -O - | tar -C /opt -xz fi fi From 27557f7848b0bcb235ccaedba49521cbb83a9fb1 Mon Sep 17 00:00:00 2001 From: wisc Date: Wed, 10 Feb 2016 18:07:47 +0100 Subject: [PATCH 65/96] added missing gpio2spi Former-commit-id: 7882635b25d9568fc13ce98c136c97772e6ada03 --- deploy/hyperion_rpi.tar.gz.REMOVED.git-id | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id index 44bbdc58..9c96bfd2 100644 --- a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id @@ -1 +1 @@ -5c164e4ff52076a530461cdf6966943d52cd39df \ No newline at end of file +d079238ea69f0fb1422e9d7181016d4e290c12d5 \ No newline at end of file From e10392b0c85e9b601376f4b2f37ab01a410ca1a8 Mon Sep 17 00:00:00 2001 From: wisc Date: Wed, 10 Feb 2016 18:36:04 +0100 Subject: [PATCH 66/96] added gpio2spi Former-commit-id: c04a47d0ac351a8840f3b00d7a2ab866c22c5008 --- bin/create_release.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/create_release.sh b/bin/create_release.sh index 625ff0e1..d6b9bf66 100644 --- a/bin/create_release.sh +++ b/bin/create_release.sh @@ -28,6 +28,7 @@ tar --create --verbose --gzip --absolute-names --show-transformed-names --ignore "$builddir/bin/hyperiond" \ "$builddir/bin/hyperion-remote" \ "$builddir/bin/hyperion-v4l2" \ + "$builddir/bin/gpio2spi" \ "$builddir/bin/dispmanx2png" \ "$repodir/effects/"* \ "$repodir/bin/hyperion.init.sh" \ From 0661ad74f6402ed414749575e9f29a33ab6eadea Mon Sep 17 00:00:00 2001 From: Danimal4326 Date: Wed, 10 Feb 2016 12:22:19 -0600 Subject: [PATCH 67/96] Fx compile issue for missing ceil function Former-commit-id: f5a6ac2c19b73aa48b5f4292cfa912dc2936701b --- libsrc/blackborder/BlackBorderDetector.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libsrc/blackborder/BlackBorderDetector.cpp b/libsrc/blackborder/BlackBorderDetector.cpp index 60a57c30..669f22f9 100644 --- a/libsrc/blackborder/BlackBorderDetector.cpp +++ b/libsrc/blackborder/BlackBorderDetector.cpp @@ -1,6 +1,7 @@ #include // BlackBorders includes #include +#include using namespace hyperion; From 63ec2909eb7baa5ceeacb77d96d93ebce551f6ee Mon Sep 17 00:00:00 2001 From: wisc Date: Thu, 11 Feb 2016 15:50:51 +0100 Subject: [PATCH 68/96] added bottom right to osd mode Former-commit-id: 3972abaf30d46558d310dbc5e2d164330e9a5b63 --- include/blackborder/BlackBorderDetector.h | 28 +++++++++++++-------- libsrc/blackborder/BlackBorderProcessor.cpp | 5 +--- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/include/blackborder/BlackBorderDetector.h b/include/blackborder/BlackBorderDetector.h index a3a1c32b..7323ebd1 100644 --- a/include/blackborder/BlackBorderDetector.h +++ b/include/blackborder/BlackBorderDetector.h @@ -1,3 +1,4 @@ +//#include #pragma once // Utils includes @@ -82,10 +83,13 @@ namespace hyperion int firstNonBlackXPixelIndex = -1; int firstNonBlackYPixelIndex = -1; + width--; // remove 1 pixel to get end pixel index + height--; + // find first X pixel of the image for (int x = 0; x < width33percent; ++x) { - const Pixel_T & color1 = image( (width - 1 - x), yCenter); // right side center line check + const Pixel_T & color1 = image( (width - x), yCenter); // right side center line check const Pixel_T & color2 = image(x, height33percent); const Pixel_T & color3 = image(x, height66percent); if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3)) @@ -98,7 +102,7 @@ namespace hyperion // find first Y pixel of the image for (int y = 0; y < height33percent; ++y) { - const Pixel_T & color1 = image(xCenter, (height - 1 - y)); // bottom center line check + const Pixel_T & color1 = image(xCenter, (height - y)); // bottom center line check const Pixel_T & color2 = image(width33percent, y ); const Pixel_T & color3 = image(width66percent, y); if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3)) @@ -174,7 +178,8 @@ namespace hyperion } -// osd detection mode (find x then y at detected x to avoid changes by osd overlays) + /// + /// osd detection mode (find x then y at detected x to avoid changes by osd overlays) template BlackBorder process_osd(const Image & image) { @@ -184,20 +189,21 @@ namespace hyperion int height = image.height(); int width33percent = width / 3; int height33percent = height / 3; -// int width66percent = width33percent * 2; int height66percent = height33percent * 2; -// int xCenter = width / 2; int yCenter = height / 2; int firstNonBlackXPixelIndex = -1; int firstNonBlackYPixelIndex = -1; + width--; // remove 1 pixel to get end pixel index + height--; + // find first X pixel of the image int x; for (x = 0; x < width33percent; ++x) { - const Pixel_T & color1 = image( (width - 1 - x), yCenter); // right side center line check + const Pixel_T & color1 = image( (width - x), yCenter); // right side center line check const Pixel_T & color2 = image(x, height33percent); const Pixel_T & color3 = image(x, height66percent); if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3)) @@ -210,11 +216,13 @@ namespace hyperion // find first Y pixel of the image for (int y = 0; y < height33percent; ++y) { - const Pixel_T & color1 = image(x, (height - 1 - y)); // left side bottom check - const Pixel_T & color2 = image(x, y );// left side top check - const Pixel_T & color3 = image( (width - 1 - x), y); // right side top check - if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3)) + const Pixel_T & color1 = image(x, y );// left side top check + const Pixel_T & color2 = image(x, (height - y)); // left side bottom check + const Pixel_T & color3 = image( (width - x), y); // right side top check + const Pixel_T & color4 = image( (width - x), (height - y)); // right side bottom check + if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3) || !isBlack(color4)) { +// std::cout << "y " << y << " lt " << int(isBlack(color1)) << " lb " << int(isBlack(color2)) << " rt " << int(isBlack(color3)) << " rb " << int(isBlack(color4)) << std::endl; firstNonBlackYPixelIndex = y; break; } diff --git a/libsrc/blackborder/BlackBorderProcessor.cpp b/libsrc/blackborder/BlackBorderProcessor.cpp index d6678d51..e7fbc205 100644 --- a/libsrc/blackborder/BlackBorderProcessor.cpp +++ b/libsrc/blackborder/BlackBorderProcessor.cpp @@ -1,12 +1,9 @@ -//* #include /* #include -using std::cout; -using std::endl; using std::setw; -using std::left; //*/ + // Blackborder includes #include From 3996ff789cd9f954252b2fa59c405b614cf5d433 Mon Sep 17 00:00:00 2001 From: Danimal4326 Date: Thu, 11 Feb 2016 12:55:41 -0600 Subject: [PATCH 69/96] remove include of cmath lib Former-commit-id: 004c76c724b9739d977a93d3574821db2c4de2e8 --- libsrc/hyperion/ImageProcessorFactory.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libsrc/hyperion/ImageProcessorFactory.cpp b/libsrc/hyperion/ImageProcessorFactory.cpp index c85b35cd..e3e4f44c 100644 --- a/libsrc/hyperion/ImageProcessorFactory.cpp +++ b/libsrc/hyperion/ImageProcessorFactory.cpp @@ -1,7 +1,3 @@ - -// STL includes -#include - // Hyperion includes #include #include From ca24450618cda5763fcaacd23a57483f173ac508 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Sat, 13 Feb 2016 23:00:31 +1100 Subject: [PATCH 70/96] added configurable latchtime for 2801 SPI driver Former-commit-id: a10b0bd24a85580b021c735b30ebd2635180a514 --- libsrc/leddevice/LedDeviceFactory.cpp | 3 ++- libsrc/leddevice/LedDeviceWs2801.cpp | 9 ++++++++- libsrc/leddevice/LedDeviceWs2801.h | 4 ++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 6e7b3da8..1a0e1709 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -128,8 +128,9 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) { const std::string output = deviceConfig["output"].asString(); const unsigned rate = deviceConfig["rate"].asInt(); + const unsigned latchtime = deviceConfig.get("latchtime",500000).asInt(); - LedDeviceWs2801* deviceWs2801 = new LedDeviceWs2801(output, rate); + LedDeviceWs2801* deviceWs2801 = new LedDeviceWs2801(output, rate, latchtime); deviceWs2801->open(); device = deviceWs2801; diff --git a/libsrc/leddevice/LedDeviceWs2801.cpp b/libsrc/leddevice/LedDeviceWs2801.cpp index 31bb43cd..b36d2f49 100644 --- a/libsrc/leddevice/LedDeviceWs2801.cpp +++ b/libsrc/leddevice/LedDeviceWs2801.cpp @@ -11,13 +11,20 @@ // hyperion local includes #include "LedDeviceWs2801.h" -LedDeviceWs2801::LedDeviceWs2801(const std::string& outputDevice, const unsigned baudrate) : +LedDeviceWs2801::LedDeviceWs2801(const std::string& outputDevice, const unsigned baudrate ) : LedSpiDevice(outputDevice, baudrate, 500000), mLedCount(0) { // empty } +LedDeviceWs2801::LedDeviceWs2801(const std::string& outputDevice, const unsigned baudrate, const unsigned latchTime) : + LedSpiDevice(outputDevice, baudrate, latchTime), + mLedCount(0) +{ + // empty +} + int LedDeviceWs2801::write(const std::vector &ledValues) { mLedCount = ledValues.size(); diff --git a/libsrc/leddevice/LedDeviceWs2801.h b/libsrc/leddevice/LedDeviceWs2801.h index e7ff6998..c2231cd7 100644 --- a/libsrc/leddevice/LedDeviceWs2801.h +++ b/libsrc/leddevice/LedDeviceWs2801.h @@ -21,6 +21,10 @@ public: LedDeviceWs2801(const std::string& outputDevice, const unsigned baudrate); + LedDeviceWs2801(const std::string& outputDevice, + const unsigned baudrate, + const unsigned latchTime); + /// /// Writes the led color values to the led-device /// From b01b5eb005d51e7cf35de62a76b908e686d4e994 Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 15 Feb 2016 18:25:18 +0100 Subject: [PATCH 71/96] - prepare general way to send (proto) messages. currently only incomming protomessages are forwarded - begin impl. of json server Former-commit-id: 8f9237cd57ada1e84dc05e60b9ad723e47fd57b1 --- include/hyperion/Hyperion.h | 9 ++ include/hyperion/MessageForwarder.h | 31 +++++ include/protoserver/ProtoServer.h | 15 ++- libsrc/hyperion/CMakeLists.txt | 134 ++++++++++--------- libsrc/hyperion/Hyperion.cpp | 30 +++++ libsrc/hyperion/MessageForwarder.cpp | 34 +++++ libsrc/jsonserver/JsonClientConnection.cpp | 67 +++++++++- libsrc/jsonserver/JsonClientConnection.h | 6 + libsrc/protoserver/ProtoClientConnection.cpp | 16 +-- libsrc/protoserver/ProtoClientConnection.h | 7 +- libsrc/protoserver/ProtoServer.cpp | 29 +++- src/hyperiond/hyperiond.cpp | 13 +- 12 files changed, 287 insertions(+), 104 deletions(-) create mode 100644 include/hyperion/MessageForwarder.h create mode 100644 libsrc/hyperion/MessageForwarder.cpp diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index b6ed0946..811f0199 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -13,6 +13,7 @@ // Hyperion includes #include #include +#include // Effect engine includes #include @@ -125,6 +126,10 @@ public slots: /// Tell Hyperion that the transforms have changed and the leds need to be updated void transformsUpdated(); + /// Returns MessageForwarder Object + /// @return instance of message forwarder object + MessageForwarder * getForwarder(); + /// /// Clears the given priority channel. This will switch the led-colors to the colors of the next /// lower priority channel (or off if no more channels are set) @@ -168,6 +173,7 @@ public: static RgbChannelTransform * createRgbChannelTransform(const Json::Value& colorConfig); static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice); + static MessageForwarder * createMessageForwarder(const Json::Value & forwarderConfig); signals: /// Signal which is emitted when a priority channel is actively cleared @@ -201,6 +207,9 @@ private: /// Effect engine EffectEngine * _effectEngine; + // proto and json Message forwarder + MessageForwarder * _messageForwarder; + /// The timer for handling priority channel timeouts QTimer _timer; }; diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h new file mode 100644 index 00000000..467d0d35 --- /dev/null +++ b/include/hyperion/MessageForwarder.h @@ -0,0 +1,31 @@ +#pragma once + +// STL includes +#include +#include +#include +#include + +// QT includes +#include +#include + +// Utils includes +#include +class MessageForwarder +{ +public: + MessageForwarder(); + ~MessageForwarder(); + + void addJsonSlave(std::string slave); + void addProtoSlave(std::string slave); + void sendMessage(); + + QStringList getProtoSlaves(); + +private: + bool _running; + + QStringList _protoSlaves; +}; diff --git a/include/protoserver/ProtoServer.h b/include/protoserver/ProtoServer.h index c18b38fb..1d530caa 100644 --- a/include/protoserver/ProtoServer.h +++ b/include/protoserver/ProtoServer.h @@ -6,12 +6,19 @@ // Qt includes #include #include +#include #include // Hyperion includes #include +// forward decl class ProtoClientConnection; +class ProtoConnection; + +namespace proto { +class HyperionRequest; +} /// /// This class creates a TCP server which accepts connections wich can then send @@ -28,7 +35,7 @@ public: /// @param hyperion Hyperion instance /// @param port port number on which to start listening for connections /// - ProtoServer(Hyperion * hyperion, uint16_t port = 19445, QStringList * forwardClientList = new QStringList() ); + ProtoServer(Hyperion * hyperion, uint16_t port = 19445); ~ProtoServer(); /// @@ -48,6 +55,8 @@ private slots: /// void closedConnection(ProtoClientConnection * connection); + void newMessage(const proto::HyperionRequest * message); + private: /// Hyperion instance Hyperion * _hyperion; @@ -58,4 +67,8 @@ private: /// List with open connections QSet _openConnections; QStringList _forwardClients; + + /// Hyperion proto connection object for forwarding + QList _proxy_connections; + }; diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 1434f105..3a277a7e 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -1,66 +1,68 @@ - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion) - -# Group the headers that go through the MOC compiler -SET(Hyperion_QT_HEADERS - ${CURRENT_HEADER_DIR}/Hyperion.h - - ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h -) - -SET(Hyperion_HEADERS - ${CURRENT_HEADER_DIR}/ImageProcessor.h - ${CURRENT_HEADER_DIR}/ImageProcessorFactory.h - ${CURRENT_HEADER_DIR}/ImageToLedsMap.h - ${CURRENT_HEADER_DIR}/LedString.h - ${CURRENT_HEADER_DIR}/PriorityMuxer.h - - ${CURRENT_SOURCE_DIR}/MultiColorTransform.h -) - -SET(Hyperion_SOURCES - ${CURRENT_SOURCE_DIR}/Hyperion.cpp - ${CURRENT_SOURCE_DIR}/ImageProcessor.cpp - ${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp - ${CURRENT_SOURCE_DIR}/LedString.cpp - ${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp - - ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp - ${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp - ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp -) - -set(Hyperion_RESOURCES - ${CURRENT_SOURCE_DIR}/resource.qrc -) - -if(ENABLE_QT5) -QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) -QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") -else(ENABLE_QT5) -QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) -QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") -endif(ENABLE_QT5) - -add_library(hyperion - ${Hyperion_HEADERS} - ${Hyperion_QT_HEADERS} - ${Hyperion_HEADERS_MOC} - ${Hyperion_SOURCES} - ${Hyperion_RESOURCES_RCC} -) - -if(ENABLE_QT5) -qt5_use_modules(hyperion Widgets) -endif(ENABLE_QT5) - -target_link_libraries(hyperion - blackborder - hyperion-utils - leddevice - effectengine - serialport - ${QT_LIBRARIES} -) + +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion) + +# Group the headers that go through the MOC compiler +SET(Hyperion_QT_HEADERS + ${CURRENT_HEADER_DIR}/Hyperion.h + ${CURRENT_HEADER_DIR}/MessageForwarder.h + + ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h +) + +SET(Hyperion_HEADERS + ${CURRENT_HEADER_DIR}/ImageProcessor.h + ${CURRENT_HEADER_DIR}/ImageProcessorFactory.h + ${CURRENT_HEADER_DIR}/ImageToLedsMap.h + ${CURRENT_HEADER_DIR}/LedString.h + ${CURRENT_HEADER_DIR}/PriorityMuxer.h + + ${CURRENT_SOURCE_DIR}/MultiColorTransform.h +) + +SET(Hyperion_SOURCES + ${CURRENT_SOURCE_DIR}/Hyperion.cpp + ${CURRENT_SOURCE_DIR}/ImageProcessor.cpp + ${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp + ${CURRENT_SOURCE_DIR}/LedString.cpp + ${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp + + ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp + ${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp + ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp + ${CURRENT_SOURCE_DIR}/MessageForwarder.cpp +) + +set(Hyperion_RESOURCES + ${CURRENT_SOURCE_DIR}/resource.qrc +) + +if(ENABLE_QT5) +QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) +QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") +else(ENABLE_QT5) +QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) +QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") +endif(ENABLE_QT5) + +add_library(hyperion + ${Hyperion_HEADERS} + ${Hyperion_QT_HEADERS} + ${Hyperion_HEADERS_MOC} + ${Hyperion_SOURCES} + ${Hyperion_RESOURCES_RCC} +) + +if(ENABLE_QT5) +qt5_use_modules(hyperion Widgets) +endif(ENABLE_QT5) + +target_link_libraries(hyperion + blackborder + hyperion-utils + leddevice + effectengine + serialport + ${QT_LIBRARIES} +) diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 37c77927..ed23fb30 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -267,12 +267,39 @@ LedDevice * Hyperion::createColorSmoothing(const Json::Value & smoothingConfig, } +MessageForwarder * Hyperion::createMessageForwarder(const Json::Value & forwarderConfig) +{ + MessageForwarder * forwarder = new MessageForwarder(); + if ( ! forwarderConfig.isNull() ) + { + if ( ! forwarderConfig["json"].isNull() && forwarderConfig["json"].isArray() ) + { + for (const Json::Value& addr : forwarderConfig["json"]) + forwarder->addJsonSlave(addr.asString()); + } + + if ( ! forwarderConfig["proto"].isNull() && forwarderConfig["proto"].isArray() ) + { + for (const Json::Value& addr : forwarderConfig["proto"]) + forwarder->addProtoSlave(addr.asString()); + } + } + + return forwarder; +} + +MessageForwarder * Hyperion::getForwarder() +{ + return _messageForwarder; +} + Hyperion::Hyperion(const Json::Value &jsonConfig) : _ledString(createLedString(jsonConfig["leds"], createColorOrder(jsonConfig["device"]))), _muxer(_ledString.leds().size()), _raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])), _device(LedDeviceFactory::construct(jsonConfig["device"])), _effectEngine(nullptr), + _messageForwarder(createMessageForwarder(jsonConfig["forwarder"])), _timer() { if (!_raw2ledTransform->verifyTransforms()) @@ -314,6 +341,9 @@ Hyperion::~Hyperion() // delete the color transform delete _raw2ledTransform; + + // delete the message forwarder + delete _messageForwarder; } unsigned Hyperion::getLedCount() const diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp new file mode 100644 index 00000000..8da277e2 --- /dev/null +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -0,0 +1,34 @@ +#include + + +MessageForwarder::MessageForwarder() : +_running(false) +{ +} + +MessageForwarder::~MessageForwarder() +{ +} + + +void MessageForwarder::addJsonSlave(std::string slave) +{ + std::cout << slave << std::endl; +} + +void MessageForwarder::addProtoSlave(std::string slave) +{ + _protoSlaves << QString(slave.c_str()); +} + +void MessageForwarder::sendMessage() +{ + if ( ! _running ) + return; + +} + +QStringList MessageForwarder::getProtoSlaves() +{ + return _protoSlaves; +} diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 87fb7c1f..1b700b25 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -250,8 +250,22 @@ void JsonClientConnection::handleMessage(const std::string &messageString) handleNotImplemented(); } + +void JsonClientConnection::forwardJsonMessage(const Json::Value & message) +{ + QTcpSocket client; + client.connectToHost(QHostAddress("127.0.0.1"), 19444); + if ( client.waitForConnected(500) ) + { + sendMessage(message,&client); + client.close(); + } +} + void JsonClientConnection::handleColorCommand(const Json::Value &message) { + forwardJsonMessage(message); + // extract parameters int priority = message["priority"].asInt(); int duration = message.get("duration", -1).asInt(); @@ -289,6 +303,8 @@ void JsonClientConnection::handleColorCommand(const Json::Value &message) void JsonClientConnection::handleImageCommand(const Json::Value &message) { + forwardJsonMessage(message); + // extract parameters int priority = message["priority"].asInt(); int duration = message.get("duration", -1).asInt(); @@ -320,6 +336,8 @@ void JsonClientConnection::handleImageCommand(const Json::Value &message) void JsonClientConnection::handleEffectCommand(const Json::Value &message) { + forwardJsonMessage(message); + // extract parameters int priority = message["priority"].asInt(); int duration = message.get("duration", -1).asInt(); @@ -418,6 +436,8 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &) void JsonClientConnection::handleClearCommand(const Json::Value &message) { + forwardJsonMessage(message); + // extract parameters int priority = message["priority"].asInt(); @@ -428,8 +448,10 @@ void JsonClientConnection::handleClearCommand(const Json::Value &message) sendSuccessReply(); } -void JsonClientConnection::handleClearallCommand(const Json::Value &) +void JsonClientConnection::handleClearallCommand(const Json::Value & message) { + forwardJsonMessage(message); + // clear priority _hyperion->clearall(); @@ -530,10 +552,51 @@ void JsonClientConnection::sendMessage(const Json::Value &message) response.append(serializedReply.c_str(), serializedReply.length()); - _socket->write(response.data(), response.length()); + _socket->write(response.data(), response.length()); } } + +void JsonClientConnection::sendMessage(const Json::Value & message, QTcpSocket * socket) +{ + // serialize message (FastWriter already appends a newline) + std::string serializedMessage = Json::FastWriter().write(message); + + // write message + socket->write(serializedMessage.c_str()); + if (!socket->waitForBytesWritten()) + { + //std::cout << "Error while writing data to host" << std::endl; + return; + } + + // read reply data + QByteArray serializedReply; + while (!serializedReply.contains('\n')) + { + // receive reply + if (!socket->waitForReadyRead()) + { + //std::cout << "Error while reading data from host" << std::endl; + return; + } + + serializedReply += socket->readAll(); + } + int bytes = serializedReply.indexOf('\n') + 1; // Find the end of message + + // parse reply data + Json::Reader jsonReader; + Json::Value reply; + if (!jsonReader.parse(serializedReply.constData(), serializedReply.constData() + bytes, reply)) + { + //std::cout << "Error while parsing reply: invalid json" << std::endl; + return; + } + +} + + void JsonClientConnection::sendSuccessReply() { // create reply diff --git a/libsrc/jsonserver/JsonClientConnection.h b/libsrc/jsonserver/JsonClientConnection.h index 6575388a..01db54b1 100644 --- a/libsrc/jsonserver/JsonClientConnection.h +++ b/libsrc/jsonserver/JsonClientConnection.h @@ -124,6 +124,7 @@ private: /// @param message The JSON message to send /// void sendMessage(const Json::Value & message); + void sendMessage(const Json::Value & message, QTcpSocket * socket); /// /// Send a standard reply indicating success @@ -147,6 +148,11 @@ private: /// void handleWebSocketFrame(); + /// + /// forward json message + /// + void forwardJsonMessage(const Json::Value & message); + private: /// /// Check if a JSON messag is valid according to a given JSON schema diff --git a/libsrc/protoserver/ProtoClientConnection.cpp b/libsrc/protoserver/ProtoClientConnection.cpp index 2f0cc8d3..d1f087cd 100644 --- a/libsrc/protoserver/ProtoClientConnection.cpp +++ b/libsrc/protoserver/ProtoClientConnection.cpp @@ -20,7 +20,7 @@ // project includes #include "ProtoClientConnection.h" -ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion, QStringList forwardClientList) : +ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion) : QObject(), _socket(socket), _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()), @@ -30,22 +30,11 @@ ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hype // connect internal signals and slots connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed())); connect(_socket, SIGNAL(readyRead()), this, SLOT(readData())); - - for (int i = 0; i < forwardClientList.size(); ++i) { - std::cout << "Proto forward to " << forwardClientList.at(i).toLocal8Bit().constData() << std::endl; - ProtoConnection* p = new ProtoConnection("127.0.0.1:19445"); - p->setSkipReply(true); - _proxy_connections << p; - } - } ProtoClientConnection::~ProtoClientConnection() { delete _socket; - - while (!_proxy_connections.isEmpty()) - delete _proxy_connections.takeFirst(); } void ProtoClientConnection::readData() @@ -93,8 +82,7 @@ void ProtoClientConnection::socketClosed() void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message) { // forward messages - for (int i = 0; i < _proxy_connections.size(); ++i) - _proxy_connections.at(i)->sendMessage(message); + emit newMessage(&message); switch (message.command()) { diff --git a/libsrc/protoserver/ProtoClientConnection.h b/libsrc/protoserver/ProtoClientConnection.h index a0c1186e..c68f56e0 100644 --- a/libsrc/protoserver/ProtoClientConnection.h +++ b/libsrc/protoserver/ProtoClientConnection.h @@ -30,7 +30,7 @@ public: /// @param socket The Socket object for this connection /// @param hyperion The Hyperion server /// - ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion, QStringList forwardClientList); + ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion); /// /// Destructor @@ -43,6 +43,7 @@ signals: /// @param connection This connection object /// void connectionClosed(ProtoClientConnection * connection); + void newMessage(const proto::HyperionRequest * message); private slots: /// @@ -125,8 +126,4 @@ private: /// The buffer used for reading data from the socket QByteArray _receiveBuffer; - - /// Hyperion proto connection object for forwarding - QList _proxy_connections; - }; diff --git a/libsrc/protoserver/ProtoServer.cpp b/libsrc/protoserver/ProtoServer.cpp index 54d8611b..a7c51ca8 100644 --- a/libsrc/protoserver/ProtoServer.cpp +++ b/libsrc/protoserver/ProtoServer.cpp @@ -2,17 +2,27 @@ #include // project includes +#include #include +#include "protoserver/ProtoConnection.h" #include "ProtoClientConnection.h" -ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port, QStringList * forwardClientList) : +ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port) : QObject(), _hyperion(hyperion), _server(), _openConnections() { - for (int i = 0; i < forwardClientList->size(); ++i) - _forwardClients << forwardClientList->at(i); + + MessageForwarder * forwarder = hyperion->getForwarder(); + QStringList slaves = forwarder->getProtoSlaves(); + + for (int i = 0; i < slaves.size(); ++i) { + std::cout << "Proto forward to " << slaves.at(i).toLocal8Bit().constData() << std::endl; + ProtoConnection* p = new ProtoConnection(slaves.at(i).toLocal8Bit().constData()); + p->setSkipReply(true); + _proxy_connections << p; + } if (!_server.listen(QHostAddress::Any, port)) { @@ -28,6 +38,9 @@ ProtoServer::~ProtoServer() foreach (ProtoClientConnection * connection, _openConnections) { delete connection; } + + while (!_proxy_connections.isEmpty()) + delete _proxy_connections.takeFirst(); } uint16_t ProtoServer::getPort() const @@ -42,14 +55,22 @@ void ProtoServer::newConnection() if (socket != nullptr) { std::cout << "New proto connection" << std::endl; - ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion, _forwardClients); + ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion); _openConnections.insert(connection); // register slot for cleaning up after the connection closed connect(connection, SIGNAL(connectionClosed(ProtoClientConnection*)), this, SLOT(closedConnection(ProtoClientConnection*))); + connect(connection, SIGNAL(newMessage(const proto::HyperionRequest*)), this, SLOT(newMessage(const proto::HyperionRequest*))); + } } +void ProtoServer::newMessage(const proto::HyperionRequest * message) +{ + for (int i = 0; i < _proxy_connections.size(); ++i) + _proxy_connections.at(i)->sendMessage(*message); +} + void ProtoServer::closedConnection(ProtoClientConnection *connection) { std::cout << "Proto connection closed" << std::endl; diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index d96b345a..7bb5e60e 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -369,18 +369,7 @@ int main(int argc, char** argv) if (config.isMember("protoServer")) { const Json::Value & protoServerConfig = config["protoServer"]; - QStringList forwardClientList; - - if ( ! protoServerConfig["forward"].isNull() && protoServerConfig["forward"].isArray() ) - { - for (const Json::Value& client : protoServerConfig["forward"]) - { - forwardClientList << client.asString().c_str(); - std::cout << client.asString() << std::endl; - } - } - - protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt(), &forwardClientList ); + protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl; } #endif From df91527557342e7925c57de81610b67485d3d9ce Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 15 Feb 2016 20:53:03 +0100 Subject: [PATCH 72/96] implement json forwarder Former-commit-id: 5519118304bd5690e6b512481347579339e78ac9 --- include/hyperion/MessageForwarder.h | 13 ++++++++--- libsrc/hyperion/Hyperion.cpp | 6 ++++++ libsrc/hyperion/MessageForwarder.cpp | 25 ++++++++++++++++------ libsrc/jsonserver/JsonClientConnection.cpp | 14 ++++++++---- libsrc/protoserver/ProtoServer.cpp | 1 - 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h index 467d0d35..0a3c1b19 100644 --- a/include/hyperion/MessageForwarder.h +++ b/include/hyperion/MessageForwarder.h @@ -9,12 +9,19 @@ // QT includes #include #include +#include // Utils includes #include class MessageForwarder { public: + + struct JsonSlaveAddress { + QHostAddress addr; + quint16 port = 19444; + }; + MessageForwarder(); ~MessageForwarder(); @@ -23,9 +30,9 @@ public: void sendMessage(); QStringList getProtoSlaves(); + QList getJsonSlaves(); private: - bool _running; - - QStringList _protoSlaves; + QStringList _protoSlaves; + QList _jsonSlaves; }; diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index ed23fb30..2463ed15 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -275,13 +275,19 @@ MessageForwarder * Hyperion::createMessageForwarder(const Json::Value & forwarde if ( ! forwarderConfig["json"].isNull() && forwarderConfig["json"].isArray() ) { for (const Json::Value& addr : forwarderConfig["json"]) + { + std::cout << "Json forward to " << addr.asString() << std::endl; forwarder->addJsonSlave(addr.asString()); + } } if ( ! forwarderConfig["proto"].isNull() && forwarderConfig["proto"].isArray() ) { for (const Json::Value& addr : forwarderConfig["proto"]) + { + std::cout << "Proto forward to " << addr.asString() << std::endl; forwarder->addProtoSlave(addr.asString()); + } } } diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp index 8da277e2..be9c9825 100644 --- a/libsrc/hyperion/MessageForwarder.cpp +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -1,8 +1,7 @@ #include -MessageForwarder::MessageForwarder() : -_running(false) +MessageForwarder::MessageForwarder() { } @@ -13,7 +12,19 @@ MessageForwarder::~MessageForwarder() void MessageForwarder::addJsonSlave(std::string slave) { - std::cout << slave << std::endl; + QStringList parts = QString(slave.c_str()).split(":"); + if (parts.size() != 2) + throw std::runtime_error(QString("Wrong address: unable to parse address (%1)").arg(slave.c_str()).toStdString()); + + bool ok; + quint16 port = parts[1].toUShort(&ok); + if (!ok) + throw std::runtime_error(QString("Wrong address: Unable to parse the port number (%1)").arg(parts[1]).toStdString()); + + JsonSlaveAddress c; + c.addr = QHostAddress(parts[0]); + c.port = port; + _jsonSlaves << c; } void MessageForwarder::addProtoSlave(std::string slave) @@ -23,12 +34,14 @@ void MessageForwarder::addProtoSlave(std::string slave) void MessageForwarder::sendMessage() { - if ( ! _running ) - return; - } QStringList MessageForwarder::getProtoSlaves() { return _protoSlaves; } + +QList MessageForwarder::getJsonSlaves() +{ + return _jsonSlaves; +} diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 1b700b25..e4dbc096 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -16,6 +16,7 @@ // hyperion util includes #include #include +#include #include #include @@ -254,11 +255,16 @@ void JsonClientConnection::handleMessage(const std::string &messageString) void JsonClientConnection::forwardJsonMessage(const Json::Value & message) { QTcpSocket client; - client.connectToHost(QHostAddress("127.0.0.1"), 19444); - if ( client.waitForConnected(500) ) + QList list = _hyperion->getForwarder()->getJsonSlaves(); + + for ( int i=0; igetProtoSlaves(); for (int i = 0; i < slaves.size(); ++i) { - std::cout << "Proto forward to " << slaves.at(i).toLocal8Bit().constData() << std::endl; ProtoConnection* p = new ProtoConnection(slaves.at(i).toLocal8Bit().constData()); p->setSkipReply(true); _proxy_connections << p; From 2b1ac785d16da8c4dba39c5adc2585e95bf2fe66 Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 15 Feb 2016 21:21:56 +0100 Subject: [PATCH 73/96] add example configs Former-commit-id: 8176d915580bd0bd3d1604bcbf678f988e1d85d8 --- config/hyperion.config.json | 14 ++++++++++++++ config/hyperion_x86.config.json | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/config/hyperion.config.json b/config/hyperion.config.json index 0f8404a9..291086db 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -23,6 +23,20 @@ "colorOrder" : "rgb" }, + /// Configuration for message forwarding to other hyperions + /// protobuffer and json remote interface are forwarded to configured hosts + /// 'proto' is mostly used for video streams and 'json' for effects + /// + /// ** pay attention which port you use. use correct ports for protols ** + /// + /// * 'proto' : list of host in form of : + /// * 'json' : list of host in form of : +/// "forwarder" : +/// { +/// "proto" : [ "127.0.0.1:19445","192.168.178.88:19445" ], +/// "json" : [ "127.0.0.1:19444","192.168.178.88:19444" ] +/// }, + /// Color manipulation configuration used to tune the output colors to specific surroundings. /// The configuration contains a list of color-transforms. Each transform contains the /// following fields: diff --git a/config/hyperion_x86.config.json b/config/hyperion_x86.config.json index 4121c499..ec21a35b 100644 --- a/config/hyperion_x86.config.json +++ b/config/hyperion_x86.config.json @@ -19,6 +19,21 @@ "colorOrder" : "rgb" }, + /// Configuration for message forwarding to other hyperions + /// protobuffer and json remote interface are forwarded to configured hosts + /// 'proto' is mostly used for video streams and 'json' for effects + /// + /// ** pay attention which port you use. use correct ports for protols ** + /// + /// * 'proto' : list of host in form of : + /// * 'json' : list of host in form of : +/// "forwarder" : +/// { +/// "proto" : [ "127.0.0.1:19445","192.168.178.88:19445" ], +/// "json" : [ "127.0.0.1:19444","192.168.178.88:19444" ] +/// }, + + /// Color manipulation configuration used to tune the output colors to specific surroundings. /// The configuration contains a list of color-transforms. Each transform contains the /// following fields: From 7f5b141f435efb4747ca57412dd2732a1cb09741 Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 16 Feb 2016 14:16:59 +0100 Subject: [PATCH 74/96] forwarder: remove default init of port, could procude compile errors and it is not needed Former-commit-id: 08d7524a2cda53136ae8c72d5fdc1f95f51a23e7 --- include/hyperion/MessageForwarder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h index 0a3c1b19..9cc034fc 100644 --- a/include/hyperion/MessageForwarder.h +++ b/include/hyperion/MessageForwarder.h @@ -19,7 +19,7 @@ public: struct JsonSlaveAddress { QHostAddress addr; - quint16 port = 19444; + quint16 port; }; MessageForwarder(); From 738bafee994a266365d25b090ac3ede8c820d84e Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 16 Feb 2016 14:59:31 +0100 Subject: [PATCH 75/96] forwarder: add missing include Former-commit-id: 58d07b73ff1ad321a9cfbf73895b438665ce3c14 --- libsrc/hyperion/MessageForwarder.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp index be9c9825..1ae4bef6 100644 --- a/libsrc/hyperion/MessageForwarder.cpp +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -1,3 +1,6 @@ +// STL includes +#include + #include From 629461b944a94c55c02736b9a8ab28f23ff51e1a Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 16 Feb 2016 15:41:40 +0100 Subject: [PATCH 76/96] implement proto forwarding for hyperiond internal v4l2 grabber cleanup Former-commit-id: 669f139386633e3435cdc33639134819464afd4d --- include/grabber/V4L2Wrapper.h | 1 + include/hyperion/MessageForwarder.h | 1 - include/protoserver/ProtoServer.h | 7 +++ libsrc/grabber/v4l2/V4L2Wrapper.cpp | 3 ++ libsrc/hyperion/CMakeLists.txt | 2 +- libsrc/hyperion/MessageForwarder.cpp | 4 -- libsrc/protoserver/ProtoServer.cpp | 6 +++ src/hyperiond/hyperiond.cpp | 78 ++++++++++++++++------------ 8 files changed, 62 insertions(+), 40 deletions(-) diff --git a/include/grabber/V4L2Wrapper.h b/include/grabber/V4L2Wrapper.h index 2a9ece2c..2b8dc74a 100644 --- a/include/grabber/V4L2Wrapper.h +++ b/include/grabber/V4L2Wrapper.h @@ -44,6 +44,7 @@ public slots: signals: void emitColors(int priority, const std::vector &ledColors, const int timeout_ms); + void emitImage(int priority, const Image & image, const int timeout_ms); private slots: void newFrame(const Image & image); diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h index 9cc034fc..c9c27fe5 100644 --- a/include/hyperion/MessageForwarder.h +++ b/include/hyperion/MessageForwarder.h @@ -27,7 +27,6 @@ public: void addJsonSlave(std::string slave); void addProtoSlave(std::string slave); - void sendMessage(); QStringList getProtoSlaves(); QList getJsonSlaves(); diff --git a/include/protoserver/ProtoServer.h b/include/protoserver/ProtoServer.h index 1d530caa..520848a9 100644 --- a/include/protoserver/ProtoServer.h +++ b/include/protoserver/ProtoServer.h @@ -12,6 +12,10 @@ // Hyperion includes #include +// hyperion includes +#include +#include + // forward decl class ProtoClientConnection; class ProtoConnection; @@ -43,6 +47,9 @@ public: /// uint16_t getPort() const; +public slots: + void sendImageToProtoSlaves(int priority, const Image & image, int duration_ms); + private slots: /// /// Slot which is called when a client tries to create a new connection diff --git a/libsrc/grabber/v4l2/V4L2Wrapper.cpp b/libsrc/grabber/v4l2/V4L2Wrapper.cpp index 76b16ab7..cbccf41b 100644 --- a/libsrc/grabber/v4l2/V4L2Wrapper.cpp +++ b/libsrc/grabber/v4l2/V4L2Wrapper.cpp @@ -94,6 +94,9 @@ void V4L2Wrapper::newFrame(const Image &image) // process the new image _processor->process(image, _ledColors); + // forward to other hyperions + emit emitImage(_priority, image, _timeout_ms); + // send colors to Hyperion emit emitColors(_priority, _ledColors, _timeout_ms); } diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 3a277a7e..ebd25254 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -6,7 +6,6 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion) # Group the headers that go through the MOC compiler SET(Hyperion_QT_HEADERS ${CURRENT_HEADER_DIR}/Hyperion.h - ${CURRENT_HEADER_DIR}/MessageForwarder.h ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h ) @@ -19,6 +18,7 @@ SET(Hyperion_HEADERS ${CURRENT_HEADER_DIR}/PriorityMuxer.h ${CURRENT_SOURCE_DIR}/MultiColorTransform.h + ${CURRENT_HEADER_DIR}/MessageForwarder.h ) SET(Hyperion_SOURCES diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp index 1ae4bef6..09bcf685 100644 --- a/libsrc/hyperion/MessageForwarder.cpp +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -35,10 +35,6 @@ void MessageForwarder::addProtoSlave(std::string slave) _protoSlaves << QString(slave.c_str()); } -void MessageForwarder::sendMessage() -{ -} - QStringList MessageForwarder::getProtoSlaves() { return _protoSlaves; diff --git a/libsrc/protoserver/ProtoServer.cpp b/libsrc/protoserver/ProtoServer.cpp index ca1b6358..03c334d4 100644 --- a/libsrc/protoserver/ProtoServer.cpp +++ b/libsrc/protoserver/ProtoServer.cpp @@ -70,6 +70,12 @@ void ProtoServer::newMessage(const proto::HyperionRequest * message) _proxy_connections.at(i)->sendMessage(*message); } +void ProtoServer::sendImageToProtoSlaves(int priority, const Image & image, int duration_ms) +{ + for (int i = 0; i < _proxy_connections.size(); ++i) + _proxy_connections.at(i)->setImage(image, priority, duration_ms); +} + void ProtoServer::closedConnection(ProtoClientConnection *connection) { std::cout << "Proto connection closed" << std::endl; diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 7bb5e60e..fe24762a 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -189,6 +189,39 @@ int main(int argc, char** argv) std::cout << "XBMC video checker created and started" << std::endl; } +// ---- network services ----- + + // Create Json server if configuration is present + JsonServer * jsonServer = nullptr; + if (config.isMember("jsonServer")) + { + const Json::Value & jsonServerConfig = config["jsonServer"]; + jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt()); + std::cout << "Json server created and started on port " << jsonServer->getPort() << std::endl; + } + +#ifdef ENABLE_PROTOBUF + // Create Proto server if configuration is present + ProtoServer * protoServer = nullptr; + if (config.isMember("protoServer")) + { + const Json::Value & protoServerConfig = config["protoServer"]; + protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); + std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl; + } +#endif + + // Create Boblight server if configuration is present + BoblightServer * boblightServer = nullptr; + if (config.isMember("boblightServer")) + { + const Json::Value & boblightServerConfig = config["boblightServer"]; + boblightServer = new BoblightServer(&hyperion, boblightServerConfig["port"].asUInt()); + std::cout << "Boblight server created and started on port " << boblightServer->getPort() << std::endl; + } + +// ---- grabber ----- + #ifdef ENABLE_DISPMANX // Construct and start the frame-grabber if the configuration is present DispmanxWrapper * dispmanx = nullptr; @@ -214,7 +247,7 @@ int main(int argc, char** argv) #if !defined(ENABLE_OSX) && !defined(ENABLE_FB) if (config.isMember("framegrabber")) { - std::cerr << "The dispmanx framegrabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The dispmanx framegrabber can not be instantiated, because it has been left out from the build" << std::endl; } #endif #endif @@ -246,14 +279,19 @@ int main(int argc, char** argv) grabberConfig.get("cropTop", 0).asInt(), grabberConfig.get("cropBottom", 0).asInt()); + #ifdef ENABLE_PROTOBUF + QObject::connect(v4l2Grabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif + v4l2Grabber->start(); std::cout << "V4l2 grabber created and started" << std::endl; } #else if (config.isMember("grabber-v4l2")) { - std::cerr << "The v4l2 grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The v4l2 grabber can not be instantiated, because it has been left out from the build" << std::endl; } + #endif #ifdef ENABLE_AMLOGIC @@ -309,12 +347,12 @@ int main(int argc, char** argv) #else if (config.isMember("framebuffergrabber")) { - std::cerr << "The framebuffer grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The framebuffer grabber can not be instantiated, because it has been left out from the build" << std::endl; } #if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX) else if (config.isMember("framegrabber")) { - std::cerr << "The framebuffer grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The framebuffer grabber can not be instantiated, because it has been left out from the build" << std::endl; } #endif #endif @@ -344,44 +382,16 @@ int main(int argc, char** argv) #else if (config.isMember("osxgrabber")) { - std::cerr << "The osx grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The osx grabber can not be instantiated, because it has been left out from the build" << std::endl; } #if !defined(ENABLE_DISPMANX) && !defined(ENABLE_FB) else if (config.isMember("framegrabber")) { - std::cerr << "The osx grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The osx grabber can not be instantiated, because it has been left out from the build" << std::endl; } #endif #endif - // Create Json server if configuration is present - JsonServer * jsonServer = nullptr; - if (config.isMember("jsonServer")) - { - const Json::Value & jsonServerConfig = config["jsonServer"]; - jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt()); - std::cout << "Json server created and started on port " << jsonServer->getPort() << std::endl; - } - -#ifdef ENABLE_PROTOBUF - // Create Proto server if configuration is present - ProtoServer * protoServer = nullptr; - if (config.isMember("protoServer")) - { - const Json::Value & protoServerConfig = config["protoServer"]; - protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); - std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl; - } -#endif - - // Create Boblight server if configuration is present - BoblightServer * boblightServer = nullptr; - if (config.isMember("boblightServer")) - { - const Json::Value & boblightServerConfig = config["boblightServer"]; - boblightServer = new BoblightServer(&hyperion, boblightServerConfig["port"].asUInt()); - std::cout << "Boblight server created and started on port " << boblightServer->getPort() << std::endl; - } // run the application int rc = app.exec(); From 46c5a2ec051b68ea7d1c774062e04bb5d71c8b63 Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 16 Feb 2016 15:56:20 +0100 Subject: [PATCH 77/96] use correct include for std::runtime_error Former-commit-id: a96b727cc0258fda9684f5df52084dd8d96068e3 --- libsrc/hyperion/MessageForwarder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp index 09bcf685..2e277fc8 100644 --- a/libsrc/hyperion/MessageForwarder.cpp +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -1,5 +1,5 @@ // STL includes -#include +#include #include From a9e8f0264a0b6a1262b99e59dfb0b6d4cd854488 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 17 Feb 2016 00:44:06 +0100 Subject: [PATCH 78/96] implement proto forwarding for osxgrabber and framebuffer. prepare forwarding in amlogic and dispmanx Former-commit-id: d67fc2b7fe8877e6eadf31a8c76e4a68110c6680 --- include/grabber/DispmanxWrapper.h | 3 +++ include/grabber/FramebufferWrapper.h | 3 +++ include/grabber/OsxWrapper.h | 3 +++ libsrc/grabber/dispmanx/DispmanxWrapper.cpp | 4 +++- libsrc/grabber/framebuffer/FramebufferWrapper.cpp | 3 ++- libsrc/grabber/osx/OsxWrapper.cpp | 3 ++- libsrc/leddevice/LedDeviceFadeCandy.cpp | 2 +- src/hyperiond/hyperiond.cpp | 12 ++++++++++++ 8 files changed, 29 insertions(+), 4 deletions(-) diff --git a/include/grabber/DispmanxWrapper.h b/include/grabber/DispmanxWrapper.h index 4868c1a0..2df81340 100644 --- a/include/grabber/DispmanxWrapper.h +++ b/include/grabber/DispmanxWrapper.h @@ -68,6 +68,9 @@ public slots: /// void setVideoMode(const VideoMode videoMode); +signals: + void emitImage(int priority, const Image & image, const int timeout_ms); + private: /// The update rate [Hz] const int _updateInterval_ms; diff --git a/include/grabber/FramebufferWrapper.h b/include/grabber/FramebufferWrapper.h index f633ae55..75252d24 100644 --- a/include/grabber/FramebufferWrapper.h +++ b/include/grabber/FramebufferWrapper.h @@ -68,6 +68,9 @@ public slots: /// void setVideoMode(const VideoMode videoMode); +signals: + void emitImage(int priority, const Image & image, const int timeout_ms); + private: /// The update rate [Hz] const int _updateInterval_ms; diff --git a/include/grabber/OsxWrapper.h b/include/grabber/OsxWrapper.h index 39ac1a7e..fa597c67 100644 --- a/include/grabber/OsxWrapper.h +++ b/include/grabber/OsxWrapper.h @@ -69,6 +69,9 @@ public slots: /// void setVideoMode(const VideoMode videoMode); +signals: + void emitImage(int priority, const Image & image, const int timeout_ms); + private: /// The update rate [Hz] const int _updateInterval_ms; diff --git a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp index c9d2b22c..84657fc8 100644 --- a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp +++ b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp @@ -51,10 +51,12 @@ void DispmanxWrapper::action() // Grab frame into the allocated image _frameGrabber->grabFrame(_image); - _processor->process(_image, _ledColors); + //emit emitImage(_priority, _image, _timeout_ms); + _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); } + void DispmanxWrapper::stop() { // Stop the timer, effectivly stopping the process diff --git a/libsrc/grabber/framebuffer/FramebufferWrapper.cpp b/libsrc/grabber/framebuffer/FramebufferWrapper.cpp index abc6400c..96506d55 100644 --- a/libsrc/grabber/framebuffer/FramebufferWrapper.cpp +++ b/libsrc/grabber/framebuffer/FramebufferWrapper.cpp @@ -46,8 +46,9 @@ void FramebufferWrapper::action() // Grab frame into the allocated image _frameGrabber->grabFrame(_image); - _processor->process(_image, _ledColors); + emit emitImage(_priority, _image, _timeout_ms); + _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); } void FramebufferWrapper::stop() diff --git a/libsrc/grabber/osx/OsxWrapper.cpp b/libsrc/grabber/osx/OsxWrapper.cpp index 6d6f9a00..da8b039e 100644 --- a/libsrc/grabber/osx/OsxWrapper.cpp +++ b/libsrc/grabber/osx/OsxWrapper.cpp @@ -46,8 +46,9 @@ void OsxWrapper::action() // Grab frame into the allocated image _frameGrabber->grabFrame(_image); - _processor->process(_image, _ledColors); + emit emitImage(_priority, _image, _timeout_ms); + _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); } void OsxWrapper::stop() diff --git a/libsrc/leddevice/LedDeviceFadeCandy.cpp b/libsrc/leddevice/LedDeviceFadeCandy.cpp index 685795a9..2e6a1411 100755 --- a/libsrc/leddevice/LedDeviceFadeCandy.cpp +++ b/libsrc/leddevice/LedDeviceFadeCandy.cpp @@ -1,6 +1,6 @@ #include "LedDeviceFadeCandy.h" -static const unsigned MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds +static const signed MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds static const unsigned OPC_SET_PIXELS = 0; // OPC command codes static const unsigned OPC_HEADER_SIZE = 4; // OPC header size diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index fe24762a..b300aefc 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -240,6 +240,10 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), dispmanx, SLOT(setVideoMode(VideoMode))); } + #ifdef ENABLE_PROTOBUF + QObject::connect(dispmanx, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif + dispmanx->start(); std::cout << "Frame grabber created and started" << std::endl; } @@ -341,6 +345,10 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), fbGrabber, SLOT(setVideoMode(VideoMode))); } + #ifdef ENABLE_PROTOBUF + QObject::connect(fbGrabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif + fbGrabber->start(); std::cout << "Framebuffer grabber created and started" << std::endl; } @@ -375,6 +383,10 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), osxGrabber, SLOT(setGrabbingMode(GrabbingMode))); QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), osxGrabber, SLOT(setVideoMode(VideoMode))); } + + #ifdef ENABLE_PROTOBUF + QObject::connect(osxGrabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif osxGrabber->start(); std::cout << "OSX grabber created and started" << std::endl; From 0f17e031e85dc7359ce1a0cbb842b07d2b2aa82a Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 18 Feb 2016 10:32:38 +0100 Subject: [PATCH 79/96] basic loop connection detection. prevent if you configure forward to 127.0.0.1: and your server has the same port. But this doesn't protect if not forwarded to localhost "127.0.0.1". Loop connections across different hosts arn't detected too. Former-commit-id: 464a80708ebd11c0f7c83dc87a1afe0f10e0e078 --- libsrc/jsonserver/JsonServer.cpp | 8 ++++++++ libsrc/protoserver/ProtoServer.cpp | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/libsrc/jsonserver/JsonServer.cpp b/libsrc/jsonserver/JsonServer.cpp index 4efe855c..4cd7f411 100644 --- a/libsrc/jsonserver/JsonServer.cpp +++ b/libsrc/jsonserver/JsonServer.cpp @@ -16,6 +16,14 @@ JsonServer::JsonServer(Hyperion *hyperion, uint16_t port) : throw std::runtime_error("Json server could not bind to port"); } + QList list = _hyperion->getForwarder()->getJsonSlaves(); + for ( int i=0; igetProtoSlaves(); for (int i = 0; i < slaves.size(); ++i) { + if ( QString("127.0.0.1:%1").arg(port) == slaves.at(i) ) { + throw std::runtime_error("Loop between proto server and forwarder detected. Fix your config!"); + } + ProtoConnection* p = new ProtoConnection(slaves.at(i).toLocal8Bit().constData()); p->setSkipReply(true); _proxy_connections << p; From 736d841567f3e482f2d8f9d2e00c6908be8b05e8 Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 18 Feb 2016 23:32:42 +0100 Subject: [PATCH 80/96] update rpi bins Former-commit-id: 851c37754b2e9a020d9a82c90438db96988f472d --- deploy/hyperion_rpi.tar.gz.REMOVED.git-id | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id index 44bbdc58..94286a16 100644 --- a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id @@ -1 +1 @@ -5c164e4ff52076a530461cdf6966943d52cd39df \ No newline at end of file +d6c2a97271d37ffb04fa2e1e9ce7812d5b132811 \ No newline at end of file From ec67caf24ed3d7d9f457190f294a92e12865a024 Mon Sep 17 00:00:00 2001 From: redpanther Date: Fri, 19 Feb 2016 13:31:08 +0100 Subject: [PATCH 81/96] add ability to convert an image to RGB color order forwarder: add flag to detect if forwarding is enabled Former-commit-id: c814651ec4973fe3b2bfca7c0370a0bac752f025 --- include/hyperion/MessageForwarder.h | 3 ++- include/utils/Image.h | 21 ++++++++++++++++++ libsrc/hyperion/MessageForwarder.cpp | 5 +++++ test/TestRgbImage.cpp | 32 ++++++++++++++++++++++------ 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h index c9c27fe5..a762ae41 100644 --- a/include/hyperion/MessageForwarder.h +++ b/include/hyperion/MessageForwarder.h @@ -27,7 +27,8 @@ public: void addJsonSlave(std::string slave); void addProtoSlave(std::string slave); - + + bool protoForwardingEnabled(); QStringList getProtoSlaves(); QList getJsonSlaves(); diff --git a/include/utils/Image.h b/include/utils/Image.h index 0a8ca31a..ece6155a 100644 --- a/include/utils/Image.h +++ b/include/utils/Image.h @@ -5,6 +5,8 @@ #include #include #include +#include + template class Image @@ -183,6 +185,25 @@ public: { return _pixels; } + + + /// + /// Convert image of any color order to a RGB image. + /// + /// @param[out] image The image that buffers the output + /// + void toRgb(Image& image) + { + image.resize(_width, _height); + const unsigned imageSize = _width * _height; + + for (unsigned idx=0; idx MessageForwarder::getJsonSlaves() { return _jsonSlaves; } + +bool MessageForwarder::protoForwardingEnabled() +{ + return ! _protoSlaves.empty(); +} diff --git a/test/TestRgbImage.cpp b/test/TestRgbImage.cpp index 374408f5..67773763 100644 --- a/test/TestRgbImage.cpp +++ b/test/TestRgbImage.cpp @@ -4,22 +4,42 @@ // Utils includes #include +#include #include +#include +#include int main() { std::cout << "Constructing image" << std::endl; - Image image(64, 64, ColorRgb::BLACK); + int width = 64; + int height = 64; + Image image_rgb(width, height, ColorRgb::BLACK); + Image image_bgr(image_rgb.width(), image_rgb.height(), ColorBgr::BLACK); std::cout << "Writing image" << std::endl; - for (unsigned y=0; y<64; ++y) + unsigned l = width * height; + + // BGR + for (unsigned i=0; i Date: Tue, 23 Feb 2016 21:17:03 +0100 Subject: [PATCH 82/96] Switched flag from soft to hard float Former-commit-id: 98053c8eba7f4f811cbbd63aad5b1210236b2556 --- Toolchain-imx6.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Toolchain-imx6.cmake b/Toolchain-imx6.cmake index 6ca757a7..3afbeaed 100644 --- a/Toolchain-imx6.cmake +++ b/Toolchain-imx6.cmake @@ -6,8 +6,8 @@ SET(CMAKE_SYSTEM_VERSION 1) # specify the cross compiler SET(CMAKE_C_COMPILER ${CUBIXCROSS_DIR}/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin/arm-linux-gnueabihf-gcc) SET(CMAKE_CXX_COMPILER ${CUBIXCROSS_DIR}/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin/arm-linux-gnueabihf-g++) -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=vfpv3 -mfloat-abi=softfp") -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=vfpv3 -mfloat-abi=softfp") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard") # where is the target environment SET(CMAKE_FIND_ROOT_PATH ${CUBIXCROSS_DIR}/rootfs) From dea32ebc2b5482d9428e2f905493518a62b5871c Mon Sep 17 00:00:00 2001 From: "T.van der Zwan" Date: Tue, 23 Feb 2016 21:17:55 +0100 Subject: [PATCH 83/96] Updated all releases Former-commit-id: b18a9a48f977eaed128d9d641e349e98113ab24b --- deploy/hyperion_imx6.tar.gz.REMOVED.git-id | 2 +- deploy/hyperion_rpi.tar.gz.REMOVED.git-id | 2 +- deploy/hyperion_wetek.tar.gz.REMOVED.git-id | 2 +- deploy/hyperion_x32.tar.gz.REMOVED.git-id | 2 +- deploy/hyperion_x64.tar.gz.REMOVED.git-id | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy/hyperion_imx6.tar.gz.REMOVED.git-id b/deploy/hyperion_imx6.tar.gz.REMOVED.git-id index 99536c87..882af089 100644 --- a/deploy/hyperion_imx6.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_imx6.tar.gz.REMOVED.git-id @@ -1 +1 @@ -471d676fb66aa53e3b10d887a1d9e6d3b4afea90 \ No newline at end of file +44d552b5adb3dc5af38edd5e6fb208a0dc75d63d \ No newline at end of file diff --git a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id index 9c96bfd2..f3692ead 100644 --- a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id @@ -1 +1 @@ -d079238ea69f0fb1422e9d7181016d4e290c12d5 \ No newline at end of file +5b0f057a8591d76be009018b302977faeec5159a \ No newline at end of file diff --git a/deploy/hyperion_wetek.tar.gz.REMOVED.git-id b/deploy/hyperion_wetek.tar.gz.REMOVED.git-id index 668065d1..4f6eb81f 100644 --- a/deploy/hyperion_wetek.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_wetek.tar.gz.REMOVED.git-id @@ -1 +1 @@ -d2bf44cca4e7753b53acc2ebbdb933ba8f74f93f \ No newline at end of file +7f0d60e7e0c7075cae5cef69ec5408f3087c00df \ No newline at end of file diff --git a/deploy/hyperion_x32.tar.gz.REMOVED.git-id b/deploy/hyperion_x32.tar.gz.REMOVED.git-id index 89355ddf..4866065e 100644 --- a/deploy/hyperion_x32.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_x32.tar.gz.REMOVED.git-id @@ -1 +1 @@ -7936b39302bec31b18f11a321ba6904c12b5c3ec \ No newline at end of file +511ab205cce688c5d7151087d8659905402e5015 \ No newline at end of file diff --git a/deploy/hyperion_x64.tar.gz.REMOVED.git-id b/deploy/hyperion_x64.tar.gz.REMOVED.git-id index 38e3e0b0..812ded3c 100644 --- a/deploy/hyperion_x64.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_x64.tar.gz.REMOVED.git-id @@ -1 +1 @@ -774c67bd8e4e46d2ebf9c223a38fdfd93cae1100 \ No newline at end of file +e26ac1a0bf52bcd54ab00c37ff25d01a457eec9d \ No newline at end of file From 63e150756dbb514a5c8f0b887fbf1ca3200d7693 Mon Sep 17 00:00:00 2001 From: tpmodding Date: Wed, 24 Feb 2016 00:24:46 +0100 Subject: [PATCH 84/96] Update CMakeLists.txt If you want to compile for OpenElec on Raspberry Pi, you must use Python 2.7 Former-commit-id: 813a997161461b90626359e2e23149f8fab59fbf --- libsrc/effectengine/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libsrc/effectengine/CMakeLists.txt b/libsrc/effectengine/CMakeLists.txt index 619b691d..adb430e0 100644 --- a/libsrc/effectengine/CMakeLists.txt +++ b/libsrc/effectengine/CMakeLists.txt @@ -1,5 +1,7 @@ find_package(PythonLibs REQUIRED) +#OpenElec uses 2.7, if you want to compile for OpenElec require 2.7 +#find_package(PythonLibs 2.7 REQUIRED) # Include the python directory. Also include the parent (which is for example /usr/include) # which may be required when it is not includes by the (cross-) compiler by default. From 6bef43887bca62253c99413ac94fa3f936d040fd Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 14:34:19 +0100 Subject: [PATCH 85/96] implement dispmanx forwarding a a separate dispmanx wrapper implement forwarding for amlogic grabber Former-commit-id: 8a793d24bd083f9eca07c34ec3b222f0e54b4426 --- include/grabber/AmlogicWrapper.h | 6 ++ .../grabber}/DispmanxFrameGrabber.h | 0 include/grabber/DispmanxWrapper.h | 3 + libsrc/grabber/amlogic/AmlogicWrapper.cpp | 9 +- libsrc/grabber/dispmanx/CMakeLists.txt | 81 ++++++++-------- .../grabber/dispmanx/DispmanxFrameGrabber.cpp | 2 +- libsrc/grabber/dispmanx/DispmanxWrapper.cpp | 10 +- src/CMakeLists.txt | 5 + src/hyperion-dispmanx/CMakeLists.txt | 70 ++++++++++++++ src/hyperion-dispmanx/DispmanxWrapper.cpp | 38 ++++++++ src/hyperion-dispmanx/DispmanxWrapper.h | 42 +++++++++ src/hyperion-dispmanx/hyperion-dispmanx.cpp | 92 +++++++++++++++++++ 12 files changed, 314 insertions(+), 44 deletions(-) rename {libsrc/grabber/dispmanx => include/grabber}/DispmanxFrameGrabber.h (100%) create mode 100644 src/hyperion-dispmanx/CMakeLists.txt create mode 100644 src/hyperion-dispmanx/DispmanxWrapper.cpp create mode 100644 src/hyperion-dispmanx/DispmanxWrapper.h create mode 100644 src/hyperion-dispmanx/hyperion-dispmanx.cpp diff --git a/include/grabber/AmlogicWrapper.h b/include/grabber/AmlogicWrapper.h index 0ce70b80..c712b60e 100644 --- a/include/grabber/AmlogicWrapper.h +++ b/include/grabber/AmlogicWrapper.h @@ -68,6 +68,9 @@ public slots: /// void setVideoMode(const VideoMode videoMode); +signals: + void emitImage(int priority, const Image & image, const int timeout_ms); + private: /// The update rate [Hz] const int _updateInterval_ms; @@ -91,4 +94,7 @@ private: /// Pointer to Hyperion for writing led values Hyperion * _hyperion; + + // forwarding enabled + bool _forward; }; diff --git a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.h b/include/grabber/DispmanxFrameGrabber.h similarity index 100% rename from libsrc/grabber/dispmanx/DispmanxFrameGrabber.h rename to include/grabber/DispmanxFrameGrabber.h diff --git a/include/grabber/DispmanxWrapper.h b/include/grabber/DispmanxWrapper.h index 2df81340..e64adf47 100644 --- a/include/grabber/DispmanxWrapper.h +++ b/include/grabber/DispmanxWrapper.h @@ -94,4 +94,7 @@ private: /// Pointer to Hyperion for writing led values Hyperion * _hyperion; + + // forwarding enabled + bool _forward; }; diff --git a/libsrc/grabber/amlogic/AmlogicWrapper.cpp b/libsrc/grabber/amlogic/AmlogicWrapper.cpp index 1dca6764..b77f1612 100644 --- a/libsrc/grabber/amlogic/AmlogicWrapper.cpp +++ b/libsrc/grabber/amlogic/AmlogicWrapper.cpp @@ -26,6 +26,7 @@ AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeig // Configure the timer to generate events every n milliseconds _timer.setInterval(_updateInterval_ms); _timer.setSingleShot(false); + _forward = _hyperion->getForwarder()->protoForwardingEnabled(); _processor->setSize(grabWidth, grabHeight); @@ -55,8 +56,14 @@ void AmlogicWrapper::action() return; } - _processor->process(_image, _ledColors); + if ( _forward ) + { + Image image_rgb; + _image.toRgb(image_rgb); + emit emitImage(_priority, image_rgb, _timeout_ms); + } + _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); } diff --git a/libsrc/grabber/dispmanx/CMakeLists.txt b/libsrc/grabber/dispmanx/CMakeLists.txt index d4d64b72..27c1f11c 100644 --- a/libsrc/grabber/dispmanx/CMakeLists.txt +++ b/libsrc/grabber/dispmanx/CMakeLists.txt @@ -1,40 +1,41 @@ - -# Find the BCM-package (VC control) -find_package(BCM REQUIRED) -include_directories(${BCM_INCLUDE_DIRS}) - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx) - -# Group the headers that go through the MOC compiler -SET(DispmanxGrabberQT_HEADERS - ${CURRENT_HEADER_DIR}/DispmanxWrapper.h -) - -SET(DispmanxGrabberHEADERS - ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.h -) - -SET(DispmanxGrabberSOURCES - ${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp - ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp -) - -if(ENABLE_QT5) -QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) -else(ENABLE_QT5) -QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) -endif(ENABLE_QT5) - -add_library(dispmanx-grabber - ${DispmanxGrabberHEADERS} - ${DispmanxGrabberQT_HEADERS} - ${DispmanxGrabberHEADERS_MOC} - ${DispmanxGrabberSOURCES} -) - -target_link_libraries(dispmanx-grabber - hyperion - ${QT_LIBRARIES} - ${BCM_LIBRARIES}) + +# Find the BCM-package (VC control) +find_package(BCM REQUIRED) +include_directories(${BCM_INCLUDE_DIRS}) + +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx) + +# Group the headers that go through the MOC compiler +SET(DispmanxGrabberQT_HEADERS + ${CURRENT_HEADER_DIR}/DispmanxWrapper.h +) + +SET(DispmanxGrabberHEADERS + ${CURRENT_HEADER_DIR}/DispmanxFrameGrabber.h +) + +SET(DispmanxGrabberSOURCES + ${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp + ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp +) + +if(ENABLE_QT5) + QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) +else(ENABLE_QT5) + QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) +endif(ENABLE_QT5) + +add_library(dispmanx-grabber + ${DispmanxGrabberHEADERS} + ${DispmanxGrabberQT_HEADERS} + ${DispmanxGrabberHEADERS_MOC} + ${DispmanxGrabberSOURCES} +) + +target_link_libraries(dispmanx-grabber + hyperion + ${QT_LIBRARIES} + ${BCM_LIBRARIES} +) diff --git a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp index 1f6516a4..53397acf 100644 --- a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp +++ b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp @@ -4,7 +4,7 @@ #include // Local includes -#include "DispmanxFrameGrabber.h" +#include "grabber/DispmanxFrameGrabber.h" DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned height) : _vc_display(0), diff --git a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp index 84657fc8..7868ce34 100644 --- a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp +++ b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp @@ -9,7 +9,7 @@ // Dispmanx grabber includes #include -#include "DispmanxFrameGrabber.h" +#include DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion) : @@ -28,6 +28,7 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe _timer.setSingleShot(false); _processor->setSize(grabWidth, grabHeight); + _forward = _hyperion->getForwarder()->protoForwardingEnabled(); // Connect the QTimer to this QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(action())); @@ -51,7 +52,12 @@ void DispmanxWrapper::action() // Grab frame into the allocated image _frameGrabber->grabFrame(_image); - //emit emitImage(_priority, _image, _timeout_ms); + if ( _forward ) + { + Image image_rgb; + _image.toRgb(image_rgb); + emit emitImage(_priority, image_rgb, _timeout_ms); + } _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a291850..f55af750 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,4 +15,9 @@ if(ENABLE_PROTOBUF) if(ENABLE_X11) add_subdirectory(hyperion-x11) endif() + + if(ENABLE_DISPMANX) + add_subdirectory(hyperion-dispmanx) + endif() + endif() diff --git a/src/hyperion-dispmanx/CMakeLists.txt b/src/hyperion-dispmanx/CMakeLists.txt new file mode 100644 index 00000000..4d48174e --- /dev/null +++ b/src/hyperion-dispmanx/CMakeLists.txt @@ -0,0 +1,70 @@ +# Configure minimum CMAKE version +cmake_minimum_required(VERSION 2.8) + +# Set the project name +project(hyperion-dispmanx) + +if(ENABLE_QT5) + find_package(Qt5Widgets REQUIRED) +else(ENABLE_QT5) + # find Qt4 + find_package(Qt4 REQUIRED QtCore QtGui QtNetwork ) +endif(ENABLE_QT5) + +# Find the BCM-package (VC control) +#find_package(BCM REQUIRED) +SET( BCM_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/dependencies/external/rapsi_vc ) +SET( BCM_LIBRARIES "" ) +ADD_DEFINITIONS ( -DDISPMANX_DUMMY ) + + + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver + ${QT_INCLUDES} + ${BCM_INCLUDE_DIRS} + ${PROTOBUF_INCLUDE_DIRS} +) + +set(Hyperion_Dispmanx_QT_HEADERS + DispmanxWrapper.h) + +set(Hyperion_Dispmanx_HEADERS +) + +set(Hyperion_Dispmanx_SOURCES + hyperion-dispmanx.cpp + DispmanxWrapper.cpp +) + +if(ENABLE_QT5) + QT5_WRAP_CPP(Hyperion_Dispmanx_HEADERS_MOC ${Hyperion_Dispmanx_QT_HEADERS}) +else(ENABLE_QT5) + QT4_WRAP_CPP(Hyperion_Dispmanx_HEADERS_MOC ${Hyperion_Dispmanx_QT_HEADERS}) +endif(ENABLE_QT5) + +add_executable( ${PROJECT_NAME} + ${Hyperion_Dispmanx_HEADERS} + ${Hyperion_Dispmanx_SOURCES} + ${Hyperion_Dispmanx_HEADERS_MOC} +) + +target_link_libraries( ${PROJECT_NAME} + getoptPlusPlus + blackborder + hyperion-utils + protoserver + dispmanx-grabber + ${Dispmanx_LIBRARIES} + pthread +) + +if(ENABLE_QT5) + qt5_use_modules(hyperion-dispmanx Widgets Core Gui Network) +else(ENABLE_QT5) + qt4_use_modules(hyperion-dispmanx + Core + Gui + Network + ) +endif(ENABLE_QT5) diff --git a/src/hyperion-dispmanx/DispmanxWrapper.cpp b/src/hyperion-dispmanx/DispmanxWrapper.cpp new file mode 100644 index 00000000..b11830a7 --- /dev/null +++ b/src/hyperion-dispmanx/DispmanxWrapper.cpp @@ -0,0 +1,38 @@ + +// Hyperion-X11 includes +#include "DispmanxWrapper.h" + +DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : + _timer(this), + _grabber(grabWidth, grabHeight) +{ + _timer.setSingleShot(false); + _timer.setInterval(updateRate_Hz); + + // Connect capturing to the timeout signal of the timer + connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); +} + +const Image & DispmanxWrapper::getScreenshot() +{ + capture(); + return _screenshot_rgb; +} + +void DispmanxWrapper::start() +{ + _timer.start(); +} + +void DispmanxWrapper::stop() +{ + _timer.stop(); +} + +void DispmanxWrapper::capture() +{ + _grabber.grabFrame(_screenshot); + _screenshot.toRgb(_screenshot_rgb); + + emit sig_screenshot(_screenshot_rgb); +} diff --git a/src/hyperion-dispmanx/DispmanxWrapper.h b/src/hyperion-dispmanx/DispmanxWrapper.h new file mode 100644 index 00000000..827a4d53 --- /dev/null +++ b/src/hyperion-dispmanx/DispmanxWrapper.h @@ -0,0 +1,42 @@ + +// QT includes +#include + +// Hyperion-Dispmanx includes +#include + +class DispmanxWrapper : public QObject +{ + Q_OBJECT +public: + DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); + + const Image & getScreenshot(); + + /// + /// Starts the timed capturing of screenshots + /// + void start(); + + void stop(); + +signals: + void sig_screenshot(const Image & screenshot); + +private slots: + /// + /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot + /// signal. + /// + void capture(); + +private: + /// The QT timer to generate capture-publish events + QTimer _timer; + + /// The grabber for creating screenshots + DispmanxFrameGrabber _grabber; + Image _screenshot_rgb; + Image _screenshot; + +}; diff --git a/src/hyperion-dispmanx/hyperion-dispmanx.cpp b/src/hyperion-dispmanx/hyperion-dispmanx.cpp new file mode 100644 index 00000000..c7d5fe0e --- /dev/null +++ b/src/hyperion-dispmanx/hyperion-dispmanx.cpp @@ -0,0 +1,92 @@ + +// QT includes +#include +#include + +// getoptPlusPLus includes +#include + +#include "protoserver/ProtoConnectionWrapper.h" +#include "DispmanxWrapper.h" + +using namespace vlofgren; + +// save the image as screenshot +void saveScreenshot(const char * filename, const Image & image) +{ + // store as PNG + QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); + pngImage.save(filename); +} + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + + try + { + // create the option parser and initialize all parameters + OptionsParser optionParser("Dispmanx capture application for Hyperion"); + ParameterSet & parameters = optionParser.getParameters(); + + IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); + IntParameter & argWidth = parameters.add (0x0, "width", "The width of the grabbed frames [pixels]"); + IntParameter & argHeight = parameters.add (0x0, "height", "The height of the grabbed frames"); + + SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); + StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); + IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); + SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); + SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); + + // set defaults + argFps.setDefault(10); + argWidth.setDefault(64); + argHeight.setDefault(64); + argAddress.setDefault("127.0.0.1:19445"); + argPriority.setDefault(800); + + // parse all options + optionParser.parse(argc, const_cast(argv)); + + // check if we need to display the usage. exit if we do. + if (argHelp.isSet()) + { + optionParser.usage(); + return 0; + } + + // Create the dispmanx grabbing stuff + int grabInterval = 1000 / argFps.getValue(); + DispmanxWrapper dispmanxWrapper(argWidth.getValue(),argHeight.getValue(),grabInterval); + + if (argScreenshot.isSet()) + { + // Capture a single screenshot and finish + const Image & screenshot = dispmanxWrapper.getScreenshot(); + saveScreenshot("screenshot.png", screenshot); + } + else + { + // Create the Proto-connection with hyperiond + ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); + + // Connect the screen capturing to the proto processing + QObject::connect(&dispmanxWrapper, SIGNAL(sig_screenshot(const Image &)), &protoWrapper, SLOT(receiveImage(Image))); + + // Start the capturing + dispmanxWrapper.start(); + + // Start the application + app.exec(); + } + } + catch (const std::runtime_error & e) + { + // An error occured. Display error and quit + std::cerr << e.what() << std::endl; + return -1; + } + + return 0; +} From 8fdf97e6934138b91e7e2950f1f2fb2c53a13842 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 14:42:25 +0100 Subject: [PATCH 86/96] prepare standalone amlogic grabber activate internal amlogic grabber forwarding Former-commit-id: 21dabf759935836eef556baeb8a27e362e95ae96 --- {libsrc/grabber/amlogic => include/grabber}/AmlogicGrabber.h | 0 libsrc/grabber/amlogic/AmlogicGrabber.cpp | 2 +- libsrc/grabber/amlogic/AmlogicWrapper.cpp | 2 +- libsrc/grabber/amlogic/CMakeLists.txt | 2 +- src/hyperion-aml/hyperion-aml.cpp | 2 +- src/hyperiond/hyperiond.cpp | 4 ++++ 6 files changed, 8 insertions(+), 4 deletions(-) rename {libsrc/grabber/amlogic => include/grabber}/AmlogicGrabber.h (100%) diff --git a/libsrc/grabber/amlogic/AmlogicGrabber.h b/include/grabber/AmlogicGrabber.h similarity index 100% rename from libsrc/grabber/amlogic/AmlogicGrabber.h rename to include/grabber/AmlogicGrabber.h diff --git a/libsrc/grabber/amlogic/AmlogicGrabber.cpp b/libsrc/grabber/amlogic/AmlogicGrabber.cpp index 8eaa9799..25153142 100644 --- a/libsrc/grabber/amlogic/AmlogicGrabber.cpp +++ b/libsrc/grabber/amlogic/AmlogicGrabber.cpp @@ -13,7 +13,7 @@ #include // Local includes -#include "AmlogicGrabber.h" +#include // Flags copied from 'include/linux/amlogic/amports/amvideocap.h' at https://github.com/codesnake/linux-amlogic #define AMVIDEOCAP_IOC_MAGIC 'V' diff --git a/libsrc/grabber/amlogic/AmlogicWrapper.cpp b/libsrc/grabber/amlogic/AmlogicWrapper.cpp index b77f1612..29022afe 100644 --- a/libsrc/grabber/amlogic/AmlogicWrapper.cpp +++ b/libsrc/grabber/amlogic/AmlogicWrapper.cpp @@ -9,7 +9,7 @@ // Amlogic grabber includes #include -#include "AmlogicGrabber.h" +#include AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion) : diff --git a/libsrc/grabber/amlogic/CMakeLists.txt b/libsrc/grabber/amlogic/CMakeLists.txt index be6cb97d..9ec98bfe 100644 --- a/libsrc/grabber/amlogic/CMakeLists.txt +++ b/libsrc/grabber/amlogic/CMakeLists.txt @@ -7,7 +7,7 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/amlogic) SET(AmlogicQT_HEADERS ${CURRENT_HEADER_DIR}/AmlogicWrapper.h) SET(AmlogicHEADERS - ${CURRENT_SOURCE_DIR}/AmlogicGrabber.h + ${CURRENT_HEADER_DIR}/AmlogicGrabber.h ) SET(AmlogicSOURCES diff --git a/src/hyperion-aml/hyperion-aml.cpp b/src/hyperion-aml/hyperion-aml.cpp index 13da6686..71bcd495 100644 --- a/src/hyperion-aml/hyperion-aml.cpp +++ b/src/hyperion-aml/hyperion-aml.cpp @@ -7,7 +7,7 @@ // getoptPlusPLus includes #include -#include "../../libsrc/grabber/amlogic/AmlogicGrabber.h" +#include using namespace vlofgren; diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index b300aefc..8af26879 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -316,6 +316,10 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), amlGrabber, SLOT(setVideoMode(VideoMode))); } + #ifdef ENABLE_PROTOBUF + QObject::connect(amlGrabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif + amlGrabber->start(); std::cout << "AMLOGIC grabber created and started" << std::endl; } From 1b6b90df51b5c13ebefc1fe9315ba1596156c63c Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 15:09:07 +0100 Subject: [PATCH 87/96] bring back hyperion.tar.gz Former-commit-id: 2e507be1aca9e58076cafc38ca10e09a65cd3998 --- deploy/hyperion_rpi.tar.gz.REMOVED.git-id | 1 + 1 file changed, 1 insertion(+) create mode 100644 deploy/hyperion_rpi.tar.gz.REMOVED.git-id diff --git a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id new file mode 100644 index 00000000..f3692ead --- /dev/null +++ b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id @@ -0,0 +1 @@ +5b0f057a8591d76be009018b302977faeec5159a \ No newline at end of file From 2c831c111021dde35f2ff0c3f94b38296f3fbb68 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 16:03:21 +0100 Subject: [PATCH 88/96] add standalone amlogic grabber fix standalone dispmanx grabber Former-commit-id: 5ace9bc90a6fe76f5a51ecef95d6e7119d1102db --- src/hyperion-aml/AmlogicWrapper.cpp | 38 ++++++++++++++++++ src/hyperion-aml/AmlogicWrapper.h | 43 +++++++++++++++++++++ src/hyperion-aml/CMakeLists.txt | 6 ++- src/hyperion-aml/hyperion-aml.cpp | 38 +++++++++++------- src/hyperion-dispmanx/CMakeLists.txt | 7 +--- src/hyperion-dispmanx/DispmanxWrapper.cpp | 2 +- src/hyperion-dispmanx/DispmanxWrapper.h | 40 +++++++++---------- src/hyperion-dispmanx/hyperion-dispmanx.cpp | 16 ++++---- 8 files changed, 138 insertions(+), 52 deletions(-) create mode 100644 src/hyperion-aml/AmlogicWrapper.cpp create mode 100644 src/hyperion-aml/AmlogicWrapper.h diff --git a/src/hyperion-aml/AmlogicWrapper.cpp b/src/hyperion-aml/AmlogicWrapper.cpp new file mode 100644 index 00000000..e4c1f7f1 --- /dev/null +++ b/src/hyperion-aml/AmlogicWrapper.cpp @@ -0,0 +1,38 @@ + +// Hyperion-AmLogic includes +#include "AmlogicWrapper.h" + +AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : + _timer(this), + _grabber(grabWidth, grabHeight) +{ + _timer.setSingleShot(false); + _timer.setInterval(updateRate_Hz); + + // Connect capturing to the timeout signal of the timer + connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); +} + +const Image & AmlogicWrapper::getScreenshot() +{ + capture(); + return _screenshot_rgb; +} + +void AmlogicWrapper::start() +{ + _timer.start(); +} + +void AmlogicWrapper::stop() +{ + _timer.stop(); +} + +void AmlogicWrapper::capture() +{ + _grabber.grabFrame(_screenshot); + _screenshot.toRgb(_screenshot_rgb); + + emit sig_screenshot(_screenshot_rgb); +} diff --git a/src/hyperion-aml/AmlogicWrapper.h b/src/hyperion-aml/AmlogicWrapper.h new file mode 100644 index 00000000..3f5b0bc8 --- /dev/null +++ b/src/hyperion-aml/AmlogicWrapper.h @@ -0,0 +1,43 @@ + +// QT includes +#include + +// Hyperion-Dispmanx includes +#include + +class AmlogicWrapper : public QObject +{ + Q_OBJECT +public: + AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); + + const Image & getScreenshot(); + + /// + /// Starts the timed capturing of screenshots + /// + void start(); + + void stop(); + +signals: + void sig_screenshot(const Image & screenshot); + +private slots: + /// + /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot signal. + /// + void capture(); + +private: + /// The QT timer to generate capture-publish events + QTimer _timer; + + /// The grabber for creating screenshots + AmlogicGrabber _grabber; + + // image buffers + Image _screenshot_rgb; + Image _screenshot; + +}; diff --git a/src/hyperion-aml/CMakeLists.txt b/src/hyperion-aml/CMakeLists.txt index 5d45222a..cd27c046 100644 --- a/src/hyperion-aml/CMakeLists.txt +++ b/src/hyperion-aml/CMakeLists.txt @@ -14,6 +14,7 @@ include_directories( ) set(Hyperion_AML_QT_HEADERS + AmlogicWrapper.h ) set(Hyperion_AML_HEADERS @@ -21,12 +22,13 @@ set(Hyperion_AML_HEADERS set(Hyperion_AML_SOURCES hyperion-aml.cpp + AmlogicWrapper.cpp ) if(ENABLE_QT5) -QT5_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) + QT5_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) else(ENABLE_QT5) -QT4_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) + QT4_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) endif(ENABLE_QT5) add_executable(hyperion-amlogic diff --git a/src/hyperion-aml/hyperion-aml.cpp b/src/hyperion-aml/hyperion-aml.cpp index 71bcd495..cca5e688 100644 --- a/src/hyperion-aml/hyperion-aml.cpp +++ b/src/hyperion-aml/hyperion-aml.cpp @@ -7,16 +7,16 @@ // getoptPlusPLus includes #include -#include +#include +#include "AmlogicWrapper.h" using namespace vlofgren; // save the image as screenshot -void saveScreenshot(const char * filename, const Image & image) +void saveScreenshot(const char * filename, const Image & image) { // store as PNG QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); - pngImage = pngImage.rgbSwapped(); pngImage.save(filename); } @@ -30,16 +30,17 @@ int main(int argc, char ** argv) OptionsParser optionParser("X11 capture application for Hyperion"); ParameterSet & parameters = optionParser.getParameters(); - //IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); + IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); IntParameter & argWidth = parameters.add (0x0, "width", "Width of the captured image [default=128]"); IntParameter & argHeight = parameters.add (0x0, "height", "Height of the captured image [default=128]"); SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); - //SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); + SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); // set defaults + argFps.setDefault(10); argWidth.setDefault(160); argHeight.setDefault(160); argAddress.setDefault("127.0.0.1:19445"); @@ -57,29 +58,36 @@ int main(int argc, char ** argv) int width = argWidth.getValue(); int height = argHeight.getValue(); - if (width < 160 || height < 60) + if (width < 160 || height < 160) { std::cout << "Minimum width and height is 160" << std::endl; width = std::max(160, width); height = std::max(160, height); } + + int grabInterval = 1000 / argFps.getValue(); + AmlogicWrapper amlWrapper(argWidth.getValue(),argHeight.getValue(),grabInterval); + if (argScreenshot.isSet()) { - - // Create the grabber - AmlogicGrabber amlGrabber(width, height); - // Capture a single screenshot and finish - Image screenshot; - amlGrabber.grabFrame(screenshot); + const Image & screenshot = amlWrapper.getScreenshot(); saveScreenshot("screenshot.png", screenshot); } else { - // TODO[TvdZ]: Implement the proto-client mechanisme - std::cerr << "The PROTO-interface has not been implemented yet" << std::endl; - } + // Create the Proto-connection with hyperiond + ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); + // Connect the screen capturing to the proto processing + QObject::connect(&amlWrapper, SIGNAL(sig_screenshot(const Image &)), &protoWrapper, SLOT(receiveImage(Image))); + + // Start the capturing + amlWrapper.start(); + + // Start the application + app.exec(); + } } catch (const std::runtime_error & e) { diff --git a/src/hyperion-dispmanx/CMakeLists.txt b/src/hyperion-dispmanx/CMakeLists.txt index 4d48174e..130cb661 100644 --- a/src/hyperion-dispmanx/CMakeLists.txt +++ b/src/hyperion-dispmanx/CMakeLists.txt @@ -12,12 +12,7 @@ else(ENABLE_QT5) endif(ENABLE_QT5) # Find the BCM-package (VC control) -#find_package(BCM REQUIRED) -SET( BCM_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/dependencies/external/rapsi_vc ) -SET( BCM_LIBRARIES "" ) -ADD_DEFINITIONS ( -DDISPMANX_DUMMY ) - - +find_package(BCM REQUIRED) include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver diff --git a/src/hyperion-dispmanx/DispmanxWrapper.cpp b/src/hyperion-dispmanx/DispmanxWrapper.cpp index b11830a7..7d8702d2 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.cpp +++ b/src/hyperion-dispmanx/DispmanxWrapper.cpp @@ -1,5 +1,5 @@ -// Hyperion-X11 includes +// Hyperion-Dispmanx includes #include "DispmanxWrapper.h" DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : diff --git a/src/hyperion-dispmanx/DispmanxWrapper.h b/src/hyperion-dispmanx/DispmanxWrapper.h index 827a4d53..e8526b02 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.h +++ b/src/hyperion-dispmanx/DispmanxWrapper.h @@ -7,36 +7,36 @@ class DispmanxWrapper : public QObject { - Q_OBJECT + Q_OBJECT public: - DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); + DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); - const Image & getScreenshot(); + const Image & getScreenshot(); - /// - /// Starts the timed capturing of screenshots - /// - void start(); + /// + /// Starts the timed capturing of screenshots + /// + void start(); - void stop(); + void stop(); signals: - void sig_screenshot(const Image & screenshot); + void sig_screenshot(const Image & screenshot); private slots: - /// - /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot - /// signal. - /// - void capture(); + /// + /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot + /// signal. + /// + void capture(); private: - /// The QT timer to generate capture-publish events - QTimer _timer; + /// The QT timer to generate capture-publish events + QTimer _timer; - /// The grabber for creating screenshots - DispmanxFrameGrabber _grabber; - Image _screenshot_rgb; - Image _screenshot; + /// The grabber for creating screenshots + DispmanxFrameGrabber _grabber; + Image _screenshot_rgb; + Image _screenshot; }; diff --git a/src/hyperion-dispmanx/hyperion-dispmanx.cpp b/src/hyperion-dispmanx/hyperion-dispmanx.cpp index c7d5fe0e..abf78c8c 100644 --- a/src/hyperion-dispmanx/hyperion-dispmanx.cpp +++ b/src/hyperion-dispmanx/hyperion-dispmanx.cpp @@ -6,7 +6,7 @@ // getoptPlusPLus includes #include -#include "protoserver/ProtoConnectionWrapper.h" +#include #include "DispmanxWrapper.h" using namespace vlofgren; @@ -81,12 +81,12 @@ int main(int argc, char ** argv) app.exec(); } } - catch (const std::runtime_error & e) - { - // An error occured. Display error and quit - std::cerr << e.what() << std::endl; - return -1; - } + catch (const std::runtime_error & e) + { + // An error occured. Display error and quit + std::cerr << e.what() << std::endl; + return -1; + } - return 0; + return 0; } From 11af47d799a80bb31070f021c47b1d76b207c0c9 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 23:30:50 +0100 Subject: [PATCH 89/96] make it compile on raspi Former-commit-id: 378b2ed1f605d060feb955819fb632424f21a218 --- test/dispmanx2png/dispmanx2png.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dispmanx2png/dispmanx2png.cpp b/test/dispmanx2png/dispmanx2png.cpp index 1004b8ed..77dcb6b7 100644 --- a/test/dispmanx2png/dispmanx2png.cpp +++ b/test/dispmanx2png/dispmanx2png.cpp @@ -10,7 +10,7 @@ #include // Dispmanx grabber includes -#include +#include using namespace vlofgren; From 878538eb50f573658a21bad99a80db8e4e10662e Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 23:34:47 +0100 Subject: [PATCH 90/96] fix compile on raspi Former-commit-id: f526a9facebe8027f6bf50b1e54ab21bc1534faa --- test/dispmanx2png/dispmanx2png.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dispmanx2png/dispmanx2png.cpp b/test/dispmanx2png/dispmanx2png.cpp index 1004b8ed..77dcb6b7 100644 --- a/test/dispmanx2png/dispmanx2png.cpp +++ b/test/dispmanx2png/dispmanx2png.cpp @@ -10,7 +10,7 @@ #include // Dispmanx grabber includes -#include +#include using namespace vlofgren; From 3be4ebe6dcfb4d5cfbf8b2cc83ca40d92259580f Mon Sep 17 00:00:00 2001 From: penfold42 Date: Thu, 25 Feb 2016 22:33:13 +1100 Subject: [PATCH 91/96] clean up formatting Former-commit-id: dc3a3c7597af42b8fb37f09011d52ebacffd8959 --- libsrc/leddevice/LedDeviceWs2801.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/leddevice/LedDeviceWs2801.cpp b/libsrc/leddevice/LedDeviceWs2801.cpp index b36d2f49..aaee8cf6 100644 --- a/libsrc/leddevice/LedDeviceWs2801.cpp +++ b/libsrc/leddevice/LedDeviceWs2801.cpp @@ -11,7 +11,7 @@ // hyperion local includes #include "LedDeviceWs2801.h" -LedDeviceWs2801::LedDeviceWs2801(const std::string& outputDevice, const unsigned baudrate ) : +LedDeviceWs2801::LedDeviceWs2801(const std::string& outputDevice, const unsigned baudrate) : LedSpiDevice(outputDevice, baudrate, 500000), mLedCount(0) { From ea89a85ddb87361ccd19ed520861f07f53713dc1 Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 25 Feb 2016 15:21:25 +0100 Subject: [PATCH 92/96] make protoconnection to invalid host less blocking Former-commit-id: e7a89c87b15fbe9809ec63468b59ecc55c6d3e72 --- include/protoserver/ProtoConnection.h | 14 +++++++-- libsrc/protoserver/ProtoConnection.cpp | 40 +++++++++++++++++++++----- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/include/protoserver/ProtoConnection.h b/include/protoserver/ProtoConnection.h index a61947fe..7ecd8f36 100644 --- a/include/protoserver/ProtoConnection.h +++ b/include/protoserver/ProtoConnection.h @@ -7,6 +7,7 @@ #include #include #include +#include #include // hyperion util @@ -19,8 +20,11 @@ /// /// Connection class to setup an connection to the hyperion server and execute commands /// -class ProtoConnection +class ProtoConnection : public QObject { + +Q_OBJECT + public: /// /// Constructor @@ -74,10 +78,13 @@ public: /// void sendMessage(const proto::HyperionRequest & message); -private: +private slots: /// Try to connect to the Hyperion host void connectToHost(); + +private: + /// /// Parse a reply message /// @@ -99,4 +106,7 @@ private: /// Skip receiving reply messages from Hyperion if set bool _skipReply; + + QTimer _timer; + QAbstractSocket::SocketState _prevSocketState; }; diff --git a/libsrc/protoserver/ProtoConnection.cpp b/libsrc/protoserver/ProtoConnection.cpp index d7a6037e..5eb5e53c 100644 --- a/libsrc/protoserver/ProtoConnection.cpp +++ b/libsrc/protoserver/ProtoConnection.cpp @@ -9,7 +9,8 @@ ProtoConnection::ProtoConnection(const std::string & a) : _socket(), - _skipReply(false) + _skipReply(false), + _prevSocketState(QAbstractSocket::UnconnectedState) { QString address(a.c_str()); QStringList parts = address.split(":"); @@ -29,10 +30,18 @@ ProtoConnection::ProtoConnection(const std::string & a) : // try to connect to host std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; connectToHost(); + + // start the connection timer + _timer.setInterval(5000); + _timer.setSingleShot(false); + + connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()) ); + _timer.start(); } ProtoConnection::~ProtoConnection() { + _timer.stop(); _socket.close(); } @@ -91,20 +100,37 @@ void ProtoConnection::clearAll() void ProtoConnection::connectToHost() { - _socket.connectToHost(_host, _port); - if (_socket.waitForConnected()) { - std::cout << "Connected to Hyperion host" << std::endl; + // try connection only when + if (_socket.state() == QAbstractSocket::UnconnectedState) + { + _socket.connectToHost(_host, _port); + //_socket.waitForConnected(1000); } } void ProtoConnection::sendMessage(const proto::HyperionRequest &message) { - if (_socket.state() == QAbstractSocket::UnconnectedState) + // print out connection message only when state is changed + if (_socket.state() != _prevSocketState ) { - std::cout << "Currently disconnected: trying to connect to host" << std::endl; - connectToHost(); + switch (_socket.state() ) + { + case QAbstractSocket::UnconnectedState: + std::cout << "No connection to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + break; + + case QAbstractSocket::ConnectedState: + std::cout << "Connected to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + break; + + default: + //std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + break; + } + _prevSocketState = _socket.state(); } + if (_socket.state() != QAbstractSocket::ConnectedState) { return; From f0c1e63fba17cfe99211202972cdb15ca0aed48d Mon Sep 17 00:00:00 2001 From: redpanther Date: Sat, 27 Feb 2016 18:06:04 +0100 Subject: [PATCH 93/96] update compile howto for making release binaries Former-commit-id: 5105b3f374221e573290c98990c55f0bd67ba849 --- CompileHowto.txt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/CompileHowto.txt b/CompileHowto.txt index 621cf8fd..9f419709 100644 --- a/CompileHowto.txt +++ b/CompileHowto.txt @@ -24,11 +24,11 @@ mkdir "$HYPERION_DIR/build" cd "$HYPERION_DIR/build" # run cmake to generate make files on the raspberry pi -cmake .. +cmake -DCMAKE_BUILD_TYPE=Release -Wno-dev .. # or if you are not compiling on the raspberry pi and need to disable the Dispmanx grabber and support for spi devices -cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_X11=ON .. +cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_X11=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. # as an alternative for the dispmanx grabber on non-rpi devices (e.g. cubox-i) you could try the framebuffer grabber -cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_FB=ON .. +cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_FB=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. # for OSX build you need XCode, qt4 libraries and cmake. You can use macport (homebrew might work too) to install them sudo port install qt4-mac sudo port install cmake @@ -36,6 +36,12 @@ cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_V4L2=OFF -DENABLE_OSX=O # run make to build Hyperion make +# or if you have a system with more then 1 cpu core +make -j 4 +# "4" is the number of cpu cores (e.g. 4 on RPi2), this makes compile faster + +#after compile, to remove any stuff not needed for a release version. +strip bin/* # The binaries are build in "$HYPERION_DIR/build/bin". You could copy those to /usr/bin sudo cp ./bin/hyperion-remote /usr/bin/ From b63cdc1bcfc9d719061b104455fa8d377f90d919 Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 29 Feb 2016 04:29:55 +0100 Subject: [PATCH 94/96] Revert "make it compile on raspi" This reverts commit 11af47d799a80bb31070f021c47b1d76b207c0c9 [formerly 378b2ed1f605d060feb955819fb632424f21a218]. Former-commit-id: 5343c8139825860e74243ecbbb67d9aae6697d63 --- test/dispmanx2png/dispmanx2png.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dispmanx2png/dispmanx2png.cpp b/test/dispmanx2png/dispmanx2png.cpp index 77dcb6b7..1004b8ed 100644 --- a/test/dispmanx2png/dispmanx2png.cpp +++ b/test/dispmanx2png/dispmanx2png.cpp @@ -10,7 +10,7 @@ #include // Dispmanx grabber includes -#include +#include using namespace vlofgren; From 42e488c193be9394c0304eca2b85888438c7342c Mon Sep 17 00:00:00 2001 From: Serhan Date: Mon, 7 Mar 2016 12:10:30 +0100 Subject: [PATCH 95/96] Removed debug-build option Removed debug-build option Former-commit-id: ce88ca30ecf296617d6fe2d2b0e9d7f050d7d68a --- CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 81479cb3..9c8e077a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,9 +91,6 @@ include_directories(${CMAKE_SOURCE_DIR}/include) # Prefer static linking over dynamic #set(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so") -set(CMAKE_BUILD_TYPE "Debug") -#set(CMAKE_BUILD_TYPE "Release") - # enable C++11 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -std=c++11 -Wall") From 02d055b75c54ca1777e4000deced9fd9d3eda7ab Mon Sep 17 00:00:00 2001 From: brindosch Date: Tue, 8 Mar 2016 18:20:09 +0100 Subject: [PATCH 96/96] Add the service files and new hyperion conf Former-commit-id: 2083ce117791e6ad22037f91618af917fe99d40b --- bin/create_release.sh | 4 + bin/hyperion.init.sh | 11 +- bin/hyperion.initctl.sh | 17 ++ bin/hyperion.systemd.sh | 15 ++ bin/remove_hyperion.sh | 105 ++++++++++ config/hyperion.config.json | 372 ++++++++++++++++++------------------ 6 files changed, 341 insertions(+), 183 deletions(-) create mode 100644 bin/hyperion.initctl.sh create mode 100644 bin/hyperion.systemd.sh create mode 100644 bin/remove_hyperion.sh diff --git a/bin/create_release.sh b/bin/create_release.sh index d6b9bf66..c44fb5c5 100644 --- a/bin/create_release.sh +++ b/bin/create_release.sh @@ -24,6 +24,8 @@ tar --create --verbose --gzip --absolute-names --show-transformed-names --ignore --transform "s:$repodir/effects/:hyperion/effects/:" \ --transform "s:$repodir/config/:hyperion/config/:" \ --transform "s:$repodir/bin/hyperion.init.sh:hyperion/init.d/hyperion.init.sh:" \ + --transform "s:$repodir/bin/hyperion.systemd.sh:hyperion/init.d/hyperion.systemd.sh:" \ + --transform "s:$repodir/bin/hyperion.initctl.sh:hyperion/init.d/hyperion.initctl.sh:" \ --transform "s://:/:g" \ "$builddir/bin/hyperiond" \ "$builddir/bin/hyperion-remote" \ @@ -32,5 +34,7 @@ tar --create --verbose --gzip --absolute-names --show-transformed-names --ignore "$builddir/bin/dispmanx2png" \ "$repodir/effects/"* \ "$repodir/bin/hyperion.init.sh" \ + "$repodir/bin/hyperion.systemd.sh" \ + "$repodir/bin/hyperion.initctl.sh" \ "$repodir/config/hyperion.config.json" diff --git a/bin/hyperion.init.sh b/bin/hyperion.init.sh index d83bdb28..fbae0156 100644 --- a/bin/hyperion.init.sh +++ b/bin/hyperion.init.sh @@ -1,7 +1,16 @@ #!/bin/bash -# Hyperion daemon +# Hyperion daemon service # description: Hyperion daemon # processname: hyperiond +### BEGIN INIT INFO +# Provides: Hyperion +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Hyperion Ambilight init.d Service. +# Description: Hyperion Ambilight init.d Service. +### END INIT INFO DAEMON=hyperiond DAEMONOPTS="/etc/hyperion.config.json" diff --git a/bin/hyperion.initctl.sh b/bin/hyperion.initctl.sh new file mode 100644 index 00000000..e533b14a --- /dev/null +++ b/bin/hyperion.initctl.sh @@ -0,0 +1,17 @@ +## Hyperion daemon initctl script + +description "hyperion" +author "poljvd & tvdzwan" + +start on (runlevel [2345]) +stop on (runlevel [!2345]) + +respawn + +pre-start script +#comment out the following 2 lines for x32/64 +modprobe spidev +/usr/bin/gpio2spi +end script + +exec /usr/bin/hyperiond /etc/hyperion.config.json \ No newline at end of file diff --git a/bin/hyperion.systemd.sh b/bin/hyperion.systemd.sh new file mode 100644 index 00000000..005c0c14 --- /dev/null +++ b/bin/hyperion.systemd.sh @@ -0,0 +1,15 @@ +[Unit] +Description=Hyperion Systemd service + +[Service] +Type=simple +User=root +Group=root +UMask=007 +ExecStart=/opt/hyperion/bin/hyperiond /etc/hyperion.config.json +ExecReload=/bin/kill -HUP $MAINPID +Restart=on-failure +TimeoutStopSec=10 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/bin/remove_hyperion.sh b/bin/remove_hyperion.sh new file mode 100644 index 00000000..2b0c2788 --- /dev/null +++ b/bin/remove_hyperion.sh @@ -0,0 +1,105 @@ +#!/bin/sh +# Script to remove Hyperion and all services + +# Make sure /sbin is on the path (for service to find sub scripts) +PATH="/sbin:$PATH" + +#Check if HyperCon is logged in as root +if [ $(id -u) != 0 ] && [ "$1" = "HyperConRemove" ]; then + echo '---> Critical Error: Please connect as user "root" through HyperCon' + echo '---> We need admin privileges to remove your Hyperion! -> abort' + exit 1 +fi + +#Check, if script is running as root +if [ $(id -u) != 0 ]; then + echo '---> Critical Error: Please run the script as root (sudo sh ./remove_hyperion.sh)' + exit 1 +fi + +#Welcome message +echo '*******************************************************************************' +echo 'This script will remove Hyperion and itīs services' +echo '-----> Please BACKUP your hyperion.config.json if necessary <-----' +echo '*******************************************************************************' + +#Skip the prompt if HyperCon Remove +if [ "$1" = "" ]; then +#Prompt for confirmation to proceed +while true +do +echo -n "---> Do you really want to remove Hyperion and itīs services? (y or n) :" +read CONFIRM +case $CONFIRM in +y|Y|YES|yes|Yes) break ;; +n|N|no|NO|No) +echo "---> Aborting - you entered \"$CONFIRM\"" +exit +;; +*) echo "-> Please enter only y or n" +esac +done +echo "---> You entered \"$CONFIRM\". Remove Hyperion!" +fi +# Find out if we are on OpenElec +OS_OPENELEC=`grep -m1 -c OpenELEC /etc/issue` + +# check which init script we should use +USE_SYSTEMD=`grep -m1 -c systemd /proc/1/comm` +USE_INITCTL=`which /sbin/initctl | wc -l` +USE_SERVICE=`which /usr/sbin/service | wc -l` + +# Stop hyperion daemon if it is running +echo '---> Stop Hyperion, if necessary' +if [ $OS_OPENELEC -eq 1 ]; then + killall hyperiond 2>/dev/null +elif [ $USE_INITCTL -eq 1 ]; then + /sbin/initctl stop hyperion 2>/dev/null +elif [ $USE_SERVICE -eq 1 ]; then + /usr/sbin/service hyperion stop 2>/dev/null +elif [ $USE_SYSTEMD -eq 1 ]; then + service hyperion stop 2>/dev/null +fi + +#Disabling and delete service files +if [ $USE_INITCTL -eq 1 ]; then + echo '---> Delete and disable Hyperion initctl script' + rm -v /etc/init/hyperion 2>/dev/null + initctl reload-configuration +elif [ $OS_OPENELEC -eq 1 ]; then + # Remove Hyperion from OpenELEC autostart.sh + echo "---> Remove Hyperion from OpenELEC autostart.sh" + sed -i "/hyperiond/d" /storage/.config/autostart.sh 2>/dev/null +elif [ $USE_SYSTEMD -eq 1 ]; then + # Delete and disable Hyperion systemd script + echo '---> Delete and disable Hyperion systemd script' + systemctl disable hyperion.service + rm -v /etc/systemd/system/hyperion.service 2>/dev/null +elif [ $USE_SERVICE -eq 1 ]; then + # Delete and disable Hyperion init.d script + echo '---> Delete and disable Hyperion init.d script' + update-rc.d -f hyperion remove + rm /etc/init.d/hyperion 2>/dev/null +fi + +# Delete Hyperion binaries +if [ $OS_OPENELEC -eq 1 ]; then + # Remove OpenELEC Hyperion binaries and configs + echo '---> Remove the OpenELEC Hyperion binaries and hyperion.config.json' + rm -rv /storage/hyperion 2>/dev/null + rm -v /storage/.config/hyperion.config.json 2>/dev/null +else + #Remove binaries on all distributions/systems (not OpenELEC) + echo "---> Remove links to the binaries" + rm -v /usr/bin/hyperiond 2>/dev/null + rm -v /usr/bin/hyperion-remote 2>/dev/null + rm -v /usr/bin/hyperion-v4l2 2>/dev/null + rm -v /etc/hyperion.config.json 2>/dev/null + echo "---> Remove binaries" + rm -rv /opt/hyperion 2>/dev/null +fi +echo '*******************************************************************************' +echo 'Hyperion successful removed!' +echo '*******************************************************************************' +exit 0 + \ No newline at end of file diff --git a/config/hyperion.config.json b/config/hyperion.config.json index 291086db..5bc313c3 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -4,39 +4,19 @@ { /// Device configuration contains the following fields: /// * 'name' : The user friendly name of the device (only used for display purposes) - /// * 'type' : The type of the device or leds (known types for now are 'ws2801', 'ldp8806', - /// 'lpd6803', 'sedu', 'adalight', 'lightpack', 'philipshue', 'test' and 'none') - /// * 'output' : The output specification depends on selected device. This can for example be the - /// device specifier, device serial number, or the output file name - /// * 'rate' : The baudrate of the output to the device + /// * 'type' : The type of the device or leds (known types for now are + /// APA102, Adalight, AmbiLed, Atmo, Hyperion-USBASP-WS2801, Hyperion-USBASP-WS2812, Lightberry, Lightpack, LPD6803, LPD8806, Multi-Lightpack, P9813, Paintpack, PhilipsHUE, PiBlaster, SEDU, Test, ThinkerForge, TPM2, WS2801, WS2812b, None) + /// * [device type specific configuration] /// * 'colorOrder' : The order of the color bytes ('rgb', 'rbg', 'bgr', etc.). - /// Specific of Philips Hue: - /// * 'username' : The name of user registred on the Philips Hue Bridge - /// * 'switchOffOnBlack' : Define if Hue light switch off when black is detected - /// * 'transitiontime' : Set the time of transition between color of Hue light "device" : { "name" : "MyPi", "type" : "ws2801", "output" : "/dev/spidev0.0", - "rate" : 250000, + "rate" : 1000000, "colorOrder" : "rgb" }, - /// Configuration for message forwarding to other hyperions - /// protobuffer and json remote interface are forwarded to configured hosts - /// 'proto' is mostly used for video streams and 'json' for effects - /// - /// ** pay attention which port you use. use correct ports for protols ** - /// - /// * 'proto' : list of host in form of : - /// * 'json' : list of host in form of : -/// "forwarder" : -/// { -/// "proto" : [ "127.0.0.1:19445","192.168.178.88:19445" ], -/// "json" : [ "127.0.0.1:19444","192.168.178.88:19444" ] -/// }, - /// Color manipulation configuration used to tune the output colors to specific surroundings. /// The configuration contains a list of color-transforms. Each transform contains the /// following fields: @@ -59,6 +39,7 @@ /// - 'type' The type of smoothing algorithm ('linear' or 'none') /// - 'time_ms' The time constant for smoothing algorithm in milliseconds /// - 'updateFrequency' The update frequency of the leds in Hz + /// - 'updateDelay' The delay of the output to leds (in periods of smoothing) "color" : { "transform" : @@ -96,13 +77,156 @@ ], "smoothing" : { - "type" : "none", + "type" : "linear", "time_ms" : 200, "updateFrequency" : 20.0000, "updateDelay" : 0 } }, + /// The black border configuration, contains the following items: + /// * enable : true if the detector should be activated + /// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0) + /// * unknownFrameCnt : Number of frames without any detection before the border is set to 0 (default 600) + /// * borderFrameCnt : Number of frames before a consistent detected border gets set (default 50) + /// * maxInconsistentCnt : Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency + /// * blurRemoveCnt : Number of pixels that get removed from the detected border to cut away blur (default 1) + /// * mode : Border detection mode (values=default,classic,osd) + "blackborderdetector" : + { + "enable" : true, + "threshold" : 0.0, + "unknownFrameCnt" : 600, + "borderFrameCnt" : 50, + "maxInconsistentCnt" : 10, + "blurRemoveCnt" : 1, + "mode" : "default" + }, + + /// The configuration of the effect engine, contains the following items: + /// * paths : An array with absolute location(s) of directories with effects + /// * color : Set static color after boot -> set effect to "" (empty) and input the values [R,G,B] and set duration_ms NOT to 0 (use 1) instead + /// * effect : The effect selected as 'boot sequence' + /// * duration_ms : The duration of the selected effect (0=endless) + /// * priority : The priority of the selected effect/static color (default=0) + "effects" : + { + "paths" : + [ + "/opt/hyperion/effects" + ] + }, + + "bootsequence" : + { + "color" : [0,0,0], + "effect" : "Rainbow swirl fast", + "duration_ms" : 3000, + "priority" : 990 + }, + + /// The configuration of the Json/Proto forwarder. Forward messages to multiple instances of Hyperion on same and/or other hosts + /// 'proto' is mostly used for video streams and 'json' for effects + /// * proto : Proto server adress and port of your target. Syntax:[IP:PORT] -> ["127.0.0.1:19447"] or more instances to forward ["127.0.0.1:19447","192.168.0.24:19449"] + /// * json : Json server adress and port of your target. Syntax:[IP:PORT] -> ["127.0.0.1:19446"] or more instances to forward ["127.0.0.1:19446","192.168.0.24:19448"] + /// HINT: If you redirect to "127.0.0.1" (localhost) you could start a second hyperion with another device/led config! + /// Be sure your client(s) is/are listening on the configured ports. The second Hyperion (if used) also needs to be configured! (HyperCon -> External -> Json Server/Proto Server) +// "forwarder" : +// { +// "proto" : ["127.0.0.1:19447"], +// "json" : ["127.0.0.1:19446"] +// }, + + /// The configuration for the frame-grabber, contains the following items: + /// * width : The width of the grabbed frames [pixels] + /// * height : The height of the grabbed frames [pixels] + /// * frequency_Hz : The frequency of the frame grab [Hz] + "framegrabber" : + { + "width" : 80, + "height" : 45, + "frequency_Hz" : 10.0 + }, + + /// The configuration of the Kodi connection used to enable and disable the frame-grabber. Contains the following fields: + /// * xbmcAddress : The IP address of the Kodi-host + /// * xbmcTcpPort : The TCP-port of the Kodi-server + /// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback + /// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show + /// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback + /// * grabMenu : Flag indicating that the frame-grabber is on(true) at the Kodi menu + /// * grabScreensaver : Flag indicating that the frame-grabber is on(true) when Kodi is on screensaver + /// * enable3DDetection : Flag indicating that the frame-grabber should switch to a 3D compatible modus if a 3D video is playing +// "xbmcVideoChecker" : +// { +// "xbmcAddress" : "127.0.0.1", +// "xbmcTcpPort" : 9090, +// "grabVideo" : true, +// "grabPictures" : true, +// "grabAudio" : true, +// "grabMenu" : false, +// "grabScreensaver" : true, +// "enable3DDetection" : true +// }, + + /// The configuration of the Json server which enables the json remote interface + /// * port : Port at which the json server is started + "jsonServer" : + { + "port" : 19444 + }, + + /// The configuration of the Proto server which enables the protobuffer remote interface + /// * port : Port at which the protobuffer server is started + "protoServer" : + { + "port" : 19445 + }, + + /// The configuration of the boblight server which enables the boblight remote interface + /// * port : Port at which the boblight server is started +// "boblightServer" : +// { +// "port" : 19333 +// }, + + /// Configuration for the embedded V4L2 grabber + /// * device : V4L2 Device to use [default="/dev/video0"] + /// * input : V4L2 input to use [default=0] + /// * standard : Video standard (no-change/PAL/NTSC) [default="no-change"] + /// * width : V4L2 width to set [default=-1] + /// * height : V4L2 height to set [default=-1] + /// * frameDecimation : Frame decimation factor [default=2] + /// * sizeDecimation : Size decimation factor [default=8] + /// * priority : Hyperion priority channel [default=800] + /// * mode : 3D mode to use 2D/3DSBS/3DTAB (note: no autodetection) [default="2D"] + /// * cropLeft : Cropping from the left [default=0] + /// * cropRight : Cropping from the right [default=0] + /// * cropTop : Cropping from the top [default=0] + /// * cropBottom : Cropping from the bottom [default=0] + /// * redSignalThreshold : Signal threshold for the red channel between 0.0 and 1.0 [default=0.0] + /// * greenSignalThreshold : Signal threshold for the green channel between 0.0 and 1.0 [default=0.0] + /// * blueSignalThreshold : Signal threshold for the blue channel between 0.0 and 1.0 [default=0.0] +// "grabber-v4l2" : +// { +// "device" : "/dev/video0", +// "input" : 0, +// "standard" : "no-change", +// "width" : -1, +// "height" : -1, +// "frameDecimation" : 2, +// "sizeDecimation" : 8, +// "priority" : 800, +// "mode" : "2D", +// "cropLeft" : 0, +// "cropRight" : 0, +// "cropTop" : 0, +// "cropBottom" : 0, +// "redSignalThreshold" : 0.0, +// "greenSignalThreshold" : 0.0, +// "blueSignalThreshold" : 0.0 +// }, + /// The configuration for each individual led. This contains the specification of the area /// averaged of an input image for each led to determine its color. Each item in the list /// contains the following fields: @@ -116,47 +240,47 @@ [ { "index" : 0, - "hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, + "hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 1, - "hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, + "hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 2, - "hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, + "hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 3, - "hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, + "hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 4, - "hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, + "hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 5, - "hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, + "hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 6, - "hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, + "hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 7, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, + "hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 8, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { @@ -196,271 +320,155 @@ }, { "index" : 16, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 17, "hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 18, + "index" : 17, "hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 19, + "index" : 18, "hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 20, + "index" : 19, "hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 21, + "index" : 20, "hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 22, + "index" : 21, "hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 23, + "index" : 22, "hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 24, + "index" : 23, "hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 25, + "index" : 24, "hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, + { + "index" : 25, + "hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, { "index" : 26, - "hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, + "hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { "index" : 27, - "hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, + "hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { "index" : 28, - "hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, + "hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { "index" : 29, - "hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, + "hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { "index" : 30, - "hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, + "hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { "index" : 31, - "hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, + "hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { "index" : 32, - "hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 33, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 34, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 } }, { - "index" : 35, + "index" : 33, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 } }, { - "index" : 36, + "index" : 34, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 } }, { - "index" : 37, + "index" : 35, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 } }, { - "index" : 38, + "index" : 36, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 } }, { - "index" : 39, + "index" : 37, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 } }, { - "index" : 40, + "index" : 38, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 } }, { - "index" : 41, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 42, + "index" : 39, "hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { - "index" : 43, + "index" : 40, "hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { - "index" : 44, + "index" : 41, "hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { - "index" : 45, + "index" : 42, "hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { - "index" : 46, + "index" : 43, "hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { - "index" : 47, + "index" : 44, "hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { - "index" : 48, + "index" : 45, "hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 49, - "hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } } ], - /// The black border configuration, contains the following items: - /// * enable : true if the detector should be activated - /// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0) - /// * unknownFrameCnt : Number of frames without any detection before the border is set to 0 (default 600) - optional - /// * borderFrameCnt : Number of frames before a consistent detected border gets set (default 50) - optional - /// * maxInconsistentCnt : Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency - optional - /// * blurRemoveCnt : Number of pixels that get removed from the detected border to cut away blur (default 1) - optional - /// * mode : Border detection mode (values "default","classic","osd") - optional - - "blackborderdetector" : - { - "enable" : true, - "threshold" : 0.01, - "unknownFrameCnt": 600, - "borderFrameCnt" : 50, - "maxInconsistentCnt" : 10, - "blurRemoveCnt": 1, - "mode" : "default" - }, - - /// The configuration of the effect engine, contains the following items: - /// * paths : An array with absolute location(s) of directories with effects - /// * bootsequence : The effect selected as 'boot sequence' - /// * effect : name of the effect you want to start. Set to empty if no effect wanted - /// * color : switch to static color after effect is done - /// * duration_ms : duration of boot effect in ms. 0 means effect stays forever - /// * priority : priority of boot effect and static color - "effects" : - { - "paths" : - [ - "/opt/hyperion/effects" - ] - }, - - "bootsequence" : - { - "color" : [0,0,0], - "effect" : "Rainbow swirl fast", - "duration_ms" : 3000, - "priority" : 0 - }, - - /// The configuration for the frame-grabber, contains the following items: - /// * width : The width of the grabbed frames [pixels] - /// * height : The height of the grabbed frames [pixels] - /// * frequency_Hz : The frequency of the frame grab [Hz] - "framegrabber" : - { - "width" : 64, - "height" : 64, - "frequency_Hz" : 10.0 - }, - - /// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields: - /// * xbmcAddress : The IP address of the XBMC-host - /// * xbmcTcpPort : The TCP-port of the XBMC-server - /// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback - /// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show - /// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback - /// * grabMenu : Flag indicating that the frame-grabber is on(true) in the XBMC menu - /// * grabScreensaver : Flag indicating that the frame-grabber is on(true) when XBMC is on screensaver - /// * enable3DDetection : Flag indicating that the frame-grabber should switch to a 3D compatible modus if a 3D video is playing - "xbmcVideoChecker" : - { - "xbmcAddress" : "127.0.0.1", - "xbmcTcpPort" : 9090, - "grabVideo" : true, - "grabPictures" : true, - "grabAudio" : true, - "grabMenu" : false, - "grabScreensaver" : true, - "enable3DDetection" : true - }, - - /// The configuration of the Json server which enables the json remote interface - /// * port : Port at which the json server is started - "jsonServer" : - { - "port" : 19444 - }, - - /// The configuration of the Proto server which enables the protobuffer remote interface - /// * port : Port at which the protobuffer server is started - "protoServer" : - { - "port" : 19445 - }, - - /// The configuration of the boblight server which enables the boblight remote interface - /// * port : Port at which the boblight server is started -// "boblightServer" : -// { -// "port" : 19333 -// }, - "endOfJson" : "endOfJson" }