From 2eea311dcef21d6dedc3f1712238b7d1b69c89be Mon Sep 17 00:00:00 2001 From: pcaffardi Date: Sun, 9 Aug 2015 16:15:25 +0200 Subject: [PATCH 01/50] 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 02/50] 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 03/50] 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 04/50] 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 05/50] 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 06/50] 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 07/50] 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 08/50] 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 09/50] 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 10/50] 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 11/50] 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 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 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 12/50] 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 13/50] 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 14/50] 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 15/50] 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 16/50] 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 17/50] 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 18/50] 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 19/50] 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 20/50] 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 21/50] 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 defe217c899a0258eda2ef9672ff3c8f83dc0038 Mon Sep 17 00:00:00 2001 From: frostworx Date: Wed, 6 Jan 2016 17:31:23 +0100 Subject: [PATCH 22/50] 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 23/50] 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 544ae68429cf8e7eb026d912a508e6905d76e404 Mon Sep 17 00:00:00 2001 From: wisc Date: Sun, 10 Jan 2016 14:41:47 +0100 Subject: [PATCH 24/50] 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 25/50] 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 26/50] 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 27/50] 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 28/50] 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 29/50] 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 30/50] 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 31/50] 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 32/50] 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 33/50] 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 6b860a7e244d87e0e6202012d9c2d2f4a7585d11 Mon Sep 17 00:00:00 2001 From: ntim Date: Mon, 18 Jan 2016 10:41:45 +0100 Subject: [PATCH 34/50] 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 35/50] 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: Thu, 21 Jan 2016 16:39:52 +0100 Subject: [PATCH 36/50] 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 37/50] 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 38/50] 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 39/50] 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 40/50] 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 41/50] 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 42/50] 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 43/50] 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 a257f185c93ff304e6ed1b358ed3266bf211c971 Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 26 Jan 2016 15:08:21 +0100 Subject: [PATCH 44/50] 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 45/50] 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 8a906b9d01c247895ceb60f2206b8136b7efa5b5 Mon Sep 17 00:00:00 2001 From: redpanther Date: Sun, 31 Jan 2016 04:34:13 +0100 Subject: [PATCH 46/50] 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 47/50] 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 48/50] 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 49/50] 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 50/50] 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})); -} +}