From 536b51dba11afb3affd2ec8a9eb6f3ca36d8c29e Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Fri, 6 May 2016 15:05:28 +0200 Subject: [PATCH 01/63] Update JsonClientConnection.cpp JSON API: Get current LED color Former-commit-id: 0b40c1eb1627afd8077bdf690109609fd531c2fb --- libsrc/jsonserver/JsonClientConnection.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 34819367..6d6bbaab 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -528,6 +528,21 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &) activeEffects.append(activeEffect); } + + // collect active led colors + Json::Value & activeLedColors = info["activeLedColors"] = Json::Value(Json::arrayValue); + foreach (int priority, activePriorities) { + const Hyperion::InputInfo & priorityInfo = _hyperion->getPriorityInfo(priority); + int i=0; + Json::Value LEDcolor; + for (auto it = priorityInfo.ledColors.begin(); it!=priorityInfo.ledColors.end(); ++it, ++i) { + LEDcolor[std::to_string(i)].append(it->red); + LEDcolor[std::to_string(i)].append(it->green); + LEDcolor[std::to_string(i)].append(it->blue); + } + + activeLedColors.append(LEDcolor); + } // send the result sendMessage(result); From 3ba86a125321f01c9650c5a449be55a19de025cc Mon Sep 17 00:00:00 2001 From: Peter Fern Date: Mon, 9 May 2016 19:19:52 +1000 Subject: [PATCH 02/63] Allow random mood blobs color, set mood-blobs-full to random Small change to allow a random start hue for mood blobs - adds a bit of spice instead of starting at the same color every time. Former-commit-id: 2b5a0250b95ac5632661d3b8fce3c1567f5daaa3 --- effects/mood-blobs-full.json | 2 +- effects/mood-blobs.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/effects/mood-blobs-full.json b/effects/mood-blobs-full.json index 8b230010..05e4ff1e 100644 --- a/effects/mood-blobs-full.json +++ b/effects/mood-blobs-full.json @@ -4,7 +4,7 @@ "args" : { "rotationTime" : 60.0, - "color" : [0,0,255], + "colorRandom" : true, "hueChange" : 30.0, "blobs" : 5, "reverse" : false, diff --git a/effects/mood-blobs.py b/effects/mood-blobs.py index b638f3d3..45efff85 100644 --- a/effects/mood-blobs.py +++ b/effects/mood-blobs.py @@ -2,10 +2,12 @@ import hyperion import time import colorsys import math +from random import random # Get the parameters rotationTime = float(hyperion.args.get('rotationTime', 20.0)) color = hyperion.args.get('color', (0,0,255)) +colorRandom = bool(hyperion.args.get('colorRandom', False)) hueChange = float(hyperion.args.get('hueChange', 60.0)) blobs = int(hyperion.args.get('blobs', 5)) reverse = bool(hyperion.args.get('reverse', False)) @@ -34,6 +36,9 @@ baseColorChangeRate = max(0, baseColorChangeRate) # > 0 # Calculate the color data baseHsv = colorsys.rgb_to_hsv(color[0]/255.0, color[1]/255.0, color[2]/255.0) +if colorRandom: + baseHsv = (random(), baseHsv[1], baseHsv[2]) + colorData = bytearray() for i in range(hyperion.ledCount): hue = (baseHsv[0] + hueChange * math.sin(2*math.pi * i / hyperion.ledCount)) % 1.0 From c17e4894d9a8ac8328ad838f1feae155615e1531 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Tue, 10 May 2016 20:16:19 +1000 Subject: [PATCH 03/63] Apa102 fix if the led strip has more physical LEDs than you want to configure with hyperion (#626) * Removed -HUP so the default -TERM signal is sent instead. - hyperiond only listens for TERM and INT. HUP is often used to get an exe to reread its config Changed pgrep to add '-x' so it wont partial match on the exe name. - I have multiple instances with multiple hyperiond-instance1 names - this ensures the service script only kills the right process * reversing errant change to hyperion.systemd.sh * started bug fixes for APA strips with more physical leds than configured * 1st cut of changes to APA102. now looks at config for "leds" which is the # of hardware leds in the strip. This enables us to write the correct trailer length in the packet. Also fixed a bug where switchoff was writing the wrong # of leds * removed commented out old code removed debug printf * included prebuild test binary for Pi2 * Second attempt at the fix. BEFORE: If you have more physcial LEDs than defined in the "leds" "index" section of the config there is random junk added to the end of the strip. WITH THIS FIX: In the "device" section specify the number of physical leds with: "leds" : 212, If this is greater than the number of led indexes, additional LEDs are set to black If this is smaller than the number of led indexes, it is ignored * included test binary * Clean exit if the device config is missing or a non-supported device type is specified Former-commit-id: 8ae96188fa74d91b13a921e7d5faf6d6ac1c42ee --- dependencies/external/rpi_ws281x | 2 +- hyperiond.test-binary.REMOVED.git-id | 1 + libsrc/leddevice/LedDeviceAPA102.cpp | 49 ++++++++++++++++++++------- libsrc/leddevice/LedDeviceAPA102.h | 5 ++- libsrc/leddevice/LedDeviceFactory.cpp | 4 ++- 5 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 hyperiond.test-binary.REMOVED.git-id diff --git a/dependencies/external/rpi_ws281x b/dependencies/external/rpi_ws281x index e053bc9b..f82fa85f 160000 --- a/dependencies/external/rpi_ws281x +++ b/dependencies/external/rpi_ws281x @@ -1 +1 @@ -Subproject commit e053bc9be127d1f4f0cffd10e7892cd32657ecf7 +Subproject commit f82fa85f26c9ee10210469e61315d9c0182a2b81 diff --git a/hyperiond.test-binary.REMOVED.git-id b/hyperiond.test-binary.REMOVED.git-id new file mode 100644 index 00000000..dc9b6471 --- /dev/null +++ b/hyperiond.test-binary.REMOVED.git-id @@ -0,0 +1 @@ +5d75f380f2bd74d3cd6b574f0a7d05850786216b \ No newline at end of file diff --git a/libsrc/leddevice/LedDeviceAPA102.cpp b/libsrc/leddevice/LedDeviceAPA102.cpp index 26a21f72..e7dc7eb6 100644 --- a/libsrc/leddevice/LedDeviceAPA102.cpp +++ b/libsrc/leddevice/LedDeviceAPA102.cpp @@ -12,38 +12,61 @@ // hyperion local includes #include "LedDeviceAPA102.h" -LedDeviceAPA102::LedDeviceAPA102(const std::string& outputDevice, const unsigned baudrate) : +LedDeviceAPA102::LedDeviceAPA102(const std::string& outputDevice, const unsigned baudrate, const unsigned ledcount) : LedSpiDevice(outputDevice, baudrate, 500000), _ledBuffer(0) { - // empty + _HW_ledcount = ledcount; } int LedDeviceAPA102::write(const std::vector &ledValues) { + _mLedCount = ledValues.size(); + const unsigned int max_leds = std::max(_mLedCount, _HW_ledcount); 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); + const unsigned int endFrameSize = std::max(((max_leds + 15) / 16), 4); + const unsigned int APAbufferSize = (max_leds * 4) + startFrameSize + endFrameSize; + +//printf ("_mLedCount %d _HW_ledcount %d max_leds %d APAbufferSize %d\n", +// _mLedCount, _HW_ledcount, max_leds, APAbufferSize); + + if(_ledBuffer.size() != APAbufferSize){ + _ledBuffer.resize(APAbufferSize, 0xFF); _ledBuffer[0] = 0x00; _ledBuffer[1] = 0x00; _ledBuffer[2] = 0x00; _ledBuffer[3] = 0x00; } - for (unsigned iLed=1; iLed<=ledValues.size(); ++iLed) { - const ColorRgb& rgb = ledValues[iLed-1]; - _ledBuffer[iLed*4] = 0xFF; - _ledBuffer[iLed*4+1] = rgb.red; - _ledBuffer[iLed*4+2] = rgb.green; - _ledBuffer[iLed*4+3] = rgb.blue; + unsigned iLed=0; + for (iLed=0; iLed < _mLedCount; ++iLed) { + const ColorRgb& rgb = ledValues[iLed]; + _ledBuffer[4+iLed*4] = 0xFF; + _ledBuffer[4+iLed*4+1] = rgb.red; + _ledBuffer[4+iLed*4+2] = rgb.green; + _ledBuffer[4+iLed*4+3] = rgb.blue; } + for ( ; iLed < max_leds; ++iLed) { + _ledBuffer[4+iLed*4] = 0xFF; + _ledBuffer[4+iLed*4+1] = 0x00; + _ledBuffer[4+iLed*4+2] = 0x00; + _ledBuffer[4+iLed*4+3] = 0x00; + } + +/* +for (unsigned i=0; i< _ledBuffer.size(); i+=4) { + printf ("i %2d led %2d RGB 0x0%02x%02x%02x%02x\n",i, i/4-1, + _ledBuffer[i+0], + _ledBuffer[i+1], + _ledBuffer[i+2], + _ledBuffer[i+3]); +} +*/ return writeBytes(_ledBuffer.size(), _ledBuffer.data()); } int LedDeviceAPA102::switchOff() { - return write(std::vector(_ledBuffer.size(), ColorRgb{0,0,0})); + return write(std::vector(_mLedCount, ColorRgb{0,0,0})); } diff --git a/libsrc/leddevice/LedDeviceAPA102.h b/libsrc/leddevice/LedDeviceAPA102.h index 3cc4e518..405e54d8 100644 --- a/libsrc/leddevice/LedDeviceAPA102.h +++ b/libsrc/leddevice/LedDeviceAPA102.h @@ -21,7 +21,8 @@ public: /// @param baudrate The used baudrate for writing to the output device /// LedDeviceAPA102(const std::string& outputDevice, - const unsigned baudrate); + const unsigned baudrate, const unsigned ledcount ); + /// /// Writes the led color values to the led-device @@ -38,5 +39,7 @@ private: /// The buffer containing the packed RGB values std::vector _ledBuffer; + unsigned int _HW_ledcount; + unsigned int _mLedCount; }; diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 6d737ec9..7cf2385b 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -124,8 +124,9 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) { const std::string output = deviceConfig["output"].asString(); const unsigned rate = deviceConfig["rate"].asInt(); + const unsigned ledcount = deviceConfig.get("leds",0).asInt(); - LedDeviceAPA102* deviceAPA102 = new LedDeviceAPA102(output, rate); + LedDeviceAPA102* deviceAPA102 = new LedDeviceAPA102(output, rate, ledcount); deviceAPA102->open(); device = deviceAPA102; @@ -349,6 +350,7 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) { std::cout << "LEDDEVICE ERROR: Unknown/Unimplemented device " << type << std::endl; // Unknown / Unimplemented device + exit(1); } return device; } From a960894d140405e29edb413685e700d2f1714212 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Mon, 16 May 2016 02:39:17 +1000 Subject: [PATCH 04/63] Another option for Ws2812 - direct spi from the pi with 1 wire (#631) * Removed -HUP so the default -TERM signal is sent instead. - hyperiond only listens for TERM and INT. HUP is often used to get an exe to reread its config Changed pgrep to add '-x' so it wont partial match on the exe name. - I have multiple instances with multiple hyperiond-instance1 names - this ensures the service script only kills the right process * reversing errant change to hyperion.systemd.sh * This add a new device type - ws2812spi. I've (ab)used the SPI interface to send the correct timing pulses to keep the ws2812 happy. THE RATE IS IMPORTANT! A FIXED CORE_CLK IS IMPORTANT! Attach the SPI MOSI pin on the Pi to the DIN pin on your ws2812 "device" : { "name" : "MyPi", "type" : "ws2812spi", "colorOrder" : "grb", "output" : "/dev/spidev0.0", "rate" : 3800000 }, * updated hyperiond.test-binary * Updated default SPI speed to the "correct" value. My Pi was undervolted so was dropping the core clock confusing everything * Code cleanups explicitly set the final 3 bytes to 0 * Removed latchtime option - not applicable * updated test binary Former-commit-id: d3c19c8374999f7a554bb25ca181a8a483f86289 --- hyperiond.test-binary.REMOVED.git-id | 2 +- libsrc/leddevice/CMakeLists.txt | 2 + libsrc/leddevice/LedDeviceFactory.cpp | 11 +++++ libsrc/leddevice/LedDeviceWs2812SPI.cpp | 57 +++++++++++++++++++++++++ libsrc/leddevice/LedDeviceWs2812SPI.h | 52 ++++++++++++++++++++++ 5 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 libsrc/leddevice/LedDeviceWs2812SPI.cpp create mode 100644 libsrc/leddevice/LedDeviceWs2812SPI.h diff --git a/hyperiond.test-binary.REMOVED.git-id b/hyperiond.test-binary.REMOVED.git-id index dc9b6471..007dd52b 100644 --- a/hyperiond.test-binary.REMOVED.git-id +++ b/hyperiond.test-binary.REMOVED.git-id @@ -1 +1 @@ -5d75f380f2bd74d3cd6b574f0a7d05850786216b \ No newline at end of file +23f1b917ec588d71521aa698edf446a2e8c0ea5d \ No newline at end of file diff --git a/libsrc/leddevice/CMakeLists.txt b/libsrc/leddevice/CMakeLists.txt index 6d89205a..2d2ceba5 100755 --- a/libsrc/leddevice/CMakeLists.txt +++ b/libsrc/leddevice/CMakeLists.txt @@ -75,6 +75,7 @@ if(ENABLE_SPIDEV) ${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.h ${CURRENT_SOURCE_DIR}/LedDeviceP9813.h ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h + ${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.h ${CURRENT_SOURCE_DIR}/LedDeviceAPA102.h ) SET(Leddevice_SOURCES @@ -84,6 +85,7 @@ if(ENABLE_SPIDEV) ${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.cpp ${CURRENT_SOURCE_DIR}/LedDeviceP9813.cpp ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.cpp ${CURRENT_SOURCE_DIR}/LedDeviceAPA102.cpp ) endif(ENABLE_SPIDEV) diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 7cf2385b..689ef91f 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -14,6 +14,7 @@ #include "LedDeviceLpd8806.h" #include "LedDeviceP9813.h" #include "LedDeviceWs2801.h" + #include "LedDeviceWs2812SPI.h" #include "LedDeviceAPA102.h" #endif @@ -142,6 +143,16 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) device = deviceWs2801; } + else if (type == "ws2812spi") + { + const std::string output = deviceConfig["output"].asString(); + const unsigned rate = deviceConfig.get("rate",2857143).asInt(); + + LedDeviceWs2812SPI* deviceWs2812SPI = new LedDeviceWs2812SPI(output, rate); + deviceWs2812SPI->open(); + + device = deviceWs2812SPI; + } #endif #ifdef ENABLE_TINKERFORGE else if (type=="tinkerforge") diff --git a/libsrc/leddevice/LedDeviceWs2812SPI.cpp b/libsrc/leddevice/LedDeviceWs2812SPI.cpp new file mode 100644 index 00000000..7b915595 --- /dev/null +++ b/libsrc/leddevice/LedDeviceWs2812SPI.cpp @@ -0,0 +1,57 @@ + +// STL includes +#include +#include +#include + +// Linux includes +#include +#include + +// hyperion local includes +#include "LedDeviceWs2812SPI.h" + +LedDeviceWs2812SPI::LedDeviceWs2812SPI(const std::string& outputDevice, const unsigned baudrate) : + LedSpiDevice(outputDevice, baudrate, 0), + mLedCount(0) +{ + // empty +} + +int LedDeviceWs2812SPI::write(const std::vector &ledValues) +{ + mLedCount = ledValues.size(); + +// 3 colours, 4 spi bytes per colour + 3 frame end latch bytes +#define COLOURS_PER_LED 3 +#define SPI_BYTES_PER_COLOUR 4 +#define SPI_BYTES_PER_LED COLOURS_PER_LED * SPI_BYTES_PER_COLOUR + + unsigned spi_size = mLedCount * SPI_BYTES_PER_LED + 3; + if(_spiBuffer.size() != spi_size){ + _spiBuffer.resize(spi_size, 0x00); + } + + unsigned spi_ptr = 0; + for (unsigned i=0; i< mLedCount; ++i) { + uint32_t colorBits = ((unsigned int)ledValues[i].red << 16) + | ((unsigned int)ledValues[i].green << 8) + | ledValues[i].blue; + + for (int j=SPI_BYTES_PER_LED - 1; j>=0; j--) { + _spiBuffer[spi_ptr+j] = bitpair_to_byte[ colorBits & 0x3 ]; + colorBits >>= 2; + } + spi_ptr += SPI_BYTES_PER_LED; + } + _spiBuffer[spi_ptr++] = 0; + _spiBuffer[spi_ptr++] = 0; + _spiBuffer[spi_ptr++] = 0; + + return writeBytes(spi_size, _spiBuffer.data()); +} + +int LedDeviceWs2812SPI::switchOff() +{ + return write(std::vector(mLedCount, ColorRgb{0,0,0})); +} diff --git a/libsrc/leddevice/LedDeviceWs2812SPI.h b/libsrc/leddevice/LedDeviceWs2812SPI.h new file mode 100644 index 00000000..e82d9134 --- /dev/null +++ b/libsrc/leddevice/LedDeviceWs2812SPI.h @@ -0,0 +1,52 @@ +#pragma once + +// STL includes +#include + +// hyperion incluse +#include "LedSpiDevice.h" + +/// +/// Implementation of the LedDevice interface for writing to Ws2801 led device. +/// +class LedDeviceWs2812SPI : public LedSpiDevice +{ +public: + /// + /// Constructs the LedDevice for a string containing leds of the type Ws2812SPI + /// + /// @param outputDevice The name of the output device (eg '/etc/SpiDev.0.0') + /// @param baudrate The used baudrate for writing to the output device + /// + LedDeviceWs2812SPI(const std::string& outputDevice, + const unsigned baudrate); + + LedDeviceWs2812SPI(const std::string& outputDevice, + const unsigned baudrate, + const unsigned latchTime); + + /// + /// Writes the led color values to the led-device + /// + /// @param ledValues The color-value per led + /// @return Zero on succes else negative + /// + virtual int write(const std::vector &ledValues); + + /// Switch the leds off + virtual int switchOff(); + +private: + + /// the number of leds (needed when switching off) + size_t mLedCount; + std::vector _spiBuffer; + + uint8_t bitpair_to_byte[4] = { + 0b10001000, + 0b10001100, + 0b11001000, + 0b11001100, + }; + +}; From 8310a6d9d0cc3293cc4ee452a8eba0d9c17dcf4f Mon Sep 17 00:00:00 2001 From: recliq Date: Sun, 15 May 2016 18:39:26 +0200 Subject: [PATCH 05/63] added simple TPM2.net support to UDP output (#627) Former-commit-id: 59356ae53c90e178a4bc198c6babc5832bb15d12 --- doc/UDP_led_driver.txt | 9 +++++++ libsrc/leddevice/LedDeviceUdp.cpp | 41 +++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/doc/UDP_led_driver.txt b/doc/UDP_led_driver.txt index 646abe21..f7a3f589 100644 --- a/doc/UDP_led_driver.txt +++ b/doc/UDP_led_driver.txt @@ -55,3 +55,12 @@ Packet Format protocol 2: 3: 1st led# of this update - low byte 4..n 3 bytes per LED as R, G, B +Packet Format protocol 3: (simple TPM2.net implementation) +0: 0x9C +1: 0xDA +2: number of databytes (leds * 3) - high byte +3: number of databytes (leds * 3) - low byte +4: fragment number (1-255) +5: number of fragments (1-255) +6..n: 3 bytes per LED as R, G, B +n+1: 0x36 diff --git a/libsrc/leddevice/LedDeviceUdp.cpp b/libsrc/leddevice/LedDeviceUdp.cpp index 129eb47f..1fc67647 100644 --- a/libsrc/leddevice/LedDeviceUdp.cpp +++ b/libsrc/leddevice/LedDeviceUdp.cpp @@ -155,6 +155,47 @@ int LedDeviceUdp::write(const std::vector & ledValues) } } + + if (ledprotocol == 3) { + udpPtr = 0; + unsigned int ledCtr = 0; + unsigned int fragments = 1; + unsigned int datasize = ledValues.size() * 3; + if (ledValues.size() > leds_per_pkt) { + fragments = (ledValues.size() / leds_per_pkt) + 1; + } + fragment_number = 1; + udpbuffer[udpPtr++] = 0x9C; + udpbuffer[udpPtr++] = 0xDA; + udpbuffer[udpPtr++] = datasize/256; // high byte + udpbuffer[udpPtr++] = datasize%256; // low byte + udpbuffer[udpPtr++] = fragment_number++; + udpbuffer[udpPtr++] = fragments; + + + for (const ColorRgb& color : ledValues) + { + if (udpPtr<4090) { + udpbuffer[udpPtr++] = color.red; + udpbuffer[udpPtr++] = color.green; + udpbuffer[udpPtr++] = color.blue; + } + ledCtr++; + if ( (ledCtr % leds_per_pkt == 0) || (ledCtr == ledValues.size()) ) { + udpbuffer[udpPtr++] = 0x36; + sendto(sockfd, udpbuffer, udpPtr, 0, p->ai_addr, p->ai_addrlen); + memset(udpbuffer, 0, sizeof udpbuffer); + udpPtr = 0; + udpbuffer[udpPtr++] = 0x9C; + udpbuffer[udpPtr++] = 0xDA; + udpbuffer[udpPtr++] = datasize/256; // high byte + udpbuffer[udpPtr++] = datasize%256; // low byte + udpbuffer[udpPtr++] = fragment_number++; + udpbuffer[udpPtr++] = fragments; + } + } + } + return 0; } From 04414b11b929717784bff642f9cd58090759d384 Mon Sep 17 00:00:00 2001 From: brindosch Date: Sun, 15 May 2016 18:57:16 +0200 Subject: [PATCH 06/63] cleanup Former-commit-id: b2dbb71c420528b78fd374dbcdba36bf4139c1b4 --- doc/UDP_led_driver.txt | 66 --------- doc/datasheets/APA102_LED.pdf | Bin 282134 -> 0 bytes doc/datasheets/AtmoOrb_sample_config.json | 165 ---------------------- doc/datasheets/WS2811.pdf | Bin 323304 -> 0 bytes doc/datasheets/WS2812.pdf | Bin 278275 -> 0 bytes doc/datasheets/WS2812B_preliminary.pdf | Bin 355361 -> 0 bytes doc/datasheets/fadecandy_opc_protocol.md | 79 ----------- hyperiond.test-binary.REMOVED.git-id | 1 - 8 files changed, 311 deletions(-) delete mode 100644 doc/UDP_led_driver.txt delete mode 100644 doc/datasheets/APA102_LED.pdf delete mode 100644 doc/datasheets/AtmoOrb_sample_config.json delete mode 100644 doc/datasheets/WS2811.pdf delete mode 100644 doc/datasheets/WS2812.pdf delete mode 100644 doc/datasheets/WS2812B_preliminary.pdf delete mode 100644 doc/datasheets/fadecandy_opc_protocol.md delete mode 100644 hyperiond.test-binary.REMOVED.git-id diff --git a/doc/UDP_led_driver.txt b/doc/UDP_led_driver.txt deleted file mode 100644 index f7a3f589..00000000 --- a/doc/UDP_led_driver.txt +++ /dev/null @@ -1,66 +0,0 @@ -BACKGROUND ---------------------------------------------------------- -The UDP led device type can be used to send LED data over UDP packets. -It was originally designed to support an ESP8266 Wifi module based WS2812 -LED strip controller. - -I've used this to support : -- A string of 600 LEDs as xmas decorations - The effects development kit is great for these scenarios - -- a 61 LED collection of concentric circles - This has been used as a "night light" and a super lo-res - TV - -In each of these cases, the hyperion-remote iOS app is a great way to -control the effects. - - -CONFIG ---------------------------------------------------------- -Simple example for devices that support a raw binary protocol. - "device" : - { - "name" : "MyPi", - "type" : "udp", - "output" : "esp201-0.home:2391", "protocol" : 0, - "rate" : 1000000, - "colorOrder" : "grb" - }, - - - -If you are using an ESP8266/Arduino device with a long LED strip, you chould use this alternate protocol. -The ESP8266/Arduino doesnt support datagram re-assembly so will never see any udp packets greater than 1450. - "device" : - { - "name" : "MyPi", - "type" : "udp", -// "output" : "esp201-0.home:2392", "protocol" : 2, "maxpacket" : 1450, - "rate" : 1000000, - "colorOrder" : "rgb" - }, - -PROTOCOL ---------------------------------------------------------- -Simple UDP packets are sent. - -Packet Format protocol 0: -3 bytes per LED as R, G, B - -Packet Format protocol 2: -0: update number & 0xf; -1: fragment of this update -2: 1st led# of this update - high byte -3: 1st led# of this update - low byte -4..n 3 bytes per LED as R, G, B - -Packet Format protocol 3: (simple TPM2.net implementation) -0: 0x9C -1: 0xDA -2: number of databytes (leds * 3) - high byte -3: number of databytes (leds * 3) - low byte -4: fragment number (1-255) -5: number of fragments (1-255) -6..n: 3 bytes per LED as R, G, B -n+1: 0x36 diff --git a/doc/datasheets/APA102_LED.pdf b/doc/datasheets/APA102_LED.pdf deleted file mode 100644 index 2a45763169a8ae37e74cd36b31a8da2916c7f69b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 282134 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%0D;$mulI_m%O<5{>lSeRvi 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 set effect to "" (empty) and input the values [R,G,B] and set duration_ms NOT to 0 (use 1) instead - /// * effect : The effect selected as 'boot sequence' - /// * duration_ms : The duration of the selected effect (0=endless) - /// * priority : The priority of the selected effect/static color (default=990) HINT: lower value result in HIGHER priority! - "effects" : - { - "paths" : - [ - "/opt/hyperion/effects" - ] - }, - - /// The configuration of the Json server which enables the json remote interface - /// * port : Port at which the json server is started - "jsonServer" : - { - "port" : 19446 - }, - - /// The configuration of the Proto server which enables the protobuffer remote interface - /// * port : Port at which the protobuffer server is started - "protoServer" : - { - "port" : 19447 - }, - - /// The configuration for each individual led. This contains the specification of the area - /// averaged of an input image for each led to determine its color. Each item in the list - /// contains the following fields: - /// * index: The index of the led. This determines its location in the string of leds; zero - /// being the first led. - /// * hscan: The fractional part of the image along the horizontal used for the averaging - /// (minimum and maximum inclusive) - /// * vscan: The fractional part of the image along the vertical used for the averaging - /// (minimum and maximum inclusive) - "leds" : - [ - { - "index" : 0, - "hscan" : { "minimum" : 0.0000, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 1.0000 } - } - ], - - "endOfJson" : "endOfJson" -} \ No newline at end of file diff --git a/doc/datasheets/WS2811.pdf b/doc/datasheets/WS2811.pdf deleted file mode 100644 index b08b0171b8f27276798ffe58e554acddcbd39f33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 323304 zcmeFZby!=`mNy)vMcP7Xf#NA{1xibb6DY-t1Pe}ar??g}d*5%uvvW>P4mo@6z1DB9^;_#4Mx}R>9Ne65@EO-uhsW@_ zpTB(m(a;iKn+tuMOUA~)%;fFAY{dU%Bg3U?;^w4_Z(?iw=RBUjo-ZWC_1?tR%*p&Y z2z^8upG(rh+R4O$OVZlF$>g1h(MMwwd=U|RM<)jp0~>s|x!0;M0dIB1pBoq$7Mhu6 zMWzmzWSSXck_Ns0>=%fyCz{%I53m)82mW)Nzy8x-ulVQp|8nJ5f9u1Wf9r#av!Ro_ zoyos+6`u=gVT|q(H}}hz_*~K^7G~y7&p|xs{kIlQj!GsD;va47KH8etIz8vZ=Mw*D z{n0_i&cMio>z#>$_>UewBp{-GO7!?K5j{C22{jwz3wBmU78XvPw|t!3;8!dx z0ty1)cT%!)vK+h+C`4NQt&FVHpC7?^_~;Q4Aralvr*u*;Szb#0zkc2Q01)9~QenTx z!k`0S5@BEwVcc~BfB*o-J#=sXboj3?3`{KSd-rkBeSUyGq2@6F69Wqi6C3N^J#1|B z*xP(n%cVhhQ{`e&aUpB-oE~^@rlW)>6zKN<(1X7^^MJ~?H$DN z$?4ho#pTuYAGt69SpOo{ze@HWWI*ua%ET3>`-CNf~&S84-U(`-^1%J;D6`w%&SuyAPU*Tp z_u=xzlIxRe^{704>(BzNR9-VR3HRHch(mp_X;mPX{GK+F{msW`yV2>KokpYd`Wuo~ zZohY0PWkh~b8Cg=c#J(@$9T>yTIvHkykLn~-z$9IL)*2R3zfR5w?1W--(KwurW?^j z38&CcK%#coI~#J6;f3H0<{P=2){y-Mn(WZ&uRZqmk2_U*KReBJs(qQPVL?kvzMz^854IWr{S;cIn=HdSp) zD=IJMhAk&3t<~y0^haY=^6Q;YDj(U|Dg;xMd$oictmjgH9b9I>Mnc~xKpUJVoKz+! zuMSn}Z}Z&}+f^tHYlpF9V*dZ2VQ2emc(lTt7P*{km@@r#Eg4O`$eRU=kGhIa*I z?0qS5DMh=FWYzQttrxtVY*R>z5zho2W>*=jM_dW`14X4iJy;1E`iagncl^Ps%Ot06LQ(s;?z| zNCzuC^9dx4>n#vzPZL0lWzg{a*AKQoG5sa)fe5I8^dB zKkvu4D9^Vya#Y!pS}`l0eW}~Bibtqdne$pS3cc(iTd^<_<@Kq=-QV#%z1~)QQY;sb z`!kt|(7ePs_E5<6^hkeV)82(90De^$1K` zX<@pJ6S@P?sUV+(wZavrYTJ5yH=32Jt6MxFW8oZTOyH}vE90}@E=YD*K29n5mhvFY zxKtTLr#xoWioI0IyVWG-W>ECh)BgPAURp zDFprBxrF8mveCMJD9&Ms`OJbbnNqSFPa&iYXT0j|?{2R022LP!rh}Vpi&DIZgKWhW z27cTDoLsNdMQZvju3d7<^`bEQ1S@Eaf66>a-|M*pOmFMP9!={^Qb%<_pP3CPs+;e6 zb4-9F-Lj0VEZuN}HVh7Y3b1xnPcsO2v?}h;VbTr1YVB{$@aX`}nWy7dR?c&vI5&aq zK9lg}UkGGLff|06DgXz7Kc88N^Pq^bX1D?k?;2dSj3mbBpkdM5JTb7T1&kg>odKy+H2ydQEJ6+ z$S!Sxw5g#BsJ;Hdl}nfbvYd5JguA|M3L?8tVlVo0j@RnJk; z{uy}S^mnmLUbK6mFeTPDi#Btn z)i-1NMd+59ZpcyHWT{(ilgS_KGFqEIFRlK0gO*)dLcTUx-S>pZ5Efa+Q+7|sgi(+< zmc;&%`L@78R&ML{i`j@~#eQH%-7;)Awx7UR<9iRIc?XEO!-;*;Wx&1m3vOoZN)}?aaBk2hWYOr_^Je;!!9#(K^vXT= z<5UD!JjJ{AqeH*E##!fLe`02A@zmE5K4RCm>@795fj<{H_Omrs!~)dFF!Qq;*rwv7 zTwIiMDC9)5Ve6mNR^{YL^yWtLhK_#cdu!azgrk1-XLCEaNS4hkPC9FI&`m7p|Ezd^ zlbNn_jj=GD=$6v+Y_3Gc##lZtUHS^|*YgXZ4?wZYjfQpD-xeb&{y!beC0L^D7 ztZg-`k-Q+t*TLxK^*827MF{q7>0m*Ojf#RQ6TC zY>FVM02Bn|Jy28|x^ENqK;eN31H;5N?rH8?e&dw#JlC=k&v?qTPNeHkY#4rk-67c)h*J{r+Fjatwq@H2=DeklCiM|<+bZ*OON&kv2_%dYh9X8K($_15r)JuuX)Oo z47*u%J+@r7+3e)?b%0i_mjBv}*!0(Za1X8A(PNy# z;7?vr34pX`qCWeiCd-w4y#qY4(yk@9WfC+BQ^dzHNdN5M^I9)%xs`B!%cWjN#$oj$ zI;!uS#;@sifyeeNMrdOl7WciM@X@9BFY#Jhd&Z84C0Qx3*uFLoMCVCNOp`Efmzd@Q zc~ktn#Ls{}roa!yn!$jF(VozFx6STHg}v7eSB5-?2I<;ySx?m)i#MZ#RCx}5Ip#aFS`qD5YsO{k?40MoWlpMSuP7y@Nigdk?r~;ze8Vq_-PO0FG9j&F2d}AwMN}4B2{$BIy832` z7sK^exL_1A+LGhz?VJ+hMK?V+NvG7emwQ&9^GrFrQsWIBWcV3I^;!fhi7H>lmbb^l z*p(^qS|>_OTgBbkF{k9RNTq5O1Eq_= zOv3(TTGkym%j8bHyx_q2zT_>3Y<7k9PN*mc9|ymBu3G8*n^4Jsf_p`n<9-wT6opY= za!llF!)k=O93rhVB{lYyWP|{0USA>seL@e_4^j%gnw&5I`h5_i5P@QrdWfUR0}kA8 zPjsVkjH!K|YAb1X*ftr2DS6_@$JcKvD=(&v$MRNbTy_=Hx9|RK_;@=A7CVdk5utoJrVY zL%DfWx+^6Y)dI!J`!)JHWGureW+)t|1YUQ`)0PkG9~nt~-;^F;S^J@YHdv>NYapt| zeoPV}J=z-@UhuH=rPwK5i>$K&M2|U2J#<@8I&_S}K7T6ExHjRn=Ax9N?K)#v9V>7% z&!aBrEVw2O#Qc^N(pll(4?Gfsa?d zcPuWw2M&Q~>qt1;#{5`bwIkPXqRWF*8Z9VX|I_-2j1DON>F}h2uX38)u6DS+LfNh& zJ>QUC>{%_1u>POgML+379&n$Ntk%`>Y8_OcSaX3omLEI%j$oXUOa|r+bDCB1bA#OJ z`|C^-{Hy6pEe&NRZlf_N#AhQ+?f}4#g>W@BRi$D8{!73fTX;}jSFVM_0k`iOdzNDTC!S)+}14F@kuEL62vOB-{5LT_luM3 zg68ELI%KS~UlAf`w^6{)aJDjPEVTrQ$>r}~Up!uU_mj712i&oMHCIulm@Z)ZID>uK zsA7WWV*D_D(RYsjttZ@4dK$KKkX3^qh#^@|3G6=z>G4q$Nk!~gB^}RF<@l8rVAFKx z$LYDv9)xR62&b0U8Wt9*s;H_Kvi5yZDz0HG!>^$$GoEcW#IRWQD(a78k?rf9eHYBg z*`LVBClw9YvE=`{{=!1tH)GhoJtJXPYogbPsIyQI-^;OI=jW!XQGY21F+^DjB0&uJ z_bn~}erYpw9$03XU1iV@Ifv?M7I_BV*O>Qc=L`P!nF18kI z>O?-Hn5qfa@@)8C--i;v!atW6_$l}R*M^o%I+Eq$0%`TV>YOJI)WpXEw^19~`^p26 zu%r2mo^p&IpP=AHnf--rk zagWd0Fs+5YZ`m-`q*}Cx@cK=Ad^FlH%%H#ZpFX15n$v6Y3OD3u4o;b-32O1UUy)z7 z;#EHVhzUbb!8O#GWTj^IlD%tFp1r`*R%--7m2onVj>^esuisU+xRJJXQYp-BV6G_7 zNta|ZCTZ}@@9-pRtTK7ALq_tv^z%uiPnl5wo81pT0e=Vu%sfG+EgYgkH~v_4i;ZE3 zE{JU+%Ys<7u*TnX`w_mSmBxu(dJj)=oZ+nfOVFb&Ev*D}s4zJ5_u>WF!D%NqPztHv z2W%J~OkwNS@(#NK%s%F8BNIef-7Iv6l$XMJExt~s_8r)lI`|x<-lEv0g}+NGn61RQ zLLS!IELe07-fVHVVwGh3QG(@1Xr#A@-(UJ^7>7t~G_LUxsP6Zzj)g$`6})!t6GMX# zq4=c_oz>$pim_bc)&9Zlp>|p6ix*>4IR4Ix`@#e-_mj#HR7w2ISpJt0)1Vf;hbybh zq+Smh3P>3K7_G*?H`ssleJBxvUG=zhd7K{1^Q$@LcEksXgDeyX7#}`Uc6{bxU1zHXK^xArS*8t?=2ejqrUyo@70XQYrj_6D{g)JX;(JnXbTR;;rNvp}m90y@XN={7)xD4t zJ`0?N>uar-1T}30Zb}H8>r~F1CiqD+%+f_l?J8&Ho2N653yG5jz87=80|=!xFjK2u zpguX3#Ar6-&~GT}%dW&&%xR~|vX=B11oIb-sNzkP_Gng)vX#j{S#HZ`e2nD0G3laL6!4WW?&|CXKp1Q@$Z+{Kk*T zo=MM-x;R2LdxLgJmJ9cZzcN^>jRa!5(C2x+iTKnQA7|rMf4hSzy0?gnB#>}VoO6jz zaGd-x(X8{J`VSTb|D$X0zv~}H)Jn?X-XXz~0;N@AKkZ>dJ#ZKt;12h%z60z7pJ>x_ z8UPrQr-jg5xz48kA#I7_=bLtmcoEN9Dw5+`@k{&LVk3X7J+>1o zAMRKZs;`;aOu`f)h zLo@-jbeRhK_8W$nXP++=3pN_Da^R)2j>dFGL)hb;Vt$D|7|1L&53Vl7wRVtG9@VA#Xo*Nd^r0-{6);r@= zW}xc9Y3|$QK|fqGOb{>ZV*=7BUZ3rNA=guvi6<(iWSYmSQpFGnl9lwWf2S7z4-e`e z?>OzYD2*Zl^Kf5;CH|#D?N&v^0P`7W>GIY1p7*mVolj$2$v(ezBF0J9lT*Wd;0uk% z<2rACb=3p=TZ(bxAGj@t8bIFq?%ii^B03lkC7=SgC@V8&!`QzZ{B3T8dR9sWojv&x z7r$ArxWP9dJM^Ftmxj(Uw#ed=2 zwdp){^H!kLN=qwYf4zWKzmtLRXeqk_f;QB+t*YJ=66_%gK^vv%Vy0 zaJx^QTUSfxc@>^bo?9+8Ihnt%dfe*3t{weEws!rsEs*^V;EQafSSk7ved#P{v9j{3 zC2N~lT_I|Pnis0XQ83Ttmb)CZ{Of4Q3i>d6W$))!pNuZIc{WVq9x+7pKWlh8;LbE5 z>)Ht-ckC|OTj=$)y=FQ?<+JO13uFWCCNa0my(qOZykph(-Oc>l)ozGgcOyGL`GTUc;&<2V!o|A}TcriGfno(yW`UbGib2*U%na?B8Fnvy;w+%UeVWx? z#JVeqXjr8~htU7<*o31d#}Am9X>`!+S>%vLDV(Hl{Ze1aHpw^PgbY;!fkwaU zo8w4VTTb*IUD3wwmP#*`8ri&t)p^yl44PsesRAjM^_`&RHIkfF4Kk-~Hjtmm%3{ zU`^g{Bo#p!1KJ!C5UpezcwETim_TF`ilj`B0uTGKG<{Zif&?Nx z>w~&rrR{GjgNUCv6^ED8_jI0W{WxVciWxJ@AJv@GYbe+$e3ZMR-E7lA*j{br+toFj z{>3=AJOJ&q6aQ^A{&gFa$3cv-;!)N*3z93bHX4YF^}<*wrr7%Aj1#r;)$cxbaXI(} zaDrm9WT}ADoaxh<^zl&6#CPC(#-nD7)GK8HFaF`P^7#7UKnF9Krih!W1LTBHfQ$1g zRK0N6ir`QNZ4H`~0e{CV{xehgKX&Yc+d8rpS0AX9b7IHt(QpX71N3INpGDjO#I?o} zx}JtRYC-)elL-0ZNc2x7xFbh$MiGdmiTAG6mGiC1Nzn4 zfVz>0*z{<^gN!Yo?&f5TC2~Dh)sif>eh)uBx)vBoob*+?u9j^Ir7Y_`4%-hL#L6Sm z=*gAf#%KAniw0El$M{+-#JKkaV64G^oY+4*(ZtpGS^#wFR8BPL-7%Uaep)Gz8mQt& zSW({e4$(Y95~QlaV+4?Gb@P()Slue!Q4W)^pqF(nkY9Rn{#9_mY72WRhM^*T$Fj?9 zDW!06I|0*^Kh$Qy#b8Uyn^h3y~tv}qC(T>tL)z|Gk^!xSAv1gNCb-HNAmf%^3$jl z!?@zAmP@^>2#BIMIr73Mz*Vgc$+=tPGtYIK-ZXb&5AHI{3qUi@nw4Arj9YD6xcKn?x)L-au`D7pA{0((nkA^rI zRNSufst7?sA41pPj6CM!1}>^*Z*n~Ja{QS8C}P1JU5!}(6CI!btMnM`v525AhEw!b zP1w@#X}AH)sR%0QNXS8;ku8fC$LW1`Zs{;)`jVCA+=JjbR;A^rZd@d5++I5UQCEBm z?khs3b?>#U9FevbsTz0Ns;pmIbu?#;`;2wd&JdBwCD;J zNfwfyIUVVo>0QzD5DrkC=&cs_t<)~EWaL9Kd$77WgC@QG9~KDuRsFj!e9^oLwU@*( zv%bvi=OvYeF4S4>G$3x-vi0DzHVSGIj!@4o+D;CuEi$fq6VX6fD6D!-G&9+MoLn1v zuA&S@yBNfOEcP#pgT2pFDWu$s`7vd%>`C$I$B+UPqq;vT1$c`+ojP6d1@%P8S|6dg zgydAIgV=UaN>^A3jBM0vSuOTx;O#vw3J*h);`IPM~@&df_c4KyxMkIt%}( zx`@G+4kw&*^6cdwj1)i|Gfa@vU+b1sUJrLGYq5Dk#HINA=qPb{R3E z*@3l#y$Bm2WaXodkQO6nfiEO=W?YV6FQqBUD zhMAz4)BM2IfLkGDJ-(-SOw~@Fx|5aX1r0AoT+mxKSwyYyVi#I{$k1Sk(ScO_q@__% zQi1%8PA8s>Pc=n^9B&+SQ{7IO_DuNRvIoJ<@XKUqI9ZoUgvFN!Mf3yF8R22g*;Y|- zo--(7nM`DO*$VqC!sqtX)kkXv&Q{VqFRUdyB8>)%s(+foD;O5w4DNm@)`1*sE|{&K)YT=Bvz_ljEw zeA4H-6Q#B_e39sML-Wb2|NOwigczb{zxDUL4m?$7VW8rq(X6L+bmU7)GLvhXY&b;z zP1;DZyk@#j@h71uN2WLjDu+)+^=qn zT*e40KB-|0Y;W9N*#v%7iOwf@a_J<*qEa$`riir-ZSb_2a`>=1u>N{S^$zfsJ$~X7 zVTqPWS-WmGcr&TPXaTq-@6z#9!OPlCwS6K;E_H}QhUckvuTg!-iv6UnH2o1z|F*nv zxOyqt1BDp}pmP>z4aS5S;yXVtP?APd1Ken+%~WC!f$6Ax&cpQ8F=gqJf$1p8_abCq z3B-w+t^#nZT}kr51UsqNwM30OzylxGEqA1M&Ej+zt@)xZp1LxA)C}wlOt@pDHkMt_ z;O@U3>+y0I1rBrPn-hYkISV(p5)HPbY+0ZgwI3e7Xv4>e|MV_n2*Di+JbPJ;atBW} z6dGD=hLd&c&alv|{Z@|%Iq;rb5!|kd+9bi5u>*^#3z3+e4-;##l52#-wbUMib)YrC z#nCGohL-Er*HdLH8XT(uB75e^9YZ68MVEf@mXs<_JGEGwcouO|_U*VQNgHC~l33hC-6gWA4ZG0JQ=-2(Vx>auwYQLdf}5}|t%%Y{??k{%J5QYc9~<@8(i z>^TnBFPtd(n2vO+$;iGuOUy+?T1q9(q#|8?Ra@H*3$}lxG+m2gNnR;+1pO|@HbiG( zLWsO%c0D`9HqteC4JDP)|1B3Lt&`h3TEA0@OMg`MmGG(M6dBPXPcYa|KhY;*S9|2L z>HUOC-!#wq=~78E;STuW*hbl-$&oAbVKcK0dra7&@lkn5Nl}V)3sI`q1Z}LB6huQS z$iK$wxi0-P?(n13i~;z1a^VVV-|QB$FP$RSS$6A39`R`9L-Yv zF)t2AK78yh%v90<61pNLKT3*w(iJhvJtPVhupo8{$r#VLFFc3Lb7jHX^KAS>am0|9 zH!2i#?4o(xIW)1XA)}J^$^x)0BvB!y4Wx|0TFQ*JP33cg%g~9*-@@c)c=_di#XGKYCiyyxywW*l zNYN6tex$_r8{VL<%2d#xug`D#m}_6Cg3!1$EPCDFEK%^8!=Qu4T87r4H<^Zk?b&_3 z`T)Y6UpHLqI`=%e0? zU8?kN9@Ia>meGB<^OhxVkfPM;xL2siE71uY+>5;D0W!0?wzRzF7>dDYm|kP93Rgw> zr_#h)41NFoQxM4M2@`FJNrXDV;HWK&2lW3~N zvrV9P@|59(l9%){Tqj+TigyL9WL5G^aX%;J0r=Zb*q^*){ol(!{q6YiF!}bX;`BNT zH}UF_zNjMPYV(97Ao-LlINnf~jq;m_IYZkWz`6DMH#FTW`TS^nGe07uOJ%Ki>=}=; zDQug+RPNze+w*8VJzi>ZJZx{eMqT#qi>W4~?+|CQRaYrsggDB*TpiZ$vIbSwx__S9qYXn)wy0hl*am5yI1N=Wxq9z7MT*b5(Tc5senID!Qmn`-RvZ^zG#$@ zvfQrzNTIK31H0h03xCzK35@XRIVp!q=5bgE3sS>s*c#QeE?(MlY}6!n*gut`OC>RY znOU9z=6GQ*eEdG(C`3#8B%&l69(lIAYT0g=)#=Q8_?~c05G>sR`fKuFp&2i#O+nwH z{Wby%H$NBnO0)ikYHrr@OIi*>ChWO98YmE&eaT}1XH+37Y!Hgc0NHkBL8B+!)Pe&= zQvyB-nhg|%BoCb_rJ$kSlTY(Nw0y*xY|T+q{(0)oWk&RPoqM0i!716e5gIyhku<53 zvYqu$52c@#WW*9b_e?|A0TsiU8fzpy$;>>Y*$2GoEHMxDNfD`e#nxbSuIUtQ3?e0- zG->%ddU6+rZ)eVggI4U=JIk4(S5{;;Y{sO!X0D?hta5N33?!X$cPospgPLjc(x9C$ z-}S$TWW3SO+`ml4KWAI}PHiDMAZaxVeX%D@; z>OrUf3atO0@A7~0IE^*}C~-qt*ci$lY#TA`+ukdHGRpWd1r7k!j+`YP;E9MMV^}uX z6!i;tuU+Aq)7AB7VRWA4FCTtA=0=fH`Cm;3FSK!#4c4BpYSJ5)5*j}8aC0xNzG85n zT-hE@qPZY0;*ojro`zScADz?iAX0=2UAnHwm-1N65)dLiU(;ml-2sBuxAlT_NLU*k zsst^D6nN1=A4yW?e_$Z~J#mkbu%aO{x;(#yh*_(`IN%5NH~WM36N+j2orEdg0Q20U z;EI^1=EwHCOYgO`Y{=oFCqWSTA@WR|zr5q^+ZI&SYwnwv=jw$P+;6%A5V-YIF4oRv zNi*|3U_NTS1dd-pQ%95A%g83R4n9g&ZwtQ>rtI`4mg!is2qv{&U!lUe_5g0`KqRI9 zl10XCyWdEN@7A(E`vN4jh_e`OG%1X6Msq85Jcm#WnmT@6sF7vyV<7uvgHXSaBtW1t zhs#XGHgu{5cPgSfuT|B41TNb^Ry+c$BXN>RRMvXhU1JIw5+^Hx5X22LIk!DwaDE;U z9($R*;e6Wr!NNPSU#^x=9Pt@?N&mnr6)*o{yKzfh~7{ z&pvyT6HwvbTQ0N1+(54*;UjbiTv4PaRj_@sB!5Bsw&&Me^A74v%4jU>U<}GP9O6+= z)Ro)*i`DFY z0{r{~$v)-{+-jYjlW9%^)Hh-TQ5CxYr;ks|w?RQUwgprwaP?b)Y?d*yXqE{!x&S3X zj2}fTx$qZf_x=e&@c&2+V6gjMMlIiN-&R@B=-SoMND{@DLlv#}J z)O-&JwZ_t<6lA4gkt$(HzgY&u$;nDs|B%dj6~8lxIV&tVxTqdn1_?Kh-Yy^RfO~&` z($190+$n{X+L$nAI{uWhQ!GStCcU-w$y3Xm9Bbz5p$F=EnbSqeMDPbWLtoY;wB&wHo&5TbL8<>` z%W3}Lfs9P@YtcPUtHvX)kO!|Uo|UC;_BvkegU8Vd@FY$*s)L>6UrK}6swbsqlgA3T z`?pTHh%M-*HuvMVgN?y_SO;}?0KJNp^1655BRaoR-lBxsg&IEZb=2QJa)^F6bwT*x zsJBaTS*O}`&Mtmyrwlte)x{)uXF;;Cd(!kxaWwAhw@hs%R!qY=35N2vCoTu5Z zDtLZAQjHx?mi3b=4z+%tE6!S6sd^038YvAs$ZrZX{JQxG<$qFUo1J1xx)CkC3l8jS(#~sv;l$e(2`Y~pcO1AuA{IN%!3G(%D>sTZFnN>;FwnS9xSbqNx?sU(X zJ#c$-cK_I}+Jy2FU~E|MxQ7|8tXSY+^$;Xjr!1vF=OUXb?{nXrqjV>07XCG_EoVDQQ#<^zNeWeyEAy^~z+_Lz{-Ig)w9hPYbbyg$`|5Va z&&ncZJ#WeC--R86yXJ5{nio@|J#*+tbRL9O6#Yv%=ZvdM#hdeLFLe`7xAZUx_Z}o; z@-Py~e0!sRRHpqPf^?XNb3XLpj|x_@{>}8IxK|zh?COCf%oVd}>Q{pjPr{yt9zlKk zy@I19peKP!l$DZry(wMn+M6T^9iu3qCkfnog$HhLqz_Diayw_IMaX8?AL3v7U0BC(c(650mIZRU#J!%^Eg$i zvzyQ7JCko0cJEdD$xvnoCm`8Nju2B1U!|EH8oPhuQb1?kuO}5^{3c-_;`G2Sbhd)x zKU+8Pbjsl?O<{s6$rGA6#YBNGB;Cr3bCPk*C^7NTI93Y20mOykKkraz49Z|1C~g-7rAWV?M2Yc!g0%UzD1b=t26_|P}{Z% z@b=uQ`mGj-;X@=I{JF%7WhrG*xPcykWGMKHfvt+iD~A>|E5shV@W)wPJJTl}HYggh ztPS3!{J?F9w^DouXm{EB*t9{SC0@C|yk43M!{75w_O_rnd9)rLU6YfNY=lp5-!_N#0b;|?G^ zg37Lqqp;vL0x8QMc+{Y26N|b39k-v+csKd1HvBW+tDmdv6d4oO_)~ChgkaNU;9i4} z$bC=1eRfOYiFH#Gbz63E%}@5u8z!a8tm(eN;0$znpfL=nUN^b_Y2HCCc6rsPKjY{E z&QW#;!0z3K7ni##_ zN2_mcY-A^GIhZtwT5$Q!MFN`}V@>3DJa~4xt==yFQRRUDz>45WaEQ6uQ|FZ?JguEs zRo?RgKmA&G7?zds!gL|*qr7=Oct+2yM~C9vOiZ$eiEJt%WpWB zvX*davPX@q`9QS4bJjlIu@DHwOUNi(y)taR{<&PnWl;atRf4V_NnkZ0WLUx!cdz{z z+aG7f{|+!!PVqIqGJ40Q?L^7qls|Ex`VYzXWM3QpcKY(Fum76I>`3;65u=N@) z3hlSuf@JU4>|4Sok%DMS#TelYXGca5yQ7FBz{4O&$4{*pg;EIm-uj0ZG@O1|jw~?) zSoZf+o_qQZsrz>elv+OwBhINe?m6xP1;xxR=*@Bri)S~a@piv)Wnf&PG-Jm2ew@)$ z&Z^IEAI9S!o2P`;iVRFR&w3)R=8T>7}k3< zm1kdUQRe7WQG$p6`Lpk5oFb7kDGh{IOYG3SR3D2d2lA=_mF+`h%PvSkL8tJ$Q{2yZ z*vZMNywdmI@xMK+!K=FZLC*YVHbM)-_>$srlro#tx5WjLN>IZv>AqPiu8=?>aX0Y% z@D}^4nr2n*6}i@nAe0|FQwy69K3@Uim7GCJVNglLre3oEG-@XFm#DC@{s#Lrj_g|3 zL3pUhAgcxYGi?N8erz|D`vuu>e8Iu3;>S&$sIM`Vybf~eHV{2W*Oeiy-#RhC|wUKXCJI1@6r`N|}`e}yfdbn}dJHSYot;S_5#Q)=b*3(Xp z+QqV~aIj)`!){+d*WNe_t#MQ$)-?7;ZI*&kOhcMx5eKf7R7Z}$Z6sPHGpC#_-HgpT z)qM^(PeG&LfW#gr4=-XBO}`@3=YUr-@aLxz*$uiX-FBiwq#4iBJ0iI26+0Sk*)e@c zte$eyt-S*`2IJfT^v}vxgHq!L^R!q_li9yiMRd8^g{&lhD9FEfkYPt?8R+HOsb$g= z=T7?&94I~Ee}GGcx}Ti66q4nsS|^pI3VGfhsm_E9rcT>2fPNA)95GQ z92|S43>A}5|Ng!9oBvQ#lA+%0j<JCgO|G21W)6z)VB8rarnwCno#)@KE(l$s!pmm7yx8?iYI4jYtea?pB;2cMSf^+| z$PXvt95rHPjDtqaQCxuskb9?wi^KTKmAN<9%JDSzP%0~lEob7`FUZ_*w{j+Zl3n$l zTV};@Zq$TA>)@1K{$_KVH9N_gqV9p8YC@s8gm7eXj|PjHAQ6ih{FMay1mo zbyZkWS)x+Hwxxcd10m!c2l=E{TJGpXDN+Fk=2?FmH??h6l*z7dVeVGG+9k~oHZsIX z_P^)Vdmxfg=3?0v`zlh59NV?DKtahPfxO6?!%>9gXnyC_ZDr5LIqsmh_N~;oA~mFS zE7VYhi98s)^xUHK+&-n_59ZX>sj8Ij>j+Al{h)Gj;I7tq0Yt<+>8G8C^dJq*q$M`<~OKHIN zc;9-sG?QE2+h}?c69Ye7zUR{;paHkm_LsX+DJi0nzY1>_v2#XSZV8u9_c~Vig=eiD z)U$>Tr5yV#H`0pqwi9Ta13KDo&(jGfoalGe4xXb!%-{84*>MEq8Xx>28!dvY^!^%E zW7Xhbm*ar18o@s z6iMF;ko2iQPH+Kdfxd+CoLh`!(}Q)($C!&GsjNWXvUgDoqP;u)9whwtzu8+kS>~n> zdJ!iP8!NN0*3cHm(=yYv z7=r=Mpbc*jLVA*HMx*YUj`!ys;AA91(cpR#{P?o{M&l8-W^J_)*~IZ3;1IYy)-X7o z6V%~wGcL4qnf}p*z6u=!=MA}1y?MrC8pC7ynG`0=^5B7_1N)))Q6NlpSNaHyz0EwA2w z#9FHICsKZq>s(&7vN+l{{O|ld2}Fdyr^LDr?)~f{G69X zaciVx6ykCxEb$3&;1__$Q@RQ+-;;M#^zKZ5g;3djO)2+Ex%|^K{6)%!AKD z4~N>s;-0HFW{OLk5X0s`0{xcg9RN#*(OD0WVRJT!eS6vAErkX&wP0v|U+zAAJ!mr` z&bRhg zP)4u=f!Vv;ZI+-2Yv1bHCQ+RDCC#3!H6O02`rjvQFQrFi7)}Au)XO0K47Idu@yb!{H8G^#CQ{J5X3TBlEOTtN zR@~q27ccsm1=lO}Y}1eAwUd&jQZALC;=fZs^;7SEzWT#@}85|)fDda`DC2T*Hcrs~#oUbWorX&_|9r10h_Wq~# z*O%(UL2!zjceQCh^=+q^8*s>x_Q`#SI{?z3qjk6L6ttiJL?8(9e5AnB&=U? z@AWLsabH0hN+e^GrMJR(K`!nj9zj7IsDaEmsn91W5fdl3Rxt=tzfmjc7d8uRZwQFo z#8ZKphq`O#72Sn77^0X}ovO;P3a1Y%i^Fda`pD1(A2qa>BVnxG3cCZWnKWI)(LNVl z6DtyTBcpSG!c`#d8`_sCL3Vjey1zjO>a=qD*LxX*(9&rpb|)vL*~ITGlXrm1YUDe6 zd)@)yjY!$0j}SC&WF%obn6VF9DBGB;N<*raUI5)ZN z7_<4OHO?7Tmu;sGNB9zQjrh)aS{_JvgU$(eF+tR zHMdJ))fs~m2=No96Bpv!*NQ>!E48&9)`?>h=ovC}FmyhK!zpYuZNxuCKJUE)m>>JRSIgTkj{a5U z8&s&jV9EQ@-svVO0$@k%fw8StnB77gtu96BI+<4R*?L5KL9cRsz}-^u1ArNrh%70M zB9)${!bGRLC)5f3?hAyWvQ$83TRkvPv4~ zbCV}myW3(1J0Cj`f@E9xkSxod>At^PBo29c{7g9*8vsunWYaTxVN+9&Wpb8i53$bA zK?6uI^yy+PL3{D*aJ-Gi7CDqyg8o@oYZUxVF{CJK9>>kn9fan5vO4ufb6V1G_O3q# z@|!9L_;x=l>f7Thn-wB-pyi-mv*EgsjU-$}NACG<_g~JXb$)TE_~6a(r(Cm3t2#%J zK0gh_vY0NkHQGe)SDNc5{D{%q%@^C_Y$ZJ13OKlVJ>}&hvB=~IGL^S*7EWs)wxJD| z*g`)YOR$}n_o!^~f3f$Lad9=zy66DGEx5Zwa0@yR9D=(C3-0a-8a$8y!QEkSx8UyX z7Tn#3Graq6Tkbh$-w*e9KWt!t>9wX;*XrtC)zwcubv*HH=yE-3)Ok7e_V8|w8#=Th z3SIIOQ0ID`4FIx{kV1Akv6V#9O*bjGxUiVB#*(Iy((hk45zdU!83qk)B1I)AF5{66 zHZ0CYre>y4=Bk;Q;_Rp6{2JR>(y%Me0|KPU@;uYLfPwyhbn745!9mvVG=J-(e_Nso zzhKIWD3Z#_*fnVK(u^~RG*l3xw%@T9q&;eSq(rLCg8+s#rohc~;2_2_?McXpX0m(% z=>LFVd2kk(qsN{s&y#D>m+b_kzO<^WiivU-CQi)T9Txb3{v3lJt1; zROTA&)rTxT2$jv~duozq&Na=*%gI;IFh{jMH^~$1#|~yFc?F&@C-XYLx^Oyx=&VVES6574)^6`xiH8r&}C|W9F~_# zwzITc!0gG(pGY>YIDokHnISfeT(T`T;AkS*&H`f5K%7U*6Uoq>JCT#h$p9UO#vCpv z<3Si#U)ZKyj{ZU*Caf2*n;?OSNI-pyMVIuq$-^AOIx?2$rbk+c%EHHjgZE@b@Mk4p z?v_W*Z`2ZWHb_)t1_k$9XCU*_Il0Qx3|f-=Utgxa7HBUluPIQ}1n)R6NGX=*x#>s+ z8VAGnR+1a@u`?M-P0wCie@NfOdB=6o?rPzjtPtZ}JQU&4A4$wr)>(e{4C`9z;tw}} z|D!!g;A+p*Kl2FKTg|;jyl8oz!VLHRj~S78rr$Aeh2#a0INPYtDLwO~>NmwH5CUvz zOcao+xPCyNZ1}UQZr~+;WvLQOLQxtt%U!0}Lm1>}OO4yjbN=Uxf6*;4&#evf%+%}i z(u(xEdjHNe4c2qv=XRaBv)hm(7kuEv+;Cb5sXH0_4QXI>e6`+;^@@|2xSML0`H0Y8 zPT_;UTm0m0L3;CJQ2W$2?Z0|FDc)cr^fJxMdn#1IFI;;!IDVF{kHo!H-Xo}XUVREF+o zNsGX{zaP6I`wE&@tuvN{qz!NTLd^!w2^DS9BoHQ7QL8zv}T8VaiR@~6P_PkzW zRMJOl(pmk;G~{|{SZS@P^fh=@+b=Zs>2SIv?EE@^sl>XLnE$5dQm!4s9fBPOKNybf3y;&GPcIcu;*#>SF`BOLNFm22El3<}3UPTm&CEWD z1Vu#1oOfs_b`wJ!%zsMqL(e9n45NY}F(v4I52zE6M{wZ1CI$pVeCcL=TLPz0y?7F_k2QVwNc&9bXS`2efX5~NvU}D8CFj-S1!u2R5yREPEf9Nxie~Mx z>jfZ+^FybNp6?uI_i^hUX|UWN<97_dAr`Y`#sv-p-vb(W0c0UvhhNxof;BNi;8F5b-s0!uJm@{Cw+UsihWRLJc{Xz_O$!03DSl< zo__+bNBrYGNxa(P$rEL2zWZY{`itr{w8plgk+v1cyGEIEfRdqMOgB}uX5 z$HVjnuSvJfH;C#1FF1Alf45)3XkAxspx+ae0oVN>pg_eLFl?dSF|r`^UN7;4+mS-? z+z#HgzBAtTO0ee*=%QLxb?O><;cDzUIxFbgKp#9@%Ymvx{KSF^qwMg-15?#Z3qC<) zlWy?9K)BfN2eLhX{%zKGAe+1k(1u6GbJpCRHyCHHv(&t@kN*9MsK&c;P$})DEv>~; z8~Q6dV!4E_%-(>)5^2)Lv6*WG$My$BGE8zoU#ZGh)|4)fqzI4jv-IZkdng?PnAk+E zWHvv|pg5rpeDLRDk2WmyZy-c`OjyTzsHYB)j-yiXByWmSe$s11lJ=0AvBB|@L6nz-k+P-)*463_S$j+*zvesbfb~Cq9_#Qcw zB;a@PL&j6UN&6uL7)+&M1u7Pqv>Vu?@PB?Y%{=H$st9RUm1lwW*$V&+WO)HB8}91Y zTWt!HWn2xlKkNY0+@4E@yZtfJYW!e^1?3=hpzc1qfCH+TV_B7%(QBE`M|A)#M^1#)-PaZ>TX2qytnn`wm=}62Y!~K@x~l%pAyFiJzZr+{-{OB^~OTI-ta&zU5;tJWzK6 z?B*-@%j%-T3RZKERyroQtxj}%#W^`CUOny4rSneIM2Oc+VSt9|F`%Cc+1NPx%Ga4< zrk|wBJi^y?DIBVZnOhs)3;LNy?lh1W4>U4k3D6d4)0IVUDV<9OZY(+58W(XzOfosK zXWXRBU2=CFq?6CK$iJ^u>g544*C09gwT^A|P1d>qL+29TRa>3jXjKo(ipGY{Wj_1G zuUUEtXXN&5&+Afa<9~*Ex28Hh%{Q5QHItB~l07Hx=tp+v)swKL=bu z0J2!i2j+QkI~u;F=$`%Ybw(R~BLJ8LiWI0Bwr1-7W076DUsvW`*kJ?Q&iUdS>U{sX z6&HemnQRO7UVp@}%$A};kpZ3(?Jr${T^r@a)g;6LjFA8VBv((&L{6J4%FM@uldORb=G}E%LhvDt^XjHM8@$A z@Lhv+-u_5rZ`GzD!k<C{`0GGukny-3fx> znr*3+$_es4=tHtVzY0f$LVk+M%QfN{Bb`o zTA*K|xH6i$BpYnhxo#fPDz~MsYtWzQXY=p&o=ZFQBWs#8HSb7R0=~I++fdro0k0e7dYnI?4XBA0UqjxKgkBJVTz8!XCHEQ1%}eKO+CU^?b6n zEa}NLBO$c8cK$u$c^hJneOEKs2ff}f);K^mSWj^-t`i)5GEYhuzLJsfhV-}jfrLYB z|G8|HWRE_A8C4-9=2n&~EjMXG#cDrio-w-G3>BQj#YqojFnj-47L8CUB+#2sjs(gg z>S5tC)hhyLXV116+SB~}ZaH{N9cbyM2MZ4p*r|+S4A&*(kG0sM&#rTcK{K@CU=p;2 zZT!=}ML^oseo-!~s;p_VrEI%r^*F!*X8?>f{{qO+xpHvg zVCu6rS2*X%E9kCdDxD~o_=)v(4_&9T7M^zmOGn*PJ!zjSDELhrfW$gfn0uPKv%?bY z!k3`>3Oe;&i&XjBdeH1mUmQLx*=_$HFfh&e5w4BS#NH~s&k{R~OOE;@0lpc8=dAe9 z988_qetq%+ct9*FE$hkq$+HoG@SU8l=r>4C_xw{bas)oJmK`dQK)pgAz&}cye481b zkGhtRkiG}MTx)|r13-57OE2cZ6qx4Dy+eowa`CSJCAJf)pKI4gFm?qR-0B_|%kC(A zPM5@DSN|A|Kv(pH>Uq6CFuHe;N1bC5c~15eiI;IbK5MHr%@TF}G$+ABpjEfLOBSWs z<1QwhJ8EflB5&SvLsu;Kvbf(NXV`_%rtP*h;dn$t0<{ z$B%2~dc5E5(&!rh%j4zQ#*{tYqO_==yeMP6)0>;tQ6Z_|%jk&V6cwwMo5QRq@|Uqg z^J?rE-X|Y(qvLg1QDNxFP{|PX^Rnqd0|_@ys5$jy81(Rr=dT7v%tL~5+=j}iZ>WlF zMwj{(bHn|0BCrc(`74M6WA*J#(nve`Rpz*}@5)?>`pal)+57Lim`oiw?_59$EnyOW ziy#kxaIVt-9jE@^{TpsUna)XkUi!_e1SL=}r1I=iq1l8bjY(TtYPt6hFjV;-jI%JI zi4+%jtBo0C*0|+W5OCcpz?wl$$#GmfF4dfH83oFy=!k2GnV*6rzQ&<&YnvEM zSEifYNT=bvlEzkmZxakzYjcYHS5VHv?GT19n7wf(`P=X~G}usvM;aNI$LPl-j~TT6meH$$()#= zBU^0BLzw!6r3ap^p0Stz+!}9(??E^hRFnoVOg~i7n+b`b z1b)O#=*q=FzXKE%W*>n z<0u@w2}xMta8096h3Tt^WZqpwyhTd#auP5UkIaxEnt<^FSc6VH8uuT=hiv7=s!S*x zX;3_Jw?Cc5fbXyaW|!HF-iQQ#|9}#n9?sI)AuU1$mk=(-X+B<460*V^sT-q`V}Fs~ zw{c9#8DANhaZ|N6TC-QYo9N`JX;j$@xjhrgQX)Cf*^j9C&No_4{`(gyP-#? zUFsqrm+*~S0{d=4R*JBS5&{)f zGwAULn7c&6uqM&bsjt#tad2`DEL4^qvGNvW214lB>>b^q^c=TFeUIV423?Swy+!rN zMRp0nAO2Cku>kHy`rq~!SroW2QNmc;crEonItt0KT11H=L@1(PKLvjXzq0|2Pq3ok~ z-`f7B2iPH#^Vjv?UI4#g|2qHQ8u0t~JuK@21Yfutp zWfd=qs(UwGsxQhm#P2l zlz)_+vf`p*Lu;xx{{DtOEWf4O?m;8i)t1YbgALm9CI<%QR<3Vf(;|15t{Jk{7LDy8 zHo@pE6v8&nkdsjnK>phR|BtZs|9Sua|7idJ>7)PYqyN!?|IvZ}uXF(BW#K=kjeO15 z_?kA7gO81u?eCc*-~TgnW2bDO9i_~Es?@<(*KDL0Fpw!34wY#a( z%9)luu&)O03?xN@L2b_y8E~}CLuGjEML>7VFWHtX<^D6fbB1Ou!)|-a6A<{~eKP}L z(v1LB7lq%CpmPee-+R{C>$&EsS1fsT$VmdYMs^fpG?)zUcP?Z|0+K_9l@<~+sf1g&>d0989ohQWAN zdZ$oDia}SRrs~R9*I*NOwt*QpmmJ2Fi9!^MQ_EQbMZ>E3*%&41=e_Nh*u zk9IfVOSq-X6mIAax9@$-)potxNHUkduOEm#Yio(s)!)aZ6_nzjb-Lyzx2K71wdf~d zKS}HDDVE_UmjT+F>Je`)T0GxxXP+osjh6D2O!SlCz0rKQVstR=8p6BUr)9&2ZxiyV zbvq#fvhD(3tZ%xgU_E$Oqv|llJB{0pEX>_MEEUzgJU7GxidV+)st@;uwp%Wa!Dh{m ze147O-&BtimR#X_xPze~NF^!p=^GGz@aF0*; z^V*hO*T7jsB~fdx{usyll3wmtg{P>ryp<>sI)9b*6p&%TRe-eL*D z?L-Cp%|(i)=6U?SY0e&+x9(KlGb1t>FF=+zy!lDt_m(WBe?XRHK>TLR0wLx0o%n)Y zkQ@8>LRd;Z^=7`U2?q#8D0wmlA(&IVo2-!6x=LR#3)w`s4W&PeIFUI1@Li=6n;U;B zb8pSkIQIfVZlwgrI$t2y4LVfZArfkRmCGZor8-Kkz1U@PKSzMHKxCddQGVefRKw(* zq_xvsZ9~Ih)LtK#mPjoz@bE18Q-7NiZ2~KTfx0KUzB@4FT~aw zvdNo}ivO|1^z*O`!Pa-ZkCEx^s44#We>P69j#dMlg40W9UD@??3DvnJlEgF~Pr_VW z_sFpOQGdFwxIj0?7a7YHhO-~E2b9Di+v zqL`TsiVOUO(i45cLar=HkRTh1pr54hnIjFvzure=d1r_Gnke3rM=9goDVk^?uX znY|EU&kH(gFN;4`Qf(EWU~HzuZge*^FkCVhpFI!Z@7nM6R z5w1xBm!>ejmT3%<6H`LPaHi(E9A9bPHo_oe7^TBQ-*D6W%O< z;P1s3K%kbO5V(P$iSLLxvHQVlCKnah?!^^9@tb`Co^WU%1PM|L`c=~mcz)|-3(m}! z(kDQA#k2UdU2dq320Jqd_X_q68ZkpO-y1l0w;aB^$S^Qm2x>;h+j?u)FP&WH`lYA4 z6fAaT0lIC~J#in4-DTJkT2r|heW2TP~xjw$kX>j>t;-VqGg_Ri#dEYuIFx#kjE zoUQT+gH>xvk_-@%z-I^$mHU87(oFx$=$HYUKrPE05n5s^yp*_>U0ken^L zRw(%006ctwJ(ogHeP;Z%M*B%Iao!v|+OUXTtrFZf?Ls&B<1Bm(c6XIys3p!y=ysGO zoS<`+xX3L20pj80Lp|!cS(!@u(GMwA0|)K3TISc~mpi-?N%a7e@L`-^{LZkmW}r{H z0D5~sMq|LF87R|+Q&Z`F7{?=}5qj-2C=Bqh`B35V$%q+czLb)AuL^CRp8TUNmK(cK3rmJpT64{93aKgw*emF9u(q7r!aZ0K1 zKFnv=$y5ywYFKNefu+WQJ`}TYeXyg$(lQwwh`KKRiT5#=j*ERuYaVO2hleAd%V?0w zSrpzHh^QQK&j*6uK%D@*v5`^T_NMv6iv&X!;L~HtK{R=Xggo4%(kn?upD4DrF~M+b zL$Zt-L?u3bI5*|CD}Yk*b-x*3m8}a+C4|e_ z6wUCxBHJ;J@ZqxdW0a6 zP%0C(8SJ@aE@5K&9NGMCf~)r|>fH7Lt9EfnpA`D%)x&i^xKyxtFnJKN>-{zcDs=S- zr+xYo&KBeeWp5b2?}X}W*~dbFmm}T8A2VN=l^k~bHdG9L>titW9SJ^Su9Q8^n02q- zeiRqz^AHEc_Mh&M-#Ymf>uew6{fZg!3W_Jfga);;vCJ^}3CN}jLb=^gSiL-~WqA+U zCp0@tC`}RQn78Ts87fQKh>tlY;y1!I^d@FD1HRQp{@ie?zYiOERu#(|Xjc;Oz*)>J zesE(bp{x#hFmD@>K$w5mL_!ERy15b`vMgFqKp-+wx z)h=Q|?BDTRb9~}IPb-ld8JyIe=o`A-kK!ui{tcV$D($~#`TrF#ADT3D+e=u)@_hN zz?A){IleF?K0!ROX*x5mCOcdyl*gx2H1nxpX53(d_k?HMCBGOo)c1P|mE1X&q*2ok zEPC~x6*;J^x43#bqLcL~`_x?t4p9_!MzmHw&NbzMf+Np7GwEjc8kDw02(|(12^#b| zG~SzIRDz@Zw@Ne=@>*Tv)_C$S~gVlvDWdIt1Qm#gff>jWxyzUvxEd@P%FT+9{0{U0)ZqZBFvgWdr4H z9>0Ib7a$44@Pnq18o_$slf$SQttu$GB8%04m+a(*->v@j3Yk86!vdxSHWe$RJ(FZ| z1T%0FFW~8{``2pfaINOG=UeqO@y`l27S$nHcJnLr76;t)YjvMiLO{*%ASo9jkCiyA zeJL;ib3gSvMHu&Ne_Sao*P&768I7IxLIIoF%|k7%5(!gqTm`(hk3K3<0p?wrOk8^m zUUF6Ai?_SBo7F}zOBMrVUnL$2P#U>s04g_TFWNv|iK?znU-7o~yZEd!*`OlHDOPA7 zXZs&KGRLzNR)sDZ1)8c7;qQVUv7bo05s_3_H~QmF>zh?!dyxZw)4uQ&dP}&;6=&0% zY?gc$7gVb(n(qqI51H4j{~@4{Qm?j_)H@7o@|!RK9n3Zqgb34~$H@8~5&-h+gIN^< z1DjXKJnW6mGV7N0ujoil zTNjoO@u1QV%3otyzG@OP?vkdU@ddAp;7EN7=#CIX_nj(F{=f#TWT6?Z_?;!FHPsXt z>5^9z+b}H<*Ycqv(hJ@&9uY`~B)FGDZ??mV^Kp|&b-$TND+9?p`YiEsHN;qAkBU!u z`GrG?{V}~*0Jo{PIQNNRU@o+D=TMBj=z!?%!s(#!mN~@|{dz_l!@AcsRahyDFa|8_ zBEPYR_D;wzDSA^;2JB zdqn4$p$kzJ&U35pZqME`UUfO?2pFB7BOLBO`w3nh0Iz-mE;cUCzq<+8x&KzEOV0J` zA0U7A8>s02<1o+P4hsshDmmGksG7Nuv%j8!#42fT=K?8}WFu#1`&$V+Is4xaa*(rg z{H>IeoSpM;|8kMD|8*54VPPazEk$E1Gn3akWZ1}GucPu>4EZs$Gkt9)`+s&}u>W8B zFf`@tr$pXL9@r{=(RuSh+M6-YYSPz(Y~$O9xCCj6q9yEUBBk7797;TDKOyUs`A1ux ze2f$^9GaWmq_jTX>L1(%!@m5>&-0P)wRwgo2#4XNJ_c(Ip{eOjr>OTbrAjl!kqm=n zxy71R#2IXhFQWMhd2gNhi7*$`L(H${*61Qm|L7}3!w1XtSoq1m8NthiHgPvQc}Q_E zDg2qbV>r-}lg4|G%Dz~3o4NSrz?PwX?1$+PaSTyjNj*leDe1obL`*OJjnV^VUNilQ zJbuoE;3vj-BQehFGs0;1D0SL|GF>e?-DUV=4LV&7jm5k~_D8WgR0 z?n%dCCtE9Q_IT>sVS+N}H8IvPj5g^VHNMb!eN^Vqy(__92h?)V_k8-EL+Pg=w(kl$ z%s}gSwDIZCS>ga$McsJ1A}ez0AEKynKW9f!;QAol^fNQEgJUoDIfRD zW*5Ei5Oxcf?bCuTZS$x&S<^mc==Vy7YIDj+-hNxljWKMVKfH^9z&5_zxi;w+Ni;AY zE{BxCxckH;C8g7L1ZnP2xipb^7}d%v2q=s!ykkx08|{3e7~J*}6)4szKN>vOogXIK zh1Lna1t8T0nHN4G#b+dp1N62Pbx3o{k!rKix8g^QuugY5g7~xXv0cR#-@*-Y{!Gtt z379m>wow~1e{rNN(Ye!LWxK+ly}`)aLNJTE0OVDFE2_9J1|J|6m*o@a`%uk=64lht zOv=$TA!?sjF_MS{muz}#rUKMFz2!z{8O_!94f5U%>KZ0>^cv0dYI{bFe^C1>W4eh@ z56znAaf3%FgEJqB6yomu#LvKNO^-LWj<8nR8d+1be#SaSKjzpDmtdk?mZGZM^iy$e zw0EesMA`J7EXMd_@_!zvf2sNF5a4rlG5+%PVeTWuj%JtgWm0S_u^T+qXEFI1G4r44VAx{F?vmub1Bd z3)-&3I+q}r5iv706@V)TKn4IzkNYL!@PlogGWF_LWZ1B`xXEV1p@>9 z1_l=P%^S$szL4X9HyE&(6zrmKSjtB5l#bXOUt_Zns6JG7;HXTTQF9tQ1t22f;^7kz z($Lb;Gca;-^YFgs;};W`kd%^^kyTYw*U;3`)-f?P`)qDuY31zV>gMj@=@l3h91{91 zEIjVV&-jGIUrEW?Ik|cH1%*Y$Rn;}Mb@dI6O`TocJ-vPX1A~)O(=)Sk^9zd`n_GXj zcXs#o56&+xudZ)y@9rO7<$?mh{F_++knBImg#nQZ`pp}dH}J1=K|#AiUN9JMU@6$) zFh!N&jU2HkIldxbe~8Vh>_DXAR5`;jcA7xKrRLh8Ie!)HFUkJz1Pl0oCD}g&`=?xs z02CM~Naw*|0Dyq2M<; z{BD}RlR5+E>MB-!BAWn(1AXv%#W!FG>~jp+<{pQT2LT{^{r@~05|V%ngk;OeKyDxL z?`>AB(DoloYk#F-$~nR{yxg^a0r<^5(ZfLC-oY99{^P=@mxkv#U|hc>2)6O@^)pRN zheYfq4idQp7(75XA>sHR>&*f(f^-Ff3FFQ9quM!dGJZWO!AU*6d*%fDKrrDDOdcWd zwFOt`%};Yr)-{i?iBI=S5F7*~<_BpYkSATsO{S#Gy82|=FqjNZ;>fK^P9^J-1XXUrk6)Ec8KGbxvan!dF4%o>c}B>EH%#VW3a_;_@6s8G zO3x~)D=_lurHNA#>wRvD^Eceqd=heY%5pc9g@9A{bD6LmF7W@ewVB%T$xd zu6{AUcGFgfn<>HvUz~*`<_ClnGB$Fnj){;2PdBmKoger_;}vkvR@!E_yDL=L9^F<0 zweOk3-QkgB7gC+KU$)6mGY{_f8T!E>a@0CD%m>u53v_lj+Vs{JX2tNg)79%erdVko zBzJIbth~S7|1d3;sexO&8G(v>&CHV17^fLC42^&5(?~Tpt+5WtuIxV`L3V@m0$8j; z`Li`cJ_DxRpL3fS4y(4KkuUpRw%97%@~HL#h^vL*Mdm0V+0t6QPyyJr5oYCG{$(-+ zOJWq!?~}megC81E;P9rMXX_*YJmQ#=6ZI>fM4zlv&(!vDGgu-hdS+9oB*^>J-^o_o zP&Vo8UYDcGIlFN)6J9y?(wv+X&49R=nATyTawhCx|3ByhMRBg+RzId{f- z2`2kf;f|!-7Q^_H%9SxS0lVi*(Y4lMXZICpr`JS3e2e;dYP(Qu4NnS>=wVz?0I-m> zEC3puDEAVB7l74B!G0b4=*{`ND#7Y|lbum)2PcoiNzgv;VbOlVZ4r?qt=^GITtOB# z)XsxJvsvcdl79LNV0eMLit^sNVb{;PZM;R)s62P9Ac-9j>ZyBauHXWs+KE)Ywe~hd zX^ksQ>Y1yo9OX+J^*KENKo{{9yq}4d!3FWIRMhsQp5;biNe7GN;FwXnzHtHRO3ZCX zbku9&RpGTv-S#lJ4X_BG$Xu^0!5cxeYxEkbxMPC^he)+0{Nm)o43n z@k}~Le+@0u9nYI_$#_eGuGVIKmm4(l<^=5ooqQKKJV`LGEX}Vn{&%Dav?fKF?m-jq zo1xyMP1_o3w*FuIWwU10|P1r%{>LNn^ z{Bg6h8$Q1NPUEuV*5c|vvlbPk09PX}HO61H{?s1h3K{myB72)t-+WlOtysp<6*LPK zgUpkXKfwg&RJytgf{VU;gL?0DlVP4`KM9{g=A`NzY-YG?s8`*VG<<~hKi1jnacbHI zwW5dR%y8*Sv)~>1i6N!}&@NUugbHD(Ue&w)pX!aSb8(k9y>pk8Usr99(>gkA6IRvi zR)?-?kR?LE+7}K9LMcZCUKwlDN`Csb91#^bil78^$PJL%W0VEx{L9?`zRX;4>e?S; zHNT*U2)901g`KF>W=~QM)9-A6ilp*X7mV-w01HC;DKgQ!*DRJ@ss2gmH~e{#D+$)e z84@z3s&ID&oL^4x`M!)-%DL>+%9OblJjI2-VaAaF>pqY;L#o?v?W>UJOG%Bf5D3`( z^EvOcJ7lgGx-1K2nj{G&}6H*Eqa0%7h~35K0)e4F@O^foeY7wsxj<+0U%>e1uebg(!r8q>3qK(q?O1(BeTq z@O@=dEvM(Zo;tSo{bN&4n`J)2V^35k2)oA|{``PFBK0YaXm zi&=!=Z_+SY71USI+rZw&3?xf8o%T?>GFN<`J&C7iJa1O2J*hIav(peR-85^RaBHCf zONSDKOFbLn2U0KhOih8MloD&{$a>YDHzp;68zN8gG_@-v3Vy>vKT+O&P%H%Yh-}IeU8SXv5;> zKh)-Syf}Y2YCTnL;9KlJpgZM%_#J|OHE6y^4zhm-eJ3DBjB=9+uQEsAYF%hiZFw82 z-PG9D)F8cG>)b?#;^$Bj^AoM{IQ%FW07*{z&#p^mN;((LV3cq!k}5fHH7WCp`ln^Q_aM&QG0{uNjxW0vz1GnbJPYDc6Rtdef;<@-Cx^Lc&ef;QjlbH(76UUjP&FwHxjC1U?X? zs6NDK8kYyStT2`w=y>TPYqr(t22N5jh5|#JRR;-jJ{4GFeDP%(LJKoDGZ$+A#^ozw zQ0e?!fM97tK!+mo2?)(8LYm>~ZE1!dcd$ds~An%G%o_$|nFll3DON#2usozr3$FIm= zgC(xWVk#aq^wJ5=NrGnv@BFnwkeR|zqKJns8H5}!GWPZBEHY8b(e}2)C*y`?Kl}Fl z`5tL!GMhEwk`jTcs?n6RW!myf246)605eBfcPRnQ7iHbm6qKA|wMsS(8-JK7qdvz# z%a7Hudj<>^-B?3hp0{EuI&kMXbqQBjnSB!m=Nu=k+yKUz`y7rN==BBU@B;Y9yndK; zju)Ii%PoC+>}pv`E$#DTn_+-}uF&Z4K?#l)lH8TX8lnIoG03Fob!ta_@hMI}hPH>f z5>C5_eo}|%#L-t&9}K_!8sMjj*qrg;miAD+=H!SIqwq7htjzVb|jsp zTem^Q6$6i3y8@hfNI=-X8jvu^I^hSqdJ{&`c-Ct1yJ^4g)ry~zfU3G_g_#cYFk?@D zpR4_!33LsJUI4L)-D}sYtdO)qWCi=~O$AY|{iWP8E;}-&pFKKgLcpnzDB}nsXIYk9EF@D>&A*InZNk%U zS1WMb*7ro-&;2<>Y3=CeWzKpowCH!*c>Z<^JI_hN1MMUNTWfsJ7Kfj>u2^yQbuNFE z{&7h~x#wh=?JMjc2g8Bp4`y!{gRg(eP!5?6R^h_DiS6aPxhX}*^34Eaj=&r}`mODz zJvufI_6fA>`Ek>Ql3?|cQiuIQB$WQe;z?z>dyUO3ZrFG(5mh;Zv)KS#ND(|@d|GO< z-OcF3iGr*^IK}sG^u@r>1up~+$n8jvJGQka&j78iz=W51*ve64Fpm{Nfk%8B3(!$*y;sge9230b>G z_(vCIa^;(EKX#uM5uC`br7;O}7_C7y-a zT8y>V%eWiS*hA!c&zu?m`s}%^qBu_ki?~zPPw&ZEAWSQeD4M~=v$dzlRa(fXKKI|F z{lYIrp;oyEXC0{+rbFP6zj`nF{+-E3bU(sof)~K_0C*o{`1=FrdcSywPw7Al@S`2y z2swATps0~G#7M9S@jOOQK_SO~DGO{dL*#8lxp<9DWv~EK%3dJ|-B*YZv zEP!Zf@a6VuJay;&tNYW#TRK$MXMp)bh__l2G9fLJ^K zz=}g_NH%Y*2pB|ZJkYKNBEGW?F}yt0#a4oY3*Hc75_M+Ib&}!3zx-@F44?TM;HOU7 zynf82*NDeUX;IKiD6Iwk+htS~XF^$oAekl9Bx{k#8(}bn&&?#k`NVQ!pXc0K^w~H5-MEu=^ysA%OmNSwiS&j(&nc{cY73N$+iW-VbMP@mcyQC5HT# zXCGRQ(3Y=z0if`3IGiDUeO(=&585mzlwZ*jzf3kLXYl6ByK;}-g)1U6|1mMd?cEx> z7o4F!9=N(40XVxS^4uEY)GXMVM_W8q@b+$mxV1YPgmM{crE^H5<;kc92JTr89qY>2 zhw)pEKb2S6LXi9-Uz@F8BV7tahz~9Jqoy?yyh8Gb6Wpq(qGB7bd4;9-P;4|j6d{$FAvPp(1gAze)D=5xE9C(qw+3+ZR z#UN-7LVx?KTi7Mt;KuB}{?S|0bK}>O5V2|u+OKe2QoG*IyQ!{E7BIGRUhzT*J&qA) zbK+?D%ZBgaX+A~-9(V3E>(Il{UUuE!>5$#9X$DLo0fN3rqIrGy4*$M4+ox4OgFLh= zivGPMwx+yji|@%=HvElAd#H_WHvKJMG%`gFpv-%f9}i%Fveb~p7_T5os@ z40(*iKUHN5nlgP#Js*`a`Z)U}v`j;=o-ebTQi;fM|VQ9L8w1Y zWy1X6suhEZDBqtVu45{dxl-l>WC z>)pkIr}$Q0a3lIN>|y=%32n_3h{d*SanoYFO1xF?1{+F8-)e>Xj>{BwH;yN^Ur-XT zCA^zFMZz@pjvJA=)|Q?GOGRcO&oW)QVzT*b!UOuaaVr{x0q~z0d{N|%t#(L0?bq>} z7|2#2riLZ3Wme+v?(5W5$un2UIKsy=p(j&r)PW(~ig=66(FJ9za?fR+u${dT)EXD} z-f)O29=k=t@%~-Tay$`;$tD6+1Ngr#Op%VV+TX$g9McJ^YTC}{zF}T05(R614~~Zc zKt{moSt*9@U10b3rS3|}AKf@_0q}!fP};(15M$=C+wc?!jw~xjg)kotZQ4Ja;(-G! zU~+!ONBwdT;ofcHTIHW{`7>R{tt*9p zhB=}a%d={!AAgkJ9C*eUEd;OJa3<8xj(>W>BEJ`OCOZ1z*@0nXYl691TPpX}8T51M zj}1O*%oxdoDop7FH~qCQ?JAg})=V#c)GfAy>=(CR0N%|FsbzH*6kMNWjfVgr_y|Lyk(e>gyP+cmIA>#j*iVN5m|Ol9(ij5%PV z{>R$V{hX$Z2&pN{iM=14WwpN6fEn$urwW@%RM{BLenUBM2KcAUa_zd`e~;DRtH|2{ zYm|DW<)$4i7=%$pq7Zbl;E((&6aQFLz0%VY5SE8rr5SISx7S|Ms4unZ|BSzSPsN>Q z|3;(ke5r%558Da{!wbNuBMZ2ACQ?dKIB#pECUosNx1?72j;6UgD(^~)C09RvU2@n= za5Q_MwaE4B(^)QI-X4wOt{TRLWrz^d62A!&=A_izj9{& zKM|^X7KELyPl9Q**Yr;=jDzKD354)no~)h0xV)h+fL6$4YI3<4^tnnUjS!|M~`6N{E9#Z z{o8fdj`)Ag2w?bJ*R}J0oaMYdd=sVLBs+UZ*T2`Y^}p6g@xNyN=jxrn_uIjLKlFd< zdgl5D{LPN%%BFlge-rxuHIoZR->s&&`8=fE7T}u1U?$rK4th&HQ(je_V`QklvMOk+ zb%jv?oikbm=l?(T9YFuqkHG)06#4(e&Hf4CaWel$sGaF=K>Xh#c>f+>`}e^3zXEV# z)&@UK{w)OepD{PL)eCJMJKPpTo4gR97D0ppmop9ud;D}R#Q5N?{YORx5)H))UCA5q z-IRPAAP~8T{UQM$uaT7w&lC{%-(yWs*c9&s^c*nm@2#R=!|k&K-tpIarG z=~Yc0WA0|nK5qthE6AO^FH5E^FAjYYyCqj_Ia{`T+y}bJHg;Vb(>Y@kC7CZ>Un}-w z!J92UTfgob3S#WKwthKeC=!H2ohL&dy?!#?r{v-DdL!YvxA^SOTRz6HV5Gbak>7JP z^TEgTUf{dl>{0TDf9x@zT0O<2+?PJaERj?at3*U9Ysy7xUy@u@?a$s+VuSET%l%22 zvwaVAI(d`mTyS}t<7b1&Yj2 zzq1@)*-+TWF}g)&Q_Ri0Ch|56`Z`+bX&I7UQ`wqK8k5EdW5wV!N2nZ=<{-@jE4lae zv&u%lIhz!~Rq@+I^nXz;8FK;h+k_!t&<8+zJ5dcU=6+9$&AIJJn)$Ha5+5Vo;;&4u z`z~>CElX2%5tsh3+hc8}=I1<^+`||1^s~!Kw7mq`KoQ|GEqF*v zyFX8TVs%%8nInQM>z(3H>aenANfJFqx#RoBH{S3Bss|TS;_|^9L zTGL{8UX_SIr*`dGL8jY$!u|loNa2;u<1+=9xsI;Lk2olkL zP$FR{tU@Ibg>fZW(!P#(Op6s6eW6h`C45Gd-v9QKTJj^MqV@AyEB)EH$I(o@6L6QR ziIl&=dTq?{Qke=OKW~}8{eWC`qV%gK!CZDdrG`Lrpgj8=vJ^ShoLiB2wLUo8T$r2e z9}66eHABP=QB;mVi-4g}jx_@m#x;ZGLs2sF>Wn=T{ekVYSocMg|4~b8rURH9+6?k& zL%cc@4ZoN9K*g6%ZkokznoHe2$y*?U((Y{vi_JUu6wFi+$tInq(R4x3V97;6Wcpo6 zjWS#&>S=*-DGaJ{s0#=R+@bMs5RXIw{cZq~({alI`>pp3HdEX;b_S~s@_(gLm(VfMIEYDoQb2S;$l zM>cu|@P`4WxG$6|ZV;&&jl_VkLgPwtnUJOhB1JH$B0;`eGKm=FyCoN+6(kJ7h@FL1 zAH9i*oiD^ouchqHbF6RWcl&_!f;6*I0FPI^8uYv)zxwt?X)esQLbb)e{5nz02eUQF&X|3CQ zKU&DAjkUwE-EQCgSj_QC^{{%S258K2euKN4+Pco9AP3>q)(|?YxC6CZ6jnHTq3eYKRkh;15LwJs zW!8S}2FP7v3Nuq{mz1STXQWPSR2LbVDyT}0mse?<9zOkUC%OHoyy3)%qa<2CH*Ae| zVTOzmC-5;yXAi^$2QUB@1#qrQDj)!CA|OJr6d1twgYE&N!>k3CfZ_1##{)wsGXuZp$d=r592Z(JjJrNA0T?F<}3?VVVk1j+k^ zvp3)%SknA<`>bmsbXhk)i~1n~U5=H^mX7OE8Tn;Ve+zYIiSGu84emzs;x>dXB&-#U z0c-$mCeCG1zCH>E>WIs)(s{T*6$gYM0SG3LSK@vo!SDy^M%cHk&p)(eke~+?D}z!# zy9>G=L8v<28VFNT%Ku<_QkCyx&n-gQCBcSkzC0@tvRGut2M;NBLr&BVp{-C6=Z43*Dn1g}~Lz35l zB;gy*7aI!zMqRyfw2V!I(+SpG+M2Yg}H-Tzi{Y&fc0xxGG7E{eMOekmQMkeZU_$#;H_}Pi|0p87K#dtd_b><-~zzu8Swz$0wh@9Xg(|uKPeW0 zoJqt;g#-)QTd-IRYfz*B(tld8JB4CWJ`|BB181w-e}8`wBt=TM_w+#LQq%a?`;SX! z@vwgq&4V_GJFRQ?9|4G52Q>s#89 zgKDH)-l}oU_EDEPgdJ`LAwefuAwhf4qm&yk)$6qw5Jx*9F3KhZIGmjXcn~{M_YQ1p zfolo~saODa?65v95@uvvZE~23hraht zXkAtrRF)tDR>f-uWdFlX%HKJV@FAVDc2NB^N89FgYSTEh3_$t(*u7+-Xx|=6`|Y8c zu>jF%65yiHy?zCtvw}1JAoh&{m&Y4L5o$^u0;R0NPy*b5*B2^2XQK}|7{;lHRJfJn zq1Dci2LX_Jp65S$WCc7rYe0(x)2YiDqZd_8dz~Q72etVSPbeTd2~)r_DBC~ zZhfjK%)R28=gG6pFdLS;)DoQ9>c$Qvr`vLvwT;)$Au9uPrgI(r>-hI^YU&;H2>teF zH}~hJp)phDtC%tP*fZOE8z1)P-oo%jSH~pu6yGGiOe6dUKg^fexV7F()RCb07d%r9 z*=-G54!+$dbYIKl?SGfDU; z0;d11ww7L!k>DQ@;r~Ns%k54BHhY15AKvddHD4FE=u`Ap>jiYOt{$Ij((WFg z4<^6e&V5`yk9>5Xj^w1m=I*w%Kli!O`Mo~dq|LnEj%Te~8gVw&| z|COgDx_Bii@N;7&CkHy6Kj#h-5=WuNIt9Gi$=uN%^hM_hjh1wec^4Y}xRa;`kDJs}8 zep)fJ`Vm4sP69tUy@gxT_3&rvb!)`5A*XPOpYO7|k*SOJsBR+!`Erl>aC~oqgd4N< z#mu4v-?-yvgN(!LaD#i=J24XZpI`4`$v-^ZUxx!9i@SijOltN{w8`>_g7=kN<_=0I z@8EwNw!F-erl?(%c+{D8=2|l7mDk+j(!G9$tE94Owk0-*ZOPL!ADU4LgJ%zP zwNqh9T*#;`2vIqp715d5s(}E+_dW6Km|G>bMr%+)JAJQyKcv!HKZt>xd-BdHxkp(dH= zx@-J^vCqG{?n(bJ`)1+kM4WQCwYIrVR}3AaA)UHTA;k=8A-o?Nfp4v98k+QyaWN5c zT)es2HZ>4OITmmge(^B-<@#mVa3g|#^0oM7v!o~T;bXRpGbHq!<^g9s=%$oHu!VUl zLE6x*TU_BfC-LUZwb0SB@f~7S=O&V;X!-8LjJ_kVvBe8rvT4}s`Xc*a)vuv^lvg&` zX^c8EuGs|^4!oNkLu`~x z5KN~eM3&l$yn-LIt0us_kQ(dh`}u>D)NjWw`f@>&c}=JB6ecgYT?{OY^d{0VvH#q`YIMzlGuG0_s1&^bm*4%2(lSF><;I4%{`tM@ zRkq$yZ9=r@pDGFa4u2$V{?k&~p7E^HTx>4XaT;qua7wWAVXUm(Zh5KO{U4SiQ@)el zAottk{oS?#FxDpB2$7)}%V55M{NSGU^AW$R+p55}?{IjBot)BuCb?nZ4_p)v^LGTN z`J=}#WV!mreol@SGb~-FnoXpQ&N4^Y$@9k>Q~vVAUj2$YdRzJFW9`0R!{SyC>oxt}Fd&a?A7>T0G0Fvd72r_Xi748n(5%_?85%7?m z#P6e0j->c}h>7>POa}i00K-2GP`K7G&42|-AA*g7xjREtaWprxk!H&@!ibI5VOeNl z_m0Kg#71~V42_D`b&k9^=y(;WfDBkC3J=~&BiM9ijd_uGQeU|RRLBqSFod&$cjWM9yOB2dUAYinh=k8rq zAOQG9XW&|Taj9U`T%lD|8yf5WbfRwszE+#28u1FZbP^%Ls^8P;&FC6WHN;+^CYVV# zA+-`1vxjp!dmAT?F%uXFV-gX!kCVi28z)&n07R02W9TQukuONFQzdYqlLSz!BJwKs z&zYESX8^k22Ji1S6@#%B{dR`Hzs`^cbi|{1`G-zwp%+!ZpXxUyZE(lP_TZT2;IEn5 zxZUuH<{oT*_nYc@kGF@5;#fo5|ufihiYk=Iw29@ z%VDy^R@3qi+vELKGI|niVX~``-;cy|t5cO*@JdvX>^UH%?5}Z2#O;3^ZcJDD8c*#E zaPp*Tnz}STB2Vq&)bO)EHyV_g_}McCn=nkBZgZ?Xm2bBkJQW`HB!YrPbfs_c*IV!8 z3D=n4eX%553IjbkzI~oIUI3DRT5(VuiQ)hpSASBRh~tDAc=B5mQ}huIGvp?_yMf~e zXzG28B=sQ(pZb;uK}%As zqqL+(<=z2pG-hN&#<^DY`m%ax3hL^+O3CWhdB+UZf~3Y?U?XV7XBdRNI+Na&SDIf7 zW_!uf@lszp7rtl;SY=+tlB?RtMmZn3c!;QjtjRsKe{dU`JMz)}I!sj4B)}ANOc2>f zPT?6%$zIvH6<1}_nV>{J8&;f`$wuOO{OPzgy{5AW0dUby2@b$g320_H6@XU6pcC^G zqU+mn^+amA=?RFs=?zP}=}7{1(35-Y0Y~(o2VgL~0Wkr+>+mqV2{C)h8vPfvwilTC zjvJZ!_K~|8HF4}CA8DLq7J+aIXh(5SpAQ1$SNW*YX=>!7t}4u*n`=3*CMvEY>z zFnQ$2YZjgcSOOg{87N#)?OzmP@oZ*R5U~MLqF~m*e#?;L0oq&S*c8o8JTO?Pir2y# zOaN&jF7o&XAS@OtF!!d5|CEI|<4FJxB)!O6t3!8>daFx8v;ks?!mf7>qFE|61q5Fx zb)i5Zn08M9@D)%8o=mO}kXDizVx=PR6GWOLlmJ4)AgP1HAOS=KBpIo0W&$-~kmzON zC?m#%iBAO#AlXL(ldJ>>lavs%Z=+UoNi~>O2gr3=ck`gN#i2{^qZ86c>_Ae7Lthm@ zC%iRBX&QD)(!@PBj+C8Jh>}$+d&<)ly6@E;Ja$e>Cp;zXXJ?$>T~j%Yruf~9D_~T% z0a&fnCeksFQ9gtMX|h12J^XmHr&in$r5m$dQN9vU3BPm-a>_H}s^*e-!IdJ>>lAh$ z?G!f8nkh|!_SA$UBVzC5^7WVyww_!1G5w1ru2%62)(lyZ)yj6ukwekAi&&04yq^_U z9;IT=o==fqn0l;S8CJo!}@fgKR2lsz(Rge%nz3P1)p7r^DF7UV%pF+~4(2244naU;l6>SKDX zRu?Th-gzC_Tt&4afod!KQP43eilTujokiFWx?(9{OV1psOUo=H2aMCaIAVOwG-NE- zO=#6|t#cesj_C;-iN~)0>t?R$X;WI9eamY3YE!hs#^!i){+`cew?Ak!a8oeuf!{tS{7$Gny>Zs}gCEfQq?5PO)UCXj~nUQab4 zGq-in%>hp@vul-~t*!iJAx+_lcRW^P2op(S8)oEZDxn|9WNanyWUPS5aBRQANUTI~ zmYCAF0W*^@?Z!lE4P+)c^J6CYNnOVH^ZK257$Fl3Lo9~?PV3CLk$fAYDu~0l3cVdW zEZgR!|E#Iu(q4s_x_Vv56M{YHLTttK+Iq>oPg0x(hFV5jk@4sv!lSc!U;`~2JS|_t z0Gvl9DMsj$XkZLD1Yl6=0Sj<^eXWWOfVssEl%c^l0AL(12%{UPG*)uI2`E*g`)vtG z|M7ST;7}j{HmqG0fEn5xoB>ag1t1l5qQ;cTh<2R@_Qa!5*bRt;frrooG#daBFdIP_ zG@Ag^1xxa;fss!I>_a9X?nYh&?n5Ra=1AI(VD7Fk37)Yq2_7N$?OWtZJJ&c&tpxq9 zR>~-3a3iN~KkLMKfr%)a%y~tbqE_7mgwd_^q{%Z$h|nI5_&32evvcjG0U^8`J%6R7nko{ zJ4E|7gZaYG;b$$qT<|QK>ph)Jma502FEcx^2zHQ=SC}qi=0H+9V5yK!U41rd-{mq! z4-J~rM^;p9ra00)Tj?A8GH}tl;?g+=VC=kZoCDI#=N_XyNw=ptao~INxO=(Vk6m+x zjdZSYvfRf>jVs{YvhsIIf=hU|9RxQza~mycsJ%{cn`ESVKpzQt%drHY9DC}jFX^+ z5K;BWjEPz+!zN5qzlzwN_VXy=WBP=o=nv4T2T%;L+XP0WE=DSnB5zX^FHg(!&#M z5%=mTKlLV5+Tk%L1k*+6AV3CwB4eyYhp(fYvWt@)sx~j+rwL6II~uP$l~urerZxz+bvmU0<$FT4_8# z59e4QDq!P>>1@@{ulgdLs5iAX1d9%D0$aVNx`NnA0fpmB#bqhZOe&;#V;C^L^V_P{ zT&Wc5V#{c+n&m~th+tFKmivCX(&yP}^Wqw_#6A(2evE;M93Exyx}c?R#$|!xbiRyY zw94}XnMe2<0j$ymnKM58Gx2~XDiE#F=)SmDeQ~?67KFaR`rg*tg%9<`EQr>sV*UJ7 zpqlKVXZIF;hA|l!31f^A*N~IIuMX$Tw+;sZu@;9>xfUnhpd{|E=~0iyWJngKGoTsr z(5C_47`3#g9p>Lk*?{5@YXOWNp$#2SeM^gkQYXtGMANt^y>&pna$@W#zh335jxXwy z-)XywSyIT~sAC?RMa1f5tI>YYO)L5UhYgX$w7g31sx~~Q`*5#WAlgptP;EoW_n(M^ zN)yqg#^X>REODipf2#A%Xp?uvn&%5LW-pZxZ~+eh2UW-~14Ep+(#8U^$U0%DB8E&{ z1ja3LCh?o~m?g3pY;Lo18p@LFT-PV|HKrYBSNtlIYkdEc>CZT&r z`le&h4hHbkpuG%C%Ntn37)}NI8{F={<8CgxMxA<6p2zR_MAOivA*msjZ96ivt8O!T zax?7vhOu+n+lVC8xr2unnTogCf`y`$S?CiDad@^a0BdJ_jfR6HaC`yGEsxN2gT7$UQr$yQhv=fxtBk1BULE< z6V5h-2(wS^%fQbLp8>BrHl}>4H5;xSx{pEsw@aG zCqodKr`1}eF_#UElrjBT!>9^Dzo%yjtO#Qq>fKCbQ0k|ckw_DoU~TRaU>Qa1rnRjf z6U{Kmk6$)mZ^)*#xOoUn>R8YN!uz(YhXqQdIEgWjFkSMtMeGFlJ3ZGhWuowRurm&w zfJhu$2p#cuzM-*p>d={Xu`rYD-vbrV`M-OjR8%li85-P@+{<48q*OE z!iI$eIamBZsW}=C8js9Z4t*hL9HL`=IN?6 zR_Vnl?vLu~=9)U$pzjcuCKEKDoIFXN`3HqxgtMSi;XdY^C;ZXHDYV>qk3kI><`INw z-A>S6$k?*|B16cGvE9gwGt|h82#92ci$L=I5@7QE{R(NJd5r3?6AfDm`xuG-NCZ0I z9uw;V;D-QSwZfsg&Jf2WwZ6LkQ*IQjIeE6Jpw4}^q`~D{acildFGYh2TYG{zak`ve zCLcd=ikwh=Qk5E3zRa$jeqb_xDleQq2}$J~_Hsh{L{Pt#N za3weT^YVV-+4IP3mY%-o+LEjbc`60*DwiJg|K+#;lJu+`4F5sW zGyfNP&i~t`F8+gqrx#-*VE*@IG1v*1|KmIQ|Kq9`%zsJz|5+u({5O2?cg2nWy-H|7 zXDnuu!x4VEJ&F zJ$7PCqMq45lYO_pNnUL&0*CtWeP}`~973%Ep05se&QGn7UI^VEG$0@16Ag+_*o}{t zs(unADKO)*DB9d(i@iafj+?8&ZTMCAL}ZOrL}h01TJ4|3kJ4IrT#fa$)!!k{B5!{0 zHj$Ve%A8@wPtyvgc0)47etoriXGeTR{IxaNzH&9Xx7D1Hq&iu0K(PjUVy|a&opuo- z3B{>+$4)v^W2W363b~dR11p?Qv{pmlpqXF0J*EGb!DCOx}{KHX^z7I`JrzS?d(~;T1!Ww94>y619RDHvy%b&Lwet94F zaRxiP1(C!7NeZR9@?8j0rIW6=L_iE{Zw@cLi%M=I;Y*r2&I_9GFyh<(m(s}EO<5)@ zjaN9%$;g(21^nSjJG9%Xy9Et1oLGt}$D6QuvF7lrxMkeS5qD;YULmNINbW6E}w_dPJ$M@j*N21OjfmF;(N~_8z7AD;IvX^*T za0HeUgMb_@vkUO#HGPFiHDnjw{V^@P{DKz;;2?q7c?3w3XZo|fV`(vx%zAppkb#Qg zLl7buV338^z#o!7o*7K^A$e}^mXHao>}f?<;4r7SVxYzQ8W-GGPYqY2`F0}0a1$l6 z!|p4C3k9xYZ7aU#+Of9f5{q}S*)iXn6{pgP@HeN82K-@TfiJ6$GB=jcV`NlS-e6UCD#lipb6u=s)=+xtCEg5j z(3|!tfeKGZV{pYDJBC{aAmuk-;HI9xsz&@R|(iWY}s^T!W+YoEv(tM zV51y2AX~3V>xs>$g`9n7YHm|!fX>X(xIpOYU5M%_P|b(gw)$Y|)@ZlD+7#oUX7JiT`Q!xd$sq&x_yB(NT|C zH@1XH+~!!hRfzZ*D(XgWj#=XBVqAMAvT5w-MZ#!f!l+}>pGv6%Vmzs$ zKOB3{N=0v3*R+LDgLk=ji-qwFGf4;1K~E*HL_LnLPLrL>N&sNRm|1& z0bZi*`@^Hj@eBX<^Z~V^hm-JU=F*abg?E>r`J_!C*(DUt9ITpGrR^^IE3f*-96REa zhP-wf?kR|wCq5qgs{&Fot7Mjj8P|jMY>ioX(p%Sq9cd-Xt;AvGBAQhVS?GI|tT2YQ zCrOK-ni0P&!3l_oUsq$KLiNkGUU(xbA|AqU=L7L!$Wa*G8x*q!o~}k9AVcqjrDfZvV1iC6Bsd7h+bo#YqD*#inmmI+Q!9Wh%m3()b)<;mm=CG z3zVKS58I;c%VBy>Qlv92>q6#!Eg{M|H)d0n#Gr9T1+Bu#-Bc52Vu{+n+K2tvd$Lcz z;_59^$)7wqKq^^0!TsmzQ<9#O08+WEjXsOcGl&wr+{qJk>C9L4M-w^HfPV@MNOcUq z@{$&Roy*mkqGaHhaK+taLCBhz6IA%6)nMO@VxH;mX6?&A;XTlzmn?kC~`$~3re#a&$Njny~cMiiw@Nk zpN1KGpU$*zMg$;|C{^daR=<6nxhIl;oTl@TOX%HHcoxbchm_y(;k(R5z@GE^oB{al z>$Hi#S!n+i6aKRaI@3Fwp;TCqhB0rp3%Io&>&^>=h92Z`x>pU#`D!WZEtk@Hq{*c; zo%;r)eLTDAEtgP@T95{KD$>ezwLUykRV@D%QT_-xAJRf3Vu#Ih^Hfb6*5= zxXcp3Og+HsXs~O#X(Es_N#AV{Sb$!TRTR)*ekdZFesaQY2@f2BQ&fnu11NMUK-j!Q zO}}ZSSp?1RL%>$d*s8^B>Vi`?7_ePjnQWDUfvgZmY6O{j0oS&my=|$LL611KtM;Ia}6nriS0o5v;B@|s12*cT|gyLU7 zseessJlvC#8_PXUxqmF9Fg%m?uk^KSq!QfLzpfo}^%uh5DwE9dL}=hL13-z(1XK`l zg!h-2M1-)p=L8ZZc_Ikir}2*`F+)U&TMr;vm}I6PY6TZ0F(dlEAS`whZ*iTo z^7)QWEiZH*4jB?&Fj`4D0Fnc$sMWwRV z^zHog#N{xlg#uD9;8PEU|NkD|rk}h=ThZ1^v%6x|h=rIEOC5 zf-ez|bY$QdoG^QQbc&1TXmyl#?8*w~>ze~=V&fMu$nJ^Q1QBXCJpE-gbLhLX)V*_0 zM+9B`;2C-YV+xF5*SXpAxseJorEOHoP|H!jnY01v%M~c$^#waB1T_d#6{ac_!l}0- zsFYtfRfz!utVwet%HZHny--I%$mYkWlo_hdM}b`{vsLm~Tq|$eTq4vloHJ@sNtRgK ztA#A)Mr-}84zYx`p@u)iAmagxX70wovhh*8%K`&boa=Lw3=KCH>LM+MQd(px%fpRk zY17oNPSsProNBX|>S)vk(VZ)EGe*pdtjP*kv%?-bqYr?QE3iPiCFjOFGY_Me8n}}8 zqSbiee8HC@8SQ>Y?>gg-t(bzLiExY0h;xH22E)_R(t(9K#bvIwjZWpMaxKZWjn?F4 z-e8K!EhVstbHLc2{D4cSV|G7>nMkFtL@wt=qM91__ZsralTl+RNu4SWFCW4I`+qFO+Ir|AUfa}sPcC4(s+Z-^o~AT|D$!51j#Yh*sySF+ zYd{rYwi&8Ab~D(*7>*$G6K982R~9QdUvM_uZu_?O^p^V9@IX(w+TF=hjJx^+6wd-E zPvxs+TrYVtP9?O5Xk?JHhMv1&%m=Zd=s0s-HWIaAUYb|hy>K=6!*H73pn=?>=5ltA ziagxnT@orCoT`@riC0=eh_lvE?*cyDV#cdf{I=o7`BL3d@c<8-`5sQ?D^GLxfQLw> zAr#r-4?|SsRP_gU>$|51S!kb3?<~U_JkH16Uu_t>pzO^HYJnY&6Ytb?$!y_Un+|oh zp#w_hXimVXri|!0ux#P2&-S&l<4OKDdNrr&N?y^aRu1$9inPg*`Ad6(3n`I?vD<$Q zNJ_jy&ve(G46xsZQ_XXIN;fRFvKL;rPqJ(|kskGR$eIT%k9ure{;GY83oJY&p zCga4$GnoX^g6_a_dQ8xsK%(SG8sumhVH-6{}+b8L1i5Fd|51|G0GZ9dUXoHX(n>+ z2}N_i{`>BDKKF$XTWJ{bLbX*H@=jYTA7vQre7qQl*OHx%was> z&-#!fOAuVD(@gz>`>-PnM) zIU`4KiuS0^;*k#U&?635TSgLjtzS#pWD3;4?Mwgay_NXaWPrU^e`4qStY?FMU?fEr3K_WaT^-7IIH9d( z_kPHkJ0j*7k6ARWk{bas**)EH z$PwAOWp!S;J>4$e{>*}GD^C}x!E#vR*_vcg125O4!D-r$>{f}45tUcPgiw8)v!}wh zTNXld6U}xjs{EP*g9Us)fmPAT-g5qQzeJFh-7!Gq3SCp-?P#wK>%@^kb@c~vF(qm; z)sHyDNno@^*t!HPm$SGO%Oed$Yv_sGFYBNr95m=Nz0*bT?68G}x=KSsFG=-!V?!@N zbtZ;7ZvvV$E95KJBzM9KM46l$&dWH5yr7VW_UIxUoZM%oR|N zPsy&xdGX1-`fz;g+?;#?c;Nvi{&&*%9~Si=(wCX@KS|&J&%*2P?==6@STq0M zNvtL_c^+2d3vVO( zJZz)w5EYA--avKj0Tl($`(m>b-`D?}Z==yI*Nxx3aSzI)k{5t$)DeCxhB>a6zA zImO>O8rF5G*{kNdfIAAeL3y}xmVOcoD}8J1@6(#&W8fC^?xUjKpm&sWb(N9ipE$?# zc;T?L?agh#{1g#J;D~WZe=EjMuPKO#oYTo-3^w<{*=?Zw$iK%lPhLXLIe%2X>pfS% zNuE}&pXEhD@vD6#%qI@{E8>l!A?E0|0BWfpywd;K(Ywro;pVNth|p2_O@c`L>Ifft z_w0Qw<)vln&JN%16n07cq^ku|C6@T~iStbUHu{6`>v1i780n_qeeDcNx$IZ29!O3g z61mIkiM*PRcWv&b)U>c#c>==91Qjb%z3ht5RV8@0&dtSwY(i?*?`Z)U?Hh^6`mg}~ z-Ao%|kcT_DLw~@nsB7!u*!64uWa%X13ipf42SJKE?04Tk z$TX$gVqU?IA@`AL4nOlOxTSqj;kuTpy|3n?&V1qj3L@jYn z(OY?hU~9I{UrycH@sGD%Ykb~(RFk!ugo{>tr@^oAFD(e>Llmh7;a;(m!mtjRLS zT=_+D&B30V831S0X~mmBu~t;9nvcbP{lrL7647zjHo<|8tr&#<`Z{6ty{wcLd5l`U z5D8BFgVAh(&#Y`8N>b@Qbg%d*k-k@=Ok31+7+v9iKx;AFe1#UBO2Fla10S*SCf09x zpSJKkq9ZnaQ%k{z#V;clm3+l8E+$xazf&aI>?G`cn{Mh`0Oo;Ja9D`gw4QSUyNF?8 zB(V`+%>{_6p}Mur^9v9N91o2@unb-lf+H-V++r<2;CQxuW8?;#G1ai=yKkcqVcB|p zL5UGNV|0d&HV}IxI6@2LGLeD9en3UK*^+C{vnVdr8s)$(xG|tA{7eVb2jLoqwqg|7 zgN!0$8ImVCJ`O>)Kw!aIf#C;WQIJ0gB~-F94L~>D8~;gIP&%4MXN zl<)Ifka{A$Bu*>3mJ)OB4K16Ku+1zp#B7#UKe|i^2fnq313iodX=YF@HF=nkHLkol1=V?=q?3N5^H7PHY}IGywI0YvFXR@sOnwtH#U>e)|-_&K$iJ+ zYjEv4*$WInOLl1~%k_M;-bVqgX3&H~%I4(xLCn4%C^?Qry>r7G<0!r!#d#K9Z@-IL zduc5_bJr1S1Yjp}6WS$&$)*K-3dP7xU;@+FOy4RMWQD2824sNC9(eY0nvM0fw1s9{ zA&uaC<1E~J=U>tLjiHLg`^7#1`AKjZuUp$~A&oS04Vo;;xtnEZhZFubE z{NSm%?mR?e9Y}5PQWx6PJi_)gqDd&A3WDGUlC-#X0Tv{;-8OIkvJ`xc119j}^<&A_ z;dcS}Ztf{jcp}GAFi#+GFi-#adk+6?Eje?RJa6L@O)>OUl0`0G?i+6C4hL~M{NZ{q7X3wMI0as zDN7F=_2JZ7(e!BnDZktb3a-mp9fw>BF56)n2RX$=hxkj9-t8pddlB(~e35lNaDTbT z9_UE0Si#tyINxk@88Jbyq5?sO`2@jWUz~Dx-kF))!eVlNm}y6$0!Y|Gl6%Ocpi zf1ul5pHB>6GpM=!=mvD^pqBHky6S=+J-%B^1wLc~17j$$Yv!Gj4vNF5R= zqLvFJtd(sR#OXyP2SQAxL?lA&X^B+?m+UTri`#m@nP$ z%SzuHoNIewUM|Bu;S7rdn?uHRHI^yD#YwOLA97pmVQjAd5s>cbq9!x#rEWWJSNEf$ zBDD5@u=mz+Rc&kA@S-G@?(PObQh^01E#1K^xXUt`R9UCZ~g<|>xc;D;*(Ltj#+OdWdzA6uum7DT~DBTy9m8EvvCW0Uc&kv%Y$$zR1Nsv;_s zN0^OdePI5ozOExv!CRzaj3+Pfab@MHQ#*|u^5eD$1k7h7gOMGo5V5N06(=Um)*m=k>OW3GXr1YGK0Lt~^ z@kYn-H&WQeY~Gi)Veg{6yNm0_ZSg8x-tQ1kJn-eSLbF1?wQ*A;5T((ubn||;a{fjs z&ZxOiQH><9rt@mhthEYQa~yMIe75HKBJ#qx20H`Qcg!5GvOVCq998G>pji`%@$hT0 zW-{ZXdXexGN59t_0v@zYnKpx{Iw8BCV=%o%NsZB+gSQ){m2{rr9C$c6wpb<62-kv6 z`k3PKLscBJ>P%bR#n#VUQ80j~A`x96#dT5o3Fe;>0e<+o%GpfOJqI3*GpvjQ+X;KQ zSgED$3W*}7xEYlS@gAl)O!HE4n6t$q(%Xk+31YgS^KFguFUetGnGnm zDV90`*5&GISyF|-> zoO5}P=}PaRvYYS+olnyPlvL$ab(c!|`lBZA`nvcji5gS&UrO$F_GyyY969pixh<`* z$<=w(4=susayh%VB!)7YHqPqr$DE$mKb0eBq%hz>nOoUNCe++>bO}%FK09w1K3DUq zMevr_8~fV4-=5$9uA2GFHgqp@tgf^D{OG>6z&(mx)V1v1$t5jn^oP%7m6K&pU(I5S zDB{a)8i;;ByYD#`Oy6KhAMt=l%k_) z*ozo^{Lm-+#lZ~3(S`!iakC7}5k%4Hg3;U9zGpPJ4L!yCnw;*!jy*2tt+Arpl)h7A zcNB4Qm!d^YuP%mhKZa4U;zf+%GRO*9%S6pAU9P>#UzQ~g+r5XI1tLDRiWF{q ziANw4!PMXzKkj&qWKZ&?yfua|Hg~yd-dnHWNPYoMLZcfM8OS%f}wNB`IlpCPadw@bNY?@;1g#FWGIqQ zH3?Q;aLK(GgsRsFv>kk!U*?|R_(pO14jR*hJ*memz(JyC1lgg*eJWds)8%GDWH-b9 zEn50eaGa2vyx?MM!hZF__?zEl)&$OgQJu6S>38WyNca4vTiT>gD#TmOBitmwGfhzA zxX$QI6~5!L1M}cq)~>g2{t_J8fO63EF-zuRi{424mW7zf1n8VfS+Ah8AJ3Sh3%21@KvC6|bj5Mw{&>S7Ci_zXbl9Xh(H2iBZLGd$d zZu=eO4bEyunabd9WmRScCoqKCMKKiL*(mOejl25Arlsa?;q#y;w+Z*uebOL$Z}Y?) zTV8gg8jcJT^E*v#4!3u$Xm6VmmA@`}B0C%PbY6tO%)8>bd-^gS>#f!Nk};`=ukDS- z`9OoLrmaVj7vAn#UgTTL$c4a*KlL0(`A0r6q{nKuYMNMuOgpMW-$3oS(o+*r5>cq% z^Eb1upEa`g*|EFf5pX-EzgL@gdEZjG=u-%{{$Rde{```YEZ;&-*l?T)5*nUzz^7n( zoyFVqjCjS%fO1YuP$TDM2MNqe`-=~C(|TK2ywyqF-5doMqcH6(%n4G?r$nP&a|7*) z+Dn-9O?;g&-OJCt%er3^kG+mRZrwRKv#+q$61H-f-#>;9*||%v=ovI^;T2Lr99qINim$FWY!JeYczNAf548ZJ4IB8W&G(4Zf(IL-ti)yPLrP-QyBjo8BrMD+0D)pZIz8(JVW`%~-yE$dJG;Vc|BBq5R1+G6DuFHfV~%VGx` z^mZ}5EiSIRwS8v|rZ0iDIjo1-TW-yUx@u1!$?S~e5J}7nMXM5>N?|%ck-?a?czf>tr1=Al%>kFBuiuOhsma$2eS6ZZC-q@b zZ(jGI;X63Y&&n({qN~p(HKI%H*|s5{IIP&V9q*vH;pg`ntqtJ=-wkywDJuHDf+n%y zlXH!ihFW-;HE#I3&0+R7rkH0=PemX;w78JIEzA^{%Bd7%74-lVv#RkE4(m$9tqHEX z47+?44lvTS3Z34;FiQnnspGX{A{<(U0lz!j9WxP;q!D zJYKor+|M?%COXLtnIq9fPOSVu7eSA?1H8;e^nlV?Dq-l6B)*v_f@&jm|Fj_e?PKKR zFbshlW}W9QGM)iD3J;9mDDtca@5wNbtOwIZ(&Qn3k)dLzJVt&ll3QDli^QKYf&Y@? zxcwcm^h6yo`qL8z=OIElNi+2Ds_1lg)rZlQ{^{pTO#zCV!ARz z?VN865&bh=>*WLzI0BZFhp64{FnU{FB4PD$M0f>yNjx-D$_}vImS9M zWy<1_DOmc5I!K;myLObPpVOj^IeD5w6l-#sv9*pFN*}OQBc-B~g|m}w%H8eTd@)zF z5p3jE>K^J+kk3pi0A#jhR~$De`UI!|UD1Qb;?azJ(LN zJtGY@`OM!UHKQpP9!rU~jw`&z0Ge)0Mfp>t%l84;RB<{*RmaD4V=9>mXcgOKRZu?j z3G!RNY*|aTtfDHQ^YF1qHZC^GQlsw#r8#va94^FC5XS7hLeAG)+gltfXT zF*Q>B4x~)VUsbVgq>kU5&18&WP+>AI>-i4sMCn_SD&F>{-7T~+)&-DyKF zW+2*?y{i(tuv8@pI`PL=DrHHXy2by()h}7GM9$t+%GneFE69H!ZHksG)N-Mn>XHoo zmNnj^oe%@&32cPWT2#g2o*4X@D?+HME^BzNJU?lXfQj7uMu~Uy?_sya7Eil!PJQ}c zkp$Gii((d8r9?#XtcG*q!X|7j+X;(ka%7QJ8o&E}B_aJBm*d*O^Imrx(FOd}J(nqg z)wF7-X}=vSfU}`Mzq25wt6=x^(V#&jqeLl78teBb;rEUA8jr>#H=H&9Opm5{8`=eEn8K_E)fb&^|92 z6co2L9D)mU0Q~Tm@l}8ZMAiM}JCd_LID+ve{Vj|hF2t7LeB5wCRt1u;T_BGk8lGf9Com(9_Nfnd!@_lnQ z8|5t1mA9&`1NCofFXxcmC%s22W8EJv${2=!=86CaZg1QRoKna9d`Zf0t46P|qmOLs zV>L6Ow=f8P|9xMXH9{H5?VfAMJbkH{@-K=ic$|{q-nh&j5lc}Hv*f&C zg%~-;+!+*McRL@UI)?F+g*zxItB?qX*_}U(`70B8sJ3*2X)=*!j97-O+rJ1 zjGp-JrRxPMp_$aM-!HvC_ZH1qA zDH^aJ6q(uK4XF4SFYWrb>rm2AAXe`_gNTYMY~D+{zP-Sq*=|*tHT>vag;-XJM&O6; zsu>v~)Xk;Wc6~3Wfb`r@$5YfY9?0KnR6T2So%Erm6+UGe4jb#TTSq9&z&j1!C=`2{ zTiL~c>M2kmCZ>UC@h09~oC4MBK0igW@*5m(Vb=%1<;-Z*y>oyR06{`2VX|gMV-GHB zJc8=fB!}lobSi@?jz~W~>NI1fZ~m0v>bOjwYWdVC#lc#22SRE`V8A6y%$Q8yMVP~v z5V69@``wR~3nTFzam2PW8a9_u8Ap_hBb!n;Y}L9<`Y1fg2aPK~n8(YyJO-briCt7ajCcgeNPMIVNWv6yx%$pq_`!qti@|uLBicqaVm@auZH$N^^0oSxADjnbx=VB*2+$4 zfBdEh7v|9BxYJie;l(qHkt@1u?> zD?vM*$I>M{znaA$iKa{fXB(@}QV?*us?wFzf>!af&r-1Gl=$d(g4^6yn&-DsUo+~x ze)|5|^I9^p0=^;#un{HJio^~Sw>6AvII2d#fR@&3C!?{HA6SITFH#Uh_%7qa9WHT4 z)Jybm92EYI+r6(;qoa+7=1Md6fo_cN zefspOzcx=k82u_yH1l#cE67pseHxR0!I@UIDNo6TeE%a}EfuP#hCEKaYibqEBK=LK ztBwZJb2 zr0F$rS!N6t>vS3F`2F8d-?5jhO1l#$;MDaEX`&jC3C;9e zeo0!b?OQ70Gxn;QScXetgOv33OKv#UV*}}dm)v}m-dT$an72`lws(Bs3!ydQr=;i_ z43tK+i?WzgtQ*hUT8YW-G!Mzf1B-)PLXa{0UosglBI3su8(V)jXfUQgZBQT$Q(SY) zylqv4)+fzW*sD3!wS+x({%Fh)kxL53w7n!Do$RYNefAR8)9ozl=-nF|@+E1g*V}E) zxKx_bJXj*Z9ggwhE~O{#rmt6XO=wm_lS=`g)(scq=4^o?&!2V7rd^Gamk@NMtsbE6 zoU%YL!z9Fbimp_SvD+HAFdLbEiuPq-Lo{F%IQPQYw?^jx(Dn@+I1Y$x}+~rGNNosL?$FmXL;xu~Iwu53EUm{#mmh=F%STL-twqzZT zAjxbPjul|mWFoF_mzZf^SEry-(^r^Ad%to0n+}27ByUp78rg(cGaBR9=NbC1tQ+1= zR2aUzEJc^nwitKLCM+O+c-vcNs&4Rp6>XRYn$@O5cN`Vo{=G#bHqXWHUwu0|@M_Pi zZ71LLB)xVYqjay)`Jle2mx{^3Ft=i0oHfREhS;|vk#=NRHRrj9mu?Py#e5;XDCf*< z$eCI*#ULWsDu}Ke?bD`?wR8HSUNO(_877h2zB+oiPFNh9Tu`)*%-#VdENttA&~T&o zvwr@W6%leTrM-490f3H~eKu3KTdTi%hjw7J+N+*;Xygwp#a;2`^d;38)^onZL)BSB)v?j(*9Ti z;OO330fmgGRmWI#rmChd?ZjYh#7bbUGO}%ux%65ADo^KCtEGSlw z)$3^&$>D90wOf*ft*b$M-+`Ax);;BQf}s)e;4JzC*wO^N zL263QoD5F?&eN20;D1Nk4M)~N1lf~EVi5cIT`slf(bET=ZHt*I(ypO?FLp>}sZa(tviRrq3t>OH-R@&P>YYA%a+ z9-&9W9iuqRG`Q`|uvIkg0dc1~Du^&Wu)Onhp2A&s!_O}bJ8%HwbyEzh$&{Fhg!7bo zeW>wGl8d=_1NTU`--_hnWHry|dT0PEb}S0U;3-JlC6sU2kS&lY_j@Is)oAIyj~2dI z&O~HjyM-&EtM5}GNf1;pga^*Mxx?{ki2b_OKaARC6@L+wXjS zFWi+#){(?w&AcV>no~a!Gc5L@d#CNACx4nmpC67S!fhX=lO1wbrRU`g2PN^1=St^V_G`fbk=AFmwY%G82J8lgwBTu5+NsI8zE(S?H*$Lz^N+5i zzP%=%d)|d9kUm~MmpaxU`9*3@vhua<$K6^z=N53;tWw(g)vd9a$0cxm6(>P~`EPee zLc=_=urk)#isnw6y)zy}2e@((+0CsR?8B-{-ur}VIWLuX^91(2mUGPvsofMSXQdn1 zOSAErF~Yh`d}-J6r8&=9!R@v7dm=%u2#AP@WypA1f7vd$l;!hQ{00xt_2ep2ZGF5D ztyr%f`}S#z0myEY8y9Y}n{u3pk~A2SgkYI;Y6`M#_^fU~w7$~&L_ch9x&H1I^)fYh zg9}q(^&;ger)7q6P_Dqw@QH~X7^{qNwPBT>bAvR^iQBH>i_W4COeJYLul#YtD85(t ziOW!WM#kOM4#T{=M#>GJwf12)HdEcHYiBOn-aclAB#~Rak}V8kwu81Z2TgT`^MMzp zu)WEx8IVuub0<50j^A>B>P!&S)Lw zz1Dz)ERR{r-4>fl&>kAmz6eB(WwD=1((s)?KQiXJd}XG^5avm zaYVj?lG;)PA4Pxk^_HTdd;O--R%roWYX7@3luJol?7_mzV98Tfb@F2|JK_KhYY@5>4|$b77D>>~7yPfVzXUc@alt&+jk zHiuFTQ7fN_N2>;W^&EOC%fBLL-v;e+36;yER8hK_5aXmN^ z-)Rg%H8WK{vmT;N8=pL_B%PEYjCqYwr2o3xz5U6on%te)Z%i$al(dK7_OEAwq3vX{ zZ@Q(k%Nq2SouFa9Xyr7%AGwK+KQvZqnMu6kd3CRKYQivU&*gZDT-k0B`*d)CAZ7cE zyHYrR#T0|1(PNA&LdxfS+WQphv1FJzs$SEs!|X?IHJH}O%X_C+Z}fKCQFWe&SEgIb z#5vd%$(Zqk_?soc}}|20}cAKmAln`WZyI% zqqTR32Dg0Mh)eq-_?W$9#s5Xa&ZN_-ezVi+yOp^5`8#fq+67UYjl}0|p4t0npIQOd*U93g;Sk;zM)2E`!>(lxIYLZaATK|S~WOq96$IKSny;*N&yJzNZIt?0O zU%1|6){v|DM?bjd23P#Rqam;K%&2EIHgB>l6+X=ba{(}!H4VSdp zQ5iJHatSZommn)hwx&Pi4`SC4#Y z3d5nIOQoT3w_LRkQ=_h|ygj1&#qsX@44!eh-PiZX9F3&7xpA7e`->d!R5e;ZsU6yo zi&z8=4o2s5bSN_TO1_otDoe4|nTb}#ctO`)(@MIG4;SjzYETF zRTym3!spDBZRmW*=gP(8E(o+dCdwYpa-bg@Vr(>RN`<%)4LP-~w9J`AEfRpJfonpdgZf4AfxR&rys zg8aWP6y^K%3SYpO)Ll%SJ?t&Gi_)YuccXPd2 zo%-W-y-v=K7A7_r*HhOEARKvVIcd<1=DRHL4|F{PdI(~nprWTDWud2~=VWKOD`GAo zA}A>0rDGsx9_^Qu5a|~dlKF1+b7t|^vXHRu>%OnMC)d~4DXqYNm)EPX>+_pL5ZF06 zMfgQrB_v$W^TP7Z|Kq>wPas@0L~g_?Bm_D@!5sk!7vV;x9t1)_0djkj;otuLB2$k8 z$kZbtAtEE8pa3%UAOs)aJO~*V1&@|T;ugND2`Zff0k3~_78<=|RV$&|@IJ#mQ^x>w z45Ay2dd43j^?d(5mHPjYNd4mXrR9~?we^k7gFj^IfpQ^$kbV~H_mcgkT)05F5Rs9Q zkWp{Sg@EV=e2{RFQD}K?;Yp~XnmFLo@%p0?NJeK>wW8DCQ`;vrbsWYZV&Ge3Jh&;^ zkCOfO3KsA`D%tM^`=eZ6L0Cu#K;t3dg213@K*jx+EJdL5OVj+n`bNCR#`=_oWjR(8{NBdtEXD4umO`E1*VG^Vf=cuDaY>8}dE0P9 z_$%XxsZ7)W62vZ$PejQ>^)>!(PTVuDnNKy=M}X{B412xBT} zG`K_mDCcz}>GijdcFQ#=(g9F0#=izh5}KA+lS1!y8Ek|Bb;W`>Kqzl9Rs*f4>4N4` zZ>iZd!LO*#daglapc*Ny8Ly0!C^Oh+IA5b3c&!wCwtWo>2kB&&*fb4ZP60{k51tQK zpM4wx)U;~gdLUrsTfxhkT3_Sjr$~K9DSvRoBkkBn9OYwTx&2z`%dD_==Y zD3V(+<$E6&7CL>poz8-Ato|rE;VY$r=d)y&e_I$rLnvId3+Aj0L(>eY@VN$2Ek!N? zJ1Qt4EQPy_cRNWyz7~c)-2@1Xf9|1#6uhJ&{b4qafA0Mnj=gHKaab2&8c=)XaR}ur zyMU-hBJFn$j1})pCCGj7yJu00#+E@PIXqW>nYY=@W2J~Mdw|EYgh~(SgsEJ{KSQdc zd9jC{=7#8@?Q03#-ZV9Zh^Qd9olwIbJ1Xp!_+KR7^I(<=!QFME-jJEuff>PJg6C?m z=K1k!(B3HIHHhZjvulu%14sI&9qOne`q}{cx8F6zKCB((`}}?pwO!o_1bRHbD2@V` zDiPXzC3JPivL!mZI(}#|VBd$0yri3ILR0HSHIA6{@ufxv<4Gu8>=75Q1PLF4vB~GYvdnvMKM_ZQD+q6XUBmzFvDN5 zb!az})?I`A3*fI<5IdgEdW__TuT^R$X|SmJA7PA?o?U}f1!3NiFmy{qckij)Ftx|# z1}TB!6l-5g$34^>>=|FtUI;|BM;uS2e`ksuh!8Db^wnYrgA*WF-*l3a*(9vW&KQ!j z*ccGA|DNpAwAE<32oY)VJ|5B~vGij$eUXEYC1l0VcB@2XM*P^mTbib8)|$PhakP(U(U*}D8GKNw%QU=# z%^#S*jq&8#hAfrDUJl)AkL^I~k74sslsFxSoZu>Of6&M7A4l6MCyxtGoJRzYtrX7+ zxS`##6=|AtMQn$2ir-e~DK|(E457K7O4POVskr8z9Idj*z{?19;cJjzA$3t1t_gy0 z6koxFH1lx@T1e=70+wSW0)%M7+_l%?ah@^s)Ne?ck4kW@N((sIfNIK@8-yJ@K9>vu z1(M5V*=(YF8`tnK<^M?{`$j6etVnKU>ajR8dj#-i`OF8IVV8w)&D&=K6b{kR3?XQz zUz86^`2LE7{XZ>i3X6x?h_}v$y0^hHHcc!XfG0m3=HZwJH)^3 zfXvm<1s8DNhh%vA@N#o=uPp6R&Oh-1Nj!t+wQS`8BHPjhg&cr-cE%+jxOs_Nw2s)c zCJWxG9uKMT7{R{WesAhW%HU7MPtQ1mG!p>H6MOqz^kA=ZXP(K&9+Gc$j9_SY4zIlg z9|CY?0J!nQybN5jR0Tn^6nmFE%=h5p6TqfseWz_o&i7kvnTrVHX+4O>D26(5AZEqRah{1 zEqDIxcnGlSmZ?~{r{XmTqNrUH_~4DgMGeIR?319$$Wa1>EGca$9%N7s7;QIlwt+8E zKwrEi{|1e~+cS))&}Wucfo$#efH(Ot?i=98yOR^uO=j?h{LKQknmZw*#0^fE-{%9QT3>_sWZcC$9Y{n!MS>?v^z{Y_IDCh4MT*-!eEP6G zD+fjD@MQ2gtf&x7>lvbx19#b@(KsDT1uLiw!Ed~VP$Jp(;J&dp0@at6#!l*aw*?hvnCxwGHr3h1TDHynbj49Nvb^XTkYA zh#^Pk;5`7pl7XzB%;q#==Jlm!%z2qjWULrK21g(_`mwYDd+!&3hJJWud1%}6( zsG8C5%+uPimjiD$Dfw7^)11G8G5-*a9bTSu{YZVbu67{^J_7t+R0oJx;d!vYZi7+$ zODvgLU!VrrwwgwMO4?E>4qm~oLCZWcu>g<(LoTpXknuYlnd%05WAvBKe8klE)GxG+ zjt*OXDA}qg-~N<5FDT6T1v^3LLQ#2n763!@@P`DT&e{)Fc+&Oy`3`TIAY_nu7a%o- zAELX*9=|g3`_05r|9rlC$Cgg5$ngV1y4lIvM8@xFrr(tICU4@HD+a)Qe#^4v``Qog zG!Blp`s1k#ePqgX4{af9d)FY^kiakGFQ1d@m0~#`w(g1JH5jrH$t}53yyjT~mx(@6 zNO8{%l)yEKjh{PLr}xPIfYZN4y$4<&_hhBRajE=Mn76m# zkJhY`0tqm>JeFOY8RKFd`^VS|VOdjAfH80`{$37tg}z;3fNzZ8mkCo>|&etBHNhlAEiddm;jK;J^=?g=X2dxLG8sa@P{yFJ>k5P4&~ z8D+erC$hN@>|qj}o&adF{cj`dKZM5rhP*SIfSAedoD2x<3kta*OEd6W8J9Sji1TnU zu9kV~OSB@UH}WZRG`6UbX2}sZMo%P+v7f&hZS2BAyWAPGWIZU4y~LDuL- zcOd}ugjD^VQy|cgl!ofbbPoBqP$YvA{z>P+ID&L7-&Ac5P=z;va<<+1)l1kUJPruf z!i3>F0FMB0OND@+j4ZJ$fv}}#rohF@n#-;V5k3EzGYJ@k0e-bS@*0#ymY!L24N{u| z_=O+4KjXg4Dj+G%%eo_eQPua2brGOQ-V(%VWN0#|NlJ#Y{T`3biWbc?&{!Nu%iK1Q z-5hD{&g+N=lv8l&cUyGWEyNRC8QPh*f84vm1ztM?2Mqn87F*Ng<&53s7VP%V4F4_6 z`wt1S;)F50qS1r!Mb6l{}~{(Y@qTu11$8#T+GxCh6amX;NbnLj<1 z3KZ%!R(lOPIBoHK))dN9H?_u1PGGhb39n`A_=iZH5Ck}k zmp~V#y&6z{44Y5&^hlBRjRRf&lPYGvfm%@zpx7g!*yjg9u&;70OQ-WUZB|Qtu!IeL zhhX|6b{f1fif>7FD_U#-$8&IDb7HpwV8-G^w|g=U1i(w7zMx-3+*j*hJcxc&*x+tG@ow;)drLCWA!hJiyZ@`QQqn%_0bM7>`b|-C1ODMB9ERH1@xqlqh*Zx zH~eU7b3h**(0g0zPv-X1k~Fvdpltj1fkrp|z5V$>BRoZ1;I&}5Y3Z1+_N91=$g7#i zE`CN3VI=l^&=xU#P>(S3mRm=cdrQjDtsg*88z{A&4M37XPSyWc+q^J0;;DBolz7yb zpOXN=sHYzA9za;&+acjb`03?p{j4B2l@5Hr;?B%O^|hwoYHY+)GQInL7#WXQvo5Lfv{)(N{3u6 zYezR8G-d)H8ROMTL)8g$tlAKY9o-fjf(?Tbcn}*MokRAfO88WeZDU9RN*j&Bnunau z)!HM9f}$EBULf`LOpI?*z`Jt+hK=PWy?p>+RB2iMag=ossb)_uL|7&FHEKSjv!D?5 z3Q`Air0yR=eiOrC@x)*d_C3=#o;dmjh&+SCLI8KEeaHn_1LEHKD!FBS00Jxmu*kG@ zSR5;w!5o2c>T`(=Dj%CH9oxt*WN(MMH$w`fb@PiK_m=sQ5Wv8N)ckh%M?z}-G57rm znss+wUna+dfC|`Tnf)Kv`$Qh?P|X!3sC;?xo!wc3aNz|ip~(CJ)DFG{@N|0E=Z8VC zVR7^ynV7!GL~Qp>(|o>Z8r^I^+7RLBBgWP!v;0r2z*y5YcjFFpih(-q+Nrq0yih@T zzW&ufdRk37EZ**|#?X^KimY#kav(UK5Iy04eEYn^H&i;=2~Y)I6D( z&cM)q!^{yr)IllxuHqWY8+PeZazZ%p(M|PL9A4(y%Meg$tst$x;2{N73gq&HE3@R3 zb;fdTB|6nf^%`WM2N_j{ZjToPo4;zGW|PL|10?_uRnmzodWlp`lx z)FUSe!KO$S#xH*#h`00ou$k82zCkc3^^$zFK6}6!LgI(RPetpQe}ftS#2fwFYciYv zfF;EMz&_Z7e7hkpk?G_THdjo7Jh;S6r&JFkI|~Bm5|r;hJ7VnQ6~Yh&W&eR&{sE!< zKr4lk8FlxJcMd-d+UDo~^Vo^KA2Mo8z5NIJhykMB-|)%(e;`>14I$^S_W&IRVXM+y z19IDU<1zm^9{3XqQ6D2R+Qf!ALttn_KL}|;`H2-ZP#z-#(Xw>Ai|B#2H757@iBSpU zo;X(c)y%?X3<@r8g5<|#&+%da$5mym$~IR)w#RF9_93OA6*?`a)}W~y4_JI=v}Mz> zRRQm{?)dZ2`I9-gVGsVleAs|FAkU1m(Vz1b^N_A0;Ppl~10$v#;CX(s5CFl^a^-CR zX$BwTst^53wDT9lgktpY=Wug}XwZQhP zeu1X=4GaEcic8z09}86Zxv^(~BlhHcv*%+%(G=_oet{9sT08Wa)Y(;rUoAZ}q-^`ep> z=4)<@N5~+>+sB{0<;Cxu;X$z6Dp4 zS1gF0Y}hq|z=?~BbJf$Qz$go}C;v4F1Hf%Bw*k-rR);@_6Zin@t2ZG7kTyS}Z_?5E zvre^=IUD}!n&g(G$&lmVKnD5%;RP>^c?-LX%ZwxHMW7lA#ro%uPQa@zi!%T8ZfZX9 zH)-|*1h|+LDWku{;w*rLyklW(PqG|r`xq;skGgox7$Stk#=+C%aNlz9UKSASn1)oG zJ_NF*O??IoYZ$k4s4qM}0PJqi4|ca@8v6>S51D^>#R8=T3R4mZT?cNUQ&?t@TPx#~ zKp*?~PsblVdol2w6#A&IOI#Wp4^j{in*;5=A3V&f1k4zK#RXEfQM=wX!W50Esp>C& z%xFmc4H_32l%z@b7unRmSU4E*E^#SOanOw8Zl z(vjz+mKLcRnrLh3Ti;{wY2QT?==rds2OdwNi|VEl8+M(fBONvm_0fPF%o8A_fu7nh z`2#)6nm0!I?h=G~c29$&047DJELEN{-H3n8#Ql@elYc&b{l#Mcg=J4O$mVd<+o+BW zAr%(VH`T?rF=SS)-<7tKnniuKhq{NZc}C~Ql$~rY!4e4;CigqdP0(3XJiM#95i5?J z>#U0#-KiOf22j%Moaz0@^=TT;(kvYjk_wD`B<-l#(>BM17GfD7gn!@y1VEINB1K3o{R`E6HK1jK`?xwp(?&oZm z{pj9iS8N>w2=Xks9;*+X#BltCDLZ}GjDB5}JqyV*pgv8!iM>qySX!Sh3?!}TcRK_K zlTaKNHUGL{ZlF4C6mEEg_SUB&7R2~>+#D~Sta=AoY~Dwd$x}Gh`e|4^Z~|RO5#)07 zhIuUkZt6~TH^uhZN?U5>y7EXKlpQiSb`AQ`vGtmxA(NVL7g3OE`fz`gsmILP^0N0w zDo>4hbMVoL12F1h?-vZPhA*lh98p`HE@W%~7?PC6C7q;W3~J=+Ycl1-W>-yparx6a z)BsziPMF{4UQr)Hf&6h?LtyCRaKiJXqoyFN2Y8}vC)z-$rUIa@-@-TLKQ7hODO(Qb zj2h&%W8mGTuvgBr8t0)+DqW^Q)NOz?SR$-;-))cmvNfk*5201-xpShaOLezN0EbPU z1+nE13-*Zy%zg=eNxi7Wl8JE*`lB?t0=jI9{TGHo_JCmnFj5;z4;dWqf*pg~BCCNh z>W5teZ3UW&>P%6nfz~~7`SU6OUR43q7!}VwM$10*PY$?2B+c{CK0rtey|LrmtFGx47v}QXTGxRSUUrl!)E348)~_k8{C2l zJA`zG8A5!qq02v}*|XyAeg?^86`y~EAOD<_=kb88|40`k8s11zOfmxt&(7VPU*m29E7TuWU(c7Lb_ihNhWka0Uve4{fUDTq5!MC87mt$jp zn{oKd+KhjBUeiDwE-~tZdPHa)J!~#no)vd;%a65`SX}{MpCq3Cf#2ihX@saxvL-;#e}mr$t1)a}+|6@xr90_Le``2=*CZ038^F_FaQA zL#kBdEbKS}Wg>Q-PPn?*O=5?HY74e!~Q6u~t2b>ZA{MEnH_ELqM6I3xzjS92ITEw8t{_ z5IbIKpens@1wwEUNT(lj^f=kw&xtR%Cy{}H+vizVtX;uT><3_uF1_|Z-$0+Q3j(xh_r{FA0U?cV87ssPVs8zbZXTbiwI>VKMqZ` zErx`Mml(R0;030buMB~w=Hag89YTY?)x zS%|czNgyavk_GWqos%Bn90zX>R)B;)oSrUMQ3{Poc20cr^Quw5`q#GE7)>mjEz%jy z`NzgHIng9H{aShTLndaGGQs@jveqS8OjTZOn(`hU=bqm+sPHpJ%=pxb)KqYg6tn$R zO7z9htujJM_MZMg-eCGWpIIP=*lX%O4U9tZhWPNW3%)+Uf*FFbXa{3MxC6N0S5u@!cTyZf>Ih2JYH^Om+W>sXLaL=##p$z>u`9N!`Yv*_9bCLC;2O1 zy-(JDz2=3l`i?f|!l7F%t*dK~DQG8RoSv?R{cg|0=xv9{Ers8iJ{-9h13U@BUj=B8 z{O&lM6rU1pn+C`vy=9UwzlEx*y+JP(j!4rM5#UGkpGI4My*`COwU>vEJ@PcrYD@)1 z-HhxSROCT>D!p_lqJgI~yUSG_WHz>(1x}>Svm6#D2}iEN8+jxFKmC@m&j8O(BOLqm zU08qNSSa?2tkzoCW-$e3ZvAc9Nu02Z`-#WLd`)KC?|tcFnGtNj+s8^(9^AjxL$VV5 z>6o;r@IURz|K|EP4}7X(!7O1EUduzs?|zH&ZzBEwtDhc&q1(}XNt*~r)M;YCgzg$Z z+=&4pluyO^@Y*b7Fa_XYp2PV~fjPfKb+Mh=@WWKbftqEE8r;I)@sGUgnQjde2QSmi zpL7EO?(L&p$Ql6W=UWxlZkVS6_#;A~z*AlDH&$$p47}Q$Nz^uBx+Z z-;1ehP(ljiuJuiwltb2lIF}AXWGmz1_!`t5a8o6U18vns?^hap_tiiCI-XsRmnJ_{ zcyVhx6{`95k9-qyJl?I30duV7Z;$>jkRg9H&wsOzahe7!Dk?9yz^KyPzMO?jK844d z`e8^v(5PC!Wo1o1F=N3)=}NsKe!CLog~^~=JvfrzG=*$Cm>8Og!4PexGB6Yc#&ZzA z^A8>+g(8$`r=@L1c_K|5<(}t72hY)KRG}T^d=zDoW?!F7GtnAx>>s~KK4jx%{i46% zs|%0&^H7{Z5X$kK&Szpn9LMOumKqvSb{SHm@~s@o8U($S8(h~O0S=bPLO}WkLb0;io>@PknCMWZ=f&2=!D3r%4cE`g5rFX|=3tv+r3jGnk>$T;fpMUSbE3 z`B6AQhKcgU4j2aGBPS5G$N+8xveq|v&>etw7=+48{rFP->>Fed4Ol4wK=d-Zr-9!W zNSQA5A$<=Ad)XkBz+9UsP()yH1>JkE(!pAi!967>+690afbIgb_pgl305f{cn@8+tted7s`#tN$H%DXE%Ig@h6vwPS@Wzxy(Q^d)Ub2qhzd)}n| zl`~V6Zoy2FcTd&IOL*laFv+D5T3EXqz?~EjChM8emeITicb5XntbDE^NYsNb-aCT7 zT7k73IZ>g4Li%m%OI<(D%a2QVRDj1-w*yuHqyx(YN8yC*o#h8rB01(h_A>v6z4s1_ zV%hpe2aq7B=oSsEAW0MighmumL~;%eIR^zK89)@tIY}HP zXM`b7;Hw!x-RHPH`<(Z@-*fMC?;kwVbXRv**IKn|h2L7Wl-f)#{d~goa{WG2wEqAz z$_wF!!hR!CB}Mas(>f;k3DW zjO@6>(P{gM86^xIgaWXVqSaQ5FI+h-&BA`r059zIPXnV-5H%=lb$jn8$!|$D{%R95 zIvR>rw`r`XxC$-|GckL&dN4OQ){1+c-sivMjpgXv5zWAZE9VH(xfGZm9!iREK3_r54H5;XmzDpDcTb(^Z-DSDul-Yoq*~ zcIvh}Y=y3TIOE|pc3)LRY}a$T=O_KdLv0F%l^@gHCL`l5P$qX(EMgj4san_Y$+hSl z!j~e433HLYb?#N9o3ejva-6R(^CJ(|BJ1TAfef;BbyC*T+?)Zl$k#|Sir7?OXM|Wn z-lx|7;N*9_e4Nwn-Z#Mw*j;7vo?O>W=+qWki|8aGeG8nR{X{1yh+6$PW+!DocK*;U z@qv*?oI0M}-Srqh$6B#v26_>gq{VlTRsd9mfe4X7g6}AGy=nqKpT5JR(WvUEHx~!B!@G(`-c*A@^4@{~lxdi?HWE;ZXl}o45d>D8dR+HUN)h499#x$5C-naoPK?O+o>g^fF4mQYTuD z?{1B8L)2uxCSE5`2nNRXUH98I26MEH9;dVeo?W~E%X)Z!+Bpr07Xj#w+`u;6yr!8? zkBzCik?`}f*c-31Ul!fkC%fNk(#3|Oln5YcSQO8Hul?v+QtElBBm8E=4piYzPT>Gufdv~lrJa3)Y5(O0bJHh} zS>kK1iEv&{Xd4r}B=KQYX@@%<30EXz&IS0C{{sCD)^^Q1ZH|~SLl#_jQA-pm zExflh6U{h>5P}t%%LD<;P#qA<&Cf0}yg^r^`F(NRmahtt)D;)USqEf~@3C)^6F0S9 z9yK`OxOROAb<*R+8`izI5M5_o@&hM1pEV-)Nu7JoJaYZ>MH}Xj^3&=w&wFbSGr4di za8BCEAg!u5U{_r?V0o6GWYRMB>*%b7^&V5m8cVe=h|)H0`zox%dlpxD2oVss(~Nbd zu+I-Lpmy~VeN32rgAk&7hYI_J-5q7r`O7p0YhRF|u&dyjPPzY4piGAO6W{~}FLZ!H zxC5J!&{JhytZ-xWxN15qM{IEeR+>G#(4C5bVSy>J;x%WDM&0dRJL`ogQ<-c+aJK4N4VdPegrgCG9Efrqh0@xQ`*Y z@0&|AMeO%j{huLCA|Ep-O^CjRq`I5ju+JGxK1HbSMDctT-Bo?bIN1K)RzwsTy1xtMoKFQnT-vO)$9Jix+ zhnCUVyz2dw+&S}eflF35h10T(I}PXBAssj50I;fZs@AB#yVc2!VD0T5+(s7=kJCo|DEaTJ91;lN z=J~W+4jMj=TmrM|ymAWaOr4qiDASExNw5-ES%U%m1}H%4|FRcqdV^RgPfv@Za{u-D zU6{u+iEj)2r{@h(S*L{gaNnPfaitlA%Av<)hHq=ih3`+ulxFvL)&vM7_q{vUXsqc1dERvIMXX)sSl@P(&ICd8wJ=*YFBr2gku@5k5`Ar#?&O zRP(wj;MeV^{BQr#O9Gkg4_{@-Tw?krV-FAKoYfmUR0+FGRX*yI5p^d+sI>BtT7VPt zD@zZSR~TSpcd22$l$3wabQ3s`7L4&Gth!(w@Oi7D9Ooy=QjIQNAM=6TBT#ZtX-ci* zE;O_}G>+^92z0=M&yFr2O;o zjss;bAZ!H%q))~^Op!fvU(Y%OpfN;4Z*8h{2_K`Kseu3IK9N-Fx;RM?C#fr+!mq~d zjQ=jTIo}}WaSn@0!@#>j;6bfIa49->r3&xKVT0%b(RAP^ii?s5Gz5?@!fgCO!#Jv( z&;vaR-WNjU9Z<(|H1B!yuP}F!t@$*^Q2}@jKxYxLy97ktw%V+S7)u0_;coMHKNA7j zOQPDK+|zr2Wv}eD?u#3+D{a&Gr6!ysqFQ|~l>QP-U%+zWmd^pL09}4dtd*t(%NXDm zl7*%M@kVh^aSHyJu{FN`$P@odufv~wFaN^3pCZ@F&a7_O6n~Ql4zosK*Hdu-&^@KP zRs^9Zkt={)*#t+K^3ycmhq^}xMw;fJ^$xaZV6lp(1M?O9V+N94M*D%fl>wnp_*WFV z_4C$n;zKl|*h#4d#$TXzS-!0fW?NI|(bc0cq&X^Mw|Yx_2NPaTqlcZ8(OiF5keqms zWN=X&SzLPBCbEVYo~hhKuhLCL=$PpH{&C5=_HuQ@39wFsK_;L?q^j1ZfDr;M?ibt3 zl{NiQu_a4^Eka^{(A{zz2uTvMWC1oA2xX9Ivg3gBf}+bBQ9DGET_|t5(hh7SB_foj zeUT96B9WXfI-mDAir-J*bTm3JKpLU*%6g|KH;s*%QT^vnvdPYJO-y&I?VJ}YWr0^+ z!(#4Y`X!Z*3pKtV1!chFbc=FNUv}+FSSH7ZQ+Fs*;;7CXbqqY=zblbE1n;zjy?-#+tq+$C(}6;boXH(|A@$L(XWuu>aBPz^Efcts~EW>Zg*7pKa5<9qc zocgw-l!7`*Tpfet1n%1 zq;a;n>TwRI^dgm}&glK6`5;#tIubq;ed%NENnvJ@#{#99S^IWf?@UF~VwaRK<0@kx zfCEYmzfMP@bj6n1 zS>AT-D=-zj*w?L7wQ^m2=}^Ll zr-FE7CxGfBh8hv^pe)lb5&!=U6X-vD2K@}+{lP60{$5Ld9nING_mC-6DeuA8A4Cum z_0$(hcK2DICRa9@Rr8Mr-wh<$4_wfnAoRpV^;i(URYZ(i$8Ka5J=af5vT~1fi|#SR zz@erwwf_Yh@IM>?qWwuv#`w0%QnIML$soSO;d&bV}&h8Qy>j~Lm8H&uCfh;O7^XJ44av|D*)(2pf?Hv-VcZSQl zu`$m6&$@y8?5F?+;qqd(DIFgIa%N1f+0aJkixiF`zXw+TD>n51Wc>c(-o4^Km`L?1 zkDe^A(;w0%pCmBqFQBTer4@J&wF>j)oh)eH1f6^DbU|=2RiyN7yF=IoF|i{h1WS>S z^tm-MOXSEOmdgK4uiT$ksefm++sop@&$euNaFH7-Z$30Nt#M!KiJrSk4=$%U#icZa)cua{T5 zi@dwM=l1NrjoKLcHZk;dT2w zqEO#;kNngxmc244c$GY367K9ROwN(suirF8Z}(4p^RFAXMH}|U>@gT>j@?rx(OYb^ zL@~IWS6Iv`@C5RbENj*L*k<@3rcLg!!I{{yi%xI*2VMG2md27-AB-dI7!GI^SYPiw zSudSpWcJWr6ARxnLpk{37~aTvCv;UB!I16qRW`QmQ7U7_YWK9au`sZM=e%IXjB&j_Egh;CP*)nF0X7k$3Rdx_?R=dB}` zRDxKjg}w|lRK2dc9d&ZDx2R5b<9+S?g@ih#>XhzLjNtQo<7Rd3h0Es~dTb5k*FBaE z3sY>YkdL%6T6InHQ!~vKH|9)0#)YbI8B>uSW+3KJt+l-5kSB*om(Yz#o32M@X5YGR zabV@W3@oj+hK-G1Cp0IC+z6lrSEjJmw>unMZA)96u*jwoGT?(f@PJb=Ilqi1`<{e*Y3zbz)GGr6 zo{GcC#sXFwsF|yc`%!lIkaSZ)=x|X>cns3cX@JD3P72Fb_iSW_+eM$O<5RnSBke%D zfpOdWF!7t#tfNM@OnL2%V}0~T@}^7|yBEG?kXkq!4t5(aIVjXE-+kOB!t4NB+?(3W zy2pcgkjdqvL>wiFH!~Wx$nvGxnAwAQrJTF*B1~lRD2>Pw&7`jv79-+zMQO#!&?i^D zB^AkFe>*}yexBSr49=!F)w;_iHq$`k!)ll7>!?^8gcbCPoTTa0^2>gy8rAEHGpFub z2$oq1>yqX?8{pMzv}MT6s^z zBt}OCNcVnYBpJQWNJ6#x42CX$23vvkL{Qr7Nb@fD-*c*!0i4|*BF-4XNRq)WBFZj6 zs;=TN4WvY*)Zdor1C+3B0%50%IQif;FzF2tZH8> z6Wg9If`c(bA0-6$kc%ue z>iMHStwWbo)`QvQY_m@(y1mR%=3h)Kv+egCvd%DQaC85}->qTfW(g^D1xNFottm9_ zCw6wAq9$4{3v@OMbe6{oMcoN{TdDr}VVEnrZU6QDAdwf>!f_8SxNaXR&Sf|+=e;Al zvtz2o;;Mnu-mEdfs`b(b*F~!6vvPImvToe>yfb+8Y7;5>)JMq|iXuDI!B68w>e|mQ zjy?0UZHkQBrIUKIDLrBF?&gms_=%K2Js%U{7nMZh_C8mdvAW=H3BB?f(h6nDRpRIB zv6WkX7dEuieZbEkY&JXcM1{R%srv`@Vxiz1iwCEe1We8{<<{a|*!&pt4*Jan;uN^5 zD6?nNmX2hfl8AAL5%d^(tme0$(vHc#(cb7NledRMjI+nkUOPV?TDurmk1O?LOsUKj zXN0mY>~4CRmL^8=j0)_*lf38YsU$?CgiGD2S95P3<4|*7nxD;w(ASXw!>E3o?CW)Z?nm-y?ZbpXzlufL5rr}-+lBW4KnYpbt)WF|&{1D5tWwirqsmU~YJIJ1p9 zB`smGSo53|eR5HOCr65MZ9-M!Y_BRbzdS@8P!%bDqB?b%7EvxRva2RV3ggXol2y#6 zT2sv3uvFMhtuZLa;EI=mzwqobNy!OUk2hy97&kGS8fKQ|APX~osleah2h?rVV-M>(agUs0w| zI7ONWSW;&ngGR_et4}$YGzQP*1s?HIIx}*et@n;JFg>x@{x0v2bx*W|IP z>C2;mAntRLPO^t0PLPF2=yHp36c~P_7WY=i;LGusds`uPviwDOZTVe_t9vkh;rB-b zQ(5d`NEOmxD1#Ra;9a zetgw$XUzQN@JhK{!^LvG$)i>mfKZQD z=Q}Tch&Maq38$RDm4*V4H}aX5M%1|TGtFT>p5gR*Q#WQ#AzKw^Yy}`KGmM&!WS&I} ze)&n6_YSJVd7-HV2U9RFnz~X>PYgC}nApiGSmzt)D^m@Gi7ZD%=h?1AbAC3~$*WT9 zDV+ukDp!{uPA;;Lk;0@U$n31KABdblExw~Ub{9D{6!x++`O9g5Y|N@e)sBxM53i`C zTP84j>4O%P40L|`#Saz4*~f6m`BOd{x}xH8%AARf+C^XnOVdU%^`6h? zPUw|CueRIyS%UGT7nUNzP_x?BLtE&)bJX8Z8kf5 zfrf7SbOZ`}+SENbU+jIOrxHx0Zesrn_X8>c`7sBJjq&JFff2ZK27H5$e;pUUB61S_eu?ps)=)v#>7U=sHKae4(|<-pKc^fhFg+CX{WML5sZ?MPg6#@#4};yR_un zJz7PdxDBvm@Qua{PVxx7aoTXc<5iG{CSw=4Z>d|Gn{m43kLapr6&k(Q-^&IphBy0r zo?ebyE7@grdbnTLt|0eWd%F3|CHPGdzp!Z9PK~hW(C|MhI37As zdGDE|j}cF2t*<|95t%owpzudZ-p4apDsT+*;sQejTX&4y)ZUyNelD5j2@B2-%-8hF zc~7XlIr9Y0;+vGOSm!U4%xXTVaATKB@>pzbz8>H8m~Uwm+HzKyM|3A&9OmjN6T`t< zU#InPG_?1r>jsjIo3@lJHnLpwuKm!cc=uhlT`^U~ljUxV`c$)(P|ffG>>YP}?X49o zrHX*?!&U8f`sr8SaJk(aYJ8+SkZ@yEX+P^}b~MfSBFlor8wDR%&4!-a{^d+3?6Dpr zmZBd-y6eMF+G9rzg>PI>ZzdI!*8H}Eb53%^dyge-qaH568~W~%Ww2;5WIL8hfnxgrFL49#wu>a7~6$dlauDOMhiQSz^+h| z{88?fr?$7EuA4GmaxJh?lC3xWgj{y+Dpb@>EzEYF65cpxaB$|HlZEj&mllaVC9fgG zr|S(O_h`nXYeBEXCh((%RDV2d3EMdMAxG}PKTlI4hZDG;Uy$efL?BF`tx5RH8pHzp zyx(gO3!DST|AiXFe1yWs|8J{7TuzGp|7#G_fa1%q{=Z&>I4fiKw8t1D$tTxVj#FXg zX~)cTy&ncilbvy;m3tl$^#a7Ns0e}k|4030I9+<$dvn*)U@TYtL~DotI}5$G?jox@ zTq@eCs6PKM3;2YbCu8LsFloff=cJ^F5jmAUP}3DX24cd-AgRIU;u`Sq1Hb~xD7I!8 zYLfyb+mHw>2Gm(pA!a^Q;W2c27vPI6Aiwwf31>8jMS_s*yUK%mWN^Hoxb52aGtBou zpkNxBdnxq+-~$vug%kYt8JX=T+x^FH$^hUJ_ySbS{^JY$x!1h#jb9(X7p^>6>#I|S zC6!vs?f1SUmO9m$rJ?R@te$Yh;buR2*;LI3b=jk~Fl_@(@_?JdT55J8?wR4X~No9z~;*>c6> z-w9p+wryOP6Z%br`oT}KZ1*pz){L&HrZ67b^>+8E(CV36pde7>Q7NqgOc#8qy~Ahk zaMm<%(vtqlugs|jz#dCQLz?#` z)p0PPT>#oZ$mIjn?~(?A(5<87_E+EX{y`>$t&`V}qI^Cl2 z(iJxjv8q2m)g~NR%(SE`meg&Zf>gIsyONfdWrCgNCRg_n9+^4@Unz+%+JKqAAEjrr zz$8vdedx}d)lW%!%5q|lm>@#uj#|-vhT(-s$~ne4GKD-=#uUAT{1G24dXx;dU%`_3zY^3m08-KPv9536h3ytV;zfmgRYMa@aB9d=?3ZrG){&yw3#5KU)&GUXsi z&b<)E7u@x;`G zp~&fbQ_^B32QihNNsmlbY?Wv4ff?yVH76f=nh_Nm0YoDp(*3#X(wz0T_R!W^l-U;H z(GconXp4KJ{!?BJ+oE1jgRN{X7}VJXacI;^O~SZH4Ca7&25PIN|8@(hX4ebLUaOcPLB)K%qp5ZnronK0Wr?dW(DVQ%j%B#@Q)$G~VSi zo&llK0b9&)tHMEcxjKmkdfn|aZ3e1^(wy2)j@WtoI7!=Z**v|iadt-6KnuKbH@v41 z32yt+cKo%JR?$1pk=jciUmSW5N_zez{WIm$bU(04*Y}3!(8Ul+%7!mzr-P({mG_Al z%{F2e0m2pB|Mu7SXVj(XR)YI0H}B6N+@HIG#IN!~mOT&{tOp>KIAeLGS+C^s=P)v` zYvjwH0%984cWCY=nRiFzEmZ{jz+OqI;yYg9ffPnj_|NDn%?aSXnUl`YUmIAa3Fp}V zNBNB%`v5#MW7%L5g)ij;DKDD`XOeTh!oZ4V@*juT)Wh)-%1|kkt()O=>jQb8s@(A2 zRBF1IR@3)M{dJ*WlIbCrS~3V@JBPr1v*614;&;p`=*ZJu982*J?q?w`FQx*qljRo!tC z2XbxKS)3jI)va`JM7#bKXE_1@8kg(oWsN=9Nz8$U!kLUbsD)f=hB%8fKyYzr5{;V& z72^6q6qBwOF9DWNJtcHzs6yHBIpoquPaJO4Pe(Gta}{A81=T>2XFwgnhJ9w<7|dl3h}9emSGZXr}Eeb2skiT4{vX zySmz(@)0-#E9(&{GP&801zU>`Cn}*p+{aUr1oV(ll>f6SsD{b3BVg84s3e1T_k+^h*} z9IBFIKf<1(tZAYZpsU}X)l?9^!%oSvjlj0(O}33A7mAHL#0@wo70Zrq%l~w57SWFY zAk4U3t2ReVI_Qb-`{K70ufebZ``AH=<3==QH-E<*YX|hdw{~^}BNSuo3F?0nc`LJN zeH_$u;b@p2l^72_IqAvFz*1^!=v_q zXMu`iCmS! zr}jkC`%vyzyx0Bu<+!M)2O}<(2FjE*0TnP2z-~{c?JtPHIr>i#YP$KKnDUh&l|c?V zQo=*!t!%i4SnZvR!;IUbq5|^LYFOM9VBB8@2h_&B*VG-!4xEFEIcYNQ-*T_Bk+k{R zcUuL8)G58M0^ZDCKI(BqiqShQ(Qb(jrXu}ylD$s^=qgNgtmF&57L*s#1!#$954Wk7 zg#$q&5{_R>GS8uUA9}gE`V&usHfRoRPc|y~Ol+4TMwqbIFgP)w<3q8aNHuDb5;KLJ ztUQxk<^^Q^pAQ2G~n(9kzi67i;cx`rvE@E}{H9%s5%4s}Ygf}Sr zuSRnK>=WBsM`@Z8RzV$VgHQcQjv?n)w&Yk3?P7F3um~s@Hp|IV-@r@KY>6UufYwxp zy1>0@uoSuELDM4&qLDn-PoBUqhn1|QPHFeuosc4nONgk*(1xlS#x}bne0FvH4Y51Q z7(Hy{J3dBi6sY(X?L91VU*WW_qX=p0cZliUJAiW*S(<1p>I zArPlPI3I>D0mz!!e^t71Fnry)97i2y+*BMjQnFUa_JZEbLX#>=W;`LT?K}>-@5p;Z zHva}}G^~TR-$Gg@haASIxjf>uR?)3=iJD<(O7Vayvds1Ty1f?YFUnAIWhC}p-eE-k z%#%7+0Ze1ndIvy*l9=8Ux z6RIza^gWn%1om3f60aMm9qWuwNlkdlG8TS|_9al*nh@sNn& zsLW@e$BiK;EnRk&v$Ya$iPPw17j#Xfh?)49r2WzW$aS zJ;kO7d=E=__Mu&+*ac`>gvnsT49L38m6O>O!A>?qv*{NuOlUf#u5_W3N~4s_0h>x~ zE|{B(t!^7;YOO<9K*h;9jH!5T=1To*DYghC%AnEzJmOthEKJ>YZ5JC+=xUt2gYS|o zHm(uDO^y+pfZ7a7#8!-ir!JC`gFfk<-k=aYYCJP zD^Mk#lP12KM8hAe5CXOB$4>UE-Y}TCE&S+WFlr!&*hGwm(8C4%Rwms6AB8&H*R_@s z=nY6p(@6zcsBi(~Qro)5Tf+Gc;gbdh10aiwb_8gmTN!(8n7XxQa)UKrsF!w1bMna@ zd^h}DRp8W|7Lg!v^X?y3=}_ZQ0OZ6QNj^oFiC5SjM4#d_nKr>M9T~Ic1>M7Z6Rqtg54W z`Sp-#qrfh+FdtZaYVX>u+Fo=)$R{BTD4Mus-q0n!OxEms1uWIb$lo#S{oKQsVYfA_ zuK48cP`=#i&mpSCnykY{#uu9+TdM87^3F26BYbKuQ#O3`2B;jX&=J6wS0#4*sN`1 zI7SdmWdQkI>3}ILpE4k%u&>g&`E=pk27$3dE{ThQK)pB2r2q5~q3#wiA=F6(K4(K? z17|T`RJQM+Ke!CxE-HZaLPq~vH!?Cdy2UTHGM>_biliZ@a`u;SJFrgUI1OE>5aikb>j9NocmMJmGvL+^C1xOyB#9FZuqq z&0&P&7C7NQs0-Zy)yI(d^|+n?+(T%kI!*dHz%}}VZ#H;QhQ&3kHSZ`h+#b6?na|dM zGZ2_zbpu0a4HJz{oIVTK#=-qI$=U5oD$9&SHd~`V_}KvOK8hX3fR(WI8Nn-QB*E`@v_@N*vo>K1f^Dfp-cGumaMUR! zy{yf!tG(2P^Xi8JWA>fvQT|uJB6k+&2#tvy{JXx{M}w2X*6|;B1f*1gEce};!{;Q%R{< zq;VoNNpNx|s$^4Gk;EDs+j99T)_AjqQBp+SF<}ksR&{PW^wS_^d#y$Ek_L1AF~#r(|8Xia5&Y3*#>ut;5HDoB=KxfE8EI zfrdG5EJ7n%ma$FPhc`E1U!YC%`j-pVztrM0mXR)?Ttd`KjTzCUD%>63=Oa}=7Fu%Q z+|>49Z&*h?T@|t9w`1@Yw9kx>*-}vVA&Q5 zs={9cS97ee86pBWb<|S#1}qj7|N9r&Ra@6d|3se*2VhR9c7XzL+i7qzm}iU0Nl-CL z4wjn=O6eO&Vke4HSC$DgP<0|z=pI||dMj|8<`!&f5L_*UDtPk9H7d}J@(oxhaBi{T zPih*2#4Vr<{qCc4-SBbHyRt^$4B4J?;i{+#PapOavG0=#_}@0^rgUrQhwqs*whIe& zgNdZ}3ciZAT?q$MD;^(h4)xfM$fp4(Ks5BGtRC#*^t%Z{xaK#8lWY&^7X3QBM<`0Q zgWDu0ib;r?Xzu@&YD74%?u3}1Ig0_-YUq(BtgAf!D_$K|2Vb3kfG^2iNLxfLfeNWN z@OMu9Ou+N5_Po5o%C#Jg3uVKntnot{wM4fn2VpLS5vCP8 zY2gn+SvEC;n95yDZbJ+op~aMS1}&Nmw&6=5IatvzX4Ev^AGo?k{sOR15J~iN+YX=a zq*9&KT~!7nP))t92GU<^Bjkjt$Oc9Ae&vCnKhm`Boen;k*?X!rX6HgoF+ ztQZQFRp|pPQBXDuibd`ENzy(2z8(@bd#Lh-FEv1+QYlb+IQ}&P9Y+)LFM77!TeWDs zL?LRHPcOp(s@CkqeFDZXflE{oeYVM5tRQpkFf2F4*W#Q1vc*}%&?Zd?a_{H{%rOX! z7v(}sr7muc1ik7IUP2QoP4H*xLDh0y;w1YEe*C@fVte-dh1Ao{UB!Zl>|7Rl zIIt2h5+F#z6sYZp7_c3Y1qx&pIOj$n((QjS6k9}MGNrA1-4hbpoRkwqcbiUGNac#* z@5~n!{TQ7q&}T$#a+)p3i?Ur|1fILA|4fVYo6yiF+V#=0+JrVlJ8&2h=TYt7okt)D za#YuLNd`Q2 zR34E?kkzk$^PS}11>8UD6r`EN9QjF5>3lN?*y5P<*Fm8Lv46Qza|-(}(W34*j4lGWlzg0gZ zoxwbE01E;rzVz2LDlJ0)piyEQ)LsKiPyN5p#&Z*th8dV6&3iE;AIKSxi|RoaiIroL)4W47xA^I z5ZO{`SN-q4?^iA5xW)}wxWdb zqxajc2hv{I)n;7;CEfgVudOrK_*Gn;y1D^K88&(@fGw%QsJES0Efa57muYHZJg>xT zc2KagTSEbw9`g;Lwi+eAMvJ1XR@~9X3#lk?eiKoiw=Ql{2anW+s9TTD z3Of!Bgx>2VjeU+YRX1DgMi-7JL|p7o6?W+HMmyaD-zoJWy4sDd5^d*X z-E>oVz?RW*af}!A+Pme7k^q}Ks^Ssaj(?`{Lc_s5*8E^}F7{zD_A}yWM_=nEmorQQ zlH+MzjeP>vRrgepJhqHZHx?7VHVljY(61Gl9i<(I-g3`D-E0#pilPw-Uy?wM?hqx; z!C*vXqHGd)Pjj-d6F0GQd6LgwJ5rm)zOIgD0CmqkW5>>s%X1LtqT=*Y?U?mNuSG32FjigJasAQEhr&j0VXJv ze1@n!xFb8G-N52}fH0-DXAlDWa0by2^l#44Cal+KqP8&e7b`A(r;JPhmHwmIM7raC z$z?6b(F;THAx-vVqqT6O(7JHnFlnX8y9k}v8sAll14F@Ylzn}^P{2GK8rZ_&D+d=+ zRjxdJ`A!|`GpLQ<21IPB8OiNQxX$mv3pIjvfkA*xDjb3AWiI>1hc^lW>sA&%8=HOy zzPdz6`$cc<#rl2ZcEU_zsDaz`9~9*jMY)QPOo!e0l~ee42M7;_6q?j+8CbuUj8abE z-N6u0FyvMA!J3tXA}AO;Z-BGF=qg44RRR>74aO5?BQPo&;VYC2X$7byZm3HWBmn>2 zP0t9lC2AE!+V=hvZI`SUc}aAEE)#GY0ix?~hO=8EKA zy*l6OLn-dV5wfkL{py#V9))#L0J^&d*AH64P9U+)AMjuB8haw~DF*A4sKyj9H2#86 zAG|jHzpH)Vblr9n^+RQHYaYBfDB1HGXK@zl>H(W_OvtA|V79J6*(c`KrHL1z$pDW7ipRa}ZrjfL~= zX6>F7V2N${GT2J&SGA1@mKY!kiRKt6yeA6wPHXq$+PML<23jKF4A^lloe!~!MgS+t zPkZvVzcz~nn+K$k(mY+f8*!ZH z#n9-^%F9u{lBAcy&IpxWS6|W7E&8fNeF%1)s!D>>y@h7zdeHHwB@Bd(1SeCu!kPxO zi$aEC6K9JGId$a&?YvLrT@t*#$R`!t@`Hh3YA1~XdG;hAuS7as`oLn}-Wt|e5js76 z@$Yy}(D;i0P-9;fs-QdoRmGrY1s39V{4W>|DkXRP)eFzOm+m~o=aR0MP?N5knP$qq zMv>$db?9B=aOlNPRc&qG;%ImY>bL(2HlZX|+u%)dgS_I1O zSP)6)4;!@Rs^JK(Ww}2hLT45{vu_@S>`d+>iN0E=L4Y^>!NSb zB{nXd$k2K)jh1nI19PmIrFF?)evE_Ud?v3Zy$Y3`Ons%r>l)s~JQBs3om|V8B=w}R z^T`SF{78VQ8h4DA(P*%Rq;Ws31gL{Ya{em9|g=Q*yf8rui=j zf=BLO$erC|Smy@(5cF4$xdTMWGYuSb$v<(OzXH5CctGplSvi6T?j01qq-ZhSmi4TS z9By$f1mojl08|99K=9*3Z9EtmpRj6O^Ch91%ry?Q%zz$-VxL`&BmI-lZkxBPCvdn_ z5L*i=HEcxgT*eoKZ@C;cr4PO07wBVS^Ey%O{@*uVf4J;A5JT03qAfpp?7r*6z<9nt z0p!AU7Yz{w`u_0N$ox$({nH8m#@K<_q zR5l(9jQ(<=Vm*R0|F{T&=5NuDvqp?4`^(p#b5^PZ;0kAqt{Fa@b(rk;(l(7Yf0Jn* z;HM$RcZM<rjWFb^a8F{K;V${zFfZe;@r+ zX?sn}P3-BT8WoRK5=<>l1-5_TB8_&c4a9LBF!y~54fU86PhpQtA#H{@> zXMyAD7e4yE{kmKgesZM?enRPKs*~oT^2O0)c%8UvgvSIS+~F{wdvVu++iZRU4oa9i zd1=hIg8h7ML2~l1?_N3mi2*%Tpxz?>2Tb+2nqRzFI_A>ZXQBGDw%mb<;`^pp_gr44 zw_#AFdT8&Q*~2jum+W@))YNsNEf1}aZkzQGaJ{H86e8!xXu)=W>O!{v z6;2XRrFzA{;OQ<6BMDNX7kP8#P)az?Y8gMimBjedp`d|^Lm5B!XwFui}& z^MCrE^oJ7k!ywU@hp53^izF4cmiXLAVXuDk%#NVic%}ME^n_M*b>$6(94ah% z_F24*tX>NN;3xqUQEDfH`3)E$)-0a^RRt2gXi48K6b0=LYl%CKrag)2?;BwH3F(kI z)CM{U!mK^;MNp_5O#rVNE7uJ6K$y|+8Q=#I&39J^)oj`E+0{O|3fAp+Ee-JTBgUjnG*zD{v{l8YOiVN1tRIKs6Ay-bV2zDpO{^ z8N!o*5JLvi)?n?c0B&BU7gQov06hlyPtMfse^i!%Irw}(grXx6sap45SAQ_;pR5}6 z?XuU!NNLy5@?^|i7>Vt9uoZDTF2TL!)}}4L0RzD@m$h1kpEbon&it+QAqdD%4L!_6j*bhW$K3)`EGl-v=q2dD~_bnWz}xLY(Px-dEx@E zTWK%e#lO1aSz@yaxXefMAs_!v3M$ftnpD;fi}qUsWS-2h<)@Z$_8t-P!(LyzflGq* z41R$xY`{dg;sE>!lWI?&PU4}l5}DZ2=d~i_7WAs;)b}kWEezoY@#-~>1=_k1aS}A8AheG z*#gL12Wq;LR-4w*Zq2ZuWb0D$5-LS-!g6u(fW#u5{xdY7*(+lsfJ=2(ziBY*U+V#A zO}r}+BhiL;&A!@G)(;P5)WRe#5DE_W96+M`&G9XOG|#6r`EyrfMl`tgDRhjgyUq9Z zc)9V(O>bRN7)jk6 zurkZn6u&>t;m8KsCb#Qf-V<*w)Ch)+ zIHYOa2Qk_dE&j)sSHLD&kUhj{%z|$L*7EZS*{$!)+8pnNHq2AtfQ4pG0a_J67TSO! zcQQqZ_iT2KL>D911cvkM<~P3F?46@|ndKXD8Pt)tX(Xe|tt$CVYOe_tKVS9ymGI*h z8af7M&yZvLHajN=MxP%djD9Pj4^vmz%X+33{Ff+;-s%xMpmr#fuj7rHTSBKv4cH75 zF7^Ry*%;J2qhBs)!QhLt93u{A2q+C#{#$Pw=}+zlsx#KcB|TU3@)k`5k0oGsJ;CQJ z+}nT^_Il|72>NvU-e-9gL%0{>I1WwS5roK_n<6S3uus`7U>lYpmin-^v(04KXXjtZ z>nHK#G2J%da|~RQURS0t^^3Qr4^hbv`f@8?HeqsFp6}&lQ^8}5p_>3Lm0V4E2nev zN^G#ngXGOn2Jso2sQfzw;Ob^70g2HNi1R*(OR1(0cqDkFLGX66wQSMbThUOpA!6zY z{?4t8a~rTHdGK{3C{{Ox5aA?_hlVg>6$@03dk|-d`gGaQEE-=5Fn$NlAlebFN$}fl z9C_p>NBt-r6pwJ|s#?$Kf%>^@)QE}u;ECz*wcQ};0H6vqdVcRn{0pZlIU#bW+A6>< z^9rU3BAFnl3kp5{h`oo)S1sQYWA^axjD|jj<=jdh0b2qs!y zvegIDNU(0q0H-gUP!AZCp#I@drYK0u_WXRIQYh^aMTMBg6YGyLu2Dra2R!*jL=qsD))aQ|blpEEhWp#ufb_`p#GL^XUf(}Ea`CYJ_kTPf5<0AH%J;!oB>6Mzaf zKf>afR)iZ2=KM!AGm=xWZr8vr6rn_v18F>Bo*&GiDSYeXL3R;}8;e^h0iGwwz^1FJ$FNHd! zH^lq3yz-PKP|QMr1HB4oPsl_G-hl1*KumZqWrqCT+WSpxlS3PMY|u(`>CE#l9q9?$ zgXXA2YQM?e#-8!s6Oy5}<8B#(XC)EAb{Eq(V5Khb__!UKZ;Heo@fDLLQuNr*vJ2$p z4&)*6WDm4BIZUq)vU_kdE4r{R#aZZO^+e?kc$$j(omVN$xckx2;gh^ZqABD3(F2Z@ zC!P!g8!*F=&d~9po{LdReOFYJu6{_e*W)z znCV!TH^8^3qFTfkbgh9~jy)l*`X4#?6u+?G8JnCalhcx4?tOI3=1ez(T5~CJyga;jNO?f8963)+GU0F0wKO!;kE;ygR&r_10P4=shd@^Y=>JUw z2jNAh_)f=_ye_o}w%-FA_UlO2um;$GIUrz$*+~$2)ARo9L%1P4@9s0ryQrFQ%MfAF zIP^_d$~t|<%kjYhrQ<8v)Pz)mE#!1Fi9&!WRk>(YG7&HxDlMC|Ojl^UnY?l?t2*mT z$?Mk^0WbH!)*jF3+))L>@eCNx+(kMVvb)fnXXMMCk!S2}T(H5-??~U88d{wnQ3EfL zy9+dXBCcwgpEp?`e336SXt|j-Gx6QWP9I4hb5J1M%;dC2IsE*QOvUtWkje0Yn8^@F zhT(6Zxc7#n?`85~)3}L4z=&vCZC`;;!Y5Q|OGQI+v!A>xDB6{o>AMQbQ~Sk zl7U1sfVC9fncc?zkF@!_|8oR=V4BEN-}UYh*bQDaSm~04p+$(FPcCXc^+e1QG*{gt z+qdN`$XYPEbICr|M;2}cCq>{7>fKmK&(0yQ*zcK>x+^t}k564CU-Rbepwq}SUaGKp zr|$Z9X;7$EOW80JQVlyfoOt_;h`LW|B2;}rG!+ECC&2_JCE2krz%rxCVUH@DD-rJG zcuORsgDy)o)TjF`ei{*(C{Wh#jpj4+IV}nu*KC+uF~l}p*gY`+)~NTnouZ}7|6%XF zqnc{Eg>e)G#exk`x)lLw(gcLq5D}#Jt~6<(cR~~%KtMo6Kx*h!I-x^A1fF*-B5k3Gvpm2R@D*yMMi2|;1fcFSM55Taepy&$nu2n?FxD=XaRNA36 zPV}Ne8o(qXO6(vU6ru>!T%QBK0_>tVvk=twW#wOPe^{)__z$xOgvXti6(4@Q4K=-D!4*=h_!r6e z+bsu>z2+)pj=$i2);=CzaQS`j@mP&o+qAlS4nI3Mp{LUXHhQY_QJGn@l&M3b7HeX(XTx6E;amDH^jfH$CKbsxz)#^^A2$AdFX6; zW`O%MYoQ{m%CS9#XP1jlEw6+0K))tR)Z)bTig$9CzlD2BB%l0O?fq|*`w=Pk=K)GL z)_0kpA&%Nw;u;_fcHrdt0ZYM#I_M9*e{z&K#st(6=+9KHL_7}!-d!MQwBeXm09DuY zqrOA4wg2E){eR^dC!nm0kdT25WghB0&)`U&ZMzgW*Ozy1N{_TUE9AJ*H(nX?K%{H1BU)a(1`NxR0~e>C5&S(lf6cys>z z9RFE}M2fxLc)I`AF;y4VPw@4>1GC>2^6NZL!`8^)3IJ(26(}8$wDqUn@b6iQ{}->1 zoLT0x;$(AF+P-EY{^XCj>OMzG%Id>jjlJXIzG|f-`iRXafbSnjEAbN(H7K;58eQJcrQ^JpQ#)Er8bVw-dDe|@cplPL z=4zdLIz)_R2@4Ii3Ozxt%NY-@=C{8`@IC%cy!}1n@wn zj^4DMP>NR;d6zrbimu@FYvqD5;}XD<{l5BkMvm_c^K-KrMUD?GN+9M^&GX0Hv;C9b z0Rq&DM<>S>e$zYu#!ly-#SZ_A_eW3Ka|X0aoogByfR^zg>YuUQd%3%&_n@`vXya-mYW+j9~ioo z?J}dg#uQ9CY@4`orE^=B|@qDV8XLKCII3KhH+dsVDjIKitr^Y7>91A920Cr#1c zJaMB`s6z;Ct#|wRx6cz5JQ)r0mOBOkr>QXE+$^dUMgj55+*s7smNR9OqAA=GF4#^# zs5Y4OBPlym^j_#2O+VbN3`%b~1rN}IFQn}_<*C1#2;y?eBOX4glpk1*)h9k0CoWO& zqW9I(f3Tg^7yzEgNrk>pei!n$)Y|SW&*pcM&qR$m(+% zlZP|i`M*IV{7>58sS6@`2@D?E!Dz07=K6fI@cpZL`y3s6cK~So;2r-Nmc9uOq}c?R zx5NAg^b1~jz_ly^`|7It` zkZ9*-8fxn{@FOLnlWGZIed8=iUeJbdd>k$0j_l2y4~S)V>eKYR%0zEKb{^G3-qErE z;My!N4}LTmbtmIOo5aZSc;LdzAG3hEM|qzDh%G&#Q3jd%?!eZ53qa|?aWw_}&9;!C zr-~m~t`#6(2vhC@UR8FaE~>i-CvDr4eW|;RudBpz{5yK;ppAL2gz?uV*k!pv@jr?Of*+JkxqTB(fVI4q#A{ zSFAO303(w_%3YMpXXKOT53rX6vc?}!ZLQv4i@*a6U2AT)Ts{!VA+>4IFl5TLl|%$g zEC)S@Id%XO;Rwydrk}p?cUU`$^?$b+@w&9bWxkF8ceGtOs{B8tk z3Aod%zTDw&{ zaPd*PBa@|gwdj`5gqg((;E7H~h(PPgzvROg}B74ax8C$|l{sg$CddakbNaQ+$ z)Nl>Z2ps|m4xU#gSr>Xq{ zm>yFK5h`gG7Hty|L%u|wA-zhntlD_pN})l_sde>%Pz*P3*4zYlR;GMf+@6V(w;Qo* zPdn>@Q769zVkuykD8wv%!0;VKq6S3E=9egd-`Nh)8Q}K&u(ZHfJ7C1s0w979q7+4e zf}xmdW57F?G66+BIxM9$wB~ONPwyEuqSGpPFCCRVJMwCuD{e5i+MeVsPIdvd^LYi) zl~eJWfV+M-HwA(Pjt6JTe%?hFWn2KT-JVazs_1t(yE^o@-Jy?a|4wqr1C0Wy+i-y0 z0hD`aNqpF792%vUsj9wCP4NZ#U*N(z0H0M;NW>p1Wnd;8J3EJ8+Yhy*#}fbrEh5S( zger@i09smIqfn5B_oqTtICY-WfDICoZ1i$g40HkCx^cj}*hwsH8y$|qoHmJz^v!_n zx$OhuM`Um{7jZT{y#jz(Heb>#dcGUO;#YNEf@(`kDgFwe#~bFrZ4Trk<_K#PYEmxp zZiw;dM_@5D_mD{$l&%PhHvpUVDj?Ppvn{~C6jp+;{fT542MG(LPiKY$<&@4KiWe|( z&@);^#MkA`mHr(QBReO1^pLq;+9XeU9Pn|}W|ZD<^ZJk(@~S&Y(Xj#EgUszjH2#T1 zI`eGo%Zv2TE{aFEox1o# z)N)+~>O!%IbqpA^V;Ob=BqmWGpR4KLMT{g&y&F3b5kujtqsC^}V9%ILiB8@UjTucCIiO4IHN`oT(wVk7i~nkBUXini~TV zG8DF|@*{^-fS6Sej%y5n=0*VfuBU+VB-aYDwT{~B1LAh*#HT{*x%XHnnaDG0YWgKw z>p5UKY`_R+8`ck;4uE06B>5sTVQ+@c0Ej0stcXtbHgNPfX)kPo^aonqovR0xU zY5Az<&vlylq7OQCiJ;*2d@_m;I!D=AMF0j0IwzPabUB?6?O)M{xvOIz^~wJXwjo}K z3t9rAafo*wM)Odp`!fJX1}m`RfGvTnTLuL~C37;MtuWFVVC1?n`yilov%`@qr&pNe zj~@E=WlculK!9ti!`*!H&?2>z7t9*I*h=0bt$fx(;LYGr`8R+fN_B8PVtsUniDz{Z zvbrfj6(0DPU{E+|G(4R?whd44-pyw&Ky9BlCd>ojg3>=`$cx(?8ifAz`353nqeLjFlib>x4-!E289M74#>hH1=w{AAtyWb2u+P`j%0ryA!t z#q64+&qlWwSd3ZE_mX)M$7NdN?8eOuSWV%t?*hx|P;GMR`|UqsrW8ZRFHiSJx0J;# ziU4F<+HWrFXu$3x?{S?DLE`u6*>p-z#O1pRhtktP^z1#+XK`we-bFl2lFtFb?Yx;l zo74}^Qo189@7!!9E=E2#EDwO(cuDAoTI&b=4j>P-Z-k>_*B3+ zljnKr@MhbaRHd_?k0jL*WgFz10H1Q^a7meg%oP%!uX(<#0E?ANX*4OmagU)8MYUL# z`?qHweX@%Lqds66%&Z-fK6V_opBe z1isy;muk$s2C}h4p|L`YY9S^MMW~4n<(}OHZ8FoOBt;MSYEVJV$Gw10hQx^!G4^IJ zmk4qs(yBDHmB(-A4!K*Lh}D~VrBLcnpZP|_0wCt-K4pt;MpFOyY_b%ULFw-yRd)gX z4CasWx;^E)S~Uo+UEr$#3qIRWhnfQzyGIQ8o}PWA2iTB5>+`rmu-LR|uV%ysHDI3A zPtla6>ffLxm4ZT<&&F7IeTQPwC?c>iS_&kClp{-wd~3sIK@&jHSj>hqv?m?*CFc-N_^%gDT5HQV zfybCwKaOQFn|}e$59%G!V`@q<&h2(LzQ;SokUh@lV9tyt+Xp>X3Q!2`})+~8%@LcBRe5=iQHTivbz(X?6 z=V7L>({H~z(0x#jyEpsQYCitNNy_x!B{l|apED*b0!Se>gl6(r6xRa&red90x9j6a zzp5*~ZoT;w;wT@*7(M@FqKfB!C3&Yh)yyUO$aReARf!fUO@BrSIdc#&QptkVwL3@U zrhJ;Zg<80UpVc?F1IN_&-+a~o^p~gXlR+?DfTmKH-wWN;NFM%X5Vw)+8HbGzPU5D! znMTd5D!1R8@>g*r8kwIKY&eh6C`@^la-2r|nJ}T>=CPhr?ME*_FeC_IyPt@WyK8$j zdWra>15g-f)ZxK=9QTeY`o8)V*N*xoF%LNV2W}D500M7iH+nuF5FY%KB=FbdWiK99 z&Ee5nkNSBYCj%$mUx-PfeigtTphS7qE}S;d((3cWlLMfe75|IXQdtJdyG<#L6pixG z^8WM7fOV^0%C&DQbxO2rS{imL(lozfLH;vT|3ctE{M#iU4>OP$SIxZXe=jz0Zrn%q z=cjjSHLJUkF=TzRtYW!nYN5z$zY{+eL(EQnw;5xT(3AU(Z*%Rx}R@p|9)cfK*eJp7azo}*Wd z`*#!~M~|!u|9LG~!b8OnWt8!hN&x$3 zpFcEOg>jJ%gE9gi^P7G7X=l5R1(<^ILLxfiudAOnxuxR(*Mh)QgGxvC>HzMbei;Z) zD@O!$IXw%*WK!DiE8GL7Y(UT1N`dnKtPQc}k06)*Y8pVUAZ=sZb|j!w?U@ALN<$!1tOH2*=hYhlK>b>({fkfG7|jEU#X-33Umx;kF|Fd`p;^HAWBfVb<*rKU z_>*BUUI&J_RM&dgc$q~G)VvkYG@(J5g{%Fk(iVrqUp|VJ%fG@7mm~6U;MYK8oE+8w zv@--HqTdLZdG&o<<%#%R;Gf>$)h12`#^eqJa9r5qNK|8ffxu;eHYEY2V;$f%3$%uw zSp`Xo3uKd4W3ZZtuL#^E$Ees;2^8gW#N7!v*L;74Ys-O}jeE5L$NB)GWTTFQLJ&D( z|Lbw!6E;JDS|mr=ECa_=UmEe&FfkvfsB+}`*SN$=tz*}O9iVhIfOsH}J<*PFBik2T zJ5b+Di&I{-vQ|@F)%g`YG8gd7KIA<_AR+W^lII`T84+v7Ag7j@pJ6Sv|E&9q4GMeIi$3gMyYj(K!zc$Y z$HJey&M!Vl#9CxF5v@ZjeLGY3!jl>m6W6SPtN259#qZzStp9~F`hPDeRyQ;18L#g@u8yc}&6gf&vcftU+ywDyt(7pRSRs5UXV&}k8f)zBe zTzyLODc+$l>|jHaRF$V`gW=BTH1g&+aDRC)FuqC=-=oZMAWK&bGj5~Fg-HL7Rf=gH zVqApSG0Z^TOAjF)23Gw$ZDj`2lZwqnw5b~!jNen+wR?sb9qfZ2*h%ZbRPpHWo}NE?U|I_ z4dfbBVrI{Kd|$k7Dt>>560^FO7`4$S17Fi(i`dkAc$_0ocB8xV_HwnD$~791y1@98 zR&3>0XS^4NNcjXr(#?e$G%HD@9`v`*79AF z%F^bDV@h~UsAbd^@r2(pb|I0B5jq+-Z&cTo=kMehcNMK%arOOj)oSgD?l1x|T{qhAS}#|td{Dh;RWftV%4W6XeJyY2?c4B` z%Kn(%-7Ij8gWeH=I-BlDPG$2s*<0qY(AV?6jl7PgCv{bWIv%)~ zwp(NJ=P9{Z+I;cMc$mfXNQfL{Hb}KSHAe*Alp~_{tRd6wwC#QH?f&LzlC7(sMsNC`Qh`r2DCwecYEWY#@biTtF<{l=S5~^A`2MAOAu|5b>5~C*H@z*Wb^HC#=E#TyIR? z$NjKt)fz0pD9%?$5OW-@`;fRcj1hkf3UWX%c)-8ey@Lr@6euvK)HO&aLFtcjyrLMY zdB;H?;}n)qHJx~IH|2YMuBY&cV?v0xN4KQlr${sxI_>)#NKcu++hdR5!$jVp)~UBy z7(T1XOFbezJz`j;a*T;u)*<({-^C;6zfni(Z0v^bu1XLjO}H%1kcHn$?}Bux*Gpf# zF`Q0(Th~i!9*UGX>K5!B=OEw`k@eLw_9FTM?%4W$To#LBC44?<|K(@@2BnS5BM;ub zNgO+FLVc1(%*w>%`kA9*#5WC3nUC3GkGu_|YtK1$+V)a!4DX4C!1IQ=52?gL&b?ui z9?E2|`@{I8t<);)-x|9& zVUxn3*Lz2)$_sCr^zaH6nbsUz_Y6KeBLA35tk=XOlK!-9a%00Sj>{v-$q6A0Z_XSg zIO(1Q{Hzp^&l_mY@1K-s!3eEtg=q!nLvKp#_8fPU@)fJz&7TsBC_7c_-T;me-j9Q| zx;OAU^fZ7qTj1M6AM=#Y7M+?9E{drFO;%%1+b$>Vs}4MW>uHh&thnR{00@p2y*)-9 zFCtj*G|s+6n$VvpC$`T=M`-nVGpU@;raA%x+PBY2G{u4Yut{? z_E%}&YTB46MVwY_(f@G)R~B-khwQnoW~ z8X^O!9FiNUxHv9PKkz@IBqP}H@Sy|)7ZvNV-36x$4XRIKawDnEUYidZ3!c?Rh37-F zrFV@%&ej8xNht^5u6*#;W4ru*Oa0@Ea69rd6J#WETRzVwaX#tntMP`O&1^Px>f7f; z)oLD`;cOh_JfnCf{o$Yq#|P$T{@IN(oT4f~XCyes>1B0>daVEX?HA>xlS~hA!rl9V zt1!<9>D|_)PQ2@cDU-*N_xi(WPz%GPX-s97_j*7^tAL-Av1!!d&3zox_d3VN$yCc5 z4!mOXfG9RN37rxu<#Wz#xBYf;&1)0#kE`Z}EoHBEFGOnM5`yw133 zer(+@Py`%hLhhk88&3; z&K>M=U))6)`L}v6?C+5B&@s2wF$eGCP+FP6f8^PH9Un)#XG~CDn3oj~pwv6#RY~!y zjftxq3EVV6|4w?Z--eKu~o`p}CQ}nMqeSgcsC-!$4 z03SPk-RG?BqVfKSV%}zSX4xmSMVN} zpdc4e4;ZkSt0~aWzwMRtU;c5^{cQw40rO}2G!0J&bAhJ-%;*GuXHq*X5~LG&^wQb< z@PUAe;!_1>6<#HED?4>pFrU1cIoQR@#gp$Doq#OZ)ZWYrY$@>fg&OvnU@M^9oKx&i zSU)j$HU)ARz684*Ht4L+DfTOEq2b?s)X%zqe$=1TsMs&)|7X;w;ioPo{|A=>aQBZZ z7+yB{!tsLnLPlKCCYKh+n{ReEi>YJ#Wl>Wz39FATJgXPPO$fMywZzw2=$)~QE#T|U z)hs?7^Y@Y-ajj@!{gvsWu#d$f_czXNd^X#2mZ~eGZ9@|sdBtA{__8nVbXnHPdyh6# zcX>I>bUVE!ferFYa5~-zO?bNF!=pCKH&6RQ8F&jyyR72s7tTHIug$%DPRb{NOP=9q zr~cMi?={)VJ|z@o&TZl|HsoX@2i8;3qrPbnFS#;A`Tn-07}@FEL(TE4$M_yy-5u+QvYnR5#$JDHgS8`1Li?={H{tZWAdTXQ>L-Es;7+u-MVKU|Ye zRt|@|SL|12KLKrhVSQ0SK|?wrvBO`^pVxNuLm;K$uX^JD)Q9+Aef(-qT;lKB|5bKR^q=(-Z8`k<+@J|ThU$d)!ax>Ty<}{#>5>KH>*qW*DXKPoj_Q)IIr4E~X_CAw*;*gCnajEWZA`-)E zugb-aLN zx040 zxE$|ht&}Ae47lG)$RWMoa(8VOn-a~SP`CnIFRt1zkWdoCQb7qz5(lc%_FWR|wY?I{ zUnR48piQ3e9Va=-f$RIOdmTNwjP;XM$Sb)B$X-kB8Hw-VJJa2D0(IyXQvvqQ&RPqY zS6R~_e)t~7$*53Ef6g(eI7t$hs;rrqG0@%TOdCya?3KNMA~1I&qjLN*`n(s}J;%tI z`i`KEvw0nB5%;?gZM-C5+vXhpM15`Xf;=fpCV@J$h2BQDyp^+t-G;|Iara?0Nrg!w zD}xE*67)IPy3OJ$Y$LYVO|8v7dI{_!*wXVL6FuN_d+k^VjOemm4+U%p5;TSvGs={rAO zx)jQ8-L<8DNB80uXOhBV^ir;~!kV(QGrt4`8!IB^bc3TfQcj6Ony5kH!$g((>bRN@ zX(p=AiPN_9I~xjMrmxzg`=g?oczM_4FQgmQp}o|tDz5vtt*oB%P;s2x^UC^o3)97% z;y~7`L*w(^#7|W_z3L82mA(plovv>M zFg`A-TEaiclhB%TT4|w`xW9o74mKLX*?{X9ckbBi#)sY8`lOd{v_r5eW#QVGH!&@_ z!t=-1p}O3>z?(MSVItO^^~QNa3`yU^j4oBI`l39+J~AtJBoXyuq}$$aG~I~yHi&#E zOHDo{Z^L*4`t_id+&VHmjj)`Z?`U6kp$ zm5?IIlKeXfGGeHPzl;{Ip`Y=hmg|!HGb{{(I5Et!u-Yg$2Pac9D~f zMGQ3)h1Et~IO3#55B;dkT*r0oJ!zFqr2vlp(KQkg&g7HdC{w(4$-8np7HjE7K2GG| zHU0pt3I#Q=XOkZ82V<$F*0{c1T=8y-C_$ZGO7osNTYh%6aMLVY&{zS_Oz2ORaZt|DJZRfjGzfNIvRN*EX;bA|t7*rV5A)vM zB~&OC!qhvSrgiGp*$%>3?f6eO49$$*8(JMkBg+Dq z+vE^ZU3eqMLTdeVyn1Af+dAk&WdQ-MmN&RM5c5aMtNVkM8VQkUTe0f9TjMrd>@1Y# z36w^?dJd%XAb+!>KVnzrE2Y#b5<;J?YIF!y-JsMP6u}vf@Z3W@T$|M^SFR{KA zQP*R?1rdgO6wUPvUOv04)AF@m>`N6CiQ;r9PTTyjlw%UH4Fgk9~q!x=Zf>H}d({?}i0VZ=W6B zxRmDQ;W+SULiKB3cl-0gD3N}!_zC-j<+9BF8zIC*E#otgPdBWtuax4JY1uone>y!L;~Wlf!DYn zU41yblEXKkDt)56Y}ARUNc5>0!w%|sz4rQ$_$nX1yf5PI6(@a#l&vC+P*I}={st9tMZbiC0Q*!UdMrf^bNI}ehr z6DbUEHf=1FN5VkKa@`uFaWo-JH=Mi}GCRdT!$-H?>+fU3f5|Q(W86Gl7yLpF@EWzOIjC2 zo8^)WBr8@~A!=v-@aqHbu2*re>9`FsWI3*+^pU~?&A;2t+set@z0PPRLS`BPIQIj-wCI+?HAUTxk%7Vx7KW>miNbV=u_5rJ*@JhEuz@aulJu`*K(Z7 z7xZbXva}l}js&emL86#W3&cWKHb+P{LE@bV@5Qveh;EPy)Pz#3w?C6ekMVJ`6b-vn z4PtFQH4yU34OHihN(x{_dRy1ICt7JiJ$k0xzB_-5n;NVyG_=xoHi#K070;Q;of7V_ z5EnFb)Cq3c%L*@$!GC`psx?*< zGnHu+Oo)e zbfJ>nFPl>rZE0ETGKwWbbT(3~r}Mh=w*oH;h%1Tkgk|hm4tC0v5?C!b_?bh$w4k@b zXFpgc&LxIbjeeoQRgD6{PR}O5j88F5D(`UNwfEgU>IPUh%=nP++k%UtOc0^ZI(uiTXP9 zv*~=>xLB{FsUiCfy`o zPM6e5r(JGMo)1{)6WBJ^W>rXja&&RMvxhXc=^hw0^KD|DTlSS~7Rm*y;lG(HouyM0 z{Q_sdsvV9S6(=qcqkLV#M&~D|i_@zO$c^tNlDdioFl0MR%ny17N)9yqTQk>iPtE~D z;383d_UZL24H8w9iJ{Wi)9zzlJt&jFF|PqVHW6>OkK7i@8*{bi#Zw(h##dcs^$M#+ zQF~tUabn;TB~R~f=E4o5v?l1xE{7Q9e#zF`dyp~wTI@-9iEa=ImAhnk^JDTc^BV zv-Vh~rV=_#2i;4p=@`Em;UPEQJ{vXL-n=%s)||&=KV#46?uEJF-Y&(6ko;)$iLd9r zJ?18{AkK4dy{nYV0wm}R#4nqGTBE97dRY9Z4iU#d^jxY#(0lA`9tojrQakGC*|W{? zJ$9{A4ol$)x4e8*A@^5twA6*ekc0p_AxY~!lEt|nOGs!vrIBEd1gRE=63~R5HG6HT zk%DGZ|20~B)>>zk8YhRQ>F|fH)2F4}kKOr@^Qhe1zDo){xeobJ(?d*O67XD?!MxYr z3Vh6E=oT&|E=4a1A9-oX>K5q?bAIZm^h!7B1FnPC{6%JmPZ-CN_>Nxh3YI1mg2s$g z<*~P?3rW{RATI`3&~I??*gCT_Ch12#Z*U5C(~2l4NLu?EUU{+H#f!|6WiRD<*HS-v zu#q7CloU$9%o9FdUj->|bpa#|vUPQJluJCk8{Y=f(5m}>5Y+efm4ir3B<3x?db_rY z&6%#@`5LR_`}%@;ly8bwPU+j!*CBnmS~ku|J-(cDy4KuMq@HNOZJ7!!a=L!r0alqj zh_SuX3iDksnVYt=*St7)+xC;S!PLgY%(_}Xg=+}QQOJgwQmd)*Zr%Lesl94EwUbDw zz`ldnmV1|#OhAt7=jFQ^caYeWq~r}|!YdPJ-Y!tv(1vqV9y}m79LeHyN`ZIfM$}s_ zCdIaQ&cnFNxljVQ;)K0CP+60qRw(8p#Ua!9jI+q=do{ZI&kX9y^#C@6b<00XIgh+` z63%wp*IU|>23db^?9!!qZ@)#qv-U;EM6u~g_&ulBWpoUsm5(v31>T%CN|+^i=A4ZO zXPzVaY_+03Xff3MI(ho5lW4B{wQ3TmOPw3{ev;r}iRDyvwvlKUXv< zasaKe-XKuWGBVcy0ozO6*JVVE08>Q!`Z1otX2 z=}U8?C9+cFQhpra)3+{;Y~B65Rg@N@@JHWwmv7xSY$YTjH9q;^d_=&d>0M(XD)vPI z%3qfghDJt3*-&T1+%8B$&vjgqKu3j_cyM)R&KPaad6>e9L@lhuGCP%eb_hvXT!^fOu z>MGc@1VW$IzI6S5i!awRU&6puSmWsM8#uc)Mzij0f-Ib^S-h)g<%-){Cq&pdE~k6G ze^~EsBC9e_@oX=z{5JKTaW_wx7iql;iR4&tY7~AhqVk8%*7xf14+nc8XWjXi&39Y! zqLB%Y-omoEd=qXJzqb+Ag{IDA<>Kl!o@8n5OvJhH?(K3x>{ACep7fFCpFqcUv?hG& zNZ`86eLtEQ{FfVPY#V29zQ!fu3eFsa9eg=Be!xp9^(9jw5)hvdZxNB84?bDg{BqQ( zk=If0Qm*MR^e9MO&rk}|5ypqpHI^5_4|2W8q=+)W z${Gcy+}v&?`-6oHmCimP!tjAQ>aT^MWPZZ*!2o`--F|*8iKdD zhq1>fQ}{vip0R~-0d$gBO^W9w_jtfQM%1tO%|W{g^t^Znc2 zWoXwz8OGY&B(}t{Vm19lZCevu9};Qn>nYw7(B>H+RCpN(K(EKh8Y+M>BIm9~oXHH& z&5P(HeYwU&-z;Yo2Q9PU*XDq+cdo0aG2g!r`Gd`I`{HnS(G^)KC0-Z#OGmDdJA!v< zSVuo_!#u5T)I@Z4$KHik=DtMWxP>i_#@vyd_x=HNBsp=1G zbOLFdr%k!%s2vAc$_S78=$qZQwVEQCnTx7vy;?@n6sl-n^4GNa$mDVfwx(qbe;zfQUbq~! z>!Xz;!*xb_@s1Rtg7Nft#|9j`g~c(hS{tLK)91hRU3pA?=PgHP($xVvN4hN|}#T9L9jdbq~N zu8mIR!p~N1^SjYGAf3WN*hNUvi+UkFBuLHd4ocbiinx@M80=HivtqAo_%^Fy5NnxU zA4}GyuNY*6`@ZH* z&OX;D&HLiB2UmS>N5k_#S5>R3RS2_~n8N z6T3k+zd9Ot)vWU}@4x4tI)S?4kIl$hVgbg~t6n=m*%1N)P`;NPYFVRD4R_>{-oTOZUe7)!G*wwO?m!~=Gsr0-~ zp)U%GU|b;dGgU-X)R(V$pW;uygZB$&u-2r&lJ9`NeO_oQJ-F7cmP0T~?a@uB{DJk1di@xL7>ta!qJ?cS)&hFFFeyo2zK2@)?vT_59G{Ea7Z$P5gch*sMyBJOX> z;|c?NDxp$7Lu5*?J^S){;fw0K?W%E0kBeJ^FuIkNDJ6mx!b{t?bjihJTI{_<3(5Y+ z$F8lE+7Q=eno$|};KkZBv8jvQ-U;5H%T~iJkh+pplz9ob^aR$ddll>;V5tq$gU&9m zj%FpPbcPOvCU(a9KBs=E^5}Nb6Y`qtg(MBoGpNd=wTW-B1M~bvj=V(WF z$izZqh-z-Phz}R}+L+p6IyhqNV?a!mpA?@$hDQNlO$sVPER$XN5X#)dHC2-7eZ8Nn%#GlCczIV3!F8@kEspYbo zFZ{Q1Q@!jaFe5;${ ziKtf`?lO(+t};#a%cSGP@*Qa`S!A0PmjA@wZHgJuQ6-F}5n^eHk=1U|zM*~EsG}e> zymj~{$&-(bUtP8g|GLJQw@a1dh+*G7dU6@-J6}K4~ z-R=~4@Xl_2i<*j>CEzQzD|V+!HVeSJABW_|ITG_^da7>JnC;Kb%gI{uVhr~9}P{PpTZEU{P-_(FZ;ob&mQ&s4skq?#8p%H$nIDuk{m^8olvfZx%N~Y zXoKd#J#`)VSf+iYitfzGWHt@Sw~BQsi1k8zD>g*d8gy%)BR-Q4O2;@Qk zXd?xkvaU4STVI}=u&eiL&s_q!SEdBk*fouL?5m^%?Fd@fHb?I1!mD`<#ce9tGCk5f zn-z;IFYtbCLprQ};l7fhg)j`;R<2(+2Yu{#ljJ>WjZR6GDV!+MZree*Oo@I=M31e> zh?^PlzcNS_%l5XExtPT4D@0IkD%3u>MToCMh1U<90<-$QfpAv4FV6MBv?d~+a)fa> z$goQ@C&uABR++9J#Ld`@hRwt$(4Ss2npf6NS~A?2T&`=b8OT$XT-TKi+16z4I?aop z4|@6C={#X(28S!D!)KO>2@Crucv$M3w0WM3Ws2_zwFzxyvNyV4tOND>cr(=2(Gdlw z!>@M>lhv?@qY-gMk(O?wx%n^5gX?_Cn`B`113r z)J&6z=?VAm#%1n>om7h~sjrsQOVtz4)mq7P4c?I9sbbtu>fMC@JYjmz_0~tf+JZ_u1t+Z(xnR6JryF;Z^>jVb-R;?ywhk1O|N$ zR2j`)B18Q-bDvx#vMIN%(;Afz+hHe^W;be`Vo-Lsl`^wjPE|IKcPf&&&pRz8s9LFDIA@TUI!c}*O3aM&l z2`06bv^4$3Pw^r8d~A5_HE~Wg2c5Tr2zf~N@bJRY(c_VHkB%41Fs{N| zb}@Lk_L_IZ%G!>zK>w0}x`Phl;El|I4>{rHWW-xP8y9cv^4boCe;Fg^;;p^w9llK2 z=v%_QJ|Qx{bZghulSPt1mK`_BT_W%tFC4VP-3Y`Mjd?gieloZs)& zD0=*M@B_?dd8?g4UV?vVaV37wQpUc+>%QBvV^VJq`>L}uVgFrV%-Ysy;mii1w9@_p ztMW2&2Incg=s8ZZd$X?{7{6D!uAYOLs!%JsZ*9wMExD_J3&Ak)Ltwu%4cUE1?jE%K>t4RCj zbc~66aBVBS>eTU%Al!u)XILA%b;qS9ab_wNmoCvsY+i|Q?6GQ&Ek3I=<0sK{-@ z2d7*R1%0M2&p=B&Px4@eD2O7;Ikvtq8P7`qf@fiw>~xPnbdREjcgaLxh8hjNE(=X& zz?^fy+7Az6M9xTm9d~*VVX1_g%5L3!Loq;ZjHb0(Au^8)FIRad`L={4MO=|Cm)n(Y zt}!ks)E~5~R|Fk+RwoJ^nRANu9fns&2n^4ad~H3zd-;S)?|<=aQ9(Ex&DrTkG?k$r zE6I5?8yEB~#ZOl-t@>If7pi;Jr4yz+ArNJdx6y%23dTD$b5eagqxg7X*0}#mE$G=j z;ZwI;JT-g9*(VFx2tHHg(5%)qHORrSO3Z>6d*N`aK;N8E?_OR5Gl!qFixS9G2@`uf zJpTt;hQoHb@UywHv)_o9G`^rC{&r9>>D0H6_fMZT5zddF8R*Z18EXiNFr*s&sgz;%& zpC)oxN&e|^K4r#mT5{gNutCNc5G3cuc=aCOG#FUDw=yavYOsn_7F@lZINAKtuWk}v z=6($`Y}uEx>1OeuO;2+;U`X(ht5g<8$9!zO-w- zj@17}dl-e8@O(IY(GYu5NkFvS?sqI9DamHI(s{rK5-f;%GP6eE4x2Xy)itIFF=rHnFjy>8|lo!`n=dHaEXcmmY+FLbO6(7Ee`e{`XY#Ehkl8D@+VzL|_>LzUfjmabzb_1D2EIUy~mK7#Z$hlnV%TJt3Fk8;Mr5s`p zb})~FR{}b}5}y_3bhK1pCU{%wN#1@eK+*0&K&%=#OTq9i ztT9lK!=-rfs%F9cKnXSL^(By232@vVD@!qCGJnvr&p9ONmaBZ013-gkEoCm~OCetb zG>y2}bs|z&-wI5XMx@gzCEO*<5eA;yGILVw@{`Dukg%q<2gnZj+{Zd<%`)wq|6uh} zVD(Adx~e!DJ!`Hwd%07N6hX8d6uN9oy~5Y3cbmJpJ?hZrDlN2=c(@JPh~S)vIMEp* zj=A-vp~e1qwSLMiTd`V%vr|9MeW`t7De5S{Q?CFfwXczIze;tFo1i+bl_v3+C-x|B zHOsXQ^T1xQx0!du&l;ZAP6e)9n&`HzoBAj`ckeoxefmN8F?E4C#{B z#MrE43FAIMHmJwd999QubKVvLow$MaUI7;$&zqAUKMnP|6mG9AVx*$5E7})+sY{Kc zsKp=pV>7bUuFR#45Xu9*vxmR?!nJBdFhSuLO}}3c`59gr1vmzF+d+7Pu^u%39I4Jc z<@Tx(r?fnNynr3kh#bZcS!|^n`7{UcnF`d`;L3t3p~1)(5Ai{qTwybnSMYmm)3t7B zz44JednL9_v_J?ZqyN}RAZA5{Nmy|$jSih7zGda6OII$+YbvQy zPAOYQx$`{#+#)2%4fIyjlbT>VFl$ytCG4CiudgX*C4E*+qWX}SWRrG_wfB%%^Jawn zrR6>ut{JzzD_4YDS2_WhIheq*CH1CgUi=ox{JjV_AtgH~?J*eQ`G5)Amo%%heOiO9 z7sWCGk3Uj001;cfSz~Lo$~oQCR`^iy#q<+JloFP0kPj{9McAjsEGuwi3GcZoDDX$- zyov7LZ?U(s8YTvm-FIAtA}9Uvv@;I2vz&RfSy>1F;A1{86V;j~FSgJ&i#x(GblOPe zxdyE%f(eHtSK$Bg;EVrC2$C|nKS^1r2yrupL<9P!_ymT0pm>zVgl!Hh^@LALdrnGx!>~K3Xs^1H<#-Zo4<=zQkNDFK&QUs8 zk*@>v#1BLQ1GlFWn`&O=GKPB@V%fJ6pnU@E6{7R@WZ6MQJgL`53Jj5v>&@NHz0(q|<-ImKU{KHzPDu-x7B!Q5xH)C%x)#~+% z^9ii?FoASdPLlx9=6B9#FVYK3U4p3wQwggJ$)<+@Qc{53OI%F~z)DqehdZGwOk<3o z>Yox@q7KE5VJnI!22|^I9mlKTe$l5lK_z8`ThnYfjxtnlrfDNTqP;v2A$hmn}f=Iuq$oe zQY~_Pd1qT}OxU(-lQeTzKLU`d03XsEAc}6D|9QRhotZ>ne=VR2$U zw-X0!xP*GY8_Hqe$u^aa8#RObE$+nFU)<;u?+2P!-JkhSaxOIj{ z{8Ey^Dkt-$FxmJJB#+9~9BEU@ty<{E=p=qGY6G&-V3t9d?&x;KViGS^w@2*`Z`)(k zpIhf@4`syD^f?#!C18=4V-7T8y6zV?-HoAg0REayD3jab_9cLBA1Fo)>4tm-3*RZ3 z%^m>;W7ucSWPM#&)`vv~6WL{4c$mKdPHaJ2fNRqZzzYCyxiA)2N{CZcK{bcv=6-o- z=^g~$+As;135f0pxcNolSYRK24q@=1y5P$K8^ArYaJ!*H;Z%P zg?&D>wU8ari&{mLd=MF?A)80oY<(3!0!Bt)2*fHt8WGKa{UDd}q0Af>7WC84usx!+ z@j{q1xl9+*S3PQ3R`Dzj(m*z3N<)I!GVM5Mpw1>Em%giC!r-#CoxjYf))4&M>kX9g zG#MUprs&2|Axb~Yq(4>~(ISQ^aBm%~C2(z^Wo8Ta?h5gF+>TSUAWgL=uvU2#`m-E| z3|$8&muK2e!lncAMC+7rlJAC&9Scurzv$~;;)l}`ZgQaoQg^x-%?tH^AZfk{&`leL+8MQ)Jpe^ zoaDA@Dz5)J(nY8x_}OCQ;4A{(f7nNe91Fe!G0>T_zcW^>7K>tej?$CL_04?(W*+23 z>(sTRrG&$l!9n1kEmP&Cd9J!CzWO1@szZ=m8G%6sf;k|f#NhP+a$@x5yDVDg9U6s0 zooTwf6&zUB9C|=Ig`t)ggX3%;sw5D)xEjv;B(BJDp+n+WL2}d-bP*U-(Hd~xDv-NB zqHrb;<)MkARN{yXyV=&%dKjR1K@_NyXDO@h9|EqlQe;!mkPan0VrZY0`yvO{RF8k0 zsGx{uKczTE7HRshhuFPjaRFx9(e2fT&WlJa3QVXTh;)xCWs6mNG5CH~KNVZ9pj)J4 z;PHC{^ei33@DO=laag!dgS-`KksN;Lfi<$5<|kU9;mNo)rXA-~O>!}8>*P(1zWlU` zZqbf`fHg{9S9dGEmDAv!b#7WzI)TzwC+mhQO+^>sO9k3(zO1nn-j*&qj>7VYG@=yVkQ;m`1Zc%l!xRb^Z z*f$t7zRp*^Z5X%P@~(~p>+HdU8Q_>h7lO?DpfPrqkecV3 zVhYjAFGD8)Gubo)u7yF$?Der|US@~>3~X&_zPkXZ8J^TfcYXuc8ixt_00wkb{@xxE6TQ<~8uD4p{=K`aAvkHKy{%N-PebK{bwdaM0QZh|_fn z>*1J~Mt-1F0cbsgwxJBtSr_YO3)nI*IKSKN%1yNP3h0zfp-7x3rUQCp1V+2W)#rje zBmpv3vky~D(%eLNNk)xkJ%+_`)QZ704z*$<+^o6$TcD&E4u`z4Rd9M0eaYK&EJH#S zTX{5t^N&J5Z7dE86GD$3aA*30zK3~-`AAhO=!ev8f_FS9_pW~0H2dtSMeW}gRwi_M zco4pAPB_pO#7djs#ZmnZw92;^=?q|TB%7`J;@mq}e_!>D${j0%$EY-3bf-}b+*OIh zS88?mT1htG=sigYNH1?CA<3ETcrhXbp*46l8pcMm1J_NW(hjv!n`V3&9~J089mEEy z6w`Jqh2SFDtj$d|M`Dv)q*afPNjmbQBgBFw^MmFTuBr}@QEWa+Led`#YebwGQonzYF3hc3;|2Ag z=d@BrvvON;Ky_w;tZM`ujH?3QG$hy#h)J(y8uAJ&2lM#`MveG~p?wH_(^MB2fh<08 zxNY|QH*J;P00&zoj=8D%ba|%~ktT!inhd9rB4{7rh?+1WJM{A=v4ek1o+V=YHz zaYdBEn<#Xo2C$7VKJ{_fawU1}M9;i#oK^lP!eM}%{2&S1p|7U-lN8Y3GN#LVF`Ex( z<;lE}aOcORBro>{?jj`^voKXP7kFbYwmxcMP|=gEYgbj%<*{Pg7h5xr7FER=W8wy? zy)~MMGE^@QU153y;d+&C8A+0uZH%WOWN0QNCbo6^9?hHzui}L~{iqO-A|Yvp_Y0TS z7Xelj9gm#wdfFS{y!Y!F;iN=i;filZAwl=ro7ia2>1pO=1C{O9S)8buXfRQM!sV{^ zVV+q@Rx7GmnN+^Kl<3bqciudFOld+ZeYwtsH*bT|WElAQiADsapyXu9zDlIG658 z8y2COec#zE;yc{>xJ;4=gqzC`!Nfk5;{);%zOh>`KM9uZlAI((9|HrO-MLDY&GkHdU)R2gMuI6{vcXag6z zrRQjByr?$1Qs0(Co9X3wc-O6wrgm;k@_C4zq+AT(y!UL15Hl7_AzQHl+ z$y1=0jEj(#;FweHtyw;4Igy_hBT&q($SF+MV6+%u%J%3b9-xiD@EmwZ90f+iP%TBw zyi=8cXdLio*?rQm8yCl6o-N1mnALyW3;`jB#kS9O$b-xq+H-pm)$wVw>`%f!3T!d& zMgWH{&CJHrB>0sX;BG_O(v6NX-7d-%QVWA@P^P)*!8mh_i6gRbH|Clj;0)${GsOUM zFgXjhYQWAiMy&9O<33$GKWJ#L?Oepz@4QF`2Wwf*hqqB6pA++pXYA|G-~qUf$XB?B=%i(5j5{S}qCFm1R6 zXhkcmY3L)g`KFPs8CH6QFs&U;Xw5Deej3x|9x=6ajEVe2<4sf4?Rmy4C z$ZBW;Itz$8MfpzauXg)Lf$PXU#P*UngsNeDngbTN1I2**b96FsR+9FZ`(P26wRJ1Hjx5%7DB4ClKnuf;4J0? zKdttcc4ybSd-vJHXrCq0ZBi2&2a zZ+?kK<DPZrL>#7^8$N(*u( z85~>4diCWT-;!~mGn$c)M0U2hM3SS=Th3p%T2o1Ve^HqnNd9SzYcivlhkLOz@|LfCI;G<6k&t}*2fyx|dEoJPuH#MG>OPI82AP{=C&QVzpLOl* zkng(j&V9MkrJbrWofj>O2&~R}Bs$^I&4h8guJIQti}rdQ{93j%@#D*;sGgWQ_&LK6K8m#CS4OelGX%(f_&o5b> z_>Ur4)OWe&O^Vag6QodcJI%l_hE5BtZan)H^!3M_8q^3`5xsOSqv;E z4cg(UsGy3!A|!>>qisY)5}iCurdP0KES=!?mm+SudB|jD0drz*Zd;kzvs6~*!a!h; zq0B9NQYS8^NmG=pvfX0g7-5U_sPa?Q;P7OquvU8!$-IROerK5V%4;=bkPn_Q=(bnB z`6S2nwsi@MI-YEL@>+iD;LxqmD9RH~RJ&oL}2H&;@S_ zR7Kfw-_(2B-3XgAV&Y*TxnW>d05|x!VG_+t(--Fdl4M^_Wgy|2Q`9Sc=a5bzb@yCI zUi~X2pU2ehS#<}}{e1);o$U$z?=BUNr9<%u+>p5^iHD&xhue54-5t=-LyL zSRLkdu!>n`9@b7Q-6ol6hcut3`xap)7P-EuI04oJ7+EH$3xc!?C@MlJ=ly+hxS~ev z%yv~GUpAMk^LO&FQfZ9$a(+vo?#F2+LSo0%E@SQ|pjQMfUaMA%s!M>`d3?$3lFh|~ z#A|PY_T|(ENFf#(0RQZe7{9`YCIOlk;U0`94tfutH+TBIA^ahxA#u6WYJK35Ge0{` zw3v?Pc5*rJMDQM@XUr?2Y|DpnbtzA@An^_qYDBznN1pp07UU7(Rld-aHvaPE8lRGD zmjYFn&z!Gv3Kbv6!Xy{PnhB@rYFhV?uo$1B^~j>*Rj-=*n__osV@Yy#?r$woke@Sh zNshKHM!da6TQO`*DWlzwft-Jn+l!y;jkQLsM&4Pe^uCwCzVO{GYz6#JkkP zM&hFnjMEQ8)7rO{r>iNat+q(u3i@8+)6VqG^E}xFobwGfQ=$pOK9I)dcqdlaSh%v( zGXCCXfFRfeYMaS*@w1|@KA&(WG!83C8hj^riwawTA>u$tZG}>BPqR)WS#Z~Ms`y_v zI=9gp8!qo7@A@*>2{o+KG^?rhzsO0KZ*}2Uj;Ep6KU0V6qfC#q7 zm2dnbrkQGli5Avr-PO1%JCxYjm${>w+sp~Zaw5(S0wYewf~~lxift>=>Z7z+X=$aw z=TR;C_(X z%=ikmOR+uF2i-)u<(y;D{ZS~XA2jkRQ~C5(zDjg`zRgd`+^rM{MYGXSx0==!rUWJJ z^!gyQD$d)b_#UHIAjMmnvUY>70#0hkN{r!tjKsZCSFR-FOe&p#`oN2IGst8X2k~-J z-b11o+L`pqDO{0^4P;)2uyFUYhYG7%$OL0T{mkMmIZ=MsEQ53JMdWEh6xUM&sBQ4% zXjQVrpB!pF?d3yEtzotw#c8A2 zB3r1g+%sF7*19A1eCKQq?Um29+)7`21rk6S=~@Kufy|g^*?oDQ*@hetNAcd6e3U%U zM(ann^SKTM$ zUDZQor&`qtelJuV=z2G(>uE(@t&_US0Sdn$eu3Hm~w}WHSm^3zMfI+(1=Nf ziks{b_UqB@zfhWefmtt(EF(_UF$G&)TYZyD>xi;3TWip)feToX_q(^@TFrNj*||gK zYvbSlkW)I@Ib0t~I^o(FMQX{7MIHkpgI-cir?rv$sx!9J8-&-57BopUhyg2_)SP&} zP+Z!-Vv3!)Lt-0k)0fHJ`2n=W4|>m#UIqO;a%s{W#kTC`5{4Tp$Sy~f-$e8Z{|ud> ztC20cTEdpf&HPRED!UOo*LChmO;965$F>ZuGG%DedZF&*NJ*+`C=a`DBA?^djtP87V_1HWnIQ*{Du^%wg2T6>3|=)p&muw;49FLF6et zymEEI6^`G;UriT%YuL<09mt`Qe)!x3;XC6JuApF->7l7xSRph*Tmt({i6fbxoik;T<|Vc@bRRC4YUoS-tS|_)8gS^XDX6%7X|f<_1dx z>y(P_Qvq_suHpWWiU zcOta2lK-PEb0Tgb^5v-?|G8OW?6y?L55f}pXaW1>sqC;PqgR$E7yHD68OnFei%kYX z*WRTqMbYyefVEa@dTiadd?QNa53_|3oE&z!t#)ch@2)kO-jx-q2q*g-$DjK);R*)}uv3?#L7Sd;e~`Mo3v zFU7+5ZsFktL=hGa=Il@Mc%PZ2itYtpvb1eoNe1hz(bD6ed1(-I)X2awbtuz;8tX+G?LkuvG&7`JfmD6; z685YOR$V^wMD^Gb6YC&$FBkeJ2}XJ-s@8t zXgQ;ZF?pHf{Fa3u@{Rqg=(@*1Z2I;4F@1$OHgSiofsbO+yum?u z%xbjX*P86N4YA^y5_s(`TH3WtQ{#_`VQM{}7AjnOs>v-nqH+G+m|f-pQunA+p8gXd z=0r79HikG9xntbecy+4+yPZL>-(viR>SS_Z$|Cv6iuP^{OnmA4PK*qflZtpB!;{f5 zm18aQfv0qV#kOF1?#|G-(7r(vUqNpWd)wG6$~dd=3jDrJ24ALds_PZ@G4~UP8o7?y zEORU0?yGJGgwvYu47zSf@=l0R;KFANzTRnrXA1^DmY&Q)plmbOBs8#$l)I=g4Y;xd zLr0-QZ;!FrQ>w5iB@;F1aX4&9d&qKa-g> zBpWNq-4qMD2sWB#Fw#GbdFGLLtjY>Xv?=%@ldmL^a2p03stgl|?sigjTuTa7|opu}Cr`6yoivU5~9VY@NULBo8< z^2(cp_()PF3jy}7N-f(B!*@CPKTBh(atWnxm-twyHCU$1zS8rCcUN8EuD4}gClm5* z#w_w&_Ev!7Jg<3i+N|I0S!G2cC0Bm7*U?t?!KW(pg?Ued-H>!W_gZ6pPF9ESSkdsE zlZCbvcUG_Tz?$GkNH54d!hKyg!uJ!Fvlg6Cx=G~RP(G3^7%TRO+p#eQ+i_~<_=Tk?0hyek4R*%C_W_ES5SWcgz(5;l`u%Homrm*-EvMYb12f^2+p9bZX6m80|u8fjqDH1oNjMV3hC9vZIZ`JlEnBV~J`Somk6 zL+`PX(;>A4RqMf&d1lDM^5BJ zI5)cf8JvfkfP@WN!NI!~StKL!t6rP8a@cuPcp6C?&S7LSKM76P zPAT-glTs$wFHD_^8?iCvPp|*E;O*I(TIOiHa~gspCz(O@2+S<%;IC5A3H`)(9)S2* zT{Od>$iX}v<%~(wm+vs|80VDWmoaXF0h-;t zM^!J8QQcxyCHj(IQr=z9Ew|`h6k~acV~k!s6Ss2L9eYhQmzMb5G6Zd7gDx59tzWM| zvW$lHCS4eLWF9#86y5Mf+L?LqWV+?8`oxz9Gf1~e7kYTjAM9&y(H&b8I`k1ad038} zzK0Oh8s=d-yyR5EYNW?UPCwN3d-c?ebanL9TR?pF zlQ(+C4?<-W^=9(E0e1E3j{@Gr*z zc6_&z-+ij3@u~b~`u1);kFImx!!MBzV&pOD{H$enceX?PU1f5dTZ;iFM%TQ&tXWBj z<-JsKfdZPfQ@|7JOy{@PpX8-Cch4dKXFS8Sr;%Q(f)m6>b1OrOMABx=)MD^@|#4pk*iE3odh`%bXJ- zXCdxp6&Qwu$JD)9EOcwZ1l;<>qZY|g_6zA`S;WQ???nYl{WO+hwbNx0sHZSA0Y*0f zdH{P8g@em>jv7_IeP?dew%ri|4S!Sg&ZA;8|AD35g*G&ej;4X{$=aLlzV6zJpM*n2 z-9bN4t#1WREpC21;Bf|!RBcc>2f5f2|<o6=WZL;LUmDXfj(TLKnD4V#Q-VoKl#s|KRKxe8j7G+)>HQ7!O#+E01k%Qw$ikly=lY1x+@^Rpj za9HAQ`^?>)wu*ghMRgL9dO)myLDRQ>+<$vwn>#WeNGe*()m_r%mJi2 zNmy>w4sP_o{}huSn=V@>CouoQT^ITeQ6!j{$uj?at_s9GeY5o6LAjWpYj=)*h3 z?MEWYt!eZl&byH5Z-{pPxd}%uceegDrLP(DcAimRG7cdA0u+@ILNfx0?u5I3gnItE zMpwu!Ra&ujaEb~{X(&IA@05ZeI=pL20JlW=kt}&tSS*&V^;p4#j&O8LeB0UNX8ukB z34Of!#}4*N3M~)?HK9w!>ZK>UVXuwmn3o0adFIfB9;mx!`pY}K*~Q-jy7#Pq*0$wC z%#7%Ab`k6n__TPZ()z>QJA?85cAf>((CpWDmfmT<@*grrl4FwiUS@oinIS0^i1%a5 z8igr25})*>JEikm5z#ev1RbYGG02viR~OU2_Z`L7YR(2g^Uo+pSP)-*LeH6y$z;59 zpAf`dagnBXkW)#VMSuS;i<5@NHNK{HbFS+1|6EUGg7Fg zo}Ih*7SS2&i6#f>+FjLN^U=$^tLjwMj-=aT6jHUYL7{81KaWZ5twr2oPYvbo1n5En z<$51eGw)>#YAD?Gba@B(uH@!|%90aNuP*7AUb(!jJ%9RY;-~LS4x!8!f&qOcvmctl zph^9&J@XM9w_`jj$_HYVa-$ZK36wXlK>WmcPuFR~vnfZNm%wZs{RUwRboE?F=Fx}k zL5DyZ6dTiCWAfM}D7+!I3(_ULFk?+2uC1ZJ^n}Bw|4snntK(9{8JCi8RG^W3YjN28 zB%%97$0A>2IxG3zhow-vT*)Ka#5Wp0U5zd=-$KcY_bzoD>o^@w%;pMNJ^9Ln_)0_1 z=P#~5DDWCJCw*7J@9~1-TY=msqi<5dXLYYQcDSd-YUftC$44@LFy`IDt-PNFzmXawv=CHW+iha+-|Eg{%tr>ed zMZn!zX)>TfC^F9)!L)T7dqoBnUm8A|kpue~xKIiMHg~V-Z9ba->#`&kpEDh*jOBY- zZym}826?j#h%Dcu+;`VT`P@W(u-ZxBa#*;A623qVij(y-j2aXi_J%-1a*&7@XL(V_ z=C^|N9ah6PjgC(uf>u(`-xd!Xw#ZOa=Qt3UgC?)O8hE!4S9|+|a!X4%XZ-6ZmRuSxXW%h3x`w&+CUl%nDTwW>oTIBWI#NQro;4SHQF1jAqf-Iao&c z#eQTg4B+oCo-|P8j1mn9ErV--BRSE|KSG<@9OFDhz9dpQ*mt>6CTd+D{qS;z9B-;8pvKuuYi@d%D#Q8%zCko)>-6 zE5@$CKxdX}vgHM>(1dRU3)kgqL8q4`&$5)$sMd75W*k-Gxv*~;J$bHRr!>30icdVTm&#^{?mTF-3 zv>lx^YYr+BW`1%c71yLWRes)*MVqgx6T0uNWr5L^(=s6@gmkyk7*g~x`H<4ywAvas z=P5%3SCctst~kdL*Zb~GGwSzitpgc!C!=+y+qMa;vChx#%KFZZ&7xIk3LTX{I0d}h zC%9Lt(MNF}Q-1bSZH%+Qc}%*lGg0@+nU(<-dsjsAo?Cxdk@Q zPh5UqTa>R~jd{)J@FOj{vr}#6Q;?6+MY&iB+47XI-%MSN4RuJc4+Zi;(L^jo+n8H~ z*j8=2Z>gh$$2alXWGu^RPEh!aXOb9Y9j%cb_P#II2p?!V;W z-CRId%V=CKdCLfrCmCOU?^%9NHEs($;-)=5fc96`et68dFP(aPWsLA?4#DY(7P`y{iGXp5@N;R9ZwCVrKq;7i_Eq0 zHv_Eh^2yAG)=AD#TXE_vM_{&z#4YUN&h|-We2q%=wGwDvtnKQYmc9%$4cm^YOhRJoX+q|bPM*UvzHU$4#_O;46~ zhP{w%K-VE9NpnDVm!dqyHC^x*OoytOt@_Fv;prLv`quFm=qWzqW6ribrIsJr N1k?g{uR3 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�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ⅈTEyg9 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篎#}|BNOg@eiDd&h7u6Bk|93{{x5Nzp@$x{u2(vzo&_y?7Ggp(@`m|!|YvAk?SPQJrt1x@J$j=7P`+&Zi?`FSUg z8kDHhN(=aG>`6KusqgVs_7335ac-vWX=vOV?}Bk_d1l$@PVytJr zOciHso+4pcb6&qn%6GRm2j8F&!j>(dek%)raD6XQqJHIW*tIH4ZiZM0_is*DmRJQv zg&?+gdX}JE#h`09l&GIP86bJJeEs4Yr~J+R&@0g5H}O!=Z+k ztTBG3p$2aV|1yJkHzx9v;EDS<7O;kf`M93X^nwAI1V2sp9l7&yBRS%cHgU3o*znT_ zlfG$uvRMJzE_5RPfnQokU2Jcj{BpinO@W^}U;NpIXGD+5AUegz!tGUJh&w-h&Yv(Z zf^gf5=ONfDcm#-_89pllKdY+%t?-&T@q;%DeiGWSA}VI{0mMQ0-egRx&kn2TR0mx1 ziW_oNBS)BYZarv_O^Md^RpEA?f?rl#rUi@|+b^gep3Gft?_9=5$E4R+L7Xkd#4T%_ z>JczWM<)^S^prGodSOK)*q3nCuX&I)l}5fvV2y3ak`pY89i zU5+#o6vxh2dpi_Z0(#F(FwYWQ`=D>C8_Qn7G{t>&B9yXBD}_{hx$chI#m6P_}S-tG(9WGPsKs?}g=tPGSFZ z+4=1WAFzH`1$beMg0SZ3Gk2{j9LXYIkcOPSb(fpS^j91;{8Xl0T%xbMrvcmd`IJ%aFW7e+x|?*iVOUdSAD z?EId>Z=IY(pf%O;?tNo5;ig)Laf*xS8^q}V*^w|>;*6qz`6d6cTt4@+v_ex zb6+NNLly}N$i-?L?khqy4=uxG6E-Nr!4e}e9Bna61k}o@KbCtRW8WAci@%Kw5E&ug zyP$Wy=u}0^JnJ>cor;43T`r9m{3I^!9-Q6967CM*?;zz!4zdaJRP*9!^Dw;of-I!| zLNS;16$|WZbpR9E?6nL$$PI}OxP}iPo09$N)*1oa-iA;jNm)3~DMlW}Z&Ns5;u zBbkbFDI4L6h2hGzXk!8Ta3n32&735pNv@PuCbchc-JN#JKE01?mh<#J813nI{b-+a zi$FFCYi|NfU*6rI8b{%>EB>ZH0s3d+d#$ptNGT|85=L2l8MdiWgm2Q63-P_YF>pk7 zilfEGAKTQBIUY^6NL)zPRa9)BU2sm(6cYk6c7wPMH-(2oaw&Z8IgS>=4t=5+FR!65 zxMu%~$L?0F;479c2G!sL>Yd8fX;6trzvQC4;Gsa-2(@wT6isfFbGE6eJTc(W(V+XD zz3R#hY-=RAMM-A<6~nsg;Z5S&mkhHjR%oPKOi8Kue%l@IWBy$^g;_6GB3YInttB4e z1?UM<6x>`&)B`sjb%DATWu(3;R zQC7{%MH|@>|7OA+wHs(erblmP*QK?x`lWsvO#v`Kf{GiSFzUzGwzh(x;p$(}&PT*rC#ljRhMs3)p=-6B@L@xN4y${KSZoks(Cg-)tA#v zmcLn^Vs+H?!bzxXE40x9_wjRFsoMgDmsF!7k>ZVtsQgP*{toAU18&iF);p6d(HMB6oS#&Xd>mX!YOQ0}gS9d3xr{eWMi}vTtQ5hMcoTibs8&FjwAMvv- zy1aZ$7?;{A{%)ql11oNe4X+IlH<2tnbSliij2&|nb1SJkLkDIHgcb|@k=VARXtX?rx}sp_;?J_qbhKBC$JD$Kzl{0VCBax@wdkt8kJMkE-5Omleu_R#HEJJq z4@4qSNKk*_0m@NA4q%2@8^R+{p0>`i+Z&jS>KvR5(x6#3?+#s)-KH@Z*IM@Mp+>Ry zDf31EO!%$r!5=~!7vzJnR3x`s7H-b4xv+p+dUvR)vT->!;XMDh%yqn^RK%7~+kRCF z;KhUt)azNHEX!M!wKvF+-lp%od=m?|7x&KPhG*EYqN+Ko1G=;NYeG|g?Nw&Rq7t-p z+7gEe(a03;pm9@VL4x?r{O$tbcyNE`d0CRN~m!oV49s zaeSgzeWaMsR`e*+-SAYlVqn_THyY*Y)HWUz=Vw^ksDSWJEHPOPY0%qASuk7xPsc~w z6)0^D7P>qCZ5AmZ9Z0Dz4Sc9GYWq=gkzXBl4#gi#eH>^Uf&e6B=R1BgmX?Hg#<99@ z7IoM3dgE>%)s?Q%nGMDE^!dCwvQ@;`FlF_w3GS3_24scniJUs?R%AfaUxFFZQq;4& zL})R#-zY@v=YKNf=0svnGXF_eNeh6Jl8w!H;Y7)bf&xJAu%TM)@l= zVt(`-`G`puq*`kU=My@{rdeaP6Lwt_FXeGFX>Qdy3{Lr8YuL^~icDbkS7OrxBVUWx z1vZ<2NRboK2D_eUerJ4%N=_v&O*&d3nX!YL<;zUyS>a8ND)VW#N} z$g7o}IQlAywEPB1q*Otxq*3vy51ZGbrVr&M`D?yt*Q6+=OEt?5zl+)TR4q&Dg*6>} zzRydxw$;{7PlV48#M$|0`;j0rnn@Y5r8*|SnAzWq+ zX-QXm;`GEih`_k{wxTVH)dvF)bRJx}5Ka{MiT_wq(A0~R3D71i7FJV@*E~5Q@=bgs zXW@(~pw4*J4xrjvxGz_&K(kwn^-_I0d?quo6$(2_9vIUhGWY^j3TyC_(!{+_|jl6+@pER|c;NI%#NW-#}XMlc@?7D#NDr;txWX zX+F(a1CNVQe*Uz~bpq&aU2T@{IN2Q6pW1MDGr58+xxl#$AclNg92pLTXO5;~r|$!O z6M7U?zSL>~fw0qzS?f1mS$Bbe5xhrSdB$5T=s7WKjNW0asin&n`qL}pE`7i&&}ri7 z#I3r(LUAN&w^%!K^kZutORD=Qt-j25jpt#2_7r*^#UrP-vd2@02we{hRGu;MJ-E3e zha2VCA9vsNI{eAEv$I#u3}G{kp7M}+E8`q)#QLo5{E#dUb3UIDNxQs=t1&8xVV)Rz z!K~@w8RKy*vg}+uS^s|2zqJ5BV$#4F=3)paNooad+FaZg^Qh0mJG>M2i z4Ve&iUH~Oi59${pY*_QzBi-qTcVrBY73d_ zKFL0}%s}#B!_Rt}_B+%KPOcubaE_#3g$r-Xqdfvt@<7^WxD>n1*=QuqsIL3qd{=4L z=c>l|FBgpSk|`3~80XPeNy`8)3PO4ezfITBoRVF!kqAAi=C{mgo03=N=(Jz7Fz!Vr z3IRmwY$N@+-OvDMZXr4)7kJyUJm7I8?wv}j{`&1duNJ;^>`3%MqLjUdvf_MC6p8FX zh0Gx;t{Y=*LqA@SNbLd1GPdNMZ~e#&Zk}6VHr-1U(i1Y#mh*1((t!l ze<+N7SS(w*+8<$TFIWTka3OEze=TMtSL}sbEa6Sq!Ohkb=!^5v*GN9~;x)U-SFF*lng zhW)4x#_unq^TlKgCq|;uu^yD)2F$62Z>MZ322qVZ;p^vn5eIY%kRP;8lWA2$MscvQuWA>Q)r#IuqL9IUd3& zvbB2eYgvGIc5&Wg zf#ps-m$VnoHm%>^lbrJ%cWwH`eeo&+y*7(i(gdo3HJXH;fT%_r40Qf_QVCH@sCAp) zIXHm4>G}dV9Vo5Mi+k7gx_U)VOrGZeFEQ|J(tL4+*E6W2c6{Y0sh)@q)JV7N;rQ5X z&ux0|#~Q43KR)huzk`u*e>5s|nS1v)!658+-&;x%@xBxmwj3ii$|f+`s;T8y8FmAM zX3+yj(vBL2hc9&k?%nrsn!6{uqWClIdqvG~;GJhOd5bKUz^2>~E4!~Q&g0(8bV9;0 zE4TzdJ9F)}RKGA?j)!>xro##j*Ty(pL=kl${c_+Z3Y9Hl!&k(8`@2?fEKlh5d|6n5Ybo+69N3@3~ ziB-r82B()LNPiFQ(JqGk%@=<Ξ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

V2HB!2O|&zUnd(XLS=&duiITDYx+=l+~#B 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 f~H3{muDFBLD+4<;}0Jmp@iJgscnmY&Jc(X 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�mQo+0OSzBxXl# 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 diff --git a/doc/datasheets/fadecandy_opc_protocol.md b/doc/datasheets/fadecandy_opc_protocol.md deleted file mode 100644 index 53cec6a5..00000000 --- a/doc/datasheets/fadecandy_opc_protocol.md +++ /dev/null @@ -1,79 +0,0 @@ -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) diff --git a/hyperiond.test-binary.REMOVED.git-id b/hyperiond.test-binary.REMOVED.git-id deleted file mode 100644 index 007dd52b..00000000 --- a/hyperiond.test-binary.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -23f1b917ec588d71521aa698edf446a2e8c0ea5d \ No newline at end of file From 4ccda40250d81933291203c988013695246e1311 Mon Sep 17 00:00:00 2001 From: Rick164 Date: Tue, 17 May 2016 02:54:10 +0200 Subject: [PATCH 07/63] Kodi video checker bugifx (#633) * Kodi video checker patch to make it compliant with recent JSON RPC API specs. * Updated inline documentation for Kodi video checker. Former-commit-id: e0760f55e1ddd61f10ae457c485aa01ae4507260 --- libsrc/xbmcvideochecker/XBMCVideoChecker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp b/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp index 674023df..fe8efd78 100644 --- a/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp +++ b/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp @@ -6,7 +6,7 @@ #include // Request player example: -// {"id":666,"jsonrpc":"2.0","method":"Player.GetActivePlayers"} +// {"jsonrpc":"2.0","method":"Player.GetActivePlayers", "id":666} // {"id":666,"jsonrpc":"2.0","result":[{"playerid":1,"type":"video"}]} // Request playing item example: @@ -25,7 +25,7 @@ XBMCVideoChecker::XBMCVideoChecker(const std::string & address, uint16_t port, b QObject(), _address(QString::fromStdString(address)), _port(port), - _activePlayerRequest(R"({"id":666,"jsonrpc":"2.0","method":"Player.GetActivePlayers"})"), + _activePlayerRequest(R"({"jsonrpc":"2.0","method":"Player.GetActivePlayers", "id":666})"), _currentPlayingItemRequest(R"({"id":667,"jsonrpc":"2.0","method":"Player.GetItem","params":{"playerid":%1,"properties":["file"]}})"), _checkScreensaverRequest(R"({"id":668,"jsonrpc":"2.0","method":"XBMC.GetInfoBooleans","params":{"booleans":["System.ScreenSaverActive"]}})"), _getStereoscopicMode(R"({"jsonrpc":"2.0","method":"GUI.GetProperties","params":{"properties":["stereoscopicmode"]},"id":669})"), From f584b05de57a25bb9db9cb70822fc237b4fc3937 Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Wed, 18 May 2016 11:26:25 +0200 Subject: [PATCH 08/63] dispmanx: fix grabber issues with certain widths and support cropping (#634) * dispmanx: fix grabber issues with certain widths and support cropping The dispmanx grabber will produce garbage output if the destination pitch is not set to a multiple of 64 bytes (16 RGBA pixels). It can also fail when retrieving only a part of the image (eg in 3DSBS or TAB mode). Handle these cases by capturing the full image into a separate buffer with the pitch set to an appropriate value and manually handle 3D SBS/TAB left/top half copying. At this point supporting cropping like in the V4L2 grabber is rather easy and added as well. This'll help handling overscan setups (old TVs) and removing (possibly asymmetric) overscan borders. Cropping is disabled in video capture mode (when the DISPMANX_SNAPSHOT_FILL flag is set). Signed-off-by: Matthias Reichl * hyperion-dispmanx: add optional crop values and 3D mode options Signed-off-by: Matthias Reichl * hyperiond: support cropping on the dispmanx grabber Honor cropLeft, cropRight, cropTop and cropBottom settings in the framegrabber section of the conf file to control cropping. Signed-off-by: Matthias Reichl Former-commit-id: bbb55f6621b90384e417f37da4f2543d112ef57a --- include/grabber/DispmanxFrameGrabber.h | 16 ++ include/grabber/DispmanxWrapper.h | 3 + .../grabber/dispmanx/DispmanxFrameGrabber.cpp | 156 +++++++++++++++--- libsrc/grabber/dispmanx/DispmanxWrapper.cpp | 6 + src/hyperion-dispmanx/DispmanxWrapper.cpp | 8 +- src/hyperion-dispmanx/DispmanxWrapper.h | 6 +- src/hyperion-dispmanx/hyperion-dispmanx.cpp | 32 +++- src/hyperiond/hyperiond.cpp | 5 + 8 files changed, 210 insertions(+), 22 deletions(-) diff --git a/include/grabber/DispmanxFrameGrabber.h b/include/grabber/DispmanxFrameGrabber.h index f0aeeda8..a9aefea3 100644 --- a/include/grabber/DispmanxFrameGrabber.h +++ b/include/grabber/DispmanxFrameGrabber.h @@ -41,6 +41,9 @@ public: /// void setVideoMode(const VideoMode videoMode); + void setCropping(const unsigned cropLeft, const unsigned cropRight, + const unsigned cropTop, const unsigned cropBottom); + /// /// Captures a single snapshot of the display and writes the data to the given image. The /// provided image should have the same dimensions as the configured values (_width and @@ -68,4 +71,17 @@ private: const unsigned _width; /// Height of the captured snapshot [pixels] const unsigned _height; + + // the selected VideoMode + VideoMode _videoMode; + + // number of pixels to crop after capturing + unsigned _cropLeft, _cropRight, _cropTop, _cropBottom; + + // temp buffer when capturing with unsupported pitch size or + // when we need to crop the image + ColorRgba* _captureBuffer; + + // size of the capture buffer in Pixels + unsigned _captureBufferSize; }; diff --git a/include/grabber/DispmanxWrapper.h b/include/grabber/DispmanxWrapper.h index 97431864..b7367238 100644 --- a/include/grabber/DispmanxWrapper.h +++ b/include/grabber/DispmanxWrapper.h @@ -56,6 +56,9 @@ public slots: /// void stop(); + void setCropping(const unsigned cropLeft, const unsigned cropRight, + const unsigned cropTop, const unsigned cropBottom); + /// /// Set the grabbing mode /// @param[in] mode The new grabbing mode diff --git a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp index f086c582..b1cb3ec2 100644 --- a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp +++ b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp @@ -11,7 +11,14 @@ DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned _vc_resource(0), _vc_flags(0), _width(width), - _height(height) + _height(height), + _videoMode(VIDEO_2D), + _cropLeft(0), + _cropRight(0), + _cropTop(0), + _cropBottom(0), + _captureBuffer(new ColorRgba[0]), + _captureBufferSize(0) { // Initiase BCM bcm_host_init(); @@ -49,6 +56,8 @@ DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned DispmanxFrameGrabber::~DispmanxFrameGrabber() { + delete[] _captureBuffer; + // Clean up resources vc_dispmanx_resource_delete(_vc_resource); @@ -63,38 +72,147 @@ void DispmanxFrameGrabber::setFlags(const int vc_flags) void DispmanxFrameGrabber::setVideoMode(const VideoMode videoMode) { - switch (videoMode) { - case VIDEO_3DSBS: - vc_dispmanx_rect_set(&_rectangle, 0, 0, _width/2, _height); - break; - case VIDEO_3DTAB: - vc_dispmanx_rect_set(&_rectangle, 0, 0, _width, _height/2); - break; - case VIDEO_2D: - default: - vc_dispmanx_rect_set(&_rectangle, 0, 0, _width, _height); - break; + _videoMode = videoMode; +} + +void DispmanxFrameGrabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) +{ + if (cropLeft + cropRight >= _width || cropTop + cropBottom >= _height) + { + std::cout + << "DISPMANXGRABBER ERROR: Rejecting invalid crop values" + << " left: " << cropLeft + << " right: " << cropRight + << " top: " << cropTop + << " bottom: " << cropBottom + << std::endl; + return; + } + _cropLeft = cropLeft; + _cropRight = cropRight; + _cropTop = cropTop; + _cropBottom = cropBottom; + + if (cropLeft > 0 || cropRight > 0 || cropTop > 0 || cropBottom > 0) + { + std::cout + << "DISPMANXGRABBER INFO: Cropping " << _width << "x" << _height << " image" + << " left: " << cropLeft + << " right: " << cropRight + << " top: " << cropTop + << " bottom: " << cropBottom + << std::endl; } } void DispmanxFrameGrabber::grabFrame(Image & image) { - // resize the given image if needed - if (image.width() != unsigned(_rectangle.width) || image.height() != unsigned(_rectangle.height)) + int ret; + + // vc_dispmanx_resource_read_data doesn't seem to work well + // with arbitrary positions so we have to handle cropping by ourselves + unsigned cropLeft = _cropLeft; + unsigned cropRight = _cropRight; + unsigned cropTop = _cropTop; + unsigned cropBottom = _cropBottom; + + if (_vc_flags & DISPMANX_SNAPSHOT_FILL) { - image.resize(_rectangle.width, _rectangle.height); + // disable cropping, we are capturing the video overlay window + cropLeft = cropRight = cropTop = cropBottom = 0; + } + + unsigned imageWidth = _width - cropLeft - cropRight; + unsigned imageHeight = _height - cropTop - cropBottom; + + // calculate final image dimensions and adjust top/left cropping in 3D modes + switch (_videoMode) + { + case VIDEO_3DSBS: + imageWidth = imageWidth / 2; + cropLeft = cropLeft / 2; + break; + case VIDEO_3DTAB: + imageHeight = imageHeight / 2; + cropTop = cropTop / 2; + break; + case VIDEO_2D: + default: + break; + } + + // resize the given image if needed + if (image.width() != imageWidth || image.height() != imageHeight) + { + image.resize(imageWidth, imageHeight); } // Open the connection to the display _vc_display = vc_dispmanx_display_open(0); + if (_vc_display < 0) + { + std::cout << "DISPMANXGRABBER ERROR: Cannot open display: " << _vc_display << std::endl; + return; + } // Create the snapshot (incl down-scaling) - vc_dispmanx_snapshot(_vc_display, _vc_resource, (DISPMANX_TRANSFORM_T) _vc_flags); + ret = vc_dispmanx_snapshot(_vc_display, _vc_resource, (DISPMANX_TRANSFORM_T) _vc_flags); + if (ret < 0) + { + std::cout << "DISPMANXGRABBER ERROR: Snapshot failed: " << ret << std::endl; + vc_dispmanx_display_close(_vc_display); + return; + } // Read the snapshot into the memory - void* image_ptr = image.memptr(); - const unsigned destPitch = _rectangle.width * sizeof(ColorRgba); - vc_dispmanx_resource_read_data(_vc_resource, &_rectangle, image_ptr, destPitch); + void* imagePtr = image.memptr(); + void* capturePtr = imagePtr; + + unsigned imagePitch = imageWidth * sizeof(ColorRgba); + + // dispmanx seems to require the pitch to be a multiple of 64 + unsigned capturePitch = (_rectangle.width * sizeof(ColorRgba) + 63) & (~63); + + // grab to temp buffer if image pitch isn't valid or if we are cropping + if (imagePitch != capturePitch + || (unsigned)_rectangle.width != imageWidth + || (unsigned)_rectangle.height != imageHeight) + { + // check if we need to resize the capture buffer + unsigned captureSize = capturePitch * _rectangle.height / sizeof(ColorRgba); + if (_captureBufferSize != captureSize) + { + delete[] _captureBuffer; + _captureBuffer = new ColorRgba[captureSize]; + _captureBufferSize = captureSize; + } + + capturePtr = &_captureBuffer[0]; + } + + ret = vc_dispmanx_resource_read_data(_vc_resource, &_rectangle, capturePtr, capturePitch); + if (ret < 0) + { + std::cout << "DISPMANXGRABBER ERROR: vc_dispmanx_resource_read_data failed: " << ret << std::endl; + vc_dispmanx_display_close(_vc_display); + return; + } + + // copy capture data to image if we captured to temp buffer + if (imagePtr != capturePtr) + { + // adjust source pointer to top/left cropping + uint8_t* src_ptr = (uint8_t*) capturePtr + + cropLeft * sizeof(ColorRgba) + + cropTop * capturePitch; + + for (unsigned y = 0; y < imageHeight; y++) + { + memcpy((uint8_t*)imagePtr + y * imagePitch, + src_ptr + y * capturePitch, + imagePitch); + } + } // Close the displaye vc_dispmanx_display_close(_vc_display); diff --git a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp index a0d39d45..bad3807f 100644 --- a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp +++ b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp @@ -94,3 +94,9 @@ void DispmanxWrapper::setVideoMode(const VideoMode mode) { _frameGrabber->setVideoMode(mode); } + +void DispmanxWrapper::setCropping(const unsigned cropLeft, const unsigned cropRight, + const unsigned cropTop, const unsigned cropBottom) +{ + _frameGrabber->setCropping(cropLeft, cropRight, cropTop, cropBottom); +} diff --git a/src/hyperion-dispmanx/DispmanxWrapper.cpp b/src/hyperion-dispmanx/DispmanxWrapper.cpp index 7d8702d2..ff88fc77 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.cpp +++ b/src/hyperion-dispmanx/DispmanxWrapper.cpp @@ -2,10 +2,16 @@ // Hyperion-Dispmanx includes #include "DispmanxWrapper.h" -DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : +DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, + const VideoMode& videoMode, + const unsigned cropLeft, const unsigned cropRight, + const unsigned cropTop, const unsigned cropBottom, + const unsigned updateRate_Hz) : _timer(this), _grabber(grabWidth, grabHeight) { + _grabber.setVideoMode(videoMode); + _grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom); _timer.setSingleShot(false); _timer.setInterval(updateRate_Hz); diff --git a/src/hyperion-dispmanx/DispmanxWrapper.h b/src/hyperion-dispmanx/DispmanxWrapper.h index e8526b02..fa89fa4f 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.h +++ b/src/hyperion-dispmanx/DispmanxWrapper.h @@ -9,7 +9,11 @@ class DispmanxWrapper : public QObject { Q_OBJECT public: - DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); + DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, + const VideoMode& videoMode, + const unsigned cropLeft, const unsigned cropRight, + const unsigned cropTop, const unsigned cropBottom, + const unsigned updateRate_Hz); const Image & getScreenshot(); diff --git a/src/hyperion-dispmanx/hyperion-dispmanx.cpp b/src/hyperion-dispmanx/hyperion-dispmanx.cpp index 6f1f66ad..bf8b1794 100644 --- a/src/hyperion-dispmanx/hyperion-dispmanx.cpp +++ b/src/hyperion-dispmanx/hyperion-dispmanx.cpp @@ -46,6 +46,14 @@ int main(int argc, char ** argv) SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); + IntParameter & argCropLeft = parameters.add (0x0, "crop-left", "pixels to remove on left after grabbing"); + IntParameter & argCropRight = parameters.add (0x0, "crop-right", "pixels to remove on right after grabbing"); + IntParameter & argCropTop = parameters.add (0x0, "crop-top", "pixels to remove on top after grabbing"); + IntParameter & argCropBottom = parameters.add (0x0, "crop-bottom", "pixels to remove on bottom after grabbing"); + + SwitchParameter<> & arg3DSBS = parameters.add> (0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side"); + SwitchParameter<> & arg3DTAB = parameters.add> (0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom"); + // set defaults argFps.setDefault(10); argWidth.setDefault(64); @@ -53,9 +61,25 @@ int main(int argc, char ** argv) argAddress.setDefault("127.0.0.1:19445"); argPriority.setDefault(800); + argCropLeft.setDefault(0); + argCropRight.setDefault(0); + argCropTop.setDefault(0); + argCropBottom.setDefault(0); + // parse all options optionParser.parse(argc, const_cast(argv)); + VideoMode videoMode = VIDEO_2D; + + if (arg3DSBS.isSet()) + { + videoMode = VIDEO_3DSBS; + } + else if (arg3DTAB.isSet()) + { + videoMode = VIDEO_3DTAB; + } + // check if we need to display the usage. exit if we do. if (argHelp.isSet()) { @@ -65,7 +89,13 @@ int main(int argc, char ** argv) // Create the dispmanx grabbing stuff int grabInterval = 1000 / argFps.getValue(); - DispmanxWrapper dispmanxWrapper(argWidth.getValue(),argHeight.getValue(),grabInterval); + DispmanxWrapper dispmanxWrapper(argWidth.getValue(),argHeight.getValue(), + videoMode, + std::max(0, argCropLeft.getValue()), + std::max(0, argCropRight.getValue()), + std::max(0, argCropTop.getValue()), + std::max(0, argCropBottom.getValue()), + grabInterval); if (argScreenshot.isSet()) { diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index e381651e..cd427175 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -231,6 +231,11 @@ int main(int argc, char** argv) frameGrabberConfig["frequency_Hz"].asUInt(), frameGrabberConfig.get("priority",900).asInt(), &hyperion); + dispmanx->setCropping( + frameGrabberConfig.get("cropLeft", 0).asInt(), + frameGrabberConfig.get("cropRight", 0).asInt(), + frameGrabberConfig.get("cropTop", 0).asInt(), + frameGrabberConfig.get("cropBottom", 0).asInt()); if (xbmcVideoChecker != nullptr) { From 19a6bf1ee7fa6cf65b089f1f8348ae79676a5247 Mon Sep 17 00:00:00 2001 From: brindosch Date: Wed, 18 May 2016 20:35:47 +0200 Subject: [PATCH 09/63] change default effect priority Former-commit-id: ccdda396083b61c417eaf908b628a2e5a7796ba4 --- bin/install_hyperion.sh | 2 -- src/hyperiond/hyperiond.cpp | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/bin/install_hyperion.sh b/bin/install_hyperion.sh index c0b05212..7777f303 100755 --- a/bin/install_hyperion.sh +++ b/bin/install_hyperion.sh @@ -191,8 +191,6 @@ if [ $OS_OPENELEC -eq 1 ]; then curl -# -L --get $OE_DEPENDECIES | tar -C /storage/hyperion/bin -xz #set the executen bit (failsave) chmod +x -R /storage/hyperion/bin - # modify the default config to have a correct effect path - sed -i 's:/opt:/storage:g' /storage/hyperion/config/hyperion.config.json # /storage/.config is available as samba share. A symbolic link would not be working false | cp -i /storage/hyperion/config/hyperion.config.json /storage/.config/hyperion.config.json 2>/dev/null diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index cd427175..de91846c 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -129,8 +129,8 @@ 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 = (duration_ms != 0) ? 0 : effectConfig.get("priority",990).asInt(); - const int bootcolor_priority = (priority > 990) ? priority+1 : 990; + const int priority = (duration_ms != 0) ? 0 : effectConfig.get("priority",700).asInt(); + const int bootcolor_priority = (priority > 700) ? priority+1 : 700; // clear the leds ColorRgb boot_color = ColorRgb::BLACK; From b293ea20db13772539c4b7ab8ce3695d18528917 Mon Sep 17 00:00:00 2001 From: redPanther Date: Sun, 22 May 2016 00:27:06 +0200 Subject: [PATCH 10/63] build script optimization (#642) * implement make install set CMAKE_INSTALL_PREFIX e.g. to /opt to install to /opt/hyperion set ENABLE_SYSTEM_INSTALL to ON to activate installation after compiling use make install or make install/strip (for performance/size optimized binaries - compile in Release to get best performance) * cleanup cmake files use cmake -DINSTALL_PREFIX=/opt/hyperion .. to install all files to hyperion or cmake -DINSTALL_PREFIX=/usr/ to install to usr. install folders are linux standard. bin go to bin folder and additionals (effects) go to share/hyperion * add uninstall target - be patient with that, this will remove files from your system install service files to share/hyperion - if you want to use them you have to make a symlink to your location of service files * optimize build release script install service files into hyperion share folder (services not activated, this must be done by distribution package script) initial support of cmake option -DPLATFORM= option. This selects platform specific cmake flags. no need for -DENABLE_... options (unless you want some special things) automatic detect for apple build * update submodule Former-commit-id: 5f06f314841810c780c871f810158010d3d2de70 --- CMakeLists.txt | 78 ++++++++++++++++++------- bin/create_all_releases.sh | 60 ++++++++----------- bin/create_release.sh | 6 +- cmake/cmake_uninstall.cmake.in | 22 +++++++ dependencies/external/rpi_ws281x | 2 +- src/hyperion-aml/CMakeLists.txt | 13 +++-- src/hyperion-dispmanx/CMakeLists.txt | 17 +++--- src/hyperion-framebuffer/CMakeLists.txt | 17 ++++-- src/hyperion-osx/CMakeLists.txt | 15 +++-- src/hyperion-remote/CMakeLists.txt | 13 +++-- src/hyperion-v4l2/CMakeLists.txt | 18 +++--- src/hyperion-x11/CMakeLists.txt | 17 +++--- src/hyperiond/CMakeLists.txt | 22 ++++--- 13 files changed, 186 insertions(+), 114 deletions(-) create mode 100644 cmake/cmake_uninstall.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 487b066c..b789b745 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,22 +1,47 @@ # Define the main-project name -project(Hyperion) +project(hyperiond) # define the minimum cmake version (as required by cmake) cmake_minimum_required(VERSION 2.8) #set(CMAKE_TOOLCHAIN_FILE /opt/raspberrypi/Toolchain-RaspberryPi.cmake) +SET ( DEFAULT_AMLOGIC OFF ) +SET ( DEFAULT_DISPMANX OFF ) +SET ( DEFAULT_FB OFF ) +SET ( DEFAULT_OSX OFF ) +SET ( DEFAULT_X11 OFF ) +SET ( DEFAULT_WS2812BPWM OFF ) +SET ( DEFAULT_WS281XPWM OFF ) + +if (APPLE) + SET ( DEFAULT_OSX ON ) +else () + if ( ${PLATFORM} STREQUAL "rpi" ) + SET ( DEFAULT_DISPMANX ON ) + SET ( DEFAULT_WS2812BPWM ON ) + SET ( DEFAULT_WS281XPWM ON ) + elseif ( ${PLATFORM} STREQUAL "wetek" ) + SET ( DEFAULT_AMLOGIC ON ) + SET ( DEFAULT_FB ON ) + elseif ( ${PLATFORM} STREQUAL "x86" ) + SET ( DEFAULT_X11 ON ) + elseif ( ${PLATFORM} STREQUAL "imx6" ) + SET ( DEFAULT_FB ON ) + endif() +endif () + # set the build options -option(ENABLE_AMLOGIC "Enable the AMLOGIC video grabber" OFF) +option(ENABLE_AMLOGIC "Enable the AMLOGIC video grabber" ${DEFAULT_AMLOGIC} ) message(STATUS "ENABLE_AMLOGIC = " ${ENABLE_AMLOGIC}) -option(ENABLE_DISPMANX "Enable the RPi dispmanx grabber" ON) +option(ENABLE_DISPMANX "Enable the RPi dispmanx grabber" ${DEFAULT_DISPMANX} ) message(STATUS "ENABLE_DISPMANX = " ${ENABLE_DISPMANX}) -option(ENABLE_FB "Enable the framebuffer grabber" OFF) +option(ENABLE_FB "Enable the framebuffer grabber" ${DEFAULT_FB} ) message(STATUS "ENABLE_FB = " ${ENABLE_FB}) -option(ENABLE_OSX "Enable the osx grabber" OFF) +option(ENABLE_OSX "Enable the osx grabber" ${DEFAULT_OSX} ) message(STATUS "ENABLE_OSX = " ${ENABLE_OSX}) option(ENABLE_PROTOBUF "Enable PROTOBUF server" ON) @@ -31,13 +56,13 @@ message(STATUS "ENABLE_TINKERFORGE = " ${ENABLE_TINKERFORGE}) option(ENABLE_V4L2 "Enable the V4L2 grabber" ON) message(STATUS "ENABLE_V4L2 = " ${ENABLE_V4L2}) -option(ENABLE_WS2812BPWM "Enable the WS2812b-PWM device" OFF) +option(ENABLE_WS2812BPWM "Enable the WS2812b-PWM device" ${DEFAULT_WS2812BPWM} ) message(STATUS "ENABLE_WS2812BPWM = " ${ENABLE_WS2812BPWM}) -option(ENABLE_WS281XPWM "Enable the WS281x-PWM device" OFF) +option(ENABLE_WS281XPWM "Enable the WS281x-PWM device" ${DEFAULT_WS281XPWM} ) message(STATUS "ENABLE_WS281XPWM = " ${ENABLE_WS281XPWM}) -option(ENABLE_X11 "Enable the X11 grabber" OFF) +option(ENABLE_X11 "Enable the X11 grabber" ${DEFAULT_X11}) message(STATUS "ENABLE_X11 = " ${ENABLE_X11}) option(ENABLE_QT5 "Enable QT5" OFF) @@ -48,20 +73,26 @@ message(STATUS "ENABLE_TESTS = " ${ENABLE_TESTS}) 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) +endif() if(ENABLE_FB AND ENABLE_DISPMANX) message(FATAL_ERROR "dispmanx grabber and framebuffer grabber cannot be used at the same time") -endif(ENABLE_FB AND ENABLE_DISPMANX) +endif() if(ENABLE_FB AND ENABLE_OSX) message(FATAL_ERROR "osx grabber and framebuffer grabber cannot be used at the same time") -endif(ENABLE_FB AND ENABLE_OSX) +endif() 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) +endif() +if (DEFINED INSTALL_PREFIX) + SET( ENABLE_SYSTEM_INSTALL ON) + SET( CMAKE_INSTALL_PREFIX "${INSTALL_PREFIX}" ) +else() + SET(ENABLE_SYSTEM_INSTALL OFF) +endif() SET ( PROTOBUF_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/proto ) SET ( PROTOBUF_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/proto ) @@ -85,15 +116,15 @@ include_directories("${PROJECT_BINARY_DIR}") if(ENABLE_QT5) ADD_DEFINITIONS ( -DENABLE_QT5 ) #find_package(Qt5Widgets) -else(ENABLE_QT5) +else() # 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) +endif() # Define the global output path of binaries SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) - +SET(DEPLOY_DIR "${CMAKE_SOURCE_DIR}/deploy/hyperion" ) file(MAKE_DIRECTORY ${LIBRARY_OUTPUT_PATH}) file(MAKE_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) @@ -113,10 +144,10 @@ 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) +else() # Configure the use of QT4 find_package(Qt4 COMPONENTS QtCore QtNetwork QtGui REQUIRED QUIET) -endif(ENABLE_QT5) +endif() #add libusb and pthreads find_package(libusb-1.0 REQUIRED) @@ -124,10 +155,10 @@ find_package(Threads REQUIRED) if(ENABLE_QT5) #include(${QT_USE_FILE}) add_definitions(${QT_DEFINITIONS}) -else(ENABLE_QT5) +else() include(${QT_USE_FILE}) add_definitions(${QT_DEFINITIONS}) -endif(ENABLE_QT5) +endif() # TODO[TvdZ]: This linking directory should only be added if we are cross compiling if(NOT APPLE) @@ -148,8 +179,13 @@ add_subdirectory(libsrc) add_subdirectory(src) if (ENABLE_TESTS) add_subdirectory(test) -endif (ENABLE_TESTS) - +endif () # Add the doxygen generation directory add_subdirectory(doc) + +# uninstall target +configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) + +add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) + diff --git a/bin/create_all_releases.sh b/bin/create_all_releases.sh index b3e5579a..4318d3a6 100644 --- a/bin/create_all_releases.sh +++ b/bin/create_all_releases.sh @@ -1,43 +1,31 @@ #!/bin/sh -# create all directly for release with -DCMAKE_BUILD_TYPE=Release -Wno-dev -# Create the x64 build -mkdir build-x86x64 -cd build-x86x64 -cmake -DENABLE_DISPMANX=OFF -DENABLE_X11=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. -make -j 4 -cd .. -# Create the x32 build -#mkdir build-x32 -#cd build-x32 -#cmake -DIMPORT_PROTOC=../build-x64/protoc_export.cmake -DENABLE_DISPMANX=OFF -DENABLE_X11=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. -#make -j 4 -#cd .. +# make_release [] +make_release() +{ + echo + echo "--- build release for $1 ---" + echo + RELEASE=$1 + PLATFORM=$2 + shift 2 -# Create the RPI build -mkdir build-rpi -cd build-rpi -cmake -DCMAKE_TOOLCHAIN_FILE="../Toolchain-rpi.cmake" -DIMPORT_PROTOC=../build-x86x64/protoc_export.cmake -DENABLE_WS2812BPWM=ON -DENABLE_WS281XPWM=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. -make -j 4 -cd .. + mkdir -p build-${RELEASE} + cd build-${RELEASE} + cmake -DPLATFORM=${PLATFORM} $@ -DCMAKE_BUILD_TYPE=Release -Wno-dev .. || exit 1 + make -j $(nproc) || exit 1 + strip bin/* + cd .. + bin/create_release.sh . ${RELEASE} +} -# Create the WETEK build -mkdir build-wetek -cd build-wetek -cmake -DCMAKE_TOOLCHAIN_FILE="../Toolchain-rpi.cmake" -DIMPORT_PROTOC=../build-x86x64/protoc_export.cmake -DENABLE_DISPMANX=OFF -DENABLE_FB=ON -DENABLE_AMLOGIC=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. -make -j 4 -cd .. +export PATH="$PATH:$HOME/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin" +CMAKE_PROTOC_FLAG="-DIMPORT_PROTOC=../build-x86x64/protoc_export.cmake" -# Create the IMX6 build -#mkdir build-imx6 -#cd build-imx6 -#cmake -DCMAKE_TOOLCHAIN_FILE="../Toolchain-imx6.cmake" -DIMPORT_PROTOC=../build-x32x64/protoc_export.cmake -DENABLE_DISPMANX=OFF -DENABLE_FB=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. -#make -j 4 -#cd .. +make_release x86x64 x86 +#make_release x32 x86 ${CMAKE_PROTOC_FLAG} +make_release rpi rpi -DCMAKE_TOOLCHAIN_FILE="../Toolchain-rpi.cmake" ${CMAKE_PROTOC_FLAG} +make_release wetek rpi -DCMAKE_TOOLCHAIN_FILE="../Toolchain-rpi.cmake" ${CMAKE_PROTOC_FLAG} +#make_release imx6 imx6 -DCMAKE_TOOLCHAIN_FILE="../Toolchain-imx6.cmake" ${CMAKE_PROTOC_FLAG} -bin/create_release.sh . x86x64 -#bin/create_release.sh . x32 -bin/create_release.sh . rpi -bin/create_release.sh . wetek -#bin/create_release.sh . imx6 diff --git a/bin/create_release.sh b/bin/create_release.sh index 7eb07bb8..94f90e81 100644 --- a/bin/create_release.sh +++ b/bin/create_release.sh @@ -27,11 +27,7 @@ tar --create --gzip --absolute-names --show-transformed-names --ignore-failed-re --transform "s:$repodir/bin/service/hyperion.systemd.sh:hyperion/init.d/hyperion.systemd.sh:" \ --transform "s:$repodir/bin/service/hyperion.initctl.sh:hyperion/init.d/hyperion.initctl.sh:" \ --transform "s://:/:g" \ - "$builddir/bin/hyperiond" \ - "$builddir/bin/hyperion-remote" \ - "$builddir/bin/hyperion-v4l2" \ - "$builddir/bin/hyperion-x11" \ - "$builddir/bin/hyperion-dispmanx" \ + "$builddir/bin/hyperion"* \ "$repodir/effects/"* \ "$repodir/bin/service/hyperion.init.sh" \ "$repodir/bin/service/hyperion.systemd.sh" \ diff --git a/cmake/cmake_uninstall.cmake.in b/cmake/cmake_uninstall.cmake.in new file mode 100644 index 00000000..27ed4ace --- /dev/null +++ b/cmake/cmake_uninstall.cmake.in @@ -0,0 +1,22 @@ +if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") +endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + +file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif(NOT "${rm_retval}" STREQUAL 0) + else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") +endforeach(file) + diff --git a/dependencies/external/rpi_ws281x b/dependencies/external/rpi_ws281x index f82fa85f..0165896a 160000 --- a/dependencies/external/rpi_ws281x +++ b/dependencies/external/rpi_ws281x @@ -1 +1 @@ -Subproject commit f82fa85f26c9ee10210469e61315d9c0182a2b81 +Subproject commit 0165896aa04b08a777fb6732a1af6fa29e4a93c5 diff --git a/src/hyperion-aml/CMakeLists.txt b/src/hyperion-aml/CMakeLists.txt index 9445b3ec..a53e1c70 100644 --- a/src/hyperion-aml/CMakeLists.txt +++ b/src/hyperion-aml/CMakeLists.txt @@ -31,9 +31,9 @@ set(Hyperion_AML_SOURCES if(ENABLE_QT5) QT5_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) -else(ENABLE_QT5) +else() QT4_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) -endif(ENABLE_QT5) +endif() add_executable(${PROJECT_NAME} ${Hyperion_AML_HEADERS} @@ -57,8 +57,11 @@ qt4_use_modules(${PROJECT_NAME} if(ENABLE_QT5) qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) -else(ENABLE_QT5) +else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) -endif(ENABLE_QT5) +endif() -install ( TARGETS ${PROJECT_NAME} DESTINATION "${CMAKE_SOURCE_DIR}/deploy/bin" ) +install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) +if (ENABLE_SYSTEM_INSTALL) + install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" ) +endif() diff --git a/src/hyperion-dispmanx/CMakeLists.txt b/src/hyperion-dispmanx/CMakeLists.txt index ae4c02d2..07eabd9b 100644 --- a/src/hyperion-dispmanx/CMakeLists.txt +++ b/src/hyperion-dispmanx/CMakeLists.txt @@ -7,9 +7,9 @@ project(hyperion-dispmanx) # find QT if(ENABLE_QT5) find_package(Qt5Widgets REQUIRED) -else(ENABLE_QT5) +else() find_package(Qt4 REQUIRED QtCore QtGui QtNetwork ) -endif(ENABLE_QT5) +endif() # Find the BCM-package (VC control) find_package(BCM REQUIRED) @@ -34,9 +34,9 @@ set(Hyperion_Dispmanx_SOURCES if(ENABLE_QT5) QT5_WRAP_CPP(Hyperion_Dispmanx_HEADERS_MOC ${Hyperion_Dispmanx_QT_HEADERS}) -else(ENABLE_QT5) +else() QT4_WRAP_CPP(Hyperion_Dispmanx_HEADERS_MOC ${Hyperion_Dispmanx_QT_HEADERS}) -endif(ENABLE_QT5) +endif() add_executable( ${PROJECT_NAME} ${Hyperion_Dispmanx_HEADERS} @@ -56,9 +56,12 @@ target_link_libraries( ${PROJECT_NAME} if(ENABLE_QT5) qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) -else(ENABLE_QT5) +else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) -endif(ENABLE_QT5) +endif() -install ( TARGETS ${PROJECT_NAME} DESTINATION "${CMAKE_SOURCE_DIR}/deploy/bin" ) +install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) +if (ENABLE_SYSTEM_INSTALL) + install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" ) +endif() diff --git a/src/hyperion-framebuffer/CMakeLists.txt b/src/hyperion-framebuffer/CMakeLists.txt index b1e99aa0..cac8f135 100644 --- a/src/hyperion-framebuffer/CMakeLists.txt +++ b/src/hyperion-framebuffer/CMakeLists.txt @@ -7,9 +7,9 @@ project(hyperion-framebuffer) # find QT if(ENABLE_QT5) find_package(Qt5Widgets REQUIRED) -else(ENABLE_QT5) +else() find_package(Qt4 REQUIRED QtCore QtGui QtNetwork ) -endif(ENABLE_QT5) +endif() include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver @@ -31,9 +31,9 @@ set(Hyperion_FB_SOURCES if(ENABLE_QT5) QT5_WRAP_CPP(Hyperion_FB_HEADERS_MOC ${Hyperion_FB_QT_HEADERS}) -else(ENABLE_QT5) +else() QT4_WRAP_CPP(Hyperion_FB_HEADERS_MOC ${Hyperion_FB_QT_HEADERS}) -endif(ENABLE_QT5) +endif() add_executable( ${PROJECT_NAME} ${Hyperion_FB_HEADERS} @@ -52,6 +52,11 @@ target_link_libraries( ${PROJECT_NAME} if(ENABLE_QT5) qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) -else(ENABLE_QT5) +else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) -endif(ENABLE_QT5) +endif() + +install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) +if (ENABLE_SYSTEM_INSTALL) + install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" ) +endif() diff --git a/src/hyperion-osx/CMakeLists.txt b/src/hyperion-osx/CMakeLists.txt index e7143042..de821562 100644 --- a/src/hyperion-osx/CMakeLists.txt +++ b/src/hyperion-osx/CMakeLists.txt @@ -7,9 +7,9 @@ project(hyperion-osx) # find QT if(ENABLE_QT5) find_package(Qt5Widgets REQUIRED) -else(ENABLE_QT5) +else() find_package(Qt4 REQUIRED QtCore QtGui QtNetwork ) -endif(ENABLE_QT5) +endif() include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver @@ -31,9 +31,9 @@ set(Hyperion_OSX_SOURCES if(ENABLE_QT5) QT5_WRAP_CPP(Hyperion_OSX_HEADERS_MOC ${Hyperion_OSX_QT_HEADERS}) -else(ENABLE_QT5) +else() QT4_WRAP_CPP(Hyperion_OSX_HEADERS_MOC ${Hyperion_OSX_QT_HEADERS}) -endif(ENABLE_QT5) +endif() add_executable( ${PROJECT_NAME} ${Hyperion_OSX_HEADERS} @@ -52,6 +52,9 @@ target_link_libraries( ${PROJECT_NAME} if(ENABLE_QT5) qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) -else(ENABLE_QT5) +else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) -endif(ENABLE_QT5) +endif() + +install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) + diff --git a/src/hyperion-remote/CMakeLists.txt b/src/hyperion-remote/CMakeLists.txt index 36ca8cc2..d78c5506 100644 --- a/src/hyperion-remote/CMakeLists.txt +++ b/src/hyperion-remote/CMakeLists.txt @@ -7,9 +7,9 @@ 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) +else() find_package(Qt4 REQUIRED QtCore QtGui QtNetwork) -endif(ENABLE_QT5) +endif() # 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 @@ -38,9 +38,12 @@ target_link_libraries(${PROJECT_NAME} if(ENABLE_QT5) qt5_use_modules(${PROJECT_NAME} Widgets Core Network) -else(ENABLE_QT5) +else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) -endif(ENABLE_QT5) +endif() -install ( TARGETS ${PROJECT_NAME} DESTINATION "${CMAKE_SOURCE_DIR}/deploy/bin" ) +install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) +if (ENABLE_SYSTEM_INSTALL) + install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" ) +endif() diff --git a/src/hyperion-v4l2/CMakeLists.txt b/src/hyperion-v4l2/CMakeLists.txt index ee1882a1..1bd54ce2 100644 --- a/src/hyperion-v4l2/CMakeLists.txt +++ b/src/hyperion-v4l2/CMakeLists.txt @@ -7,9 +7,9 @@ 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) +else() find_package(Qt4 REQUIRED QtCore QtGui QtNetwork) -endif(ENABLE_QT5) +endif() include_directories( @@ -33,9 +33,9 @@ set(Hyperion_V4L2_SOURCES ) if(ENABLE_QT5) QT5_WRAP_CPP(Hyperion_V4L2_MOC_SOURCES ${Hyperion_V4L2_QT_HEADERS}) -else(ENABLE_QT5) +else() QT4_WRAP_CPP(Hyperion_V4L2_MOC_SOURCES ${Hyperion_V4L2_QT_HEADERS}) -endif(ENABLE_QT5) +endif() add_executable(${PROJECT_NAME} ${Hyperion_V4L2_HEADERS} @@ -56,9 +56,11 @@ target_link_libraries(${PROJECT_NAME} if(ENABLE_QT5) qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) -else(ENABLE_QT5) +else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) -endif(ENABLE_QT5) +endif() - -install ( TARGETS ${PROJECT_NAME} DESTINATION "${CMAKE_SOURCE_DIR}/deploy/bin" ) +install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) +if (ENABLE_SYSTEM_INSTALL) + install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" ) +endif() diff --git a/src/hyperion-x11/CMakeLists.txt b/src/hyperion-x11/CMakeLists.txt index 69744f4f..87a66e12 100644 --- a/src/hyperion-x11/CMakeLists.txt +++ b/src/hyperion-x11/CMakeLists.txt @@ -7,9 +7,9 @@ project(hyperion-x11) # find QT if(ENABLE_QT5) find_package(Qt5Widgets REQUIRED) -else(ENABLE_QT5) +else() find_package(Qt4 REQUIRED QtCore QtGui QtNetwork) -endif(ENABLE_QT5) +endif() # Find X11 find_package(X11 REQUIRED) @@ -34,9 +34,9 @@ set(Hyperion_X11_SOURCES if(ENABLE_QT5) QT5_WRAP_CPP(Hyperion_X11_HEADERS_MOC ${Hyperion_X11_QT_HEADERS}) -else(ENABLE_QT5) +else() QT4_WRAP_CPP(Hyperion_X11_HEADERS_MOC ${Hyperion_X11_QT_HEADERS}) -endif(ENABLE_QT5) +endif() add_executable(${PROJECT_NAME} @@ -57,8 +57,11 @@ target_link_libraries(${PROJECT_NAME} if(ENABLE_QT5) qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) -else(ENABLE_QT5) +else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) -endif(ENABLE_QT5) +endif() -install ( TARGETS ${PROJECT_NAME} DESTINATION "${CMAKE_SOURCE_DIR}/deploy/bin" ) +install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) +if (ENABLE_SYSTEM_INSTALL) + install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" ) +endif() diff --git a/src/hyperiond/CMakeLists.txt b/src/hyperiond/CMakeLists.txt index 5aef74d2..ea059138 100644 --- a/src/hyperiond/CMakeLists.txt +++ b/src/hyperiond/CMakeLists.txt @@ -12,26 +12,34 @@ target_link_libraries(hyperiond if (ENABLE_DISPMANX) target_link_libraries(hyperiond dispmanx-grabber) -endif (ENABLE_DISPMANX) +endif () if (ENABLE_FB) target_link_libraries(hyperiond framebuffer-grabber) -endif (ENABLE_FB) +endif () if (ENABLE_OSX) target_link_libraries(hyperiond osx-grabber) -endif (ENABLE_OSX) +endif () if (ENABLE_V4L2) target_link_libraries(hyperiond v4l2-grabber) -endif (ENABLE_V4L2) +endif () if (ENABLE_AMLOGIC) target_link_libraries(hyperiond amlogic-grabber) -endif (ENABLE_AMLOGIC) +endif () if (ENABLE_PROTOBUF) target_link_libraries(hyperiond protoserver) -endif (ENABLE_PROTOBUF) +endif () -install ( TARGETS hyperiond DESTINATION "${CMAKE_SOURCE_DIR}/deploy/bin" ) +install ( TARGETS hyperiond DESTINATION "${DEPLOY_DIR}/bin" ) +install ( DIRECTORY ${CMAKE_SOURCE_DIR}/effects DESTINATION "${DEPLOY_DIR}/share/hyperion/" ) +install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "${DEPLOY_DIR}/share/hyperion/" ) + +if (ENABLE_SYSTEM_INSTALL) + install ( TARGETS hyperiond DESTINATION "bin" ) + install ( DIRECTORY ${CMAKE_SOURCE_DIR}/effects DESTINATION "share/hyperion/" ) + install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "share/hyperion/" ) +endif() From 4afd73095494feaf03f9c7089b60b8a9c7abb040 Mon Sep 17 00:00:00 2001 From: Funatiq Date: Sun, 22 May 2016 00:30:28 +0200 Subject: [PATCH 11/63] Better color adjustment (#637) Only apply color channel if color is dominant. Grey color independent from color channels. Linear increase of color channel from grey to maximum. Former-commit-id: cda9fca0084174877c45a7e9a867e6209ffe9e44 --- libsrc/hyperion/MultiColorAdjustment.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libsrc/hyperion/MultiColorAdjustment.cpp b/libsrc/hyperion/MultiColorAdjustment.cpp index 79ba1d21..cb8ec5ec 100644 --- a/libsrc/hyperion/MultiColorAdjustment.cpp +++ b/libsrc/hyperion/MultiColorAdjustment.cpp @@ -89,13 +89,15 @@ std::vector MultiColorAdjustment::applyAdjustment(const std::vector_rgbRedAdjustment.adjustmentR(color.red); - int RG = adjustment->_rgbRedAdjustment.adjustmentG(color.red); - int RB = adjustment->_rgbRedAdjustment.adjustmentB(color.red); - int GR = adjustment->_rgbGreenAdjustment.adjustmentR(color.green); + int RG = color.red > color.green ? adjustment->_rgbRedAdjustment.adjustmentG(color.red-color.green) : 0; + int RB = color.red > color.blue ? adjustment->_rgbRedAdjustment.adjustmentB(color.red-color.blue) : 0; + + int GR = color.green > color.red ? adjustment->_rgbGreenAdjustment.adjustmentR(color.green-color.red) : 0; int GG = adjustment->_rgbGreenAdjustment.adjustmentG(color.green); - int GB = adjustment->_rgbGreenAdjustment.adjustmentB(color.green); - int BR = adjustment->_rgbBlueAdjustment.adjustmentR(color.blue); - int BG = adjustment->_rgbBlueAdjustment.adjustmentG(color.blue); + int GB = color.green > color.blue ? adjustment->_rgbGreenAdjustment.adjustmentB(color.green-color.blue) : 0; + + int BR = color.blue > color.red ? adjustment->_rgbBlueAdjustment.adjustmentR(color.blue-color.red) : 0; + int BG = color.blue > color.green ? adjustment->_rgbBlueAdjustment.adjustmentG(color.blue-color.green) : 0; int BB = adjustment->_rgbBlueAdjustment.adjustmentB(color.blue); int ledR = RR + GR + BR; From 82f3fbdb203707d79d2ecd18308f140612179c35 Mon Sep 17 00:00:00 2001 From: Funatiq Date: Sun, 22 May 2016 00:30:53 +0200 Subject: [PATCH 12/63] Reorder Transform and Adjustment (#636) Change order from "Adjustment -> Transform" to "Transform -> Adjustment" Former-commit-id: 5b63d0bce98a80b5a2604e43772574ec6bbfd2a5 --- libsrc/hyperion/Hyperion.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 45a2d322..67687864 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -860,9 +860,9 @@ void Hyperion::update() // Apply the correction and the transform to each led and color-channel // Avoid applying correction, the same task is performed by adjustment // std::vector correctedColors = _raw2ledCorrection->applyCorrection(priorityInfo.ledColors); - std::vector adjustedColors = _raw2ledAdjustment->applyAdjustment(priorityInfo.ledColors); - std::vector transformColors =_raw2ledTransform->applyTransform(adjustedColors); - std::vector ledColors = _raw2ledTemperature->applyCorrection(transformColors); + std::vector transformColors =_raw2ledTransform->applyTransform(priorityInfo.ledColors); + std::vector adjustedColors = _raw2ledAdjustment->applyAdjustment(transformColors); + std::vector ledColors = _raw2ledTemperature->applyCorrection(adjustedColors); const std::vector& leds = _ledString.leds(); int i = 0; for (ColorRgb& color : ledColors) @@ -885,18 +885,14 @@ void Hyperion::update() break; case ORDER_GBR: { - uint8_t temp = color.red; - color.red = color.green; - color.green = color.blue; - color.blue = temp; + std::swap(color.red, color.green); + std::swap(color.green, color.blue); break; } case ORDER_BRG: { - uint8_t temp = color.red; - color.red = color.blue; - color.blue = color.green; - color.green = temp; + std::swap(color.red, color.blue); + std::swap(color.green, color.blue); break; } } From c179b86b8d8c5f3c6b02c2c2254ccaf3adde4680 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Sun, 22 May 2016 20:56:44 +1000 Subject: [PATCH 13/63] fix LedDeviceWs2812SPI to compile on gcc 4.6 (#643) * Removed -HUP so the default -TERM signal is sent instead. - hyperiond only listens for TERM and INT. HUP is often used to get an exe to reread its config Changed pgrep to add '-x' so it wont partial match on the exe name. - I have multiple instances with multiple hyperiond-instance1 names - this ensures the service script only kills the right process * reversing errant change to hyperion.systemd.sh * cleaned up a couple of compiler warnings * moved bitpair_to_byte initialiser to (hopefully) work with older GCC * compiler warning in udp driver removed some tabs in ws2812b.cpp * formatting - spaces to tabs Former-commit-id: 42cc7325177c9fcc3d1bd29cbfe72f02118d3233 --- libsrc/leddevice/LedDevicePiBlaster.cpp | 4 ++-- libsrc/leddevice/LedDeviceUdp.cpp | 2 +- libsrc/leddevice/LedDeviceWS2812b.cpp | 18 +++++++++--------- libsrc/leddevice/LedDeviceWs2812SPI.cpp | 9 ++++++++- libsrc/leddevice/LedDeviceWs2812SPI.h | 8 +------- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/libsrc/leddevice/LedDevicePiBlaster.cpp b/libsrc/leddevice/LedDevicePiBlaster.cpp index dc09fe15..ced94ed4 100644 --- a/libsrc/leddevice/LedDevicePiBlaster.cpp +++ b/libsrc/leddevice/LedDevicePiBlaster.cpp @@ -27,7 +27,7 @@ LedDevicePiBlaster::LedDevicePiBlaster(const std::string & deviceName, const Jso // { "gpio" : 4, "ledindex" : 0, "ledcolor" : "r" }, #define TABLE_SZ sizeof(_gpio_to_led)/sizeof(_gpio_to_led[0]) - for (int i=0; i < TABLE_SZ; i++ ) + for (unsigned i=0; i < TABLE_SZ; i++ ) { _gpio_to_led[i] = -1; _gpio_to_color[i] = 'z'; @@ -41,7 +41,7 @@ LedDevicePiBlaster::LedDevicePiBlaster(const std::string & deviceName, const Jso const std::string ledcolor = gpioMap.get("ledcolor","z").asString(); // printf ("got gpio %d ledindex %d color %c\n", gpio,ledindex, ledcolor[0]); // ignore missing/invalid settings - if ( (gpio >= 0) && (gpio < TABLE_SZ) && (ledindex >= 0) ){ + if ( (gpio >= 0) && (gpio < signed(TABLE_SZ)) && (ledindex >= 0) ){ _gpio_to_led[gpio] = ledindex; _gpio_to_color[gpio] = ledcolor[0]; // 1st char of string } else { diff --git a/libsrc/leddevice/LedDeviceUdp.cpp b/libsrc/leddevice/LedDeviceUdp.cpp index 1fc67647..48c2a8d7 100644 --- a/libsrc/leddevice/LedDeviceUdp.cpp +++ b/libsrc/leddevice/LedDeviceUdp.cpp @@ -17,7 +17,7 @@ struct addrinfo hints, *servinfo, *p; //char udpbuffer[1024]; int sockfd; int ledprotocol; -int leds_per_pkt; +unsigned leds_per_pkt; int update_number; int fragment_number; diff --git a/libsrc/leddevice/LedDeviceWS2812b.cpp b/libsrc/leddevice/LedDeviceWS2812b.cpp index 67a10947..c012639b 100644 --- a/libsrc/leddevice/LedDeviceWS2812b.cpp +++ b/libsrc/leddevice/LedDeviceWS2812b.cpp @@ -666,15 +666,15 @@ void LedDeviceWS2812b::initHardware() // Allocate memory for the DMA control block & data to be sent // --------------------------------------------------------------- virtbase = (uint8_t *) mmap( - NULL, // Address - NUM_PAGES * PAGE_SIZE, // Length - PROT_READ | PROT_WRITE, // Protection - MAP_SHARED | // Shared - MAP_ANONYMOUS | // Not file-based, init contents to 0 - MAP_NORESERVE | // Don't reserve swap space - MAP_LOCKED, // Lock in RAM (don't swap) - -1, // File descriptor - 0); // Offset + NULL, // Address + NUM_PAGES * PAGE_SIZE, // Length + PROT_READ | PROT_WRITE, // Protection + MAP_SHARED | // Shared + MAP_ANONYMOUS | // Not file-based, init contents to 0 + MAP_NORESERVE | // Don't reserve swap space + MAP_LOCKED, // Lock in RAM (don't swap) + -1, // File descriptor + 0); // Offset if (virtbase == MAP_FAILED) { diff --git a/libsrc/leddevice/LedDeviceWs2812SPI.cpp b/libsrc/leddevice/LedDeviceWs2812SPI.cpp index 7b915595..b9dc8a3d 100644 --- a/libsrc/leddevice/LedDeviceWs2812SPI.cpp +++ b/libsrc/leddevice/LedDeviceWs2812SPI.cpp @@ -13,7 +13,14 @@ LedDeviceWs2812SPI::LedDeviceWs2812SPI(const std::string& outputDevice, const unsigned baudrate) : LedSpiDevice(outputDevice, baudrate, 0), - mLedCount(0) + mLedCount(0), + bitpair_to_byte { + 0b10001000, + 0b10001100, + 0b11001000, + 0b11001100, + } + { // empty } diff --git a/libsrc/leddevice/LedDeviceWs2812SPI.h b/libsrc/leddevice/LedDeviceWs2812SPI.h index e82d9134..408e2b9f 100644 --- a/libsrc/leddevice/LedDeviceWs2812SPI.h +++ b/libsrc/leddevice/LedDeviceWs2812SPI.h @@ -42,11 +42,5 @@ private: size_t mLedCount; std::vector _spiBuffer; - uint8_t bitpair_to_byte[4] = { - 0b10001000, - 0b10001100, - 0b11001000, - 0b11001100, - }; - + uint8_t bitpair_to_byte[4]; }; From e944ce46cdd2040b1c639ab3ef92462de8170230 Mon Sep 17 00:00:00 2001 From: redPanther Date: Sun, 22 May 2016 13:00:06 +0200 Subject: [PATCH 14/63] build optimization fix (#644) * implement make install set CMAKE_INSTALL_PREFIX e.g. to /opt to install to /opt/hyperion set ENABLE_SYSTEM_INSTALL to ON to activate installation after compiling use make install or make install/strip (for performance/size optimized binaries - compile in Release to get best performance) * cleanup cmake files use cmake -DINSTALL_PREFIX=/opt/hyperion .. to install all files to hyperion or cmake -DINSTALL_PREFIX=/usr/ to install to usr. install folders are linux standard. bin go to bin folder and additionals (effects) go to share/hyperion * add uninstall target - be patient with that, this will remove files from your system install service files to share/hyperion - if you want to use them you have to make a symlink to your location of service files * optimize build release script install service files into hyperion share folder (services not activated, this must be done by distribution package script) initial support of cmake option -DPLATFORM= option. This selects platform specific cmake flags. no need for -DENABLE_... options (unless you want some special things) automatic detect for apple build * update submodule * fix cmake error when no platform is given * initial support for deb,rpm and tgz packages - no usefull content atm! Former-commit-id: 7d7ca8685c632bb35fbe607b2ff463ef589f72e8 --- CMakeLists.txt | 11 +++++++---- cmake/packages.cmake | 3 +++ 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 cmake/packages.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index b789b745..2bb70d16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ cmake_minimum_required(VERSION 2.8) #set(CMAKE_TOOLCHAIN_FILE /opt/raspberrypi/Toolchain-RaspberryPi.cmake) + SET ( DEFAULT_AMLOGIC OFF ) SET ( DEFAULT_DISPMANX OFF ) SET ( DEFAULT_FB OFF ) @@ -17,16 +18,16 @@ SET ( DEFAULT_WS281XPWM OFF ) if (APPLE) SET ( DEFAULT_OSX ON ) else () - if ( ${PLATFORM} STREQUAL "rpi" ) + if ( "${PLATFORM}" STREQUAL "rpi" ) SET ( DEFAULT_DISPMANX ON ) SET ( DEFAULT_WS2812BPWM ON ) SET ( DEFAULT_WS281XPWM ON ) - elseif ( ${PLATFORM} STREQUAL "wetek" ) + elseif ( "${PLATFORM}" STREQUAL "wetek" ) SET ( DEFAULT_AMLOGIC ON ) SET ( DEFAULT_FB ON ) - elseif ( ${PLATFORM} STREQUAL "x86" ) + elseif ( "${PLATFORM}" STREQUAL "x86" ) SET ( DEFAULT_X11 ON ) - elseif ( ${PLATFORM} STREQUAL "imx6" ) + elseif ( "${PLATFORM}" STREQUAL "imx6" ) SET ( DEFAULT_FB ON ) endif() endif () @@ -189,3 +190,5 @@ configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${ add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) +# enable make package - no code after this line ! +include (${CMAKE_CURRENT_SOURCE_DIR}/cmake/packages.cmake) diff --git a/cmake/packages.cmake b/cmake/packages.cmake new file mode 100644 index 00000000..17b21485 --- /dev/null +++ b/cmake/packages.cmake @@ -0,0 +1,3 @@ +SET(CPACK_GENERATOR "DEB" "RPM" "TGZ" ) +SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "hyperion team") +include (CPack) From f8b724f9f99a648aa35c4436f18628ef5727cbe5 Mon Sep 17 00:00:00 2001 From: Funatiq Date: Mon, 23 May 2016 00:00:48 +0200 Subject: [PATCH 15/63] Minimum luminance for backlight in dark scenes (#646) * Include miminum luminance * Add luminance minimum * Add luminance minimum * fixed missing ; * Add luminance minimum * Add luminance minimum check Check if luminance mimimum is other than default * Add luminance minimum * Add luminance minimum * Add luminance minimum * Add luminance minimum * Add luminance minimum * Safe luminance calculation Former-commit-id: 35a762b18b473a333155acba7a00894204400076 --- include/utils/HslTransform.h | 18 +++++++++++++- libsrc/hyperion/Hyperion.cpp | 3 ++- libsrc/hyperion/hyperion.schema.json | 5 ++++ libsrc/jsonserver/JsonClientConnection.cpp | 6 +++++ .../jsonserver/schema/schema-transform.json | 5 ++++ libsrc/utils/HslTransform.cpp | 24 +++++++++++++++---- src/hyperion-remote/JsonConnection.cpp | 8 ++++++- src/hyperion-remote/JsonConnection.h | 2 ++ src/hyperion-remote/hyperion-remote.cpp | 8 +++++-- 9 files changed, 69 insertions(+), 10 deletions(-) diff --git a/include/utils/HslTransform.h b/include/utils/HslTransform.h index f2151e65..3fdc480a 100644 --- a/include/utils/HslTransform.h +++ b/include/utils/HslTransform.h @@ -20,7 +20,7 @@ public: /// @param saturationGain The used saturation gain /// @param luminanceGain The used luminance gain /// - HslTransform(double saturationGain, double luminanceGain); + HslTransform(double saturationGain, double luminanceGain, double luminanceMinimum); /// /// Destructor @@ -55,6 +55,20 @@ public: /// double getLuminanceGain() const; + /// + /// Updates the luminance minimum + /// + /// @param luminanceMinimum New luminance minimum + /// + void setLuminanceMinimum(double luminanceMinimum); + + /// + /// Returns the luminance minimum + /// + /// @return The current luminance minimum + /// + double getLuminanceMinimum() const; + /// /// Apply the transform the the given RGB values. /// @@ -97,4 +111,6 @@ private: double _saturationGain; /// The luminance gain double _luminanceGain; + /// The luminance minimum + double _luminanceMinimum }; diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 67687864..538772a9 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -452,8 +452,9 @@ HslTransform * Hyperion::createHslTransform(const Json::Value & hslConfig) { const double saturationGain = hslConfig.get("saturationGain", 1.0).asDouble(); const double luminanceGain = hslConfig.get("luminanceGain", 1.0).asDouble(); + const double luminanceMinimum = hslConfig.get("luminanceMinimum", 0.0).asDouble(); - return new HslTransform(saturationGain, luminanceGain); + return new HslTransform(saturationGain, luminanceGain, luminanceMinimum); } RgbChannelTransform* Hyperion::createRgbChannelTransform(const Json::Value& colorConfig) diff --git a/libsrc/hyperion/hyperion.schema.json b/libsrc/hyperion/hyperion.schema.json index f30e1a27..aded2acf 100644 --- a/libsrc/hyperion/hyperion.schema.json +++ b/libsrc/hyperion/hyperion.schema.json @@ -68,6 +68,11 @@ "type" : "number", "required" : false, "minimum" : 0.0 + }, + "luminanceMinimum" : { + "type" : "number", + "required" : false, + "minimum" : 0.0 } }, "additionalProperties" : false diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 6d6bbaab..b6471355 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -455,6 +455,7 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &) transform["valueGain"] = colorTransform->_hsvTransform.getValueGain(); transform["saturationLGain"] = colorTransform->_hslTransform.getSaturationGain(); transform["luminanceGain"] = colorTransform->_hslTransform.getLuminanceGain(); + transform["luminanceMinimum"] = colorTransform->_hslTransform.getLuminanceMinimum(); Json::Value & threshold = transform["threshold"]; threshold.append(colorTransform->_rgbRedTransform.getThreshold()); @@ -605,6 +606,11 @@ void JsonClientConnection::handleTransformCommand(const Json::Value &message) colorTransform->_hslTransform.setLuminanceGain(transform["luminanceGain"].asDouble()); } + if (transform.isMember("luminanceMinimum")) + { + colorTransform->_hslTransform.setLuminanceMinimum(transform["luminanceMinimum"].asDouble()); + } + if (transform.isMember("threshold")) { const Json::Value & values = transform["threshold"]; diff --git a/libsrc/jsonserver/schema/schema-transform.json b/libsrc/jsonserver/schema/schema-transform.json index 8b194eab..e0ec7394 100644 --- a/libsrc/jsonserver/schema/schema-transform.json +++ b/libsrc/jsonserver/schema/schema-transform.json @@ -35,6 +35,11 @@ "required" : false, "minimum" : 0.0 }, + "luminanceMinimum" : { + "type" : "number", + "required" : false, + "minimum" : 0.0 + }, "threshold": { "type": "array", "required": false, diff --git a/libsrc/utils/HslTransform.cpp b/libsrc/utils/HslTransform.cpp index 09056bb2..8d391adf 100644 --- a/libsrc/utils/HslTransform.cpp +++ b/libsrc/utils/HslTransform.cpp @@ -4,13 +4,15 @@ HslTransform::HslTransform() : _saturationGain(1.0), - _luminanceGain(1.0) + _luminanceGain(1.0), + _luminanceMinimum(0.0) { } -HslTransform::HslTransform(double saturationGain, double luminanceGain) : +HslTransform::HslTransform(double saturationGain, double luminanceGain, double luminanceMinimum) : _saturationGain(saturationGain), - _luminanceGain(luminanceGain) + _luminanceGain(luminanceGain), + _luminanceMinimum(luminanceMinimum) { } @@ -38,9 +40,19 @@ double HslTransform::getLuminanceGain() const return _luminanceGain; } +void HslTransform::setLuminanceMinimum(double luminanceMinimum) +{ + _luminanceMinimum = luminanceMinimum; +} + +double HslTransform::getLuminanceMinimum() const +{ + return _luminanceMinimum; +} + void HslTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue) const { - if (_saturationGain != 1.0 || _luminanceGain != 1.0) + if (_saturationGain != 1.0 || _luminanceGain != 1.0 || _luminanceMinimum != 0.0) { uint16_t hue; float saturation, luminance; @@ -53,9 +65,11 @@ void HslTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue) con saturation = s; float l = luminance * _luminanceGain; + if (l < _luminanceMinimum) + l = _luminanceMinimum; if (l > 1.0f) luminance = 1.0f; - else + else luminance = l; hsl2rgb(hue, saturation, luminance, red, green, blue); diff --git a/src/hyperion-remote/JsonConnection.cpp b/src/hyperion-remote/JsonConnection.cpp index 16438b7e..e555040b 100644 --- a/src/hyperion-remote/JsonConnection.cpp +++ b/src/hyperion-remote/JsonConnection.cpp @@ -192,7 +192,7 @@ void JsonConnection::clearAll() parseReply(reply); } -void JsonConnection::setTransform(std::string * transformId, double * saturation, double * value, double * saturationL, double * luminance, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel) +void JsonConnection::setTransform(std::string * transformId, double * saturation, double * value, double * saturationL, double * luminance, double * luminanceMin, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel) { std::cout << "Set color transforms" << std::endl; @@ -225,6 +225,12 @@ void JsonConnection::setTransform(std::string * transformId, double * saturation { transform["luminanceGain"] = *luminance; } + + if (luminanceMin != nullptr) + { + transform["luminanceMinimum"] = *luminanceMin; + } + if (threshold != nullptr) { Json::Value & v = transform["threshold"]; diff --git a/src/hyperion-remote/JsonConnection.h b/src/hyperion-remote/JsonConnection.h index d71ff3a3..2638c256 100644 --- a/src/hyperion-remote/JsonConnection.h +++ b/src/hyperion-remote/JsonConnection.h @@ -93,6 +93,7 @@ public: /// @param value The HSV value gain /// @param saturationL The HSL saturation gain /// @param luminance The HSL luminance gain + /// @param luminanceMin The HSL luminance minimum /// @param threshold The threshold /// @param gamma The gamma value /// @param blacklevel The blacklevel @@ -104,6 +105,7 @@ public: double * value, double * saturationL, double * luminance, + double * luminanceMin, ColorTransformValues * threshold, ColorTransformValues * gamma, ColorTransformValues * blacklevel, diff --git a/src/hyperion-remote/hyperion-remote.cpp b/src/hyperion-remote/hyperion-remote.cpp index c29c7eed..21e0fba7 100644 --- a/src/hyperion-remote/hyperion-remote.cpp +++ b/src/hyperion-remote/hyperion-remote.cpp @@ -71,6 +71,7 @@ int main(int argc, char * argv[]) DoubleParameter & argValue = parameters.add ('v', "value" , "!DEPRECATED! Will be removed soon! Set the HSV value gain of the leds"); DoubleParameter & argSaturationL = parameters.add ('u', "saturationL", "Set the HSL saturation gain of the leds"); DoubleParameter & argLuminance = parameters.add ('m', "luminance" , "Set the HSL luminance gain of the leds"); + DoubleParameter & argLuminanceMin = parameters.add ('n', "luminanceMin" , "Set the HSL luminance minimum of the leds (backlight)"); TransformParameter & argGamma = parameters.add('g', "gamma" , "Set the gamma of the leds (requires 3 space seperated values)"); TransformParameter & argThreshold = parameters.add('t', "threshold" , "Set the threshold of the leds (requires 3 space seperated values between 0.0 and 1.0)"); TransformParameter & argBlacklevel = parameters.add('b', "blacklevel", "!DEPRECATED! Will be removed soon! Set the blacklevel of the leds (requires 3 space seperated values which are normally between 0.0 and 1.0)"); @@ -103,7 +104,7 @@ int main(int argc, char * argv[]) } // check if at least one of the available color transforms is set - bool colorTransform = argSaturation.isSet() || argValue.isSet() || argSaturationL.isSet() || argLuminance.isSet() || argThreshold.isSet() || argGamma.isSet() || argBlacklevel.isSet() || argWhitelevel.isSet(); + bool colorTransform = argSaturation.isSet() || argValue.isSet() || argSaturationL.isSet() || argLuminance.isSet() || argLuminanceMin.isSet() || argThreshold.isSet() || argGamma.isSet() || argBlacklevel.isSet() || argWhitelevel.isSet(); bool colorAdjust = argRAdjust.isSet() || argGAdjust.isSet() || argBAdjust.isSet(); bool colorModding = colorTransform || colorAdjust || argCorrection.isSet() || argTemperature.isSet(); @@ -124,6 +125,7 @@ int main(int argc, char * argv[]) std::cerr << " " << argValue.usageLine() << std::endl; std::cerr << " " << argSaturationL.usageLine() << std::endl; std::cerr << " " << argLuminance.usageLine() << std::endl; + std::cerr << " " << argLuminanceMin.usageLine() << std::endl; std::cerr << " " << argThreshold.usageLine() << std::endl; std::cerr << " " << argGamma.usageLine() << std::endl; std::cerr << " " << argBlacklevel.usageLine() << std::endl; @@ -216,7 +218,7 @@ int main(int argc, char * argv[]) if (colorTransform) { std::string transId; - double saturation, value, saturationL, luminance; + double saturation, value, saturationL, luminance, luminanceMin; ColorTransformValues threshold, gamma, blacklevel, whitelevel; if (argId.isSet()) transId = argId.getValue(); @@ -224,6 +226,7 @@ int main(int argc, char * argv[]) if (argValue.isSet()) value = argValue.getValue(); if (argSaturationL.isSet()) saturationL = argSaturationL.getValue(); if (argLuminance.isSet()) luminance = argLuminance.getValue(); + if (argLuminanceMin.isSet()) luminanceMin = argLuminanceMin.getValue(); if (argThreshold.isSet()) threshold = argThreshold.getValue(); if (argGamma.isSet()) gamma = argGamma.getValue(); if (argBlacklevel.isSet()) blacklevel = argBlacklevel.getValue(); @@ -235,6 +238,7 @@ int main(int argc, char * argv[]) argValue.isSet() ? &value : nullptr, argSaturationL.isSet() ? &saturationL : nullptr, argLuminance.isSet() ? &luminance : nullptr, + argLuminanceMin.isSet() ? &luminanceMin : nullptr, argThreshold.isSet() ? &threshold : nullptr, argGamma.isSet() ? &gamma : nullptr, argBlacklevel.isSet() ? &blacklevel : nullptr, From 46a3edd1ec357a664e321a5fde8ef3a563a1e59c Mon Sep 17 00:00:00 2001 From: brindosch Date: Mon, 23 May 2016 00:25:57 +0200 Subject: [PATCH 16/63] fix typo Former-commit-id: ed5661d3bb6c4dddbe808383e4e1f717c1aa59aa --- include/utils/HslTransform.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/utils/HslTransform.h b/include/utils/HslTransform.h index 3fdc480a..3b67ad7b 100644 --- a/include/utils/HslTransform.h +++ b/include/utils/HslTransform.h @@ -112,5 +112,5 @@ private: /// The luminance gain double _luminanceGain; /// The luminance minimum - double _luminanceMinimum + double _luminanceMinimum; }; From 84a912554264792f15ac942bc8e509d0a3088563 Mon Sep 17 00:00:00 2001 From: brindosch Date: Mon, 23 May 2016 11:01:52 +0200 Subject: [PATCH 17/63] revert priority change Former-commit-id: 4c91a9710e8ea61acd8284b07868cb2e4bae0bd2 --- src/hyperiond/hyperiond.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index de91846c..cd427175 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -129,8 +129,8 @@ 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 = (duration_ms != 0) ? 0 : effectConfig.get("priority",700).asInt(); - const int bootcolor_priority = (priority > 700) ? priority+1 : 700; + const int priority = (duration_ms != 0) ? 0 : effectConfig.get("priority",990).asInt(); + const int bootcolor_priority = (priority > 990) ? priority+1 : 990; // clear the leds ColorRgb boot_color = ColorRgb::BLACK; From 409ef383f3ed37888ee44c7393f405739abe4e5a Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Tue, 24 May 2016 19:55:50 +0200 Subject: [PATCH 18/63] XRender support for X11 Grabber (#649) * Update X11Grabber.h * Update X11Grabber.cpp * Update CMakeLists.txt * Update hyperion-x11.cpp * Update X11Wrapper.cpp * Update X11Wrapper.h Former-commit-id: d2f7cb0e22248a0c2963bf53728f2e0d7bb9dee1 --- include/grabber/X11Grabber.h | 13 +++- libsrc/grabber/x11/X11Grabber.cpp | 107 ++++++++++++++++++++++++------ src/hyperion-x11/CMakeLists.txt | 1 + src/hyperion-x11/X11Wrapper.cpp | 4 +- src/hyperion-x11/X11Wrapper.h | 2 +- src/hyperion-x11/hyperion-x11.cpp | 3 + 6 files changed, 105 insertions(+), 25 deletions(-) diff --git a/include/grabber/X11Grabber.h b/include/grabber/X11Grabber.h index b35031cf..d8e4783c 100644 --- a/include/grabber/X11Grabber.h +++ b/include/grabber/X11Grabber.h @@ -6,7 +6,6 @@ // X11 includes #include - #include #include #include @@ -16,7 +15,7 @@ class X11Grabber { public: - X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation); + X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation); virtual ~X11Grabber(); @@ -28,7 +27,8 @@ public: private: ImageResampler _imageResampler; - + + bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable; int _cropLeft; int _cropRight; int _cropTop; @@ -41,6 +41,13 @@ private: Display* _x11Display; Window _window; XWindowAttributes _windowAttr; + + Pixmap _pixmap; + XRenderPictFormat* _srcFormat; + XRenderPictFormat* _dstFormat; + XRenderPictureAttributes _pictAttr; + Picture _srcPicture; + Picture _dstPicture; unsigned _screenWidth; unsigned _screenHeight; diff --git a/libsrc/grabber/x11/X11Grabber.cpp b/libsrc/grabber/x11/X11Grabber.cpp index 5b86d86c..1e3e0b4c 100644 --- a/libsrc/grabber/x11/X11Grabber.cpp +++ b/libsrc/grabber/x11/X11Grabber.cpp @@ -2,19 +2,22 @@ #include #include -// X11 includes -#include - // X11Grabber includes #include -X11Grabber::X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) : +X11Grabber::X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) : _imageResampler(), + _useXGetImage(useXGetImage), _cropLeft(cropLeft), _cropRight(cropRight), _cropTop(cropTop), _cropBottom(cropBottom), _x11Display(nullptr), + _pixmap(None), + _srcFormat(nullptr), + _dstFormat(nullptr), + _srcPicture(None), + _dstPicture(None), _screenWidth(0), _screenHeight(0), _croppedWidth(0), @@ -23,7 +26,9 @@ X11Grabber::X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom, { _imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation); _imageResampler.setVerticalPixelDecimation(verticalPixelDecimation); - _imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XShmGetImage + _imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XShmGetImage or XGetImage + memset(&_pictAttr, 0, sizeof(_pictAttr)); + _pictAttr.repeat = RepeatNone; } X11Grabber::~X11Grabber() @@ -38,23 +43,45 @@ X11Grabber::~X11Grabber() void X11Grabber::freeResources() { // Cleanup allocated resources of the X11 grab - XShmDetach(_x11Display, &_shminfo); XDestroyImage(_xImage); - shmdt(_shminfo.shmaddr); - shmctl(_shminfo.shmid, IPC_RMID, 0); + if(_XShmAvailable && !_useXGetImage) { + XShmDetach(_x11Display, &_shminfo); + shmdt(_shminfo.shmaddr); + shmctl(_shminfo.shmid, IPC_RMID, 0); + } + if (_XRenderAvailable && !_useXGetImage) { + XRenderFreePicture(_x11Display, _srcPicture); + XRenderFreePicture(_x11Display, _dstPicture); + XFreePixmap(_x11Display, _pixmap); + } } void X11Grabber::setupResources() { - _xImage = XShmCreateImage(_x11Display, _windowAttr.visual, - _windowAttr.depth, ZPixmap, NULL, &_shminfo, - _croppedWidth, _croppedHeight); + if(_XShmAvailable && !_useXGetImage) { + _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); + _xImage->data = (char*)shmat(_shminfo.shmid,0,0); + _shminfo.shmaddr = _xImage->data; + _shminfo.readOnly = False; - _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); + XShmAttach(_x11Display, &_shminfo); + } + if (_XRenderAvailable && !_useXGetImage) { + if(_XShmPixmapAvailable) { + _pixmap = XShmCreatePixmap(_x11Display, _window, _xImage->data, &_shminfo, _croppedWidth, _croppedHeight, _windowAttr.depth); + } else { + _pixmap = XCreatePixmap(_x11Display, _window, _croppedWidth, _croppedHeight, _windowAttr.depth); + } + _srcFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual); + _dstFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual); + _srcPicture = XRenderCreatePicture(_x11Display, _window, _srcFormat, CPRepeat, &_pictAttr); + _dstPicture = XRenderCreatePicture(_x11Display, _pixmap, _dstFormat, CPRepeat, &_pictAttr); + XRenderSetPictureFilter(_x11Display, _srcPicture, "bilinear", NULL, 0); + } } bool X11Grabber::Setup() @@ -72,14 +99,48 @@ bool X11Grabber::Setup() _window = DefaultRootWindow(_x11Display); + int dummy, pixmaps_supported; + + _XRenderAvailable = XRenderQueryExtension(_x11Display, &dummy, &dummy); + _XShmAvailable = XShmQueryExtension(_x11Display); + XShmQueryVersion(_x11Display, &dummy, &dummy, &pixmaps_supported); + _XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_x11Display) == ZPixmap; + return true; - } +} Image & X11Grabber::grab() { - updateScreenDimensions(); + if (_XRenderAvailable && !_useXGetImage) { + XRenderComposite( _x11Display, // *dpy, + PictOpSrc, // op, + _srcPicture, // src + None, // mask + _dstPicture, // dst + _cropLeft, // src_x + _cropTop, // src_y + 0, // mask_x + 0, // mask_y + 0, // dst_x + 0, // dst_y + _croppedWidth, // width + _croppedHeight); // height + + XSync(_x11Display, False); + + if (_XShmAvailable) { + XShmGetImage(_x11Display, _pixmap, _xImage, 0, 0, AllPlanes); + } else { + _xImage = XGetImage(_x11Display, _pixmap, 0, 0, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap); + } + } else { + if (_XShmAvailable && !_useXGetImage) { + XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes); + } else { + _xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap); + } + } - XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, 0x00FFFFFF); if (_xImage == nullptr) { std::cerr << "X11GRABBER ERROR: Grab failed" << std::endl; @@ -125,6 +186,14 @@ int X11Grabber::updateScreenDimensions() _croppedHeight = _screenHeight - _cropTop - _cropBottom; else _croppedHeight = _screenHeight; + + std::cout << "X11GRABBER INFO: Using "; + + if (_XRenderAvailable && !_useXGetImage) { + std::cout << "XRender for grabbing" << std::endl; + } else { + std::cout << "XGetImage for grabbing" << std::endl; + } setupResources(); diff --git a/src/hyperion-x11/CMakeLists.txt b/src/hyperion-x11/CMakeLists.txt index 87a66e12..a3a17d7c 100644 --- a/src/hyperion-x11/CMakeLists.txt +++ b/src/hyperion-x11/CMakeLists.txt @@ -52,6 +52,7 @@ target_link_libraries(${PROJECT_NAME} protoserver x11-grabber ${X11_LIBRARIES} + ${X11_Xrender_LIB} pthread ) diff --git a/src/hyperion-x11/X11Wrapper.cpp b/src/hyperion-x11/X11Wrapper.cpp index a0489fdf..8aa8fb49 100644 --- a/src/hyperion-x11/X11Wrapper.cpp +++ b/src/hyperion-x11/X11Wrapper.cpp @@ -2,9 +2,9 @@ // Hyperion-X11 includes #include "X11Wrapper.h" -X11Wrapper::X11Wrapper(int grabInterval, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) : +X11Wrapper::X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) : _timer(this), - _grabber(cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation) + _grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation) { _timer.setSingleShot(false); _timer.setInterval(grabInterval); diff --git a/src/hyperion-x11/X11Wrapper.h b/src/hyperion-x11/X11Wrapper.h index 18fab407..26ccc796 100644 --- a/src/hyperion-x11/X11Wrapper.h +++ b/src/hyperion-x11/X11Wrapper.h @@ -9,7 +9,7 @@ class X11Wrapper : public QObject { Q_OBJECT public: - X11Wrapper(int grabInterval, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation); + X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation); const Image & getScreenshot(); diff --git a/src/hyperion-x11/hyperion-x11.cpp b/src/hyperion-x11/hyperion-x11.cpp index 776b3326..b7be000d 100644 --- a/src/hyperion-x11/hyperion-x11.cpp +++ b/src/hyperion-x11/hyperion-x11.cpp @@ -36,6 +36,7 @@ int main(int argc, char ** argv) ParameterSet & parameters = optionParser.getParameters(); IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default: 10]"); + SwitchParameter<> & argXGetImage = parameters.add> ('x', "xgetimage", "Use XGetImage instead of XRender"); IntParameter & argCropWidth = parameters.add (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]"); IntParameter & argCropHeight = parameters.add (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]"); IntParameter & argCropLeft = parameters.add (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)"); @@ -75,8 +76,10 @@ int main(int argc, char ** argv) // Create the X11 grabbing stuff int grabInterval = 1000 / argFps.getValue(); + bool useXGetImage = argXGetImage.isSet(); X11Wrapper x11Wrapper( grabInterval, + useXGetImage, argCropLeft.getValue(), argCropRight.getValue(), argCropTop.getValue(), From 0940872870a98484669157d383134402b1be1bd4 Mon Sep 17 00:00:00 2001 From: redPanther Date: Tue, 24 May 2016 19:56:43 +0200 Subject: [PATCH 19/63] create debian packages / multiple configs (#650) * implement make install set CMAKE_INSTALL_PREFIX e.g. to /opt to install to /opt/hyperion set ENABLE_SYSTEM_INSTALL to ON to activate installation after compiling use make install or make install/strip (for performance/size optimized binaries - compile in Release to get best performance) * cleanup cmake files use cmake -DINSTALL_PREFIX=/opt/hyperion .. to install all files to hyperion or cmake -DINSTALL_PREFIX=/usr/ to install to usr. install folders are linux standard. bin go to bin folder and additionals (effects) go to share/hyperion * add uninstall target - be patient with that, this will remove files from your system install service files to share/hyperion - if you want to use them you have to make a symlink to your location of service files * optimize build release script install service files into hyperion share folder (services not activated, this must be done by distribution package script) initial support of cmake option -DPLATFORM= option. This selects platform specific cmake flags. no need for -DENABLE_... options (unless you want some special things) automatic detect for apple build * update submodule * fix cmake error when no platform is given * initial support for deb,rpm and tgz packages - no usefull content atm! * make packeages contain usefull stuff * add license make packes more functional. package specific install missing yet * implement debian postinstall * disable rpm generation until it has a working state * add hypercon compat * add posibility for multiple config files. first one found is taken Former-commit-id: 1c2669961da98fd05a97359e75f1d6d68e126715 --- CMakeLists.txt | 19 +++--- LICENSE | 21 +++++++ bin/create_all_releases.sh | 17 +++--- bin/service/hyperion.init.sh | 2 +- bin/service/hyperion.initctl.sh | 2 +- bin/service/hyperion.systemd.sh | 2 +- .../Toolchain-imx6.cmake | 0 .../Toolchain-rpi.cmake | 0 .../Toolchain-x32.cmake | 0 cmake/debian/postinst | 60 +++++++++++++++++++ cmake/packages.cmake | 35 ++++++++++- cmake/rpm/postinst | 57 ++++++++++++++++++ config/hyperion_x86.config.json | 2 +- src/hyperion-aml/CMakeLists.txt | 5 +- src/hyperion-dispmanx/CMakeLists.txt | 6 +- src/hyperion-framebuffer/CMakeLists.txt | 5 +- src/hyperion-osx/CMakeLists.txt | 2 +- src/hyperion-remote/CMakeLists.txt | 5 +- src/hyperion-v4l2/CMakeLists.txt | 5 +- src/hyperion-x11/CMakeLists.txt | 5 +- src/hyperiond/CMakeLists.txt | 13 ++-- src/hyperiond/hyperiond.cpp | 13 +++- 22 files changed, 217 insertions(+), 59 deletions(-) create mode 100644 LICENSE rename Toolchain-imx6.cmake => cmake/Toolchain-imx6.cmake (100%) rename Toolchain-rpi.cmake => cmake/Toolchain-rpi.cmake (100%) rename Toolchain-x32.cmake => cmake/Toolchain-x32.cmake (100%) create mode 100644 cmake/debian/postinst create mode 100644 cmake/rpm/postinst diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bb70d16..d2f14ab4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # Define the main-project name -project(hyperiond) +project(hyperion) # define the minimum cmake version (as required by cmake) cmake_minimum_required(VERSION 2.8) @@ -12,6 +12,7 @@ SET ( DEFAULT_DISPMANX OFF ) SET ( DEFAULT_FB OFF ) SET ( DEFAULT_OSX OFF ) SET ( DEFAULT_X11 OFF ) +SET ( DEFAULT_SPIDEV OFF ) SET ( DEFAULT_WS2812BPWM OFF ) SET ( DEFAULT_WS281XPWM OFF ) @@ -19,14 +20,19 @@ if (APPLE) SET ( DEFAULT_OSX ON ) else () if ( "${PLATFORM}" STREQUAL "rpi" ) + SET ( DEFAULT_DISPMANX ON ) + SET ( DEFAULT_SPIDEV ON ) + elseif ( "${PLATFORM}" STREQUAL "rpi-pwm" ) SET ( DEFAULT_DISPMANX ON ) SET ( DEFAULT_WS2812BPWM ON ) SET ( DEFAULT_WS281XPWM ON ) + SET ( DEFAULT_SPIDEV ON ) elseif ( "${PLATFORM}" STREQUAL "wetek" ) SET ( DEFAULT_AMLOGIC ON ) SET ( DEFAULT_FB ON ) elseif ( "${PLATFORM}" STREQUAL "x86" ) SET ( DEFAULT_X11 ON ) + SET ( DEFAULT_FB ON ) elseif ( "${PLATFORM}" STREQUAL "imx6" ) SET ( DEFAULT_FB ON ) endif() @@ -48,7 +54,7 @@ message(STATUS "ENABLE_OSX = " ${ENABLE_OSX}) option(ENABLE_PROTOBUF "Enable PROTOBUF server" ON) message(STATUS "ENABLE_PROTOBUF = " ${ENABLE_PROTOBUF}) -option(ENABLE_SPIDEV "Enable the SPIDEV device" ON) +option(ENABLE_SPIDEV "Enable the SPIDEV device" ${DEFAULT_SPIDEV} ) message(STATUS "ENABLE_SPIDEV = " ${ENABLE_SPIDEV}) option(ENABLE_TINKERFORGE "Enable the TINKERFORGE device" ON) @@ -88,13 +94,6 @@ if(ENABLE_OSX AND ENABLE_DISPMANX) message(FATAL_ERROR "dispmanx grabber and osx grabber cannot be used at the same time") endif() -if (DEFINED INSTALL_PREFIX) - SET( ENABLE_SYSTEM_INSTALL ON) - SET( CMAKE_INSTALL_PREFIX "${INSTALL_PREFIX}" ) -else() - SET(ENABLE_SYSTEM_INSTALL OFF) -endif() - SET ( PROTOBUF_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/proto ) SET ( PROTOBUF_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/proto ) @@ -125,7 +124,7 @@ endif() # Define the global output path of binaries SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) -SET(DEPLOY_DIR "${CMAKE_SOURCE_DIR}/deploy/hyperion" ) + file(MAKE_DIRECTORY ${LIBRARY_OUTPUT_PATH}) file(MAKE_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..cb9da7b4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2014 hyperion team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/bin/create_all_releases.sh b/bin/create_all_releases.sh index 4318d3a6..614325ae 100644 --- a/bin/create_all_releases.sh +++ b/bin/create_all_releases.sh @@ -11,10 +11,13 @@ make_release() shift 2 mkdir -p build-${RELEASE} + mkdir -p deploy/${RELEASE} cd build-${RELEASE} - cmake -DPLATFORM=${PLATFORM} $@ -DCMAKE_BUILD_TYPE=Release -Wno-dev .. || exit 1 + cmake -DCMAKE_INSTALL_PREFIX=/usr -DPLATFORM=${PLATFORM} $@ -DCMAKE_BUILD_TYPE=Release -Wno-dev .. || exit 1 make -j $(nproc) || exit 1 - strip bin/* + #strip bin/* + make package -j $(nproc) + mv hyperion-*-ambilight.* ../deploy/${RELEASE} cd .. bin/create_release.sh . ${RELEASE} } @@ -22,10 +25,10 @@ make_release() export PATH="$PATH:$HOME/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin" CMAKE_PROTOC_FLAG="-DIMPORT_PROTOC=../build-x86x64/protoc_export.cmake" -make_release x86x64 x86 -#make_release x32 x86 ${CMAKE_PROTOC_FLAG} -make_release rpi rpi -DCMAKE_TOOLCHAIN_FILE="../Toolchain-rpi.cmake" ${CMAKE_PROTOC_FLAG} -make_release wetek rpi -DCMAKE_TOOLCHAIN_FILE="../Toolchain-rpi.cmake" ${CMAKE_PROTOC_FLAG} -#make_release imx6 imx6 -DCMAKE_TOOLCHAIN_FILE="../Toolchain-imx6.cmake" ${CMAKE_PROTOC_FLAG} +make_release x86x64 x86 +#make_release x32 x86 ${CMAKE_PROTOC_FLAG} +make_release rpi rpi-pwm -DCMAKE_TOOLCHAIN_FILE="../cmake/Toolchain-rpi.cmake" ${CMAKE_PROTOC_FLAG} +make_release wetek wetek -DCMAKE_TOOLCHAIN_FILE="../cmake/Toolchain-rpi.cmake" ${CMAKE_PROTOC_FLAG} +#make_release imx6 imx6 -DCMAKE_TOOLCHAIN_FILE="../cmake/Toolchain-imx6.cmake" ${CMAKE_PROTOC_FLAG} diff --git a/bin/service/hyperion.init.sh b/bin/service/hyperion.init.sh index 3ed78f5b..f296a458 100644 --- a/bin/service/hyperion.init.sh +++ b/bin/service/hyperion.init.sh @@ -13,7 +13,7 @@ ### END INIT INFO DAEMON=hyperiond -DAEMONOPTS="/opt/hyperion/config/hyperion.config.json" +DAEMONOPTS="/opt/hyperion/hyperion.config.json /etc/hyperion/hyperion.config.json" DAEMON_PATH="/usr/bin" NAME=$DAEMON diff --git a/bin/service/hyperion.initctl.sh b/bin/service/hyperion.initctl.sh index 58f6f79f..774e20b9 100644 --- a/bin/service/hyperion.initctl.sh +++ b/bin/service/hyperion.initctl.sh @@ -8,4 +8,4 @@ stop on (runlevel [!2345]) respawn -exec /usr/bin/hyperiond /opt/hyperion/config/hyperion.config.json \ No newline at end of file +exec /usr/bin/hyperiond /opt/hyperion/hyperion.config.json /etc/hyperion/hyperion.config.json diff --git a/bin/service/hyperion.systemd.sh b/bin/service/hyperion.systemd.sh index b3503c7c..8fe2bc40 100644 --- a/bin/service/hyperion.systemd.sh +++ b/bin/service/hyperion.systemd.sh @@ -6,7 +6,7 @@ Type=simple User=root Group=root UMask=007 -ExecStart=/opt/hyperion/bin/hyperiond /opt/hyperion/config/hyperion.config.json +ExecStart=/usr/bin/hyperiond /opt/hyperion/hyperion.config.json /etc/hyperion/hyperion.config.json ExecReload=/bin/kill -HUP $MAINPID Restart=on-failure TimeoutStopSec=10 diff --git a/Toolchain-imx6.cmake b/cmake/Toolchain-imx6.cmake similarity index 100% rename from Toolchain-imx6.cmake rename to cmake/Toolchain-imx6.cmake diff --git a/Toolchain-rpi.cmake b/cmake/Toolchain-rpi.cmake similarity index 100% rename from Toolchain-rpi.cmake rename to cmake/Toolchain-rpi.cmake diff --git a/Toolchain-x32.cmake b/cmake/Toolchain-x32.cmake similarity index 100% rename from Toolchain-x32.cmake rename to cmake/Toolchain-x32.cmake diff --git a/cmake/debian/postinst b/cmake/debian/postinst new file mode 100644 index 00000000..69ba8fc6 --- /dev/null +++ b/cmake/debian/postinst @@ -0,0 +1,60 @@ +#!/bin/sh + +install_file() +{ + src="$1" + dest="$2" + + if [ -e "$dest" ] && ! cmp --quiet "$src" "$dest" + then + cp "$src" "${dest}.new" + else + cp "$src" "${dest}" + fi +} + + +echo "--- hyperion ambilight postinstall ---" +echo "- install configuration template" +mkdir -p /etc/hyperion +install_file /usr/share/hyperion/config/hyperion.config.json /etc/hyperion/hyperion.config.json + + +if grep -m1 systemd /proc/1/comm > /dev/null +then + # systemd + echo + systemctl stop hyperion 2> /dev/null + install_file /usr/share/hyperion/service/hyperion.systemd.sh /etc/systemd/system/hyperion.service + systemctl -q enable hyperion.service +# if [ $OS_OSMC -eq 1 ]; then +# echo '---> Modify systemd script for OSMC usage' +# # Wait until kodi is sarted (for kodi checker) +# sed -i '/After = mediacenter.service/d' /etc/systemd/system/hyperion.service +# sed -i '/Unit/a After = mediacenter.service' /etc/systemd/system/hyperion.service +# sed -i 's/User=osmc/User=root/g' /etc/systemd/system/hyperion.service +# sed -i 's/Group=osmc/Group=root/g' /etc/systemd/system/hyperion.service +# systemctl -q daemon-reload +# fi + systemctl start hyperion + +elif [ -e /sbin/initctl ] +then + # upstart + install_file /usr/share/hyperion/service/hyperion.initctl.sh /etc/init/hyperion.conf + initctl reload-configuration + initctl start hyperion + +else + # sysV + service hyperion stop 2>/dev/null + install_file /usr/share/hyperion/service/hyperion.init.sh /etc/init.d/hyperion + chmod +x /etc/init.d/hyperion + update-rc.d hyperion defaults 98 02 + service hyperion start +fi +echo "- done" + +# hypercon compat +mkdir -p /opt/hyperion/config +ln -sf /usr/share/hyperion/effects /opt/hyperion/effects diff --git a/cmake/packages.cmake b/cmake/packages.cmake index 17b21485..ed8fe87c 100644 --- a/cmake/packages.cmake +++ b/cmake/packages.cmake @@ -1,3 +1,32 @@ -SET(CPACK_GENERATOR "DEB" "RPM" "TGZ" ) -SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "hyperion team") -include (CPack) +# cmake file for generating distribution packages + +SET ( CPACK_GENERATOR "DEB" "TGZ" "STGZ" ) # "RPM" + +SET ( CPACK_PACKAGE_NAME "hyperion" ) +SET ( CPACK_PACKAGE_DESCRIPTION_SUMMARY "Hyperion is an opensource 'AmbiLight' implementation" ) +SET ( CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md" ) +SET ( CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" ) + +SET ( CPACK_DEBIAN_PACKAGE_MAINTAINER "hyperion team") +SET ( CPACK_DEBIAN_PACKAGE_NAME "hyperion" ) +SET ( CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/cmake/debian/postinst" ) +SET ( CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/hyperion-project/hyperion" ) +SET ( CPACK_DEBIAN_PACKAGE_DEPENDS "libqtcore4 (>= 4:4.8.0), libqt4-network (>= 4:4.8.0)" ) +SET ( CPACK_DEBIAN_PACKAGE_SECTION "Miscellaneous" ) + +SET ( CPACK_RPM_PACKAGE_NAME "hyperion" ) +SET ( CPACK_RPM_PACKAGE_URL "https://github.com/hyperion-project/hyperion" ) +SET ( CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/rpm/postinst" ) + +SET(CPACK_PACKAGE_VERSION_MAJOR "1") +SET(CPACK_PACKAGE_VERSION_MINOR "3") +SET(CPACK_PACKAGE_VERSION_PATCH "0") + +SET ( CPACK_COMPONENTS_ALL ambilight ) +SET ( CPACK_ARCHIVE_COMPONENT_INSTALL ON ) +SET ( CPACK_DEB_COMPONENT_INSTALL ON ) +SET ( CPACK_RPM_COMPONENT_INSTALL ON ) +SET ( CPACK_STRIP_FILES ON ) + +# no code after following line! +INCLUDE ( CPack ) diff --git a/cmake/rpm/postinst b/cmake/rpm/postinst new file mode 100644 index 00000000..677ddc66 --- /dev/null +++ b/cmake/rpm/postinst @@ -0,0 +1,57 @@ +#!/bin/sh + +install_file() +{ + src="$1" + dest="$2" + + if [ -e "$dest" ] && ! cmp --quiet "$src" "$dest" + then + cp "$src" "${dest}.new" + else + cp "$src" "${dest}" + fi +} + + +echo "--- hyperion ambilight postinstall ---" +echo "- install configuration template" +mkdir -p /etc/hyperion +install_file /usr/share/hyperion/config/hyperion.config.json /etc/hyperion/hyperion.config.json + + +if grep -m1 systemd /proc/1/comm > /dev/null +then + # systemd + echo + systemctl stop hyperion 2> /dev/null + install_file /usr/share/hyperion/service/hyperion.systemd.sh /etc/systemd/system/hyperion.service + systemctl -q enable hyperion.service +# if [ $OS_OSMC -eq 1 ]; then +# echo '---> Modify systemd script for OSMC usage' +# # Wait until kodi is sarted (for kodi checker) +# sed -i '/After = mediacenter.service/d' /etc/systemd/system/hyperion.service +# sed -i '/Unit/a After = mediacenter.service' /etc/systemd/system/hyperion.service +# sed -i 's/User=osmc/User=root/g' /etc/systemd/system/hyperion.service +# sed -i 's/Group=osmc/Group=root/g' /etc/systemd/system/hyperion.service +# systemctl -q daemon-reload +# fi + systemctl start hyperion + +elif [ -e /sbin/initctl ] +then + # upstart + install_file /usr/share/hyperion/service/hyperion.initctl.sh /etc/init/hyperion.conf + initctl reload-configuration + initctl start hyperion + +else + # sysV + service hyperion stop 2>/dev/null + install_file /usr/share/hyperion/service/hyperion.init.sh /etc/init.d/hyperion + chmod +x /etc/init.d/hyperion + update-rc.d hyperion defaults 98 02 + service hyperion start +fi +echo "- done" + diff --git a/config/hyperion_x86.config.json b/config/hyperion_x86.config.json index 4abd64db..329ff248 100644 --- a/config/hyperion_x86.config.json +++ b/config/hyperion_x86.config.json @@ -363,7 +363,7 @@ { "paths" : [ - "/home/dincs/projects/hyperion/effects" + "/opt/hyperion/effects" ] }, diff --git a/src/hyperion-aml/CMakeLists.txt b/src/hyperion-aml/CMakeLists.txt index a53e1c70..1f4b6a8f 100644 --- a/src/hyperion-aml/CMakeLists.txt +++ b/src/hyperion-aml/CMakeLists.txt @@ -61,7 +61,4 @@ else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) endif() -install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) -if (ENABLE_SYSTEM_INSTALL) - install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" ) -endif() +install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-dispmanx/CMakeLists.txt b/src/hyperion-dispmanx/CMakeLists.txt index 07eabd9b..987c37d9 100644 --- a/src/hyperion-dispmanx/CMakeLists.txt +++ b/src/hyperion-dispmanx/CMakeLists.txt @@ -60,8 +60,4 @@ else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) endif() - -install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) -if (ENABLE_SYSTEM_INSTALL) - install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" ) -endif() +install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-framebuffer/CMakeLists.txt b/src/hyperion-framebuffer/CMakeLists.txt index cac8f135..e9056b54 100644 --- a/src/hyperion-framebuffer/CMakeLists.txt +++ b/src/hyperion-framebuffer/CMakeLists.txt @@ -56,7 +56,4 @@ else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) endif() -install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) -if (ENABLE_SYSTEM_INSTALL) - install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" ) -endif() +install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-osx/CMakeLists.txt b/src/hyperion-osx/CMakeLists.txt index de821562..c492de6b 100644 --- a/src/hyperion-osx/CMakeLists.txt +++ b/src/hyperion-osx/CMakeLists.txt @@ -56,5 +56,5 @@ else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) endif() -install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) +install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-remote/CMakeLists.txt b/src/hyperion-remote/CMakeLists.txt index d78c5506..6af8fd03 100644 --- a/src/hyperion-remote/CMakeLists.txt +++ b/src/hyperion-remote/CMakeLists.txt @@ -42,8 +42,5 @@ else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) endif() -install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) -if (ENABLE_SYSTEM_INSTALL) - install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" ) -endif() +install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-v4l2/CMakeLists.txt b/src/hyperion-v4l2/CMakeLists.txt index 1bd54ce2..1c09746d 100644 --- a/src/hyperion-v4l2/CMakeLists.txt +++ b/src/hyperion-v4l2/CMakeLists.txt @@ -60,7 +60,4 @@ else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) endif() -install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) -if (ENABLE_SYSTEM_INSTALL) - install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" ) -endif() +install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-x11/CMakeLists.txt b/src/hyperion-x11/CMakeLists.txt index a3a17d7c..6ddbe5da 100644 --- a/src/hyperion-x11/CMakeLists.txt +++ b/src/hyperion-x11/CMakeLists.txt @@ -62,7 +62,4 @@ else() qt4_use_modules(${PROJECT_NAME} Core Gui Network ) endif() -install ( TARGETS ${PROJECT_NAME} DESTINATION "${DEPLOY_DIR}/bin" ) -if (ENABLE_SYSTEM_INSTALL) - install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" ) -endif() +install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperiond/CMakeLists.txt b/src/hyperiond/CMakeLists.txt index ea059138..2e214eee 100644 --- a/src/hyperiond/CMakeLists.txt +++ b/src/hyperiond/CMakeLists.txt @@ -34,12 +34,9 @@ if (ENABLE_PROTOBUF) target_link_libraries(hyperiond protoserver) endif () -install ( TARGETS hyperiond DESTINATION "${DEPLOY_DIR}/bin" ) -install ( DIRECTORY ${CMAKE_SOURCE_DIR}/effects DESTINATION "${DEPLOY_DIR}/share/hyperion/" ) -install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "${DEPLOY_DIR}/share/hyperion/" ) +install ( TARGETS hyperiond DESTINATION "bin" COMPONENT ambilight ) +install ( DIRECTORY ${CMAKE_SOURCE_DIR}/effects DESTINATION "share/hyperion/" COMPONENT ambilight ) +install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "share/hyperion/" COMPONENT ambilight ) +install ( DIRECTORY ${CMAKE_SOURCE_DIR}/config DESTINATION "share/hyperion/" COMPONENT ambilight ) + -if (ENABLE_SYSTEM_INSTALL) - install ( TARGETS hyperiond DESTINATION "bin" ) - install ( DIRECTORY ${CMAKE_SOURCE_DIR}/effects DESTINATION "share/hyperion/" ) - install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "share/hyperion/" ) -endif() diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index cd427175..00ab7a3f 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -7,6 +7,7 @@ #include #include #include +#include // config includes #include "HyperionConfig.h" @@ -114,7 +115,17 @@ int main(int argc, char** argv) return 1; } - const std::string configFile = argv[1]; + int argvId = 1; + for ( int i=1; i Date: Tue, 24 May 2016 22:14:45 +0200 Subject: [PATCH 20/63] better output for effect path loading (#652) * better output for effect path loading * effectengine: error when no efx available Former-commit-id: 7724e56850ef9f9a703fb41e82baf88e5534f492 --- libsrc/effectengine/EffectEngine.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/libsrc/effectengine/EffectEngine.cpp b/libsrc/effectengine/EffectEngine.cpp index 97492a85..c5a554cd 100644 --- a/libsrc/effectengine/EffectEngine.cpp +++ b/libsrc/effectengine/EffectEngine.cpp @@ -35,23 +35,28 @@ EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectCo { const std::string & path = paths[i].asString(); QDir directory(QString::fromStdString(path)); - if (!directory.exists()) + if (directory.exists()) { - std::cerr << "EFFECTENGINE ERROR: Effect directory can not be loaded: " << path << std::endl; - continue; - } - - QStringList filenames = directory.entryList(QStringList() << "*.json", QDir::Files, QDir::Name | QDir::IgnoreCase); - foreach (const QString & filename, filenames) - { - EffectDefinition def; - if (loadEffectDefinition(path, filename.toStdString(), def)) + int efxCount = 0; + QStringList filenames = directory.entryList(QStringList() << "*.json", QDir::Files, QDir::Name | QDir::IgnoreCase); + foreach (const QString & filename, filenames) { - _availableEffects.push_back(def); + EffectDefinition def; + if (loadEffectDefinition(path, filename.toStdString(), def)) + { + _availableEffects.push_back(def); + efxCount++; + } } + std::cerr << "EFFECTENGINE INFO: " << efxCount << " effects loaded from directory " << path << std::endl; } } + if (_availableEffects.size() == 0) + { + std::cerr << "EFFECTENGINE ERROR: no effects found, check your effect directories" << std::endl; + } + // initialize the python interpreter std::cout << "EFFECTENGINE INFO: Initializing Python interpreter" << std::endl; Effect::registerHyperionExtensionModule(); From 45dff6d1d3a8514b3d70e2bb5f803d1b64a04e45 Mon Sep 17 00:00:00 2001 From: Funatiq Date: Tue, 24 May 2016 22:15:39 +0200 Subject: [PATCH 21/63] Reduce saturation in backlight (#651) Former-commit-id: c2c4fd6f957c3623e03c37393cf3c03a7a27dc1e --- libsrc/utils/HslTransform.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsrc/utils/HslTransform.cpp b/libsrc/utils/HslTransform.cpp index 8d391adf..07e9d203 100644 --- a/libsrc/utils/HslTransform.cpp +++ b/libsrc/utils/HslTransform.cpp @@ -66,7 +66,10 @@ void HslTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue) con float l = luminance * _luminanceGain; if (l < _luminanceMinimum) + { + saturation *= l/_luminanceMinimum; l = _luminanceMinimum; + } if (l > 1.0f) luminance = 1.0f; else From 1e319be54a44433d040a05489360956b174740a6 Mon Sep 17 00:00:00 2001 From: brindosch Date: Wed, 25 May 2016 18:53:09 +0200 Subject: [PATCH 22/63] hotfix x11grabber Former-commit-id: 7068bad863cf229e01382f859ff06a51dad82d17 --- libsrc/grabber/x11/X11Grabber.cpp | 32 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/libsrc/grabber/x11/X11Grabber.cpp b/libsrc/grabber/x11/X11Grabber.cpp index 1e3e0b4c..4d4d6fa7 100644 --- a/libsrc/grabber/x11/X11Grabber.cpp +++ b/libsrc/grabber/x11/X11Grabber.cpp @@ -111,22 +111,24 @@ bool X11Grabber::Setup() Image & X11Grabber::grab() { - if (_XRenderAvailable && !_useXGetImage) { - XRenderComposite( _x11Display, // *dpy, - PictOpSrc, // op, - _srcPicture, // src - None, // mask - _dstPicture, // dst - _cropLeft, // src_x - _cropTop, // src_y - 0, // mask_x - 0, // mask_y - 0, // dst_x - 0, // dst_y - _croppedWidth, // width - _croppedHeight); // height + updateScreenDimensions(); + + if (_XRenderAvailable && !_useXGetImage) { + XRenderComposite( _x11Display, // *dpy, + PictOpSrc, // op, + _srcPicture, // src + None, // mask + _dstPicture, // dst + _cropLeft, // src_x + _cropTop, // src_y + 0, // mask_x + 0, // mask_y + 0, // dst_x + 0, // dst_y + _croppedWidth, // width + _croppedHeight); // height - XSync(_x11Display, False); + XSync(_x11Display, False); if (_XShmAvailable) { XShmGetImage(_x11Display, _pixmap, _xImage, 0, 0, AllPlanes); From 84d9f4ef804175cd85da347c254499eb8b877a5c Mon Sep 17 00:00:00 2001 From: brindosch Date: Wed, 25 May 2016 21:15:49 +0200 Subject: [PATCH 23/63] xbmc checker fix (2) Former-commit-id: 735f8e3e356b0fca0562185f30532860c7879ee3 --- libsrc/xbmcvideochecker/XBMCVideoChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp b/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp index fe8efd78..c8c82796 100644 --- a/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp +++ b/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp @@ -61,7 +61,7 @@ void XBMCVideoChecker::receiveReply() std::cout << "KODICHECK INFO: Kodi Message: " << reply.toStdString() << std::endl; - if (reply.contains("\"method\":\"Player.OnPlay\"")) + if (reply.contains("\"method\":\"Player.OnPlay\"") || reply.contains("\"method\":\"Playlist.OnAdd\"")) { // send a request for the current player state _socket.write(_activePlayerRequest.toUtf8()); From a41051cc8432e3db8a4f172f31f6a4210b960bb4 Mon Sep 17 00:00:00 2001 From: redPanther Date: Thu, 26 May 2016 07:01:10 +0200 Subject: [PATCH 24/63] prevent colorsmoothing from flooding led device with data when no new input data is available (#654) resolve compiler warnings Former-commit-id: c7fbdce5dc7fde8b8e188320408dc547b9ad5e51 --- libsrc/hyperion/Hyperion.cpp | 6 +++--- libsrc/hyperion/LinearColorSmoothing.cpp | 11 ++++++++--- libsrc/hyperion/LinearColorSmoothing.h | 2 ++ libsrc/utils/RgbChannelCorrection.cpp | 4 ++-- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 538772a9..9c871818 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -480,7 +480,7 @@ RgbChannelCorrection* Hyperion::createRgbChannelCorrection(const Json::Value& co RgbChannelAdjustment* Hyperion::createRgbChannelAdjustment(const Json::Value& colorConfig, const RgbChannel color) { - int varR, varG, varB; + int varR=0, varG=0, varB=0; if (color == RED) { varR = colorConfig.get("redChannel", 255).asInt(); @@ -618,10 +618,10 @@ MessageForwarder * Hyperion::getForwarder() Hyperion::Hyperion(const Json::Value &jsonConfig) : _ledString(createLedString(jsonConfig["leds"], createColorOrder(jsonConfig["device"]))), _muxer(_ledString.leds().size()), - _raw2ledAdjustment(createLedColorsAdjustment(_ledString.leds().size(), jsonConfig["color"])), + _raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])), _raw2ledCorrection(createLedColorsCorrection(_ledString.leds().size(), jsonConfig["color"])), _raw2ledTemperature(createLedColorsTemperature(_ledString.leds().size(), jsonConfig["color"])), - _raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])), + _raw2ledAdjustment(createLedColorsAdjustment(_ledString.leds().size(), jsonConfig["color"])), _device(LedDeviceFactory::construct(jsonConfig["device"])), _effectEngine(nullptr), _messageForwarder(createMessageForwarder(jsonConfig["forwarder"])), diff --git a/libsrc/hyperion/LinearColorSmoothing.cpp b/libsrc/hyperion/LinearColorSmoothing.cpp index bfb7c603..09f2b014 100644 --- a/libsrc/hyperion/LinearColorSmoothing.cpp +++ b/libsrc/hyperion/LinearColorSmoothing.cpp @@ -14,7 +14,8 @@ LinearColorSmoothing::LinearColorSmoothing( _updateInterval(1000 / ledUpdateFrequency_hz), _settlingTime(settlingTime_ms), _timer(), - _outputDelay(updateDelay) + _outputDelay(updateDelay), + _writeToLedsEnable(true) { _timer.setSingleShot(false); _timer.setInterval(_updateInterval); @@ -82,9 +83,11 @@ void LinearColorSmoothing::updateLeds() _previousTime = now; queueColors(_previousValues); + _writeToLedsEnable = false; } else { + _writeToLedsEnable = true; float k = 1.0f - 1.0f * deltaTime / (_targetTime - _previousTime); for (size_t i = 0; i < _previousValues.size(); ++i) @@ -107,7 +110,8 @@ void LinearColorSmoothing::queueColors(const std::vector & ledColors) if (_outputDelay == 0) { // No output delay => immediate write - _ledDevice->write(ledColors); + if ( _writeToLedsEnable ) + _ledDevice->write(ledColors); } else { @@ -116,7 +120,8 @@ void LinearColorSmoothing::queueColors(const std::vector & ledColors) // If the delay-buffer is filled pop the front and write to device if (_outputQueue.size() > _outputDelay) { - _ledDevice->write(_outputQueue.front()); + if ( _writeToLedsEnable ) + _ledDevice->write(_outputQueue.front()); _outputQueue.pop_front(); } } diff --git a/libsrc/hyperion/LinearColorSmoothing.h b/libsrc/hyperion/LinearColorSmoothing.h index 2b75059e..19cc915f 100644 --- a/libsrc/hyperion/LinearColorSmoothing.h +++ b/libsrc/hyperion/LinearColorSmoothing.h @@ -80,4 +80,6 @@ private: /** The output queue */ std::list > _outputQueue; + // prevent sending data to device when no intput data is sent + bool _writeToLedsEnable; }; diff --git a/libsrc/utils/RgbChannelCorrection.cpp b/libsrc/utils/RgbChannelCorrection.cpp index 2cced20b..7fb16884 100644 --- a/libsrc/utils/RgbChannelCorrection.cpp +++ b/libsrc/utils/RgbChannelCorrection.cpp @@ -6,8 +6,8 @@ RgbChannelCorrection::RgbChannelCorrection() : _correctionR(255), - _correctionB(255), - _correctionG(255) + _correctionG(255), + _correctionB(255) { initializeMapping(); } From f9690b03f43f9f6823beb007a40a4418ade89f2a Mon Sep 17 00:00:00 2001 From: penfold42 Date: Wed, 25 May 2016 22:04:49 -0700 Subject: [PATCH 25/63] updated reference to rpi_ws281x sub module to point to penfold42 fork (#655) * Removed -HUP so the default -TERM signal is sent instead. - hyperiond only listens for TERM and INT. HUP is often used to get an exe to reread its config Changed pgrep to add '-x' so it wont partial match on the exe name. - I have multiple instances with multiple hyperiond-instance1 names - this ensures the service script only kills the right process * reversing errant change to hyperion.systemd.sh * cleaned up a couple of compiler warnings * moved bitpair_to_byte initialiser to (hopefully) work with older GCC * compiler warning in udp driver removed some tabs in ws2812b.cpp * formatting - spaces to tabs * moved rpi_281x to tag sk6812-v1.0 * moving to my fork of rpi_281x Former-commit-id: 34ca0f4f760c6cbb47d3c434c920827ce12bb23e --- .gitmodules | 2 +- dependencies/external/rpi_ws281x | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index c23ec3d2..462e3f07 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,4 +3,4 @@ url = https://github.com/tvdzwan/protobuf.git [submodule "dependencies/external/rpi_ws281x"] path = dependencies/external/rpi_ws281x - url = https://github.com/jgarff/rpi_ws281x + url = https://github.com/penfold42/rpi_ws281x diff --git a/dependencies/external/rpi_ws281x b/dependencies/external/rpi_ws281x index 0165896a..dfcf7408 160000 --- a/dependencies/external/rpi_ws281x +++ b/dependencies/external/rpi_ws281x @@ -1 +1 @@ -Subproject commit 0165896aa04b08a777fb6732a1af6fa29e4a93c5 +Subproject commit dfcf740848898b432fe3a3170417de60f81521ee From 716935dfff9bc1b68fcbac7a07b4a01698bbfec9 Mon Sep 17 00:00:00 2001 From: brindosch Date: Thu, 26 May 2016 07:45:54 +0200 Subject: [PATCH 26/63] xbmc checker fix (3) Former-commit-id: c8b406033d333177dd2470522b2d8526a9c02d07 --- libsrc/xbmcvideochecker/XBMCVideoChecker.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp b/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp index c8c82796..667ad4e4 100644 --- a/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp +++ b/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp @@ -61,7 +61,7 @@ void XBMCVideoChecker::receiveReply() std::cout << "KODICHECK INFO: Kodi Message: " << reply.toStdString() << std::endl; - if (reply.contains("\"method\":\"Player.OnPlay\"") || reply.contains("\"method\":\"Playlist.OnAdd\"")) + if (reply.contains("\"method\":\"Player.OnPlay\"")) { // send a request for the current player state _socket.write(_activePlayerRequest.toUtf8()); @@ -193,6 +193,11 @@ void XBMCVideoChecker::receiveReply() _xbmcVersion = regex.cap(1).toInt(); } } + else if (reply.contains("picture") && reply.contains("\"method\":\"Playlist.OnAdd\"")) + { + // picture viewer is playing + setGrabbingMode(_grabPhoto ? GRABBINGMODE_PHOTO : GRABBINGMODE_OFF); + } } void XBMCVideoChecker::connected() From 667ee80ef651f9188d0b5d5fc4e387768c2e62d5 Mon Sep 17 00:00:00 2001 From: brindosch Date: Thu, 26 May 2016 23:42:23 +0200 Subject: [PATCH 27/63] add codingstyle.md Former-commit-id: 6f65784f8b0588351b1b89329bfaa59081630f50 --- CODING_STYLE.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 CODING_STYLE.md diff --git a/CODING_STYLE.md b/CODING_STYLE.md new file mode 100644 index 00000000..e7b18aec --- /dev/null +++ b/CODING_STYLE.md @@ -0,0 +1,19 @@ +### Please use the following code style/guidelines + +- use QT wherever it's possible (except there is a good reason) +- use unix line endings (not windows) +- indent your code with TABs instead of spaces +- follow this rule for curly brackets +``` +bad: +if (conditon) { + code +} + +good: +if (condition) +{ + code +} + +``` \ No newline at end of file From 945f3d1c5b7c804325bcf55e78cb5c7f554851ed Mon Sep 17 00:00:00 2001 From: redPanther Date: Thu, 26 May 2016 23:44:27 +0200 Subject: [PATCH 28/63] big code cleanup. mostly line endings and indentions (#659) No functional changes - except protobuffer is mandatory and not optional now. Former-commit-id: 1e6347e708707cc388cdedb8d0352a9f017030b8 --- CMakeLists.txt | 6 +- bin/copy_binaries_to_deploy.sh | 4 +- bin/remove_hyperion.sh | 42 +- cmake/FindBCM.cmake | 18 +- cmake/FindCoreFoundation.cmake | 4 +- cmake/FindIOKit.cmake | 8 +- cmake/FindUDev.cmake | 66 +- cmake/Findlibusb-1.0.cmake | 84 +- cmake/cmake_uninstall.cmake.in | 28 +- effects/knight-rider.json | 20 +- effects/mood-blobs-blue.json | 24 +- effects/mood-blobs-green.json | 24 +- effects/mood-blobs-red.json | 24 +- effects/rainbow-mood.json | 20 +- effects/rainbow-swirl-fast.json | 20 +- effects/rainbow-swirl.json | 20 +- effects/snake.json | 20 +- include/grabber/V4L2Grabber.h | 124 +- include/grabber/X11Grabber.h | 22 +- include/protoserver/ProtoConnection.h | 130 +- include/protoserver/ProtoConnectionWrapper.h | 24 +- include/utils/Image.h | 382 +++--- include/utils/ImageResampler.h | 21 +- include/utils/PixelFormat.h | 38 +- include/utils/Sleep.h | 6 +- include/utils/jsonschema/JsonSchemaChecker.h | 384 +++--- libsrc/CMakeLists.txt | 2 +- libsrc/blackborder/CMakeLists.txt | 46 +- libsrc/boblightserver/CMakeLists.txt | 80 +- libsrc/effectengine/CMakeLists.txt | 43 +- .../effectengine/EffectDefinition.schema.json | 684 +++++------ libsrc/grabber/CMakeLists.txt | 46 +- libsrc/grabber/amlogic/CMakeLists.txt | 66 +- libsrc/grabber/dispmanx/CMakeLists.txt | 82 +- libsrc/grabber/framebuffer/CMakeLists.txt | 24 +- libsrc/grabber/osx/CMakeLists.txt | 24 +- libsrc/grabber/v4l2/CMakeLists.txt | 78 +- libsrc/grabber/v4l2/V4L2Grabber.cpp | 1064 ++++++++--------- libsrc/grabber/x11/CMakeLists.txt | 18 +- libsrc/grabber/x11/X11Grabber.cpp | 282 ++--- libsrc/hyperion/CMakeLists.txt | 144 +-- libsrc/hyperion/hyperion.schema.json | 764 ++++++------ libsrc/jsonserver/CMakeLists.txt | 96 +- libsrc/leddevice/CMakeLists.txt | 331 ++--- libsrc/leddevice/LedDeviceAtmoOrb.cpp | 310 ++--- libsrc/leddevice/LedDeviceAtmoOrb.h | 262 ++-- libsrc/leddevice/LedDeviceLpd6803.cpp | 100 +- libsrc/leddevice/LedDeviceLpd6803.h | 84 +- libsrc/leddevice/LedDeviceLpd8806.cpp | 108 +- libsrc/leddevice/LedDeviceLpd8806.h | 206 ++-- libsrc/leddevice/LedDevicePhilipsHue.cpp | 684 +++++------ libsrc/leddevice/LedDevicePhilipsHue.h | 470 ++++---- libsrc/leddevice/LedDeviceTpm2.cpp | 22 +- libsrc/leddevice/LedDeviceUdp.cpp | 85 +- libsrc/leddevice/LedDeviceWS2812b.h | 12 +- libsrc/protoserver/CMakeLists.txt | 122 +- libsrc/protoserver/ProtoConnection.cpp | 286 ++--- libsrc/protoserver/ProtoConnectionWrapper.cpp | 10 +- libsrc/utils/CMakeLists.txt | 82 +- libsrc/utils/jsonschema/JsonSchemaChecker.cpp | 928 +++++++------- libsrc/xbmcvideochecker/CMakeLists.txt | 28 +- src/CMakeLists.txt | 49 +- src/hyperion-aml/AmlogicWrapper.cpp | 16 +- src/hyperion-dispmanx/DispmanxWrapper.cpp | 20 +- .../FramebufferWrapper.cpp | 16 +- src/hyperion-osx/OsxWrapper.cpp | 12 +- src/hyperion-v4l2/PixelFormatParameter.h | 56 +- src/hyperion-v4l2/ScreenshotHandler.cpp | 2 +- src/hyperion-v4l2/hyperion-v4l2.cpp | 252 ++-- src/hyperion-x11/X11Wrapper.cpp | 26 +- src/hyperion-x11/X11Wrapper.h | 40 +- src/hyperion-x11/hyperion-x11.cpp | 166 +-- src/hyperiond/hyperiond.cpp | 16 - 73 files changed, 4941 insertions(+), 4966 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2f14ab4..a82810e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,8 +51,7 @@ message(STATUS "ENABLE_FB = " ${ENABLE_FB}) option(ENABLE_OSX "Enable the osx grabber" ${DEFAULT_OSX} ) message(STATUS "ENABLE_OSX = " ${ENABLE_OSX}) -option(ENABLE_PROTOBUF "Enable PROTOBUF server" ON) -message(STATUS "ENABLE_PROTOBUF = " ${ENABLE_PROTOBUF}) +set(ENABLE_PROTOBUF ON) option(ENABLE_SPIDEV "Enable the SPIDEV device" ${DEFAULT_SPIDEV} ) message(STATUS "ENABLE_SPIDEV = " ${ENABLE_SPIDEV}) @@ -78,9 +77,6 @@ message(STATUS "ENABLE_QT5 = " ${ENABLE_QT5}) option(ENABLE_TESTS "Compile additional test applications" OFF) message(STATUS "ENABLE_TESTS = " ${ENABLE_TESTS}) -if(ENABLE_V4L2 AND NOT ENABLE_PROTOBUF) - message(FATAL_ERROR "V4L2 grabber requires PROTOBUF. Disable V4L2 or enable PROTOBUF") -endif() if(ENABLE_FB AND ENABLE_DISPMANX) message(FATAL_ERROR "dispmanx grabber and framebuffer grabber cannot be used at the same time") diff --git a/bin/copy_binaries_to_deploy.sh b/bin/copy_binaries_to_deploy.sh index 5ce8be74..82dc5032 100755 --- a/bin/copy_binaries_to_deploy.sh +++ b/bin/copy_binaries_to_deploy.sh @@ -1,8 +1,8 @@ #!/bin/sh if [ "$#" -ne 2 ] || ! [ -d "$1" ] || ! [ -d "$2" ]; then - echo "Usage: $0 " >&2 - exit 1 + echo "Usage: $0 " >&2 + exit 1 fi builddir="$1" diff --git a/bin/remove_hyperion.sh b/bin/remove_hyperion.sh index c3034032..b6bf9d1b 100644 --- a/bin/remove_hyperion.sh +++ b/bin/remove_hyperion.sh @@ -6,15 +6,15 @@ PATH="/sbin:$PATH" #Check if HyperCon is logged in as root if [ $(id -u) != 0 ] && [ "$1" = "HyperConRemove" ]; then - echo '---> Critical Error: Please connect as user "root" through HyperCon' - echo '---> We need admin privileges to remove your Hyperion! -> abort' - exit 1 + echo '---> Critical Error: Please connect as user "root" through HyperCon' + echo '---> We need admin privileges to remove your Hyperion! -> abort' + exit 1 fi #Check, if script is running as root if [ $(id -u) != 0 ]; then - echo '---> Critical Error: Please run the script as root (sudo sh ./remove_hyperion.sh)' - exit 1 + echo '---> Critical Error: Please run the script as root (sudo sh ./remove_hyperion.sh)' + exit 1 fi #Welcome message @@ -26,21 +26,22 @@ echo '************************************************************************** #Skip the prompt if HyperCon Remove if [ "$1" = "" ]; then -#Prompt for confirmation to proceed -while true -do -echo -n "---> Do you really want to remove Hyperion and it´s services? (y or n) :" -read CONFIRM -case $CONFIRM in -y|Y|YES|yes|Yes) break ;; -n|N|no|NO|No) -echo "---> Aborting - you entered \"$CONFIRM\"" -exit -;; -*) echo "-> Please enter only y or n" -esac -done -echo "---> You entered \"$CONFIRM\". Remove Hyperion!" + #Prompt for confirmation to proceed + while true + do + echo -n "---> Do you really want to remove Hyperion and it´s services? (y or n) :" + read CONFIRM + case $CONFIRM in + y|Y|YES|yes|Yes) break ;; + n|N|no|NO|No) + echo "---> Aborting - you entered \"$CONFIRM\"" + exit + ;; + *) echo "-> Please enter only y or n" + esac + done + + echo "---> You entered \"$CONFIRM\". Remove Hyperion!" fi # Find out if we are on OpenElec or RasPlex OS_OPENELEC=`grep -m1 -c 'OpenELEC\|RasPlex\|LibreELEC' /etc/issue` @@ -124,4 +125,3 @@ echo '************************************************************************** echo 'Hyperion successful removed!' echo '*******************************************************************************' exit 0 - \ No newline at end of file diff --git a/cmake/FindBCM.cmake b/cmake/FindBCM.cmake index 5e9ce645..f64c540e 100644 --- a/cmake/FindBCM.cmake +++ b/cmake/FindBCM.cmake @@ -8,16 +8,16 @@ # FIND_PATH(BCM_INCLUDE_DIR - bcm_host.h - /usr/include - /usr/local/include - /opt/vc/include) + bcm_host.h + /usr/include + /usr/local/include + /opt/vc/include) SET(BCM_INCLUDE_DIRS - ${BCM_INCLUDE_DIR} - ${BCM_INCLUDE_DIR}/interface/vcos/pthreads - ${BCM_INCLUDE_DIR}/interface/vmcs_host/linux) + ${BCM_INCLUDE_DIR} + ${BCM_INCLUDE_DIR}/interface/vcos/pthreads + ${BCM_INCLUDE_DIR}/interface/vmcs_host/linux) FIND_LIBRARY(BCM_LIBRARIES - NAMES bcm_host - PATHS /usr/lib /usr/local/lib /opt/vc/lib) + NAMES bcm_host + PATHS /usr/lib /usr/local/lib /opt/vc/lib) diff --git a/cmake/FindCoreFoundation.cmake b/cmake/FindCoreFoundation.cmake index aaf1502c..195fe551 100644 --- a/cmake/FindCoreFoundation.cmake +++ b/cmake/FindCoreFoundation.cmake @@ -17,5 +17,5 @@ if(APPLE) set(CoreFoundation_FOUND true) set(CoreFoundation_INCLUDE_DIR ${CoreFoundation}) set(CoreFoundation_LIBRARY ${CoreFoundation}) - endif(CoreFoundation) -endif(APPLE) + endif() +endif() diff --git a/cmake/FindIOKit.cmake b/cmake/FindIOKit.cmake index 7a532a5d..7c17be9e 100644 --- a/cmake/FindIOKit.cmake +++ b/cmake/FindIOKit.cmake @@ -13,9 +13,9 @@ set(IOKit_LIBRARY) if(APPLE) # The only platform it makes sense to check for IOKit find_library(IOKit IOKit) - if(IOKit) - set(IOKit_FOUND true) + if(IOKit) + set(IOKit_FOUND true) set(IOKit_INCLUDE_DIR ${IOKit}) - set(IOKit_LIBRARY ${IOKit}) - endif(IOKit) + set(IOKit_LIBRARY ${IOKit}) + endif(IOKit) endif(APPLE) diff --git a/cmake/FindUDev.cmake b/cmake/FindUDev.cmake index 866608dc..12a429d9 100644 --- a/cmake/FindUDev.cmake +++ b/cmake/FindUDev.cmake @@ -10,44 +10,44 @@ # FIND_PATH( - UDEV_INCLUDE_DIR - libudev.h - /usr/include - /usr/local/include - ${UDEV_PATH_INCLUDES} + UDEV_INCLUDE_DIR + libudev.h + /usr/include + /usr/local/include + ${UDEV_PATH_INCLUDES} ) FIND_LIBRARY( - UDEV_LIBRARIES - NAMES udev libudev - PATHS - /usr/lib${LIB_SUFFIX} - /usr/local/lib${LIB_SUFFIX} - ${UDEV_PATH_LIB} + UDEV_LIBRARIES + NAMES udev libudev + PATHS + /usr/lib${LIB_SUFFIX} + /usr/local/lib${LIB_SUFFIX} + ${UDEV_PATH_LIB} ) IF (UDEV_LIBRARIES AND UDEV_INCLUDE_DIR) - SET(UDEV_FOUND "YES") - execute_process(COMMAND pkg-config --atleast-version=143 libudev RESULT_VARIABLE UDEV_STABLE) - # retvale is 0 of the condition is "true" so we need to negate the value... - if (UDEV_STABLE) - set(UDEV_STABLE 0) - else (UDEV_STABLE) - set(UDEV_STABLE 1) - endif (UDEV_STABLE) - message(STATUS "libudev stable: ${UDEV_STABLE}") -ENDIF (UDEV_LIBRARIES AND UDEV_INCLUDE_DIR) + SET(UDEV_FOUND "YES") + execute_process(COMMAND pkg-config --atleast-version=143 libudev RESULT_VARIABLE UDEV_STABLE) + # retvale is 0 of the condition is "true" so we need to negate the value... + if (UDEV_STABLE) + set(UDEV_STABLE 0) + else () + set(UDEV_STABLE 1) + endif () + message(STATUS "libudev stable: ${UDEV_STABLE}") +ENDIF () IF (UDEV_FOUND) - MESSAGE(STATUS "Found UDev: ${UDEV_LIBRARIES}") - MESSAGE(STATUS " include: ${UDEV_INCLUDE_DIR}") -ELSE (UDEV_FOUND) - MESSAGE(STATUS "UDev not found.") - MESSAGE(STATUS "UDev: You can specify includes: -DUDEV_PATH_INCLUDES=/opt/udev/include") - MESSAGE(STATUS " currently found includes: ${UDEV_INCLUDE_DIR}") - MESSAGE(STATUS "UDev: You can specify libs: -DUDEV_PATH_LIB=/opt/udev/lib") - MESSAGE(STATUS " currently found libs: ${UDEV_LIBRARIES}") - IF (UDev_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find UDev library") - ENDIF (UDev_FIND_REQUIRED) -ENDIF (UDEV_FOUND) + MESSAGE(STATUS "Found UDev: ${UDEV_LIBRARIES}") + MESSAGE(STATUS " include: ${UDEV_INCLUDE_DIR}") +ELSE () + MESSAGE(STATUS "UDev not found.") + MESSAGE(STATUS "UDev: You can specify includes: -DUDEV_PATH_INCLUDES=/opt/udev/include") + MESSAGE(STATUS " currently found includes: ${UDEV_INCLUDE_DIR}") + MESSAGE(STATUS "UDev: You can specify libs: -DUDEV_PATH_LIB=/opt/udev/lib") + MESSAGE(STATUS " currently found libs: ${UDEV_LIBRARIES}") + IF (UDev_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find UDev library") + ENDIF () +ENDIF () diff --git a/cmake/Findlibusb-1.0.cmake b/cmake/Findlibusb-1.0.cmake index 77474e9a..79269e88 100644 --- a/cmake/Findlibusb-1.0.cmake +++ b/cmake/Findlibusb-1.0.cmake @@ -44,56 +44,52 @@ if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) - # in cache already - set(LIBUSB_FOUND TRUE) + # in cache already + set(LIBUSB_FOUND TRUE) else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) - find_path(LIBUSB_1_INCLUDE_DIR + find_path(LIBUSB_1_INCLUDE_DIR + NAMES + libusb.h + PATHS + /usr/include + /usr/local/include + /opt/local/include + /sw/include + PATH_SUFFIXES + libusb-1.0 + ) + + find_library(LIBUSB_1_LIBRARY NAMES - libusb.h + usb-1.0 usb PATHS - /usr/include - /usr/local/include - /opt/local/include - /sw/include - PATH_SUFFIXES - libusb-1.0 - ) + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib + ) - find_library(LIBUSB_1_LIBRARY - NAMES - usb-1.0 usb - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /sw/lib - ) + set(LIBUSB_1_INCLUDE_DIRS ${LIBUSB_1_INCLUDE_DIR} ) + set(LIBUSB_1_LIBRARIES ${LIBUSB_1_LIBRARY} ) - set(LIBUSB_1_INCLUDE_DIRS - ${LIBUSB_1_INCLUDE_DIR} - ) - set(LIBUSB_1_LIBRARIES - ${LIBUSB_1_LIBRARY} -) + if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES) + set(LIBUSB_1_FOUND TRUE) + endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES) - if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES) - set(LIBUSB_1_FOUND TRUE) - endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES) + if (LIBUSB_1_FOUND) + if (NOT libusb_1_FIND_QUIETLY) + message(STATUS "Found libusb-1.0:") + message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}") + message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}") + endif (NOT libusb_1_FIND_QUIETLY) + else (LIBUSB_1_FOUND) + unset(LIBUSB_1_LIBRARY CACHE) + if (libusb_1_FIND_REQUIRED) + message(FATAL_ERROR "Could not find libusb") + endif (libusb_1_FIND_REQUIRED) + endif (LIBUSB_1_FOUND) - if (LIBUSB_1_FOUND) - if (NOT libusb_1_FIND_QUIETLY) - message(STATUS "Found libusb-1.0:") - message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}") - message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}") - endif (NOT libusb_1_FIND_QUIETLY) - else (LIBUSB_1_FOUND) - unset(LIBUSB_1_LIBRARY CACHE) - if (libusb_1_FIND_REQUIRED) - message(FATAL_ERROR "Could not find libusb") - endif (libusb_1_FIND_REQUIRED) - endif (LIBUSB_1_FOUND) - - # show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view - mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES) + # show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view + mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES) endif (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) diff --git a/cmake/cmake_uninstall.cmake.in b/cmake/cmake_uninstall.cmake.in index 27ed4ace..75771c04 100644 --- a/cmake/cmake_uninstall.cmake.in +++ b/cmake/cmake_uninstall.cmake.in @@ -1,22 +1,22 @@ if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") - message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") foreach(file ${files}) - message(STATUS "Uninstalling $ENV{DESTDIR}${file}") - if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") - exec_program( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" - OUTPUT_VARIABLE rm_out - RETURN_VALUE rm_retval - ) - if(NOT "${rm_retval}" STREQUAL 0) - message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") - endif(NOT "${rm_retval}" STREQUAL 0) - else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") - message(STATUS "File $ENV{DESTDIR}${file} does not exist.") - endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif(NOT "${rm_retval}" STREQUAL 0) + else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") endforeach(file) diff --git a/effects/knight-rider.json b/effects/knight-rider.json index b4644387..9801d491 100644 --- a/effects/knight-rider.json +++ b/effects/knight-rider.json @@ -1,10 +1,10 @@ -{ - "name" : "Knight rider", - "script" : "knight-rider.py", - "args" : - { - "speed" : 1.0, - "fadeFactor" : 0.7, - "color" : [255,0,0] - } -} +{ + "name" : "Knight rider", + "script" : "knight-rider.py", + "args" : + { + "speed" : 1.0, + "fadeFactor" : 0.7, + "color" : [255,0,0] + } +} diff --git a/effects/mood-blobs-blue.json b/effects/mood-blobs-blue.json index 1aa188ab..32280b46 100644 --- a/effects/mood-blobs-blue.json +++ b/effects/mood-blobs-blue.json @@ -1,12 +1,12 @@ -{ - "name" : "Blue mood blobs", - "script" : "mood-blobs.py", - "args" : - { - "rotationTime" : 60.0, - "color" : [0,0,255], - "hueChange" : 60.0, - "blobs" : 5, - "reverse" : false - } -} +{ + "name" : "Blue mood blobs", + "script" : "mood-blobs.py", + "args" : + { + "rotationTime" : 60.0, + "color" : [0,0,255], + "hueChange" : 60.0, + "blobs" : 5, + "reverse" : false + } +} diff --git a/effects/mood-blobs-green.json b/effects/mood-blobs-green.json index c0c104fe..aabd536c 100644 --- a/effects/mood-blobs-green.json +++ b/effects/mood-blobs-green.json @@ -1,12 +1,12 @@ -{ - "name" : "Green mood blobs", - "script" : "mood-blobs.py", - "args" : - { - "rotationTime" : 60.0, - "color" : [0,255,0], - "hueChange" : 60.0, - "blobs" : 5, - "reverse" : false - } -} +{ + "name" : "Green mood blobs", + "script" : "mood-blobs.py", + "args" : + { + "rotationTime" : 60.0, + "color" : [0,255,0], + "hueChange" : 60.0, + "blobs" : 5, + "reverse" : false + } +} diff --git a/effects/mood-blobs-red.json b/effects/mood-blobs-red.json index 3272dded..ac47af53 100644 --- a/effects/mood-blobs-red.json +++ b/effects/mood-blobs-red.json @@ -1,12 +1,12 @@ -{ - "name" : "Red mood blobs", - "script" : "mood-blobs.py", - "args" : - { - "rotationTime" : 60.0, - "color" : [255,0,0], - "hueChange" : 60.0, - "blobs" : 5, - "reverse" : false - } -} +{ + "name" : "Red mood blobs", + "script" : "mood-blobs.py", + "args" : + { + "rotationTime" : 60.0, + "color" : [255,0,0], + "hueChange" : 60.0, + "blobs" : 5, + "reverse" : false + } +} diff --git a/effects/rainbow-mood.json b/effects/rainbow-mood.json index fe754287..c9208b60 100644 --- a/effects/rainbow-mood.json +++ b/effects/rainbow-mood.json @@ -1,10 +1,10 @@ -{ - "name" : "Rainbow mood", - "script" : "rainbow-mood.py", - "args" : - { - "rotation-time" : 60.0, - "brightness" : 1.0, - "reverse" : false - } -} +{ + "name" : "Rainbow mood", + "script" : "rainbow-mood.py", + "args" : + { + "rotation-time" : 60.0, + "brightness" : 1.0, + "reverse" : false + } +} diff --git a/effects/rainbow-swirl-fast.json b/effects/rainbow-swirl-fast.json index 19fec89c..88e8d79d 100644 --- a/effects/rainbow-swirl-fast.json +++ b/effects/rainbow-swirl-fast.json @@ -1,10 +1,10 @@ -{ - "name" : "Rainbow swirl fast", - "script" : "rainbow-swirl.py", - "args" : - { - "rotation-time" : 3.0, - "brightness" : 1.0, - "reverse" : false - } -} +{ + "name" : "Rainbow swirl fast", + "script" : "rainbow-swirl.py", + "args" : + { + "rotation-time" : 3.0, + "brightness" : 1.0, + "reverse" : false + } +} diff --git a/effects/rainbow-swirl.json b/effects/rainbow-swirl.json index 3f7b7243..43a80a8d 100644 --- a/effects/rainbow-swirl.json +++ b/effects/rainbow-swirl.json @@ -1,10 +1,10 @@ -{ - "name" : "Rainbow swirl", - "script" : "rainbow-swirl.py", - "args" : - { - "rotation-time" : 20.0, - "brightness" : 1.0, - "reverse" : false - } -} +{ + "name" : "Rainbow swirl", + "script" : "rainbow-swirl.py", + "args" : + { + "rotation-time" : 20.0, + "brightness" : 1.0, + "reverse" : false + } +} diff --git a/effects/snake.json b/effects/snake.json index 18f2b17c..d5a7674f 100644 --- a/effects/snake.json +++ b/effects/snake.json @@ -1,10 +1,10 @@ -{ - "name" : "Snake", - "script" : "snake.py", - "args" : - { - "rotation-time" : 12.0, - "color" : [255, 0, 0], - "percentage" : 10 - } -} +{ + "name" : "Snake", + "script" : "snake.py", + "args" : + { + "rotation-time" : 12.0, + "color" : [255, 0, 0], + "percentage" : 10 + } +} diff --git a/include/grabber/V4L2Grabber.h b/include/grabber/V4L2Grabber.h index c4fc5a27..b87deb29 100644 --- a/include/grabber/V4L2Grabber.h +++ b/include/grabber/V4L2Grabber.h @@ -23,103 +23,103 @@ /// @see http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html class V4L2Grabber : public QObject { - Q_OBJECT + Q_OBJECT public: - V4L2Grabber(const std::string & device, - int input, - VideoStandard videoStandard, PixelFormat pixelFormat, - int width, - int height, - int frameDecimation, - int horizontalPixelDecimation, - int verticalPixelDecimation); - virtual ~V4L2Grabber(); + V4L2Grabber(const std::string & device, + int input, + VideoStandard videoStandard, PixelFormat pixelFormat, + int width, + int height, + int frameDecimation, + int horizontalPixelDecimation, + int verticalPixelDecimation); + virtual ~V4L2Grabber(); public slots: - void setCropping(int cropLeft, - int cropRight, - int cropTop, - int cropBottom); + void setCropping(int cropLeft, + int cropRight, + int cropTop, + int cropBottom); - void set3D(VideoMode mode); + void set3D(VideoMode mode); - void setSignalThreshold(double redSignalThreshold, - double greenSignalThreshold, - double blueSignalThreshold, - int noSignalCounterThreshold); + void setSignalThreshold(double redSignalThreshold, + double greenSignalThreshold, + double blueSignalThreshold, + int noSignalCounterThreshold); - void start(); + void start(); - void stop(); + void stop(); signals: - void newFrame(const Image & image); + void newFrame(const Image & image); private slots: - int read_frame(); + int read_frame(); private: - void open_device(); + void open_device(); - void close_device(); + void close_device(); - void init_read(unsigned int buffer_size); + void init_read(unsigned int buffer_size); - void init_mmap(); + void init_mmap(); - void init_userp(unsigned int buffer_size); + void init_userp(unsigned int buffer_size); - void init_device(VideoStandard videoStandard, int input); + void init_device(VideoStandard videoStandard, int input); - void uninit_device(); + void uninit_device(); - void start_capturing(); + void start_capturing(); - void stop_capturing(); + void stop_capturing(); - bool process_image(const void *p, int size); + bool process_image(const void *p, int size); - void process_image(const uint8_t *p); + void process_image(const uint8_t *p); - int xioctl(int request, void *arg); + int xioctl(int request, void *arg); - void throw_exception(const std::string &error); + void throw_exception(const std::string &error); - void throw_errno_exception(const std::string &error); + void throw_errno_exception(const std::string &error); private: - enum io_method { - IO_METHOD_READ, - IO_METHOD_MMAP, - IO_METHOD_USERPTR - }; + enum io_method { + IO_METHOD_READ, + IO_METHOD_MMAP, + IO_METHOD_USERPTR + }; - struct buffer { - void *start; - size_t length; - }; + struct buffer { + void *start; + size_t length; + }; private: - const std::string _deviceName; - const io_method _ioMethod; - int _fileDescriptor; - std::vector _buffers; + const std::string _deviceName; + const io_method _ioMethod; + int _fileDescriptor; + std::vector _buffers; - PixelFormat _pixelFormat; - int _width; - int _height; - int _lineLength; - int _frameByteSize; - int _frameDecimation; - int _noSignalCounterThreshold; + PixelFormat _pixelFormat; + int _width; + int _height; + int _lineLength; + int _frameByteSize; + int _frameDecimation; + int _noSignalCounterThreshold; - ColorRgb _noSignalThresholdColor; + ColorRgb _noSignalThresholdColor; - int _currentFrame; - int _noSignalCounter; + int _currentFrame; + int _noSignalCounter; - QSocketNotifier * _streamNotifier; + QSocketNotifier * _streamNotifier; - ImageResampler _imageResampler; + ImageResampler _imageResampler; }; diff --git a/include/grabber/X11Grabber.h b/include/grabber/X11Grabber.h index d8e4783c..5c2dd3b2 100644 --- a/include/grabber/X11Grabber.h +++ b/include/grabber/X11Grabber.h @@ -15,7 +15,7 @@ class X11Grabber { public: - X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation); + X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation); virtual ~X11Grabber(); @@ -26,16 +26,16 @@ public: Image & grab(); private: - ImageResampler _imageResampler; - - bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable; - int _cropLeft; - int _cropRight; - int _cropTop; - int _cropBottom; - - XImage* _xImage; - XShmSegmentInfo _shminfo; + ImageResampler _imageResampler; + + bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable; + int _cropLeft; + int _cropRight; + int _cropTop; + int _cropBottom; + + XImage* _xImage; + XShmSegmentInfo _shminfo; /// Reference to the X11 display (nullptr if not opened) Display* _x11Display; diff --git a/include/protoserver/ProtoConnection.h b/include/protoserver/ProtoConnection.h index 7ecd8f36..a6480eb6 100644 --- a/include/protoserver/ProtoConnection.h +++ b/include/protoserver/ProtoConnection.h @@ -23,90 +23,90 @@ class ProtoConnection : public QObject { -Q_OBJECT + Q_OBJECT public: - /// - /// Constructor - /// - /// @param address The address of the Hyperion server (for example "192.168.0.32:19444) - /// - ProtoConnection(const std::string & address); + /// + /// Constructor + /// + /// @param address The address of the Hyperion server (for example "192.168.0.32:19444) + /// + ProtoConnection(const std::string & address); - /// - /// Destructor - /// - ~ProtoConnection(); + /// + /// Destructor + /// + ~ProtoConnection(); - /// Do not read reply messages from Hyperion if set to true - void setSkipReply(bool skip); + /// Do not read reply messages from Hyperion if set to true + void setSkipReply(bool skip); - /// - /// Set all leds to the specified color - /// - /// @param color The color - /// @param priority The priority - /// @param duration The duration in milliseconds - /// - void setColor(const ColorRgb & color, int priority, int duration = 1); + /// + /// Set all leds to the specified color + /// + /// @param color The color + /// @param priority The priority + /// @param duration The duration in milliseconds + /// + void setColor(const ColorRgb & color, int priority, int duration = 1); - /// - /// Set the leds according to the given image (assume the image is stretched to the display size) - /// - /// @param image The image - /// @param priority The priority - /// @param duration The duration in milliseconds - /// - void setImage(const Image & image, int priority, int duration = -1); + /// + /// Set the leds according to the given image (assume the image is stretched to the display size) + /// + /// @param image The image + /// @param priority The priority + /// @param duration The duration in milliseconds + /// + void setImage(const Image & image, int priority, int duration = -1); - /// - /// Clear the given priority channel - /// - /// @param priority The priority - /// - void clear(int priority); + /// + /// Clear the given priority channel + /// + /// @param priority The priority + /// + void clear(int priority); - /// - /// Clear all priority channels - /// - void clearAll(); + /// + /// Clear all priority channels + /// + void clearAll(); - /// - /// Send a command message and receive its reply - /// - /// @param message The message to send - /// - void sendMessage(const proto::HyperionRequest & message); + /// + /// Send a command message and receive its reply + /// + /// @param message The message to send + /// + void sendMessage(const proto::HyperionRequest & message); private slots: - /// Try to connect to the Hyperion host - void connectToHost(); + /// Try to connect to the Hyperion host + void connectToHost(); private: - /// - /// Parse a reply message - /// - /// @param reply The received reply - /// - /// @return true if the reply indicates success - /// - bool parseReply(const proto::HyperionReply & reply); + /// + /// Parse a reply message + /// + /// @param reply The received reply + /// + /// @return true if the reply indicates success + /// + bool parseReply(const proto::HyperionReply & reply); private: - /// The TCP-Socket with the connection to the server - QTcpSocket _socket; + /// The TCP-Socket with the connection to the server + QTcpSocket _socket; - /// Host address - QString _host; + /// Host address + QString _host; - /// Host port - uint16_t _port; + /// Host port + uint16_t _port; - /// Skip receiving reply messages from Hyperion if set - bool _skipReply; + /// Skip receiving reply messages from Hyperion if set + bool _skipReply; - QTimer _timer; - QAbstractSocket::SocketState _prevSocketState; + QTimer _timer; + QAbstractSocket::SocketState _prevSocketState; }; diff --git a/include/protoserver/ProtoConnectionWrapper.h b/include/protoserver/ProtoConnectionWrapper.h index f5b072ea..7d2f3f6c 100644 --- a/include/protoserver/ProtoConnectionWrapper.h +++ b/include/protoserver/ProtoConnectionWrapper.h @@ -11,24 +11,24 @@ /// This class handles callbacks from the V4L2 grabber class ProtoConnectionWrapper : public QObject { - Q_OBJECT + Q_OBJECT public: - ProtoConnectionWrapper(const std::string & address, int priority, int duration_ms, bool skipProtoReply); - virtual ~ProtoConnectionWrapper(); + ProtoConnectionWrapper(const std::string & address, int priority, int duration_ms, bool skipProtoReply); + virtual ~ProtoConnectionWrapper(); public slots: - /// Handle a single image - /// @param image The image to process - void receiveImage(const Image & image); + /// Handle a single image + /// @param image The image to process + void receiveImage(const Image & image); private: - /// Priority for calls to Hyperion - const int _priority; + /// Priority for calls to Hyperion + const int _priority; - /// Duration for color calls to Hyperion - const int _duration_ms; + /// Duration for color calls to Hyperion + const int _duration_ms; - /// Hyperion proto connection object - ProtoConnection _connection; + /// Hyperion proto connection object + ProtoConnection _connection; }; diff --git a/include/utils/Image.h b/include/utils/Image.h index ece6155a..e8c82e48 100644 --- a/include/utils/Image.h +++ b/include/utils/Image.h @@ -13,221 +13,221 @@ class Image { public: - typedef Pixel_T pixel_type; + typedef Pixel_T pixel_type; - /// - /// Default constructor for an image - /// - Image() : - _width(1), - _height(1), - _pixels(new Pixel_T[2]), - _endOfPixels(_pixels + 1) - { - memset(_pixels, 0, 2*sizeof(Pixel_T)); - } + /// + /// Default constructor for an image + /// + Image() : + _width(1), + _height(1), + _pixels(new Pixel_T[2]), + _endOfPixels(_pixels + 1) + { + memset(_pixels, 0, 2*sizeof(Pixel_T)); + } - /// - /// Constructor for an image with specified width and height - /// - /// @param width The width of the image - /// @param height The height of the image - /// - Image(const unsigned width, const unsigned height) : - _width(width), - _height(height), - _pixels(new Pixel_T[width * height + 1]), - _endOfPixels(_pixels + width * height) - { - memset(_pixels, 0, (_width*_height+1)*sizeof(Pixel_T)); - } + /// + /// Constructor for an image with specified width and height + /// + /// @param width The width of the image + /// @param height The height of the image + /// + Image(const unsigned width, const unsigned height) : + _width(width), + _height(height), + _pixels(new Pixel_T[width * height + 1]), + _endOfPixels(_pixels + width * height) + { + memset(_pixels, 0, (_width*_height+1)*sizeof(Pixel_T)); + } - /// - /// Constructor for an image with specified width and height - /// - /// @param width The width of the image - /// @param height The height of the image - /// @param background The color of the image - /// - Image(const unsigned width, const unsigned height, const Pixel_T background) : - _width(width), - _height(height), - _pixels(new Pixel_T[width * height + 1]), - _endOfPixels(_pixels + width * height) - { - std::fill(_pixels, _endOfPixels, background); - } + /// + /// Constructor for an image with specified width and height + /// + /// @param width The width of the image + /// @param height The height of the image + /// @param background The color of the image + /// + Image(const unsigned width, const unsigned height, const Pixel_T background) : + _width(width), + _height(height), + _pixels(new Pixel_T[width * height + 1]), + _endOfPixels(_pixels + width * height) + { + std::fill(_pixels, _endOfPixels, background); + } - /// - /// Copy constructor for an image - /// - Image(const Image & other) : - _width(other._width), - _height(other._height), - _pixels(new Pixel_T[other._width * other._height + 1]), - _endOfPixels(_pixels + other._width * other._height) - { - memcpy(_pixels, other._pixels, other._width * other._height * sizeof(Pixel_T)); - } + /// + /// Copy constructor for an image + /// + Image(const Image & other) : + _width(other._width), + _height(other._height), + _pixels(new Pixel_T[other._width * other._height + 1]), + _endOfPixels(_pixels + other._width * other._height) + { + memcpy(_pixels, other._pixels, other._width * other._height * sizeof(Pixel_T)); + } - /// - /// Destructor - /// - ~Image() - { - delete[] _pixels; - } + /// + /// Destructor + /// + ~Image() + { + delete[] _pixels; + } - /// - /// Returns the width of the image - /// - /// @return The width of the image - /// - inline unsigned width() const - { - return _width; - } + /// + /// Returns the width of the image + /// + /// @return The width of the image + /// + inline unsigned width() const + { + return _width; + } - /// - /// Returns the height of the image - /// - /// @return The height of the image - /// - inline unsigned height() const - { - return _height; - } + /// + /// Returns the height of the image + /// + /// @return The height of the image + /// + inline unsigned height() const + { + return _height; + } - uint8_t red(const unsigned pixel) const - { - return (_pixels + pixel)->red; - } + uint8_t red(const unsigned pixel) const + { + return (_pixels + pixel)->red; + } - uint8_t green(const unsigned pixel) const - { - return (_pixels + pixel)->green; - } + uint8_t green(const unsigned pixel) const + { + return (_pixels + pixel)->green; + } - uint8_t blue(const unsigned pixel) const - { - return (_pixels + pixel)->blue; - } + uint8_t blue(const unsigned pixel) const + { + return (_pixels + pixel)->blue; + } - /// - /// Returns a const reference to a specified pixel in the image - /// - /// @param x The x index - /// @param y The y index - /// - /// @return const reference to specified pixel - /// - const Pixel_T& operator()(const unsigned x, const unsigned y) const - { - return _pixels[toIndex(x,y)]; - } + /// + /// Returns a const reference to a specified pixel in the image + /// + /// @param x The x index + /// @param y The y index + /// + /// @return const reference to specified pixel + /// + const Pixel_T& operator()(const unsigned x, const unsigned y) const + { + return _pixels[toIndex(x,y)]; + } - /// - /// Returns a reference to a specified pixel in the image - /// - /// @param x The x index - /// @param y The y index - /// - /// @return reference to specified pixel - /// - Pixel_T& operator()(const unsigned x, const unsigned y) - { - return _pixels[toIndex(x,y)]; - } + /// + /// Returns a reference to a specified pixel in the image + /// + /// @param x The x index + /// @param y The y index + /// + /// @return reference to specified pixel + /// + Pixel_T& operator()(const unsigned x, const unsigned y) + { + return _pixels[toIndex(x,y)]; + } - /// Resize the image - /// @param width The width of the image - /// @param height The height of the image - void resize(const unsigned width, const unsigned height) - { - if ((width*height) > unsigned((_endOfPixels-_pixels))) - { - delete[] _pixels; - _pixels = new Pixel_T[width*height + 1]; - _endOfPixels = _pixels + width*height; - } + /// Resize the image + /// @param width The width of the image + /// @param height The height of the image + void resize(const unsigned width, const unsigned height) + { + if ((width*height) > unsigned((_endOfPixels-_pixels))) + { + delete[] _pixels; + _pixels = new Pixel_T[width*height + 1]; + _endOfPixels = _pixels + width*height; + } - _width = width; - _height = height; - } + _width = width; + _height = height; + } - /// - /// Copies another image into this image. The images should have exactly the same size. - /// - /// @param other The image to copy into this - /// - void copy(const Image& other) - { - assert(other._width == _width); - assert(other._height == _height); + /// + /// Copies another image into this image. The images should have exactly the same size. + /// + /// @param other The image to copy into this + /// + void copy(const Image& other) + { + assert(other._width == _width); + assert(other._height == _height); - memcpy(_pixels, other._pixels, _width*_height*sizeof(Pixel_T)); - } + memcpy(_pixels, other._pixels, _width*_height*sizeof(Pixel_T)); + } - /// - /// Returns a memory pointer to the first pixel in the image - /// @return The memory pointer to the first pixel - /// - Pixel_T* memptr() - { - return _pixels; - } + /// + /// Returns a memory pointer to the first pixel in the image + /// @return The memory pointer to the first pixel + /// + Pixel_T* memptr() + { + return _pixels; + } - /// - /// Returns a const memory pointer to the first pixel in the image - /// @return The const memory pointer to the first pixel - /// - const Pixel_T* memptr() const - { - return _pixels; - } - - - /// - /// Convert image of any color order to a RGB image. - /// - /// @param[out] image The image that buffers the output - /// - void toRgb(Image& image) - { - image.resize(_width, _height); - const unsigned imageSize = _width * _height; + /// + /// Returns a const memory pointer to the first pixel in the image + /// @return The const memory pointer to the first pixel + /// + const Pixel_T* memptr() const + { + return _pixels; + } - for (unsigned idx=0; idx& image) + { + image.resize(_width, _height); + const unsigned imageSize = _width * _height; + + for (unsigned idx=0; idx & outputImage) const; + void processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat, Image & outputImage) const; private: static inline uint8_t clamp(int x); diff --git a/include/utils/PixelFormat.h b/include/utils/PixelFormat.h index 3b56bdad..472b18f2 100644 --- a/include/utils/PixelFormat.h +++ b/include/utils/PixelFormat.h @@ -11,9 +11,9 @@ enum PixelFormat { PIXELFORMAT_UYVY, PIXELFORMAT_BGR16, PIXELFORMAT_BGR24, - PIXELFORMAT_RGB32, - PIXELFORMAT_BGR32, - PIXELFORMAT_NO_CHANGE + PIXELFORMAT_RGB32, + PIXELFORMAT_BGR32, + PIXELFORMAT_NO_CHANGE }; inline PixelFormat parsePixelFormat(std::string pixelFormat) @@ -29,22 +29,22 @@ inline PixelFormat parsePixelFormat(std::string pixelFormat) { return PIXELFORMAT_UYVY; } - else if (pixelFormat == "bgr16") - { - return PIXELFORMAT_BGR16; - } - else if (pixelFormat == "bgr24") - { - return PIXELFORMAT_BGR24; - } - else if (pixelFormat == "rgb32") - { - return PIXELFORMAT_RGB32; - } - else if (pixelFormat == "bgr32") - { - return PIXELFORMAT_BGR32; - } + else if (pixelFormat == "bgr16") + { + return PIXELFORMAT_BGR16; + } + else if (pixelFormat == "bgr24") + { + return PIXELFORMAT_BGR24; + } + else if (pixelFormat == "rgb32") + { + return PIXELFORMAT_RGB32; + } + else if (pixelFormat == "bgr32") + { + return PIXELFORMAT_BGR32; + } // return the default NO_CHANGE return PIXELFORMAT_NO_CHANGE; diff --git a/include/utils/Sleep.h b/include/utils/Sleep.h index a2c55815..95d2aa68 100644 --- a/include/utils/Sleep.h +++ b/include/utils/Sleep.h @@ -4,7 +4,7 @@ class Sleep : protected QThread { public: - static inline void msleep(unsigned long msecs) { - QThread::msleep(msecs); - } + static inline void msleep(unsigned long msecs) { + QThread::msleep(msecs); + } }; diff --git a/include/utils/jsonschema/JsonSchemaChecker.h b/include/utils/jsonschema/JsonSchemaChecker.h index 768b57db..d03a11e5 100644 --- a/include/utils/jsonschema/JsonSchemaChecker.h +++ b/include/utils/jsonschema/JsonSchemaChecker.h @@ -1,192 +1,192 @@ -#pragma once - -// stl includes -#include -#include - -// jsoncpp includes -#include - - -/// JsonSchemaChecker is a very basic implementation of json schema. -/// The json schema definition draft can be found at -/// http://tools.ietf.org/html/draft-zyp-json-schema-03 -/// -/// The following keywords are supported: -/// - type -/// - required -/// - properties -/// - items -/// - enum -/// - minimum -/// - maximum -/// - addtionalProperties -/// - minItems -/// - maxItems -/// -/// And the non-standard: -/// - dependencies -class JsonSchemaChecker -{ -public: - JsonSchemaChecker(); - virtual ~JsonSchemaChecker(); - - /// - /// @param schema The schema to use - /// @return true upon succes - /// - bool setSchema(const Json::Value & schema); - - /// - /// @brief Validate a JSON structure - /// @param value The JSON value to check - /// @return true when the arguments is valid according to the schema - /// - bool validate(const Json::Value & value); - - /// - /// @return A list of error messages - /// - const std::list & getMessages() const; - -private: - /// - /// Validates a json-value against a given schema. Results are stored in the members of this - /// class (_error & _messages) - /// - /// @param[in] value The value to validate - /// @param[in] schema The schema against which the value is validated - /// - void validate(const Json::Value &value, const Json::Value & schema); - - /// - /// Adds the given message to the message-queue (with reference to current line-number) - /// - /// @param[in] message The message to add to the queue - /// - void setMessage(const std::string & message); - - /// - /// Retrieves all references from the json-value as specified by the schema - /// - /// @param[in] value The json-value - /// @param[in] schema The schema - /// - void collectDependencies(const Json::Value & value, const Json::Value &schema); - -private: - // attribute check functions - /// - /// Checks if the given value is of the specified type. If the type does not match _error is set - /// to true and an error-message is added to the message-queue - /// - /// @param[in] value The given value - /// @param[in] schema The specified type (as json-value) - /// - void checkType(const Json::Value & value, const Json::Value & schema); - /// - /// Checks is required properties of an json-object exist and if all properties are of the - /// correct format. If this is not the case _error is set to true and an error-message is added - /// to the message-queue. - /// - /// @param[in] value The given json-object - /// @param[in] schema The schema of the json-object - /// - void checkProperties(const Json::Value & value, const Json::Value & schema); - - /// - /// Verifies the additional configured properties of an json-object. If this is not the case - /// _error is set to true and an error-message is added to the message-queue. - /// - /// @param value The given json-object - /// @param schema The schema for the json-object - /// @param ignoredProperties The properties that were ignored - /// - void checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties); - - /// - /// Checks if references are configued and used correctly. If this is not the case _error is set - /// to true and an error-message is added to the message-queue. - /// - /// @param value The given json-object - /// @param schemaLink The schema of the json-object - /// - void checkDependencies(const Json::Value & value, const Json::Value & schemaLink); - - /// - /// Checks if the given value is larger or equal to the specified value. If this is not the case - /// _error is set to true and an error-message is added to the message-queue. - /// - /// @param[in] value The given value - /// @param[in] schema The minimum value (as json-value) - /// - void checkMinimum(const Json::Value & value, const Json::Value & schema); - - /// - /// Checks if the given value is smaller or equal to the specified value. If this is not the - /// case _error is set to true and an error-message is added to the message-queue. - /// - /// @param[in] value The given value - /// @param[in] schema The maximum value (as json-value) - /// - void checkMaximum(const Json::Value & value, const Json::Value & schema); - - /// - /// Validates all the items of an array. - /// - /// @param value The json-array - /// @param schema The schema for the items in the array - /// - void checkItems(const Json::Value & value, const Json::Value & schema); - - /// - /// Checks if a given array has at least a minimum number of items. If this is not the case - /// _error is set to true and an error-message is added to the message-queue. - /// - /// @param value The json-array - /// @param schema The minimum size specification (as json-value) - /// - void checkMinItems(const Json::Value & value, const Json::Value & schema); - - /// - /// Checks if a given array has at most a maximum number of items. If this is not the case - /// _error is set to true and an error-message is added to the message-queue. - /// - /// @param value The json-array - /// @param schema The maximum size specification (as json-value) - /// - void checkMaxItems(const Json::Value & value, const Json::Value & schema); - - /// - /// Checks if a given array contains only unique items. If this is not the case - /// _error is set to true and an error-message is added to the message-queue. - /// - /// @param value The json-array - /// @param schema Bool to enable the check (as json-value) - /// - void checkUniqueItems(const Json::Value & value, const Json::Value & schema); - - /// - /// Checks if an enum value is actually a valid value for that enum. If this is not the case - /// _error is set to true and an error-message is added to the message-queue. - /// - /// @param value The enum value - /// @param schema The enum schema definition - /// - void checkEnum(const Json::Value & value, const Json::Value & schema); - -private: - /// The schema of the entire json-configuration - Json::Value _schema; - - /// The current location into a json-configuration structure being checked - std::list _currentPath; - /// The result messages collected during the schema verification - std::list _messages; - /// Flag indicating an error occured during validation - bool _error; - - /// A list with references (string => json-value) - std::map _references; // ref 2 value -}; +#pragma once + +// stl includes +#include +#include + +// jsoncpp includes +#include + + +/// JsonSchemaChecker is a very basic implementation of json schema. +/// The json schema definition draft can be found at +/// http://tools.ietf.org/html/draft-zyp-json-schema-03 +/// +/// The following keywords are supported: +/// - type +/// - required +/// - properties +/// - items +/// - enum +/// - minimum +/// - maximum +/// - addtionalProperties +/// - minItems +/// - maxItems +/// +/// And the non-standard: +/// - dependencies +class JsonSchemaChecker +{ +public: + JsonSchemaChecker(); + virtual ~JsonSchemaChecker(); + + /// + /// @param schema The schema to use + /// @return true upon succes + /// + bool setSchema(const Json::Value & schema); + + /// + /// @brief Validate a JSON structure + /// @param value The JSON value to check + /// @return true when the arguments is valid according to the schema + /// + bool validate(const Json::Value & value); + + /// + /// @return A list of error messages + /// + const std::list & getMessages() const; + +private: + /// + /// Validates a json-value against a given schema. Results are stored in the members of this + /// class (_error & _messages) + /// + /// @param[in] value The value to validate + /// @param[in] schema The schema against which the value is validated + /// + void validate(const Json::Value &value, const Json::Value & schema); + + /// + /// Adds the given message to the message-queue (with reference to current line-number) + /// + /// @param[in] message The message to add to the queue + /// + void setMessage(const std::string & message); + + /// + /// Retrieves all references from the json-value as specified by the schema + /// + /// @param[in] value The json-value + /// @param[in] schema The schema + /// + void collectDependencies(const Json::Value & value, const Json::Value &schema); + +private: + // attribute check functions + /// + /// Checks if the given value is of the specified type. If the type does not match _error is set + /// to true and an error-message is added to the message-queue + /// + /// @param[in] value The given value + /// @param[in] schema The specified type (as json-value) + /// + void checkType(const Json::Value & value, const Json::Value & schema); + /// + /// Checks is required properties of an json-object exist and if all properties are of the + /// correct format. If this is not the case _error is set to true and an error-message is added + /// to the message-queue. + /// + /// @param[in] value The given json-object + /// @param[in] schema The schema of the json-object + /// + void checkProperties(const Json::Value & value, const Json::Value & schema); + + /// + /// Verifies the additional configured properties of an json-object. If this is not the case + /// _error is set to true and an error-message is added to the message-queue. + /// + /// @param value The given json-object + /// @param schema The schema for the json-object + /// @param ignoredProperties The properties that were ignored + /// + void checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties); + + /// + /// Checks if references are configued and used correctly. If this is not the case _error is set + /// to true and an error-message is added to the message-queue. + /// + /// @param value The given json-object + /// @param schemaLink The schema of the json-object + /// + void checkDependencies(const Json::Value & value, const Json::Value & schemaLink); + + /// + /// Checks if the given value is larger or equal to the specified value. If this is not the case + /// _error is set to true and an error-message is added to the message-queue. + /// + /// @param[in] value The given value + /// @param[in] schema The minimum value (as json-value) + /// + void checkMinimum(const Json::Value & value, const Json::Value & schema); + + /// + /// Checks if the given value is smaller or equal to the specified value. If this is not the + /// case _error is set to true and an error-message is added to the message-queue. + /// + /// @param[in] value The given value + /// @param[in] schema The maximum value (as json-value) + /// + void checkMaximum(const Json::Value & value, const Json::Value & schema); + + /// + /// Validates all the items of an array. + /// + /// @param value The json-array + /// @param schema The schema for the items in the array + /// + void checkItems(const Json::Value & value, const Json::Value & schema); + + /// + /// Checks if a given array has at least a minimum number of items. If this is not the case + /// _error is set to true and an error-message is added to the message-queue. + /// + /// @param value The json-array + /// @param schema The minimum size specification (as json-value) + /// + void checkMinItems(const Json::Value & value, const Json::Value & schema); + + /// + /// Checks if a given array has at most a maximum number of items. If this is not the case + /// _error is set to true and an error-message is added to the message-queue. + /// + /// @param value The json-array + /// @param schema The maximum size specification (as json-value) + /// + void checkMaxItems(const Json::Value & value, const Json::Value & schema); + + /// + /// Checks if a given array contains only unique items. If this is not the case + /// _error is set to true and an error-message is added to the message-queue. + /// + /// @param value The json-array + /// @param schema Bool to enable the check (as json-value) + /// + void checkUniqueItems(const Json::Value & value, const Json::Value & schema); + + /// + /// Checks if an enum value is actually a valid value for that enum. If this is not the case + /// _error is set to true and an error-message is added to the message-queue. + /// + /// @param value The enum value + /// @param schema The enum schema definition + /// + void checkEnum(const Json::Value & value, const Json::Value & schema); + +private: + /// The schema of the entire json-configuration + Json::Value _schema; + + /// The current location into a json-configuration structure being checked + std::list _currentPath; + /// The result messages collected during the schema verification + std::list _messages; + /// Flag indicating an error occured during validation + bool _error; + + /// A list with references (string => json-value) + std::map _references; // ref 2 value +}; diff --git a/libsrc/CMakeLists.txt b/libsrc/CMakeLists.txt index 680e7a53..38ced39a 100644 --- a/libsrc/CMakeLists.txt +++ b/libsrc/CMakeLists.txt @@ -9,7 +9,7 @@ add_subdirectory(jsonserver) if (ENABLE_PROTOBUF) add_subdirectory(protoserver) -endif (ENABLE_PROTOBUF) +endif () add_subdirectory(boblightserver) add_subdirectory(leddevice) diff --git a/libsrc/blackborder/CMakeLists.txt b/libsrc/blackborder/CMakeLists.txt index 0d693c89..97d62739 100644 --- a/libsrc/blackborder/CMakeLists.txt +++ b/libsrc/blackborder/CMakeLists.txt @@ -1,23 +1,23 @@ - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/blackborder) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/blackborder) - -SET(Blackborder_HEADERS - ${CURRENT_HEADER_DIR}/BlackBorderDetector.h - ${CURRENT_HEADER_DIR}/BlackBorderProcessor.h -) - -SET(Blackborder_SOURCES - ${CURRENT_SOURCE_DIR}/BlackBorderDetector.cpp - ${CURRENT_SOURCE_DIR}/BlackBorderProcessor.cpp -) - -add_library(blackborder - ${Blackborder_HEADERS} - ${Blackborder_SOURCES} -) - -target_link_libraries(blackborder - hyperion-utils -) + +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/blackborder) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/blackborder) + +SET(Blackborder_HEADERS + ${CURRENT_HEADER_DIR}/BlackBorderDetector.h + ${CURRENT_HEADER_DIR}/BlackBorderProcessor.h +) + +SET(Blackborder_SOURCES + ${CURRENT_SOURCE_DIR}/BlackBorderDetector.cpp + ${CURRENT_SOURCE_DIR}/BlackBorderProcessor.cpp +) + +add_library(blackborder + ${Blackborder_HEADERS} + ${Blackborder_SOURCES} +) + +target_link_libraries(blackborder + hyperion-utils +) diff --git a/libsrc/boblightserver/CMakeLists.txt b/libsrc/boblightserver/CMakeLists.txt index 33be4d17..c7a0e12d 100644 --- a/libsrc/boblightserver/CMakeLists.txt +++ b/libsrc/boblightserver/CMakeLists.txt @@ -1,40 +1,40 @@ - -# Define the current source locations -set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/boblightserver) -set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/boblightserver) - -# Group the headers that go through the MOC compiler -set(BoblightServer_QT_HEADERS - ${CURRENT_HEADER_DIR}/BoblightServer.h - ${CURRENT_SOURCE_DIR}/BoblightClientConnection.h -) - -set(BoblightServer_HEADERS -) - -set(BoblightServer_SOURCES - ${CURRENT_SOURCE_DIR}/BoblightServer.cpp - ${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} - ${BoblightServer_QT_HEADERS} - ${BoblightServer_SOURCES} - ${BoblightServer_HEADERS_MOC} -) - -if(ENABLE_QT5) -qt5_use_modules(boblightserver Widgets) -endif(ENABLE_QT5) - -target_link_libraries(boblightserver - hyperion - hyperion-utils - ${QT_LIBRARIES}) + +# Define the current source locations +set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/boblightserver) +set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/boblightserver) + +# Group the headers that go through the MOC compiler +set(BoblightServer_QT_HEADERS + ${CURRENT_HEADER_DIR}/BoblightServer.h + ${CURRENT_SOURCE_DIR}/BoblightClientConnection.h +) + +set(BoblightServer_HEADERS +) + +set(BoblightServer_SOURCES + ${CURRENT_SOURCE_DIR}/BoblightServer.cpp + ${CURRENT_SOURCE_DIR}/BoblightClientConnection.cpp +) + +if(ENABLE_QT5) + qt5_wrap_cpp(BoblightServer_HEADERS_MOC ${BoblightServer_QT_HEADERS}) +else() + qt4_wrap_cpp(BoblightServer_HEADERS_MOC ${BoblightServer_QT_HEADERS}) +endif() + +add_library(boblightserver + ${BoblightServer_HEADERS} + ${BoblightServer_QT_HEADERS} + ${BoblightServer_SOURCES} + ${BoblightServer_HEADERS_MOC} +) + +if(ENABLE_QT5) + qt5_use_modules(boblightserver Widgets) +endif() + +target_link_libraries(boblightserver + hyperion + hyperion-utils + ${QT_LIBRARIES}) diff --git a/libsrc/effectengine/CMakeLists.txt b/libsrc/effectengine/CMakeLists.txt index adb430e0..e3133213 100644 --- a/libsrc/effectengine/CMakeLists.txt +++ b/libsrc/effectengine/CMakeLists.txt @@ -13,8 +13,8 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/effectengine) # Group the headers that go through the MOC compiler SET(EffectEngineQT_HEADERS - ${CURRENT_HEADER_DIR}/EffectEngine.h - ${CURRENT_SOURCE_DIR}/Effect.h + ${CURRENT_HEADER_DIR}/EffectEngine.h + ${CURRENT_SOURCE_DIR}/Effect.h ) SET(EffectEngineHEADERS @@ -22,35 +22,34 @@ SET(EffectEngineHEADERS ) SET(EffectEngineSOURCES - ${CURRENT_SOURCE_DIR}/EffectEngine.cpp - ${CURRENT_SOURCE_DIR}/Effect.cpp + ${CURRENT_SOURCE_DIR}/EffectEngine.cpp + ${CURRENT_SOURCE_DIR}/Effect.cpp ) - 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) + QT5_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS}) + qt5_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress") +else() + QT4_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS}) + qt4_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress") +endif() add_library(effectengine - ${EffectEngineHEADERS} - ${EffectEngineQT_HEADERS} - ${EffectEngineHEADERS_MOC} - ${EffectEngine_RESOURCES_RCC} - ${EffectEngineSOURCES} + ${EffectEngineHEADERS} + ${EffectEngineQT_HEADERS} + ${EffectEngineHEADERS_MOC} + ${EffectEngine_RESOURCES_RCC} + ${EffectEngineSOURCES} ) if(ENABLE_QT5) -qt5_use_modules(effectengine Widgets) -endif(ENABLE_QT5) + qt5_use_modules(effectengine Widgets) +endif() target_link_libraries(effectengine - hyperion - jsoncpp - ${QT_LIBRARIES} - ${PYTHON_LIBRARIES}) + hyperion + jsoncpp + ${QT_LIBRARIES} + ${PYTHON_LIBRARIES}) diff --git a/libsrc/effectengine/EffectDefinition.schema.json b/libsrc/effectengine/EffectDefinition.schema.json index 44733252..aa9c106a 100644 --- a/libsrc/effectengine/EffectDefinition.schema.json +++ b/libsrc/effectengine/EffectDefinition.schema.json @@ -1,342 +1,342 @@ -{ - "type" : "object", - "required" : true, - "properties" : { - "device" : { - "type" : "object", - "required" : true, - "properties" : { - "name" : { - "type" : "string", - "required" : true - }, - "type" : { - "type" : "string", - "required" : true - }, - "output" : { - "type" : "string", - "required" : true - }, - "rate" : { - "type" : "integer", - "required" : true, - "minimum" : 0 - }, - "colorOrder" : { - "type" : "string", - "required" : false - }, - "bgr-output" : { // deprecated - "type" : "boolean", - "required" : false - } - }, - "additionalProperties" : false - }, - "color": { - "type":"object", - "required":false, - "properties": { - "hsv" : { - "type" : "object", - "required" : false, - "properties" : { - "saturationGain" : { - "type" : "number", - "required" : false, - "minimum" : 0.0 - }, - "valueGain" : { - "type" : "number", - "required" : false, - "minimum" : 0.0 - } - }, - "additionalProperties" : false - }, - "red": { - "type":"object", - "required":false, - "properties":{ - "gamma": { - "type":"number", - "required":false - }, - "blacklevel": { - "type":"number", - "required":false - }, - "whitelevel": { - "type":"number", - "required":false - }, - "threshold": { - "type":"number", - "required":false, - "minimum" : 0.0, - "maximum" : 1.0 - } - }, - "additionalProperties" : false - }, - "green": { - "type":"object", - "required":false, - "properties":{ - "gamma": { - "type":"number", - "required":false - }, - "blacklevel": { - "type":"number", - "required":false - }, - "whitelevel": { - "type":"number", - "required":false - }, - "threshold": { - "type":"number", - "required":false, - "minimum" : 0.0, - "maximum" : 1.0 - } - }, - "additionalProperties" : false - }, - "blue": { - "type":"object", - "required":false, - "properties":{ - "gamma": { - "type":"number", - "required":false - }, - "whitelevel": { - "type":"number", - "required":false - }, - "blacklevel": { - "type":"number", - "required":false - }, - "threshold": { - "type":"number", - "required":false, - "minimum" : 0.0, - "maximum" : 1.0 - } - }, - "additionalProperties" : false - }, - "smoothing" : { - "type" : "object", - "required" : false, - "properties" : { - "type" : { - "type" : "enum", - "required" : true, - "values" : ["none", "linear"] - }, - "time_ms" : { - "type" : "integer", - "required" : false, - "minimum" : 10 - }, - "updateFrequency" : { - "type" : "number", - "required" : false, - "minimum" : 0.001 - } - }, - "additionalProperties" : false - } - - }, - "additionalProperties" : false - }, - "leds": { - "type":"array", - "required":true, - "items": { - "type":"object", - "properties": { - "index": { - "type":"integer", - "required":true - }, - "hscan": { - "type":"object", - "required":true, - "properties": { - "minimum": { - "type":"number", - "required":true - }, - "maximum": { - "type":"number", - "required":true - } - }, - "additionalProperties" : false - }, - "vscan": { - "type":"object", - "required":true, - "properties": { - "minimum": { - "type":"number", - "required":true - }, - "maximum": { - "type":"number", - "required":true - } - }, - "additionalProperties" : false - } - }, - "additionalProperties" : false - } - }, - "effects" : - { - "type" : "object", - "required" : false, - "properties" : { - "paths" : { - "type" : "array", - "required" : false, - "items" : { - "type" : "string" - } - } - }, - "additionalProperties" : false - }, - "blackborderdetector" : - { - "type" : "object", - "required" : false, - "properties" : { - "enable" : { - "type" : "boolean", - "required" : true - } - }, - "additionalProperties" : false - }, - "xbmcVideoChecker" : - { - "type" : "object", - "required" : false, - "properties" : { - "xbmcAddress" : { - "type" : "string", - "required" : true - }, - "xbmcTcpPort" : { - "type" : "integer", - "required" : true - }, - "grabVideo" : { - "type" : "boolean", - "required" : true - }, - "grabPictures" : { - "type" : "boolean", - "required" : true - }, - "grabAudio" : { - "type" : "boolean", - "required" : true - }, - "grabMenu" : { - "type" : "boolean", - "required" : true - } - }, - "additionalProperties" : false - }, - "bootsequence" : - { - "type" : "object", - "required" : false, - "properties" : { - "path" : { - "type" : "string", - "required" : true - }, - "effect" : { - "type" : "string", - "required" : true - } - }, - "additionalProperties" : false - }, - "framegrabber" : - { - "type" : "object", - "required" : false, - "properties" : { - "width" : { - "type" : "integer", - "required" : true - }, - "height" : { - "type" : "integer", - "required" : true - }, - "frequency_Hz" : { - "type" : "integer", - "required" : true - } - }, - "additionalProperties" : false - }, - "jsonServer" : - { - "type" : "object", - "required" : false, - "properties" : { - "port" : { - "type" : "integer", - "required" : true, - "minimum" : 0, - "maximum" : 65535 - } - }, - "additionalProperties" : false - }, - "protoServer" : - { - "type" : "object", - "required" : false, - "properties" : { - "port" : { - "type" : "integer", - "required" : true, - "minimum" : 0, - "maximum" : 65535 - } - }, - "additionalProperties" : false - }, - "boblightServer" : - { - "type" : "object", - "required" : false, - "properties" : { - "port" : { - "type" : "integer", - "required" : true, - "minimum" : 0, - "maximum" : 65535 - } - }, - "additionalProperties" : false - } - }, - "additionalProperties" : false -} +{ + "type" : "object", + "required" : true, + "properties" : { + "device" : { + "type" : "object", + "required" : true, + "properties" : { + "name" : { + "type" : "string", + "required" : true + }, + "type" : { + "type" : "string", + "required" : true + }, + "output" : { + "type" : "string", + "required" : true + }, + "rate" : { + "type" : "integer", + "required" : true, + "minimum" : 0 + }, + "colorOrder" : { + "type" : "string", + "required" : false + }, + "bgr-output" : { // deprecated + "type" : "boolean", + "required" : false + } + }, + "additionalProperties" : false + }, + "color": { + "type":"object", + "required":false, + "properties": { + "hsv" : { + "type" : "object", + "required" : false, + "properties" : { + "saturationGain" : { + "type" : "number", + "required" : false, + "minimum" : 0.0 + }, + "valueGain" : { + "type" : "number", + "required" : false, + "minimum" : 0.0 + } + }, + "additionalProperties" : false + }, + "red": { + "type":"object", + "required":false, + "properties":{ + "gamma": { + "type":"number", + "required":false + }, + "blacklevel": { + "type":"number", + "required":false + }, + "whitelevel": { + "type":"number", + "required":false + }, + "threshold": { + "type":"number", + "required":false, + "minimum" : 0.0, + "maximum" : 1.0 + } + }, + "additionalProperties" : false + }, + "green": { + "type":"object", + "required":false, + "properties":{ + "gamma": { + "type":"number", + "required":false + }, + "blacklevel": { + "type":"number", + "required":false + }, + "whitelevel": { + "type":"number", + "required":false + }, + "threshold": { + "type":"number", + "required":false, + "minimum" : 0.0, + "maximum" : 1.0 + } + }, + "additionalProperties" : false + }, + "blue": { + "type":"object", + "required":false, + "properties":{ + "gamma": { + "type":"number", + "required":false + }, + "whitelevel": { + "type":"number", + "required":false + }, + "blacklevel": { + "type":"number", + "required":false + }, + "threshold": { + "type":"number", + "required":false, + "minimum" : 0.0, + "maximum" : 1.0 + } + }, + "additionalProperties" : false + }, + "smoothing" : { + "type" : "object", + "required" : false, + "properties" : { + "type" : { + "type" : "enum", + "required" : true, + "values" : ["none", "linear"] + }, + "time_ms" : { + "type" : "integer", + "required" : false, + "minimum" : 10 + }, + "updateFrequency" : { + "type" : "number", + "required" : false, + "minimum" : 0.001 + } + }, + "additionalProperties" : false + } + + }, + "additionalProperties" : false + }, + "leds": { + "type":"array", + "required":true, + "items": { + "type":"object", + "properties": { + "index": { + "type":"integer", + "required":true + }, + "hscan": { + "type":"object", + "required":true, + "properties": { + "minimum": { + "type":"number", + "required":true + }, + "maximum": { + "type":"number", + "required":true + } + }, + "additionalProperties" : false + }, + "vscan": { + "type":"object", + "required":true, + "properties": { + "minimum": { + "type":"number", + "required":true + }, + "maximum": { + "type":"number", + "required":true + } + }, + "additionalProperties" : false + } + }, + "additionalProperties" : false + } + }, + "effects" : + { + "type" : "object", + "required" : false, + "properties" : { + "paths" : { + "type" : "array", + "required" : false, + "items" : { + "type" : "string" + } + } + }, + "additionalProperties" : false + }, + "blackborderdetector" : + { + "type" : "object", + "required" : false, + "properties" : { + "enable" : { + "type" : "boolean", + "required" : true + } + }, + "additionalProperties" : false + }, + "xbmcVideoChecker" : + { + "type" : "object", + "required" : false, + "properties" : { + "xbmcAddress" : { + "type" : "string", + "required" : true + }, + "xbmcTcpPort" : { + "type" : "integer", + "required" : true + }, + "grabVideo" : { + "type" : "boolean", + "required" : true + }, + "grabPictures" : { + "type" : "boolean", + "required" : true + }, + "grabAudio" : { + "type" : "boolean", + "required" : true + }, + "grabMenu" : { + "type" : "boolean", + "required" : true + } + }, + "additionalProperties" : false + }, + "bootsequence" : + { + "type" : "object", + "required" : false, + "properties" : { + "path" : { + "type" : "string", + "required" : true + }, + "effect" : { + "type" : "string", + "required" : true + } + }, + "additionalProperties" : false + }, + "framegrabber" : + { + "type" : "object", + "required" : false, + "properties" : { + "width" : { + "type" : "integer", + "required" : true + }, + "height" : { + "type" : "integer", + "required" : true + }, + "frequency_Hz" : { + "type" : "integer", + "required" : true + } + }, + "additionalProperties" : false + }, + "jsonServer" : + { + "type" : "object", + "required" : false, + "properties" : { + "port" : { + "type" : "integer", + "required" : true, + "minimum" : 0, + "maximum" : 65535 + } + }, + "additionalProperties" : false + }, + "protoServer" : + { + "type" : "object", + "required" : false, + "properties" : { + "port" : { + "type" : "integer", + "required" : true, + "minimum" : 0, + "maximum" : 65535 + } + }, + "additionalProperties" : false + }, + "boblightServer" : + { + "type" : "object", + "required" : false, + "properties" : { + "port" : { + "type" : "integer", + "required" : true, + "minimum" : 0, + "maximum" : 65535 + } + }, + "additionalProperties" : false + } + }, + "additionalProperties" : false +} diff --git a/libsrc/grabber/CMakeLists.txt b/libsrc/grabber/CMakeLists.txt index bb35f046..a075e79d 100644 --- a/libsrc/grabber/CMakeLists.txt +++ b/libsrc/grabber/CMakeLists.txt @@ -1,23 +1,23 @@ -if (ENABLE_AMLOGIC) - add_subdirectory(amlogic) -endif (ENABLE_AMLOGIC) - -if (ENABLE_DISPMANX) - add_subdirectory(dispmanx) -endif (ENABLE_DISPMANX) - -if (ENABLE_FB) - add_subdirectory(framebuffer) -endif (ENABLE_FB) - -if (ENABLE_OSX) - add_subdirectory(osx) -endif() - -if (ENABLE_V4L2) - add_subdirectory(v4l2) -endif (ENABLE_V4L2) - -if (ENABLE_X11) - add_subdirectory(x11) -endif() +if (ENABLE_AMLOGIC) + add_subdirectory(amlogic) +endif (ENABLE_AMLOGIC) + +if (ENABLE_DISPMANX) + add_subdirectory(dispmanx) +endif (ENABLE_DISPMANX) + +if (ENABLE_FB) + add_subdirectory(framebuffer) +endif (ENABLE_FB) + +if (ENABLE_OSX) + add_subdirectory(osx) +endif() + +if (ENABLE_V4L2) + add_subdirectory(v4l2) +endif (ENABLE_V4L2) + +if (ENABLE_X11) + add_subdirectory(x11) +endif() diff --git a/libsrc/grabber/amlogic/CMakeLists.txt b/libsrc/grabber/amlogic/CMakeLists.txt index 9ec98bfe..cf8844b9 100644 --- a/libsrc/grabber/amlogic/CMakeLists.txt +++ b/libsrc/grabber/amlogic/CMakeLists.txt @@ -1,33 +1,33 @@ - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/amlogic) - -# Group the headers that go through the MOC compiler -SET(AmlogicQT_HEADERS ${CURRENT_HEADER_DIR}/AmlogicWrapper.h) - -SET(AmlogicHEADERS - ${CURRENT_HEADER_DIR}/AmlogicGrabber.h -) - -SET(AmlogicSOURCES - ${CURRENT_SOURCE_DIR}/AmlogicWrapper.cpp - ${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} - ${AmlogicQT_HEADERS} - ${AmlogicHEADERS_MOC} - ${AmlogicSOURCES} -) - -target_link_libraries(amlogic-grabber - hyperion - ${QT_LIBRARIES}) + +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/amlogic) + +# Group the headers that go through the MOC compiler +SET(AmlogicQT_HEADERS ${CURRENT_HEADER_DIR}/AmlogicWrapper.h) + +SET(AmlogicHEADERS + ${CURRENT_HEADER_DIR}/AmlogicGrabber.h +) + +SET(AmlogicSOURCES + ${CURRENT_SOURCE_DIR}/AmlogicWrapper.cpp + ${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} + ${AmlogicQT_HEADERS} + ${AmlogicHEADERS_MOC} + ${AmlogicSOURCES} +) + +target_link_libraries(amlogic-grabber + hyperion + ${QT_LIBRARIES}) diff --git a/libsrc/grabber/dispmanx/CMakeLists.txt b/libsrc/grabber/dispmanx/CMakeLists.txt index 4eb59e64..b453e3ab 100644 --- a/libsrc/grabber/dispmanx/CMakeLists.txt +++ b/libsrc/grabber/dispmanx/CMakeLists.txt @@ -1,41 +1,41 @@ - -# Find the BCM-package (VC control) -find_package(BCM REQUIRED) -include_directories(${BCM_INCLUDE_DIRS}) - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx) - -# Group the headers that go through the MOC compiler -SET(DispmanxGrabberQT_HEADERS - ${CURRENT_HEADER_DIR}/DispmanxWrapper.h -) - -SET(DispmanxGrabberHEADERS - ${CURRENT_HEADER_DIR}/DispmanxFrameGrabber.h -) - -SET(DispmanxGrabberSOURCES - ${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp - ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp -) - -if(ENABLE_QT5) - QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) -else(ENABLE_QT5) - QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) -endif(ENABLE_QT5) - -add_library(dispmanx-grabber - ${DispmanxGrabberHEADERS} - ${DispmanxGrabberQT_HEADERS} - ${DispmanxGrabberHEADERS_MOC} - ${DispmanxGrabberSOURCES} -) - -target_link_libraries(dispmanx-grabber - hyperion - ${QT_LIBRARIES} - ${BCM_LIBRARIES} -) + +# Find the BCM-package (VC control) +find_package(BCM REQUIRED) +include_directories(${BCM_INCLUDE_DIRS}) + +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx) + +# Group the headers that go through the MOC compiler +SET(DispmanxGrabberQT_HEADERS + ${CURRENT_HEADER_DIR}/DispmanxWrapper.h +) + +SET(DispmanxGrabberHEADERS + ${CURRENT_HEADER_DIR}/DispmanxFrameGrabber.h +) + +SET(DispmanxGrabberSOURCES + ${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp + ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp +) + +if(ENABLE_QT5) + QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) +else() + QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) +endif() + +add_library(dispmanx-grabber + ${DispmanxGrabberHEADERS} + ${DispmanxGrabberQT_HEADERS} + ${DispmanxGrabberHEADERS_MOC} + ${DispmanxGrabberSOURCES} +) + +target_link_libraries(dispmanx-grabber + hyperion + ${QT_LIBRARIES} + ${BCM_LIBRARIES} +) diff --git a/libsrc/grabber/framebuffer/CMakeLists.txt b/libsrc/grabber/framebuffer/CMakeLists.txt index 0dec11f4..c001155c 100644 --- a/libsrc/grabber/framebuffer/CMakeLists.txt +++ b/libsrc/grabber/framebuffer/CMakeLists.txt @@ -9,31 +9,31 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/framebuffer) # Group the headers that go through the MOC compiler SET(FramebufferGrabberQT_HEADERS - ${CURRENT_HEADER_DIR}/FramebufferWrapper.h + ${CURRENT_HEADER_DIR}/FramebufferWrapper.h ) SET(FramebufferGrabberHEADERS - ${CURRENT_HEADER_DIR}/FramebufferFrameGrabber.h + ${CURRENT_HEADER_DIR}/FramebufferFrameGrabber.h ) SET(FramebufferGrabberSOURCES - ${CURRENT_SOURCE_DIR}/FramebufferWrapper.cpp - ${CURRENT_SOURCE_DIR}/FramebufferFrameGrabber.cpp + ${CURRENT_SOURCE_DIR}/FramebufferWrapper.cpp + ${CURRENT_SOURCE_DIR}/FramebufferFrameGrabber.cpp ) if(ENABLE_QT5) QT5_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS}) -else(ENABLE_QT5) +else() QT4_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS}) -endif(ENABLE_QT5) +endif() add_library(framebuffer-grabber - ${FramebufferGrabberHEADERS} - ${FramebufferGrabberQT_HEADERS} - ${FramebufferGrabberHEADERS_MOC} - ${FramebufferGrabberSOURCES} + ${FramebufferGrabberHEADERS} + ${FramebufferGrabberQT_HEADERS} + ${FramebufferGrabberHEADERS_MOC} + ${FramebufferGrabberSOURCES} ) target_link_libraries(framebuffer-grabber - hyperion - ${QT_LIBRARIES}) + hyperion + ${QT_LIBRARIES}) diff --git a/libsrc/grabber/osx/CMakeLists.txt b/libsrc/grabber/osx/CMakeLists.txt index ca72df4c..63bdfaa4 100644 --- a/libsrc/grabber/osx/CMakeLists.txt +++ b/libsrc/grabber/osx/CMakeLists.txt @@ -4,31 +4,31 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/osx) # Group the headers that go through the MOC compiler SET(OsxGrabberQT_HEADERS - ${CURRENT_HEADER_DIR}/OsxWrapper.h + ${CURRENT_HEADER_DIR}/OsxWrapper.h ) SET(OsxGrabberHEADERS - ${CURRENT_HEADER_DIR}/OsxFrameGrabber.h + ${CURRENT_HEADER_DIR}/OsxFrameGrabber.h ) SET(OsxGrabberSOURCES - ${CURRENT_SOURCE_DIR}/OsxWrapper.cpp - ${CURRENT_SOURCE_DIR}/OsxFrameGrabber.cpp + ${CURRENT_SOURCE_DIR}/OsxWrapper.cpp + ${CURRENT_SOURCE_DIR}/OsxFrameGrabber.cpp ) if(ENABLE_QT5) QT5_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS}) -else(ENABLE_QT5) +else() QT4_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS}) -endif(ENABLE_QT5) +endif() add_library(osx-grabber - ${OsxGrabberHEADERS} - ${OsxGrabberQT_HEADERS} - ${OsxGrabberHEADERS_MOC} - ${OsxGrabberSOURCES} + ${OsxGrabberHEADERS} + ${OsxGrabberQT_HEADERS} + ${OsxGrabberHEADERS_MOC} + ${OsxGrabberSOURCES} ) target_link_libraries(osx-grabber - hyperion - ${QT_LIBRARIES}) + hyperion + ${QT_LIBRARIES}) diff --git a/libsrc/grabber/v4l2/CMakeLists.txt b/libsrc/grabber/v4l2/CMakeLists.txt index 71de7806..56f81814 100644 --- a/libsrc/grabber/v4l2/CMakeLists.txt +++ b/libsrc/grabber/v4l2/CMakeLists.txt @@ -1,39 +1,39 @@ -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/v4l2) - -SET(V4L2_QT_HEADERS - ${CURRENT_HEADER_DIR}/V4L2Grabber.h - ${CURRENT_HEADER_DIR}/V4L2Wrapper.h -) - -SET(V4L2_HEADERS - ${CURRENT_HEADER_DIR}/VideoStandard.h -) - -SET(V4L2_SOURCES - ${CURRENT_SOURCE_DIR}/V4L2Grabber.cpp - ${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} - ${V4L2_SOURCES} - ${V4L2_QT_HEADERS} - ${V4L2_HEADERS_MOC} -) - -if(ENABLE_QT5) -qt5_use_modules(v4l2-grabber Widgets) -endif(ENABLE_QT5) - -target_link_libraries(v4l2-grabber - hyperion - ${QT_LIBRARIES} -) +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/v4l2) + +SET(V4L2_QT_HEADERS + ${CURRENT_HEADER_DIR}/V4L2Grabber.h + ${CURRENT_HEADER_DIR}/V4L2Wrapper.h +) + +SET(V4L2_HEADERS + ${CURRENT_HEADER_DIR}/VideoStandard.h +) + +SET(V4L2_SOURCES + ${CURRENT_SOURCE_DIR}/V4L2Grabber.cpp + ${CURRENT_SOURCE_DIR}/V4L2Wrapper.cpp +) + +if(ENABLE_QT5) + QT5_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS}) +else() + QT4_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS}) +endif() + +add_library(v4l2-grabber + ${V4L2_HEADERS} + ${V4L2_SOURCES} + ${V4L2_QT_HEADERS} + ${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/v4l2/V4L2Grabber.cpp b/libsrc/grabber/v4l2/V4L2Grabber.cpp index 4bce3a57..1f65395f 100644 --- a/libsrc/grabber/v4l2/V4L2Grabber.cpp +++ b/libsrc/grabber/v4l2/V4L2Grabber.cpp @@ -19,720 +19,720 @@ #define CLEAR(x) memset(&(x), 0, sizeof(x)) V4L2Grabber::V4L2Grabber(const std::string & device, - int input, - VideoStandard videoStandard, - PixelFormat pixelFormat, - int width, - int height, - int frameDecimation, - int horizontalPixelDecimation, - int verticalPixelDecimation) : - _deviceName(device), - _ioMethod(IO_METHOD_MMAP), - _fileDescriptor(-1), - _buffers(), - _pixelFormat(pixelFormat), - _width(width), - _height(height), - _lineLength(-1), - _frameByteSize(-1), - _frameDecimation(std::max(1, frameDecimation)), - _noSignalCounterThreshold(50), - _noSignalThresholdColor(ColorRgb{0,0,0}), - _currentFrame(0), - _noSignalCounter(0), - _streamNotifier(nullptr), - _imageResampler() + int input, + VideoStandard videoStandard, + PixelFormat pixelFormat, + int width, + int height, + int frameDecimation, + int horizontalPixelDecimation, + int verticalPixelDecimation) : + _deviceName(device), + _ioMethod(IO_METHOD_MMAP), + _fileDescriptor(-1), + _buffers(), + _pixelFormat(pixelFormat), + _width(width), + _height(height), + _lineLength(-1), + _frameByteSize(-1), + _frameDecimation(std::max(1, frameDecimation)), + _noSignalCounterThreshold(50), + _noSignalThresholdColor(ColorRgb{0,0,0}), + _currentFrame(0), + _noSignalCounter(0), + _streamNotifier(nullptr), + _imageResampler() { - _imageResampler.setHorizontalPixelDecimation(std::max(1, horizontalPixelDecimation)); - _imageResampler.setVerticalPixelDecimation(std::max(1, verticalPixelDecimation)); + _imageResampler.setHorizontalPixelDecimation(std::max(1, horizontalPixelDecimation)); + _imageResampler.setVerticalPixelDecimation(std::max(1, verticalPixelDecimation)); - open_device(); - init_device(videoStandard, input); + open_device(); + init_device(videoStandard, input); } V4L2Grabber::~V4L2Grabber() { - // stop if the grabber was not stopped - stop(); - uninit_device(); - close_device(); + // stop if the grabber was not stopped + stop(); + uninit_device(); + close_device(); } void V4L2Grabber::setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom) { - _imageResampler.setCropping(cropLeft, cropRight, cropTop, cropBottom); + _imageResampler.setCropping(cropLeft, cropRight, cropTop, cropBottom); } void V4L2Grabber::set3D(VideoMode mode) { - _imageResampler.set3D(mode); + _imageResampler.set3D(mode); } void V4L2Grabber::setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold) { - _noSignalThresholdColor.red = uint8_t(255*redSignalThreshold); - _noSignalThresholdColor.green = uint8_t(255*greenSignalThreshold); - _noSignalThresholdColor.blue = uint8_t(255*blueSignalThreshold); - _noSignalCounterThreshold = std::max(1, noSignalCounterThreshold); + _noSignalThresholdColor.red = uint8_t(255*redSignalThreshold); + _noSignalThresholdColor.green = uint8_t(255*greenSignalThreshold); + _noSignalThresholdColor.blue = uint8_t(255*blueSignalThreshold); + _noSignalCounterThreshold = std::max(1, noSignalCounterThreshold); - std::cout << "V4L2GRABBER INFO: signal threshold set to: " << _noSignalThresholdColor << std::endl; + std::cout << "V4L2GRABBER INFO: signal threshold set to: " << _noSignalThresholdColor << std::endl; } void V4L2Grabber::start() { - if (_streamNotifier != nullptr && !_streamNotifier->isEnabled()) - { - _streamNotifier->setEnabled(true); - start_capturing(); - std::cout << "V4L2GRABBER INFO: started" << std::endl; - } + if (_streamNotifier != nullptr && !_streamNotifier->isEnabled()) + { + _streamNotifier->setEnabled(true); + start_capturing(); + std::cout << "V4L2GRABBER INFO: started" << std::endl; + } } void V4L2Grabber::stop() { - if (_streamNotifier != nullptr && _streamNotifier->isEnabled()) - { - stop_capturing(); - _streamNotifier->setEnabled(false); - std::cout << "V4L2GRABBER INFO: stopped" << std::endl; - } + if (_streamNotifier != nullptr && _streamNotifier->isEnabled()) + { + stop_capturing(); + _streamNotifier->setEnabled(false); + std::cout << "V4L2GRABBER INFO: stopped" << std::endl; + } } void V4L2Grabber::open_device() { - struct stat st; + struct stat st; - if (-1 == stat(_deviceName.c_str(), &st)) - { - std::ostringstream oss; - oss << "V4L2GRABBER ERROR: Cannot identify '" << _deviceName << "'"; - throw_errno_exception(oss.str()); - } + if (-1 == stat(_deviceName.c_str(), &st)) + { + std::ostringstream oss; + oss << "V4L2GRABBER ERROR: Cannot identify '" << _deviceName << "'"; + throw_errno_exception(oss.str()); + } - if (!S_ISCHR(st.st_mode)) - { - std::ostringstream oss; - oss << "'" << _deviceName << "' is no device"; - throw_exception(oss.str()); - } + if (!S_ISCHR(st.st_mode)) + { + std::ostringstream oss; + oss << "'" << _deviceName << "' is no device"; + throw_exception(oss.str()); + } - _fileDescriptor = open(_deviceName.c_str(), O_RDWR /* required */ | O_NONBLOCK, 0); + _fileDescriptor = open(_deviceName.c_str(), O_RDWR /* required */ | O_NONBLOCK, 0); - if (-1 == _fileDescriptor) - { - std::ostringstream oss; - oss << "V4L2GRABBER ERROR: Cannot open '" << _deviceName << "'"; - throw_errno_exception(oss.str()); - } + if (-1 == _fileDescriptor) + { + std::ostringstream oss; + oss << "V4L2GRABBER ERROR: Cannot open '" << _deviceName << "'"; + throw_errno_exception(oss.str()); + } - // create the notifier for when a new frame is available - _streamNotifier = new QSocketNotifier(_fileDescriptor, QSocketNotifier::Read); - _streamNotifier->setEnabled(false); - connect(_streamNotifier, SIGNAL(activated(int)), this, SLOT(read_frame())); + // create the notifier for when a new frame is available + _streamNotifier = new QSocketNotifier(_fileDescriptor, QSocketNotifier::Read); + _streamNotifier->setEnabled(false); + connect(_streamNotifier, SIGNAL(activated(int)), this, SLOT(read_frame())); } void V4L2Grabber::close_device() { - if (-1 == close(_fileDescriptor)) - throw_errno_exception("close"); + if (-1 == close(_fileDescriptor)) + throw_errno_exception("close"); - _fileDescriptor = -1; + _fileDescriptor = -1; - if (_streamNotifier != nullptr) - { - delete _streamNotifier; - _streamNotifier = nullptr; - } + if (_streamNotifier != nullptr) + { + delete _streamNotifier; + _streamNotifier = nullptr; + } } void V4L2Grabber::init_read(unsigned int buffer_size) { - _buffers.resize(1); + _buffers.resize(1); - _buffers[0].length = buffer_size; - _buffers[0].start = malloc(buffer_size); + _buffers[0].length = buffer_size; + _buffers[0].start = malloc(buffer_size); - if (!_buffers[0].start) { - throw_exception("V4L2GRABBER ERROR: Out of memory"); - } + if (!_buffers[0].start) { + throw_exception("V4L2GRABBER ERROR: Out of memory"); + } } void V4L2Grabber::init_mmap() { - struct v4l2_requestbuffers req; + struct v4l2_requestbuffers req; - CLEAR(req); + CLEAR(req); - req.count = 4; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_MMAP; + req.count = 4; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; - if (-1 == xioctl(VIDIOC_REQBUFS, &req)) { - if (EINVAL == errno) { - std::ostringstream oss; - oss << "'" << _deviceName << "' does not support memory mapping"; - throw_exception(oss.str()); - } else { - throw_errno_exception("VIDIOC_REQBUFS"); - } - } + if (-1 == xioctl(VIDIOC_REQBUFS, &req)) { + if (EINVAL == errno) { + std::ostringstream oss; + oss << "'" << _deviceName << "' does not support memory mapping"; + throw_exception(oss.str()); + } else { + throw_errno_exception("VIDIOC_REQBUFS"); + } + } - if (req.count < 2) { - std::ostringstream oss; - oss << "Insufficient buffer memory on " << _deviceName; - throw_exception(oss.str()); - } + if (req.count < 2) { + std::ostringstream oss; + oss << "Insufficient buffer memory on " << _deviceName; + throw_exception(oss.str()); + } - _buffers.resize(req.count); + _buffers.resize(req.count); - for (size_t n_buffers = 0; n_buffers < req.count; ++n_buffers) { - struct v4l2_buffer buf; + for (size_t n_buffers = 0; n_buffers < req.count; ++n_buffers) { + struct v4l2_buffer buf; - CLEAR(buf); + CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = n_buffers; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = n_buffers; - if (-1 == xioctl(VIDIOC_QUERYBUF, &buf)) - throw_errno_exception("VIDIOC_QUERYBUF"); + if (-1 == xioctl(VIDIOC_QUERYBUF, &buf)) + throw_errno_exception("VIDIOC_QUERYBUF"); - _buffers[n_buffers].length = buf.length; - _buffers[n_buffers].start = - mmap(NULL /* start anywhere */, - buf.length, - PROT_READ | PROT_WRITE /* required */, - MAP_SHARED /* recommended */, - _fileDescriptor, buf.m.offset); + _buffers[n_buffers].length = buf.length; + _buffers[n_buffers].start = + mmap(NULL /* start anywhere */, + buf.length, + PROT_READ | PROT_WRITE /* required */, + MAP_SHARED /* recommended */, + _fileDescriptor, buf.m.offset); - if (MAP_FAILED == _buffers[n_buffers].start) - throw_errno_exception("mmap"); - } + if (MAP_FAILED == _buffers[n_buffers].start) + throw_errno_exception("mmap"); + } } void V4L2Grabber::init_userp(unsigned int buffer_size) { - struct v4l2_requestbuffers req; + struct v4l2_requestbuffers req; - CLEAR(req); + CLEAR(req); - req.count = 4; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_USERPTR; + req.count = 4; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_USERPTR; - if (-1 == xioctl(VIDIOC_REQBUFS, &req)) { - if (EINVAL == errno) - { - std::ostringstream oss; - oss << "'" << _deviceName << "' does not support user pointer"; - throw_exception(oss.str()); - } else { - throw_errno_exception("VIDIOC_REQBUFS"); - } - } + if (-1 == xioctl(VIDIOC_REQBUFS, &req)) { + if (EINVAL == errno) + { + std::ostringstream oss; + oss << "'" << _deviceName << "' does not support user pointer"; + throw_exception(oss.str()); + } else { + throw_errno_exception("VIDIOC_REQBUFS"); + } + } - _buffers.resize(4); + _buffers.resize(4); - for (size_t n_buffers = 0; n_buffers < 4; ++n_buffers) { - _buffers[n_buffers].length = buffer_size; - _buffers[n_buffers].start = malloc(buffer_size); + for (size_t n_buffers = 0; n_buffers < 4; ++n_buffers) { + _buffers[n_buffers].length = buffer_size; + _buffers[n_buffers].start = malloc(buffer_size); - if (!_buffers[n_buffers].start) { - throw_exception("V4L2GRABBER ERROR: Out of memory"); - } - } + if (!_buffers[n_buffers].start) { + throw_exception("V4L2GRABBER ERROR: Out of memory"); + } + } } void V4L2Grabber::init_device(VideoStandard videoStandard, int input) { - struct v4l2_capability cap; - if (-1 == xioctl(VIDIOC_QUERYCAP, &cap)) - { - if (EINVAL == errno) { - std::ostringstream oss; - oss << "'" << _deviceName << "' is no V4L2 device"; - throw_exception(oss.str()); - } else { - throw_errno_exception("VIDIOC_QUERYCAP"); - } - } + struct v4l2_capability cap; + if (-1 == xioctl(VIDIOC_QUERYCAP, &cap)) + { + if (EINVAL == errno) { + std::ostringstream oss; + oss << "'" << _deviceName << "' is no V4L2 device"; + throw_exception(oss.str()); + } else { + throw_errno_exception("VIDIOC_QUERYCAP"); + } + } - if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) - { - std::ostringstream oss; - oss << "'" << _deviceName << "' is no video capture device"; - throw_exception(oss.str()); - } + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) + { + std::ostringstream oss; + oss << "'" << _deviceName << "' is no video capture device"; + throw_exception(oss.str()); + } - switch (_ioMethod) { - case IO_METHOD_READ: - if (!(cap.capabilities & V4L2_CAP_READWRITE)) - { - std::ostringstream oss; - oss << "'" << _deviceName << "' does not support read i/o"; - throw_exception(oss.str()); - } - break; + switch (_ioMethod) { + case IO_METHOD_READ: + if (!(cap.capabilities & V4L2_CAP_READWRITE)) + { + std::ostringstream oss; + oss << "'" << _deviceName << "' does not support read i/o"; + throw_exception(oss.str()); + } + break; - case IO_METHOD_MMAP: - case IO_METHOD_USERPTR: - if (!(cap.capabilities & V4L2_CAP_STREAMING)) - { - std::ostringstream oss; - oss << "'" << _deviceName << "' does not support streaming i/o"; - throw_exception(oss.str()); - } - break; - } + case IO_METHOD_MMAP: + case IO_METHOD_USERPTR: + if (!(cap.capabilities & V4L2_CAP_STREAMING)) + { + std::ostringstream oss; + oss << "'" << _deviceName << "' does not support streaming i/o"; + throw_exception(oss.str()); + } + break; + } - /* Select video input, video standard and tune here. */ + /* Select video input, video standard and tune here. */ - struct v4l2_cropcap cropcap; - CLEAR(cropcap); + struct v4l2_cropcap cropcap; + CLEAR(cropcap); - cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (0 == xioctl(VIDIOC_CROPCAP, &cropcap)) { - struct v4l2_crop crop; - crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - crop.c = cropcap.defrect; /* reset to default */ + if (0 == xioctl(VIDIOC_CROPCAP, &cropcap)) { + struct v4l2_crop crop; + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + crop.c = cropcap.defrect; /* reset to default */ - if (-1 == xioctl(VIDIOC_S_CROP, &crop)) { - switch (errno) { - case EINVAL: - /* Cropping not supported. */ - break; - default: - /* Errors ignored. */ - break; - } - } - } else { - /* Errors ignored. */ - } + if (-1 == xioctl(VIDIOC_S_CROP, &crop)) { + switch (errno) { + case EINVAL: + /* Cropping not supported. */ + break; + default: + /* Errors ignored. */ + break; + } + } + } else { + /* Errors ignored. */ + } - // set input if needed - if (input >= 0) - { - if (-1 == xioctl(VIDIOC_S_INPUT, &input)) - { - throw_errno_exception("VIDIOC_S_INPUT"); - } - } + // set input if needed + if (input >= 0) + { + if (-1 == xioctl(VIDIOC_S_INPUT, &input)) + { + throw_errno_exception("VIDIOC_S_INPUT"); + } + } - // set the video standard if needed - switch (videoStandard) - { - case VIDEOSTANDARD_PAL: - { - v4l2_std_id std_id = V4L2_STD_PAL; - if (-1 == xioctl(VIDIOC_S_STD, &std_id)) - { - throw_errno_exception("VIDIOC_S_STD"); - } - } - break; - case VIDEOSTANDARD_NTSC: - { - v4l2_std_id std_id = V4L2_STD_NTSC; - if (-1 == xioctl(VIDIOC_S_STD, &std_id)) - { - throw_errno_exception("VIDIOC_S_STD"); - } - } - break; - case VIDEOSTANDARD_NO_CHANGE: - default: - // No change to device settings - break; - } + // set the video standard if needed + switch (videoStandard) + { + case VIDEOSTANDARD_PAL: + { + v4l2_std_id std_id = V4L2_STD_PAL; + if (-1 == xioctl(VIDIOC_S_STD, &std_id)) + { + throw_errno_exception("VIDIOC_S_STD"); + } + } + break; + case VIDEOSTANDARD_NTSC: + { + v4l2_std_id std_id = V4L2_STD_NTSC; + if (-1 == xioctl(VIDIOC_S_STD, &std_id)) + { + throw_errno_exception("VIDIOC_S_STD"); + } + } + break; + case VIDEOSTANDARD_NO_CHANGE: + default: + // No change to device settings + break; + } - // get the current settings - struct v4l2_format fmt; - CLEAR(fmt); - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (-1 == xioctl(VIDIOC_G_FMT, &fmt)) - { - throw_errno_exception("VIDIOC_G_FMT"); - } + // get the current settings + struct v4l2_format fmt; + CLEAR(fmt); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == xioctl(VIDIOC_G_FMT, &fmt)) + { + throw_errno_exception("VIDIOC_G_FMT"); + } - // set the requested pixel format - switch (_pixelFormat) - { - case PIXELFORMAT_UYVY: - fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; - break; - case PIXELFORMAT_YUYV: - fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - break; - case PIXELFORMAT_RGB32: - fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32; - break; - case PIXELFORMAT_NO_CHANGE: - default: - // No change to device settings - break; - } + // set the requested pixel format + switch (_pixelFormat) + { + case PIXELFORMAT_UYVY: + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + break; + case PIXELFORMAT_YUYV: + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + break; + case PIXELFORMAT_RGB32: + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32; + break; + case PIXELFORMAT_NO_CHANGE: + default: + // No change to device settings + break; + } - // set the requested withd and height - if (_width > 0 || _height > 0) - { - if (_width > 0) - { - fmt.fmt.pix.width = _width; - } + // set the requested withd and height + if (_width > 0 || _height > 0) + { + if (_width > 0) + { + fmt.fmt.pix.width = _width; + } - if (fmt.fmt.pix.height > 0) - { - fmt.fmt.pix.height = _height; - } - } + if (fmt.fmt.pix.height > 0) + { + fmt.fmt.pix.height = _height; + } + } - // set the line length - _lineLength = fmt.fmt.pix.bytesperline; + // set the line length + _lineLength = fmt.fmt.pix.bytesperline; - // set the settings - if (-1 == xioctl(VIDIOC_S_FMT, &fmt)) - { - throw_errno_exception("VIDIOC_S_FMT"); - } + // set the settings + if (-1 == xioctl(VIDIOC_S_FMT, &fmt)) + { + throw_errno_exception("VIDIOC_S_FMT"); + } - // get the format settings again - // (the size may not have been accepted without an error) - if (-1 == xioctl(VIDIOC_G_FMT, &fmt)) - { - throw_errno_exception("VIDIOC_G_FMT"); - } + // get the format settings again + // (the size may not have been accepted without an error) + if (-1 == xioctl(VIDIOC_G_FMT, &fmt)) + { + throw_errno_exception("VIDIOC_G_FMT"); + } - // store width & height - _width = fmt.fmt.pix.width; - _height = fmt.fmt.pix.height; + // store width & height + _width = fmt.fmt.pix.width; + _height = fmt.fmt.pix.height; - // print the eventually used width and height - std::cout << "V4L2GRABBER INFO: width=" << _width << " height=" << _height << std::endl; + // print the eventually used width and height + std::cout << "V4L2GRABBER INFO: width=" << _width << " height=" << _height << std::endl; - // check pixel format and frame size - switch (fmt.fmt.pix.pixelformat) - { - case V4L2_PIX_FMT_UYVY: - _pixelFormat = PIXELFORMAT_UYVY; - _frameByteSize = _width * _height * 2; - std::cout << "V4L2GRABBER INFO: pixel format=UYVY" << std::endl; - break; - case V4L2_PIX_FMT_YUYV: - _pixelFormat = PIXELFORMAT_YUYV; - _frameByteSize = _width * _height * 2; - std::cout << "V4L2GRABBER INFO: pixel format=YUYV" << std::endl; - break; - case V4L2_PIX_FMT_RGB32: - _pixelFormat = PIXELFORMAT_RGB32; - _frameByteSize = _width * _height * 4; - std::cout << "V4L2GRABBER INFO: pixel format=RGB32" << std::endl; - break; - default: - throw_exception("V4L2GRABBER ERROR: Only pixel formats UYVY, YUYV, and RGB32 are supported"); - } + // check pixel format and frame size + switch (fmt.fmt.pix.pixelformat) + { + case V4L2_PIX_FMT_UYVY: + _pixelFormat = PIXELFORMAT_UYVY; + _frameByteSize = _width * _height * 2; + std::cout << "V4L2GRABBER INFO: pixel format=UYVY" << std::endl; + break; + case V4L2_PIX_FMT_YUYV: + _pixelFormat = PIXELFORMAT_YUYV; + _frameByteSize = _width * _height * 2; + std::cout << "V4L2GRABBER INFO: pixel format=YUYV" << std::endl; + break; + case V4L2_PIX_FMT_RGB32: + _pixelFormat = PIXELFORMAT_RGB32; + _frameByteSize = _width * _height * 4; + std::cout << "V4L2GRABBER INFO: pixel format=RGB32" << std::endl; + break; + default: + throw_exception("V4L2GRABBER ERROR: Only pixel formats UYVY, YUYV, and RGB32 are supported"); + } - switch (_ioMethod) { - case IO_METHOD_READ: - init_read(fmt.fmt.pix.sizeimage); - break; + switch (_ioMethod) { + case IO_METHOD_READ: + init_read(fmt.fmt.pix.sizeimage); + break; - case IO_METHOD_MMAP: - init_mmap(); - break; + case IO_METHOD_MMAP: + init_mmap(); + break; - case IO_METHOD_USERPTR: - init_userp(fmt.fmt.pix.sizeimage); - break; - } + case IO_METHOD_USERPTR: + init_userp(fmt.fmt.pix.sizeimage); + break; + } } void V4L2Grabber::uninit_device() { - switch (_ioMethod) { - case IO_METHOD_READ: - free(_buffers[0].start); - break; + switch (_ioMethod) { + case IO_METHOD_READ: + free(_buffers[0].start); + break; - case IO_METHOD_MMAP: - for (size_t i = 0; i < _buffers.size(); ++i) - if (-1 == munmap(_buffers[i].start, _buffers[i].length)) - throw_errno_exception("munmap"); - break; + case IO_METHOD_MMAP: + for (size_t i = 0; i < _buffers.size(); ++i) + if (-1 == munmap(_buffers[i].start, _buffers[i].length)) + throw_errno_exception("munmap"); + break; - case IO_METHOD_USERPTR: - for (size_t i = 0; i < _buffers.size(); ++i) - free(_buffers[i].start); - break; - } + case IO_METHOD_USERPTR: + for (size_t i = 0; i < _buffers.size(); ++i) + free(_buffers[i].start); + break; + } - _buffers.resize(0); + _buffers.resize(0); } void V4L2Grabber::start_capturing() { - switch (_ioMethod) { - case IO_METHOD_READ: - /* Nothing to do. */ - break; + switch (_ioMethod) { + case IO_METHOD_READ: + /* Nothing to do. */ + break; - case IO_METHOD_MMAP: - { - for (size_t i = 0; i < _buffers.size(); ++i) { - struct v4l2_buffer buf; + case IO_METHOD_MMAP: + { + for (size_t i = 0; i < _buffers.size(); ++i) { + struct v4l2_buffer buf; - CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = i; + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; - if (-1 == xioctl(VIDIOC_QBUF, &buf)) - throw_errno_exception("VIDIOC_QBUF"); - } - v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (-1 == xioctl(VIDIOC_STREAMON, &type)) - throw_errno_exception("VIDIOC_STREAMON"); - break; - } - case IO_METHOD_USERPTR: - { - for (size_t i = 0; i < _buffers.size(); ++i) { - struct v4l2_buffer buf; + if (-1 == xioctl(VIDIOC_QBUF, &buf)) + throw_errno_exception("VIDIOC_QBUF"); + } + v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == xioctl(VIDIOC_STREAMON, &type)) + throw_errno_exception("VIDIOC_STREAMON"); + break; + } + case IO_METHOD_USERPTR: + { + for (size_t i = 0; i < _buffers.size(); ++i) { + struct v4l2_buffer buf; - CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_USERPTR; - buf.index = i; - buf.m.userptr = (unsigned long)_buffers[i].start; - buf.length = _buffers[i].length; + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_USERPTR; + buf.index = i; + buf.m.userptr = (unsigned long)_buffers[i].start; + buf.length = _buffers[i].length; - if (-1 == xioctl(VIDIOC_QBUF, &buf)) - throw_errno_exception("VIDIOC_QBUF"); - } - v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (-1 == xioctl(VIDIOC_STREAMON, &type)) - throw_errno_exception("VIDIOC_STREAMON"); - break; - } - } + if (-1 == xioctl(VIDIOC_QBUF, &buf)) + throw_errno_exception("VIDIOC_QBUF"); + } + v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == xioctl(VIDIOC_STREAMON, &type)) + throw_errno_exception("VIDIOC_STREAMON"); + break; + } + } } void V4L2Grabber::stop_capturing() { - enum v4l2_buf_type type; + enum v4l2_buf_type type; - switch (_ioMethod) { - case IO_METHOD_READ: - /* Nothing to do. */ - break; + switch (_ioMethod) { + case IO_METHOD_READ: + /* Nothing to do. */ + break; - case IO_METHOD_MMAP: - case IO_METHOD_USERPTR: - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (-1 == xioctl(VIDIOC_STREAMOFF, &type)) - throw_errno_exception("VIDIOC_STREAMOFF"); - break; - } + case IO_METHOD_MMAP: + case IO_METHOD_USERPTR: + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == xioctl(VIDIOC_STREAMOFF, &type)) + throw_errno_exception("VIDIOC_STREAMOFF"); + break; + } } int V4L2Grabber::read_frame() { - bool rc = false; + bool rc = false; - struct v4l2_buffer buf; + struct v4l2_buffer buf; - switch (_ioMethod) { - case IO_METHOD_READ: - int size; - if ((size = read(_fileDescriptor, _buffers[0].start, _buffers[0].length)) == -1) - { - switch (errno) - { - case EAGAIN: - return 0; + switch (_ioMethod) { + case IO_METHOD_READ: + int size; + if ((size = read(_fileDescriptor, _buffers[0].start, _buffers[0].length)) == -1) + { + switch (errno) + { + case EAGAIN: + return 0; - case EIO: - /* Could ignore EIO, see spec. */ + case EIO: + /* Could ignore EIO, see spec. */ - /* fall through */ + /* fall through */ - default: - throw_errno_exception("read"); - } - } + default: + throw_errno_exception("read"); + } + } - rc = process_image(_buffers[0].start, size); - break; + rc = process_image(_buffers[0].start, size); + break; - case IO_METHOD_MMAP: - CLEAR(buf); + case IO_METHOD_MMAP: + CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; - if (-1 == xioctl(VIDIOC_DQBUF, &buf)) - { - switch (errno) - { - case EAGAIN: - return 0; + if (-1 == xioctl(VIDIOC_DQBUF, &buf)) + { + switch (errno) + { + case EAGAIN: + return 0; - case EIO: - /* Could ignore EIO, see spec. */ + case EIO: + /* Could ignore EIO, see spec. */ - /* fall through */ + /* fall through */ - default: - throw_errno_exception("VIDIOC_DQBUF"); - } - } + default: + throw_errno_exception("VIDIOC_DQBUF"); + } + } - assert(buf.index < _buffers.size()); + assert(buf.index < _buffers.size()); - rc = process_image(_buffers[buf.index].start, buf.bytesused); + rc = process_image(_buffers[buf.index].start, buf.bytesused); - if (-1 == xioctl(VIDIOC_QBUF, &buf)) - { - throw_errno_exception("VIDIOC_QBUF"); - } + if (-1 == xioctl(VIDIOC_QBUF, &buf)) + { + throw_errno_exception("VIDIOC_QBUF"); + } - break; + break; - case IO_METHOD_USERPTR: - CLEAR(buf); + case IO_METHOD_USERPTR: + CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_USERPTR; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_USERPTR; - if (-1 == xioctl(VIDIOC_DQBUF, &buf)) - { - switch (errno) - { - case EAGAIN: - return 0; + if (-1 == xioctl(VIDIOC_DQBUF, &buf)) + { + switch (errno) + { + case EAGAIN: + return 0; - case EIO: - /* Could ignore EIO, see spec. */ + case EIO: + /* Could ignore EIO, see spec. */ - /* fall through */ + /* fall through */ - default: - throw_errno_exception("VIDIOC_DQBUF"); - } - } + default: + throw_errno_exception("VIDIOC_DQBUF"); + } + } - for (size_t i = 0; i < _buffers.size(); ++i) - { - if (buf.m.userptr == (unsigned long)_buffers[i].start && buf.length == _buffers[i].length) - { - break; - } - } + for (size_t i = 0; i < _buffers.size(); ++i) + { + if (buf.m.userptr == (unsigned long)_buffers[i].start && buf.length == _buffers[i].length) + { + break; + } + } - rc = process_image((void *)buf.m.userptr, buf.bytesused); + rc = process_image((void *)buf.m.userptr, buf.bytesused); - if (-1 == xioctl(VIDIOC_QBUF, &buf)) - { - throw_errno_exception("VIDIOC_QBUF"); - } - break; - } + if (-1 == xioctl(VIDIOC_QBUF, &buf)) + { + throw_errno_exception("VIDIOC_QBUF"); + } + break; + } - return rc ? 1 : 0; + return rc ? 1 : 0; } bool V4L2Grabber::process_image(const void *p, int size) { - if (++_currentFrame >= _frameDecimation) - { - // We do want a new frame... + if (++_currentFrame >= _frameDecimation) + { + // We do want a new frame... - if (size != _frameByteSize) - { - std::cout << "V4L2GRABBER ERROR: Frame too small: " << size << " != " << _frameByteSize << std::endl; - } - else - { - process_image(reinterpret_cast(p)); - _currentFrame = 0; // restart counting - return true; - } - } + if (size != _frameByteSize) + { + std::cout << "V4L2GRABBER ERROR: Frame too small: " << size << " != " << _frameByteSize << std::endl; + } + else + { + process_image(reinterpret_cast(p)); + _currentFrame = 0; // restart counting + return true; + } + } - return false; + return false; } void V4L2Grabber::process_image(const uint8_t * data) { - Image image(0, 0); - _imageResampler.processImage(data, _width, _height, _lineLength, _pixelFormat, image); + Image image(0, 0); + _imageResampler.processImage(data, _width, _height, _lineLength, _pixelFormat, image); - // check signal (only in center of the resulting image, because some grabbers have noise values along the borders) - bool noSignal = true; - for (unsigned x = 0; noSignal && x < (image.width()>>1); ++x) - { - int xImage = (image.width()>>2) + x; + // check signal (only in center of the resulting image, because some grabbers have noise values along the borders) + bool noSignal = true; + for (unsigned x = 0; noSignal && x < (image.width()>>1); ++x) + { + int xImage = (image.width()>>2) + x; - for (unsigned y = 0; noSignal && y < (image.height()>>1); ++y) - { - int yImage = (image.height()>>2) + y; + for (unsigned y = 0; noSignal && y < (image.height()>>1); ++y) + { + int yImage = (image.height()>>2) + y; - ColorRgb & rgb = image(xImage, yImage); - noSignal &= rgb <= _noSignalThresholdColor; - } - } + ColorRgb & rgb = image(xImage, yImage); + noSignal &= rgb <= _noSignalThresholdColor; + } + } - if (noSignal) - { - ++_noSignalCounter; - } - else - { - if (_noSignalCounter >= _noSignalCounterThreshold) - { - std::cout << "V4L2GRABBER INFO: " << "Signal detected" << std::endl; - } + if (noSignal) + { + ++_noSignalCounter; + } + else + { + if (_noSignalCounter >= _noSignalCounterThreshold) + { + std::cout << "V4L2GRABBER INFO: " << "Signal detected" << std::endl; + } - _noSignalCounter = 0; - } + _noSignalCounter = 0; + } - if (_noSignalCounter < _noSignalCounterThreshold) - { - emit newFrame(image); - } - else if (_noSignalCounter == _noSignalCounterThreshold) - { - std::cout << "V4L2GRABBER INFO: " << "Signal lost" << std::endl; - } + if (_noSignalCounter < _noSignalCounterThreshold) + { + emit newFrame(image); + } + else if (_noSignalCounter == _noSignalCounterThreshold) + { + std::cout << "V4L2GRABBER INFO: " << "Signal lost" << std::endl; + } } int V4L2Grabber::xioctl(int request, void *arg) { - int r; + int r; - do - { - r = ioctl(_fileDescriptor, request, arg); - } - while (-1 == r && EINTR == errno); + do + { + r = ioctl(_fileDescriptor, request, arg); + } + while (-1 == r && EINTR == errno); - return r; + return r; } void V4L2Grabber::throw_exception(const std::string & error) { - std::ostringstream oss; - oss << error << " ERROR"; - throw std::runtime_error(oss.str()); + std::ostringstream oss; + oss << error << " ERROR"; + throw std::runtime_error(oss.str()); } void V4L2Grabber::throw_errno_exception(const std::string & error) { - std::ostringstream oss; - oss << error << " ERROR " << errno << ", " << strerror(errno); - throw std::runtime_error(oss.str()); + std::ostringstream oss; + oss << error << " ERROR " << errno << ", " << strerror(errno); + throw std::runtime_error(oss.str()); } diff --git a/libsrc/grabber/x11/CMakeLists.txt b/libsrc/grabber/x11/CMakeLists.txt index 4d8ead6d..cd1bb0f0 100644 --- a/libsrc/grabber/x11/CMakeLists.txt +++ b/libsrc/grabber/x11/CMakeLists.txt @@ -19,20 +19,20 @@ SET(X11_HEADERS ) SET(X11_SOURCES - ${CURRENT_SOURCE_DIR}/X11Grabber.cpp + ${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) + QT5_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS}) +else() + QT4_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS}) +endif() add_library(x11-grabber - ${X11_HEADERS} - ${X11_SOURCES} - ${X11_QT_HEADERS} - ${X11_HEADERS_MOC} + ${X11_HEADERS} + ${X11_SOURCES} + ${X11_QT_HEADERS} + ${X11_HEADERS_MOC} ) target_link_libraries(x11-grabber diff --git a/libsrc/grabber/x11/X11Grabber.cpp b/libsrc/grabber/x11/X11Grabber.cpp index 4d4d6fa7..5b662288 100644 --- a/libsrc/grabber/x11/X11Grabber.cpp +++ b/libsrc/grabber/x11/X11Grabber.cpp @@ -6,107 +6,108 @@ #include X11Grabber::X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) : - _imageResampler(), - _useXGetImage(useXGetImage), - _cropLeft(cropLeft), - _cropRight(cropRight), - _cropTop(cropTop), - _cropBottom(cropBottom), - _x11Display(nullptr), - _pixmap(None), - _srcFormat(nullptr), - _dstFormat(nullptr), - _srcPicture(None), - _dstPicture(None), - _screenWidth(0), - _screenHeight(0), - _croppedWidth(0), - _croppedHeight(0), - _image(0,0) + _imageResampler(), + _useXGetImage(useXGetImage), + _cropLeft(cropLeft), + _cropRight(cropRight), + _cropTop(cropTop), + _cropBottom(cropBottom), + _x11Display(nullptr), + _pixmap(None), + _srcFormat(nullptr), + _dstFormat(nullptr), + _srcPicture(None), + _dstPicture(None), + _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 XShmGetImage or XGetImage - memset(&_pictAttr, 0, sizeof(_pictAttr)); - _pictAttr.repeat = RepeatNone; + _imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation); + _imageResampler.setVerticalPixelDecimation(verticalPixelDecimation); + _imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XShmGetImage or XGetImage + memset(&_pictAttr, 0, sizeof(_pictAttr)); + _pictAttr.repeat = RepeatNone; } X11Grabber::~X11Grabber() { - if (_x11Display != nullptr) - { - freeResources(); - XCloseDisplay(_x11Display); - } + if (_x11Display != nullptr) + { + freeResources(); + XCloseDisplay(_x11Display); + } } void X11Grabber::freeResources() { - // Cleanup allocated resources of the X11 grab - XDestroyImage(_xImage); - if(_XShmAvailable && !_useXGetImage) { - XShmDetach(_x11Display, &_shminfo); - shmdt(_shminfo.shmaddr); - shmctl(_shminfo.shmid, IPC_RMID, 0); - } - if (_XRenderAvailable && !_useXGetImage) { - XRenderFreePicture(_x11Display, _srcPicture); - XRenderFreePicture(_x11Display, _dstPicture); - XFreePixmap(_x11Display, _pixmap); - } + // Cleanup allocated resources of the X11 grab + XDestroyImage(_xImage); + if(_XShmAvailable && !_useXGetImage) { + XShmDetach(_x11Display, &_shminfo); + shmdt(_shminfo.shmaddr); + shmctl(_shminfo.shmid, IPC_RMID, 0); + } + if (_XRenderAvailable && !_useXGetImage) { + XRenderFreePicture(_x11Display, _srcPicture); + XRenderFreePicture(_x11Display, _dstPicture); + XFreePixmap(_x11Display, _pixmap); + } } void X11Grabber::setupResources() { - if(_XShmAvailable && !_useXGetImage) { - _xImage = XShmCreateImage(_x11Display, _windowAttr.visual, - _windowAttr.depth, ZPixmap, NULL, &_shminfo, - _croppedWidth, _croppedHeight); + if(_XShmAvailable && !_useXGetImage) { + _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); - _xImage->data = (char*)shmat(_shminfo.shmid,0,0); - _shminfo.shmaddr = _xImage->data; - _shminfo.readOnly = False; - + _shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777); + _xImage->data = (char*)shmat(_shminfo.shmid,0,0); + _shminfo.shmaddr = _xImage->data; + _shminfo.readOnly = False; + XShmAttach(_x11Display, &_shminfo); - } - if (_XRenderAvailable && !_useXGetImage) { - if(_XShmPixmapAvailable) { - _pixmap = XShmCreatePixmap(_x11Display, _window, _xImage->data, &_shminfo, _croppedWidth, _croppedHeight, _windowAttr.depth); - } else { - _pixmap = XCreatePixmap(_x11Display, _window, _croppedWidth, _croppedHeight, _windowAttr.depth); } - _srcFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual); - _dstFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual); - _srcPicture = XRenderCreatePicture(_x11Display, _window, _srcFormat, CPRepeat, &_pictAttr); - _dstPicture = XRenderCreatePicture(_x11Display, _pixmap, _dstFormat, CPRepeat, &_pictAttr); - XRenderSetPictureFilter(_x11Display, _srcPicture, "bilinear", NULL, 0); - } + if (_XRenderAvailable && !_useXGetImage) { + if(_XShmPixmapAvailable) { + _pixmap = XShmCreatePixmap(_x11Display, _window, _xImage->data, &_shminfo, _croppedWidth, _croppedHeight, _windowAttr.depth); + } else { + _pixmap = XCreatePixmap(_x11Display, _window, _croppedWidth, _croppedHeight, _windowAttr.depth); + } + _srcFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual); + _dstFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual); + _srcPicture = XRenderCreatePicture(_x11Display, _window, _srcFormat, CPRepeat, &_pictAttr); + _dstPicture = XRenderCreatePicture(_x11Display, _pixmap, _dstFormat, CPRepeat, &_pictAttr); + XRenderSetPictureFilter(_x11Display, _srcPicture, "bilinear", NULL, 0); + } } bool X11Grabber::Setup() { - _x11Display = XOpenDisplay(NULL); - if (_x11Display == nullptr) - { - std::cerr << "X11GRABBER ERROR: 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); + _x11Display = XOpenDisplay(NULL); + if (_x11Display == nullptr) + { + std::cerr << "X11GRABBER ERROR: 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); - int dummy, pixmaps_supported; - - _XRenderAvailable = XRenderQueryExtension(_x11Display, &dummy, &dummy); - _XShmAvailable = XShmQueryExtension(_x11Display); - XShmQueryVersion(_x11Display, &dummy, &dummy, &pixmaps_supported); - _XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_x11Display) == ZPixmap; + int dummy, pixmaps_supported; + + _XRenderAvailable = XRenderQueryExtension(_x11Display, &dummy, &dummy); + _XShmAvailable = XShmQueryExtension(_x11Display); + XShmQueryVersion(_x11Display, &dummy, &dummy, &pixmaps_supported); + _XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_x11Display) == ZPixmap; - return true; + return true; } Image & X11Grabber::grab() @@ -129,75 +130,74 @@ Image & X11Grabber::grab() _croppedHeight); // height XSync(_x11Display, False); - - if (_XShmAvailable) { - XShmGetImage(_x11Display, _pixmap, _xImage, 0, 0, AllPlanes); - } else { - _xImage = XGetImage(_x11Display, _pixmap, 0, 0, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap); - } - } else { - if (_XShmAvailable && !_useXGetImage) { - XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes); - } else { - _xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap); - } - } - - if (_xImage == nullptr) - { - std::cerr << "X11GRABBER ERROR: Grab failed" << std::endl; - return _image; - } - _imageResampler.processImage(reinterpret_cast(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, _image); + if (_XShmAvailable) { + XShmGetImage(_x11Display, _pixmap, _xImage, 0, 0, AllPlanes); + } else { + _xImage = XGetImage(_x11Display, _pixmap, 0, 0, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap); + } + } else { + if (_XShmAvailable && !_useXGetImage) { + XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes); + } else { + _xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap); + } + } - return _image; + if (_xImage == nullptr) + { + std::cerr << "X11GRABBER ERROR: Grab failed" << std::endl; + return _image; + } + + _imageResampler.processImage(reinterpret_cast(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, _image); + + return _image; } int X11Grabber::updateScreenDimensions() { - const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr); - if (status == 0) - { - std::cerr << "X11GRABBER ERROR: Failed to obtain window attributes" << std::endl; - return -1; - } + const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr); + if (status == 0) + { + std::cerr << "X11GRABBER ERROR: Failed to obtain window attributes" << std::endl; + return -1; + } - if (_screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height)) - { - // No update required - return 0; - } - - std::cout << "X11GRABBER INFO: Update of screen resolution: [" << _screenWidth << "x" << _screenHeight <<"] => "; + if (_screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height)) + { + // No update required + return 0; + } + + std::cout << "X11GRABBER INFO: Update of screen resolution: [" << _screenWidth << "x" << _screenHeight <<"] => "; - 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; - - std::cout << "X11GRABBER INFO: Using "; - - if (_XRenderAvailable && !_useXGetImage) { - std::cout << "XRender for grabbing" << std::endl; - } else { - std::cout << "XGetImage for grabbing" << std::endl; - } - - setupResources(); + if (_screenWidth || _screenHeight) { + freeResources(); + } - return 0; + _screenWidth = _windowAttr.width; + _screenHeight = _windowAttr.height; + + std::cout << "[" << _screenWidth << "x" << _screenHeight <<"]" << std::endl; + + _croppedWidth = (_screenWidth > unsigned(_cropLeft + _cropRight)) + ? (_screenWidth - _cropLeft - _cropRight) + : _screenWidth; + + _croppedHeight = (_screenHeight > unsigned(_cropTop + _cropBottom)) + ? (_screenHeight - _cropTop - _cropBottom) + : (_croppedHeight = _screenHeight); + + std::cout << "X11GRABBER INFO: Using "; + + if (_XRenderAvailable && !_useXGetImage) { + std::cout << "XRender for grabbing" << std::endl; + } else { + std::cout << "XGetImage for grabbing" << std::endl; + } + + setupResources(); + + return 0; } diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index b4f53a19..021b4e2d 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -1,72 +1,72 @@ - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion) - -# Group the headers that go through the MOC compiler -SET(Hyperion_QT_HEADERS - ${CURRENT_HEADER_DIR}/Hyperion.h - - ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h -) - -SET(Hyperion_HEADERS - ${CURRENT_HEADER_DIR}/ImageProcessor.h - ${CURRENT_HEADER_DIR}/ImageProcessorFactory.h - ${CURRENT_HEADER_DIR}/ImageToLedsMap.h - ${CURRENT_HEADER_DIR}/LedString.h - ${CURRENT_HEADER_DIR}/PriorityMuxer.h - - ${CURRENT_SOURCE_DIR}/MultiColorTransform.h - ${CURRENT_SOURCE_DIR}/MultiColorCorrection.h - ${CURRENT_SOURCE_DIR}/MultiColorAdjustment.h - ${CURRENT_HEADER_DIR}/MessageForwarder.h -) - -SET(Hyperion_SOURCES - ${CURRENT_SOURCE_DIR}/Hyperion.cpp - ${CURRENT_SOURCE_DIR}/ImageProcessor.cpp - ${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp - ${CURRENT_SOURCE_DIR}/LedString.cpp - ${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp - - ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp - ${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp - ${CURRENT_SOURCE_DIR}/MultiColorCorrection.cpp - ${CURRENT_SOURCE_DIR}/MultiColorAdjustment.cpp - ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp - ${CURRENT_SOURCE_DIR}/MessageForwarder.cpp -) - -set(Hyperion_RESOURCES - ${CURRENT_SOURCE_DIR}/resource.qrc -) - -if(ENABLE_QT5) -QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) -QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") -else(ENABLE_QT5) -QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) -QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") -endif(ENABLE_QT5) - -add_library(hyperion - ${Hyperion_HEADERS} - ${Hyperion_QT_HEADERS} - ${Hyperion_HEADERS_MOC} - ${Hyperion_SOURCES} - ${Hyperion_RESOURCES_RCC} -) - -if(ENABLE_QT5) -qt5_use_modules(hyperion Widgets) -endif(ENABLE_QT5) - -target_link_libraries(hyperion - blackborder - hyperion-utils - leddevice - effectengine - serialport - ${QT_LIBRARIES} -) + +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion) + +# Group the headers that go through the MOC compiler +SET(Hyperion_QT_HEADERS + ${CURRENT_HEADER_DIR}/Hyperion.h + + ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h +) + +SET(Hyperion_HEADERS + ${CURRENT_HEADER_DIR}/ImageProcessor.h + ${CURRENT_HEADER_DIR}/ImageProcessorFactory.h + ${CURRENT_HEADER_DIR}/ImageToLedsMap.h + ${CURRENT_HEADER_DIR}/LedString.h + ${CURRENT_HEADER_DIR}/PriorityMuxer.h + + ${CURRENT_SOURCE_DIR}/MultiColorTransform.h + ${CURRENT_SOURCE_DIR}/MultiColorCorrection.h + ${CURRENT_SOURCE_DIR}/MultiColorAdjustment.h + ${CURRENT_HEADER_DIR}/MessageForwarder.h +) + +SET(Hyperion_SOURCES + ${CURRENT_SOURCE_DIR}/Hyperion.cpp + ${CURRENT_SOURCE_DIR}/ImageProcessor.cpp + ${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp + ${CURRENT_SOURCE_DIR}/LedString.cpp + ${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp + + ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp + ${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp + ${CURRENT_SOURCE_DIR}/MultiColorCorrection.cpp + ${CURRENT_SOURCE_DIR}/MultiColorAdjustment.cpp + ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp + ${CURRENT_SOURCE_DIR}/MessageForwarder.cpp +) + +SET(Hyperion_RESOURCES + ${CURRENT_SOURCE_DIR}/resource.qrc +) + +if(ENABLE_QT5) + QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) + QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") +else() + QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) + QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") +endif() + +add_library(hyperion + ${Hyperion_HEADERS} + ${Hyperion_QT_HEADERS} + ${Hyperion_HEADERS_MOC} + ${Hyperion_SOURCES} + ${Hyperion_RESOURCES_RCC} +) + +if(ENABLE_QT5) + qt5_use_modules(hyperion Widgets) +endif() + +target_link_libraries(hyperion + blackborder + hyperion-utils + leddevice + effectengine + serialport + ${QT_LIBRARIES} +) diff --git a/libsrc/hyperion/hyperion.schema.json b/libsrc/hyperion/hyperion.schema.json index aded2acf..f839b7f1 100644 --- a/libsrc/hyperion/hyperion.schema.json +++ b/libsrc/hyperion/hyperion.schema.json @@ -1,382 +1,382 @@ -{ - "type" : "object", - "required" : true, - "properties" : { - "device" : { - "type" : "object", - "required" : true, - "properties" : { - "name" : { - "type" : "string", - "required" : true - }, - "type" : { - "type" : "string", - "required" : true - }, - "output" : { - "type" : "string", - "required" : true - }, - "rate" : { - "type" : "integer", - "required" : true, - "minimum" : 0 - }, - "colorOrder" : { - "type" : "string", - "required" : false - }, - "bgr-output" : { // deprecated - "type" : "boolean", - "required" : false - } - }, - "additionalProperties" : false - }, - "color": { - "type":"object", - "required":false, - "properties": { - "hsv" : { - "type" : "object", - "required" : false, - "properties" : { - "saturationGain" : { - "type" : "number", - "required" : false, - "minimum" : 0.0 - }, - "valueGain" : { - "type" : "number", - "required" : false, - "minimum" : 0.0 - } - }, - "additionalProperties" : false - }, - "hsl" : { - "type" : "object", - "required" : false, - "properties" : { - "saturationGain" : { - "type" : "number", - "required" : false, - "minimum" : 0.0 - }, - "luminanceGain" : { - "type" : "number", - "required" : false, - "minimum" : 0.0 - }, - "luminanceMinimum" : { - "type" : "number", - "required" : false, - "minimum" : 0.0 - } - }, - "additionalProperties" : false - }, - "red": { - "type":"object", - "required":false, - "properties":{ - "gamma": { - "type":"number", - "required":false - }, - "blacklevel": { - "type":"number", - "required":false - }, - "whitelevel": { - "type":"number", - "required":false - }, - "threshold": { - "type":"number", - "required":false, - "minimum" : 0.0, - "maximum" : 1.0 - } - }, - "additionalProperties" : false - }, - "green": { - "type":"object", - "required":false, - "properties":{ - "gamma": { - "type":"number", - "required":false - }, - "blacklevel": { - "type":"number", - "required":false - }, - "whitelevel": { - "type":"number", - "required":false - }, - "threshold": { - "type":"number", - "required":false, - "minimum" : 0.0, - "maximum" : 1.0 - } - }, - "additionalProperties" : false - }, - "blue": { - "type":"object", - "required":false, - "properties":{ - "gamma": { - "type":"number", - "required":false - }, - "whitelevel": { - "type":"number", - "required":false - }, - "blacklevel": { - "type":"number", - "required":false - }, - "threshold": { - "type":"number", - "required":false, - "minimum" : 0.0, - "maximum" : 1.0 - } - }, - "additionalProperties" : false - }, - "smoothing" : { - "type" : "object", - "required" : false, - "properties" : { - "type" : { - "type" : "enum", - "required" : true, - "values" : ["none", "linear"] - }, - "time_ms" : { - "type" : "integer", - "required" : false, - "minimum" : 10 - }, - "updateFrequency" : { - "type" : "number", - "required" : false, - "minimum" : 0.001 - } - }, - "additionalProperties" : false - } - - }, - "additionalProperties" : false - }, - "leds": { - "type":"array", - "required":true, - "items": { - "type":"object", - "properties": { - "index": { - "type":"integer", - "required":true - }, - "hscan": { - "type":"object", - "required":true, - "properties": { - "minimum": { - "type":"number", - "required":true - }, - "maximum": { - "type":"number", - "required":true - } - }, - "additionalProperties" : false - }, - "vscan": { - "type":"object", - "required":true, - "properties": { - "minimum": { - "type":"number", - "required":true - }, - "maximum": { - "type":"number", - "required":true - } - }, - "additionalProperties" : false - }, - "colorOrder" : { - "type" : "string", - "required" : false - } - }, - "additionalProperties" : false - } - }, - "effects" : - { - "type" : "object", - "required" : false, - "properties" : { - "paths" : { - "type" : "array", - "required" : false, - "items" : { - "type" : "string" - } - } - }, - "additionalProperties" : false - }, - "blackborderdetector" : - { - "type" : "object", - "required" : false, - "properties" : { - "enable" : { - "type" : "boolean", - "required" : true - }, - "threshold" : { - "type" : "number", - "required" : false, - "minimum" : 0.0, - "maximum" : 1.0 - } - }, - "additionalProperties" : false - }, - "xbmcVideoChecker" : - { - "type" : "object", - "required" : false, - "properties" : { - "xbmcAddress" : { - "type" : "string", - "required" : true - }, - "xbmcTcpPort" : { - "type" : "integer", - "required" : true - }, - "grabVideo" : { - "type" : "boolean", - "required" : true - }, - "grabPictures" : { - "type" : "boolean", - "required" : true - }, - "grabAudio" : { - "type" : "boolean", - "required" : true - }, - "grabMenu" : { - "type" : "boolean", - "required" : true - }, - "grabScreensaver" : { - "type" : "boolean", - "required" : false - }, - "enable3DDetection" : { - "type" : "boolean", - "required" : false - } - }, - "additionalProperties" : false - }, - "bootsequence" : - { - "type" : "object", - "required" : false, - "properties" : { - "path" : { - "type" : "string", - "required" : true - }, - "effect" : { - "type" : "string", - "required" : true - } - }, - "additionalProperties" : false - }, - "framegrabber" : - { - "type" : "object", - "required" : false, - "properties" : { - "width" : { - "type" : "integer", - "required" : true - }, - "height" : { - "type" : "integer", - "required" : true - }, - "frequency_Hz" : { - "type" : "integer", - "required" : true - } - }, - "additionalProperties" : false - }, - "jsonServer" : - { - "type" : "object", - "required" : false, - "properties" : { - "port" : { - "type" : "integer", - "required" : true, - "minimum" : 0, - "maximum" : 65535 - } - }, - "additionalProperties" : false - }, - "protoServer" : - { - "type" : "object", - "required" : false, - "properties" : { - "port" : { - "type" : "integer", - "required" : true, - "minimum" : 0, - "maximum" : 65535 - } - }, - "additionalProperties" : false - }, - "boblightServer" : - { - "type" : "object", - "required" : false, - "properties" : { - "port" : { - "type" : "integer", - "required" : true, - "minimum" : 0, - "maximum" : 65535 - } - }, - "additionalProperties" : false - } - }, - "additionalProperties" : false -} +{ + "type" : "object", + "required" : true, + "properties" : { + "device" : { + "type" : "object", + "required" : true, + "properties" : { + "name" : { + "type" : "string", + "required" : true + }, + "type" : { + "type" : "string", + "required" : true + }, + "output" : { + "type" : "string", + "required" : true + }, + "rate" : { + "type" : "integer", + "required" : true, + "minimum" : 0 + }, + "colorOrder" : { + "type" : "string", + "required" : false + }, + "bgr-output" : { // deprecated + "type" : "boolean", + "required" : false + } + }, + "additionalProperties" : false + }, + "color": { + "type":"object", + "required":false, + "properties": { + "hsv" : { + "type" : "object", + "required" : false, + "properties" : { + "saturationGain" : { + "type" : "number", + "required" : false, + "minimum" : 0.0 + }, + "valueGain" : { + "type" : "number", + "required" : false, + "minimum" : 0.0 + } + }, + "additionalProperties" : false + }, + "hsl" : { + "type" : "object", + "required" : false, + "properties" : { + "saturationGain" : { + "type" : "number", + "required" : false, + "minimum" : 0.0 + }, + "luminanceGain" : { + "type" : "number", + "required" : false, + "minimum" : 0.0 + }, + "luminanceMinimum" : { + "type" : "number", + "required" : false, + "minimum" : 0.0 + } + }, + "additionalProperties" : false + }, + "red": { + "type":"object", + "required":false, + "properties":{ + "gamma": { + "type":"number", + "required":false + }, + "blacklevel": { + "type":"number", + "required":false + }, + "whitelevel": { + "type":"number", + "required":false + }, + "threshold": { + "type":"number", + "required":false, + "minimum" : 0.0, + "maximum" : 1.0 + } + }, + "additionalProperties" : false + }, + "green": { + "type":"object", + "required":false, + "properties":{ + "gamma": { + "type":"number", + "required":false + }, + "blacklevel": { + "type":"number", + "required":false + }, + "whitelevel": { + "type":"number", + "required":false + }, + "threshold": { + "type":"number", + "required":false, + "minimum" : 0.0, + "maximum" : 1.0 + } + }, + "additionalProperties" : false + }, + "blue": { + "type":"object", + "required":false, + "properties":{ + "gamma": { + "type":"number", + "required":false + }, + "whitelevel": { + "type":"number", + "required":false + }, + "blacklevel": { + "type":"number", + "required":false + }, + "threshold": { + "type":"number", + "required":false, + "minimum" : 0.0, + "maximum" : 1.0 + } + }, + "additionalProperties" : false + }, + "smoothing" : { + "type" : "object", + "required" : false, + "properties" : { + "type" : { + "type" : "enum", + "required" : true, + "values" : ["none", "linear"] + }, + "time_ms" : { + "type" : "integer", + "required" : false, + "minimum" : 10 + }, + "updateFrequency" : { + "type" : "number", + "required" : false, + "minimum" : 0.001 + } + }, + "additionalProperties" : false + } + + }, + "additionalProperties" : false + }, + "leds": { + "type":"array", + "required":true, + "items": { + "type":"object", + "properties": { + "index": { + "type":"integer", + "required":true + }, + "hscan": { + "type":"object", + "required":true, + "properties": { + "minimum": { + "type":"number", + "required":true + }, + "maximum": { + "type":"number", + "required":true + } + }, + "additionalProperties" : false + }, + "vscan": { + "type":"object", + "required":true, + "properties": { + "minimum": { + "type":"number", + "required":true + }, + "maximum": { + "type":"number", + "required":true + } + }, + "additionalProperties" : false + }, + "colorOrder" : { + "type" : "string", + "required" : false + } + }, + "additionalProperties" : false + } + }, + "effects" : + { + "type" : "object", + "required" : false, + "properties" : { + "paths" : { + "type" : "array", + "required" : false, + "items" : { + "type" : "string" + } + } + }, + "additionalProperties" : false + }, + "blackborderdetector" : + { + "type" : "object", + "required" : false, + "properties" : { + "enable" : { + "type" : "boolean", + "required" : true + }, + "threshold" : { + "type" : "number", + "required" : false, + "minimum" : 0.0, + "maximum" : 1.0 + } + }, + "additionalProperties" : false + }, + "xbmcVideoChecker" : + { + "type" : "object", + "required" : false, + "properties" : { + "xbmcAddress" : { + "type" : "string", + "required" : true + }, + "xbmcTcpPort" : { + "type" : "integer", + "required" : true + }, + "grabVideo" : { + "type" : "boolean", + "required" : true + }, + "grabPictures" : { + "type" : "boolean", + "required" : true + }, + "grabAudio" : { + "type" : "boolean", + "required" : true + }, + "grabMenu" : { + "type" : "boolean", + "required" : true + }, + "grabScreensaver" : { + "type" : "boolean", + "required" : false + }, + "enable3DDetection" : { + "type" : "boolean", + "required" : false + } + }, + "additionalProperties" : false + }, + "bootsequence" : + { + "type" : "object", + "required" : false, + "properties" : { + "path" : { + "type" : "string", + "required" : true + }, + "effect" : { + "type" : "string", + "required" : true + } + }, + "additionalProperties" : false + }, + "framegrabber" : + { + "type" : "object", + "required" : false, + "properties" : { + "width" : { + "type" : "integer", + "required" : true + }, + "height" : { + "type" : "integer", + "required" : true + }, + "frequency_Hz" : { + "type" : "integer", + "required" : true + } + }, + "additionalProperties" : false + }, + "jsonServer" : + { + "type" : "object", + "required" : false, + "properties" : { + "port" : { + "type" : "integer", + "required" : true, + "minimum" : 0, + "maximum" : 65535 + } + }, + "additionalProperties" : false + }, + "protoServer" : + { + "type" : "object", + "required" : false, + "properties" : { + "port" : { + "type" : "integer", + "required" : true, + "minimum" : 0, + "maximum" : 65535 + } + }, + "additionalProperties" : false + }, + "boblightServer" : + { + "type" : "object", + "required" : false, + "properties" : { + "port" : { + "type" : "integer", + "required" : true, + "minimum" : 0, + "maximum" : 65535 + } + }, + "additionalProperties" : false + } + }, + "additionalProperties" : false +} diff --git a/libsrc/jsonserver/CMakeLists.txt b/libsrc/jsonserver/CMakeLists.txt index d03ed1ea..9569f076 100644 --- a/libsrc/jsonserver/CMakeLists.txt +++ b/libsrc/jsonserver/CMakeLists.txt @@ -1,48 +1,48 @@ - -# Define the current source locations -set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/jsonserver) -set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/jsonserver) - -# Group the headers that go through the MOC compiler -set(JsonServer_QT_HEADERS - ${CURRENT_HEADER_DIR}/JsonServer.h - ${CURRENT_SOURCE_DIR}/JsonClientConnection.h -) - -set(JsonServer_HEADERS -) - -set(JsonServer_SOURCES - ${CURRENT_SOURCE_DIR}/JsonServer.cpp - ${CURRENT_SOURCE_DIR}/JsonClientConnection.cpp -) - -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} - ${JsonServer_QT_HEADERS} - ${JsonServer_SOURCES} - ${JsonServer_RESOURCES} - ${JsonServer_HEADERS_MOC} - ${JsonServer_RESOURCES_RCC} -) - -if(ENABLE_QT5) -qt5_use_modules(jsonserver Widgets Network) -endif(ENABLE_QT5) - -target_link_libraries(jsonserver - hyperion - hyperion-utils - jsoncpp - ${QT_LIBRARIES}) + +# Define the current source locations +set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/jsonserver) +set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/jsonserver) + +# Group the headers that go through the MOC compiler +set(JsonServer_QT_HEADERS + ${CURRENT_HEADER_DIR}/JsonServer.h + ${CURRENT_SOURCE_DIR}/JsonClientConnection.h +) + +set(JsonServer_HEADERS +) + +set(JsonServer_SOURCES + ${CURRENT_SOURCE_DIR}/JsonServer.cpp + ${CURRENT_SOURCE_DIR}/JsonClientConnection.cpp +) + +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() + qt4_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS}) + qt4_add_resources(JsonServer_RESOURCES_RCC ${JsonServer_RESOURCES} OPTIONS "-no-compress") +endif() + +add_library(jsonserver + ${JsonServer_HEADERS} + ${JsonServer_QT_HEADERS} + ${JsonServer_SOURCES} + ${JsonServer_RESOURCES} + ${JsonServer_HEADERS_MOC} + ${JsonServer_RESOURCES_RCC} +) + +if(ENABLE_QT5) + qt5_use_modules(jsonserver Widgets Network) +endif() + +target_link_libraries(jsonserver + hyperion + hyperion-utils + jsoncpp + ${QT_LIBRARIES}) diff --git a/libsrc/leddevice/CMakeLists.txt b/libsrc/leddevice/CMakeLists.txt index 2d2ceba5..efdbffa6 100755 --- a/libsrc/leddevice/CMakeLists.txt +++ b/libsrc/leddevice/CMakeLists.txt @@ -1,165 +1,166 @@ - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/leddevice) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/leddevice) - -#add libusb and pthreads (required for the Lighpack usb device) -find_package(libusb-1.0 REQUIRED) -find_package(Threads REQUIRED) - -include_directories( - ../../include/hidapi - ${LIBUSB_1_INCLUDE_DIRS}) # for Lightpack device - -# Group the headers that go through the MOC compiler -SET(Leddevice_QT_HEADERS - ${CURRENT_SOURCE_DIR}/LedRs232Device.h - ${CURRENT_SOURCE_DIR}/LedDeviceAdalight.h - ${CURRENT_SOURCE_DIR}/LedDeviceAdalightApa102.h - ${CURRENT_SOURCE_DIR}/LedDeviceAmbiLed.h - ${CURRENT_SOURCE_DIR}/LedDeviceAtmoOrb.h - ${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.h - ${CURRENT_SOURCE_DIR}/LedHIDDevice.h - ${CURRENT_SOURCE_DIR}/LedDeviceRawHID.h - ${CURRENT_SOURCE_DIR}/LedDeviceFile.h - ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h -) - -SET(Leddevice_HEADERS - ${CURRENT_HEADER_DIR}/LedDevice.h - ${CURRENT_HEADER_DIR}/LedDeviceFactory.h - - ${CURRENT_SOURCE_DIR}/LedDeviceLightpack.h - ${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.h - ${CURRENT_SOURCE_DIR}/LedDevicePaintpack.h - ${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.h - ${CURRENT_SOURCE_DIR}/LedDeviceSedu.h - ${CURRENT_SOURCE_DIR}/LedDeviceFile.h - ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h - ${CURRENT_SOURCE_DIR}/LedDeviceUdp.h - ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h - ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.h - ${CURRENT_SOURCE_DIR}/LedDeviceAtmo.h -) - -SET(Leddevice_SOURCES - ${CURRENT_SOURCE_DIR}/LedDeviceFactory.cpp - - ${CURRENT_SOURCE_DIR}/LedRs232Device.cpp - ${CURRENT_SOURCE_DIR}/LedHIDDevice.cpp - - ${CURRENT_SOURCE_DIR}/LedDeviceAdalight.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceAdalightApa102.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceAmbiLed.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceAtmoOrb.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceRawHID.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceLightpack.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.cpp - ${CURRENT_SOURCE_DIR}/LedDevicePaintpack.cpp - ${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceFile.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp - ${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceAtmo.cpp -) - -if(ENABLE_SPIDEV) - SET(Leddevice_HEADERS - ${Leddevice_HEADERS} - ${CURRENT_SOURCE_DIR}/LedSpiDevice.h - ${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.h - ${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.h - ${CURRENT_SOURCE_DIR}/LedDeviceP9813.h - ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h - ${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.h - ${CURRENT_SOURCE_DIR}/LedDeviceAPA102.h - ) - SET(Leddevice_SOURCES - ${Leddevice_SOURCES} - ${CURRENT_SOURCE_DIR}/LedSpiDevice.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceP9813.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceAPA102.cpp - ) -endif(ENABLE_SPIDEV) - -if(ENABLE_WS2812BPWM) -SET(Leddevice_HEADERS - ${Leddevice_HEADERS} - ${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.h - ) -SET(Leddevice_SOURCES - ${Leddevice_SOURCES} - ${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.cpp -) -endif(ENABLE_WS2812BPWM) - -if(ENABLE_WS281XPWM) -include_directories(../../dependencies/external/rpi_ws281x) -SET(Leddevice_HEADERS - ${Leddevice_HEADERS} - ${CURRENT_SOURCE_DIR}/LedDeviceWS281x.h - ) -SET(Leddevice_SOURCES - ${Leddevice_SOURCES} - ${CURRENT_SOURCE_DIR}/LedDeviceWS281x.cpp -) -endif(ENABLE_WS281XPWM) - -if(ENABLE_TINKERFORGE) - SET(Leddevice_HEADERS - ${Leddevice_HEADERS} - ${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.h - ) - SET(Leddevice_SOURCES - ${Leddevice_SOURCES} - ${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.cpp - ) -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} - ${Leddevice_QT_HEADERS} - ${Leddevice_HEADERS_MOC} - ${Leddevice_SOURCES} -) - -if(ENABLE_QT5) -qt5_use_modules(leddevice Widgets Network) -endif(ENABLE_QT5) - -target_link_libraries(leddevice - hyperion-utils - serialport - ${LIBUSB_1_LIBRARIES} #apt-get install libusb-1.0-0-dev - ${CMAKE_THREAD_LIBS_INIT} - ${QT_LIBRARIES} -) - -if(ENABLE_TINKERFORGE) - target_link_libraries(leddevice tinkerforge) -endif() - -if(ENABLE_WS281XPWM) - target_link_libraries(leddevice ws281x) -endif() - -if(APPLE) - target_link_libraries(leddevice hidapi-mac) -else() - target_link_libraries(leddevice hidapi-libusb) -endif() + +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/leddevice) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/leddevice) + +#add libusb and pthreads (required for the Lighpack usb device) +find_package(libusb-1.0 REQUIRED) +find_package(Threads REQUIRED) + +include_directories( + ../../include/hidapi + ${LIBUSB_1_INCLUDE_DIRS} +) # for Lightpack device + +# Group the headers that go through the MOC compiler +SET(Leddevice_QT_HEADERS + ${CURRENT_SOURCE_DIR}/LedRs232Device.h + ${CURRENT_SOURCE_DIR}/LedDeviceAdalight.h + ${CURRENT_SOURCE_DIR}/LedDeviceAdalightApa102.h + ${CURRENT_SOURCE_DIR}/LedDeviceAmbiLed.h + ${CURRENT_SOURCE_DIR}/LedDeviceAtmoOrb.h + ${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.h + ${CURRENT_SOURCE_DIR}/LedHIDDevice.h + ${CURRENT_SOURCE_DIR}/LedDeviceRawHID.h + ${CURRENT_SOURCE_DIR}/LedDeviceFile.h + ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h +) + +SET(Leddevice_HEADERS + ${CURRENT_HEADER_DIR}/LedDevice.h + ${CURRENT_HEADER_DIR}/LedDeviceFactory.h + + ${CURRENT_SOURCE_DIR}/LedDeviceLightpack.h + ${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.h + ${CURRENT_SOURCE_DIR}/LedDevicePaintpack.h + ${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.h + ${CURRENT_SOURCE_DIR}/LedDeviceSedu.h + ${CURRENT_SOURCE_DIR}/LedDeviceFile.h + ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h + ${CURRENT_SOURCE_DIR}/LedDeviceUdp.h + ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h + ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.h + ${CURRENT_SOURCE_DIR}/LedDeviceAtmo.h +) + +SET(Leddevice_SOURCES + ${CURRENT_SOURCE_DIR}/LedDeviceFactory.cpp + + ${CURRENT_SOURCE_DIR}/LedRs232Device.cpp + ${CURRENT_SOURCE_DIR}/LedHIDDevice.cpp + + ${CURRENT_SOURCE_DIR}/LedDeviceAdalight.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceAdalightApa102.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceAmbiLed.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceAtmoOrb.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceRawHID.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceLightpack.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.cpp + ${CURRENT_SOURCE_DIR}/LedDevicePaintpack.cpp + ${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceFile.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp + ${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceAtmo.cpp +) + +if(ENABLE_SPIDEV) + SET(Leddevice_HEADERS + ${Leddevice_HEADERS} + ${CURRENT_SOURCE_DIR}/LedSpiDevice.h + ${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.h + ${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.h + ${CURRENT_SOURCE_DIR}/LedDeviceP9813.h + ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h + ${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.h + ${CURRENT_SOURCE_DIR}/LedDeviceAPA102.h + ) + SET(Leddevice_SOURCES + ${Leddevice_SOURCES} + ${CURRENT_SOURCE_DIR}/LedSpiDevice.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceP9813.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceAPA102.cpp + ) +endif() + +if(ENABLE_WS2812BPWM) + SET(Leddevice_HEADERS + ${Leddevice_HEADERS} + ${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.h + ) + SET(Leddevice_SOURCES + ${Leddevice_SOURCES} + ${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.cpp + ) +endif() + +if(ENABLE_WS281XPWM) + include_directories(../../dependencies/external/rpi_ws281x) + SET(Leddevice_HEADERS + ${Leddevice_HEADERS} + ${CURRENT_SOURCE_DIR}/LedDeviceWS281x.h + ) + SET(Leddevice_SOURCES + ${Leddevice_SOURCES} + ${CURRENT_SOURCE_DIR}/LedDeviceWS281x.cpp + ) +endif() + +if(ENABLE_TINKERFORGE) + SET(Leddevice_HEADERS + ${Leddevice_HEADERS} + ${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.h + ) + SET(Leddevice_SOURCES + ${Leddevice_SOURCES} + ${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.cpp + ) +endif() + +if(ENABLE_QT5) + QT5_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS}) +else() + QT4_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS}) +endif() + + +add_library(leddevice + ${Leddevice_HEADERS} + ${Leddevice_QT_HEADERS} + ${Leddevice_HEADERS_MOC} + ${Leddevice_SOURCES} +) + +if(ENABLE_QT5) + qt5_use_modules(leddevice Widgets Network) +endif() + +target_link_libraries(leddevice + hyperion-utils + serialport + ${LIBUSB_1_LIBRARIES} #apt-get install libusb-1.0-0-dev + ${CMAKE_THREAD_LIBS_INIT} + ${QT_LIBRARIES} +) + +if(ENABLE_TINKERFORGE) + target_link_libraries(leddevice tinkerforge) +endif() + +if(ENABLE_WS281XPWM) + target_link_libraries(leddevice ws281x) +endif() + +if(APPLE) + target_link_libraries(leddevice hidapi-mac) +else() + target_link_libraries(leddevice hidapi-libusb) +endif() diff --git a/libsrc/leddevice/LedDeviceAtmoOrb.cpp b/libsrc/leddevice/LedDeviceAtmoOrb.cpp index ae448f33..28532105 100644 --- a/libsrc/leddevice/LedDeviceAtmoOrb.cpp +++ b/libsrc/leddevice/LedDeviceAtmoOrb.cpp @@ -1,152 +1,158 @@ -// Local-Hyperion includes -#include "LedDeviceAtmoOrb.h" - -// qt includes -#include -#include -#include -#include - -#include -#include -#include - -AtmoOrbLight::AtmoOrbLight(unsigned int id) { - // Not implemented -} - -LedDeviceAtmoOrb::LedDeviceAtmoOrb(const std::string &output, bool useOrbSmoothing, - int transitiontime, int skipSmoothingDiff, int port, int numLeds, std::vector orbIds) : - multicastGroup(output.c_str()), useOrbSmoothing(useOrbSmoothing), transitiontime(transitiontime), skipSmoothingDiff(skipSmoothingDiff), - multiCastGroupPort(port), numLeds(numLeds), orbIds(orbIds) { - manager = new QNetworkAccessManager(); - groupAddress = QHostAddress(multicastGroup); - - udpSocket = new QUdpSocket(this); - udpSocket->bind(multiCastGroupPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); - - joinedMulticastgroup = udpSocket->joinMulticastGroup(groupAddress); -} - -int LedDeviceAtmoOrb::write(const std::vector &ledValues) { - - // If not in multicast group return - if (!joinedMulticastgroup) { - return 0; - } - - // Command options: - // - // 1 = force off - // 2 = use lamp smoothing and validate by Orb ID - // 4 = validate by Orb ID - - // When setting useOrbSmoothing = true it's recommended to disable Hyperion's own smoothing as it will conflict (double smoothing) - int commandType = 4; - if(useOrbSmoothing) - { - commandType = 2; - } - - // Iterate through colors and set Orb color - // Start off with idx 1 as 0 is reserved for controlling all orbs at once - unsigned int idx = 1; - - for (const ColorRgb &color : ledValues) { - // Retrieve last send colors - int lastRed = lastColorRedMap[idx]; - int lastGreen = lastColorGreenMap[idx]; - int lastBlue = lastColorBlueMap[idx]; - - // If color difference is higher than skipSmoothingDiff than we skip Orb smoothing (if enabled) and send it right away - if ((skipSmoothingDiff != 0 && useOrbSmoothing) && (abs(color.red - lastRed) >= skipSmoothingDiff || abs(color.blue - lastBlue) >= skipSmoothingDiff || - abs(color.green - lastGreen) >= skipSmoothingDiff)) - { - // Skip Orb smoothing when using (command type 4) - for (unsigned int i = 0; i < orbIds.size(); i++) { - if (orbIds[i] == idx) { - setColor(idx, color, 4); - } - } - } - else { - // Send color - for (unsigned int i = 0; i < orbIds.size(); i++) { - if (orbIds[i] == idx) { - setColor(idx, color, commandType); - } - } - } - - // Store last colors send for light id - lastColorRedMap[idx] = color.red; - lastColorGreenMap[idx] = color.green; - lastColorBlueMap[idx] = color.blue; - - // Next light id. - idx++; - } - - return 0; -} - -void LedDeviceAtmoOrb::setColor(unsigned int orbId, const ColorRgb &color, int commandType) { - QByteArray bytes; - bytes.resize(5 + numLeds * 3); - bytes.fill('\0'); - - // Command identifier: C0FFEE - bytes[0] = 0xC0; - bytes[1] = 0xFF; - bytes[2] = 0xEE; - - // Command type - bytes[3] = commandType; - - // Orb ID - bytes[4] = orbId; - - // RED / GREEN / BLUE - bytes[5] = color.red; - bytes[6] = color.green; - bytes[7] = color.blue; - - sendCommand(bytes); -} - -void LedDeviceAtmoOrb::sendCommand(const QByteArray &bytes) { - QByteArray datagram = bytes; - udpSocket->writeDatagram(datagram.data(), datagram.size(), - groupAddress, multiCastGroupPort); -} - -int LedDeviceAtmoOrb::switchOff() { - for (unsigned int i = 0; i < orbIds.size(); i++) { - QByteArray bytes; - bytes.resize(5 + numLeds * 3); - bytes.fill('\0'); - - // Command identifier: C0FFEE - bytes[0] = 0xC0; - bytes[1] = 0xFF; - bytes[2] = 0xEE; - - // Command type - bytes[3] = 1; - - // Orb ID - bytes[4] = orbIds[i]; - - // RED / GREEN / BLUE - bytes[5] = 0; - bytes[6] = 0; - bytes[7] = 0; - - sendCommand(bytes); - } - return 0; -} - -LedDeviceAtmoOrb::~LedDeviceAtmoOrb() { - delete manager; -} \ No newline at end of file +// Local-Hyperion includes +#include "LedDeviceAtmoOrb.h" + +// qt includes +#include +#include +#include +#include + +#include +#include +#include + +AtmoOrbLight::AtmoOrbLight(unsigned int id) { + // Not implemented +} + +LedDeviceAtmoOrb::LedDeviceAtmoOrb( + const std::string &output, + bool useOrbSmoothing, + int transitiontime, + int skipSmoothingDiff, + int port, + int numLeds, + std::vector orbIds) : + multicastGroup(output.c_str()), useOrbSmoothing(useOrbSmoothing), transitiontime(transitiontime), skipSmoothingDiff(skipSmoothingDiff), + multiCastGroupPort(port), numLeds(numLeds), orbIds(orbIds) +{ + manager = new QNetworkAccessManager(); + groupAddress = QHostAddress(multicastGroup); + + udpSocket = new QUdpSocket(this); + udpSocket->bind(multiCastGroupPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); + + joinedMulticastgroup = udpSocket->joinMulticastGroup(groupAddress); +} + +int LedDeviceAtmoOrb::write(const std::vector &ledValues) { + // If not in multicast group return + if (!joinedMulticastgroup) { + return 0; + } + + // Command options: + // + // 1 = force off + // 2 = use lamp smoothing and validate by Orb ID + // 4 = validate by Orb ID + + // When setting useOrbSmoothing = true it's recommended to disable Hyperion's own smoothing as it will conflict (double smoothing) + int commandType = 4; + if(useOrbSmoothing) + { + commandType = 2; + } + + // Iterate through colors and set Orb color + // Start off with idx 1 as 0 is reserved for controlling all orbs at once + unsigned int idx = 1; + + for (const ColorRgb &color : ledValues) { + // Retrieve last send colors + int lastRed = lastColorRedMap[idx]; + int lastGreen = lastColorGreenMap[idx]; + int lastBlue = lastColorBlueMap[idx]; + + // If color difference is higher than skipSmoothingDiff than we skip Orb smoothing (if enabled) and send it right away + if ((skipSmoothingDiff != 0 && useOrbSmoothing) && (abs(color.red - lastRed) >= skipSmoothingDiff || abs(color.blue - lastBlue) >= skipSmoothingDiff || + abs(color.green - lastGreen) >= skipSmoothingDiff)) + { + // Skip Orb smoothing when using (command type 4) + for (unsigned int i = 0; i < orbIds.size(); i++) { + if (orbIds[i] == idx) { + setColor(idx, color, 4); + } + } + } + else { + // Send color + for (unsigned int i = 0; i < orbIds.size(); i++) { + if (orbIds[i] == idx) { + setColor(idx, color, commandType); + } + } + } + + // Store last colors send for light id + lastColorRedMap[idx] = color.red; + lastColorGreenMap[idx] = color.green; + lastColorBlueMap[idx] = color.blue; + + // Next light id. + idx++; + } + + return 0; +} + +void LedDeviceAtmoOrb::setColor(unsigned int orbId, const ColorRgb &color, int commandType) { + QByteArray bytes; + bytes.resize(5 + numLeds * 3); + bytes.fill('\0'); + + // Command identifier: C0FFEE + bytes[0] = 0xC0; + bytes[1] = 0xFF; + bytes[2] = 0xEE; + + // Command type + bytes[3] = commandType; + + // Orb ID + bytes[4] = orbId; + + // RED / GREEN / BLUE + bytes[5] = color.red; + bytes[6] = color.green; + bytes[7] = color.blue; + + sendCommand(bytes); +} + +void LedDeviceAtmoOrb::sendCommand(const QByteArray &bytes) { + QByteArray datagram = bytes; + udpSocket->writeDatagram(datagram.data(), datagram.size(), + groupAddress, multiCastGroupPort); +} + +int LedDeviceAtmoOrb::switchOff() { + for (unsigned int i = 0; i < orbIds.size(); i++) { + QByteArray bytes; + bytes.resize(5 + numLeds * 3); + bytes.fill('\0'); + + // Command identifier: C0FFEE + bytes[0] = 0xC0; + bytes[1] = 0xFF; + bytes[2] = 0xEE; + + // Command type + bytes[3] = 1; + + // Orb ID + bytes[4] = orbIds[i]; + + // RED / GREEN / BLUE + bytes[5] = 0; + bytes[6] = 0; + bytes[7] = 0; + + sendCommand(bytes); + } + return 0; +} + +LedDeviceAtmoOrb::~LedDeviceAtmoOrb() { + delete manager; +} diff --git a/libsrc/leddevice/LedDeviceAtmoOrb.h b/libsrc/leddevice/LedDeviceAtmoOrb.h index 8c697af2..6b574155 100644 --- a/libsrc/leddevice/LedDeviceAtmoOrb.h +++ b/libsrc/leddevice/LedDeviceAtmoOrb.h @@ -1,132 +1,132 @@ -#pragma once - -// STL includes -#include - -// Qt includes -#include -#include -#include -#include - -// Leddevice includes -#include - -class QUdpSocket; - -class AtmoOrbLight { -public: - unsigned int id; - - /// - /// Constructs the light. - /// - /// @param id the orb id - AtmoOrbLight(unsigned int id); -}; - -/** - * Implementation for the AtmoOrb - * - * To use set the device to "atmoorb". - * - * @author RickDB (github) - */ -class LedDeviceAtmoOrb : public QObject, public LedDevice { - Q_OBJECT -public: - // Last send color map - QMap lastColorRedMap; - QMap lastColorGreenMap; - QMap lastColorBlueMap; - - // Multicast status - bool joinedMulticastgroup; - - /// - /// Constructs the device. - /// - /// @param output is the multicast address of Orbs - /// - /// @param transitiontime is optional and not used at the moment - /// - /// @param useOrbSmoothing use Orbs own (external) smoothing algorithm (default: false) - /// - /// @param skipSmoothingDiff minimal color (0-255) difference to override smoothing so that if current and previously received colors are higher than set dif we override smoothing - /// - /// @param port is the multicast port. - /// - /// @param numLeds is the total amount of leds per Orb - /// - /// @param array containing orb ids - /// - LedDeviceAtmoOrb(const std::string &output, bool useOrbSmoothing = - false, int transitiontime = 0, int skipSmoothingDiff = 0, int port = 49692, int numLeds = 24, - std::vector orbIds = std::vector < unsigned int>()); - - /// - /// Destructor of this device - /// - virtual ~LedDeviceAtmoOrb(); - - /// - /// Sends the given led-color values to the Orbs - /// - /// @param ledValues The color-value per led - /// - /// @return Zero on success else negative - /// - virtual int write(const std::vector &ledValues); - - virtual int switchOff(); - -private: - /// QNetworkAccessManager object for sending requests. - QNetworkAccessManager *manager; - - /// String containing multicast group IP address - QString multicastGroup; - - /// use Orbs own (external) smoothing algorithm - bool useOrbSmoothing; - - /// Transition time between colors (not implemented) - int transitiontime; - - // Maximum allowed color difference, will skip Orb (external) smoothing once reached - int skipSmoothingDiff; - - /// Multicast port to send data to - int multiCastGroupPort; - - /// Number of leds in Orb, used to determine buffer size - int numLeds; - - /// QHostAddress object of multicast group IP address - QHostAddress groupAddress; - - /// QUdpSocket object used to send data over - QUdpSocket *udpSocket; - - /// Array of the orb ids. - std::vector orbIds; - - /// - /// Set Orbcolor - /// - /// @param orbId the orb id - /// - /// @param color which color to set - /// - /// - /// @param commandType which type of command to send (off / smoothing / etc..) - /// - void setColor(unsigned int orbId, const ColorRgb &color, int commandType); - - /// - /// Send Orb command - /// - /// @param bytes the byte array containing command to send over multicast - /// - void sendCommand(const QByteArray &bytes); +#pragma once + +// STL includes +#include + +// Qt includes +#include +#include +#include +#include + +// Leddevice includes +#include + +class QUdpSocket; + +class AtmoOrbLight { +public: + unsigned int id; + + /// + /// Constructs the light. + /// + /// @param id the orb id + AtmoOrbLight(unsigned int id); +}; + +/** + * Implementation for the AtmoOrb + * + * To use set the device to "atmoorb". + * + * @author RickDB (github) + */ +class LedDeviceAtmoOrb : public QObject, public LedDevice { + Q_OBJECT +public: + // Last send color map + QMap lastColorRedMap; + QMap lastColorGreenMap; + QMap lastColorBlueMap; + + // Multicast status + bool joinedMulticastgroup; + + /// + /// Constructs the device. + /// + /// @param output is the multicast address of Orbs + /// + /// @param transitiontime is optional and not used at the moment + /// + /// @param useOrbSmoothing use Orbs own (external) smoothing algorithm (default: false) + /// + /// @param skipSmoothingDiff minimal color (0-255) difference to override smoothing so that if current and previously received colors are higher than set dif we override smoothing + /// + /// @param port is the multicast port. + /// + /// @param numLeds is the total amount of leds per Orb + /// + /// @param array containing orb ids + /// + LedDeviceAtmoOrb(const std::string &output, bool useOrbSmoothing = + false, int transitiontime = 0, int skipSmoothingDiff = 0, int port = 49692, int numLeds = 24, + std::vector orbIds = std::vector < unsigned int>()); + + /// + /// Destructor of this device + /// + virtual ~LedDeviceAtmoOrb(); + + /// + /// Sends the given led-color values to the Orbs + /// + /// @param ledValues The color-value per led + /// + /// @return Zero on success else negative + /// + virtual int write(const std::vector &ledValues); + + virtual int switchOff(); + +private: + /// QNetworkAccessManager object for sending requests. + QNetworkAccessManager *manager; + + /// String containing multicast group IP address + QString multicastGroup; + + /// use Orbs own (external) smoothing algorithm + bool useOrbSmoothing; + + /// Transition time between colors (not implemented) + int transitiontime; + + // Maximum allowed color difference, will skip Orb (external) smoothing once reached + int skipSmoothingDiff; + + /// Multicast port to send data to + int multiCastGroupPort; + + /// Number of leds in Orb, used to determine buffer size + int numLeds; + + /// QHostAddress object of multicast group IP address + QHostAddress groupAddress; + + /// QUdpSocket object used to send data over + QUdpSocket *udpSocket; + + /// Array of the orb ids. + std::vector orbIds; + + /// + /// Set Orbcolor + /// + /// @param orbId the orb id + /// + /// @param color which color to set + /// + /// + /// @param commandType which type of command to send (off / smoothing / etc..) + /// + void setColor(unsigned int orbId, const ColorRgb &color, int commandType); + + /// + /// Send Orb command + /// + /// @param bytes the byte array containing command to send over multicast + /// + void sendCommand(const QByteArray &bytes); }; \ No newline at end of file diff --git a/libsrc/leddevice/LedDeviceLpd6803.cpp b/libsrc/leddevice/LedDeviceLpd6803.cpp index 09d5f838..2a3aeb6b 100644 --- a/libsrc/leddevice/LedDeviceLpd6803.cpp +++ b/libsrc/leddevice/LedDeviceLpd6803.cpp @@ -1,50 +1,50 @@ -// STL includes -#include -#include -#include - -// Linux includes -#include -#include - -// hyperion local includes -#include "LedDeviceLpd6803.h" - -LedDeviceLpd6803::LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate) : - LedSpiDevice(outputDevice, baudrate), - _ledBuffer(0) -{ - // empty -} - -int LedDeviceLpd6803::write(const std::vector &ledValues) -{ - unsigned messageLength = 4 + 2*ledValues.size() + ledValues.size()/8 + 1; - // Reconfigure if the current connfiguration does not match the required configuration - if (messageLength != _ledBuffer.size()) - { - // Initialise the buffer - _ledBuffer.resize(messageLength, 0x00); - } - - // Copy the colors from the ColorRgb vector to the Ldp6803 data vector - for (unsigned iLed=0; iLed> 1) | (rgb.green >> 6); - _ledBuffer[5 + 2 * iLed] = ((rgb.green & 0x38) << 2) | (rgb.blue >> 3); - } - - // Write the data - if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0) - { - return -1; - } - return 0; -} - -int LedDeviceLpd6803::switchOff() -{ - return write(std::vector(_ledBuffer.size(), ColorRgb{0,0,0})); -} +// STL includes +#include +#include +#include + +// Linux includes +#include +#include + +// hyperion local includes +#include "LedDeviceLpd6803.h" + +LedDeviceLpd6803::LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate) : + LedSpiDevice(outputDevice, baudrate), + _ledBuffer(0) +{ + // empty +} + +int LedDeviceLpd6803::write(const std::vector &ledValues) +{ + unsigned messageLength = 4 + 2*ledValues.size() + ledValues.size()/8 + 1; + // Reconfigure if the current connfiguration does not match the required configuration + if (messageLength != _ledBuffer.size()) + { + // Initialise the buffer + _ledBuffer.resize(messageLength, 0x00); + } + + // Copy the colors from the ColorRgb vector to the Ldp6803 data vector + for (unsigned iLed=0; iLed> 1) | (rgb.green >> 6); + _ledBuffer[5 + 2 * iLed] = ((rgb.green & 0x38) << 2) | (rgb.blue >> 3); + } + + // Write the data + if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0) + { + return -1; + } + return 0; +} + +int LedDeviceLpd6803::switchOff() +{ + return write(std::vector(_ledBuffer.size(), ColorRgb{0,0,0})); +} diff --git a/libsrc/leddevice/LedDeviceLpd6803.h b/libsrc/leddevice/LedDeviceLpd6803.h index c53919b2..f3d08978 100644 --- a/libsrc/leddevice/LedDeviceLpd6803.h +++ b/libsrc/leddevice/LedDeviceLpd6803.h @@ -1,42 +1,42 @@ -#pragma once - -// Local hyperion incluse -#include "LedSpiDevice.h" - -/// -/// Implementation of the LedDevice interface for writing to LDP6803 led device. -/// -/// 00000000 00000000 00000000 00000000 1RRRRRGG GGGBBBBB 1RRRRRGG GGGBBBBB ... -/// |---------------------------------| |---------------| |---------------| -/// 32 zeros to start the frame Led1 Led2 ... -/// -/// For each led, the first bit is always 1, and then you have 5 bits each for red, green and blue -/// (R, G and B in the above illustration) making 16 bits per led. Total bytes = 4 + (2 x number of -/// leds) -/// -class LedDeviceLpd6803 : public LedSpiDevice -{ -public: - /// - /// Constructs the LedDevice for a string containing leds of the type LDP6803 - /// - /// @param[in] outputDevice The name of the output device (eg '/dev/spidev0.0') - /// @param[in] baudrate The used baudrate for writing to the output device - /// - LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate); - - /// - /// Writes the led color values to the led-device - /// - /// @param ledValues The color-value per led - /// @return Zero on succes else negative - /// - virtual int write(const std::vector &ledValues); - - /// Switch the leds off - virtual int switchOff(); - -private: - /// The buffer containing the packed RGB values - std::vector _ledBuffer; -}; +#pragma once + +// Local hyperion incluse +#include "LedSpiDevice.h" + +/// +/// Implementation of the LedDevice interface for writing to LDP6803 led device. +/// +/// 00000000 00000000 00000000 00000000 1RRRRRGG GGGBBBBB 1RRRRRGG GGGBBBBB ... +/// |---------------------------------| |---------------| |---------------| +/// 32 zeros to start the frame Led1 Led2 ... +/// +/// For each led, the first bit is always 1, and then you have 5 bits each for red, green and blue +/// (R, G and B in the above illustration) making 16 bits per led. Total bytes = 4 + (2 x number of +/// leds) +/// +class LedDeviceLpd6803 : public LedSpiDevice +{ +public: + /// + /// Constructs the LedDevice for a string containing leds of the type LDP6803 + /// + /// @param[in] outputDevice The name of the output device (eg '/dev/spidev0.0') + /// @param[in] baudrate The used baudrate for writing to the output device + /// + LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate); + + /// + /// Writes the led color values to the led-device + /// + /// @param ledValues The color-value per led + /// @return Zero on succes else negative + /// + virtual int write(const std::vector &ledValues); + + /// Switch the leds off + virtual int switchOff(); + +private: + /// The buffer containing the packed RGB values + std::vector _ledBuffer; +}; diff --git a/libsrc/leddevice/LedDeviceLpd8806.cpp b/libsrc/leddevice/LedDeviceLpd8806.cpp index 3e8cc1da..f9dfb53c 100644 --- a/libsrc/leddevice/LedDeviceLpd8806.cpp +++ b/libsrc/leddevice/LedDeviceLpd8806.cpp @@ -1,54 +1,54 @@ -// STL includes -#include -#include -#include - -// Linux includes -#include -#include - -// hyperion local includes -#include "LedDeviceLpd8806.h" - -LedDeviceLpd8806::LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate) : - LedSpiDevice(outputDevice, baudrate), - _ledBuffer(0) -{ - // empty -} - -int LedDeviceLpd8806::write(const std::vector &ledValues) -{ - const unsigned clearSize = ledValues.size()/32+1; - // Reconfigure if the current connfiguration does not match the required configuration - if (3*ledValues.size() + clearSize != _ledBuffer.size()) - { - // Initialise the buffer - _ledBuffer.resize(3*ledValues.size() + clearSize, 0x00); - - // Perform an initial reset to start accepting data on the first led - writeBytes(clearSize, _ledBuffer.data()); - } - - // Copy the colors from the ColorRgb vector to the Ldp8806 data vector - for (unsigned iLed=0; iLed> 1); - _ledBuffer[iLed*3+1] = 0x80 | (rgb.green >> 1); - _ledBuffer[iLed*3+2] = 0x80 | (rgb.blue >> 1); - } - - // Write the data - if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0) - { - return -1; - } - return 0; -} - -int LedDeviceLpd8806::switchOff() -{ - return write(std::vector(_ledBuffer.size(), ColorRgb{0,0,0})); -} +// STL includes +#include +#include +#include + +// Linux includes +#include +#include + +// hyperion local includes +#include "LedDeviceLpd8806.h" + +LedDeviceLpd8806::LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate) : + LedSpiDevice(outputDevice, baudrate), + _ledBuffer(0) +{ + // empty +} + +int LedDeviceLpd8806::write(const std::vector &ledValues) +{ + const unsigned clearSize = ledValues.size()/32+1; + // Reconfigure if the current connfiguration does not match the required configuration + if (3*ledValues.size() + clearSize != _ledBuffer.size()) + { + // Initialise the buffer + _ledBuffer.resize(3*ledValues.size() + clearSize, 0x00); + + // Perform an initial reset to start accepting data on the first led + writeBytes(clearSize, _ledBuffer.data()); + } + + // Copy the colors from the ColorRgb vector to the Ldp8806 data vector + for (unsigned iLed=0; iLed> 1); + _ledBuffer[iLed*3+1] = 0x80 | (rgb.green >> 1); + _ledBuffer[iLed*3+2] = 0x80 | (rgb.blue >> 1); + } + + // Write the data + if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0) + { + return -1; + } + return 0; +} + +int LedDeviceLpd8806::switchOff() +{ + return write(std::vector(_ledBuffer.size(), ColorRgb{0,0,0})); +} diff --git a/libsrc/leddevice/LedDeviceLpd8806.h b/libsrc/leddevice/LedDeviceLpd8806.h index bf85b177..8d4bed3a 100644 --- a/libsrc/leddevice/LedDeviceLpd8806.h +++ b/libsrc/leddevice/LedDeviceLpd8806.h @@ -1,103 +1,103 @@ -#pragma once - -// Local hyperion incluse -#include "LedSpiDevice.h" - -/// -/// Implementation of the LedDevice interface for writing to LPD8806 led device. -/// -/// The following description is copied from 'adafruit' (github.com/adafruit/LPD8806) -/// -/// Clearing up some misconceptions about how the LPD8806 drivers work: -/// -/// The LPD8806 is not a FIFO shift register. The first data out controls the -/// LED *closest* to the processor (unlike a typical shift register, where the -/// first data out winds up at the *furthest* LED). Each LED driver 'fills up' -/// with data and then passes through all subsequent bytes until a latch -/// condition takes place. This is actually pretty common among LED drivers. -/// -/// All color data bytes have the high bit (128) set, with the remaining -/// seven bits containing a brightness value (0-127). A byte with the high -/// bit clear has special meaning (explained later). -/// -/// The rest gets bizarre... -/// -/// The LPD8806 does not perform an in-unison latch (which would display the -/// newly-transmitted data all at once). Rather, each individual byte (even -/// the separate G, R, B components of each LED) is latched AS IT ARRIVES... -/// or more accurately, as the first bit of the subsequent byte arrives and -/// is passed through. So the strip actually refreshes at the speed the data -/// is issued, not instantaneously (this can be observed by greatly reducing -/// the data rate). This has implications for POV displays and light painting -/// applications. The 'subsequent' rule also means that at least one extra -/// byte must follow the last pixel, in order for the final blue LED to latch. -/// -/// To reset the pass-through behavior and begin sending new data to the start -/// of the strip, a number of zero bytes must be issued (remember, all color -/// data bytes have the high bit set, thus are in the range 128 to 255, so the -/// zero is 'special'). This should be done before each full payload of color -/// values to the strip. Curiously, zero bytes can only travel one meter (32 -/// LEDs) down the line before needing backup; the next meter requires an -/// extra zero byte, and so forth. Longer strips will require progressively -/// more zeros. *(see note below) -/// -/// In the interest of efficiency, it's possible to combine the former EOD -/// extra latch byte and the latter zero reset...the same data can do double -/// duty, latching the last blue LED while also resetting the strip for the -/// next payload. -/// -/// So: reset byte(s) of suitable length are issued once at startup to 'prime' -/// the strip to a known ready state. After each subsequent LED color payload, -/// these reset byte(s) are then issued at the END of each payload, both to -/// latch the last LED and to prep the strip for the start of the next payload -/// (even if that data does not arrive immediately). This avoids a tiny bit -/// of latency as the new color payload can begin issuing immediately on some -/// signal, such as a timer or GPIO trigger. -/// -/// Technically these zero byte(s) are not a latch, as the color data (save -/// for the last byte) is already latched. It's a start-of-data marker, or -/// an indicator to clear the thing-that's-not-a-shift-register. But for -/// conversational consistency with other LED drivers, we'll refer to it as -/// a 'latch' anyway. -/// -/// This has been validated independently with multiple customers' -/// hardware. Please do not report as a bug or issue pull requests for -/// this. Fewer zeros sometimes gives the *illusion* of working, the first -/// payload will correctly load and latch, but subsequent frames will drop -/// data at the end. The data shortfall won't always be visually apparent -/// depending on the color data loaded on the prior and subsequent frames. -/// Tested. Confirmed. Fact. -/// -/// -/// The summary of the story is that the following needs to be writen on the spi-device: -/// 1RRRRRRR 1GGGGGGG 1BBBBBBB 1RRRRRRR 1GGGGGGG ... ... 1GGGGGGG 1BBBBBBB 00000000 00000000 ... -/// |---------led_1----------| |---------led_2-- -led_n----------| |----clear data-- -/// -/// The number of zeroes in the 'clear data' is (#led/32 + 1)bytes (or *8 for bits) -/// -class LedDeviceLpd8806 : public LedSpiDevice -{ -public: - /// - /// Constructs the LedDevice for a string containing leds of the type LPD8806 - /// - /// @param[in] outputDevice The name of the output device (eg '/dev/spidev0.0') - /// @param[in] baudrate The used baudrate for writing to the output device - /// - LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate); - - /// - /// Writes the led color values to the led-device - /// - /// @param ledValues The color-value per led - /// @return Zero on succes else negative - /// - virtual int write(const std::vector &ledValues); - - /// Switch the leds off - virtual int switchOff(); - -private: - /// The buffer containing the packed RGB values - std::vector _ledBuffer; -}; +#pragma once + +// Local hyperion incluse +#include "LedSpiDevice.h" + +/// +/// Implementation of the LedDevice interface for writing to LPD8806 led device. +/// +/// The following description is copied from 'adafruit' (github.com/adafruit/LPD8806) +/// +/// Clearing up some misconceptions about how the LPD8806 drivers work: +/// +/// The LPD8806 is not a FIFO shift register. The first data out controls the +/// LED *closest* to the processor (unlike a typical shift register, where the +/// first data out winds up at the *furthest* LED). Each LED driver 'fills up' +/// with data and then passes through all subsequent bytes until a latch +/// condition takes place. This is actually pretty common among LED drivers. +/// +/// All color data bytes have the high bit (128) set, with the remaining +/// seven bits containing a brightness value (0-127). A byte with the high +/// bit clear has special meaning (explained later). +/// +/// The rest gets bizarre... +/// +/// The LPD8806 does not perform an in-unison latch (which would display the +/// newly-transmitted data all at once). Rather, each individual byte (even +/// the separate G, R, B components of each LED) is latched AS IT ARRIVES... +/// or more accurately, as the first bit of the subsequent byte arrives and +/// is passed through. So the strip actually refreshes at the speed the data +/// is issued, not instantaneously (this can be observed by greatly reducing +/// the data rate). This has implications for POV displays and light painting +/// applications. The 'subsequent' rule also means that at least one extra +/// byte must follow the last pixel, in order for the final blue LED to latch. +/// +/// To reset the pass-through behavior and begin sending new data to the start +/// of the strip, a number of zero bytes must be issued (remember, all color +/// data bytes have the high bit set, thus are in the range 128 to 255, so the +/// zero is 'special'). This should be done before each full payload of color +/// values to the strip. Curiously, zero bytes can only travel one meter (32 +/// LEDs) down the line before needing backup; the next meter requires an +/// extra zero byte, and so forth. Longer strips will require progressively +/// more zeros. *(see note below) +/// +/// In the interest of efficiency, it's possible to combine the former EOD +/// extra latch byte and the latter zero reset...the same data can do double +/// duty, latching the last blue LED while also resetting the strip for the +/// next payload. +/// +/// So: reset byte(s) of suitable length are issued once at startup to 'prime' +/// the strip to a known ready state. After each subsequent LED color payload, +/// these reset byte(s) are then issued at the END of each payload, both to +/// latch the last LED and to prep the strip for the start of the next payload +/// (even if that data does not arrive immediately). This avoids a tiny bit +/// of latency as the new color payload can begin issuing immediately on some +/// signal, such as a timer or GPIO trigger. +/// +/// Technically these zero byte(s) are not a latch, as the color data (save +/// for the last byte) is already latched. It's a start-of-data marker, or +/// an indicator to clear the thing-that's-not-a-shift-register. But for +/// conversational consistency with other LED drivers, we'll refer to it as +/// a 'latch' anyway. +/// +/// This has been validated independently with multiple customers' +/// hardware. Please do not report as a bug or issue pull requests for +/// this. Fewer zeros sometimes gives the *illusion* of working, the first +/// payload will correctly load and latch, but subsequent frames will drop +/// data at the end. The data shortfall won't always be visually apparent +/// depending on the color data loaded on the prior and subsequent frames. +/// Tested. Confirmed. Fact. +/// +/// +/// The summary of the story is that the following needs to be writen on the spi-device: +/// 1RRRRRRR 1GGGGGGG 1BBBBBBB 1RRRRRRR 1GGGGGGG ... ... 1GGGGGGG 1BBBBBBB 00000000 00000000 ... +/// |---------led_1----------| |---------led_2-- -led_n----------| |----clear data-- +/// +/// The number of zeroes in the 'clear data' is (#led/32 + 1)bytes (or *8 for bits) +/// +class LedDeviceLpd8806 : public LedSpiDevice +{ +public: + /// + /// Constructs the LedDevice for a string containing leds of the type LPD8806 + /// + /// @param[in] outputDevice The name of the output device (eg '/dev/spidev0.0') + /// @param[in] baudrate The used baudrate for writing to the output device + /// + LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate); + + /// + /// Writes the led color values to the led-device + /// + /// @param ledValues The color-value per led + /// @return Zero on succes else negative + /// + virtual int write(const std::vector &ledValues); + + /// Switch the leds off + virtual int switchOff(); + +private: + /// The buffer containing the packed RGB values + std::vector _ledBuffer; +}; diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index eec1c824..464820bb 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -1,342 +1,342 @@ -// Local-Hyperion includes -#include "LedDevicePhilipsHue.h" - -// jsoncpp includes -#include - -// qt includes -#include -#include -#include - -#include -#include - -bool operator ==(CiColor p1, CiColor p2) { - return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri); -} - -bool operator !=(CiColor p1, CiColor p2) { - return !(p1 == p2); -} - -PhilipsHueLight::PhilipsHueLight(unsigned int id, QString originalState, QString modelId) : - id(id), originalState(originalState) { - // Hue system model ids (http://www.developers.meethue.com/documentation/supported-lights). - // Light strips, color iris, ... - const std::set GAMUT_A_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012", - "LLC013", "LLC014", "LST001" }; - // Hue bulbs, spots, ... - const std::set GAMUT_B_MODEL_IDS = { "LCT001", "LCT002", "LCT003", "LCT007", "LLM001" }; - // Hue Lightstrip plus, go ... - const std::set GAMUT_C_MODEL_IDS = { "LLC020", "LST002" }; - // Find id in the sets and set the appropiate color space. - if (GAMUT_A_MODEL_IDS.find(modelId) != GAMUT_A_MODEL_IDS.end()) { - colorSpace.red = {0.703f, 0.296f}; - colorSpace.green = {0.2151f, 0.7106f}; - colorSpace.blue = {0.138f, 0.08f}; - } else if (GAMUT_B_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { - colorSpace.red = {0.675f, 0.322f}; - colorSpace.green = {0.4091f, 0.518f}; - colorSpace.blue = {0.167f, 0.04f}; - } else if (GAMUT_C_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { - colorSpace.red = {0.675f, 0.322f}; - colorSpace.green = {0.2151f, 0.7106f}; - colorSpace.blue = {0.167f, 0.04f}; - } else { - colorSpace.red = {1.0f, 0.0f}; - colorSpace.green = {0.0f, 1.0f}; - colorSpace.blue = {0.0f, 0.0f}; - } - // Initialize black color. - black = rgbToCiColor(0.0f, 0.0f, 0.0f); - // Initialize color with black - color = {black.x, black.y, black.bri}; -} - -float PhilipsHueLight::crossProduct(CiColor p1, CiColor p2) { - return p1.x * p2.y - p1.y * p2.x; -} - -bool PhilipsHueLight::isPointInLampsReach(CiColor p) { - CiColor v1 = { colorSpace.green.x - colorSpace.red.x, colorSpace.green.y - colorSpace.red.y }; - CiColor v2 = { colorSpace.blue.x - colorSpace.red.x, colorSpace.blue.y - colorSpace.red.y }; - CiColor q = { p.x - colorSpace.red.x, p.y - colorSpace.red.y }; - float s = crossProduct(q, v2) / crossProduct(v1, v2); - float t = crossProduct(v1, q) / crossProduct(v1, v2); - if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) { - return true; - } - return false; -} - -CiColor PhilipsHueLight::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) { - CiColor AP = { p.x - a.x, p.y - a.y }; - CiColor AB = { b.x - a.x, b.y - a.y }; - float ab2 = AB.x * AB.x + AB.y * AB.y; - float ap_ab = AP.x * AB.x + AP.y * AB.y; - float t = ap_ab / ab2; - if (t < 0.0f) { - t = 0.0f; - } else if (t > 1.0f) { - t = 1.0f; - } - return {a.x + AB.x * t, a.y + AB.y * t}; -} - -float PhilipsHueLight::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) { - // Horizontal difference. - float dx = p1.x - p2.x; - // Vertical difference. - float dy = p1.y - p2.y; - // Absolute value. - return sqrt(dx * dx + dy * dy); -} - -CiColor PhilipsHueLight::rgbToCiColor(float red, float green, float blue) { - // Apply gamma correction. - float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); - float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); - float b = (blue > 0.04045f) ? powf((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f); - // Convert to XYZ space. - float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; - float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; - float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f; - // Convert to x,y space. - float cx = X / (X + Y + Z); - float cy = Y / (X + Y + Z); - if (isnan(cx)) { - cx = 0.0f; - } - if (isnan(cy)) { - cy = 0.0f; - } - // Brightness is simply Y in the XYZ space. - CiColor xy = { cx, cy, Y }; - // Check if the given XY value is within the color reach of our lamps. - if (!isPointInLampsReach(xy)) { - // It seems the color is out of reach let's find the closes color we can produce with our lamp and send this XY value out. - CiColor pAB = getClosestPointToPoint(colorSpace.red, colorSpace.green, xy); - CiColor pAC = getClosestPointToPoint(colorSpace.blue, colorSpace.red, xy); - CiColor pBC = getClosestPointToPoint(colorSpace.green, colorSpace.blue, xy); - // Get the distances per point and see which point is closer to our Point. - float dAB = getDistanceBetweenTwoPoints(xy, pAB); - float dAC = getDistanceBetweenTwoPoints(xy, pAC); - float dBC = getDistanceBetweenTwoPoints(xy, pBC); - float lowest = dAB; - CiColor closestPoint = pAB; - if (dAC < lowest) { - lowest = dAC; - closestPoint = pAC; - } - if (dBC < lowest) { - lowest = dBC; - closestPoint = pBC; - } - // Change the xy value to a value which is within the reach of the lamp. - xy.x = closestPoint.x; - xy.y = closestPoint.y; - } - return xy; -} - -LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::string& username, bool switchOffOnBlack, - int transitiontime, std::vector lightIds) : - host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime( - transitiontime), lightIds(lightIds) { - manager = new QNetworkAccessManager(); - timer.setInterval(3000); - timer.setSingleShot(true); - connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates())); -} - -LedDevicePhilipsHue::~LedDevicePhilipsHue() { - delete manager; -} - -int LedDevicePhilipsHue::write(const std::vector & ledValues) { - // Save light states if not done before. - if (!areStatesSaved()) { - saveStates((unsigned int) ledValues.size()); - switchOn((unsigned int) ledValues.size()); - } - // If there are less states saved than colors given, then maybe something went wrong before. - if (lights.size() != ledValues.size()) { - restoreStates(); - return 0; - } - // Iterate through colors and set light states. - unsigned int idx = 0; - for (const ColorRgb& color : ledValues) { - // Get lamp. - PhilipsHueLight& lamp = lights.at(idx); - // Scale colors from [0, 255] to [0, 1] and convert to xy space. - CiColor xy = lamp.rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f); - // Write color if color has been changed. - if (xy != lamp.color) { - // Switch on if the lamp has been previously switched off. - if (switchOffOnBlack && lamp.color == lamp.black) { - put(getStateRoute(lamp.id), QString("{\"on\": true}")); - } - // Send adjust color and brightness command in JSON format. - // We have to set the transition time each time. - put(getStateRoute(lamp.id), - QString("{\"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg(xy.y).arg( - qRound(xy.bri * 255.0f)).arg(transitiontime)); - - } - // Switch lamp off if switchOffOnBlack is enabled and the lamp is currently on. - if (switchOffOnBlack) { - // From black to a color. - if (lamp.color == lamp.black && xy != lamp.black) { - put(getStateRoute(lamp.id), QString("{\"on\": true}")); - } - // From a color to black. - else if (lamp.color != lamp.black && xy == lamp.black) { - put(getStateRoute(lamp.id), QString("{\"on\": false}")); - } - } - // Remember last color. - lamp.color = xy; - // Next light id. - idx++; - } - timer.start(); - return 0; -} - -int LedDevicePhilipsHue::switchOff() { - timer.stop(); - // If light states have been saved before, ... - if (areStatesSaved()) { - // ... restore them. - restoreStates(); - } - return 0; -} - -void LedDevicePhilipsHue::put(QString route, QString content) { - QString url = getUrl(route); - // Perfrom request - QNetworkRequest request(url); - 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())); - // Go into the loop until the request is finished. - loop.exec(); - // Free space. - reply->deleteLater(); -} - -QByteArray LedDevicePhilipsHue::get(QString route) { - QString url = getUrl(route); - // Perfrom request - 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. - QByteArray response = reply->readAll(); - // Free space. - reply->deleteLater(); - // Return response - return response; -} - -QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) { - return QString("lights/%1/state").arg(lightId); -} - -QString LedDevicePhilipsHue::getRoute(unsigned int lightId) { - return QString("lights/%1").arg(lightId); -} - -QString LedDevicePhilipsHue::getUrl(QString route) { - return QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route); -} - -void LedDevicePhilipsHue::saveStates(unsigned int nLights) { - // Clear saved lamps. - lights.clear(); - // Use json parser to parse reponse. - Json::Reader reader; - Json::FastWriter writer; - // Read light ids if none have been supplied by the user. - if (lightIds.size() != nLights) { - lightIds.clear(); - // - QByteArray response = get("lights"); - Json::Value json; - if (!reader.parse(QString(response).toStdString(), json)) { - throw std::runtime_error(("No lights found at " + getUrl("lights")).toStdString()); - } - // Loop over all children. - for (Json::ValueIterator it = json.begin(); it != json.end() && lightIds.size() < nLights; it++) { - int lightId = atoi(it.key().asCString()); - lightIds.push_back(lightId); - std::cout << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): found light with id " << lightId - << "." << std::endl; - } - // Check if we found enough lights. - if (lightIds.size() != nLights) { - throw std::runtime_error(("Not enough lights found at " + getUrl("lights")).toStdString()); - } - } - // Iterate lights. - for (unsigned int i = 0; i < nLights; i++) { - // Read the response. - QByteArray response = get(getRoute(lightIds.at(i))); - // Parse JSON. - Json::Value json; - if (!reader.parse(QString(response).toStdString(), json)) { - // Error occured, break loop. - std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got invalid response from light " - << getUrl(getRoute(lightIds.at(i))).toStdString() << "." << std::endl; - break; - } - // Get state object values which are subject to change. - Json::Value state(Json::objectValue); - if (!json.isMember("state")) { - std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no state for light from " - << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; - break; - } - if (!json["state"].isMember("on")) { - std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no valid state from light " - << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; - break; - } - state["on"] = json["state"]["on"]; - if (json["state"]["on"] == true) { - state["xy"] = json["state"]["xy"]; - state["bri"] = json["state"]["bri"]; - } - // Determine the model id. - QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", ""); - QString originalState = QString(writer.write(state).c_str()).trimmed(); - // Save state object. - lights.push_back(PhilipsHueLight(lightIds.at(i), originalState, modelId)); - } -} - -void LedDevicePhilipsHue::switchOn(unsigned int nLights) { - for (PhilipsHueLight light : lights) { - put(getStateRoute(light.id), "{\"on\": true}"); - } -} - -void LedDevicePhilipsHue::restoreStates() { - for (PhilipsHueLight light : lights) { - put(getStateRoute(light.id), light.originalState); - } - // Clear saved light states. - lights.clear(); -} - -bool LedDevicePhilipsHue::areStatesSaved() { - return !lights.empty(); -} +// Local-Hyperion includes +#include "LedDevicePhilipsHue.h" + +// jsoncpp includes +#include + +// qt includes +#include +#include +#include + +#include +#include + +bool operator ==(CiColor p1, CiColor p2) { + return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri); +} + +bool operator !=(CiColor p1, CiColor p2) { + return !(p1 == p2); +} + +PhilipsHueLight::PhilipsHueLight(unsigned int id, QString originalState, QString modelId) : + id(id), originalState(originalState) { + // Hue system model ids (http://www.developers.meethue.com/documentation/supported-lights). + // Light strips, color iris, ... + const std::set GAMUT_A_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012", + "LLC013", "LLC014", "LST001" }; + // Hue bulbs, spots, ... + const std::set GAMUT_B_MODEL_IDS = { "LCT001", "LCT002", "LCT003", "LCT007", "LLM001" }; + // Hue Lightstrip plus, go ... + const std::set GAMUT_C_MODEL_IDS = { "LLC020", "LST002" }; + // Find id in the sets and set the appropiate color space. + if (GAMUT_A_MODEL_IDS.find(modelId) != GAMUT_A_MODEL_IDS.end()) { + colorSpace.red = {0.703f, 0.296f}; + colorSpace.green = {0.2151f, 0.7106f}; + colorSpace.blue = {0.138f, 0.08f}; + } else if (GAMUT_B_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { + colorSpace.red = {0.675f, 0.322f}; + colorSpace.green = {0.4091f, 0.518f}; + colorSpace.blue = {0.167f, 0.04f}; + } else if (GAMUT_C_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { + colorSpace.red = {0.675f, 0.322f}; + colorSpace.green = {0.2151f, 0.7106f}; + colorSpace.blue = {0.167f, 0.04f}; + } else { + colorSpace.red = {1.0f, 0.0f}; + colorSpace.green = {0.0f, 1.0f}; + colorSpace.blue = {0.0f, 0.0f}; + } + // Initialize black color. + black = rgbToCiColor(0.0f, 0.0f, 0.0f); + // Initialize color with black + color = {black.x, black.y, black.bri}; +} + +float PhilipsHueLight::crossProduct(CiColor p1, CiColor p2) { + return p1.x * p2.y - p1.y * p2.x; +} + +bool PhilipsHueLight::isPointInLampsReach(CiColor p) { + CiColor v1 = { colorSpace.green.x - colorSpace.red.x, colorSpace.green.y - colorSpace.red.y }; + CiColor v2 = { colorSpace.blue.x - colorSpace.red.x, colorSpace.blue.y - colorSpace.red.y }; + CiColor q = { p.x - colorSpace.red.x, p.y - colorSpace.red.y }; + float s = crossProduct(q, v2) / crossProduct(v1, v2); + float t = crossProduct(v1, q) / crossProduct(v1, v2); + if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) { + return true; + } + return false; +} + +CiColor PhilipsHueLight::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) { + CiColor AP = { p.x - a.x, p.y - a.y }; + CiColor AB = { b.x - a.x, b.y - a.y }; + float ab2 = AB.x * AB.x + AB.y * AB.y; + float ap_ab = AP.x * AB.x + AP.y * AB.y; + float t = ap_ab / ab2; + if (t < 0.0f) { + t = 0.0f; + } else if (t > 1.0f) { + t = 1.0f; + } + return {a.x + AB.x * t, a.y + AB.y * t}; +} + +float PhilipsHueLight::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) { + // Horizontal difference. + float dx = p1.x - p2.x; + // Vertical difference. + float dy = p1.y - p2.y; + // Absolute value. + return sqrt(dx * dx + dy * dy); +} + +CiColor PhilipsHueLight::rgbToCiColor(float red, float green, float blue) { + // Apply gamma correction. + float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); + float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); + float b = (blue > 0.04045f) ? powf((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f); + // Convert to XYZ space. + float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; + float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; + float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f; + // Convert to x,y space. + float cx = X / (X + Y + Z); + float cy = Y / (X + Y + Z); + if (isnan(cx)) { + cx = 0.0f; + } + if (isnan(cy)) { + cy = 0.0f; + } + // Brightness is simply Y in the XYZ space. + CiColor xy = { cx, cy, Y }; + // Check if the given XY value is within the color reach of our lamps. + if (!isPointInLampsReach(xy)) { + // It seems the color is out of reach let's find the closes color we can produce with our lamp and send this XY value out. + CiColor pAB = getClosestPointToPoint(colorSpace.red, colorSpace.green, xy); + CiColor pAC = getClosestPointToPoint(colorSpace.blue, colorSpace.red, xy); + CiColor pBC = getClosestPointToPoint(colorSpace.green, colorSpace.blue, xy); + // Get the distances per point and see which point is closer to our Point. + float dAB = getDistanceBetweenTwoPoints(xy, pAB); + float dAC = getDistanceBetweenTwoPoints(xy, pAC); + float dBC = getDistanceBetweenTwoPoints(xy, pBC); + float lowest = dAB; + CiColor closestPoint = pAB; + if (dAC < lowest) { + lowest = dAC; + closestPoint = pAC; + } + if (dBC < lowest) { + lowest = dBC; + closestPoint = pBC; + } + // Change the xy value to a value which is within the reach of the lamp. + xy.x = closestPoint.x; + xy.y = closestPoint.y; + } + return xy; +} + +LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::string& username, bool switchOffOnBlack, + int transitiontime, std::vector lightIds) : + host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime( + transitiontime), lightIds(lightIds) { + manager = new QNetworkAccessManager(); + timer.setInterval(3000); + timer.setSingleShot(true); + connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates())); +} + +LedDevicePhilipsHue::~LedDevicePhilipsHue() { + delete manager; +} + +int LedDevicePhilipsHue::write(const std::vector & ledValues) { + // Save light states if not done before. + if (!areStatesSaved()) { + saveStates((unsigned int) ledValues.size()); + switchOn((unsigned int) ledValues.size()); + } + // If there are less states saved than colors given, then maybe something went wrong before. + if (lights.size() != ledValues.size()) { + restoreStates(); + return 0; + } + // Iterate through colors and set light states. + unsigned int idx = 0; + for (const ColorRgb& color : ledValues) { + // Get lamp. + PhilipsHueLight& lamp = lights.at(idx); + // Scale colors from [0, 255] to [0, 1] and convert to xy space. + CiColor xy = lamp.rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f); + // Write color if color has been changed. + if (xy != lamp.color) { + // Switch on if the lamp has been previously switched off. + if (switchOffOnBlack && lamp.color == lamp.black) { + put(getStateRoute(lamp.id), QString("{\"on\": true}")); + } + // Send adjust color and brightness command in JSON format. + // We have to set the transition time each time. + put(getStateRoute(lamp.id), + QString("{\"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg(xy.y).arg( + qRound(xy.bri * 255.0f)).arg(transitiontime)); + + } + // Switch lamp off if switchOffOnBlack is enabled and the lamp is currently on. + if (switchOffOnBlack) { + // From black to a color. + if (lamp.color == lamp.black && xy != lamp.black) { + put(getStateRoute(lamp.id), QString("{\"on\": true}")); + } + // From a color to black. + else if (lamp.color != lamp.black && xy == lamp.black) { + put(getStateRoute(lamp.id), QString("{\"on\": false}")); + } + } + // Remember last color. + lamp.color = xy; + // Next light id. + idx++; + } + timer.start(); + return 0; +} + +int LedDevicePhilipsHue::switchOff() { + timer.stop(); + // If light states have been saved before, ... + if (areStatesSaved()) { + // ... restore them. + restoreStates(); + } + return 0; +} + +void LedDevicePhilipsHue::put(QString route, QString content) { + QString url = getUrl(route); + // Perfrom request + QNetworkRequest request(url); + 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())); + // Go into the loop until the request is finished. + loop.exec(); + // Free space. + reply->deleteLater(); +} + +QByteArray LedDevicePhilipsHue::get(QString route) { + QString url = getUrl(route); + // Perfrom request + 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. + QByteArray response = reply->readAll(); + // Free space. + reply->deleteLater(); + // Return response + return response; +} + +QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) { + return QString("lights/%1/state").arg(lightId); +} + +QString LedDevicePhilipsHue::getRoute(unsigned int lightId) { + return QString("lights/%1").arg(lightId); +} + +QString LedDevicePhilipsHue::getUrl(QString route) { + return QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route); +} + +void LedDevicePhilipsHue::saveStates(unsigned int nLights) { + // Clear saved lamps. + lights.clear(); + // Use json parser to parse reponse. + Json::Reader reader; + Json::FastWriter writer; + // Read light ids if none have been supplied by the user. + if (lightIds.size() != nLights) { + lightIds.clear(); + // + QByteArray response = get("lights"); + Json::Value json; + if (!reader.parse(QString(response).toStdString(), json)) { + throw std::runtime_error(("No lights found at " + getUrl("lights")).toStdString()); + } + // Loop over all children. + for (Json::ValueIterator it = json.begin(); it != json.end() && lightIds.size() < nLights; it++) { + int lightId = atoi(it.key().asCString()); + lightIds.push_back(lightId); + std::cout << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): found light with id " << lightId + << "." << std::endl; + } + // Check if we found enough lights. + if (lightIds.size() != nLights) { + throw std::runtime_error(("Not enough lights found at " + getUrl("lights")).toStdString()); + } + } + // Iterate lights. + for (unsigned int i = 0; i < nLights; i++) { + // Read the response. + QByteArray response = get(getRoute(lightIds.at(i))); + // Parse JSON. + Json::Value json; + if (!reader.parse(QString(response).toStdString(), json)) { + // Error occured, break loop. + std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got invalid response from light " + << getUrl(getRoute(lightIds.at(i))).toStdString() << "." << std::endl; + break; + } + // Get state object values which are subject to change. + Json::Value state(Json::objectValue); + if (!json.isMember("state")) { + std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no state for light from " + << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; + break; + } + if (!json["state"].isMember("on")) { + std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no valid state from light " + << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; + break; + } + state["on"] = json["state"]["on"]; + if (json["state"]["on"] == true) { + state["xy"] = json["state"]["xy"]; + state["bri"] = json["state"]["bri"]; + } + // Determine the model id. + QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", ""); + QString originalState = QString(writer.write(state).c_str()).trimmed(); + // Save state object. + lights.push_back(PhilipsHueLight(lightIds.at(i), originalState, modelId)); + } +} + +void LedDevicePhilipsHue::switchOn(unsigned int nLights) { + for (PhilipsHueLight light : lights) { + put(getStateRoute(light.id), "{\"on\": true}"); + } +} + +void LedDevicePhilipsHue::restoreStates() { + for (PhilipsHueLight light : lights) { + put(getStateRoute(light.id), light.originalState); + } + // Clear saved light states. + lights.clear(); +} + +bool LedDevicePhilipsHue::areStatesSaved() { + return !lights.empty(); +} diff --git a/libsrc/leddevice/LedDevicePhilipsHue.h b/libsrc/leddevice/LedDevicePhilipsHue.h index 5e5409b6..9f48a661 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/LedDevicePhilipsHue.h @@ -1,236 +1,236 @@ -#pragma once - -// STL includes -#include - -// Qt includes -#include -#include -#include -#include -// Leddevice includes -#include - -/** - * A color point in the color space of the hue system. - */ -struct CiColor { - /// X component. - float x; - /// Y component. - float y; - /// The brightness. - float bri; -}; - -bool operator==(CiColor p1, CiColor p2); -bool operator!=(CiColor p1, CiColor p2); - -/** - * Color triangle to define an available color space for the hue lamps. - */ -struct CiColorTriangle { - CiColor red, green, blue; -}; - -/** - * Simple class to hold the id, the latest color, the color space and the original state. - */ -class PhilipsHueLight { -public: - unsigned int id; - CiColor black; - CiColor color; - CiColorTriangle colorSpace; - QString originalState; - - /// - /// Constructs the light. - /// - /// @param id the light id - /// - /// @param originalState the json string of the original state - /// - /// @param modelId the model id of the hue lamp which is used to determine the color space - /// - PhilipsHueLight(unsigned int id, QString originalState, QString modelId); - - /// - /// Converts an RGB color to the Hue xy color space and brightness. - /// https://github.com/PhilipsHue/PhilipsHueSDK-iOS-OSX/blob/master/ApplicationDesignNotes/RGB%20to%20xy%20Color%20conversion.md - /// - /// @param red the red component in [0, 1] - /// - /// @param green the green component in [0, 1] - /// - /// @param blue the blue component in [0, 1] - /// - /// @return color point - /// - CiColor rgbToCiColor(float red, float green, float blue); - - /// - /// @param p the color point to check - /// - /// @return true if the color point is covered by the lamp color space - /// - bool isPointInLampsReach(CiColor p); - - /// - /// @param p1 point one - /// - /// @param p2 point tow - /// - /// @return the cross product between p1 and p2 - /// - float crossProduct(CiColor p1, CiColor p2); - - /// - /// @param a reference point one - /// - /// @param b reference point two - /// - /// @param p the point to which the closest point is to be found - /// - /// @return the closest color point of p to a and b - /// - CiColor getClosestPointToPoint(CiColor a, CiColor b, CiColor p); - - /// - /// @param p1 point one - /// - /// @param p2 point tow - /// - /// @return the distance between the two points - /// - float getDistanceBetweenTwoPoints(CiColor p1, CiColor p2); -}; - -/** - * Implementation for the Philips Hue system. - * - * To use set the device to "philipshue". - * Uses the official Philips Hue API (http://developers.meethue.com). - * Framegrabber must be limited to 10 Hz / numer of lights to avoid rate limitation by the hue bridge. - * Create a new API user name "newdeveloper" on the bridge (http://developers.meethue.com/gettingstarted.html) - * - * @author ntim (github), bimsarck (github) - */ -class LedDevicePhilipsHue: public QObject, public LedDevice { -Q_OBJECT -public: - /// - /// Constructs the device. - /// - /// @param output the ip address of the bridge - /// - /// @param username username of the hue bridge (default: newdeveloper) - /// - /// @param switchOffOnBlack kill lights for black (default: false) - /// - /// @param transitiontime the time duration a light change takes in multiples of 100 ms (default: 400 ms). - /// - /// @param lightIds light ids of the lights to control if not starting at one in ascending order. - /// - LedDevicePhilipsHue(const std::string& output, const std::string& username = "newdeveloper", bool switchOffOnBlack = - false, int transitiontime = 1, std::vector lightIds = std::vector()); - - /// - /// Destructor of this device - /// - virtual ~LedDevicePhilipsHue(); - - /// - /// Sends the given led-color values via put request to the hue system - /// - /// @param ledValues The color-value per led - /// - /// @return Zero on success else negative - /// - virtual int write(const std::vector & ledValues); - - /// Restores the original state of the leds. - virtual int switchOff(); - -private slots: - /// Restores the status of all lights. - void restoreStates(); - -private: - /// Array to save the lamps. - std::vector lights; - /// Ip address of the bridge - QString host; - /// User name for the API ("newdeveloper") - QString username; - /// QNetworkAccessManager object for sending requests. +#pragma once + +// STL includes +#include + +// Qt includes +#include +#include +#include +#include +// Leddevice includes +#include + +/** + * A color point in the color space of the hue system. + */ +struct CiColor { + /// X component. + float x; + /// Y component. + float y; + /// The brightness. + float bri; +}; + +bool operator==(CiColor p1, CiColor p2); +bool operator!=(CiColor p1, CiColor p2); + +/** + * Color triangle to define an available color space for the hue lamps. + */ +struct CiColorTriangle { + CiColor red, green, blue; +}; + +/** + * Simple class to hold the id, the latest color, the color space and the original state. + */ +class PhilipsHueLight { +public: + unsigned int id; + CiColor black; + CiColor color; + CiColorTriangle colorSpace; + QString originalState; + + /// + /// Constructs the light. + /// + /// @param id the light id + /// + /// @param originalState the json string of the original state + /// + /// @param modelId the model id of the hue lamp which is used to determine the color space + /// + PhilipsHueLight(unsigned int id, QString originalState, QString modelId); + + /// + /// Converts an RGB color to the Hue xy color space and brightness. + /// https://github.com/PhilipsHue/PhilipsHueSDK-iOS-OSX/blob/master/ApplicationDesignNotes/RGB%20to%20xy%20Color%20conversion.md + /// + /// @param red the red component in [0, 1] + /// + /// @param green the green component in [0, 1] + /// + /// @param blue the blue component in [0, 1] + /// + /// @return color point + /// + CiColor rgbToCiColor(float red, float green, float blue); + + /// + /// @param p the color point to check + /// + /// @return true if the color point is covered by the lamp color space + /// + bool isPointInLampsReach(CiColor p); + + /// + /// @param p1 point one + /// + /// @param p2 point tow + /// + /// @return the cross product between p1 and p2 + /// + float crossProduct(CiColor p1, CiColor p2); + + /// + /// @param a reference point one + /// + /// @param b reference point two + /// + /// @param p the point to which the closest point is to be found + /// + /// @return the closest color point of p to a and b + /// + CiColor getClosestPointToPoint(CiColor a, CiColor b, CiColor p); + + /// + /// @param p1 point one + /// + /// @param p2 point tow + /// + /// @return the distance between the two points + /// + float getDistanceBetweenTwoPoints(CiColor p1, CiColor p2); +}; + +/** + * Implementation for the Philips Hue system. + * + * To use set the device to "philipshue". + * Uses the official Philips Hue API (http://developers.meethue.com). + * Framegrabber must be limited to 10 Hz / numer of lights to avoid rate limitation by the hue bridge. + * Create a new API user name "newdeveloper" on the bridge (http://developers.meethue.com/gettingstarted.html) + * + * @author ntim (github), bimsarck (github) + */ +class LedDevicePhilipsHue: public QObject, public LedDevice { +Q_OBJECT +public: + /// + /// Constructs the device. + /// + /// @param output the ip address of the bridge + /// + /// @param username username of the hue bridge (default: newdeveloper) + /// + /// @param switchOffOnBlack kill lights for black (default: false) + /// + /// @param transitiontime the time duration a light change takes in multiples of 100 ms (default: 400 ms). + /// + /// @param lightIds light ids of the lights to control if not starting at one in ascending order. + /// + LedDevicePhilipsHue(const std::string& output, const std::string& username = "newdeveloper", bool switchOffOnBlack = + false, int transitiontime = 1, std::vector lightIds = std::vector()); + + /// + /// Destructor of this device + /// + virtual ~LedDevicePhilipsHue(); + + /// + /// Sends the given led-color values via put request to the hue system + /// + /// @param ledValues The color-value per led + /// + /// @return Zero on success else negative + /// + virtual int write(const std::vector & ledValues); + + /// Restores the original state of the leds. + virtual int switchOff(); + +private slots: + /// Restores the status of all lights. + void restoreStates(); + +private: + /// Array to save the lamps. + std::vector lights; + /// Ip address of the bridge + QString host; + /// User name for the API ("newdeveloper") + QString username; + /// QNetworkAccessManager object for sending requests. QNetworkAccessManager* manager; - /// Use timer to reset lights when we got into "GRABBINGMODE_OFF". - QTimer timer; - /// - bool switchOffOnBlack; - /// Transition time in multiples of 100 ms. - /// The default of the Hue lights will be 400 ms, but we want to have it snapier - int transitiontime; - /// Array of the light ids. - std::vector lightIds; - - /// - /// Sends a HTTP GET request (blocking). - /// - /// @param route the URI of the request - /// - /// @return response of the request - /// - QByteArray get(QString route); - - /// - /// Sends a HTTP PUT request (non-blocking). - /// - /// @param route the URI of the request - /// - /// @param content content of the request - /// - void put(QString route, QString content); - - /// - /// @param lightId the id of the hue light (starting from 1) - /// - /// @return the URI of the light state for PUT requests. - /// - QString getStateRoute(unsigned int lightId); - - /// - /// @param lightId the id of the hue light (starting from 1) - /// - /// @return the URI of the light for GET requests. - /// - QString getRoute(unsigned int lightId); - - /// - /// @param route - /// - /// @return the full URL of the request. - /// - QString getUrl(QString route); - - /// - /// Queries the status of all lights and saves it. - /// - /// @param nLights the number of lights - /// - void saveStates(unsigned int nLights); - - /// - /// Switches the leds on. - /// - /// @param nLights the number of lights - /// - void switchOn(unsigned int nLights); - - /// - /// @return true if light states have been saved. - /// - bool areStatesSaved(); - -}; + /// Use timer to reset lights when we got into "GRABBINGMODE_OFF". + QTimer timer; + /// + bool switchOffOnBlack; + /// Transition time in multiples of 100 ms. + /// The default of the Hue lights will be 400 ms, but we want to have it snapier + int transitiontime; + /// Array of the light ids. + std::vector lightIds; + + /// + /// Sends a HTTP GET request (blocking). + /// + /// @param route the URI of the request + /// + /// @return response of the request + /// + QByteArray get(QString route); + + /// + /// Sends a HTTP PUT request (non-blocking). + /// + /// @param route the URI of the request + /// + /// @param content content of the request + /// + void put(QString route, QString content); + + /// + /// @param lightId the id of the hue light (starting from 1) + /// + /// @return the URI of the light state for PUT requests. + /// + QString getStateRoute(unsigned int lightId); + + /// + /// @param lightId the id of the hue light (starting from 1) + /// + /// @return the URI of the light for GET requests. + /// + QString getRoute(unsigned int lightId); + + /// + /// @param route + /// + /// @return the full URL of the request. + /// + QString getUrl(QString route); + + /// + /// Queries the status of all lights and saves it. + /// + /// @param nLights the number of lights + /// + void saveStates(unsigned int nLights); + + /// + /// Switches the leds on. + /// + /// @param nLights the number of lights + /// + void switchOn(unsigned int nLights); + + /// + /// @return true if light states have been saved. + /// + bool areStatesSaved(); + +}; diff --git a/libsrc/leddevice/LedDeviceTpm2.cpp b/libsrc/leddevice/LedDeviceTpm2.cpp index c865ef96..c6054038 100644 --- a/libsrc/leddevice/LedDeviceTpm2.cpp +++ b/libsrc/leddevice/LedDeviceTpm2.cpp @@ -16,18 +16,18 @@ LedDeviceTpm2::LedDeviceTpm2(const std::string& outputDevice, const unsigned bau int LedDeviceTpm2::write(const std::vector &ledValues) { - if (_ledBuffer.size() == 0) - { - _ledBuffer.resize(5 + 3*ledValues.size()); - _ledBuffer[0] = 0xC9; // block-start byte - _ledBuffer[1] = 0xDA; // DATA frame - _ledBuffer[2] = ((3 * ledValues.size()) >> 8) & 0xFF; // frame size high byte - _ledBuffer[3] = (3 * ledValues.size()) & 0xFF; // frame size low byte - _ledBuffer.back() = 0x36; // block-end byte - } + if (_ledBuffer.size() == 0) + { + _ledBuffer.resize(5 + 3*ledValues.size()); + _ledBuffer[0] = 0xC9; // block-start byte + _ledBuffer[1] = 0xDA; // DATA frame + _ledBuffer[2] = ((3 * ledValues.size()) >> 8) & 0xFF; // frame size high byte + _ledBuffer[3] = (3 * ledValues.size()) & 0xFF; // frame size low byte + _ledBuffer.back() = 0x36; // block-end byte + } - // write data - memcpy(4 + _ledBuffer.data(), ledValues.data(), ledValues.size() * 3); + // write data + memcpy(4 + _ledBuffer.data(), ledValues.data(), ledValues.size() * 3); return writeBytes(_ledBuffer.size(), _ledBuffer.data()); } diff --git a/libsrc/leddevice/LedDeviceUdp.cpp b/libsrc/leddevice/LedDeviceUdp.cpp index 48c2a8d7..71078ed0 100644 --- a/libsrc/leddevice/LedDeviceUdp.cpp +++ b/libsrc/leddevice/LedDeviceUdp.cpp @@ -25,55 +25,54 @@ LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate, c //LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate) : // _ofs(output.empty()?"/home/pi/LedDevice.out":output.c_str()) { - - std::string hostname; - std::string port; - ledprotocol = protocol; - leds_per_pkt = ((maxPacket-4)/3); - if (leds_per_pkt <= 0) { - leds_per_pkt = 200; - } + std::string hostname; + std::string port; + ledprotocol = protocol; + leds_per_pkt = ((maxPacket-4)/3); + if (leds_per_pkt <= 0) { + leds_per_pkt = 200; + } //printf ("leds_per_pkt is %d\n", leds_per_pkt); - int got_colon=0; - for (unsigned int i=0; iai_next) { - if ((sockfd = socket(p->ai_family, p->ai_socktype, - p->ai_protocol)) == -1) { - perror("talker: socket"); - continue; - } + // loop through all the results and make a socket + for(p = servinfo; p != NULL; p = p->ai_next) { + if ((sockfd = socket(p->ai_family, p->ai_socktype, + p->ai_protocol)) == -1) { + perror("talker: socket"); + continue; + } - break; - } + break; + } - if (p == NULL) { - fprintf(stderr, "talker: failed to create socket\n"); - assert(p!=NULL); - } + if (p == NULL) { + fprintf(stderr, "talker: failed to create socket\n"); + assert(p!=NULL); + } } LedDeviceUdp::~LedDeviceUdp() @@ -99,7 +98,7 @@ int LedDeviceUdp::write(const std::vector & ledValues) udpbuffer[i++] = color.green; udpbuffer[i++] = color.blue; } - //printf ("c.red %d sz c.red %d\n", color.red, sizeof(color.red)); + //printf ("c.red %d sz c.red %d\n", color.red, sizeof(color.red)); } sendto(sockfd, udpbuffer, i, 0, p->ai_addr, p->ai_addrlen); } @@ -153,7 +152,6 @@ int LedDeviceUdp::write(const std::vector & ledValues) udpbuffer[udpPtr++] = ledCtr%256; // low byte } } - } if (ledprotocol == 3) { @@ -172,7 +170,6 @@ int LedDeviceUdp::write(const std::vector & ledValues) udpbuffer[udpPtr++] = fragment_number++; udpbuffer[udpPtr++] = fragments; - for (const ColorRgb& color : ledValues) { if (udpPtr<4090) { @@ -201,6 +198,6 @@ int LedDeviceUdp::write(const std::vector & ledValues) int LedDeviceUdp::switchOff() { -// return write(std::vector(mLedCount, ColorRgb{0,0,0})); +// return write(std::vector(mLedCount, ColorRgb{0,0,0})); return 0; } diff --git a/libsrc/leddevice/LedDeviceWS2812b.h b/libsrc/leddevice/LedDeviceWS2812b.h index d945e20d..1e19cf73 100644 --- a/libsrc/leddevice/LedDeviceWS2812b.h +++ b/libsrc/leddevice/LedDeviceWS2812b.h @@ -86,17 +86,17 @@ // Raspberry Pi low-level peripherals: // http://elinux.org/RPi_Low-level_peripherals // -// Richard Hirst's nice, clean code: -// https://github.com/richardghirst/PiBits/blob/master/PiFmDma/PiFmDma.c +// Richard Hirst's nice, clean code: +// https://github.com/richardghirst/PiBits/blob/master/PiFmDma/PiFmDma.c // // PWM clock register: // http://www.raspberrypi.org/forums/viewtopic.php?t=8467&p=124620 // -// Simple (because it's in assembly) PWM+DMA setup: -// https://github.com/mikedurso/rpi-projects/blob/master/asm-nyancat/rpi-nyancat.s +// Simple (because it's in assembly) PWM+DMA setup: +// https://github.com/mikedurso/rpi-projects/blob/master/asm-nyancat/rpi-nyancat.s // -// Adafruit's NeoPixel driver: -// https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp +// Adafruit's NeoPixel driver: +// https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp // Hyperion includes #include diff --git a/libsrc/protoserver/CMakeLists.txt b/libsrc/protoserver/CMakeLists.txt index 769cc807..5d8737d7 100644 --- a/libsrc/protoserver/CMakeLists.txt +++ b/libsrc/protoserver/CMakeLists.txt @@ -1,61 +1,61 @@ - -# Define the current source locations -set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/protoserver) -set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/protoserver) - -include_directories( - ${CMAKE_CURRENT_BINARY_DIR} - ${PROTOBUF_INCLUDE_DIRS} -) - -# Group the headers that go through the MOC compiler -set(ProtoServer_QT_HEADERS - ${CURRENT_HEADER_DIR}/ProtoServer.h - ${CURRENT_HEADER_DIR}/ProtoConnection.h - ${CURRENT_SOURCE_DIR}/ProtoClientConnection.h - ${CURRENT_HEADER_DIR}/ProtoConnectionWrapper.h -) - -set(ProtoServer_HEADERS -) - -set(ProtoServer_SOURCES - ${CURRENT_SOURCE_DIR}/ProtoServer.cpp - ${CURRENT_SOURCE_DIR}/ProtoClientConnection.cpp - ${CURRENT_SOURCE_DIR}/ProtoConnection.cpp - ${CURRENT_SOURCE_DIR}/ProtoConnectionWrapper.cpp -) - -set(ProtoServer_PROTOS - ${CURRENT_SOURCE_DIR}/message.proto -) - -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} - ${ProtoServer_QT_HEADERS} - ${ProtoServer_SOURCES} - ${ProtoServer_HEADERS_MOC} - ${ProtoServer_PROTOS} - ${ProtoServer_PROTO_SRCS} - ${ProtoServer_PROTO_HDRS} -) -if(ENABLE_QT5) -qt5_use_modules(protoserver Widgets) -endif(ENABLE_QT5) - -target_link_libraries(protoserver - hyperion - hyperion-utils - protobuf - ${QT_LIBRARIES} -) + +# Define the current source locations +set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/protoserver) +set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/protoserver) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${PROTOBUF_INCLUDE_DIRS} +) + +# Group the headers that go through the MOC compiler +set(ProtoServer_QT_HEADERS + ${CURRENT_HEADER_DIR}/ProtoServer.h + ${CURRENT_HEADER_DIR}/ProtoConnection.h + ${CURRENT_SOURCE_DIR}/ProtoClientConnection.h + ${CURRENT_HEADER_DIR}/ProtoConnectionWrapper.h +) + +set(ProtoServer_HEADERS +) + +set(ProtoServer_SOURCES + ${CURRENT_SOURCE_DIR}/ProtoServer.cpp + ${CURRENT_SOURCE_DIR}/ProtoClientConnection.cpp + ${CURRENT_SOURCE_DIR}/ProtoConnection.cpp + ${CURRENT_SOURCE_DIR}/ProtoConnectionWrapper.cpp +) + +set(ProtoServer_PROTOS + ${CURRENT_SOURCE_DIR}/message.proto +) + +protobuf_generate_cpp(ProtoServer_PROTO_SRCS ProtoServer_PROTO_HDRS + ${ProtoServer_PROTOS} +) + +if(ENABLE_QT5) + qt5_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS}) +else() + qt4_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS}) +endif() + +add_library(protoserver + ${ProtoServer_HEADERS} + ${ProtoServer_QT_HEADERS} + ${ProtoServer_SOURCES} + ${ProtoServer_HEADERS_MOC} + ${ProtoServer_PROTOS} + ${ProtoServer_PROTO_SRCS} + ${ProtoServer_PROTO_HDRS} +) +if(ENABLE_QT5) + qt5_use_modules(protoserver Widgets) +endif() + +target_link_libraries(protoserver + hyperion + hyperion-utils + protobuf + ${QT_LIBRARIES} +) diff --git a/libsrc/protoserver/ProtoConnection.cpp b/libsrc/protoserver/ProtoConnection.cpp index b48c3466..d4850d48 100644 --- a/libsrc/protoserver/ProtoConnection.cpp +++ b/libsrc/protoserver/ProtoConnection.cpp @@ -8,207 +8,207 @@ #include "protoserver/ProtoConnection.h" ProtoConnection::ProtoConnection(const std::string & a) : - _socket(), - _skipReply(false), - _prevSocketState(QAbstractSocket::UnconnectedState) + _socket(), + _skipReply(false), + _prevSocketState(QAbstractSocket::UnconnectedState) { - QString address(a.c_str()); - QStringList parts = address.split(":"); - if (parts.size() != 2) - { - throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong address: Unable to parse address (%1)").arg(address).toStdString()); - } - _host = parts[0]; + QString address(a.c_str()); + QStringList parts = address.split(":"); + if (parts.size() != 2) + { + throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong address: Unable to parse address (%1)").arg(address).toStdString()); + } + _host = parts[0]; - bool ok; - _port = parts[1].toUShort(&ok); - if (!ok) - { - throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong port: Unable to parse the port number (%1)").arg(parts[1]).toStdString()); - } + bool ok; + _port = parts[1].toUShort(&ok); + if (!ok) + { + throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong port: Unable to parse the port number (%1)").arg(parts[1]).toStdString()); + } - // try to connect to host - std::cout << "PROTOCONNECTION INFO: Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; - connectToHost(); + // try to connect to host + std::cout << "PROTOCONNECTION INFO: Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + connectToHost(); - // start the connection timer - _timer.setInterval(5000); - _timer.setSingleShot(false); + // start the connection timer + _timer.setInterval(5000); + _timer.setSingleShot(false); - connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()) ); - _timer.start(); + connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()) ); + _timer.start(); } ProtoConnection::~ProtoConnection() { - _timer.stop(); - _socket.close(); + _timer.stop(); + _socket.close(); } void ProtoConnection::setSkipReply(bool skip) { - _skipReply = skip; + _skipReply = skip; } void ProtoConnection::setColor(const ColorRgb & color, int priority, int duration) { - proto::HyperionRequest request; - request.set_command(proto::HyperionRequest::COLOR); - proto::ColorRequest * colorRequest = request.MutableExtension(proto::ColorRequest::colorRequest); - colorRequest->set_rgbcolor((color.red << 16) | (color.green << 8) | color.blue); - colorRequest->set_priority(priority); - colorRequest->set_duration(duration); + proto::HyperionRequest request; + request.set_command(proto::HyperionRequest::COLOR); + proto::ColorRequest * colorRequest = request.MutableExtension(proto::ColorRequest::colorRequest); + colorRequest->set_rgbcolor((color.red << 16) | (color.green << 8) | color.blue); + colorRequest->set_priority(priority); + colorRequest->set_duration(duration); - // send command message - sendMessage(request); + // send command message + sendMessage(request); } void ProtoConnection::setImage(const Image &image, int priority, int duration) { - proto::HyperionRequest request; - request.set_command(proto::HyperionRequest::IMAGE); - proto::ImageRequest * imageRequest = request.MutableExtension(proto::ImageRequest::imageRequest); - imageRequest->set_imagedata(image.memptr(), image.width() * image.height() * 3); - imageRequest->set_imagewidth(image.width()); - imageRequest->set_imageheight(image.height()); - imageRequest->set_priority(priority); - imageRequest->set_duration(duration); + proto::HyperionRequest request; + request.set_command(proto::HyperionRequest::IMAGE); + proto::ImageRequest * imageRequest = request.MutableExtension(proto::ImageRequest::imageRequest); + imageRequest->set_imagedata(image.memptr(), image.width() * image.height() * 3); + imageRequest->set_imagewidth(image.width()); + imageRequest->set_imageheight(image.height()); + imageRequest->set_priority(priority); + imageRequest->set_duration(duration); - // send command message - sendMessage(request); + // send command message + sendMessage(request); } void ProtoConnection::clear(int priority) { - proto::HyperionRequest request; - request.set_command(proto::HyperionRequest::CLEAR); - proto::ClearRequest * clearRequest = request.MutableExtension(proto::ClearRequest::clearRequest); - clearRequest->set_priority(priority); + proto::HyperionRequest request; + request.set_command(proto::HyperionRequest::CLEAR); + proto::ClearRequest * clearRequest = request.MutableExtension(proto::ClearRequest::clearRequest); + clearRequest->set_priority(priority); - // send command message - sendMessage(request); + // send command message + sendMessage(request); } void ProtoConnection::clearAll() { - proto::HyperionRequest request; - request.set_command(proto::HyperionRequest::CLEARALL); + proto::HyperionRequest request; + request.set_command(proto::HyperionRequest::CLEARALL); - // send command message - sendMessage(request); + // send command message + sendMessage(request); } void ProtoConnection::connectToHost() { - // try connection only when - if (_socket.state() == QAbstractSocket::UnconnectedState) - { - _socket.connectToHost(_host, _port); - //_socket.waitForConnected(1000); - } + // try connection only when + if (_socket.state() == QAbstractSocket::UnconnectedState) + { + _socket.connectToHost(_host, _port); + //_socket.waitForConnected(1000); + } } void ProtoConnection::sendMessage(const proto::HyperionRequest &message) { - // print out connection message only when state is changed - if (_socket.state() != _prevSocketState ) - { - switch (_socket.state() ) - { - case QAbstractSocket::UnconnectedState: - std::cout << "PROTOCONNECTION INFO: No connection to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; - break; + // print out connection message only when state is changed + if (_socket.state() != _prevSocketState ) + { + switch (_socket.state() ) + { + case QAbstractSocket::UnconnectedState: + std::cout << "PROTOCONNECTION INFO: No connection to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + break; - case QAbstractSocket::ConnectedState: - std::cout << "PROTOCONNECTION INFO: Connected to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; - break; + case QAbstractSocket::ConnectedState: + std::cout << "PROTOCONNECTION INFO: Connected to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + break; - default: - //std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; - break; - } - _prevSocketState = _socket.state(); - } + default: + //std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + break; + } + _prevSocketState = _socket.state(); + } - if (_socket.state() != QAbstractSocket::ConnectedState) - { - return; - } + if (_socket.state() != QAbstractSocket::ConnectedState) + { + return; + } - // We only get here if we are connected + // We only get here if we are connected - // serialize message (FastWriter already appends a newline) - std::string serializedMessage = message.SerializeAsString(); + // serialize message (FastWriter already appends a newline) + std::string serializedMessage = message.SerializeAsString(); - int length = serializedMessage.size(); - const uint8_t header[] = { - uint8_t((length >> 24) & 0xFF), - uint8_t((length >> 16) & 0xFF), - uint8_t((length >> 8) & 0xFF), - uint8_t((length ) & 0xFF)}; + int length = serializedMessage.size(); + const uint8_t header[] = { + uint8_t((length >> 24) & 0xFF), + uint8_t((length >> 16) & 0xFF), + uint8_t((length >> 8) & 0xFF), + uint8_t((length ) & 0xFF)}; - // write message - int count = 0; - count += _socket.write(reinterpret_cast(header), 4); - count += _socket.write(reinterpret_cast(serializedMessage.data()), length); - if (!_socket.waitForBytesWritten()) - { - std::cerr << "PROTOCONNECTION ERROR: Error while writing data to host" << std::endl; - return; - } + // write message + int count = 0; + count += _socket.write(reinterpret_cast(header), 4); + count += _socket.write(reinterpret_cast(serializedMessage.data()), length); + if (!_socket.waitForBytesWritten()) + { + std::cerr << "PROTOCONNECTION ERROR: Error while writing data to host" << std::endl; + return; + } - if (!_skipReply) - { - // read reply data - QByteArray serializedReply; - length = -1; - while (length < 0 && serializedReply.size() < length+4) - { - // receive reply - if (!_socket.waitForReadyRead()) - { - std::cerr << "PROTOCONNECTION ERROR: Error while reading data from host" << std::endl; - return; - } + if (!_skipReply) + { + // read reply data + QByteArray serializedReply; + length = -1; + while (length < 0 && serializedReply.size() < length+4) + { + // receive reply + if (!_socket.waitForReadyRead()) + { + std::cerr << "PROTOCONNECTION ERROR: Error while reading data from host" << std::endl; + return; + } - serializedReply += _socket.readAll(); + serializedReply += _socket.readAll(); - if (length < 0 && serializedReply.size() >= 4) - { - // read the message size - length = - ((serializedReply[0]<<24) & 0xFF000000) | - ((serializedReply[1]<<16) & 0x00FF0000) | - ((serializedReply[2]<< 8) & 0x0000FF00) | - ((serializedReply[3] ) & 0x000000FF); - } - } + if (length < 0 && serializedReply.size() >= 4) + { + // read the message size + length = + ((serializedReply[0]<<24) & 0xFF000000) | + ((serializedReply[1]<<16) & 0x00FF0000) | + ((serializedReply[2]<< 8) & 0x0000FF00) | + ((serializedReply[3] ) & 0x000000FF); + } + } - // parse reply data - proto::HyperionReply reply; - reply.ParseFromArray(serializedReply.constData()+4, length); + // parse reply data + proto::HyperionReply reply; + reply.ParseFromArray(serializedReply.constData()+4, length); - // parse reply message - parseReply(reply); - } + // parse reply message + parseReply(reply); + } } bool ProtoConnection::parseReply(const proto::HyperionReply &reply) { - bool success = false; + bool success = false; - if (!reply.success()) - { - if (reply.has_error()) - { - throw std::runtime_error("PROTOCONNECTION ERROR: " + reply.error()); - } - else - { - throw std::runtime_error("PROTOCONNECTION ERROR: No error info"); - } - } + if (!reply.success()) + { + if (reply.has_error()) + { + throw std::runtime_error("PROTOCONNECTION ERROR: " + reply.error()); + } + else + { + throw std::runtime_error("PROTOCONNECTION ERROR: No error info"); + } + } - return success; + return success; } diff --git a/libsrc/protoserver/ProtoConnectionWrapper.cpp b/libsrc/protoserver/ProtoConnectionWrapper.cpp index 7cf88f43..e1c5b8d4 100644 --- a/libsrc/protoserver/ProtoConnectionWrapper.cpp +++ b/libsrc/protoserver/ProtoConnectionWrapper.cpp @@ -2,11 +2,11 @@ #include "protoserver/ProtoConnectionWrapper.h" ProtoConnectionWrapper::ProtoConnectionWrapper(const std::string & address, int priority, int duration_ms, bool skipProtoReply) : - _priority(priority), - _duration_ms(duration_ms), - _connection(address) + _priority(priority), + _duration_ms(duration_ms), + _connection(address) { - _connection.setSkipReply(skipProtoReply); + _connection.setSkipReply(skipProtoReply); } ProtoConnectionWrapper::~ProtoConnectionWrapper() @@ -15,5 +15,5 @@ ProtoConnectionWrapper::~ProtoConnectionWrapper() void ProtoConnectionWrapper::receiveImage(const Image & image) { - _connection.setImage(image, _priority, _duration_ms); + _connection.setImage(image, _priority, _duration_ms); } diff --git a/libsrc/utils/CMakeLists.txt b/libsrc/utils/CMakeLists.txt index 5978c2c1..1b9e2982 100644 --- a/libsrc/utils/CMakeLists.txt +++ b/libsrc/utils/CMakeLists.txt @@ -1,41 +1,41 @@ - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/utils) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/utils) - -add_library(hyperion-utils - ${CURRENT_HEADER_DIR}/ColorArgb.h - ${CURRENT_SOURCE_DIR}/ColorArgb.cpp - ${CURRENT_HEADER_DIR}/ColorBgr.h - ${CURRENT_SOURCE_DIR}/ColorBgr.cpp - ${CURRENT_HEADER_DIR}/ColorRgb.h - ${CURRENT_SOURCE_DIR}/ColorRgb.cpp - ${CURRENT_HEADER_DIR}/ColorRgba.h - ${CURRENT_SOURCE_DIR}/ColorRgba.cpp - ${CURRENT_HEADER_DIR}/Image.h - ${CURRENT_HEADER_DIR}/Sleep.h - - ${CURRENT_HEADER_DIR}/PixelFormat.h - ${CURRENT_HEADER_DIR}/VideoMode.h - - ${CURRENT_HEADER_DIR}/ImageResampler.h - ${CURRENT_SOURCE_DIR}/ImageResampler.cpp - - ${CURRENT_HEADER_DIR}/HsvTransform.h - ${CURRENT_SOURCE_DIR}/HsvTransform.cpp - ${CURRENT_HEADER_DIR}/HslTransform.h - ${CURRENT_SOURCE_DIR}/HslTransform.cpp - ${CURRENT_HEADER_DIR}/RgbChannelTransform.h - ${CURRENT_SOURCE_DIR}/RgbChannelTransform.cpp - ${CURRENT_HEADER_DIR}/RgbChannelCorrection.h - ${CURRENT_SOURCE_DIR}/RgbChannelCorrection.cpp - ${CURRENT_HEADER_DIR}/RgbChannelAdjustment.h - ${CURRENT_SOURCE_DIR}/RgbChannelAdjustment.cpp - - ${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h - ${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h - ${CURRENT_SOURCE_DIR}/jsonschema/JsonSchemaChecker.cpp -) - -target_link_libraries(hyperion-utils - jsoncpp) + +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/utils) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/utils) + +add_library(hyperion-utils + ${CURRENT_HEADER_DIR}/ColorArgb.h + ${CURRENT_SOURCE_DIR}/ColorArgb.cpp + ${CURRENT_HEADER_DIR}/ColorBgr.h + ${CURRENT_SOURCE_DIR}/ColorBgr.cpp + ${CURRENT_HEADER_DIR}/ColorRgb.h + ${CURRENT_SOURCE_DIR}/ColorRgb.cpp + ${CURRENT_HEADER_DIR}/ColorRgba.h + ${CURRENT_SOURCE_DIR}/ColorRgba.cpp + ${CURRENT_HEADER_DIR}/Image.h + ${CURRENT_HEADER_DIR}/Sleep.h + + ${CURRENT_HEADER_DIR}/PixelFormat.h + ${CURRENT_HEADER_DIR}/VideoMode.h + + ${CURRENT_HEADER_DIR}/ImageResampler.h + ${CURRENT_SOURCE_DIR}/ImageResampler.cpp + + ${CURRENT_HEADER_DIR}/HsvTransform.h + ${CURRENT_SOURCE_DIR}/HsvTransform.cpp + ${CURRENT_HEADER_DIR}/HslTransform.h + ${CURRENT_SOURCE_DIR}/HslTransform.cpp + ${CURRENT_HEADER_DIR}/RgbChannelTransform.h + ${CURRENT_SOURCE_DIR}/RgbChannelTransform.cpp + ${CURRENT_HEADER_DIR}/RgbChannelCorrection.h + ${CURRENT_SOURCE_DIR}/RgbChannelCorrection.cpp + ${CURRENT_HEADER_DIR}/RgbChannelAdjustment.h + ${CURRENT_SOURCE_DIR}/RgbChannelAdjustment.cpp + + ${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h + ${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h + ${CURRENT_SOURCE_DIR}/jsonschema/JsonSchemaChecker.cpp +) + +target_link_libraries(hyperion-utils + jsoncpp) diff --git a/libsrc/utils/jsonschema/JsonSchemaChecker.cpp b/libsrc/utils/jsonschema/JsonSchemaChecker.cpp index 3411d84d..9a6a6116 100644 --- a/libsrc/utils/jsonschema/JsonSchemaChecker.cpp +++ b/libsrc/utils/jsonschema/JsonSchemaChecker.cpp @@ -1,464 +1,464 @@ -// stdlib includes -#include -#include -#include -#include - -// Utils-Jsonschema includes -#include - -JsonSchemaChecker::JsonSchemaChecker() -{ - // empty -} - -JsonSchemaChecker::~JsonSchemaChecker() -{ - // empty -} - -bool JsonSchemaChecker::setSchema(const Json::Value & schema) -{ - _schema = schema; - - // TODO: check the schema - - return true; -} - -bool JsonSchemaChecker::validate(const Json::Value & value) -{ - // initialize state - _error = false; - _messages.clear(); - _currentPath.clear(); - _currentPath.push_back("[root]"); - _references.clear(); - - // collect dependencies - collectDependencies(value, _schema); - - // validate - validate(value, _schema); - - return !_error; -} - -void JsonSchemaChecker::collectDependencies(const Json::Value & value, const Json::Value &schema) -{ - assert (schema.isObject()); - - // check if id is present - if (schema.isMember("id")) - { - // strore reference - assert (schema["id"].isString()); - std::ostringstream ref; - ref << "$(" << schema["id"].asString() << ")"; - _references[ref.str()] = &value; - } - - // check the current json value - if (schema.isMember("properties")) - { - const Json::Value & properties = schema["properties"]; - assert(properties.isObject()); - - for (Json::Value::const_iterator j = properties.begin(); j != properties.end(); ++j) - { - std::string property = j.memberName(); - if (value.isMember(property)) - { - collectDependencies(value[property], properties[property]); - } - } - } -} - -void JsonSchemaChecker::validate(const Json::Value & value, const Json::Value &schema) -{ - assert (schema.isObject()); - - // check the current json value - for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i) - { - std::string attribute = i.memberName(); - const Json::Value & attributeValue = *i; - - if (attribute == "type") - checkType(value, attributeValue); - else if (attribute == "properties") - checkProperties(value, attributeValue); - else if (attribute == "additionalProperties") - { - // ignore the properties which are handled by the properties attribute (if present) - Json::Value::Members ignoredProperties; - if (schema.isMember("properties")) { - const Json::Value & props = schema["properties"]; - ignoredProperties = props.getMemberNames(); - } - - checkAdditionalProperties(value, attributeValue, ignoredProperties); - } - else if (attribute == "dependencies") - checkDependencies(value, attributeValue); - else if (attribute == "minimum") - checkMinimum(value, attributeValue); - else if (attribute == "maximum") - checkMaximum(value, attributeValue); - else if (attribute == "items") - checkItems(value, attributeValue); - else if (attribute == "minItems") - checkMinItems(value, attributeValue); - else if (attribute == "maxItems") - checkMaxItems(value, attributeValue); - else if (attribute == "uniqueItems") - checkUniqueItems(value, attributeValue); - else if (attribute == "enum") - checkEnum(value, attributeValue); - else if (attribute == "required") - ; // nothing to do. value is present so always oke - else if (attribute == "id") - ; // references have already been collected - else - { - // no check function defined for this attribute - setMessage(std::string("No check function defined for attribute ") + attribute); - continue; - } - } -} - -void JsonSchemaChecker::setMessage(const std::string & message) -{ - std::ostringstream oss; - std::copy(_currentPath.begin(), _currentPath.end(), std::ostream_iterator(oss, "")); - oss << ": " << message; - _messages.push_back(oss.str()); -} - -const std::list & JsonSchemaChecker::getMessages() const -{ - return _messages; -} - -void JsonSchemaChecker::checkType(const Json::Value & value, const Json::Value & schema) -{ - assert(schema.isString()); - - std::string type = schema.asString(); - bool wrongType = false; - if (type == "string") - wrongType = !value.isString(); - else if (type == "number") - wrongType = !value.isNumeric(); - else if (type == "integer") - wrongType = !value.isIntegral(); - else if (type == "double") - wrongType = !value.isDouble(); - else if (type == "boolean") - wrongType = !value.isBool(); - else if (type == "object") - wrongType = !value.isObject(); - else if (type == "array") - wrongType = !value.isArray(); - else if (type == "null") - wrongType = !value.isNull(); - else if (type == "enum") - wrongType = !value.isString(); - else if (type == "any") - wrongType = false; -// else -// assert(false); - - if (wrongType) - { - _error = true; - setMessage(type + " expected"); - } -} - -void JsonSchemaChecker::checkProperties(const Json::Value & value, const Json::Value & schema) -{ - assert(schema.isObject()); - - if (!value.isObject()) - { - _error = true; - setMessage("properies attribute is only valid for objects"); - return; - } - - for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i) - { - std::string property = i.memberName(); - const Json::Value & propertyValue = *i; - - assert(propertyValue.isObject()); - - _currentPath.push_back(std::string(".") + property); - if (value.isMember(property)) - { - validate(value[property], propertyValue); - } - else if (propertyValue.get("required", false).asBool()) - { - _error = true; - setMessage("missing member"); - } - _currentPath.pop_back(); - } -} - -void JsonSchemaChecker::checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties) -{ - if (!value.isObject()) - { - _error = true; - setMessage("additional properies attribute is only valid for objects"); - return; - } - - for (Json::Value::const_iterator i = value.begin(); i != value.end(); ++i) - { - std::string property = i.memberName(); - if (std::find(ignoredProperties.begin(), ignoredProperties.end(), property) == ignoredProperties.end()) - { - // property has no property definition. check against the definition for additional properties - _currentPath.push_back(std::string(".") + property); - if (schema.isBool()) - { - if (schema.asBool() == false) - { - _error = true; - setMessage("no schema definition"); - } - } - else - { - validate(value[property], schema); - } - _currentPath.pop_back(); - } - } -} - -void JsonSchemaChecker::checkDependencies(const Json::Value & value, const Json::Value & schemaLink) -{ - if (!value.isObject()) - { - _error = true; - setMessage("dependencies attribute is only valid for objects"); - return; - } - - assert(schemaLink.isString()); - std::map::iterator iter = _references.find(schemaLink.asString()); - if (iter == _references.end()) - { - _error = true; - std::ostringstream oss; - oss << "reference " << schemaLink.asString() << " could not be resolved"; - setMessage(oss.str()); - return; - } - const Json::Value & schema = *(iter->second); - - std::list requiredProperties; - if (schema.isString()) - { - requiredProperties.push_back(schema.asString()); - } - else if (schema.isArray()) - { - for (Json::UInt i = 0; i < schema.size(); ++i) - { - assert(schema[i].isString()); - requiredProperties.push_back(schema[i].asString()); - } - } - else - { - _error = true; - std::ostringstream oss; - oss << "Exepected reference " << schemaLink.asString() << " to resolve to a string or array"; - setMessage(oss.str()); - return; - } - - for (std::list::const_iterator i = requiredProperties.begin(); i != requiredProperties.end(); ++i) - { - if (!value.isMember(*i)) - { - _error = true; - std::ostringstream oss; - oss << "missing member " << *i; - setMessage(oss.str()); - } - } -} - -void JsonSchemaChecker::checkMinimum(const Json::Value & value, const Json::Value & schema) -{ - assert(schema.isNumeric()); - - if (!value.isNumeric()) - { - // only for numeric - _error = true; - setMessage("minimum check only for numeric fields"); - return; - } - - if (value.asDouble() < schema.asDouble()) - { - _error = true; - std::ostringstream oss; - oss << "value is too small (minimum=" << schema.asDouble() << ")"; - setMessage(oss.str()); - } -} - -void JsonSchemaChecker::checkMaximum(const Json::Value & value, const Json::Value & schema) -{ - assert(schema.isNumeric()); - - if (!value.isNumeric()) - { - // only for numeric - _error = true; - setMessage("maximum check only for numeric fields"); - return; - } - - if (value.asDouble() > schema.asDouble()) - { - _error = true; - std::ostringstream oss; - oss << "value is too large (maximum=" << schema.asDouble() << ")"; - setMessage(oss.str()); - } -} - -void JsonSchemaChecker::checkItems(const Json::Value & value, const Json::Value & schema) -{ - assert(schema.isObject()); - - if (!value.isArray()) - { - // only for arrays - _error = true; - setMessage("items only valid for arrays"); - return; - } - - for(Json::ArrayIndex i = 0; i < value.size(); ++i) - { - // validate each item - std::ostringstream oss; - oss << "[" << i << "]"; - _currentPath.push_back(oss.str()); - validate(value[i], schema); - _currentPath.pop_back(); - } -} - -void JsonSchemaChecker::checkMinItems(const Json::Value & value, const Json::Value & schema) -{ - assert(schema.isIntegral()); - - if (!value.isArray()) - { - // only for arrays - _error = true; - setMessage("minItems only valid for arrays"); - return; - } - - int minimum = schema.asInt(); - - if (static_cast(value.size()) < minimum) - { - _error = true; - std::ostringstream oss; - oss << "array is too small (minimum=" << minimum << ")"; - setMessage(oss.str()); - } -} - -void JsonSchemaChecker::checkMaxItems(const Json::Value & value, const Json::Value & schema) -{ - assert(schema.isIntegral()); - - if (!value.isArray()) - { - // only for arrays - _error = true; - setMessage("maxItems only valid for arrays"); - return; - } - - int maximum = schema.asInt(); - - if (static_cast(value.size()) > maximum) - { - _error = true; - std::ostringstream oss; - oss << "array is too large (maximum=" << maximum << ")"; - setMessage(oss.str()); - } -} - -void JsonSchemaChecker::checkUniqueItems(const Json::Value & value, const Json::Value & schema) -{ - assert(schema.isBool()); - - if (!value.isArray()) - { - // only for arrays - _error = true; - setMessage("uniqueItems only valid for arrays"); - return; - } - - if (schema.asBool() == true) - { - // make sure no two items are identical - - for(Json::UInt i = 0; i < value.size(); ++i) - { - for (Json::UInt j = i+1; j < value.size(); ++j) - { - if (value[i] == value[j]) - { - // found a value twice - _error = true; - setMessage("array must have unique values"); - } - } - } - } -} - -void JsonSchemaChecker::checkEnum(const Json::Value & value, const Json::Value & schema) -{ - assert(schema.isArray()); - - for(Json::ArrayIndex i = 0; i < schema.size(); ++i) - { - if (schema[i] == value) - { - // found enum value. done. - return; - } - } - - // nothing found - _error = true; - std::ostringstream oss; - oss << "Unknown enum value (allowed values are: "; - std::string values = Json::FastWriter().write(schema); - oss << values.substr(0, values.size()-1); // The writer append a new line which we don't want - oss << ")"; - setMessage(oss.str()); -} +// stdlib includes +#include +#include +#include +#include + +// Utils-Jsonschema includes +#include + +JsonSchemaChecker::JsonSchemaChecker() +{ + // empty +} + +JsonSchemaChecker::~JsonSchemaChecker() +{ + // empty +} + +bool JsonSchemaChecker::setSchema(const Json::Value & schema) +{ + _schema = schema; + + // TODO: check the schema + + return true; +} + +bool JsonSchemaChecker::validate(const Json::Value & value) +{ + // initialize state + _error = false; + _messages.clear(); + _currentPath.clear(); + _currentPath.push_back("[root]"); + _references.clear(); + + // collect dependencies + collectDependencies(value, _schema); + + // validate + validate(value, _schema); + + return !_error; +} + +void JsonSchemaChecker::collectDependencies(const Json::Value & value, const Json::Value &schema) +{ + assert (schema.isObject()); + + // check if id is present + if (schema.isMember("id")) + { + // strore reference + assert (schema["id"].isString()); + std::ostringstream ref; + ref << "$(" << schema["id"].asString() << ")"; + _references[ref.str()] = &value; + } + + // check the current json value + if (schema.isMember("properties")) + { + const Json::Value & properties = schema["properties"]; + assert(properties.isObject()); + + for (Json::Value::const_iterator j = properties.begin(); j != properties.end(); ++j) + { + std::string property = j.memberName(); + if (value.isMember(property)) + { + collectDependencies(value[property], properties[property]); + } + } + } +} + +void JsonSchemaChecker::validate(const Json::Value & value, const Json::Value &schema) +{ + assert (schema.isObject()); + + // check the current json value + for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i) + { + std::string attribute = i.memberName(); + const Json::Value & attributeValue = *i; + + if (attribute == "type") + checkType(value, attributeValue); + else if (attribute == "properties") + checkProperties(value, attributeValue); + else if (attribute == "additionalProperties") + { + // ignore the properties which are handled by the properties attribute (if present) + Json::Value::Members ignoredProperties; + if (schema.isMember("properties")) { + const Json::Value & props = schema["properties"]; + ignoredProperties = props.getMemberNames(); + } + + checkAdditionalProperties(value, attributeValue, ignoredProperties); + } + else if (attribute == "dependencies") + checkDependencies(value, attributeValue); + else if (attribute == "minimum") + checkMinimum(value, attributeValue); + else if (attribute == "maximum") + checkMaximum(value, attributeValue); + else if (attribute == "items") + checkItems(value, attributeValue); + else if (attribute == "minItems") + checkMinItems(value, attributeValue); + else if (attribute == "maxItems") + checkMaxItems(value, attributeValue); + else if (attribute == "uniqueItems") + checkUniqueItems(value, attributeValue); + else if (attribute == "enum") + checkEnum(value, attributeValue); + else if (attribute == "required") + ; // nothing to do. value is present so always oke + else if (attribute == "id") + ; // references have already been collected + else + { + // no check function defined for this attribute + setMessage(std::string("No check function defined for attribute ") + attribute); + continue; + } + } +} + +void JsonSchemaChecker::setMessage(const std::string & message) +{ + std::ostringstream oss; + std::copy(_currentPath.begin(), _currentPath.end(), std::ostream_iterator(oss, "")); + oss << ": " << message; + _messages.push_back(oss.str()); +} + +const std::list & JsonSchemaChecker::getMessages() const +{ + return _messages; +} + +void JsonSchemaChecker::checkType(const Json::Value & value, const Json::Value & schema) +{ + assert(schema.isString()); + + std::string type = schema.asString(); + bool wrongType = false; + if (type == "string") + wrongType = !value.isString(); + else if (type == "number") + wrongType = !value.isNumeric(); + else if (type == "integer") + wrongType = !value.isIntegral(); + else if (type == "double") + wrongType = !value.isDouble(); + else if (type == "boolean") + wrongType = !value.isBool(); + else if (type == "object") + wrongType = !value.isObject(); + else if (type == "array") + wrongType = !value.isArray(); + else if (type == "null") + wrongType = !value.isNull(); + else if (type == "enum") + wrongType = !value.isString(); + else if (type == "any") + wrongType = false; +// else +// assert(false); + + if (wrongType) + { + _error = true; + setMessage(type + " expected"); + } +} + +void JsonSchemaChecker::checkProperties(const Json::Value & value, const Json::Value & schema) +{ + assert(schema.isObject()); + + if (!value.isObject()) + { + _error = true; + setMessage("properies attribute is only valid for objects"); + return; + } + + for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i) + { + std::string property = i.memberName(); + const Json::Value & propertyValue = *i; + + assert(propertyValue.isObject()); + + _currentPath.push_back(std::string(".") + property); + if (value.isMember(property)) + { + validate(value[property], propertyValue); + } + else if (propertyValue.get("required", false).asBool()) + { + _error = true; + setMessage("missing member"); + } + _currentPath.pop_back(); + } +} + +void JsonSchemaChecker::checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties) +{ + if (!value.isObject()) + { + _error = true; + setMessage("additional properies attribute is only valid for objects"); + return; + } + + for (Json::Value::const_iterator i = value.begin(); i != value.end(); ++i) + { + std::string property = i.memberName(); + if (std::find(ignoredProperties.begin(), ignoredProperties.end(), property) == ignoredProperties.end()) + { + // property has no property definition. check against the definition for additional properties + _currentPath.push_back(std::string(".") + property); + if (schema.isBool()) + { + if (schema.asBool() == false) + { + _error = true; + setMessage("no schema definition"); + } + } + else + { + validate(value[property], schema); + } + _currentPath.pop_back(); + } + } +} + +void JsonSchemaChecker::checkDependencies(const Json::Value & value, const Json::Value & schemaLink) +{ + if (!value.isObject()) + { + _error = true; + setMessage("dependencies attribute is only valid for objects"); + return; + } + + assert(schemaLink.isString()); + std::map::iterator iter = _references.find(schemaLink.asString()); + if (iter == _references.end()) + { + _error = true; + std::ostringstream oss; + oss << "reference " << schemaLink.asString() << " could not be resolved"; + setMessage(oss.str()); + return; + } + const Json::Value & schema = *(iter->second); + + std::list requiredProperties; + if (schema.isString()) + { + requiredProperties.push_back(schema.asString()); + } + else if (schema.isArray()) + { + for (Json::UInt i = 0; i < schema.size(); ++i) + { + assert(schema[i].isString()); + requiredProperties.push_back(schema[i].asString()); + } + } + else + { + _error = true; + std::ostringstream oss; + oss << "Exepected reference " << schemaLink.asString() << " to resolve to a string or array"; + setMessage(oss.str()); + return; + } + + for (std::list::const_iterator i = requiredProperties.begin(); i != requiredProperties.end(); ++i) + { + if (!value.isMember(*i)) + { + _error = true; + std::ostringstream oss; + oss << "missing member " << *i; + setMessage(oss.str()); + } + } +} + +void JsonSchemaChecker::checkMinimum(const Json::Value & value, const Json::Value & schema) +{ + assert(schema.isNumeric()); + + if (!value.isNumeric()) + { + // only for numeric + _error = true; + setMessage("minimum check only for numeric fields"); + return; + } + + if (value.asDouble() < schema.asDouble()) + { + _error = true; + std::ostringstream oss; + oss << "value is too small (minimum=" << schema.asDouble() << ")"; + setMessage(oss.str()); + } +} + +void JsonSchemaChecker::checkMaximum(const Json::Value & value, const Json::Value & schema) +{ + assert(schema.isNumeric()); + + if (!value.isNumeric()) + { + // only for numeric + _error = true; + setMessage("maximum check only for numeric fields"); + return; + } + + if (value.asDouble() > schema.asDouble()) + { + _error = true; + std::ostringstream oss; + oss << "value is too large (maximum=" << schema.asDouble() << ")"; + setMessage(oss.str()); + } +} + +void JsonSchemaChecker::checkItems(const Json::Value & value, const Json::Value & schema) +{ + assert(schema.isObject()); + + if (!value.isArray()) + { + // only for arrays + _error = true; + setMessage("items only valid for arrays"); + return; + } + + for(Json::ArrayIndex i = 0; i < value.size(); ++i) + { + // validate each item + std::ostringstream oss; + oss << "[" << i << "]"; + _currentPath.push_back(oss.str()); + validate(value[i], schema); + _currentPath.pop_back(); + } +} + +void JsonSchemaChecker::checkMinItems(const Json::Value & value, const Json::Value & schema) +{ + assert(schema.isIntegral()); + + if (!value.isArray()) + { + // only for arrays + _error = true; + setMessage("minItems only valid for arrays"); + return; + } + + int minimum = schema.asInt(); + + if (static_cast(value.size()) < minimum) + { + _error = true; + std::ostringstream oss; + oss << "array is too small (minimum=" << minimum << ")"; + setMessage(oss.str()); + } +} + +void JsonSchemaChecker::checkMaxItems(const Json::Value & value, const Json::Value & schema) +{ + assert(schema.isIntegral()); + + if (!value.isArray()) + { + // only for arrays + _error = true; + setMessage("maxItems only valid for arrays"); + return; + } + + int maximum = schema.asInt(); + + if (static_cast(value.size()) > maximum) + { + _error = true; + std::ostringstream oss; + oss << "array is too large (maximum=" << maximum << ")"; + setMessage(oss.str()); + } +} + +void JsonSchemaChecker::checkUniqueItems(const Json::Value & value, const Json::Value & schema) +{ + assert(schema.isBool()); + + if (!value.isArray()) + { + // only for arrays + _error = true; + setMessage("uniqueItems only valid for arrays"); + return; + } + + if (schema.asBool() == true) + { + // make sure no two items are identical + + for(Json::UInt i = 0; i < value.size(); ++i) + { + for (Json::UInt j = i+1; j < value.size(); ++j) + { + if (value[i] == value[j]) + { + // found a value twice + _error = true; + setMessage("array must have unique values"); + } + } + } + } +} + +void JsonSchemaChecker::checkEnum(const Json::Value & value, const Json::Value & schema) +{ + assert(schema.isArray()); + + for(Json::ArrayIndex i = 0; i < schema.size(); ++i) + { + if (schema[i] == value) + { + // found enum value. done. + return; + } + } + + // nothing found + _error = true; + std::ostringstream oss; + oss << "Unknown enum value (allowed values are: "; + std::string values = Json::FastWriter().write(schema); + oss << values.substr(0, values.size()-1); // The writer append a new line which we don't want + oss << ")"; + setMessage(oss.str()); +} diff --git a/libsrc/xbmcvideochecker/CMakeLists.txt b/libsrc/xbmcvideochecker/CMakeLists.txt index f6e71b00..bb13fb21 100644 --- a/libsrc/xbmcvideochecker/CMakeLists.txt +++ b/libsrc/xbmcvideochecker/CMakeLists.txt @@ -5,33 +5,33 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/xbmcvideochecker) # Group the headers that go through the MOC compiler SET(XBMCVideoChecker_QT_HEADERS - ${CURRENT_HEADER_DIR}/XBMCVideoChecker.h + ${CURRENT_HEADER_DIR}/XBMCVideoChecker.h ) SET(XBMCVideoChecker_HEADERS ) SET(XBMCVideoChecker_SOURCES - ${CURRENT_SOURCE_DIR}/XBMCVideoChecker.cpp + ${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) + QT5_WRAP_CPP(XBMCVideoChecker_HEADERS_MOC ${XBMCVideoChecker_QT_HEADERS}) +else() + QT4_WRAP_CPP(XBMCVideoChecker_HEADERS_MOC ${XBMCVideoChecker_QT_HEADERS}) +endif() add_library(xbmcvideochecker - ${XBMCVideoChecker_HEADERS} - ${XBMCVideoChecker_QT_HEADERS} - ${XBMCVideoChecker_HEADERS_MOC} - ${XBMCVideoChecker_SOURCES} + ${XBMCVideoChecker_HEADERS} + ${XBMCVideoChecker_QT_HEADERS} + ${XBMCVideoChecker_HEADERS_MOC} + ${XBMCVideoChecker_SOURCES} ) if(ENABLE_QT5) -qt5_use_modules(xbmcvideochecker Widgets) -endif(ENABLE_QT5) + qt5_use_modules(xbmcvideochecker Widgets) +endif() target_link_libraries(xbmcvideochecker - hyperion - ${QT_LIBRARIES}) + hyperion + ${QT_LIBRARIES}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2626ba9b..89a91802 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,30 +2,27 @@ add_subdirectory(hyperiond) add_subdirectory(hyperion-remote) # The following clients depend on the protobuf library -if(ENABLE_PROTOBUF) - - if (ENABLE_AMLOGIC) - add_subdirectory(hyperion-aml) - endif() - - if(ENABLE_V4L2) - add_subdirectory(hyperion-v4l2) - endif() - - if(ENABLE_X11) - add_subdirectory(hyperion-x11) - endif() - - if(ENABLE_DISPMANX) - add_subdirectory(hyperion-dispmanx) - endif() - - if(ENABLE_FB) - add_subdirectory(hyperion-framebuffer) - endif() - - if(ENABLE_OSX) - add_subdirectory(hyperion-osx) - endif() - +if (ENABLE_AMLOGIC) + add_subdirectory(hyperion-aml) endif() + +if(ENABLE_V4L2) + add_subdirectory(hyperion-v4l2) +endif() + +if(ENABLE_X11) + add_subdirectory(hyperion-x11) +endif() + +if(ENABLE_DISPMANX) + add_subdirectory(hyperion-dispmanx) +endif() + +if(ENABLE_FB) + add_subdirectory(hyperion-framebuffer) +endif() + +if(ENABLE_OSX) + add_subdirectory(hyperion-osx) +endif() + diff --git a/src/hyperion-aml/AmlogicWrapper.cpp b/src/hyperion-aml/AmlogicWrapper.cpp index e4c1f7f1..cf9c2ea2 100644 --- a/src/hyperion-aml/AmlogicWrapper.cpp +++ b/src/hyperion-aml/AmlogicWrapper.cpp @@ -3,14 +3,14 @@ #include "AmlogicWrapper.h" AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : - _timer(this), - _grabber(grabWidth, grabHeight) + _timer(this), + _grabber(grabWidth, grabHeight) { - _timer.setSingleShot(false); - _timer.setInterval(updateRate_Hz); + _timer.setSingleShot(false); + _timer.setInterval(updateRate_Hz); - // Connect capturing to the timeout signal of the timer - connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); + // Connect capturing to the timeout signal of the timer + connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); } const Image & AmlogicWrapper::getScreenshot() @@ -21,12 +21,12 @@ const Image & AmlogicWrapper::getScreenshot() void AmlogicWrapper::start() { - _timer.start(); + _timer.start(); } void AmlogicWrapper::stop() { - _timer.stop(); + _timer.stop(); } void AmlogicWrapper::capture() diff --git a/src/hyperion-dispmanx/DispmanxWrapper.cpp b/src/hyperion-dispmanx/DispmanxWrapper.cpp index ff88fc77..78f10f02 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.cpp +++ b/src/hyperion-dispmanx/DispmanxWrapper.cpp @@ -7,16 +7,16 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe const unsigned cropLeft, const unsigned cropRight, const unsigned cropTop, const unsigned cropBottom, const unsigned updateRate_Hz) : - _timer(this), - _grabber(grabWidth, grabHeight) + _timer(this), + _grabber(grabWidth, grabHeight) { - _grabber.setVideoMode(videoMode); - _grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom); - _timer.setSingleShot(false); - _timer.setInterval(updateRate_Hz); + _grabber.setVideoMode(videoMode); + _grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom); + _timer.setSingleShot(false); + _timer.setInterval(updateRate_Hz); - // Connect capturing to the timeout signal of the timer - connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); + // Connect capturing to the timeout signal of the timer + connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); } const Image & DispmanxWrapper::getScreenshot() @@ -27,12 +27,12 @@ const Image & DispmanxWrapper::getScreenshot() void DispmanxWrapper::start() { - _timer.start(); + _timer.start(); } void DispmanxWrapper::stop() { - _timer.stop(); + _timer.stop(); } void DispmanxWrapper::capture() diff --git a/src/hyperion-framebuffer/FramebufferWrapper.cpp b/src/hyperion-framebuffer/FramebufferWrapper.cpp index b7d7c7b7..48ef4ec7 100644 --- a/src/hyperion-framebuffer/FramebufferWrapper.cpp +++ b/src/hyperion-framebuffer/FramebufferWrapper.cpp @@ -3,14 +3,14 @@ #include "FramebufferWrapper.h" FramebufferWrapper::FramebufferWrapper(const std::string & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : - _timer(this), - _grabber(device,grabWidth, grabHeight) + _timer(this), + _grabber(device,grabWidth, grabHeight) { - _timer.setSingleShot(false); - _timer.setInterval(updateRate_Hz); + _timer.setSingleShot(false); + _timer.setInterval(updateRate_Hz); - // Connect capturing to the timeout signal of the timer - connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); + // Connect capturing to the timeout signal of the timer + connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); } const Image & FramebufferWrapper::getScreenshot() @@ -21,12 +21,12 @@ const Image & FramebufferWrapper::getScreenshot() void FramebufferWrapper::start() { - _timer.start(); + _timer.start(); } void FramebufferWrapper::stop() { - _timer.stop(); + _timer.stop(); } void FramebufferWrapper::capture() diff --git a/src/hyperion-osx/OsxWrapper.cpp b/src/hyperion-osx/OsxWrapper.cpp index eb9256c2..26544153 100644 --- a/src/hyperion-osx/OsxWrapper.cpp +++ b/src/hyperion-osx/OsxWrapper.cpp @@ -3,14 +3,14 @@ #include "OsxWrapper.h" OsxWrapper::OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : - _timer(this), - _grabber(display,grabWidth, grabHeight) + _timer(this), + _grabber(display,grabWidth, grabHeight) { - _timer.setSingleShot(false); - _timer.setInterval(updateRate_Hz); + _timer.setSingleShot(false); + _timer.setInterval(updateRate_Hz); - // Connect capturing to the timeout signal of the timer - connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); + // Connect capturing to the timeout signal of the timer + connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); } const Image & OsxWrapper::getScreenshot() diff --git a/src/hyperion-v4l2/PixelFormatParameter.h b/src/hyperion-v4l2/PixelFormatParameter.h index 3ebccfc7..e789f96c 100644 --- a/src/hyperion-v4l2/PixelFormatParameter.h +++ b/src/hyperion-v4l2/PixelFormatParameter.h @@ -10,34 +10,34 @@ using namespace vlofgren; typedef vlofgren::PODParameter PixelFormatParameter; namespace vlofgren { - /// Translates a string (as passed on the commandline) to a pixel format - /// - /// @param[in] s The string (as passed on the commandline) - /// @return The pixel format - /// @throws Parameter::ParameterRejected If the string did not result in a pixel format - template<> - PixelFormat PixelFormatParameter::validate(const std::string& s) throw (Parameter::ParameterRejected) - { - QString input = QString::fromStdString(s).toLower(); + /// Translates a string (as passed on the commandline) to a pixel format + /// + /// @param[in] s The string (as passed on the commandline) + /// @return The pixel format + /// @throws Parameter::ParameterRejected If the string did not result in a pixel format + template<> + PixelFormat PixelFormatParameter::validate(const std::string& s) throw (Parameter::ParameterRejected) + { + QString input = QString::fromStdString(s).toLower(); - if (input == "yuyv") - { - return PIXELFORMAT_YUYV; - } - else if (input == "uyvy") - { - return PIXELFORMAT_UYVY; - } - else if (input == "rgb32") - { - return PIXELFORMAT_RGB32; - } - else if (input == "no-change") - { - return PIXELFORMAT_NO_CHANGE; - } + if (input == "yuyv") + { + return PIXELFORMAT_YUYV; + } + else if (input == "uyvy") + { + return PIXELFORMAT_UYVY; + } + else if (input == "rgb32") + { + return PIXELFORMAT_RGB32; + } + else if (input == "no-change") + { + return PIXELFORMAT_NO_CHANGE; + } - throw Parameter::ParameterRejected("Invalid value for pixel format. Valid values are: YUYV, UYVY, RGB32, and NO-CHANGE"); - return PIXELFORMAT_NO_CHANGE; - } + throw Parameter::ParameterRejected("Invalid value for pixel format. Valid values are: YUYV, UYVY, RGB32, and NO-CHANGE"); + return PIXELFORMAT_NO_CHANGE; + } } diff --git a/src/hyperion-v4l2/ScreenshotHandler.cpp b/src/hyperion-v4l2/ScreenshotHandler.cpp index 0f9daaef..6acd6cc3 100644 --- a/src/hyperion-v4l2/ScreenshotHandler.cpp +++ b/src/hyperion-v4l2/ScreenshotHandler.cpp @@ -6,7 +6,7 @@ #include "ScreenshotHandler.h" ScreenshotHandler::ScreenshotHandler(const std::string & filename) : - _filename(filename) + _filename(filename) { } diff --git a/src/hyperion-v4l2/hyperion-v4l2.cpp b/src/hyperion-v4l2/hyperion-v4l2.cpp index 22add6c7..747bd4a5 100644 --- a/src/hyperion-v4l2/hyperion-v4l2.cpp +++ b/src/hyperion-v4l2/hyperion-v4l2.cpp @@ -31,150 +31,150 @@ using namespace vlofgren; // save the image as screenshot void saveScreenshot(void *, const Image & image) { - // store as PNG - QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); - pngImage.save("screenshot.png"); + // store as PNG + QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); + pngImage.save("screenshot.png"); } int main(int argc, char** argv) { std::cout - << "hyperion-v4l2:" << std::endl - << "\tversion : " << HYPERION_VERSION_ID << std::endl - << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; + << "hyperion-v4l2:" << std::endl + << "\tversion : " << HYPERION_VERSION_ID << std::endl + << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; - QCoreApplication app(argc, argv); + QCoreApplication app(argc, argv); - // force the locale - setlocale(LC_ALL, "C"); - QLocale::setDefault(QLocale::c()); + // force the locale + setlocale(LC_ALL, "C"); + QLocale::setDefault(QLocale::c()); - // register the image type to use in signals - qRegisterMetaType>("Image"); + // register the image type to use in signals + qRegisterMetaType>("Image"); - try - { - // create the option parser and initialize all parameters - OptionsParser optionParser("V4L capture application for Hyperion"); - ParameterSet & parameters = optionParser.getParameters(); + try + { + // create the option parser and initialize all parameters + OptionsParser optionParser("V4L capture application for Hyperion"); + ParameterSet & parameters = optionParser.getParameters(); - StringParameter & argDevice = parameters.add ('d', "device", "The device to use [default: /dev/video0]"); - VideoStandardParameter & argVideoStandard = parameters.add('v', "video-standard", "The used video standard. Valid values are PAL or NTSC (optional)"); - PixelFormatParameter & argPixelFormat = parameters.add (0x0, "pixel-format", "The use pixel format. Valid values are YUYV, UYVY, and RGB32 (optional)"); - IntParameter & argInput = parameters.add (0x0, "input", "Input channel (optional)"); - IntParameter & argWidth = parameters.add (0x0, "width", "Try to set the width of the video input (optional)"); - IntParameter & argHeight = parameters.add (0x0, "height", "Try to set the height of the video input (optional)"); - IntParameter & argCropWidth = parameters.add (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]"); - IntParameter & argCropHeight = parameters.add (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]"); - IntParameter & argCropLeft = parameters.add (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)"); - IntParameter & argCropRight = parameters.add (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)"); - IntParameter & argCropTop = parameters.add (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)"); - IntParameter & argCropBottom = parameters.add (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)"); - IntParameter & argSizeDecimation = parameters.add ('s', "size-decimator", "Decimation factor for the output size [default=1]"); - IntParameter & argFrameDecimation = parameters.add ('f', "frame-decimator", "Decimation factor for the video frames [default=1]"); - SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); - DoubleParameter & argSignalThreshold = parameters.add ('t', "signal-threshold", "The signal threshold for detecting the presence of a signal. Value should be between 0.0 and 1.0."); - DoubleParameter & argRedSignalThreshold = parameters.add (0x0, "red-threshold", "The red signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)"); - DoubleParameter & argGreenSignalThreshold = parameters.add (0x0, "green-threshold", "The green signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)"); - DoubleParameter & argBlueSignalThreshold = parameters.add (0x0, "blue-threshold", "The blue signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)"); - SwitchParameter<> & arg3DSBS = parameters.add> (0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side"); - SwitchParameter<> & arg3DTAB = parameters.add> (0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom"); - StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); - IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); - SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); - SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); + StringParameter & argDevice = parameters.add ('d', "device", "The device to use [default: /dev/video0]"); + VideoStandardParameter & argVideoStandard = parameters.add('v', "video-standard", "The used video standard. Valid values are PAL or NTSC (optional)"); + PixelFormatParameter & argPixelFormat = parameters.add (0x0, "pixel-format", "The use pixel format. Valid values are YUYV, UYVY, and RGB32 (optional)"); + IntParameter & argInput = parameters.add (0x0, "input", "Input channel (optional)"); + IntParameter & argWidth = parameters.add (0x0, "width", "Try to set the width of the video input (optional)"); + IntParameter & argHeight = parameters.add (0x0, "height", "Try to set the height of the video input (optional)"); + IntParameter & argCropWidth = parameters.add (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]"); + IntParameter & argCropHeight = parameters.add (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]"); + IntParameter & argCropLeft = parameters.add (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)"); + IntParameter & argCropRight = parameters.add (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)"); + IntParameter & argCropTop = parameters.add (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)"); + IntParameter & argCropBottom = parameters.add (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)"); + IntParameter & argSizeDecimation = parameters.add ('s', "size-decimator", "Decimation factor for the output size [default=1]"); + IntParameter & argFrameDecimation = parameters.add ('f', "frame-decimator", "Decimation factor for the video frames [default=1]"); + SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); + DoubleParameter & argSignalThreshold = parameters.add ('t', "signal-threshold", "The signal threshold for detecting the presence of a signal. Value should be between 0.0 and 1.0."); + DoubleParameter & argRedSignalThreshold = parameters.add (0x0, "red-threshold", "The red signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)"); + DoubleParameter & argGreenSignalThreshold = parameters.add (0x0, "green-threshold", "The green signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)"); + DoubleParameter & argBlueSignalThreshold = parameters.add (0x0, "blue-threshold", "The blue signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)"); + SwitchParameter<> & arg3DSBS = parameters.add> (0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side"); + SwitchParameter<> & arg3DTAB = parameters.add> (0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom"); + StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); + IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); + SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); + SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); - // set defaults - argDevice.setDefault("/dev/video0"); - argVideoStandard.setDefault(VIDEOSTANDARD_NO_CHANGE); - argPixelFormat.setDefault(PIXELFORMAT_NO_CHANGE); - argInput.setDefault(-1); - argWidth.setDefault(-1); - argHeight.setDefault(-1); - argCropWidth.setDefault(0); - argCropHeight.setDefault(0); - argSizeDecimation.setDefault(1); - argFrameDecimation.setDefault(1); - argAddress.setDefault("127.0.0.1:19445"); - argPriority.setDefault(800); - argSignalThreshold.setDefault(-1); + // set defaults + argDevice.setDefault("/dev/video0"); + argVideoStandard.setDefault(VIDEOSTANDARD_NO_CHANGE); + argPixelFormat.setDefault(PIXELFORMAT_NO_CHANGE); + argInput.setDefault(-1); + argWidth.setDefault(-1); + argHeight.setDefault(-1); + argCropWidth.setDefault(0); + argCropHeight.setDefault(0); + argSizeDecimation.setDefault(1); + argFrameDecimation.setDefault(1); + argAddress.setDefault("127.0.0.1:19445"); + argPriority.setDefault(800); + argSignalThreshold.setDefault(-1); - // parse all options - optionParser.parse(argc, const_cast(argv)); + // parse all options + optionParser.parse(argc, const_cast(argv)); - // check if we need to display the usage. exit if we do. - if (argHelp.isSet()) - { - optionParser.usage(); - return 0; - } + // check if we need to display the usage. exit if we do. + if (argHelp.isSet()) + { + optionParser.usage(); + return 0; + } - // cropping values if not defined - if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue()); - if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue()); - if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue()); - if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue()); + // cropping values if not defined + if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue()); + if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue()); + if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue()); + if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue()); - // initialize the grabber - V4L2Grabber grabber( - argDevice.getValue(), - argInput.getValue(), - argVideoStandard.getValue(), - argPixelFormat.getValue(), - argWidth.getValue(), - argHeight.getValue(), - std::max(1, argFrameDecimation.getValue()), - std::max(1, argSizeDecimation.getValue()), - std::max(1, argSizeDecimation.getValue())); + // initialize the grabber + V4L2Grabber grabber( + argDevice.getValue(), + argInput.getValue(), + argVideoStandard.getValue(), + argPixelFormat.getValue(), + argWidth.getValue(), + argHeight.getValue(), + std::max(1, argFrameDecimation.getValue()), + std::max(1, argSizeDecimation.getValue()), + std::max(1, argSizeDecimation.getValue())); - // set signal detection - grabber.setSignalThreshold( - std::min(1.0, std::max(0.0, argRedSignalThreshold.isSet() ? argRedSignalThreshold.getValue() : argSignalThreshold.getValue())), - std::min(1.0, std::max(0.0, argGreenSignalThreshold.isSet() ? argGreenSignalThreshold.getValue() : argSignalThreshold.getValue())), - std::min(1.0, std::max(0.0, argBlueSignalThreshold.isSet() ? argBlueSignalThreshold.getValue() : argSignalThreshold.getValue())), - 50); + // set signal detection + grabber.setSignalThreshold( + std::min(1.0, std::max(0.0, argRedSignalThreshold.isSet() ? argRedSignalThreshold.getValue() : argSignalThreshold.getValue())), + std::min(1.0, std::max(0.0, argGreenSignalThreshold.isSet() ? argGreenSignalThreshold.getValue() : argSignalThreshold.getValue())), + std::min(1.0, std::max(0.0, argBlueSignalThreshold.isSet() ? argBlueSignalThreshold.getValue() : argSignalThreshold.getValue())), + 50); - // set cropping values - grabber.setCropping( - std::max(0, argCropLeft.getValue()), - std::max(0, argCropRight.getValue()), - std::max(0, argCropTop.getValue()), - std::max(0, argCropBottom.getValue())); + // set cropping values + grabber.setCropping( + std::max(0, argCropLeft.getValue()), + std::max(0, argCropRight.getValue()), + std::max(0, argCropTop.getValue()), + std::max(0, argCropBottom.getValue())); - // set 3D mode if applicable - if (arg3DSBS.isSet()) - { - grabber.set3D(VIDEO_3DSBS); - } - else if (arg3DTAB.isSet()) - { - grabber.set3D(VIDEO_3DTAB); - } + // set 3D mode if applicable + if (arg3DSBS.isSet()) + { + grabber.set3D(VIDEO_3DSBS); + } + else if (arg3DTAB.isSet()) + { + grabber.set3D(VIDEO_3DTAB); + } - // run the grabber - if (argScreenshot.isSet()) - { - ScreenshotHandler handler("screenshot.png"); - QObject::connect(&grabber, SIGNAL(newFrame(Image)), &handler, SLOT(receiveImage(Image))); - grabber.start(); - QCoreApplication::exec(); - grabber.stop(); - } - else - { - ProtoConnectionWrapper handler(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); - QObject::connect(&grabber, SIGNAL(newFrame(Image)), &handler, SLOT(receiveImage(Image))); - grabber.start(); - QCoreApplication::exec(); - grabber.stop(); - } - } - catch (const std::runtime_error & e) - { - // An error occured. Display error and quit - std::cerr << e.what() << std::endl; - return 1; - } + // run the grabber + if (argScreenshot.isSet()) + { + ScreenshotHandler handler("screenshot.png"); + QObject::connect(&grabber, SIGNAL(newFrame(Image)), &handler, SLOT(receiveImage(Image))); + grabber.start(); + QCoreApplication::exec(); + grabber.stop(); + } + else + { + ProtoConnectionWrapper handler(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); + QObject::connect(&grabber, SIGNAL(newFrame(Image)), &handler, SLOT(receiveImage(Image))); + grabber.start(); + QCoreApplication::exec(); + grabber.stop(); + } + } + catch (const std::runtime_error & e) + { + // An error occured. Display error and quit + std::cerr << e.what() << std::endl; + return 1; + } - return 0; + return 0; } diff --git a/src/hyperion-x11/X11Wrapper.cpp b/src/hyperion-x11/X11Wrapper.cpp index 8aa8fb49..e417a07b 100644 --- a/src/hyperion-x11/X11Wrapper.cpp +++ b/src/hyperion-x11/X11Wrapper.cpp @@ -3,39 +3,39 @@ #include "X11Wrapper.h" X11Wrapper::X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) : - _timer(this), - _grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation) + _timer(this), + _grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation) { - _timer.setSingleShot(false); - _timer.setInterval(grabInterval); + _timer.setSingleShot(false); + _timer.setInterval(grabInterval); - // Connect capturing to the timeout signal of the timer - connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); + // Connect capturing to the timeout signal of the timer + connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); } const Image & X11Wrapper::getScreenshot() { - const Image & screenshot = _grabber.grab(); - return screenshot; + const Image & screenshot = _grabber.grab(); + return screenshot; } void X11Wrapper::start() { - _timer.start(); + _timer.start(); } void X11Wrapper::stop() { - _timer.stop(); + _timer.stop(); } bool X11Wrapper::displayInit() { - return _grabber.Setup(); + return _grabber.Setup(); } void X11Wrapper::capture() { - const Image & screenshot = _grabber.grab(); - emit sig_screenshot(screenshot); + const Image & screenshot = _grabber.grab(); + emit sig_screenshot(screenshot); } diff --git a/src/hyperion-x11/X11Wrapper.h b/src/hyperion-x11/X11Wrapper.h index 26ccc796..b672c3a0 100644 --- a/src/hyperion-x11/X11Wrapper.h +++ b/src/hyperion-x11/X11Wrapper.h @@ -7,35 +7,35 @@ class X11Wrapper : public QObject { - Q_OBJECT + Q_OBJECT public: - X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation); + X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation); - const Image & getScreenshot(); + const Image & getScreenshot(); - /// - /// Starts the timed capturing of screenshots - /// - void start(); + /// + /// Starts the timed capturing of screenshots + /// + void start(); - void stop(); - - bool displayInit(); + void stop(); + + bool displayInit(); signals: - void sig_screenshot(const Image & screenshot); + void sig_screenshot(const Image & screenshot); private slots: - /// - /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot - /// signal. - /// - void capture(); + /// + /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot + /// signal. + /// + void capture(); private: - /// The QT timer to generate capture-publish events - QTimer _timer; + /// The QT timer to generate capture-publish events + QTimer _timer; - /// The grabber for creating screenshots - X11Grabber _grabber; + /// The grabber for creating screenshots + X11Grabber _grabber; }; diff --git a/src/hyperion-x11/hyperion-x11.cpp b/src/hyperion-x11/hyperion-x11.cpp index b7be000d..1c9f4d65 100644 --- a/src/hyperion-x11/hyperion-x11.cpp +++ b/src/hyperion-x11/hyperion-x11.cpp @@ -15,108 +15,108 @@ using namespace vlofgren; // save the image as screenshot void saveScreenshot(const char * filename, const Image & image) { - // store as PNG - QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); - pngImage.save(filename); + // store as PNG + QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); + pngImage.save(filename); } int main(int argc, char ** argv) { std::cout - << "hyperion-x11:" << std::endl - << "\tversion : " << HYPERION_VERSION_ID << std::endl - << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; + << "hyperion-x11:" << std::endl + << "\tversion : " << HYPERION_VERSION_ID << std::endl + << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; - QCoreApplication app(argc, argv); + QCoreApplication app(argc, argv); - try - { - // create the option parser and initialize all parameters - OptionsParser optionParser("X11 capture application for Hyperion"); - ParameterSet & parameters = optionParser.getParameters(); + try + { + // create the option parser and initialize all parameters + OptionsParser optionParser("X11 capture application for Hyperion"); + ParameterSet & parameters = optionParser.getParameters(); - IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default: 10]"); - SwitchParameter<> & argXGetImage = parameters.add> ('x', "xgetimage", "Use XGetImage instead of XRender"); - IntParameter & argCropWidth = parameters.add (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]"); - IntParameter & argCropHeight = parameters.add (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]"); - IntParameter & argCropLeft = parameters.add (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)"); - IntParameter & argCropRight = parameters.add (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)"); - IntParameter & argCropTop = parameters.add (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)"); - IntParameter & argCropBottom = parameters.add (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)"); - IntParameter & argSizeDecimation = parameters.add ('s', "size-decimator", "Decimation factor for the output size [default=8]"); - SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); - StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); - IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); - SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); - SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); + IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default: 10]"); + SwitchParameter<> & argXGetImage = parameters.add> ('x', "xgetimage", "Use XGetImage instead of XRender"); + IntParameter & argCropWidth = parameters.add (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]"); + IntParameter & argCropHeight = parameters.add (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]"); + IntParameter & argCropLeft = parameters.add (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)"); + IntParameter & argCropRight = parameters.add (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)"); + IntParameter & argCropTop = parameters.add (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)"); + IntParameter & argCropBottom = parameters.add (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)"); + IntParameter & argSizeDecimation = parameters.add ('s', "size-decimator", "Decimation factor for the output size [default=8]"); + SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); + StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); + IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); + SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); + SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); - // set defaults - argFps.setDefault(10); - argCropWidth.setDefault(0); - argCropHeight.setDefault(0); - argSizeDecimation.setDefault(8); - argAddress.setDefault("127.0.0.1:19445"); - argPriority.setDefault(800); + // set defaults + argFps.setDefault(10); + argCropWidth.setDefault(0); + argCropHeight.setDefault(0); + argSizeDecimation.setDefault(8); + argAddress.setDefault("127.0.0.1:19445"); + argPriority.setDefault(800); - // parse all options - optionParser.parse(argc, const_cast(argv)); + // parse all options + optionParser.parse(argc, const_cast(argv)); - // check if we need to display the usage. exit if we do. - if (argHelp.isSet()) - { - optionParser.usage(); - return 0; - } + // check if we need to display the usage. exit if we do. + if (argHelp.isSet()) + { + optionParser.usage(); + return 0; + } - // cropping values if not defined - if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue()); - if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue()); - if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue()); - if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue()); + // cropping values if not defined + if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue()); + if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue()); + if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue()); + if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue()); - // Create the X11 grabbing stuff - int grabInterval = 1000 / argFps.getValue(); - bool useXGetImage = argXGetImage.isSet(); - X11Wrapper x11Wrapper( - grabInterval, - useXGetImage, - argCropLeft.getValue(), - argCropRight.getValue(), - argCropTop.getValue(), - argCropBottom.getValue(), - argSizeDecimation.getValue(), // horizontal decimation - argSizeDecimation.getValue()); // vertical decimation + // Create the X11 grabbing stuff + int grabInterval = 1000 / argFps.getValue(); + bool useXGetImage = argXGetImage.isSet(); + X11Wrapper x11Wrapper( + grabInterval, + useXGetImage, + argCropLeft.getValue(), + argCropRight.getValue(), + argCropTop.getValue(), + argCropBottom.getValue(), + argSizeDecimation.getValue(), // horizontal decimation + argSizeDecimation.getValue()); // vertical decimation if (!x11Wrapper.displayInit()) return -1; - if (argScreenshot.isSet()) - { - // Capture a single screenshot and finish - const Image & screenshot = x11Wrapper.getScreenshot(); - saveScreenshot("screenshot.png", screenshot); - } - else - { - // Create the Proto-connection with hyperiond - ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); + if (argScreenshot.isSet()) + { + // Capture a single screenshot and finish + const Image & screenshot = x11Wrapper.getScreenshot(); + saveScreenshot("screenshot.png", screenshot); + } + else + { + // Create the Proto-connection with hyperiond + ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); - // Connect the screen capturing to the proto processing - QObject::connect(&x11Wrapper, SIGNAL(sig_screenshot(const Image &)), &protoWrapper, SLOT(receiveImage(Image))); + // Connect the screen capturing to the proto processing + QObject::connect(&x11Wrapper, SIGNAL(sig_screenshot(const Image &)), &protoWrapper, SLOT(receiveImage(Image))); - // Start the capturing - x11Wrapper.start(); + // Start the capturing + x11Wrapper.start(); - // Start the application - app.exec(); - } - } - catch (const std::runtime_error & e) - { - // An error occured. Display error and quit - std::cerr << e.what() << std::endl; - return -1; - } + // Start the application + app.exec(); + } + } + catch (const std::runtime_error & e) + { + // An error occured. Display error and quit + std::cerr << e.what() << std::endl; + return -1; + } - return 0; + return 0; } diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 00ab7a3f..c52e82ee 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -51,10 +51,8 @@ // JsonServer includes #include -#ifdef ENABLE_PROTOBUF // ProtoServer includes #include -#endif // BoblightServer includes #include @@ -208,7 +206,6 @@ int main(int argc, char** argv) std::cout << "INFO: Json server created and started on port " << jsonServer->getPort() << std::endl; } -#ifdef ENABLE_PROTOBUF // Create Proto server if configuration is present ProtoServer * protoServer = nullptr; if (config.isMember("protoServer")) @@ -217,7 +214,6 @@ int main(int argc, char** argv) protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); std::cout << "INFO: Proto server created and started on port " << protoServer->getPort() << std::endl; } -#endif // Create Boblight server if configuration is present BoblightServer * boblightServer = nullptr; @@ -254,9 +250,7 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), dispmanx, SLOT(setVideoMode(VideoMode))); } - #ifdef ENABLE_PROTOBUF QObject::connect(dispmanx, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); - #endif dispmanx->start(); std::cout << "INFO: Frame grabber created and started" << std::endl; @@ -297,9 +291,7 @@ int main(int argc, char** argv) grabberConfig.get("cropTop", 0).asInt(), grabberConfig.get("cropBottom", 0).asInt()); - #ifdef ENABLE_PROTOBUF QObject::connect(v4l2Grabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); - #endif v4l2Grabber->start(); std::cout << "INFO: V4L2 grabber created and started" << std::endl; @@ -331,9 +323,7 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), amlGrabber, SLOT(setVideoMode(VideoMode))); } - #ifdef ENABLE_PROTOBUF QObject::connect(amlGrabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); - #endif amlGrabber->start(); std::cout << "INFO: AMLOGIC grabber created and started" << std::endl; @@ -365,9 +355,7 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), fbGrabber, SLOT(setVideoMode(VideoMode))); } - #ifdef ENABLE_PROTOBUF QObject::connect(fbGrabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); - #endif fbGrabber->start(); std::cout << "INFO: Framebuffer grabber created and started" << std::endl; @@ -405,9 +393,7 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), osxGrabber, SLOT(setVideoMode(VideoMode))); } - #ifdef ENABLE_PROTOBUF QObject::connect(osxGrabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); - #endif osxGrabber->start(); std::cout << "INFO: OSX grabber created and started" << std::endl; @@ -445,9 +431,7 @@ int main(int argc, char** argv) #endif delete xbmcVideoChecker; delete jsonServer; -#ifdef ENABLE_PROTOBUF delete protoServer; -#endif delete boblightServer; // leave application From 019d4ba6d832bb0711f24c6e986f100b23fb2d21 Mon Sep 17 00:00:00 2001 From: tpmodding Date: Fri, 27 May 2016 11:16:42 +0200 Subject: [PATCH 29/63] Update LedDevicePhilipsHue.cpp Changed "isnan" to "std::isnan" Former-commit-id: 528f02452762fade16b84d17dc7692de9129559c --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index 464820bb..05d0a63d 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -105,10 +105,10 @@ CiColor PhilipsHueLight::rgbToCiColor(float red, float green, float blue) { // Convert to x,y space. float cx = X / (X + Y + Z); float cy = Y / (X + Y + Z); - if (isnan(cx)) { + if (std::isnan(cx)) { cx = 0.0f; } - if (isnan(cy)) { + if (std::isnan(cy)) { cy = 0.0f; } // Brightness is simply Y in the XYZ space. From a912a9469148125ffe6ac1c0e7d066e1de9b2c0d Mon Sep 17 00:00:00 2001 From: brindosch Date: Sat, 28 May 2016 00:26:41 +0200 Subject: [PATCH 30/63] add fw_script Former-commit-id: 95b5b420df99c3b7985a998c5c68d11549d493a3 --- bin/scripts/setup_hyperion_forward.sh | 165 ++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 bin/scripts/setup_hyperion_forward.sh diff --git a/bin/scripts/setup_hyperion_forward.sh b/bin/scripts/setup_hyperion_forward.sh new file mode 100644 index 00000000..4fe45218 --- /dev/null +++ b/bin/scripts/setup_hyperion_forward.sh @@ -0,0 +1,165 @@ +#!/bin/bash +# Script to add a second or more hyperion instance(s) to the corresponding system service + +# Make sure /sbin is on the path (for service to find sub scripts) +PATH="/sbin:$PATH" + +#Check, if script is running as root +if [ $(id -u) != 0 ]; then + echo '---> Critical Error: Please run the script as root (sudo sh ./setup_hyperion_forward.sh) -> abort' + exit 1 +fi + +#Welcome message +echo '*******************************************************************************' +echo 'This setup script will duplicate the hyperion service' +echo 'Choose the name(s) for one or more config files - one service for each config' +echo 'Created by brindosch - hyperion-project.org - the official Hyperion source.' +echo '*******************************************************************************' + +#Prompt for confirmation to proceed +while true +do +echo -n "---> Do you really want to proceed? (y or n) :" +read CONFIRM +case $CONFIRM in +y|Y|YES|yes|Yes) break ;; +n|N|no|NO|No) +echo "---> Aborting - you entered \"$CONFIRM\"" +exit +;; +*) echo "-> Please enter only y or n" +esac +done +echo "---> You entered \"$CONFIRM\". We will proceed!" +echo "" + +#Check which system we are on +OS_OPENELEC=`grep -m1 -c 'OpenELEC\|RasPlex\|LibreELEC' /etc/issue` +USE_SYSTEMD=`grep -m1 -c systemd /proc/1/comm` +USE_INITCTL=`which /sbin/initctl | wc -l` +USE_SERVICE=`which /usr/sbin/service | wc -l` + +#Setting up the paths to service files +if [ $USE_INITCTL -eq 1 ]; then + SERVICEPATH=/etc/init +elif [ $OS_OPENELEC -eq 1 ]; then + SERVICEPATH=/storage/.config +elif [ $USE_SYSTEMD -eq 1 ]; then + SERVICEPATH=/etc/systemd/system +elif [ $USE_SERVICE -eq 1 ]; then + SERVICEPATH/etc/init.d +fi + +#Setting up the default PROTO/JSON ports +JSONPORT=19444 +PROTOPORT=19445 +# and service count +SERVICEC=1 + +#Setting up the paths to config files +if [ $OS_OPENELEC -eq 1 ]; then + CONFIGPATH=/storage/.config +else CONFIGPATH=/opt/hyperion/config +fi + +#Ask the user for some informations regarding the setup +echo "---> Please enter the config name(s) you want to create" +echo "---> Information: One name creates one service and two names two services etc" +echo '---> Please enter them seperated with a space in a one line row!' +echo '---> example: hyperion.philipshue_1.json hyperion.AtmoOrb_2.json hypthreeconf.json' +echo '---> In any case, add ".json" at the end of each file name' +read -p 'Config file name(s): ' FILENAMES +echo '---> Thank you, we will modify your Hyperion installation now' +sleep 2 + +#Processing input +set $FILENAMES +FWCOUNT=${#} + +#Convert all old config file paths to make sure this script is working (default for new installs with 1.02.0 and higher) +if [ $USE_INITCTL -eq 1 ]; then + sed -i "s|/etc/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEPATH/hyperion.conf +elif [ $OS_OPENELEC -eq 1 ]; then + sleep 0 +elif [ $USE_SYSTEMD -eq 1 ]; then + sed -i "s|/etc/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEPATH/hyperion.service +elif [ $USE_SERVICE -eq 1 ]; then + sed -i "s|/etc/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEPATH/hyperion +fi + +#Processing service files +if [ $USE_INITCTL -eq 1 ]; then + echo "---> Initctl detected, processing service files" + while [ $SERVICEC -le $FWCOUNT ]; do + echo "Processing service ${SERVICEC}: \"hyperion_fw${SERVICEC}.conf\"" + if [ -e "${SERVICEPATH}/hyperion_fw${SERVICEC}.conf" ]; then + echo "Service was already created - skipped" + echo "Input \"${1}\" was skipped" + else + echo "Create ${SERVICEPATH}/hyperion_fw${SERVICEC}.conf" + cp -s $SERVICEPATH/hyperion.conf $SERVICEPATH/hyperion_fw$SERVICEC.conf + echo "Config name changed to \"${1}\" inside \"hyperion_fw${SERVICEC}.conf\"" + sed -i "s/hyperion.config.json/$1/g" $SERVICEPATH/hyperion_fw$SERVICEC.conf + initctl reload-configuration + fi + shift + SERVICEC=$((SERVICEC + 1)) + done +elif [ $OS_OPENELEC -eq 1 ]; then + echo "---> OE/LE detected, processing autostart.sh" + while [ $SERVICEC -le $FWCOUNT ]; do + echo "${SERVICEC}. processing OE autostart.sh entry \"${1}\"" + OE=`grep -m1 -c ${1} $SERVICEPATH/autostart.sh` + if [ $OE -eq 0 ]; then + echo "Add config name \"${1}\" to \"autostart.sh\"" + echo "/storage/hyperion/bin/hyperiond.sh /storage/.config/${1} > /storage/logfiles/hyperion_fw${SERVICEC}.log 2>&1 &" >> /storage/.config/autostart.sh + else + echo "\"${1}\" was already added - skipped" + fi + shift + SERVICEC=$((SERVICEC + 1)) + done +elif [ $USE_SYSTEMD -eq 1 ]; then + echo "---> Systemd detected, processing service files" + while [ $SERVICEC -le $FWCOUNT ]; do + echo "Processing service ${SERVICEC}: \"hyperion_fw${SERVICEC}.service\"" + if [ -e "${SERVICEPATH}/hyperion_fw${SERVICEC}.service" ]; then + echo "Service was already created - skipped" + echo "Input \"${1}\" was skipped" + else + echo "Create ${SERVICEPATH}/hyperion_fw${SERVICEC}.service" + cp -s $SERVICEPATH/hyperion.service $SERVICEPATH/hyperion_fw$SERVICEC.service + echo "Config name changed to \"${1}\" inside \"hyperion_fw${SERVICEC}.service\"" + sed -i "s/hyperion.config.json/$1/g" $SERVICEPATH/hyperion_fw$SERVICEC.service + systemctl -q enable hyperion_fw$SERVICEC.service + fi + shift + SERVICEC=$((SERVICEC + 1)) + done +elif [ $USE_SERVICE -eq 1 ]; then + echo "---> Init.d detected, processing service files" + while [ $SERVICEC -le $FWCOUNT ]; do + echo "Processing service ${SERVICEC}: \"hyperion_fw${SERVICEC}\"" + if [ -e "${SERVICEPATH}/hyperion_fw${SERVICEC}" ]; then + echo "Service was already created - skipped" + echo "Input \"${1}\" was skipped" + else + echo "Create ${SERVICEPATH}/hyperion_fw${SERVICEC}" + cp -s $SERVICEPATH/hyperion $SERVICEPATH/hyperion_fw$SERVICEC + echo "Config name changed to \"${1}\" inside \"hyperion_fw${SERVICEC}\"" + sed -i "s/hyperion.config.json/$1/g" $SERVICEPATH/hyperion_fw$SERVICEC + update-rc.d hyperion_fw$SERVICEC defaults 98 02 + fi + shift + SERVICEC=$((SERVICEC + 1)) + done +fi + +#Service creation done +echo '*******************************************************************************' +echo 'Script done all actions - all input processed' +echo 'Now upload your configuration(s) with HyperCon at the SSH Tab' +echo 'All created Hyperion services will start with your chosen confignames' +echo 'Wiki: wiki.hyperion-project.org Webpage: www.hyperion-project.org' +echo '*******************************************************************************' \ No newline at end of file From 71a4d0ba78e016f0fe66bc2df8e54d0cf2d06d8f Mon Sep 17 00:00:00 2001 From: redPanther Date: Mon, 30 May 2016 22:38:40 +0200 Subject: [PATCH 31/63] start multiple hyperions (#663) * start multiple hyperions. add a config for every hyperiond to start. * spawned hyperiond will exit when parent hyperiond exits, needed for propper function with service script. this should work, but must be refectored asap when hyperiond understands commandline params * add optionParser to hyperiond. multi daemon: exit when any child/parent dies * cleanup * refactor cosmetics for hyperiond Former-commit-id: 3b99c78661550704256f0d5887680e92cb3ddda3 --- src/hyperiond/CMakeLists.txt | 1 + src/hyperiond/hyperiond.cpp | 255 ++++++++++++++++++++++++----------- 2 files changed, 178 insertions(+), 78 deletions(-) diff --git a/src/hyperiond/CMakeLists.txt b/src/hyperiond/CMakeLists.txt index 2e214eee..ed72cff0 100644 --- a/src/hyperiond/CMakeLists.txt +++ b/src/hyperiond/CMakeLists.txt @@ -3,6 +3,7 @@ add_executable(hyperiond hyperiond.cpp) target_link_libraries(hyperiond + getoptPlusPlus hyperion xbmcvideochecker effectengine diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index c52e82ee..398a6770 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -2,6 +2,7 @@ #include #include #include +#include // QT includes #include @@ -9,6 +10,9 @@ #include #include +// getoptPlusPLus includes +#include + // config includes #include "HyperionConfig.h" @@ -56,6 +60,9 @@ // BoblightServer includes #include +#include + +using namespace vlofgren; void signal_handler(const int signum) { @@ -65,6 +72,7 @@ void signal_handler(const int signum) signal(signum, SIG_DFL); } + Json::Value loadConfig(const std::string & configFile) { // make sure the resources are loaded (they may be left out after static linking) @@ -89,47 +97,20 @@ Json::Value loadConfig(const std::string & configFile) return jsonConfig; } -int main(int argc, char** argv) + +void startNewHyperion(int parentPid, std::string hyperionFile, std::string configFile) { - std::cout - << "Hyperion Ambilight Deamon" << std::endl - << "\tVersion : " << HYPERION_VERSION_ID << std::endl - << "\tBuild Time: " << __DATE__ << " " << __TIME__ << std::endl; - - // Initialising QCoreApplication - QCoreApplication app(argc, argv); - - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); - - // force the locale - setlocale(LC_ALL, "C"); - QLocale::setDefault(QLocale::c()); - - if (argc < 2) + if ( fork() == 0 ) { - std::cout << "ERROR: Missing required configuration file. Usage:" << std::endl; - std::cout << "hyperiond [config.file]" << std::endl; - return 1; + sleep(3); + execl(hyperionFile.c_str(), hyperionFile.c_str(), "--parent", QString::number(parentPid).toStdString().c_str(), configFile.c_str(), NULL); + exit(0); } +} - int argvId = 1; - for ( int i=1; istart(); std::cout << "INFO: Kodi checker created and started" << std::endl; } +} -// ---- network services ----- - +void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonServer* jsonServer, ProtoServer* protoServer, BoblightServer* boblightServer) +{ // Create Json server if configuration is present - JsonServer * jsonServer = nullptr; if (config.isMember("jsonServer")) { const Json::Value & jsonServerConfig = config["jsonServer"]; @@ -207,7 +191,6 @@ int main(int argc, char** argv) } // Create Proto server if configuration is present - ProtoServer * protoServer = nullptr; if (config.isMember("protoServer")) { const Json::Value & protoServerConfig = config["protoServer"]; @@ -216,19 +199,18 @@ int main(int argc, char** argv) } // Create Boblight server if configuration is present - BoblightServer * boblightServer = nullptr; if (config.isMember("boblightServer")) { const Json::Value & boblightServerConfig = config["boblightServer"]; boblightServer = new BoblightServer(&hyperion, boblightServerConfig.get("priority",900).asInt(), boblightServerConfig["port"].asUInt()); std::cout << "INFO: Boblight server created and started on port " << boblightServer->getPort() << std::endl; } - -// ---- grabber ----- +} #ifdef ENABLE_DISPMANX +void startGrabberDispmanx(const Json::Value &config, Hyperion &hyperion, ProtoServer * protoServer, XBMCVideoChecker* xbmcVideoChecker, DispmanxWrapper * dispmanx) +{ // Construct and start the frame-grabber if the configuration is present - DispmanxWrapper * dispmanx = nullptr; if (config.isMember("framegrabber")) { const Json::Value & frameGrabberConfig = config["framegrabber"]; @@ -255,18 +237,13 @@ int main(int argc, char** argv) dispmanx->start(); std::cout << "INFO: Frame grabber created and started" << std::endl; } -#else -#if !defined(ENABLE_OSX) && !defined(ENABLE_FB) - if (config.isMember("framegrabber")) - { - std::cerr << "ERRROR: The dispmanx framegrabber can not be instantiated, because it has been left out from the build" << std::endl; - } -#endif +} #endif #ifdef ENABLE_V4L2 +void startGrabberV4L2(const Json::Value &config, Hyperion &hyperion, ProtoServer * protoServer, V4L2Wrapper * v4l2Grabber ) +{ // construct and start the v4l2 grabber if the configuration is present - V4L2Wrapper * v4l2Grabber = nullptr; if (config.isMember("grabber-v4l2")) { const Json::Value & grabberConfig = config["grabber-v4l2"]; @@ -296,17 +273,14 @@ int main(int argc, char** argv) v4l2Grabber->start(); std::cout << "INFO: V4L2 grabber created and started" << std::endl; } -#else - if (config.isMember("grabber-v4l2")) - { - std::cerr << "ERROR: The v4l2 grabber can not be instantiated, because it has been left out from the build" << std::endl; - } +} #endif #ifdef ENABLE_AMLOGIC +void startGrabberAmlogic(const Json::Value &config, Hyperion &hyperion, ProtoServer * protoServer, XBMCVideoChecker* xbmcVideoChecker, AmlogicWrapper * amlGrabber) +{ // Construct and start the framebuffer grabber if the configuration is present - AmlogicWrapper * amlGrabber = nullptr; if (config.isMember("amlgrabber")) { const Json::Value & grabberConfig = config["amlgrabber"]; @@ -328,16 +302,14 @@ int main(int argc, char** argv) amlGrabber->start(); std::cout << "INFO: AMLOGIC grabber created and started" << std::endl; } -#else - if (config.isMember("amlgrabber")) - { - std::cerr << "ERROR: The AMLOGIC grabber can not be instantiated, because it has been left out from the build" << std::endl; - } +} #endif + #ifdef ENABLE_FB +void startGrabberFramebuffer(const Json::Value &config, Hyperion &hyperion, ProtoServer * protoServer, XBMCVideoChecker* xbmcVideoChecker, FramebufferWrapper * fbGrabber) +{ // Construct and start the framebuffer grabber if the configuration is present - FramebufferWrapper * fbGrabber = nullptr; if (config.isMember("framebuffergrabber") || config.isMember("framegrabber")) { const Json::Value & grabberConfig = config.isMember("framebuffergrabber")? config["framebuffergrabber"] : config["framegrabber"]; @@ -360,22 +332,14 @@ int main(int argc, char** argv) fbGrabber->start(); std::cout << "INFO: Framebuffer grabber created and started" << std::endl; } -#else - if (config.isMember("framebuffergrabber")) - { - std::cerr << "ERROR: The framebuffer grabber can not be instantiated, because it has been left out from the build" << std::endl; - } -#if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX) - else if (config.isMember("framegrabber")) - { - std::cerr << "ERROR: The framebuffer grabber can not be instantiated, because it has been left out from the build" << std::endl; - } -#endif +} #endif + #ifdef ENABLE_OSX +void startGrabberOsx(const Json::Value &config, Hyperion &hyperion, ProtoServer * protoServer, XBMCVideoChecker* xbmcVideoChecker, OsxWrapper * osxGrabber) +{ // Construct and start the osx grabber if the configuration is present - OsxWrapper * osxGrabber = nullptr; if (config.isMember("osxgrabber") || config.isMember("framegrabber")) { const Json::Value & grabberConfig = config.isMember("osxgrabber")? config["osxgrabber"] : config["framegrabber"]; @@ -398,6 +362,141 @@ int main(int argc, char** argv) osxGrabber->start(); std::cout << "INFO: OSX grabber created and started" << std::endl; } +} +#endif + +int main(int argc, char** argv) +{ + std::cout + << "Hyperion Ambilight Deamon (" << getpid() << ")" << std::endl + << "\tVersion : " << HYPERION_VERSION_ID << std::endl + << "\tBuild Time: " << __DATE__ << " " << __TIME__ << std::endl; + + // Initialising QCoreApplication + QCoreApplication app(argc, argv); + + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + signal(SIGCHLD, signal_handler); + + // force the locale + setlocale(LC_ALL, "C"); + QLocale::setDefault(QLocale::c()); + + OptionsParser optionParser("X11 capture application for Hyperion"); + ParameterSet & parameters = optionParser.getParameters(); + + IntParameter & argParentPid = parameters.add (0x0, "parent", "pid of parent hyperiond"); + + argParentPid.setDefault(0); + optionParser.parse(argc, const_cast(argv)); + const std::vector configFiles = optionParser.getFiles(); + + if (configFiles.size() == 0) + { + std::cout << "ERROR: Missing required configuration file. Usage:" << std::endl; + std::cout << "hyperiond [config.file ...]" << std::endl; + return 1; + } + + + if (argParentPid.getValue() > 0 ) + { + std::cout << "hyperiond client, parent is pid " << argParentPid.getValue() << std::endl; + prctl(PR_SET_PDEATHSIG, SIGHUP); + } + + int argvId = -1; + for(size_t idx=0; idx < configFiles.size(); idx++) { + if ( QFile::exists(configFiles[idx].c_str())) + { + if (argvId < 0) argvId=idx; + else startNewHyperion(getpid(), argv[0], configFiles[idx].c_str()); + } + } + + if ( argvId < 0) + { + std::cout << "ERROR: No valid config found " << std::endl; + return 1; + } + + const std::string configFile = configFiles[argvId]; + std::cout << "INFO: Selected configuration file: " << configFile.c_str() << std::endl; + const Json::Value config = loadConfig(configFile); + + Hyperion hyperion(config); + std::cout << "INFO: Hyperion started and initialised" << std::endl; + + + startBootsequence(config, hyperion); + + XBMCVideoChecker * xbmcVideoChecker = nullptr; + startXBMCVideoChecker(config, xbmcVideoChecker); + + // ---- network services ----- + JsonServer * jsonServer = nullptr; + ProtoServer * protoServer = nullptr; + BoblightServer * boblightServer = nullptr; + startNetworkServices(config, hyperion, jsonServer, protoServer, boblightServer); + + +// ---- grabber ----- + +#ifdef ENABLE_DISPMANX + DispmanxWrapper * dispmanx = nullptr; + startGrabberDispmanx(config, hyperion, protoServer, xbmcVideoChecker, dispmanx); +#else +#if !defined(ENABLE_OSX) && !defined(ENABLE_FB) + if (config.isMember("framegrabber")) + { + std::cerr << "ERRROR: The dispmanx framegrabber can not be instantiated, because it has been left out from the build" << std::endl; + } +#endif +#endif + +#ifdef ENABLE_V4L2 + V4L2Wrapper * v4l2Grabber = nullptr; + startGrabberV4L2(config, hyperion, protoServer, v4l2Grabber); +#else + if (config.isMember("grabber-v4l2")) + { + std::cerr << "ERROR: The v4l2 grabber can not be instantiated, because it has been left out from the build" << std::endl; + } +#endif + +#ifdef ENABLE_AMLOGIC + // Construct and start the framebuffer grabber if the configuration is present + AmlogicWrapper * amlGrabber = nullptr; + startGrabberAmlogic(config, hyperion, protoServer, xbmcVideoChecker, amlGrabber); +#else + if (config.isMember("amlgrabber")) + { + std::cerr << "ERROR: The AMLOGIC grabber can not be instantiated, because it has been left out from the build" << std::endl; + } +#endif + +#ifdef ENABLE_FB + // Construct and start the framebuffer grabber if the configuration is present + FramebufferWrapper * fbGrabber = nullptr; + startGrabberFramebuffer(config, hyperion, protoServer, xbmcVideoChecker, fbGrabber); +#else + if (config.isMember("framebuffergrabber")) + { + std::cerr << "ERROR: The framebuffer grabber can not be instantiated, because it has been left out from the build" << std::endl; + } +#if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX) + else if (config.isMember("framegrabber")) + { + std::cerr << "ERROR: The framebuffer grabber can not be instantiated, because it has been left out from the build" << std::endl; + } +#endif +#endif + +#ifdef ENABLE_OSX + // Construct and start the osx grabber if the configuration is present + OsxWrapper * osxGrabber = nullptr; + startGrabberDispmanx(config, hyperion, protoServer, xbmcVideoChecker, osxGrabber); #else if (config.isMember("osxgrabber")) { From 23042ba07cdd017d7d71517496ed70764344e9dd Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Mon, 30 May 2016 22:39:12 +0200 Subject: [PATCH 32/63] Update Json Interface (Active LED Color) (#664) * add getCurrentPriority * add getCurrentPriority * Update active led color Former-commit-id: 0e6b828991fdf51d2ec859d3836ce4f976dfd88c --- include/hyperion/Hyperion.h | 8 ++- libsrc/hyperion/Hyperion.cpp | 5 ++ libsrc/jsonserver/JsonClientConnection.cpp | 68 ++++++++++++++++++---- 3 files changed, 69 insertions(+), 12 deletions(-) diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index aaf5bb87..34b053a5 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -78,7 +78,13 @@ public: /// Returns the number of attached leds /// unsigned getLedCount() const; - + + /// + /// Returns the current priority + /// + /// @return The current priority + /// + int getCurrentPriority() const; /// /// Returns a list of active priorities /// diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 9c871818..aefa0607 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -819,6 +819,11 @@ void Hyperion::clearall() _effectEngine->allChannelsCleared(); } +int Hyperion::getCurrentPriority() const +{ + return _muxer.getCurrentPriority(); +} + QList Hyperion::getActivePriorities() const { return _muxer.getPriorities(); diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index b6471355..2f5b13a9 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -1,6 +1,7 @@ // system includes #include #include +#include // stl includes #include @@ -530,19 +531,64 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &) activeEffects.append(activeEffect); } - // collect active led colors - Json::Value & activeLedColors = info["activeLedColors"] = Json::Value(Json::arrayValue); - foreach (int priority, activePriorities) { - const Hyperion::InputInfo & priorityInfo = _hyperion->getPriorityInfo(priority); - int i=0; + //////////////////////////////////// + // collect active static led color// + //////////////////////////////////// + + // create New JSON Array Value "activeLEDColor" + Json::Value & activeLedColors = info["activeLedColor"] = Json::Value(Json::arrayValue); + // get current Priority from Hyperion Muxer + const Hyperion::InputInfo & priorityInfo = _hyperion->getPriorityInfo(_hyperion->getCurrentPriority()); + // check if current Priority exist + if (priorityInfo.priority != std::numeric_limits::max()) + { Json::Value LEDcolor; - for (auto it = priorityInfo.ledColors.begin(); it!=priorityInfo.ledColors.end(); ++it, ++i) { - LEDcolor[std::to_string(i)].append(it->red); - LEDcolor[std::to_string(i)].append(it->green); - LEDcolor[std::to_string(i)].append(it->blue); + // check if all LEDs has the same Color + if (std::all_of(priorityInfo.ledColors.begin(), priorityInfo.ledColors.end(), [&](ColorRgb color) + { + return ((color.red == priorityInfo.ledColors.begin()->red) && + (color.green == priorityInfo.ledColors.begin()->green) && + (color.blue == priorityInfo.ledColors.begin()->blue)); + } )) + { + // check if LED Color not Black (0,0,0) + if ((priorityInfo.ledColors.begin()->red != 0) && + (priorityInfo.ledColors.begin()->green != 0) && + (priorityInfo.ledColors.begin()->blue != 0)) + { + // add RGB Value to Array + LEDcolor["RGB Value"].append(priorityInfo.ledColors.begin()->red); + LEDcolor["RGB Value"].append(priorityInfo.ledColors.begin()->green); + LEDcolor["RGB Value"].append(priorityInfo.ledColors.begin()->blue); + + uint16_t Hue; + float Saturation, Luminace; + + // add HSL Value to Array + HslTransform::rgb2hsl(priorityInfo.ledColors.begin()->red, + priorityInfo.ledColors.begin()->green, + priorityInfo.ledColors.begin()->blue, + Hue, Saturation, Luminace); + + LEDcolor["HSL Value"].append(Hue); + LEDcolor["HSL Value"].append(Saturation); + LEDcolor["HSL Value"].append(Luminace); + + // add HEX Value to Array + std::stringstream hex; + hex << "0x" + << std::uppercase << std::setw(2) << std::setfill('0') + << std::hex << unsigned(priorityInfo.ledColors.begin()->red) + << std::uppercase << std::setw(2) << std::setfill('0') + << std::hex << unsigned(priorityInfo.ledColors.begin()->green) + << std::uppercase << std::setw(2) << std::setfill('0') + << std::hex << unsigned(priorityInfo.ledColors.begin()->blue); + + LEDcolor["HEX Value"].append(hex.str()); + + activeLedColors.append(LEDcolor); + } } - - activeLedColors.append(LEDcolor); } // send the result From 6f43fe11967489d17f0ecbc20fce685586474b85 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Tue, 31 May 2016 07:58:31 +1000 Subject: [PATCH 33/63] New QT based udp driver (#662) * Removed -HUP so the default -TERM signal is sent instead. - hyperiond only listens for TERM and INT. HUP is often used to get an exe to reread its config Changed pgrep to add '-x' so it wont partial match on the exe name. - I have multiple instances with multiple hyperiond-instance1 names - this ensures the service script only kills the right process * reversing errant change to hyperion.systemd.sh * cleaned up a couple of compiler warnings * moved bitpair_to_byte initialiser to (hopefully) work with older GCC * compiler warning in udp driver removed some tabs in ws2812b.cpp * formatting - spaces to tabs * moved rpi_281x to tag sk6812-v1.0 * moving to my fork of rpi_281x * half way thru re merging the newudp support * Whoops.... dont know how it compiled before.. * Removed debugging that was commented out Former-commit-id: ac4330422f93f3d594dfcba5593759288298d25e --- libsrc/leddevice/CMakeLists.txt | 4 ++ libsrc/leddevice/LedDeviceFactory.cpp | 11 ++++ libsrc/leddevice/LedDeviceUdpRaw.cpp | 41 +++++++++++++ libsrc/leddevice/LedDeviceUdpRaw.h | 43 ++++++++++++++ libsrc/leddevice/LedUdpDevice.cpp | 85 +++++++++++++++++++++++++++ libsrc/leddevice/LedUdpDevice.h | 66 +++++++++++++++++++++ 6 files changed, 250 insertions(+) create mode 100644 libsrc/leddevice/LedDeviceUdpRaw.cpp create mode 100644 libsrc/leddevice/LedDeviceUdpRaw.h create mode 100644 libsrc/leddevice/LedUdpDevice.cpp create mode 100644 libsrc/leddevice/LedUdpDevice.h diff --git a/libsrc/leddevice/CMakeLists.txt b/libsrc/leddevice/CMakeLists.txt index efdbffa6..7d3ea06e 100755 --- a/libsrc/leddevice/CMakeLists.txt +++ b/libsrc/leddevice/CMakeLists.txt @@ -38,6 +38,8 @@ SET(Leddevice_HEADERS ${CURRENT_SOURCE_DIR}/LedDeviceFile.h ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h ${CURRENT_SOURCE_DIR}/LedDeviceUdp.h + ${CURRENT_SOURCE_DIR}/LedDeviceUdpRaw.h + ${CURRENT_SOURCE_DIR}/LedUdpDevice.h ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.h ${CURRENT_SOURCE_DIR}/LedDeviceAtmo.h @@ -62,6 +64,8 @@ SET(Leddevice_SOURCES ${CURRENT_SOURCE_DIR}/LedDeviceFile.cpp ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.cpp ${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceUdpRaw.cpp + ${CURRENT_SOURCE_DIR}/LedUdpDevice.cpp ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp ${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.cpp diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 689ef91f..ed07249c 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -33,6 +33,7 @@ #include "LedDeviceFile.h" #include "LedDeviceFadeCandy.h" #include "LedDeviceUdp.h" +#include "LedDeviceUdpRaw.h" #include "LedDeviceHyperionUsbasp.h" #include "LedDevicePhilipsHue.h" #include "LedDeviceTpm2.h" @@ -318,6 +319,16 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) const unsigned maxPacket = deviceConfig["maxpacket"].asInt(); device = new LedDeviceUdp(output, rate, protocol, maxPacket); } + else if (type == "udpraw") + { + const std::string output = deviceConfig["output"].asString(); + const unsigned rate = deviceConfig["rate"].asInt(); + const unsigned latchtime = deviceConfig.get("latchtime",500000).asInt(); + + LedDeviceUdpRaw* deviceUdpRaw = new LedDeviceUdpRaw(output, rate, latchtime); + deviceUdpRaw->open(); + device = deviceUdpRaw; + } else if (type == "tpm2") { const std::string output = deviceConfig["output"].asString(); diff --git a/libsrc/leddevice/LedDeviceUdpRaw.cpp b/libsrc/leddevice/LedDeviceUdpRaw.cpp new file mode 100644 index 00000000..5880b2f9 --- /dev/null +++ b/libsrc/leddevice/LedDeviceUdpRaw.cpp @@ -0,0 +1,41 @@ + +// STL includes +#include +#include +#include + +// Linux includes +#include +#include + +// hyperion local includes +#include "LedDeviceUdpRaw.h" + +LedDeviceUdpRaw::LedDeviceUdpRaw(const std::string& outputDevice, const unsigned baudrate) : + LedUdpDevice(outputDevice, baudrate, 500000), + mLedCount(0) +{ + // empty +} + +LedDeviceUdpRaw::LedDeviceUdpRaw(const std::string& outputDevice, const unsigned baudrate, const unsigned latchTime) : + LedUdpDevice(outputDevice, baudrate, latchTime), + mLedCount(0) +{ + // empty +} + +int LedDeviceUdpRaw::write(const std::vector &ledValues) +{ + mLedCount = ledValues.size(); + + const unsigned dataLen = ledValues.size() * sizeof(ColorRgb); + const uint8_t * dataPtr = reinterpret_cast(ledValues.data()); + + return writeBytes(dataLen, dataPtr); +} + +int LedDeviceUdpRaw::switchOff() +{ + return write(std::vector(mLedCount, ColorRgb{0,0,0})); +} diff --git a/libsrc/leddevice/LedDeviceUdpRaw.h b/libsrc/leddevice/LedDeviceUdpRaw.h new file mode 100644 index 00000000..4ddf8098 --- /dev/null +++ b/libsrc/leddevice/LedDeviceUdpRaw.h @@ -0,0 +1,43 @@ +#pragma once + +// STL includes +#include + +// hyperion incluse +#include "LedUdpDevice.h" + +/// +/// Implementation of the LedDevice interface for writing to Ws2801 led device. +/// +class LedDeviceUdpRaw : public LedUdpDevice +{ +public: + /// + /// Constructs the LedDevice for a string containing leds of the type Ws2801 + /// + /// @param outputDevice The name of the output device (eg '/etc/SpiDev.0.0') + /// @param baudrate The used baudrate for writing to the output device + /// + LedDeviceUdpRaw(const std::string& outputDevice, + const unsigned baudrate); + + LedDeviceUdpRaw(const std::string& outputDevice, + const unsigned baudrate, + const unsigned latchTime); + + /// + /// Writes the led color values to the led-device + /// + /// @param ledValues The color-value per led + /// @return Zero on succes else negative + /// + virtual int write(const std::vector &ledValues); + + /// Switch the leds off + virtual int switchOff(); + +private: + + /// the number of leds (needed when switching off) + size_t mLedCount; +}; diff --git a/libsrc/leddevice/LedUdpDevice.cpp b/libsrc/leddevice/LedUdpDevice.cpp new file mode 100644 index 00000000..b8126592 --- /dev/null +++ b/libsrc/leddevice/LedUdpDevice.cpp @@ -0,0 +1,85 @@ + +// STL includes +#include +#include +#include + +// Linux includes +#include +#include + +#include +#include +#include + +// Local Hyperion includes +#include "LedUdpDevice.h" + + +LedUdpDevice::LedUdpDevice(const std::string& outputDevice, const unsigned baudrate, const int latchTime_ns) : + mDeviceName(outputDevice), + mBaudRate_Hz(baudrate), + mLatchTime_ns(latchTime_ns), + mFid(-1) +{ + udpSocket = new QUdpSocket(); + QString str = QString::fromStdString(mDeviceName); + QStringList _list = str.split(":"); + if (_list.size() != 2) { + printf ("ERROR: LedUdpDevice: Error parsing hostname:port\n"); + exit (-1); + } + QHostInfo info = QHostInfo::fromName(_list.at(0)); + if (!info.addresses().isEmpty()) { + _address = info.addresses().first(); + // use the first IP address + } + _port = _list.at(1).toInt(); +} + +LedUdpDevice::~LedUdpDevice() +{ +// close(mFid); +} + +int LedUdpDevice::open() +{ + udpSocket->bind(QHostAddress::Any, 7755); + + +/* + if (mFid < 0) + { + std::cerr << "Failed to open device('" << mDeviceName << "') " << std::endl; + return -1; + } +*/ + + return 0; +} + +int LedUdpDevice::writeBytes(const unsigned size, const uint8_t * data) +{ +/* + if (mFid < 0) + { + return -1; + } +*/ + +// int retVal = udpSocket->writeDatagram((const char *)data,size,QHostAddress::LocalHost,9998); + int retVal = udpSocket->writeDatagram((const char *)data,size,_address,_port); + + if (retVal == 0 && mLatchTime_ns > 0) + { + // The 'latch' time for latching the shifted-value into the leds + timespec latchTime; + latchTime.tv_sec = 0; + latchTime.tv_nsec = mLatchTime_ns; + + // Sleep to latch the leds (only if write succesfull) + nanosleep(&latchTime, NULL); + } + + return retVal; +} diff --git a/libsrc/leddevice/LedUdpDevice.h b/libsrc/leddevice/LedUdpDevice.h new file mode 100644 index 00000000..cd9e2463 --- /dev/null +++ b/libsrc/leddevice/LedUdpDevice.h @@ -0,0 +1,66 @@ +#pragma once + +#include + +// Linux-SPI includes +#include + +// Hyperion includes +#include + +/// +/// The LedUdpDevice implements an abstract base-class for LedDevices using the SPI-device. +/// +class LedUdpDevice : public LedDevice +{ +public: + /// + /// Constructs the LedDevice attached to a SPI-device + /// + /// @param[in] outputDevice The name of the output device (eg '/etc/UdpDev.0.0') + /// @param[in] baudrate The used baudrate for writing to the output device + /// @param[in] latchTime_ns The latch-time to latch in the values across the SPI-device (negative + /// means no latch required) [ns] + /// + LedUdpDevice(const std::string& outputDevice, const unsigned baudrate, const int latchTime_ns = -1); + + /// + /// Destructor of the LedDevice; closes the output device if it is open + /// + virtual ~LedUdpDevice(); + + /// + /// Opens and configures the output device + /// + /// @return Zero on succes else negative + /// + int open(); + +protected: + /// + /// Writes the given bytes/bits to the SPI-device and sleeps the latch time to ensure that the + /// values are latched. + /// + /// @param[in[ size The length of the data + /// @param[in] data The data + /// + /// @return Zero on succes else negative + /// + int writeBytes(const unsigned size, const uint8_t *data); + +private: + /// The name of the output device + const std::string mDeviceName; + /// The used baudrate of the output device + const int mBaudRate_Hz; + /// The time which the device should be untouched after a write + const int mLatchTime_ns; + + /// The File Identifier of the opened output device (or -1 if not opened) + int mFid; + /// + QUdpSocket *udpSocket; + QHostAddress _address; + quint16 _port; +}; + From 03cee33784139c5424822494bb19253d5b4b30c8 Mon Sep 17 00:00:00 2001 From: ntim Date: Tue, 31 May 2016 22:54:47 +0200 Subject: [PATCH 34/63] Fix for Philips Hue flickering when switchOffOnBlack is set true (#668) * Improved switch off on black feature. * Changed "isnan" to "std::isnan" Former-commit-id: 5db2b97674661e4e19f796a91dd443a501268e27 --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 684 +++++++++++------------ 1 file changed, 342 insertions(+), 342 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index 05d0a63d..df7c831a 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -1,342 +1,342 @@ -// Local-Hyperion includes -#include "LedDevicePhilipsHue.h" - -// jsoncpp includes -#include - -// qt includes -#include -#include -#include - -#include -#include - -bool operator ==(CiColor p1, CiColor p2) { - return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri); -} - -bool operator !=(CiColor p1, CiColor p2) { - return !(p1 == p2); -} - -PhilipsHueLight::PhilipsHueLight(unsigned int id, QString originalState, QString modelId) : - id(id), originalState(originalState) { - // Hue system model ids (http://www.developers.meethue.com/documentation/supported-lights). - // Light strips, color iris, ... - const std::set GAMUT_A_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012", - "LLC013", "LLC014", "LST001" }; - // Hue bulbs, spots, ... - const std::set GAMUT_B_MODEL_IDS = { "LCT001", "LCT002", "LCT003", "LCT007", "LLM001" }; - // Hue Lightstrip plus, go ... - const std::set GAMUT_C_MODEL_IDS = { "LLC020", "LST002" }; - // Find id in the sets and set the appropiate color space. - if (GAMUT_A_MODEL_IDS.find(modelId) != GAMUT_A_MODEL_IDS.end()) { - colorSpace.red = {0.703f, 0.296f}; - colorSpace.green = {0.2151f, 0.7106f}; - colorSpace.blue = {0.138f, 0.08f}; - } else if (GAMUT_B_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { - colorSpace.red = {0.675f, 0.322f}; - colorSpace.green = {0.4091f, 0.518f}; - colorSpace.blue = {0.167f, 0.04f}; - } else if (GAMUT_C_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { - colorSpace.red = {0.675f, 0.322f}; - colorSpace.green = {0.2151f, 0.7106f}; - colorSpace.blue = {0.167f, 0.04f}; - } else { - colorSpace.red = {1.0f, 0.0f}; - colorSpace.green = {0.0f, 1.0f}; - colorSpace.blue = {0.0f, 0.0f}; - } - // Initialize black color. - black = rgbToCiColor(0.0f, 0.0f, 0.0f); - // Initialize color with black - color = {black.x, black.y, black.bri}; -} - -float PhilipsHueLight::crossProduct(CiColor p1, CiColor p2) { - return p1.x * p2.y - p1.y * p2.x; -} - -bool PhilipsHueLight::isPointInLampsReach(CiColor p) { - CiColor v1 = { colorSpace.green.x - colorSpace.red.x, colorSpace.green.y - colorSpace.red.y }; - CiColor v2 = { colorSpace.blue.x - colorSpace.red.x, colorSpace.blue.y - colorSpace.red.y }; - CiColor q = { p.x - colorSpace.red.x, p.y - colorSpace.red.y }; - float s = crossProduct(q, v2) / crossProduct(v1, v2); - float t = crossProduct(v1, q) / crossProduct(v1, v2); - if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) { - return true; - } - return false; -} - -CiColor PhilipsHueLight::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) { - CiColor AP = { p.x - a.x, p.y - a.y }; - CiColor AB = { b.x - a.x, b.y - a.y }; - float ab2 = AB.x * AB.x + AB.y * AB.y; - float ap_ab = AP.x * AB.x + AP.y * AB.y; - float t = ap_ab / ab2; - if (t < 0.0f) { - t = 0.0f; - } else if (t > 1.0f) { - t = 1.0f; - } - return {a.x + AB.x * t, a.y + AB.y * t}; -} - -float PhilipsHueLight::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) { - // Horizontal difference. - float dx = p1.x - p2.x; - // Vertical difference. - float dy = p1.y - p2.y; - // Absolute value. - return sqrt(dx * dx + dy * dy); -} - -CiColor PhilipsHueLight::rgbToCiColor(float red, float green, float blue) { - // Apply gamma correction. - float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); - float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); - float b = (blue > 0.04045f) ? powf((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f); - // Convert to XYZ space. - float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; - float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; - float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f; - // Convert to x,y space. - float cx = X / (X + Y + Z); - float cy = Y / (X + Y + Z); - if (std::isnan(cx)) { - cx = 0.0f; - } - if (std::isnan(cy)) { - cy = 0.0f; - } - // Brightness is simply Y in the XYZ space. - CiColor xy = { cx, cy, Y }; - // Check if the given XY value is within the color reach of our lamps. - if (!isPointInLampsReach(xy)) { - // It seems the color is out of reach let's find the closes color we can produce with our lamp and send this XY value out. - CiColor pAB = getClosestPointToPoint(colorSpace.red, colorSpace.green, xy); - CiColor pAC = getClosestPointToPoint(colorSpace.blue, colorSpace.red, xy); - CiColor pBC = getClosestPointToPoint(colorSpace.green, colorSpace.blue, xy); - // Get the distances per point and see which point is closer to our Point. - float dAB = getDistanceBetweenTwoPoints(xy, pAB); - float dAC = getDistanceBetweenTwoPoints(xy, pAC); - float dBC = getDistanceBetweenTwoPoints(xy, pBC); - float lowest = dAB; - CiColor closestPoint = pAB; - if (dAC < lowest) { - lowest = dAC; - closestPoint = pAC; - } - if (dBC < lowest) { - lowest = dBC; - closestPoint = pBC; - } - // Change the xy value to a value which is within the reach of the lamp. - xy.x = closestPoint.x; - xy.y = closestPoint.y; - } - return xy; -} - -LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::string& username, bool switchOffOnBlack, - int transitiontime, std::vector lightIds) : - host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime( - transitiontime), lightIds(lightIds) { - manager = new QNetworkAccessManager(); - timer.setInterval(3000); - timer.setSingleShot(true); - connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates())); -} - -LedDevicePhilipsHue::~LedDevicePhilipsHue() { - delete manager; -} - -int LedDevicePhilipsHue::write(const std::vector & ledValues) { - // Save light states if not done before. - if (!areStatesSaved()) { - saveStates((unsigned int) ledValues.size()); - switchOn((unsigned int) ledValues.size()); - } - // If there are less states saved than colors given, then maybe something went wrong before. - if (lights.size() != ledValues.size()) { - restoreStates(); - return 0; - } - // Iterate through colors and set light states. - unsigned int idx = 0; - for (const ColorRgb& color : ledValues) { - // Get lamp. - PhilipsHueLight& lamp = lights.at(idx); - // Scale colors from [0, 255] to [0, 1] and convert to xy space. - CiColor xy = lamp.rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f); - // Write color if color has been changed. - if (xy != lamp.color) { - // Switch on if the lamp has been previously switched off. - if (switchOffOnBlack && lamp.color == lamp.black) { - put(getStateRoute(lamp.id), QString("{\"on\": true}")); - } - // Send adjust color and brightness command in JSON format. - // We have to set the transition time each time. - put(getStateRoute(lamp.id), - QString("{\"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg(xy.y).arg( - qRound(xy.bri * 255.0f)).arg(transitiontime)); - - } - // Switch lamp off if switchOffOnBlack is enabled and the lamp is currently on. - if (switchOffOnBlack) { - // From black to a color. - if (lamp.color == lamp.black && xy != lamp.black) { - put(getStateRoute(lamp.id), QString("{\"on\": true}")); - } - // From a color to black. - else if (lamp.color != lamp.black && xy == lamp.black) { - put(getStateRoute(lamp.id), QString("{\"on\": false}")); - } - } - // Remember last color. - lamp.color = xy; - // Next light id. - idx++; - } - timer.start(); - return 0; -} - -int LedDevicePhilipsHue::switchOff() { - timer.stop(); - // If light states have been saved before, ... - if (areStatesSaved()) { - // ... restore them. - restoreStates(); - } - return 0; -} - -void LedDevicePhilipsHue::put(QString route, QString content) { - QString url = getUrl(route); - // Perfrom request - QNetworkRequest request(url); - 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())); - // Go into the loop until the request is finished. - loop.exec(); - // Free space. - reply->deleteLater(); -} - -QByteArray LedDevicePhilipsHue::get(QString route) { - QString url = getUrl(route); - // Perfrom request - 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. - QByteArray response = reply->readAll(); - // Free space. - reply->deleteLater(); - // Return response - return response; -} - -QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) { - return QString("lights/%1/state").arg(lightId); -} - -QString LedDevicePhilipsHue::getRoute(unsigned int lightId) { - return QString("lights/%1").arg(lightId); -} - -QString LedDevicePhilipsHue::getUrl(QString route) { - return QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route); -} - -void LedDevicePhilipsHue::saveStates(unsigned int nLights) { - // Clear saved lamps. - lights.clear(); - // Use json parser to parse reponse. - Json::Reader reader; - Json::FastWriter writer; - // Read light ids if none have been supplied by the user. - if (lightIds.size() != nLights) { - lightIds.clear(); - // - QByteArray response = get("lights"); - Json::Value json; - if (!reader.parse(QString(response).toStdString(), json)) { - throw std::runtime_error(("No lights found at " + getUrl("lights")).toStdString()); - } - // Loop over all children. - for (Json::ValueIterator it = json.begin(); it != json.end() && lightIds.size() < nLights; it++) { - int lightId = atoi(it.key().asCString()); - lightIds.push_back(lightId); - std::cout << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): found light with id " << lightId - << "." << std::endl; - } - // Check if we found enough lights. - if (lightIds.size() != nLights) { - throw std::runtime_error(("Not enough lights found at " + getUrl("lights")).toStdString()); - } - } - // Iterate lights. - for (unsigned int i = 0; i < nLights; i++) { - // Read the response. - QByteArray response = get(getRoute(lightIds.at(i))); - // Parse JSON. - Json::Value json; - if (!reader.parse(QString(response).toStdString(), json)) { - // Error occured, break loop. - std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got invalid response from light " - << getUrl(getRoute(lightIds.at(i))).toStdString() << "." << std::endl; - break; - } - // Get state object values which are subject to change. - Json::Value state(Json::objectValue); - if (!json.isMember("state")) { - std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no state for light from " - << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; - break; - } - if (!json["state"].isMember("on")) { - std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no valid state from light " - << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; - break; - } - state["on"] = json["state"]["on"]; - if (json["state"]["on"] == true) { - state["xy"] = json["state"]["xy"]; - state["bri"] = json["state"]["bri"]; - } - // Determine the model id. - QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", ""); - QString originalState = QString(writer.write(state).c_str()).trimmed(); - // Save state object. - lights.push_back(PhilipsHueLight(lightIds.at(i), originalState, modelId)); - } -} - -void LedDevicePhilipsHue::switchOn(unsigned int nLights) { - for (PhilipsHueLight light : lights) { - put(getStateRoute(light.id), "{\"on\": true}"); - } -} - -void LedDevicePhilipsHue::restoreStates() { - for (PhilipsHueLight light : lights) { - put(getStateRoute(light.id), light.originalState); - } - // Clear saved light states. - lights.clear(); -} - -bool LedDevicePhilipsHue::areStatesSaved() { - return !lights.empty(); -} +// Local-Hyperion includes +#include "LedDevicePhilipsHue.h" + +// jsoncpp includes +#include + +// qt includes +#include +#include +#include + +#include +#include + +bool operator ==(CiColor p1, CiColor p2) { + return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri); +} + +bool operator !=(CiColor p1, CiColor p2) { + return !(p1 == p2); +} + +PhilipsHueLight::PhilipsHueLight(unsigned int id, QString originalState, QString modelId) : + id(id), originalState(originalState) { + // Hue system model ids (http://www.developers.meethue.com/documentation/supported-lights). + // Light strips, color iris, ... + const std::set GAMUT_A_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012", + "LLC013", "LLC014", "LST001" }; + // Hue bulbs, spots, ... + const std::set GAMUT_B_MODEL_IDS = { "LCT001", "LCT002", "LCT003", "LCT007", "LLM001" }; + // Hue Lightstrip plus, go ... + const std::set GAMUT_C_MODEL_IDS = { "LLC020", "LST002" }; + // Find id in the sets and set the appropiate color space. + if (GAMUT_A_MODEL_IDS.find(modelId) != GAMUT_A_MODEL_IDS.end()) { + colorSpace.red = {0.703f, 0.296f}; + colorSpace.green = {0.2151f, 0.7106f}; + colorSpace.blue = {0.138f, 0.08f}; + } else if (GAMUT_B_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { + colorSpace.red = {0.675f, 0.322f}; + colorSpace.green = {0.4091f, 0.518f}; + colorSpace.blue = {0.167f, 0.04f}; + } else if (GAMUT_C_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { + colorSpace.red = {0.675f, 0.322f}; + colorSpace.green = {0.2151f, 0.7106f}; + colorSpace.blue = {0.167f, 0.04f}; + } else { + colorSpace.red = {1.0f, 0.0f}; + colorSpace.green = {0.0f, 1.0f}; + colorSpace.blue = {0.0f, 0.0f}; + } + // Initialize black color. + black = rgbToCiColor(0.0f, 0.0f, 0.0f); + // Initialize color with black + color = {black.x, black.y, black.bri}; +} + +float PhilipsHueLight::crossProduct(CiColor p1, CiColor p2) { + return p1.x * p2.y - p1.y * p2.x; +} + +bool PhilipsHueLight::isPointInLampsReach(CiColor p) { + CiColor v1 = { colorSpace.green.x - colorSpace.red.x, colorSpace.green.y - colorSpace.red.y }; + CiColor v2 = { colorSpace.blue.x - colorSpace.red.x, colorSpace.blue.y - colorSpace.red.y }; + CiColor q = { p.x - colorSpace.red.x, p.y - colorSpace.red.y }; + float s = crossProduct(q, v2) / crossProduct(v1, v2); + float t = crossProduct(v1, q) / crossProduct(v1, v2); + if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) { + return true; + } + return false; +} + +CiColor PhilipsHueLight::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) { + CiColor AP = { p.x - a.x, p.y - a.y }; + CiColor AB = { b.x - a.x, b.y - a.y }; + float ab2 = AB.x * AB.x + AB.y * AB.y; + float ap_ab = AP.x * AB.x + AP.y * AB.y; + float t = ap_ab / ab2; + if (t < 0.0f) { + t = 0.0f; + } else if (t > 1.0f) { + t = 1.0f; + } + return {a.x + AB.x * t, a.y + AB.y * t}; +} + +float PhilipsHueLight::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) { + // Horizontal difference. + float dx = p1.x - p2.x; + // Vertical difference. + float dy = p1.y - p2.y; + // Absolute value. + return sqrt(dx * dx + dy * dy); +} + +CiColor PhilipsHueLight::rgbToCiColor(float red, float green, float blue) { + // Apply gamma correction. + float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); + float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); + float b = (blue > 0.04045f) ? powf((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f); + // Convert to XYZ space. + float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; + float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; + float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f; + // Convert to x,y space. + float cx = X / (X + Y + Z); + float cy = Y / (X + Y + Z); + if (std::isnan(cx)) { + cx = 0.0f; + } + if (std::isnan(cy)) { + cy = 0.0f; + } + // Brightness is simply Y in the XYZ space. + CiColor xy = { cx, cy, Y }; + // Check if the given XY value is within the color reach of our lamps. + if (!isPointInLampsReach(xy)) { + // It seems the color is out of reach let's find the closes color we can produce with our lamp and send this XY value out. + CiColor pAB = getClosestPointToPoint(colorSpace.red, colorSpace.green, xy); + CiColor pAC = getClosestPointToPoint(colorSpace.blue, colorSpace.red, xy); + CiColor pBC = getClosestPointToPoint(colorSpace.green, colorSpace.blue, xy); + // Get the distances per point and see which point is closer to our Point. + float dAB = getDistanceBetweenTwoPoints(xy, pAB); + float dAC = getDistanceBetweenTwoPoints(xy, pAC); + float dBC = getDistanceBetweenTwoPoints(xy, pBC); + float lowest = dAB; + CiColor closestPoint = pAB; + if (dAC < lowest) { + lowest = dAC; + closestPoint = pAC; + } + if (dBC < lowest) { + lowest = dBC; + closestPoint = pBC; + } + // Change the xy value to a value which is within the reach of the lamp. + xy.x = closestPoint.x; + xy.y = closestPoint.y; + } + return xy; +} + +LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::string& username, bool switchOffOnBlack, + int transitiontime, std::vector lightIds) : + host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime( + transitiontime), lightIds(lightIds) { + manager = new QNetworkAccessManager(); + timer.setInterval(3000); + timer.setSingleShot(true); + connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates())); +} + +LedDevicePhilipsHue::~LedDevicePhilipsHue() { + delete manager; +} + +int LedDevicePhilipsHue::write(const std::vector & ledValues) { + // Save light states if not done before. + if (!areStatesSaved()) { + saveStates((unsigned int) ledValues.size()); + switchOn((unsigned int) ledValues.size()); + } + // If there are less states saved than colors given, then maybe something went wrong before. + if (lights.size() != ledValues.size()) { + restoreStates(); + return 0; + } + // Iterate through colors and set light states. + unsigned int idx = 0; + for (const ColorRgb& color : ledValues) { + // Get lamp. + PhilipsHueLight& lamp = lights.at(idx); + // Scale colors from [0, 255] to [0, 1] and convert to xy space. + CiColor xy = lamp.rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f); + // Write color if color has been changed. + if (xy != lamp.color) { + // From a color to black. + if (switchOffOnBlack && lamp.color != lamp.black && xy == lamp.black) { + put(getStateRoute(lamp.id), QString("{\"on\": false}")); + } + // From black to a color + else if (switchOffOnBlack && lamp.color == lamp.black && xy != lamp.black) { + // Send adjust color and brightness command in JSON format. + // We have to set the transition time each time. + // Send also command to switch the lamp on. + put(getStateRoute(lamp.id), + QString("{\"on\": true, \"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg( + xy.y).arg(qRound(xy.bri * 255.0f)).arg(transitiontime)); + } + // Normal color change. + else { + // Send adjust color and brightness command in JSON format. + // We have to set the transition time each time. + put(getStateRoute(lamp.id), + QString("{\"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg(xy.y).arg( + qRound(xy.bri * 255.0f)).arg(transitiontime)); + } + } + // Remember last color. + lamp.color = xy; + // Next light id. + idx++; + } + timer.start(); + return 0; +} + +int LedDevicePhilipsHue::switchOff() { + timer.stop(); + // If light states have been saved before, ... + if (areStatesSaved()) { + // ... restore them. + restoreStates(); + } + return 0; +} + +void LedDevicePhilipsHue::put(QString route, QString content) { + QString url = getUrl(route); + // Perfrom request + QNetworkRequest request(url); + 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())); + // Go into the loop until the request is finished. + loop.exec(); + // Free space. + reply->deleteLater(); +} + +QByteArray LedDevicePhilipsHue::get(QString route) { + QString url = getUrl(route); + // Perfrom request + 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. + QByteArray response = reply->readAll(); + // Free space. + reply->deleteLater(); + // Return response + return response; +} + +QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) { + return QString("lights/%1/state").arg(lightId); +} + +QString LedDevicePhilipsHue::getRoute(unsigned int lightId) { + return QString("lights/%1").arg(lightId); +} + +QString LedDevicePhilipsHue::getUrl(QString route) { + return QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route); +} + +void LedDevicePhilipsHue::saveStates(unsigned int nLights) { + // Clear saved lamps. + lights.clear(); + // Use json parser to parse reponse. + Json::Reader reader; + Json::FastWriter writer; + // Read light ids if none have been supplied by the user. + if (lightIds.size() != nLights) { + lightIds.clear(); + // + QByteArray response = get("lights"); + Json::Value json; + if (!reader.parse(QString(response).toStdString(), json)) { + throw std::runtime_error(("No lights found at " + getUrl("lights")).toStdString()); + } + // Loop over all children. + for (Json::ValueIterator it = json.begin(); it != json.end() && lightIds.size() < nLights; it++) { + int lightId = atoi(it.key().asCString()); + lightIds.push_back(lightId); + std::cout << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): found light with id " << lightId + << "." << std::endl; + } + // Check if we found enough lights. + if (lightIds.size() != nLights) { + throw std::runtime_error(("Not enough lights found at " + getUrl("lights")).toStdString()); + } + } + // Iterate lights. + for (unsigned int i = 0; i < nLights; i++) { + // Read the response. + QByteArray response = get(getRoute(lightIds.at(i))); + // Parse JSON. + Json::Value json; + if (!reader.parse(QString(response).toStdString(), json)) { + // Error occured, break loop. + std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got invalid response from light " + << getUrl(getRoute(lightIds.at(i))).toStdString() << "." << std::endl; + break; + } + // Get state object values which are subject to change. + Json::Value state(Json::objectValue); + if (!json.isMember("state")) { + std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no state for light from " + << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; + break; + } + if (!json["state"].isMember("on")) { + std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no valid state from light " + << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; + break; + } + state["on"] = json["state"]["on"]; + if (json["state"]["on"] == true) { + state["xy"] = json["state"]["xy"]; + state["bri"] = json["state"]["bri"]; + } + // Determine the model id. + QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", ""); + QString originalState = QString(writer.write(state).c_str()).trimmed(); + // Save state object. + lights.push_back(PhilipsHueLight(lightIds.at(i), originalState, modelId)); + } +} + +void LedDevicePhilipsHue::switchOn(unsigned int nLights) { + for (PhilipsHueLight light : lights) { + put(getStateRoute(light.id), "{\"on\": true}"); + } +} + +void LedDevicePhilipsHue::restoreStates() { + for (PhilipsHueLight light : lights) { + put(getStateRoute(light.id), light.originalState); + } + // Clear saved light states. + lights.clear(); +} + +bool LedDevicePhilipsHue::areStatesSaved() { + return !lights.empty(); +} From 6fbfda03fa55d35ff8b38c475c1a6146c5e42117 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Wed, 1 Jun 2016 06:55:11 +1000 Subject: [PATCH 35/63] add zeroconf support based on qt4 libraries (#667) * Removed -HUP so the default -TERM signal is sent instead. - hyperiond only listens for TERM and INT. HUP is often used to get an exe to reread its config Changed pgrep to add '-x' so it wont partial match on the exe name. - I have multiple instances with multiple hyperiond-instance1 names - this ensures the service script only kills the right process * reversing errant change to hyperion.systemd.sh * added bonjour/zeroconf service discovery to the json interface. When clients are also modified, they can - find hyperiond on the network much more quickly than ping/portscan; - find multiple instances running on different ports instead of assuming 19444 * Moved zeroconf calls to hyperiond.cpp * Added mDNS/zerconf/bonjour registration for proto server Added config options. "jsonServer" : { "port" : 49444, // "mDNSDescr" : "hyperiond jsonServer blah de blah", "mDNSService" : "_hyperiond_json._tcp" }, * cleaned up a couple of compiler warnings * moved bitpair_to_byte initialiser to (hopefully) work with older GCC * compiler warning in udp driver removed some tabs in ws2812b.cpp * formatting - spaces to tabs * moved rpi_281x to tag sk6812-v1.0 * moving to my fork of rpi_281x * Now uses the led device name and hostname to create the annouce name Former-commit-id: abfa51bcf359cafa63338181c1b83ecfd231bc87 --- CMakeLists.txt | 4 + HyperionConfig.h.in | 3 + include/bonjour/bonjourrecord.h | 60 +++++++++++++ include/bonjour/bonjourserviceregister.h | 66 ++++++++++++++ libsrc/CMakeLists.txt | 4 + libsrc/bonjour/CMakeLists.txt | 52 +++++++++++ libsrc/bonjour/bonjourserviceregister.cpp | 102 ++++++++++++++++++++++ libsrc/bonjour/fortuneserver.pro | 15 ++++ libsrc/bonjour/main.cpp | 39 +++++++++ libsrc/bonjour/server.cpp | 96 ++++++++++++++++++++ libsrc/bonjour/server.h | 52 +++++++++++ libsrc/jsonserver/JsonServer.cpp | 1 + src/hyperiond/CMakeLists.txt | 5 +- src/hyperiond/hyperiond.cpp | 32 +++++++ 14 files changed, 530 insertions(+), 1 deletion(-) create mode 100755 include/bonjour/bonjourrecord.h create mode 100755 include/bonjour/bonjourserviceregister.h create mode 100644 libsrc/bonjour/CMakeLists.txt create mode 100755 libsrc/bonjour/bonjourserviceregister.cpp create mode 100755 libsrc/bonjour/fortuneserver.pro create mode 100755 libsrc/bonjour/main.cpp create mode 100755 libsrc/bonjour/server.cpp create mode 100755 libsrc/bonjour/server.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a82810e3..2cc8b23f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ SET ( DEFAULT_X11 OFF ) SET ( DEFAULT_SPIDEV OFF ) SET ( DEFAULT_WS2812BPWM OFF ) SET ( DEFAULT_WS281XPWM OFF ) +SET ( DEFAULT_ZEROCONF OFF ) if (APPLE) SET ( DEFAULT_OSX ON ) @@ -39,6 +40,9 @@ else () endif () # set the build options +option(ENABLE_ZEROCONF "Enable the avahi/zeroconf announce" ${DEFAULT_ZEROCONF} ) +message(STATUS "ENABLE_ZEROCONF = " ${ENABLE_ZEROCONF}) + option(ENABLE_AMLOGIC "Enable the AMLOGIC video grabber" ${DEFAULT_AMLOGIC} ) message(STATUS "ENABLE_AMLOGIC = " ${ENABLE_AMLOGIC}) diff --git a/HyperionConfig.h.in b/HyperionConfig.h.in index ddfff53c..7172ec16 100644 --- a/HyperionConfig.h.in +++ b/HyperionConfig.h.in @@ -30,4 +30,7 @@ // Define to enable the osx grabber #cmakedefine ENABLE_OSX +// Define to enable the bonjour/zeroconf publishing +#cmakedefine ENABLE_ZEROCONF + #define HYPERION_VERSION_ID "${HYPERION_VERSION_ID}" diff --git a/include/bonjour/bonjourrecord.h b/include/bonjour/bonjourrecord.h new file mode 100755 index 00000000..ae2ebc00 --- /dev/null +++ b/include/bonjour/bonjourrecord.h @@ -0,0 +1,60 @@ +/* +Copyright (c) 2007, Trenton Schulz + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef BONJOURRECORD_H +#define BONJOURRECORD_H + +#include +#include + +class BonjourRecord +{ +public: + BonjourRecord() {} + BonjourRecord(const QString &name, const QString ®Type, const QString &domain) + : serviceName(name), registeredType(regType), replyDomain(domain) + {} + BonjourRecord(const char *name, const char *regType, const char *domain) + { + serviceName = QString::fromUtf8(name); + registeredType = QString::fromUtf8(regType); + replyDomain = QString::fromUtf8(domain); + } + QString serviceName; + QString registeredType; + QString replyDomain; + bool operator==(const BonjourRecord &other) const { + return serviceName == other.serviceName + && registeredType == other.registeredType + && replyDomain == other.replyDomain; + } +}; + +Q_DECLARE_METATYPE(BonjourRecord) + +#endif // BONJOURRECORD_H diff --git a/include/bonjour/bonjourserviceregister.h b/include/bonjour/bonjourserviceregister.h new file mode 100755 index 00000000..599c9840 --- /dev/null +++ b/include/bonjour/bonjourserviceregister.h @@ -0,0 +1,66 @@ +/* +Copyright (c) 2007, Trenton Schulz + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef BONJOURSERVICEREGISTER_H +#define BONJOURSERVICEREGISTER_H + +#include + +#include "bonjourrecord.h" +class QSocketNotifier; + +#include + +class BonjourServiceRegister : public QObject +{ + Q_OBJECT +public: + BonjourServiceRegister(QObject *parent = 0); + ~BonjourServiceRegister(); + + void registerService(const BonjourRecord &record, quint16 servicePort); + inline BonjourRecord registeredRecord() const {return finalRecord; } + +signals: + void error(DNSServiceErrorType error); + void serviceRegistered(const BonjourRecord &record); + +private slots: + void bonjourSocketReadyRead(); + +private: + static void DNSSD_API bonjourRegisterService(DNSServiceRef sdRef, DNSServiceFlags, + DNSServiceErrorType errorCode, const char *name, + const char *regtype, const char *domain, + void *context); + DNSServiceRef dnssref; + QSocketNotifier *bonjourSocket; + BonjourRecord finalRecord; +}; + +#endif // BONJOURSERVICEREGISTER_H diff --git a/libsrc/CMakeLists.txt b/libsrc/CMakeLists.txt index 38ced39a..5cba07db 100644 --- a/libsrc/CMakeLists.txt +++ b/libsrc/CMakeLists.txt @@ -11,6 +11,10 @@ if (ENABLE_PROTOBUF) add_subdirectory(protoserver) endif () +if (ENABLE_ZEROCONF) + add_subdirectory(bonjour) +endif (ENABLE_ZEROCONF) + add_subdirectory(boblightserver) add_subdirectory(leddevice) add_subdirectory(utils) diff --git a/libsrc/bonjour/CMakeLists.txt b/libsrc/bonjour/CMakeLists.txt new file mode 100644 index 00000000..131b3d93 --- /dev/null +++ b/libsrc/bonjour/CMakeLists.txt @@ -0,0 +1,52 @@ + +# Define the current source locations +set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/bonjour) +set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/bonjour) + +# Group the headers that go through the MOC compiler +set(Bonjour_QT_HEADERS + ${CURRENT_HEADER_DIR}/bonjourrecord.h + ${CURRENT_HEADER_DIR}/bonjourserviceregister.h +) + +set(Bonjour_HEADERS +) + +set(Bonjour_SOURCES + ${CURRENT_SOURCE_DIR}/bonjourserviceregister.cpp +) + +set(Bonjour_RESOURCES +) + +if(ENABLE_QT5) +qt5_wrap_cpp(Bonjour_HEADERS_MOC ${Bonjour_QT_HEADERS}) +qt5_add_resources(Bonjour_RESOURCES_RCC ${Bonjour_RESOURCES} OPTIONS "-no-compress") +else(ENABLE_QT5) +qt4_wrap_cpp(Bonjour_HEADERS_MOC ${Bonjour_QT_HEADERS}) +qt4_add_resources(Bonjour_RESOURCES_RCC ${Bonjour_RESOURCES} OPTIONS "-no-compress") +endif(ENABLE_QT5) + +add_library(bonjour + ${Bonjour_HEADERS} + ${Bonjour_QT_HEADERS} + ${Bonjour_SOURCES} + ${Bonjour_RESOURCES} + ${Bonjour_HEADERS_MOC} + ${Bonjour_RESOURCES_RCC} +) + +if(ENABLE_QT5) +qt5_use_modules(bonjour Widgets Network) +endif(ENABLE_QT5) + +target_link_libraries(bonjour + libdns_sd.a + libavahi-client.a + libavahi-common.a + libavahi-core.a + libavahi-qt4.a + libdbus-1.a + hyperion + hyperion-utils + ${QT_LIBRARIES}) diff --git a/libsrc/bonjour/bonjourserviceregister.cpp b/libsrc/bonjour/bonjourserviceregister.cpp new file mode 100755 index 00000000..1d040688 --- /dev/null +++ b/libsrc/bonjour/bonjourserviceregister.cpp @@ -0,0 +1,102 @@ +/* +Copyright (c) 2007, Trenton Schulz + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +//#include "bonjourserviceregister.h" +#include + + +#include + +BonjourServiceRegister::BonjourServiceRegister(QObject *parent) + : QObject(parent), dnssref(0), bonjourSocket(0) +{ +} + +BonjourServiceRegister::~BonjourServiceRegister() +{ + if (dnssref) { + DNSServiceRefDeallocate(dnssref); + dnssref = 0; + } +} + +void BonjourServiceRegister::registerService(const BonjourRecord &record, quint16 servicePort) +{ + if (dnssref) { + qWarning("Warning: Already registered a service for this object, aborting new register"); + return; + } + quint16 bigEndianPort = servicePort; +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + { + bigEndianPort = 0 | ((servicePort & 0x00ff) << 8) | ((servicePort & 0xff00) >> 8); + } +#endif + + DNSServiceErrorType err = DNSServiceRegister(&dnssref, 0, 0, record.serviceName.toUtf8().constData(), + record.registeredType.toUtf8().constData(), + record.replyDomain.isEmpty() ? 0 + : record.replyDomain.toUtf8().constData(), 0, + bigEndianPort, 0, 0, bonjourRegisterService, this); + if (err != kDNSServiceErr_NoError) { + emit error(err); + } else { + int sockfd = DNSServiceRefSockFD(dnssref); + if (sockfd == -1) { + emit error(kDNSServiceErr_Invalid); + } else { + bonjourSocket = new QSocketNotifier(sockfd, QSocketNotifier::Read, this); + connect(bonjourSocket, SIGNAL(activated(int)), this, SLOT(bonjourSocketReadyRead())); + } + } +} + + +void BonjourServiceRegister::bonjourSocketReadyRead() +{ + DNSServiceErrorType err = DNSServiceProcessResult(dnssref); + if (err != kDNSServiceErr_NoError) + emit error(err); +} + + +void BonjourServiceRegister::bonjourRegisterService(DNSServiceRef, DNSServiceFlags, + DNSServiceErrorType errorCode, const char *name, + const char *regtype, const char *domain, + void *data) +{ + BonjourServiceRegister *serviceRegister = static_cast(data); + if (errorCode != kDNSServiceErr_NoError) { + emit serviceRegister->error(errorCode); + } else { + serviceRegister->finalRecord = BonjourRecord(QString::fromUtf8(name), + QString::fromUtf8(regtype), + QString::fromUtf8(domain)); + emit serviceRegister->serviceRegistered(serviceRegister->finalRecord); + } +} diff --git a/libsrc/bonjour/fortuneserver.pro b/libsrc/bonjour/fortuneserver.pro new file mode 100755 index 00000000..421b14c1 --- /dev/null +++ b/libsrc/bonjour/fortuneserver.pro @@ -0,0 +1,15 @@ +HEADERS = server.h \ + bonjourserviceregister.h +SOURCES = server.cpp \ + main.cpp \ + bonjourserviceregister.cpp +QT += network + +!mac:x11:LIBS+=-ldns_sd + +win32 { + LIBS+=-ldnssd + # Add your path to bonjour here. + LIBPATH=C:/Temp/mDNSResponder-107.6/mDNSWindows/DLL/Debug + INCLUDEPATH += c:/Temp/mDNSResponder-107.6/mDNSShared +} diff --git a/libsrc/bonjour/main.cpp b/libsrc/bonjour/main.cpp new file mode 100755 index 00000000..3d8db515 --- /dev/null +++ b/libsrc/bonjour/main.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.trolltech.com/products/qt/opensource.html +** +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://www.trolltech.com/products/qt/licensing.html or contact the +** sales department at sales@trolltech.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include +#include + +#include + +#include "server.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Server server; + server.show(); + qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); + int x = server.exec(); + return x; +} diff --git a/libsrc/bonjour/server.cpp b/libsrc/bonjour/server.cpp new file mode 100755 index 00000000..06768edf --- /dev/null +++ b/libsrc/bonjour/server.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.trolltech.com/products/qt/opensource.html +** +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://www.trolltech.com/products/qt/licensing.html or contact the +** sales department at sales@trolltech.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include +#include + +#include + +#include "server.h" +#include "bonjourserviceregister.h" +Server::Server(QWidget *parent) + : QDialog(parent) +{ + setWindowModality(Qt::ApplicationModal); + statusLabel = new QLabel; + quitButton = new QPushButton(tr("Quit")); + quitButton->setAutoDefault(false); + + tcpServer = new QTcpServer(this); + if (!tcpServer->listen()) { + QMessageBox::critical(this, tr("Fortune Server"), + tr("Unable to start the server: %1.") + .arg(tcpServer->errorString())); + close(); + return; + } + + statusLabel->setText(tr("The server is running on port %1.\n" + "Run the Fortune Client example now.") + .arg(tcpServer->serverPort())); + + fortunes << tr("You've been leading a dog's life. Stay off the furniture.") + << tr("You've got to think about tomorrow.") + << tr("You will be surprised by a loud noise.") + << tr("You will feel hungry again in another hour.") + << tr("You might have mail.") + << tr("You cannot kill time without injuring eternity.") + << tr("Computers are not intelligent. They only think they are."); + + connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); + connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendFortune())); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addStretch(1); + buttonLayout->addWidget(quitButton); + buttonLayout->addStretch(1); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(statusLabel); + mainLayout->addLayout(buttonLayout); + setLayout(mainLayout); + + bonjourRegister = new BonjourServiceRegister(this); + bonjourRegister->registerService(BonjourRecord(tr("Fortune Server on %1").arg(QHostInfo::localHostName()), + QLatin1String("_trollfortune._tcp"), QString()), + tcpServer->serverPort()); + setWindowTitle(tr("Fortune Server")); +} + +void Server::sendFortune() +{ + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_0); + out << (quint16)0; + out << fortunes.at(qrand() % fortunes.size()); + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + + QTcpSocket *clientConnection = tcpServer->nextPendingConnection(); + connect(clientConnection, SIGNAL(disconnected()), + clientConnection, SLOT(deleteLater())); + + clientConnection->write(block); + clientConnection->disconnectFromHost(); +} diff --git a/libsrc/bonjour/server.h b/libsrc/bonjour/server.h new file mode 100755 index 00000000..45852b11 --- /dev/null +++ b/libsrc/bonjour/server.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.trolltech.com/products/qt/opensource.html +** +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://www.trolltech.com/products/qt/licensing.html or contact the +** sales department at sales@trolltech.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef SERVER_H +#define SERVER_H + +#include + +class QLabel; +class QPushButton; +class QTcpServer; +class BonjourServiceRegister; + +class Server : public QDialog +{ + Q_OBJECT + +public: + Server(QWidget *parent = 0); + +private slots: + void sendFortune(); + +private: + QLabel *statusLabel; + QPushButton *quitButton; + QTcpServer *tcpServer; + QStringList fortunes; + BonjourServiceRegister *bonjourRegister; +}; + +#endif diff --git a/libsrc/jsonserver/JsonServer.cpp b/libsrc/jsonserver/JsonServer.cpp index 33e06017..54a8fe94 100644 --- a/libsrc/jsonserver/JsonServer.cpp +++ b/libsrc/jsonserver/JsonServer.cpp @@ -29,6 +29,7 @@ JsonServer::JsonServer(Hyperion *hyperion, uint16_t port) : // make sure the resources are loaded (they may be left out after static linking Q_INIT_RESOURCE(JsonSchemas); + } JsonServer::~JsonServer() diff --git a/src/hyperiond/CMakeLists.txt b/src/hyperiond/CMakeLists.txt index ed72cff0..42930d53 100644 --- a/src/hyperiond/CMakeLists.txt +++ b/src/hyperiond/CMakeLists.txt @@ -35,9 +35,12 @@ if (ENABLE_PROTOBUF) target_link_libraries(hyperiond protoserver) endif () +if (ENABLE_ZEROCONF) + target_link_libraries(hyperiond bonjour) +endif() + install ( TARGETS hyperiond DESTINATION "bin" COMPONENT ambilight ) install ( DIRECTORY ${CMAKE_SOURCE_DIR}/effects DESTINATION "share/hyperion/" COMPONENT ambilight ) install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "share/hyperion/" COMPONENT ambilight ) install ( DIRECTORY ${CMAKE_SOURCE_DIR}/config DESTINATION "share/hyperion/" COMPONENT ambilight ) - diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 398a6770..329fe2db 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -52,6 +52,12 @@ // Effect engine includes #include +#ifdef ENABLE_ZEROCONF +#include +#include +#include +#endif + // JsonServer includes #include @@ -188,6 +194,19 @@ void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonSer const Json::Value & jsonServerConfig = config["jsonServer"]; jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt()); std::cout << "INFO: Json server created and started on port " << jsonServer->getPort() << std::endl; +#ifdef ENABLE_ZEROCONF + const Json::Value & deviceConfig = config["device"]; + const std::string deviceName = deviceConfig.get("name", "").asString(); + + const std::string hostname = QHostInfo::localHostName().toStdString(); + const std::string mDNSDescr = jsonServerConfig.get("mDNSDescr", hostname).asString(); + const std::string mDNSService = jsonServerConfig.get("mDNSService", "_hyperiond_json._tcp").asString(); + BonjourServiceRegister *bonjourRegister_json; + bonjourRegister_json = new BonjourServiceRegister(); + bonjourRegister_json->registerService(BonjourRecord((deviceName + " @ " + mDNSDescr).c_str(), mDNSService.c_str(), + QString()), jsonServerConfig["port"].asUInt()); + std::cout << "INFO: Json mDNS responder started" << std::endl; +#endif } // Create Proto server if configuration is present @@ -196,6 +215,19 @@ void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonSer const Json::Value & protoServerConfig = config["protoServer"]; protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); std::cout << "INFO: Proto server created and started on port " << protoServer->getPort() << std::endl; +#ifdef ENABLE_ZEROCONF + const Json::Value & deviceConfig = config["device"]; + const std::string deviceName = deviceConfig.get("name", "").asString(); + + const std::string hostname = QHostInfo::localHostName().toStdString(); + const std::string mDNSDescr = protoServerConfig.get("mDNSDescr", hostname).asString(); + const std::string mDNSService = protoServerConfig.get("mDNSService", "_hyperiond_proto._tcp").asString(); + BonjourServiceRegister *bonjourRegister_proto; + bonjourRegister_proto = new BonjourServiceRegister(); + bonjourRegister_proto->registerService(BonjourRecord((deviceName + " @ " + mDNSDescr).c_str(), mDNSService.c_str(), + QString()), protoServerConfig["port"].asUInt()); + std::cout << "INFO: Proto mDNS responder started" << std::endl; +#endif } // Create Boblight server if configuration is present From d5ce395e8e76b43513f7dd337a9164ea2ca572ba Mon Sep 17 00:00:00 2001 From: penfold42 Date: Wed, 1 Jun 2016 06:55:56 +1000 Subject: [PATCH 36/63] Add sk6812rgbw support (#666) * Removed -HUP so the default -TERM signal is sent instead. - hyperiond only listens for TERM and INT. HUP is often used to get an exe to reread its config Changed pgrep to add '-x' so it wont partial match on the exe name. - I have multiple instances with multiple hyperiond-instance1 names - this ensures the service script only kills the right process * reversing errant change to hyperion.systemd.sh * adding support for SK6812 - not working yet * Changed rpi_ws281x submodule to be penfold42's fork * Set White to zero for now * starting on the code to make the White led do stuff * Added some basic whie led calculation white = min(r,g,b) r-=w, g-=w, b-=w * cleaned up a couple of compiler warnings * updated strip type to use corrected RGBW strip type (the SK6812RGBW datasheet is wrong) * moved bitpair_to_byte initialiser to (hopefully) work with older GCC * compiler warning in udp driver removed some tabs in ws2812b.cpp * formatting - spaces to tabs * moved rpi_281x to tag sk6812-v1.0 * attempt #3 at migrating the rpi_281x submodule to my fork/branch * moving to my fork of rpi_281x * Started implementing multiple RGB to RGBW conversion options a quick hack has been implemented inside WS281x.cpp but ive started moving this to RgbToRgbw.cpp for reuse by other led device types * migrated RGB to RGBW conversion to RgbToRgbw.cpp Former-commit-id: ff8e9038c4bb8203b71b42d12bf23be4abcc0b3b --- .gitmodules | 3 +- include/leddevice/LedDevice.h | 2 + include/utils/ColorRgbw.h | 65 +++++++++++++++++++++++++++ include/utils/RgbToRgbw.h | 4 ++ libsrc/leddevice/LedDeviceFactory.cpp | 5 ++- libsrc/leddevice/LedDeviceWS281x.cpp | 25 +++++++++-- libsrc/leddevice/LedDeviceWS281x.h | 6 ++- libsrc/utils/CMakeLists.txt | 6 ++- libsrc/utils/ColorRgbw.cpp | 10 +++++ libsrc/utils/RgbToRgbw.cpp | 24 ++++++++++ 10 files changed, 143 insertions(+), 7 deletions(-) create mode 100644 include/utils/ColorRgbw.h create mode 100644 include/utils/RgbToRgbw.h create mode 100644 libsrc/utils/ColorRgbw.cpp create mode 100644 libsrc/utils/RgbToRgbw.cpp diff --git a/.gitmodules b/.gitmodules index 462e3f07..ee8a54b5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,4 +3,5 @@ url = https://github.com/tvdzwan/protobuf.git [submodule "dependencies/external/rpi_ws281x"] path = dependencies/external/rpi_ws281x - url = https://github.com/penfold42/rpi_ws281x + url = https://github.com/penfold42/rpi_ws281x.git + branch = sk6812 diff --git a/include/leddevice/LedDevice.h b/include/leddevice/LedDevice.h index 548770c3..64018f10 100644 --- a/include/leddevice/LedDevice.h +++ b/include/leddevice/LedDevice.h @@ -5,6 +5,8 @@ // Utility includes #include +#include +#include /// /// Interface (pure virtual base class) for LedDevices. diff --git a/include/utils/ColorRgbw.h b/include/utils/ColorRgbw.h new file mode 100644 index 00000000..a06c6d24 --- /dev/null +++ b/include/utils/ColorRgbw.h @@ -0,0 +1,65 @@ +#pragma once + +// STL includes +#include +#include + +struct ColorRgbw; + +/// +/// Plain-Old-Data structure containing the red-green-blue color specification. Size of the +/// structure is exactly 3-bytes for easy writing to led-device +/// +struct ColorRgbw +{ + /// The red color channel + uint8_t red; + /// The green color channel + uint8_t green; + /// The blue color channel + uint8_t blue; + /// The white color channel + uint8_t white; + + /// 'Black' RgbColor (0, 0, 0, 0) + static ColorRgbw BLACK; + /// 'Red' RgbColor (255, 0, 0, 0) + static ColorRgbw RED; + /// 'Green' RgbColor (0, 255, 0, 0) + static ColorRgbw GREEN; + /// 'Blue' RgbColor (0, 0, 255, 0) + static ColorRgbw BLUE; + /// 'Yellow' RgbColor (255, 255, 0, 0) + static ColorRgbw YELLOW; + /// 'White' RgbColor (0, 0, 0, 255) + static ColorRgbw WHITE; +}; + +/// Assert to ensure that the size of the structure is 'only' 4 bytes +static_assert(sizeof(ColorRgbw) == 4, "Incorrect size of ColorRgbw"); + +/// +/// Stream operator to write ColorRgb to an outputstream (format "'{'[red]','[green]','[blue]'}'") +/// +/// @param os The output stream +/// @param color The color to write +/// @return The output stream (with the color written to it) +/// +inline std::ostream& operator<<(std::ostream& os, const ColorRgbw& color) +{ + os << "{" << unsigned(color.red) << "," << unsigned(color.green) << "," << unsigned(color.blue) << "," << unsigned(color.white) << "}"; + return os; +} + + +/// Compare operator to check if a color is 'smaller' than another color +inline bool operator<(const ColorRgbw & lhs, const ColorRgbw & rhs) +{ + return (lhs.red < rhs.red) && (lhs.green < rhs.green) && (lhs.blue < rhs.blue) && (lhs.white < rhs.white); +} + +/// Compare operator to check if a color is 'smaller' than or 'equal' to another color +inline bool operator<=(const ColorRgbw & lhs, const ColorRgbw & rhs) +{ + return (lhs.red <= rhs.red) && (lhs.green <= rhs.green) && (lhs.blue <= rhs.blue) && (lhs.white < rhs.white); +} diff --git a/include/utils/RgbToRgbw.h b/include/utils/RgbToRgbw.h new file mode 100644 index 00000000..99835512 --- /dev/null +++ b/include/utils/RgbToRgbw.h @@ -0,0 +1,4 @@ +#include +#include + +void Rgb_to_Rgbw(ColorRgb input, ColorRgbw * output, std::string _whiteAlgorithm); diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index ed07249c..4013cf40 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -363,8 +363,11 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) const int dmanum = deviceConfig.get("dmanum", 5).asInt(); const int pwmchannel = deviceConfig.get("pwmchannel", 0).asInt(); const int invert = deviceConfig.get("invert", 0).asInt(); + const int rgbw = deviceConfig.get("rgbw", 0).asInt(); + const std::string& whiteAlgorithm = deviceConfig.get("white_algorithm","").asString(); - LedDeviceWS281x * ledDeviceWS281x = new LedDeviceWS281x(gpio, leds, freq, dmanum, pwmchannel, invert); + LedDeviceWS281x * ledDeviceWS281x = new LedDeviceWS281x(gpio, leds, freq, dmanum, pwmchannel, invert, + rgbw, whiteAlgorithm); device = ledDeviceWS281x; } #endif diff --git a/libsrc/leddevice/LedDeviceWS281x.cpp b/libsrc/leddevice/LedDeviceWS281x.cpp index 542ff80c..8349c70b 100644 --- a/libsrc/leddevice/LedDeviceWS281x.cpp +++ b/libsrc/leddevice/LedDeviceWS281x.cpp @@ -3,8 +3,11 @@ #include "LedDeviceWS281x.h" // Constructor -LedDeviceWS281x::LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, const int dmanum, const int pwmchannel, const int invert) +LedDeviceWS281x::LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, const int dmanum, const int pwmchannel, const int invert, const int rgbw, const std::string& whiteAlgorithm) { + _whiteAlgorithm = whiteAlgorithm; +std::cout << "whiteAlgorithm :" << whiteAlgorithm << ":\n"; + initialized = false; led_string.freq = freq; led_string.dmanum = dmanum; @@ -17,7 +20,11 @@ LedDeviceWS281x::LedDeviceWS281x(const int gpio, const int leds, const uint32_t led_string.channel[chan].invert = invert; led_string.channel[chan].count = leds; led_string.channel[chan].brightness = 255; - led_string.channel[chan].strip_type = WS2811_STRIP_RGB; + if (rgbw == 1) { + led_string.channel[chan].strip_type = SK6812_STRIP_GRBW; + } else { + led_string.channel[chan].strip_type = WS2811_STRIP_RGB; + } led_string.channel[!chan].gpionum = 0; led_string.channel[!chan].invert = invert; @@ -42,7 +49,19 @@ int LedDeviceWS281x::write(const std::vector &ledValues) { if (idx >= led_string.channel[chan].count) break; - led_string.channel[chan].leds[idx++] = ((uint32_t)color.red << 16) + ((uint32_t)color.green << 8) + color.blue; + + _temp_rgbw.red = color.red; + _temp_rgbw.green = color.green; + _temp_rgbw.blue = color.blue; + _temp_rgbw.white = 0; + + if (led_string.channel[chan].strip_type == SK6812_STRIP_GRBW) { + Rgb_to_Rgbw(color, &_temp_rgbw, _whiteAlgorithm); + } + + led_string.channel[chan].leds[idx++] = + ((uint32_t)_temp_rgbw.white << 24) + ((uint32_t)_temp_rgbw.red << 16) + ((uint32_t)_temp_rgbw.green << 8) + _temp_rgbw.blue; + } while (idx < led_string.channel[chan].count) led_string.channel[chan].leds[idx++] = 0; diff --git a/libsrc/leddevice/LedDeviceWS281x.h b/libsrc/leddevice/LedDeviceWS281x.h index 29209016..557598a8 100644 --- a/libsrc/leddevice/LedDeviceWS281x.h +++ b/libsrc/leddevice/LedDeviceWS281x.h @@ -18,9 +18,11 @@ public: /// @param dmanum The DMA channel to use, default is 5 /// @param pwmchannel The pwm channel to use /// @param invert Invert the output line to support an inverting level shifter + /// @param rgbw Send 32 bit rgbw colour data for sk6812 /// - LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, int dmanum, int pwmchannel, int invert); + LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, int dmanum, int pwmchannel, int invert, + int rgbw, const std::string& whiteAlgorithm); /// /// Destructor of the LedDevice, waits for DMA to complete and then cleans up @@ -42,6 +44,8 @@ private: ws2811_t led_string; int chan; bool initialized; + std::string _whiteAlgorithm; + ColorRgbw _temp_rgbw; }; #endif /* LEDDEVICEWS281X_H_ */ diff --git a/libsrc/utils/CMakeLists.txt b/libsrc/utils/CMakeLists.txt index 1b9e2982..caf0aabe 100644 --- a/libsrc/utils/CMakeLists.txt +++ b/libsrc/utils/CMakeLists.txt @@ -1,4 +1,3 @@ - # Define the current source locations SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/utils) SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/utils) @@ -12,6 +11,8 @@ add_library(hyperion-utils ${CURRENT_SOURCE_DIR}/ColorRgb.cpp ${CURRENT_HEADER_DIR}/ColorRgba.h ${CURRENT_SOURCE_DIR}/ColorRgba.cpp + ${CURRENT_HEADER_DIR}/ColorRgbw.h + ${CURRENT_SOURCE_DIR}/ColorRgbw.cpp ${CURRENT_HEADER_DIR}/Image.h ${CURRENT_HEADER_DIR}/Sleep.h @@ -32,6 +33,9 @@ add_library(hyperion-utils ${CURRENT_HEADER_DIR}/RgbChannelAdjustment.h ${CURRENT_SOURCE_DIR}/RgbChannelAdjustment.cpp + ${CURRENT_HEADER_DIR}/RgbToRgbw.h + ${CURRENT_SOURCE_DIR}/RgbToRgbw.cpp + ${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h ${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h ${CURRENT_SOURCE_DIR}/jsonschema/JsonSchemaChecker.cpp diff --git a/libsrc/utils/ColorRgbw.cpp b/libsrc/utils/ColorRgbw.cpp new file mode 100644 index 00000000..af7cf9da --- /dev/null +++ b/libsrc/utils/ColorRgbw.cpp @@ -0,0 +1,10 @@ + +// Local includes +#include + +ColorRgbw ColorRgbw::BLACK = { 0, 0, 0, 0 }; +ColorRgbw ColorRgbw::RED = { 255, 0, 0, 0 }; +ColorRgbw ColorRgbw::GREEN = { 0, 255, 0, 0 }; +ColorRgbw ColorRgbw::BLUE = { 0, 0, 255, 0 }; +ColorRgbw ColorRgbw::YELLOW= { 255, 255, 0, 0 }; +ColorRgbw ColorRgbw::WHITE = { 0, 0, 0, 255 }; diff --git a/libsrc/utils/RgbToRgbw.cpp b/libsrc/utils/RgbToRgbw.cpp new file mode 100644 index 00000000..f71fa4fe --- /dev/null +++ b/libsrc/utils/RgbToRgbw.cpp @@ -0,0 +1,24 @@ +#include +#include + +void Rgb_to_Rgbw(ColorRgb input, ColorRgbw * output, std::string _whiteAlgorithm) { + if (_whiteAlgorithm == "subtract_minimum") { + output->white = std::min(input.red, input.green); + output->white = std::min(output->white, input.blue); + output->red = input.red - output->white; + output->green = input.green - output->white; + output->blue = input.blue - output->white; + } + else if (_whiteAlgorithm == "sub_min_warm_adjust") { + } + else if ( (_whiteAlgorithm == "") || (_whiteAlgorithm == "white_off") ) { + output->red = input.red; + output->green = input.green; + output->blue = input.blue; + output->white = 0; + } + else { + std::cout << "ERROR: unknown whiteAlgorithm " << _whiteAlgorithm << std::endl; + } +} + From 57e74e52f5b55d0715c0a54d01c2af5835d6f715 Mon Sep 17 00:00:00 2001 From: brindosch Date: Tue, 31 May 2016 23:27:53 +0200 Subject: [PATCH 37/63] update release.sh Former-commit-id: 26c8b198459fcbb9af908bcf2242639edbebea44 --- bin/create_all_releases.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/create_all_releases.sh b/bin/create_all_releases.sh index 614325ae..a6ef53c2 100644 --- a/bin/create_all_releases.sh +++ b/bin/create_all_releases.sh @@ -13,7 +13,7 @@ make_release() mkdir -p build-${RELEASE} mkdir -p deploy/${RELEASE} cd build-${RELEASE} - cmake -DCMAKE_INSTALL_PREFIX=/usr -DPLATFORM=${PLATFORM} $@ -DCMAKE_BUILD_TYPE=Release -Wno-dev .. || exit 1 + cmake -DCMAKE_INSTALL_PREFIX=/usr -DPLATFORM=${PLATFORM} $@ -DENABLE_ZEROCONF=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. || exit 1 make -j $(nproc) || exit 1 #strip bin/* make package -j $(nproc) From 4f6ab258ef23494392107b07569617d5f4a78000 Mon Sep 17 00:00:00 2001 From: redPanther Date: Thu, 2 Jun 2016 19:54:37 +0200 Subject: [PATCH 38/63] debian package (#669) * implement make install set CMAKE_INSTALL_PREFIX e.g. to /opt to install to /opt/hyperion set ENABLE_SYSTEM_INSTALL to ON to activate installation after compiling use make install or make install/strip (for performance/size optimized binaries - compile in Release to get best performance) * cleanup cmake files use cmake -DINSTALL_PREFIX=/opt/hyperion .. to install all files to hyperion or cmake -DINSTALL_PREFIX=/usr/ to install to usr. install folders are linux standard. bin go to bin folder and additionals (effects) go to share/hyperion * add uninstall target - be patient with that, this will remove files from your system install service files to share/hyperion - if you want to use them you have to make a symlink to your location of service files * optimize build release script install service files into hyperion share folder (services not activated, this must be done by distribution package script) initial support of cmake option -DPLATFORM= option. This selects platform specific cmake flags. no need for -DENABLE_... options (unless you want some special things) automatic detect for apple build * update submodule * fix cmake error when no platform is given * initial support for deb,rpm and tgz packages - no usefull content atm! * make packeages contain usefull stuff * add license make packes more functional. package specific install missing yet * implement debian postinstall * disable rpm generation until it has a working state * add hypercon compat * add posibility for multiple config files. first one found is taken * remove hyperion comaptlayer services is not started automaticly * rework debian postinstall: - remove /opt compatibility complety. This makes more trouble as it is usefull - when hyperiond already started, restart it - cleanup * add deb package dependencies * wipe out last support for /opt installation * change default effect path in config to /usr * revert service files and config files Former-commit-id: 4462021775b71a78497e0f0887a9f58111f91a5e --- cmake/debian/postinst | 69 ++++++++++++++++++++++++++++++------------- cmake/packages.cmake | 2 +- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/cmake/debian/postinst b/cmake/debian/postinst index 69ba8fc6..84136321 100644 --- a/cmake/debian/postinst +++ b/cmake/debian/postinst @@ -7,10 +7,13 @@ install_file() if [ -e "$dest" ] && ! cmp --quiet "$src" "$dest" then + echo "INFO: $dest exists, new version copied to ${dest}.new" cp "$src" "${dest}.new" - else - cp "$src" "${dest}" + return 1 fi + + cp "$src" "${dest}" + return 0 } @@ -20,13 +23,33 @@ mkdir -p /etc/hyperion install_file /usr/share/hyperion/config/hyperion.config.json /etc/hyperion/hyperion.config.json -if grep -m1 systemd /proc/1/comm > /dev/null +HYPERION_RUNNING=false +pgrep hyperiond > /dev/null 2>&1 && HYPERION_RUNNING=true + +start_msg="" +restart_msg="" +SERVICE_POSTFIX="" + +if [ -e /sbin/initctl ] then + echo "- init deamon: upstart" + # upstart + $HYPERION_RUNNING && initctl stop hyperion + install_file /usr/share/hyperion/service/hyperion.initctl.sh /etc/init/hyperion.conf || SERVICE_POSTFIX=".new" + initctl reload-configuration + start_msg="initctl start hyperion" + $HYPERION_RUNNING && initctl start hyperion + +elif grep -m1 systemd /proc/1/comm > /dev/null +then + echo "- init deamon: systemd" # systemd - echo - systemctl stop hyperion 2> /dev/null - install_file /usr/share/hyperion/service/hyperion.systemd.sh /etc/systemd/system/hyperion.service + $HYPERION_RUNNING && systemctl stop hyperion 2> /dev/null + install_file /usr/share/hyperion/service/hyperion.systemd.sh /etc/systemd/system/hyperion.service || SERVICE_POSTFIX=".new" systemctl -q enable hyperion.service + start_msg="systemctl start hyperion" + $HYPERION_RUNNING && systemctl start hyperion + # if [ $OS_OSMC -eq 1 ]; then # echo '---> Modify systemd script for OSMC usage' # # Wait until kodi is sarted (for kodi checker) @@ -36,25 +59,29 @@ then # sed -i 's/Group=osmc/Group=root/g' /etc/systemd/system/hyperion.service # systemctl -q daemon-reload # fi - systemctl start hyperion - -elif [ -e /sbin/initctl ] -then - # upstart - install_file /usr/share/hyperion/service/hyperion.initctl.sh /etc/init/hyperion.conf - initctl reload-configuration - initctl start hyperion +# systemctl start hyperion else + echo "- init deamon: sysV" # sysV - service hyperion stop 2>/dev/null - install_file /usr/share/hyperion/service/hyperion.init.sh /etc/init.d/hyperion + $HYPERION_RUNNING && service hyperion stop 2>/dev/null + install_file /usr/share/hyperion/service/hyperion.init.sh /etc/init.d/hyperion || SERVICE_POSTFIX=".new" chmod +x /etc/init.d/hyperion update-rc.d hyperion defaults 98 02 - service hyperion start + start_msg="service hyperion start" + $HYPERION_RUNNING && service hyperion start +fi + +echo "-----------------------------------------------------------------------------" +echo "- hyperion is installed, please check your configuration in /etc/hyperion/ -" +echo "-----------------------------------------------------------------------------" + +if [ -e /opt/hyperion/ ] +then + echo + echo "---------------------------------------------------------------------------------" + echo "- It seemd that you have an older version of hyperion installed in /opt/hyerion -" + echo "- please remove it and check your config to avoid problems -" + echo "---------------------------------------------------------------------------------" fi -echo "- done" -# hypercon compat -mkdir -p /opt/hyperion/config -ln -sf /usr/share/hyperion/effects /opt/hyperion/effects diff --git a/cmake/packages.cmake b/cmake/packages.cmake index ed8fe87c..ca821a5c 100644 --- a/cmake/packages.cmake +++ b/cmake/packages.cmake @@ -11,7 +11,7 @@ SET ( CPACK_DEBIAN_PACKAGE_MAINTAINER "hyperion team") SET ( CPACK_DEBIAN_PACKAGE_NAME "hyperion" ) SET ( CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/cmake/debian/postinst" ) SET ( CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/hyperion-project/hyperion" ) -SET ( CPACK_DEBIAN_PACKAGE_DEPENDS "libqtcore4 (>= 4:4.8.0), libqt4-network (>= 4:4.8.0)" ) +SET ( CPACK_DEBIAN_PACKAGE_DEPENDS "libqtcore4 (>= 4:4.8.0), libqt4-network (>= 4:4.8.0), libusb-1.0-0, libpython2.7, libc6" ) SET ( CPACK_DEBIAN_PACKAGE_SECTION "Miscellaneous" ) SET ( CPACK_RPM_PACKAGE_NAME "hyperion" ) From e8207cfe3175087687782cbd1a079673f79e9dd9 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Sat, 4 Jun 2016 00:46:45 +1000 Subject: [PATCH 39/63] fix more "dos" line endings (#673) * Removed -HUP so the default -TERM signal is sent instead. - hyperiond only listens for TERM and INT. HUP is often used to get an exe to reread its config Changed pgrep to add '-x' so it wont partial match on the exe name. - I have multiple instances with multiple hyperiond-instance1 names - this ensures the service script only kills the right process * reversing errant change to hyperion.systemd.sh * cleaned up a couple of compiler warnings * moved bitpair_to_byte initialiser to (hopefully) work with older GCC * compiler warning in udp driver removed some tabs in ws2812b.cpp * formatting - spaces to tabs * moved rpi_281x to tag sk6812-v1.0 * moving to my fork of rpi_281x * removed dos line endings * Found some more "dos" line ending files Former-commit-id: c756e3ccc153fd36e23a26eff37a1230bdd4b9b4 --- dependencies/CMakeLists.txt | 220 +-- .../include/tinkerforge/ip_connection.h | 1260 ++++++++--------- libsrc/bonjour/CMakeLists.txt | 104 +- libsrc/leddevice/LedDevicePhilipsHue.cpp | 684 ++++----- test/TestSpi.cpp | 322 ++--- 5 files changed, 1295 insertions(+), 1295 deletions(-) diff --git a/dependencies/CMakeLists.txt b/dependencies/CMakeLists.txt index 43569460..0ba08dd5 100644 --- a/dependencies/CMakeLists.txt +++ b/dependencies/CMakeLists.txt @@ -1,110 +1,110 @@ -add_subdirectory(build/getoptPlusPlus) -add_subdirectory(build/hidapi) -add_subdirectory(build/jsoncpp) -add_subdirectory(build/serial) -add_subdirectory(build/tinkerforge) - -if(ENABLE_WS281XPWM) - add_library(ws281x - external/rpi_ws281x/mailbox.c external/rpi_ws281x/ws2811.c - external/rpi_ws281x/pwm.c external/rpi_ws281x/dma.c - external/rpi_ws281x/rpihw.c) -endif(ENABLE_WS281XPWM) - -if(ENABLE_PROTOBUF) - set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared protobuf library") - add_subdirectory(external/protobuf) - - if(CMAKE_CROSSCOMPILING) - # when crosscompiling import the protoc executable targets from a file generated by a native build - option(IMPORT_PROTOC "Protoc export file (protoc_export.cmake) from a native build" "IMPORT_PROTOC-FILE_NOT_FOUND") - include(${IMPORT_PROTOC}) - else() - # export the protoc compiler so it can be used when cross compiling - export(TARGETS protoc_compiler FILE "${CMAKE_BINARY_DIR}/protoc_export.cmake") - endif() - - # define the include for the protobuf library at the parent scope - set(PROTOBUF_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/external/protobuf/src") - set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS} PARENT_SCOPE) - - # define the protoc executable at the parent scope - get_property(PROTOBUF_PROTOC_EXECUTABLE TARGET protoc_compiler PROPERTY LOCATION) - set(PROTOBUF_PROTOC_EXECUTABLE ${PROTOBUF_PROTOC_EXECUTABLE} PARENT_SCOPE) - message(STATUS "Using protobuf compiler: " ${PROTOBUF_PROTOC_EXECUTABLE}) - - #============================================================================= - # Copyright 2009 Kitware, Inc. - # Copyright 2009-2011 Philip Lowman - # Copyright 2008 Esben Mose Hansen, Ange Optimization ApS - # - # Distributed under the OSI-approved BSD License (the "License"); - # see accompanying file Copyright.txt for details. - # - # This software is distributed WITHOUT ANY WARRANTY; without even the - # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - # See the License for more information. - #============================================================================= - # (To distribute this file outside of CMake, substitute the full - # License text for the above reference.) - function(PROTOBUF_GENERATE_CPP SRCS HDRS) - if(NOT ARGN) - message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files") - return() - endif() - - if(PROTOBUF_GENERATE_CPP_APPEND_PATH) - # Create an include path for each file specified - foreach(FIL ${ARGN}) - get_filename_component(ABS_FIL ${FIL} ABSOLUTE) - get_filename_component(ABS_PATH ${ABS_FIL} PATH) - list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) - if(${_contains_already} EQUAL -1) - list(APPEND _protobuf_include_path -I ${ABS_PATH}) - endif() - endforeach() - else() - set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR}) - endif() - - if(DEFINED PROTOBUF_IMPORT_DIRS) - foreach(DIR ${PROTOBUF_IMPORT_DIRS}) - get_filename_component(ABS_PATH ${DIR} ABSOLUTE) - list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) - if(${_contains_already} EQUAL -1) - list(APPEND _protobuf_include_path -I ${ABS_PATH}) - endif() - endforeach() - endif() - - if(CMAKE_CROSSCOMPILING) - set(PROTOC_DEPENDENCY ${PROTOBUF_PROTOC_EXECUTABLE}) - else() - set(PROTOC_DEPENDENCY protoc_compiler) - endif() - - set(${SRCS}) - set(${HDRS}) - foreach(FIL ${ARGN}) - get_filename_component(ABS_FIL ${FIL} ABSOLUTE) - get_filename_component(FIL_WE ${FIL} NAME_WE) - - list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc") - list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h") - - add_custom_command( - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc" - "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h" - COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} - ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL} - DEPENDS ${ABS_FIL} ${PROTOC_DEPENDENCY} - COMMENT "Running C++ protocol buffer compiler on ${FIL}" - VERBATIM - ) - endforeach() - - set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE) - set(${SRCS} ${${SRCS}} PARENT_SCOPE) - set(${HDRS} ${${HDRS}} PARENT_SCOPE) - endfunction() -endif() +add_subdirectory(build/getoptPlusPlus) +add_subdirectory(build/hidapi) +add_subdirectory(build/jsoncpp) +add_subdirectory(build/serial) +add_subdirectory(build/tinkerforge) + +if(ENABLE_WS281XPWM) + add_library(ws281x + external/rpi_ws281x/mailbox.c external/rpi_ws281x/ws2811.c + external/rpi_ws281x/pwm.c external/rpi_ws281x/dma.c + external/rpi_ws281x/rpihw.c) +endif(ENABLE_WS281XPWM) + +if(ENABLE_PROTOBUF) + set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared protobuf library") + add_subdirectory(external/protobuf) + + if(CMAKE_CROSSCOMPILING) + # when crosscompiling import the protoc executable targets from a file generated by a native build + option(IMPORT_PROTOC "Protoc export file (protoc_export.cmake) from a native build" "IMPORT_PROTOC-FILE_NOT_FOUND") + include(${IMPORT_PROTOC}) + else() + # export the protoc compiler so it can be used when cross compiling + export(TARGETS protoc_compiler FILE "${CMAKE_BINARY_DIR}/protoc_export.cmake") + endif() + + # define the include for the protobuf library at the parent scope + set(PROTOBUF_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/external/protobuf/src") + set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS} PARENT_SCOPE) + + # define the protoc executable at the parent scope + get_property(PROTOBUF_PROTOC_EXECUTABLE TARGET protoc_compiler PROPERTY LOCATION) + set(PROTOBUF_PROTOC_EXECUTABLE ${PROTOBUF_PROTOC_EXECUTABLE} PARENT_SCOPE) + message(STATUS "Using protobuf compiler: " ${PROTOBUF_PROTOC_EXECUTABLE}) + + #============================================================================= + # Copyright 2009 Kitware, Inc. + # Copyright 2009-2011 Philip Lowman + # Copyright 2008 Esben Mose Hansen, Ange Optimization ApS + # + # Distributed under the OSI-approved BSD License (the "License"); + # see accompanying file Copyright.txt for details. + # + # This software is distributed WITHOUT ANY WARRANTY; without even the + # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + # See the License for more information. + #============================================================================= + # (To distribute this file outside of CMake, substitute the full + # License text for the above reference.) + function(PROTOBUF_GENERATE_CPP SRCS HDRS) + if(NOT ARGN) + message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files") + return() + endif() + + if(PROTOBUF_GENERATE_CPP_APPEND_PATH) + # Create an include path for each file specified + foreach(FIL ${ARGN}) + get_filename_component(ABS_FIL ${FIL} ABSOLUTE) + get_filename_component(ABS_PATH ${ABS_FIL} PATH) + list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) + if(${_contains_already} EQUAL -1) + list(APPEND _protobuf_include_path -I ${ABS_PATH}) + endif() + endforeach() + else() + set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR}) + endif() + + if(DEFINED PROTOBUF_IMPORT_DIRS) + foreach(DIR ${PROTOBUF_IMPORT_DIRS}) + get_filename_component(ABS_PATH ${DIR} ABSOLUTE) + list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) + if(${_contains_already} EQUAL -1) + list(APPEND _protobuf_include_path -I ${ABS_PATH}) + endif() + endforeach() + endif() + + if(CMAKE_CROSSCOMPILING) + set(PROTOC_DEPENDENCY ${PROTOBUF_PROTOC_EXECUTABLE}) + else() + set(PROTOC_DEPENDENCY protoc_compiler) + endif() + + set(${SRCS}) + set(${HDRS}) + foreach(FIL ${ARGN}) + get_filename_component(ABS_FIL ${FIL} ABSOLUTE) + get_filename_component(FIL_WE ${FIL} NAME_WE) + + list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc") + list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h") + + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc" + "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h" + COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} + ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL} + DEPENDS ${ABS_FIL} ${PROTOC_DEPENDENCY} + COMMENT "Running C++ protocol buffer compiler on ${FIL}" + VERBATIM + ) + endforeach() + + set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE) + set(${SRCS} ${${SRCS}} PARENT_SCOPE) + set(${HDRS} ${${HDRS}} PARENT_SCOPE) + endfunction() +endif() diff --git a/dependencies/include/tinkerforge/ip_connection.h b/dependencies/include/tinkerforge/ip_connection.h index 5369bf76..bd86940b 100644 --- a/dependencies/include/tinkerforge/ip_connection.h +++ b/dependencies/include/tinkerforge/ip_connection.h @@ -1,630 +1,630 @@ -/* - * Copyright (C) 2012-2013 Matthias Bolte - * Copyright (C) 2011 Olaf Lüke - * - * Redistribution and use in source and binary forms of this file, - * with or without modification, are permitted. - */ - -#ifndef IP_CONNECTION_H -#define IP_CONNECTION_H - -/** - * \defgroup IPConnection IP Connection - */ - -#ifndef __STDC_LIMIT_MACROS - #define __STDC_LIMIT_MACROS -#endif -#include -#include -#include - -#if !defined __cplusplus && defined __GNUC__ - #include -#endif - -#ifdef _WIN32 - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #include -#else - #include - #include -#endif - -enum { - E_OK = 0, - E_TIMEOUT = -1, - E_NO_STREAM_SOCKET = -2, - E_HOSTNAME_INVALID = -3, - E_NO_CONNECT = -4, - E_NO_THREAD = -5, - E_NOT_ADDED = -6, // unused since v2.0 - E_ALREADY_CONNECTED = -7, - E_NOT_CONNECTED = -8, - E_INVALID_PARAMETER = -9, // error response from device - E_NOT_SUPPORTED = -10, // error response from device - E_UNKNOWN_ERROR_CODE = -11 // error response from device -}; - -#ifdef IPCON_EXPOSE_INTERNALS - -typedef struct _Socket Socket; - -typedef struct { -#ifdef _WIN32 - CRITICAL_SECTION handle; -#else - pthread_mutex_t handle; -#endif -} Mutex; - -void mutex_create(Mutex *mutex); - -void mutex_destroy(Mutex *mutex); - -void mutex_lock(Mutex *mutex); - -void mutex_unlock(Mutex *mutex); - -typedef struct { -#ifdef _WIN32 - HANDLE handle; -#else - pthread_cond_t condition; - pthread_mutex_t mutex; - bool flag; -#endif -} Event; - -typedef struct { -#ifdef _WIN32 - HANDLE handle; -#else - sem_t object; - sem_t *pointer; -#endif -} Semaphore; - -typedef void (*ThreadFunction)(void *opaque); - -typedef struct { -#ifdef _WIN32 - HANDLE handle; - DWORD id; -#else - pthread_t handle; -#endif - ThreadFunction function; - void *opaque; -} Thread; - -typedef struct { - Mutex mutex; - int used; - int allocated; - uint32_t *keys; - void **values; -} Table; - -typedef struct _QueueItem { - struct _QueueItem *next; - int kind; - void *data; - int length; -} QueueItem; - -typedef struct { - Mutex mutex; - Semaphore semaphore; - QueueItem *head; - QueueItem *tail; -} Queue; - -#if defined _MSC_VER || defined __BORLANDC__ - #pragma pack(push) - #pragma pack(1) - #define ATTRIBUTE_PACKED -#elif defined __GNUC__ - #ifdef _WIN32 - // workaround struct packing bug in GCC 4.7 on Windows - // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 - #define ATTRIBUTE_PACKED __attribute__((gcc_struct, packed)) - #else - #define ATTRIBUTE_PACKED __attribute__((packed)) - #endif -#else - #error unknown compiler, do not know how to enable struct packing -#endif - -typedef struct { - uint32_t uid; - uint8_t length; - uint8_t function_id; - uint8_t sequence_number_and_options; - uint8_t error_code_and_future_use; -} ATTRIBUTE_PACKED PacketHeader; - -typedef struct { - PacketHeader header; - uint8_t payload[64]; - uint8_t optional_data[8]; -} ATTRIBUTE_PACKED Packet; - -#if defined _MSC_VER || defined __BORLANDC__ - #pragma pack(pop) -#endif -#undef ATTRIBUTE_PACKED - -#endif // IPCON_EXPOSE_INTERNALS - -typedef struct _IPConnection IPConnection; -typedef struct _IPConnectionPrivate IPConnectionPrivate; -typedef struct _Device Device; -typedef struct _DevicePrivate DevicePrivate; - -#ifdef IPCON_EXPOSE_INTERNALS - -typedef struct _CallbackContext CallbackContext; - -#endif - -typedef void (*EnumerateCallbackFunction)(const char *uid, - const char *connected_uid, - char position, - uint8_t hardware_version[3], - uint8_t firmware_version[3], - uint16_t device_identifier, - uint8_t enumeration_type, - void *user_data); -typedef void (*ConnectedCallbackFunction)(uint8_t connect_reason, - void *user_data); -typedef void (*DisconnectedCallbackFunction)(uint8_t disconnect_reason, - void *user_data); - -#ifdef IPCON_EXPOSE_INTERNALS - -typedef void (*CallbackWrapperFunction)(DevicePrivate *device_p, Packet *packet); - -#endif - -/** - * \internal - */ -struct _Device { - DevicePrivate *p; -}; - -#ifdef IPCON_EXPOSE_INTERNALS - -#define DEVICE_NUM_FUNCTION_IDS 256 - -/** - * \internal - */ -struct _DevicePrivate { - uint32_t uid; - - IPConnectionPrivate *ipcon_p; - - uint8_t api_version[3]; - - Mutex request_mutex; - - uint8_t expected_response_function_id; // protected by request_mutex - uint8_t expected_response_sequence_number; // protected by request_mutex - Mutex response_mutex; - Packet response_packet; // protected by response_mutex - Event response_event; - int response_expected[DEVICE_NUM_FUNCTION_IDS]; - - void *registered_callbacks[DEVICE_NUM_FUNCTION_IDS]; - void *registered_callback_user_data[DEVICE_NUM_FUNCTION_IDS]; - CallbackWrapperFunction callback_wrappers[DEVICE_NUM_FUNCTION_IDS]; -}; - -/** - * \internal - */ -enum { - DEVICE_RESPONSE_EXPECTED_INVALID_FUNCTION_ID = 0, - DEVICE_RESPONSE_EXPECTED_ALWAYS_TRUE, // getter - DEVICE_RESPONSE_EXPECTED_ALWAYS_FALSE, // callback - DEVICE_RESPONSE_EXPECTED_TRUE, // setter - DEVICE_RESPONSE_EXPECTED_FALSE // setter, default -}; - -/** - * \internal - */ -void device_create(Device *device, const char *uid, - IPConnectionPrivate *ipcon_p, uint8_t api_version_major, - uint8_t api_version_minor, uint8_t api_version_release); - -/** - * \internal - */ -void device_destroy(Device *device); - -/** - * \internal - */ -int device_get_response_expected(DevicePrivate *device_p, uint8_t function_id, - bool *ret_response_expected); - -/** - * \internal - */ -int device_set_response_expected(DevicePrivate *device_p, uint8_t function_id, - bool response_expected); - -/** - * \internal - */ -int device_set_response_expected_all(DevicePrivate *device_p, bool response_expected); - -/** - * \internal - */ -void device_register_callback(DevicePrivate *device_p, uint8_t id, void *callback, - void *user_data); - -/** - * \internal - */ -int device_get_api_version(DevicePrivate *device_p, uint8_t ret_api_version[3]); - -/** - * \internal - */ -int device_send_request(DevicePrivate *device_p, Packet *request, Packet *response); - -#endif // IPCON_EXPOSE_INTERNALS - -/** - * \ingroup IPConnection - * - * Possible IDs for ipcon_register_callback. - */ -enum { - IPCON_CALLBACK_ENUMERATE = 253, - IPCON_CALLBACK_CONNECTED = 0, - IPCON_CALLBACK_DISCONNECTED = 1 -}; - -/** - * \ingroup IPConnection - * - * Possible values for enumeration_type parameter of EnumerateCallback. - */ -enum { - IPCON_ENUMERATION_TYPE_AVAILABLE = 0, - IPCON_ENUMERATION_TYPE_CONNECTED = 1, - IPCON_ENUMERATION_TYPE_DISCONNECTED = 2 -}; - -/** - * \ingroup IPConnection - * - * Possible values for connect_reason parameter of ConnectedCallback. - */ -enum { - IPCON_CONNECT_REASON_REQUEST = 0, - IPCON_CONNECT_REASON_AUTO_RECONNECT = 1 -}; - -/** - * \ingroup IPConnection - * - * Possible values for disconnect_reason parameter of DisconnectedCallback. - */ -enum { - IPCON_DISCONNECT_REASON_REQUEST = 0, - IPCON_DISCONNECT_REASON_ERROR = 1, - IPCON_DISCONNECT_REASON_SHUTDOWN = 2 -}; - -/** - * \ingroup IPConnection - * - * Possible return values of ipcon_get_connection_state. - */ -enum { - IPCON_CONNECTION_STATE_DISCONNECTED = 0, - IPCON_CONNECTION_STATE_CONNECTED = 1, - IPCON_CONNECTION_STATE_PENDING = 2 // auto-reconnect in progress -}; - -/** - * \internal - */ -struct _IPConnection { - IPConnectionPrivate *p; -}; - -#ifdef IPCON_EXPOSE_INTERNALS - -#define IPCON_NUM_CALLBACK_IDS 256 - -/** - * \internal - */ -struct _IPConnectionPrivate { -#ifdef _WIN32 - bool wsa_startup_done; // protected by socket_mutex -#endif - - char *host; - uint16_t port; - - uint32_t timeout; // in msec - - bool auto_reconnect; - bool auto_reconnect_allowed; - bool auto_reconnect_pending; - - Mutex sequence_number_mutex; - uint8_t next_sequence_number; // protected by sequence_number_mutex - - Table devices; - - void *registered_callbacks[IPCON_NUM_CALLBACK_IDS]; - void *registered_callback_user_data[IPCON_NUM_CALLBACK_IDS]; - - Mutex socket_mutex; - Socket *socket; // protected by socket_mutex - uint64_t socket_id; // protected by socket_mutex - - bool receive_flag; - Thread receive_thread; // protected by socket_mutex - - CallbackContext *callback; - - bool disconnect_probe_flag; - Thread disconnect_probe_thread; // protected by socket_mutex - Event disconnect_probe_event; - - Semaphore wait; -}; - -#endif // IPCON_EXPOSE_INTERNALS - -/** - * \ingroup IPConnection - * - * Creates an IP Connection object that can be used to enumerate the available - * devices. It is also required for the constructor of Bricks and Bricklets. - */ -void ipcon_create(IPConnection *ipcon); - -/** - * \ingroup IPConnection - * - * Destroys the IP Connection object. Calls ipcon_disconnect internally. - * The connection to the Brick Daemon gets closed and the threads of the - * IP Connection are terminated. - */ -void ipcon_destroy(IPConnection *ipcon); - -/** - * \ingroup IPConnection - * - * Creates a TCP/IP connection to the given \c host and c\ port. The host and - * port can point to a Brick Daemon or to a WIFI/Ethernet Extension. - * - * Devices can only be controlled when the connection was established - * successfully. - * - * Blocks until the connection is established and returns an error code if - * there is no Brick Daemon or WIFI/Ethernet Extension listening at the given - * host and port. - */ -int ipcon_connect(IPConnection *ipcon, const char *host, uint16_t port); - -/** - * \ingroup IPConnection - * - * Disconnects the TCP/IP connection from the Brick Daemon or the WIFI/Ethernet - * Extension. - */ -int ipcon_disconnect(IPConnection *ipcon); - -/** - * \ingroup IPConnection - * - * Can return the following states: - * - * - IPCON_CONNECTION_STATE_DISCONNECTED: No connection is established. - * - IPCON_CONNECTION_STATE_CONNECTED: A connection to the Brick Daemon or - * the WIFI/Ethernet Extension is established. - * - IPCON_CONNECTION_STATE_PENDING: IP Connection is currently trying to - * connect. - */ -int ipcon_get_connection_state(IPConnection *ipcon); - -/** - * \ingroup IPConnection - * - * Enables or disables auto-reconnect. If auto-reconnect is enabled, - * the IP Connection will try to reconnect to the previously given - * host and port, if the connection is lost. - * - * Default value is *true*. - */ -void ipcon_set_auto_reconnect(IPConnection *ipcon, bool auto_reconnect); - -/** - * \ingroup IPConnection - * - * Returns *true* if auto-reconnect is enabled, *false* otherwise. - */ -bool ipcon_get_auto_reconnect(IPConnection *ipcon); - -/** - * \ingroup IPConnection - * - * Sets the timeout in milliseconds for getters and for setters for which the - * response expected flag is activated. - * - * Default timeout is 2500. - */ -void ipcon_set_timeout(IPConnection *ipcon, uint32_t timeout); - -/** - * \ingroup IPConnection - * - * Returns the timeout as set by ipcon_set_timeout. - */ -uint32_t ipcon_get_timeout(IPConnection *ipcon); - -/** - * \ingroup IPConnection - * - * Broadcasts an enumerate request. All devices will respond with an enumerate - * callback. - */ -int ipcon_enumerate(IPConnection *ipcon); - -/** - * \ingroup IPConnection - * - * Stops the current thread until ipcon_unwait is called. - * - * This is useful if you rely solely on callbacks for events, if you want - * to wait for a specific callback or if the IP Connection was created in - * a thread. - * - * ipcon_wait and ipcon_unwait act in the same way as "acquire" and "release" - * of a semaphore. - */ -void ipcon_wait(IPConnection *ipcon); - -/** - * \ingroup IPConnection - * - * Unwaits the thread previously stopped by ipcon_wait. - * - * ipcon_wait and ipcon_unwait act in the same way as "acquire" and "release" - * of a semaphore. - */ -void ipcon_unwait(IPConnection *ipcon); - -/** - * \ingroup IPConnection - * - * Registers a callback for a given ID. - */ -void ipcon_register_callback(IPConnection *ipcon, uint8_t id, - void *callback, void *user_data); - -#ifdef IPCON_EXPOSE_INTERNALS - -/** - * \internal - */ -int packet_header_create(PacketHeader *header, uint8_t length, - uint8_t function_id, IPConnectionPrivate *ipcon_p, - DevicePrivate *device_p); - -/** - * \internal - */ -uint8_t packet_header_get_sequence_number(PacketHeader *header); - -/** - * \internal - */ -void packet_header_set_sequence_number(PacketHeader *header, - uint8_t sequence_number); - -/** - * \internal - */ -uint8_t packet_header_get_response_expected(PacketHeader *header); - -/** - * \internal - */ -void packet_header_set_response_expected(PacketHeader *header, - uint8_t response_expected); - -/** - * \internal - */ -uint8_t packet_header_get_error_code(PacketHeader *header); - -/** - * \internal - */ -int16_t leconvert_int16_to(int16_t native); - -/** - * \internal - */ -uint16_t leconvert_uint16_to(uint16_t native); - -/** - * \internal - */ -int32_t leconvert_int32_to(int32_t native); - -/** - * \internal - */ -uint32_t leconvert_uint32_to(uint32_t native); - -/** - * \internal - */ -int64_t leconvert_int64_to(int64_t native); - -/** - * \internal - */ -uint64_t leconvert_uint64_to(uint64_t native); - -/** - * \internal - */ -float leconvert_float_to(float native); - -/** - * \internal - */ -int16_t leconvert_int16_from(int16_t little); - -/** - * \internal - */ -uint16_t leconvert_uint16_from(uint16_t little); - -/** - * \internal - */ -int32_t leconvert_int32_from(int32_t little); - -/** - * \internal - */ -uint32_t leconvert_uint32_from(uint32_t little); - -/** - * \internal - */ -int64_t leconvert_int64_from(int64_t little); - -/** - * \internal - */ -uint64_t leconvert_uint64_from(uint64_t little); - -/** - * \internal - */ -float leconvert_float_from(float little); - -#endif // IPCON_EXPOSE_INTERNALS - -#endif +/* + * Copyright (C) 2012-2013 Matthias Bolte + * Copyright (C) 2011 Olaf Lüke + * + * Redistribution and use in source and binary forms of this file, + * with or without modification, are permitted. + */ + +#ifndef IP_CONNECTION_H +#define IP_CONNECTION_H + +/** + * \defgroup IPConnection IP Connection + */ + +#ifndef __STDC_LIMIT_MACROS + #define __STDC_LIMIT_MACROS +#endif +#include +#include +#include + +#if !defined __cplusplus && defined __GNUC__ + #include +#endif + +#ifdef _WIN32 + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #include +#else + #include + #include +#endif + +enum { + E_OK = 0, + E_TIMEOUT = -1, + E_NO_STREAM_SOCKET = -2, + E_HOSTNAME_INVALID = -3, + E_NO_CONNECT = -4, + E_NO_THREAD = -5, + E_NOT_ADDED = -6, // unused since v2.0 + E_ALREADY_CONNECTED = -7, + E_NOT_CONNECTED = -8, + E_INVALID_PARAMETER = -9, // error response from device + E_NOT_SUPPORTED = -10, // error response from device + E_UNKNOWN_ERROR_CODE = -11 // error response from device +}; + +#ifdef IPCON_EXPOSE_INTERNALS + +typedef struct _Socket Socket; + +typedef struct { +#ifdef _WIN32 + CRITICAL_SECTION handle; +#else + pthread_mutex_t handle; +#endif +} Mutex; + +void mutex_create(Mutex *mutex); + +void mutex_destroy(Mutex *mutex); + +void mutex_lock(Mutex *mutex); + +void mutex_unlock(Mutex *mutex); + +typedef struct { +#ifdef _WIN32 + HANDLE handle; +#else + pthread_cond_t condition; + pthread_mutex_t mutex; + bool flag; +#endif +} Event; + +typedef struct { +#ifdef _WIN32 + HANDLE handle; +#else + sem_t object; + sem_t *pointer; +#endif +} Semaphore; + +typedef void (*ThreadFunction)(void *opaque); + +typedef struct { +#ifdef _WIN32 + HANDLE handle; + DWORD id; +#else + pthread_t handle; +#endif + ThreadFunction function; + void *opaque; +} Thread; + +typedef struct { + Mutex mutex; + int used; + int allocated; + uint32_t *keys; + void **values; +} Table; + +typedef struct _QueueItem { + struct _QueueItem *next; + int kind; + void *data; + int length; +} QueueItem; + +typedef struct { + Mutex mutex; + Semaphore semaphore; + QueueItem *head; + QueueItem *tail; +} Queue; + +#if defined _MSC_VER || defined __BORLANDC__ + #pragma pack(push) + #pragma pack(1) + #define ATTRIBUTE_PACKED +#elif defined __GNUC__ + #ifdef _WIN32 + // workaround struct packing bug in GCC 4.7 on Windows + // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 + #define ATTRIBUTE_PACKED __attribute__((gcc_struct, packed)) + #else + #define ATTRIBUTE_PACKED __attribute__((packed)) + #endif +#else + #error unknown compiler, do not know how to enable struct packing +#endif + +typedef struct { + uint32_t uid; + uint8_t length; + uint8_t function_id; + uint8_t sequence_number_and_options; + uint8_t error_code_and_future_use; +} ATTRIBUTE_PACKED PacketHeader; + +typedef struct { + PacketHeader header; + uint8_t payload[64]; + uint8_t optional_data[8]; +} ATTRIBUTE_PACKED Packet; + +#if defined _MSC_VER || defined __BORLANDC__ + #pragma pack(pop) +#endif +#undef ATTRIBUTE_PACKED + +#endif // IPCON_EXPOSE_INTERNALS + +typedef struct _IPConnection IPConnection; +typedef struct _IPConnectionPrivate IPConnectionPrivate; +typedef struct _Device Device; +typedef struct _DevicePrivate DevicePrivate; + +#ifdef IPCON_EXPOSE_INTERNALS + +typedef struct _CallbackContext CallbackContext; + +#endif + +typedef void (*EnumerateCallbackFunction)(const char *uid, + const char *connected_uid, + char position, + uint8_t hardware_version[3], + uint8_t firmware_version[3], + uint16_t device_identifier, + uint8_t enumeration_type, + void *user_data); +typedef void (*ConnectedCallbackFunction)(uint8_t connect_reason, + void *user_data); +typedef void (*DisconnectedCallbackFunction)(uint8_t disconnect_reason, + void *user_data); + +#ifdef IPCON_EXPOSE_INTERNALS + +typedef void (*CallbackWrapperFunction)(DevicePrivate *device_p, Packet *packet); + +#endif + +/** + * \internal + */ +struct _Device { + DevicePrivate *p; +}; + +#ifdef IPCON_EXPOSE_INTERNALS + +#define DEVICE_NUM_FUNCTION_IDS 256 + +/** + * \internal + */ +struct _DevicePrivate { + uint32_t uid; + + IPConnectionPrivate *ipcon_p; + + uint8_t api_version[3]; + + Mutex request_mutex; + + uint8_t expected_response_function_id; // protected by request_mutex + uint8_t expected_response_sequence_number; // protected by request_mutex + Mutex response_mutex; + Packet response_packet; // protected by response_mutex + Event response_event; + int response_expected[DEVICE_NUM_FUNCTION_IDS]; + + void *registered_callbacks[DEVICE_NUM_FUNCTION_IDS]; + void *registered_callback_user_data[DEVICE_NUM_FUNCTION_IDS]; + CallbackWrapperFunction callback_wrappers[DEVICE_NUM_FUNCTION_IDS]; +}; + +/** + * \internal + */ +enum { + DEVICE_RESPONSE_EXPECTED_INVALID_FUNCTION_ID = 0, + DEVICE_RESPONSE_EXPECTED_ALWAYS_TRUE, // getter + DEVICE_RESPONSE_EXPECTED_ALWAYS_FALSE, // callback + DEVICE_RESPONSE_EXPECTED_TRUE, // setter + DEVICE_RESPONSE_EXPECTED_FALSE // setter, default +}; + +/** + * \internal + */ +void device_create(Device *device, const char *uid, + IPConnectionPrivate *ipcon_p, uint8_t api_version_major, + uint8_t api_version_minor, uint8_t api_version_release); + +/** + * \internal + */ +void device_destroy(Device *device); + +/** + * \internal + */ +int device_get_response_expected(DevicePrivate *device_p, uint8_t function_id, + bool *ret_response_expected); + +/** + * \internal + */ +int device_set_response_expected(DevicePrivate *device_p, uint8_t function_id, + bool response_expected); + +/** + * \internal + */ +int device_set_response_expected_all(DevicePrivate *device_p, bool response_expected); + +/** + * \internal + */ +void device_register_callback(DevicePrivate *device_p, uint8_t id, void *callback, + void *user_data); + +/** + * \internal + */ +int device_get_api_version(DevicePrivate *device_p, uint8_t ret_api_version[3]); + +/** + * \internal + */ +int device_send_request(DevicePrivate *device_p, Packet *request, Packet *response); + +#endif // IPCON_EXPOSE_INTERNALS + +/** + * \ingroup IPConnection + * + * Possible IDs for ipcon_register_callback. + */ +enum { + IPCON_CALLBACK_ENUMERATE = 253, + IPCON_CALLBACK_CONNECTED = 0, + IPCON_CALLBACK_DISCONNECTED = 1 +}; + +/** + * \ingroup IPConnection + * + * Possible values for enumeration_type parameter of EnumerateCallback. + */ +enum { + IPCON_ENUMERATION_TYPE_AVAILABLE = 0, + IPCON_ENUMERATION_TYPE_CONNECTED = 1, + IPCON_ENUMERATION_TYPE_DISCONNECTED = 2 +}; + +/** + * \ingroup IPConnection + * + * Possible values for connect_reason parameter of ConnectedCallback. + */ +enum { + IPCON_CONNECT_REASON_REQUEST = 0, + IPCON_CONNECT_REASON_AUTO_RECONNECT = 1 +}; + +/** + * \ingroup IPConnection + * + * Possible values for disconnect_reason parameter of DisconnectedCallback. + */ +enum { + IPCON_DISCONNECT_REASON_REQUEST = 0, + IPCON_DISCONNECT_REASON_ERROR = 1, + IPCON_DISCONNECT_REASON_SHUTDOWN = 2 +}; + +/** + * \ingroup IPConnection + * + * Possible return values of ipcon_get_connection_state. + */ +enum { + IPCON_CONNECTION_STATE_DISCONNECTED = 0, + IPCON_CONNECTION_STATE_CONNECTED = 1, + IPCON_CONNECTION_STATE_PENDING = 2 // auto-reconnect in progress +}; + +/** + * \internal + */ +struct _IPConnection { + IPConnectionPrivate *p; +}; + +#ifdef IPCON_EXPOSE_INTERNALS + +#define IPCON_NUM_CALLBACK_IDS 256 + +/** + * \internal + */ +struct _IPConnectionPrivate { +#ifdef _WIN32 + bool wsa_startup_done; // protected by socket_mutex +#endif + + char *host; + uint16_t port; + + uint32_t timeout; // in msec + + bool auto_reconnect; + bool auto_reconnect_allowed; + bool auto_reconnect_pending; + + Mutex sequence_number_mutex; + uint8_t next_sequence_number; // protected by sequence_number_mutex + + Table devices; + + void *registered_callbacks[IPCON_NUM_CALLBACK_IDS]; + void *registered_callback_user_data[IPCON_NUM_CALLBACK_IDS]; + + Mutex socket_mutex; + Socket *socket; // protected by socket_mutex + uint64_t socket_id; // protected by socket_mutex + + bool receive_flag; + Thread receive_thread; // protected by socket_mutex + + CallbackContext *callback; + + bool disconnect_probe_flag; + Thread disconnect_probe_thread; // protected by socket_mutex + Event disconnect_probe_event; + + Semaphore wait; +}; + +#endif // IPCON_EXPOSE_INTERNALS + +/** + * \ingroup IPConnection + * + * Creates an IP Connection object that can be used to enumerate the available + * devices. It is also required for the constructor of Bricks and Bricklets. + */ +void ipcon_create(IPConnection *ipcon); + +/** + * \ingroup IPConnection + * + * Destroys the IP Connection object. Calls ipcon_disconnect internally. + * The connection to the Brick Daemon gets closed and the threads of the + * IP Connection are terminated. + */ +void ipcon_destroy(IPConnection *ipcon); + +/** + * \ingroup IPConnection + * + * Creates a TCP/IP connection to the given \c host and c\ port. The host and + * port can point to a Brick Daemon or to a WIFI/Ethernet Extension. + * + * Devices can only be controlled when the connection was established + * successfully. + * + * Blocks until the connection is established and returns an error code if + * there is no Brick Daemon or WIFI/Ethernet Extension listening at the given + * host and port. + */ +int ipcon_connect(IPConnection *ipcon, const char *host, uint16_t port); + +/** + * \ingroup IPConnection + * + * Disconnects the TCP/IP connection from the Brick Daemon or the WIFI/Ethernet + * Extension. + */ +int ipcon_disconnect(IPConnection *ipcon); + +/** + * \ingroup IPConnection + * + * Can return the following states: + * + * - IPCON_CONNECTION_STATE_DISCONNECTED: No connection is established. + * - IPCON_CONNECTION_STATE_CONNECTED: A connection to the Brick Daemon or + * the WIFI/Ethernet Extension is established. + * - IPCON_CONNECTION_STATE_PENDING: IP Connection is currently trying to + * connect. + */ +int ipcon_get_connection_state(IPConnection *ipcon); + +/** + * \ingroup IPConnection + * + * Enables or disables auto-reconnect. If auto-reconnect is enabled, + * the IP Connection will try to reconnect to the previously given + * host and port, if the connection is lost. + * + * Default value is *true*. + */ +void ipcon_set_auto_reconnect(IPConnection *ipcon, bool auto_reconnect); + +/** + * \ingroup IPConnection + * + * Returns *true* if auto-reconnect is enabled, *false* otherwise. + */ +bool ipcon_get_auto_reconnect(IPConnection *ipcon); + +/** + * \ingroup IPConnection + * + * Sets the timeout in milliseconds for getters and for setters for which the + * response expected flag is activated. + * + * Default timeout is 2500. + */ +void ipcon_set_timeout(IPConnection *ipcon, uint32_t timeout); + +/** + * \ingroup IPConnection + * + * Returns the timeout as set by ipcon_set_timeout. + */ +uint32_t ipcon_get_timeout(IPConnection *ipcon); + +/** + * \ingroup IPConnection + * + * Broadcasts an enumerate request. All devices will respond with an enumerate + * callback. + */ +int ipcon_enumerate(IPConnection *ipcon); + +/** + * \ingroup IPConnection + * + * Stops the current thread until ipcon_unwait is called. + * + * This is useful if you rely solely on callbacks for events, if you want + * to wait for a specific callback or if the IP Connection was created in + * a thread. + * + * ipcon_wait and ipcon_unwait act in the same way as "acquire" and "release" + * of a semaphore. + */ +void ipcon_wait(IPConnection *ipcon); + +/** + * \ingroup IPConnection + * + * Unwaits the thread previously stopped by ipcon_wait. + * + * ipcon_wait and ipcon_unwait act in the same way as "acquire" and "release" + * of a semaphore. + */ +void ipcon_unwait(IPConnection *ipcon); + +/** + * \ingroup IPConnection + * + * Registers a callback for a given ID. + */ +void ipcon_register_callback(IPConnection *ipcon, uint8_t id, + void *callback, void *user_data); + +#ifdef IPCON_EXPOSE_INTERNALS + +/** + * \internal + */ +int packet_header_create(PacketHeader *header, uint8_t length, + uint8_t function_id, IPConnectionPrivate *ipcon_p, + DevicePrivate *device_p); + +/** + * \internal + */ +uint8_t packet_header_get_sequence_number(PacketHeader *header); + +/** + * \internal + */ +void packet_header_set_sequence_number(PacketHeader *header, + uint8_t sequence_number); + +/** + * \internal + */ +uint8_t packet_header_get_response_expected(PacketHeader *header); + +/** + * \internal + */ +void packet_header_set_response_expected(PacketHeader *header, + uint8_t response_expected); + +/** + * \internal + */ +uint8_t packet_header_get_error_code(PacketHeader *header); + +/** + * \internal + */ +int16_t leconvert_int16_to(int16_t native); + +/** + * \internal + */ +uint16_t leconvert_uint16_to(uint16_t native); + +/** + * \internal + */ +int32_t leconvert_int32_to(int32_t native); + +/** + * \internal + */ +uint32_t leconvert_uint32_to(uint32_t native); + +/** + * \internal + */ +int64_t leconvert_int64_to(int64_t native); + +/** + * \internal + */ +uint64_t leconvert_uint64_to(uint64_t native); + +/** + * \internal + */ +float leconvert_float_to(float native); + +/** + * \internal + */ +int16_t leconvert_int16_from(int16_t little); + +/** + * \internal + */ +uint16_t leconvert_uint16_from(uint16_t little); + +/** + * \internal + */ +int32_t leconvert_int32_from(int32_t little); + +/** + * \internal + */ +uint32_t leconvert_uint32_from(uint32_t little); + +/** + * \internal + */ +int64_t leconvert_int64_from(int64_t little); + +/** + * \internal + */ +uint64_t leconvert_uint64_from(uint64_t little); + +/** + * \internal + */ +float leconvert_float_from(float little); + +#endif // IPCON_EXPOSE_INTERNALS + +#endif diff --git a/libsrc/bonjour/CMakeLists.txt b/libsrc/bonjour/CMakeLists.txt index 131b3d93..c23f51d9 100644 --- a/libsrc/bonjour/CMakeLists.txt +++ b/libsrc/bonjour/CMakeLists.txt @@ -1,52 +1,52 @@ - -# Define the current source locations -set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/bonjour) -set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/bonjour) - -# Group the headers that go through the MOC compiler -set(Bonjour_QT_HEADERS - ${CURRENT_HEADER_DIR}/bonjourrecord.h - ${CURRENT_HEADER_DIR}/bonjourserviceregister.h -) - -set(Bonjour_HEADERS -) - -set(Bonjour_SOURCES - ${CURRENT_SOURCE_DIR}/bonjourserviceregister.cpp -) - -set(Bonjour_RESOURCES -) - -if(ENABLE_QT5) -qt5_wrap_cpp(Bonjour_HEADERS_MOC ${Bonjour_QT_HEADERS}) -qt5_add_resources(Bonjour_RESOURCES_RCC ${Bonjour_RESOURCES} OPTIONS "-no-compress") -else(ENABLE_QT5) -qt4_wrap_cpp(Bonjour_HEADERS_MOC ${Bonjour_QT_HEADERS}) -qt4_add_resources(Bonjour_RESOURCES_RCC ${Bonjour_RESOURCES} OPTIONS "-no-compress") -endif(ENABLE_QT5) - -add_library(bonjour - ${Bonjour_HEADERS} - ${Bonjour_QT_HEADERS} - ${Bonjour_SOURCES} - ${Bonjour_RESOURCES} - ${Bonjour_HEADERS_MOC} - ${Bonjour_RESOURCES_RCC} -) - -if(ENABLE_QT5) -qt5_use_modules(bonjour Widgets Network) -endif(ENABLE_QT5) - -target_link_libraries(bonjour - libdns_sd.a - libavahi-client.a - libavahi-common.a - libavahi-core.a - libavahi-qt4.a - libdbus-1.a - hyperion - hyperion-utils - ${QT_LIBRARIES}) + +# Define the current source locations +set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/bonjour) +set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/bonjour) + +# Group the headers that go through the MOC compiler +set(Bonjour_QT_HEADERS + ${CURRENT_HEADER_DIR}/bonjourrecord.h + ${CURRENT_HEADER_DIR}/bonjourserviceregister.h +) + +set(Bonjour_HEADERS +) + +set(Bonjour_SOURCES + ${CURRENT_SOURCE_DIR}/bonjourserviceregister.cpp +) + +set(Bonjour_RESOURCES +) + +if(ENABLE_QT5) +qt5_wrap_cpp(Bonjour_HEADERS_MOC ${Bonjour_QT_HEADERS}) +qt5_add_resources(Bonjour_RESOURCES_RCC ${Bonjour_RESOURCES} OPTIONS "-no-compress") +else(ENABLE_QT5) +qt4_wrap_cpp(Bonjour_HEADERS_MOC ${Bonjour_QT_HEADERS}) +qt4_add_resources(Bonjour_RESOURCES_RCC ${Bonjour_RESOURCES} OPTIONS "-no-compress") +endif(ENABLE_QT5) + +add_library(bonjour + ${Bonjour_HEADERS} + ${Bonjour_QT_HEADERS} + ${Bonjour_SOURCES} + ${Bonjour_RESOURCES} + ${Bonjour_HEADERS_MOC} + ${Bonjour_RESOURCES_RCC} +) + +if(ENABLE_QT5) +qt5_use_modules(bonjour Widgets Network) +endif(ENABLE_QT5) + +target_link_libraries(bonjour + libdns_sd.a + libavahi-client.a + libavahi-common.a + libavahi-core.a + libavahi-qt4.a + libdbus-1.a + hyperion + hyperion-utils + ${QT_LIBRARIES}) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index df7c831a..fe9e359d 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -1,342 +1,342 @@ -// Local-Hyperion includes -#include "LedDevicePhilipsHue.h" - -// jsoncpp includes -#include - -// qt includes -#include -#include -#include - -#include -#include - -bool operator ==(CiColor p1, CiColor p2) { - return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri); -} - -bool operator !=(CiColor p1, CiColor p2) { - return !(p1 == p2); -} - -PhilipsHueLight::PhilipsHueLight(unsigned int id, QString originalState, QString modelId) : - id(id), originalState(originalState) { - // Hue system model ids (http://www.developers.meethue.com/documentation/supported-lights). - // Light strips, color iris, ... - const std::set GAMUT_A_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012", - "LLC013", "LLC014", "LST001" }; - // Hue bulbs, spots, ... - const std::set GAMUT_B_MODEL_IDS = { "LCT001", "LCT002", "LCT003", "LCT007", "LLM001" }; - // Hue Lightstrip plus, go ... - const std::set GAMUT_C_MODEL_IDS = { "LLC020", "LST002" }; - // Find id in the sets and set the appropiate color space. - if (GAMUT_A_MODEL_IDS.find(modelId) != GAMUT_A_MODEL_IDS.end()) { - colorSpace.red = {0.703f, 0.296f}; - colorSpace.green = {0.2151f, 0.7106f}; - colorSpace.blue = {0.138f, 0.08f}; - } else if (GAMUT_B_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { - colorSpace.red = {0.675f, 0.322f}; - colorSpace.green = {0.4091f, 0.518f}; - colorSpace.blue = {0.167f, 0.04f}; - } else if (GAMUT_C_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { - colorSpace.red = {0.675f, 0.322f}; - colorSpace.green = {0.2151f, 0.7106f}; - colorSpace.blue = {0.167f, 0.04f}; - } else { - colorSpace.red = {1.0f, 0.0f}; - colorSpace.green = {0.0f, 1.0f}; - colorSpace.blue = {0.0f, 0.0f}; - } - // Initialize black color. - black = rgbToCiColor(0.0f, 0.0f, 0.0f); - // Initialize color with black - color = {black.x, black.y, black.bri}; -} - -float PhilipsHueLight::crossProduct(CiColor p1, CiColor p2) { - return p1.x * p2.y - p1.y * p2.x; -} - -bool PhilipsHueLight::isPointInLampsReach(CiColor p) { - CiColor v1 = { colorSpace.green.x - colorSpace.red.x, colorSpace.green.y - colorSpace.red.y }; - CiColor v2 = { colorSpace.blue.x - colorSpace.red.x, colorSpace.blue.y - colorSpace.red.y }; - CiColor q = { p.x - colorSpace.red.x, p.y - colorSpace.red.y }; - float s = crossProduct(q, v2) / crossProduct(v1, v2); - float t = crossProduct(v1, q) / crossProduct(v1, v2); - if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) { - return true; - } - return false; -} - -CiColor PhilipsHueLight::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) { - CiColor AP = { p.x - a.x, p.y - a.y }; - CiColor AB = { b.x - a.x, b.y - a.y }; - float ab2 = AB.x * AB.x + AB.y * AB.y; - float ap_ab = AP.x * AB.x + AP.y * AB.y; - float t = ap_ab / ab2; - if (t < 0.0f) { - t = 0.0f; - } else if (t > 1.0f) { - t = 1.0f; - } - return {a.x + AB.x * t, a.y + AB.y * t}; -} - -float PhilipsHueLight::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) { - // Horizontal difference. - float dx = p1.x - p2.x; - // Vertical difference. - float dy = p1.y - p2.y; - // Absolute value. - return sqrt(dx * dx + dy * dy); -} - -CiColor PhilipsHueLight::rgbToCiColor(float red, float green, float blue) { - // Apply gamma correction. - float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); - float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); - float b = (blue > 0.04045f) ? powf((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f); - // Convert to XYZ space. - float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; - float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; - float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f; - // Convert to x,y space. - float cx = X / (X + Y + Z); - float cy = Y / (X + Y + Z); - if (std::isnan(cx)) { - cx = 0.0f; - } - if (std::isnan(cy)) { - cy = 0.0f; - } - // Brightness is simply Y in the XYZ space. - CiColor xy = { cx, cy, Y }; - // Check if the given XY value is within the color reach of our lamps. - if (!isPointInLampsReach(xy)) { - // It seems the color is out of reach let's find the closes color we can produce with our lamp and send this XY value out. - CiColor pAB = getClosestPointToPoint(colorSpace.red, colorSpace.green, xy); - CiColor pAC = getClosestPointToPoint(colorSpace.blue, colorSpace.red, xy); - CiColor pBC = getClosestPointToPoint(colorSpace.green, colorSpace.blue, xy); - // Get the distances per point and see which point is closer to our Point. - float dAB = getDistanceBetweenTwoPoints(xy, pAB); - float dAC = getDistanceBetweenTwoPoints(xy, pAC); - float dBC = getDistanceBetweenTwoPoints(xy, pBC); - float lowest = dAB; - CiColor closestPoint = pAB; - if (dAC < lowest) { - lowest = dAC; - closestPoint = pAC; - } - if (dBC < lowest) { - lowest = dBC; - closestPoint = pBC; - } - // Change the xy value to a value which is within the reach of the lamp. - xy.x = closestPoint.x; - xy.y = closestPoint.y; - } - return xy; -} - -LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::string& username, bool switchOffOnBlack, - int transitiontime, std::vector lightIds) : - host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime( - transitiontime), lightIds(lightIds) { - manager = new QNetworkAccessManager(); - timer.setInterval(3000); - timer.setSingleShot(true); - connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates())); -} - -LedDevicePhilipsHue::~LedDevicePhilipsHue() { - delete manager; -} - -int LedDevicePhilipsHue::write(const std::vector & ledValues) { - // Save light states if not done before. - if (!areStatesSaved()) { - saveStates((unsigned int) ledValues.size()); - switchOn((unsigned int) ledValues.size()); - } - // If there are less states saved than colors given, then maybe something went wrong before. - if (lights.size() != ledValues.size()) { - restoreStates(); - return 0; - } - // Iterate through colors and set light states. - unsigned int idx = 0; - for (const ColorRgb& color : ledValues) { - // Get lamp. - PhilipsHueLight& lamp = lights.at(idx); - // Scale colors from [0, 255] to [0, 1] and convert to xy space. - CiColor xy = lamp.rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f); - // Write color if color has been changed. - if (xy != lamp.color) { - // From a color to black. - if (switchOffOnBlack && lamp.color != lamp.black && xy == lamp.black) { - put(getStateRoute(lamp.id), QString("{\"on\": false}")); - } - // From black to a color - else if (switchOffOnBlack && lamp.color == lamp.black && xy != lamp.black) { - // Send adjust color and brightness command in JSON format. - // We have to set the transition time each time. - // Send also command to switch the lamp on. - put(getStateRoute(lamp.id), - QString("{\"on\": true, \"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg( - xy.y).arg(qRound(xy.bri * 255.0f)).arg(transitiontime)); - } - // Normal color change. - else { - // Send adjust color and brightness command in JSON format. - // We have to set the transition time each time. - put(getStateRoute(lamp.id), - QString("{\"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg(xy.y).arg( - qRound(xy.bri * 255.0f)).arg(transitiontime)); - } - } - // Remember last color. - lamp.color = xy; - // Next light id. - idx++; - } - timer.start(); - return 0; -} - -int LedDevicePhilipsHue::switchOff() { - timer.stop(); - // If light states have been saved before, ... - if (areStatesSaved()) { - // ... restore them. - restoreStates(); - } - return 0; -} - -void LedDevicePhilipsHue::put(QString route, QString content) { - QString url = getUrl(route); - // Perfrom request - QNetworkRequest request(url); - 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())); - // Go into the loop until the request is finished. - loop.exec(); - // Free space. - reply->deleteLater(); -} - -QByteArray LedDevicePhilipsHue::get(QString route) { - QString url = getUrl(route); - // Perfrom request - 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. - QByteArray response = reply->readAll(); - // Free space. - reply->deleteLater(); - // Return response - return response; -} - -QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) { - return QString("lights/%1/state").arg(lightId); -} - -QString LedDevicePhilipsHue::getRoute(unsigned int lightId) { - return QString("lights/%1").arg(lightId); -} - -QString LedDevicePhilipsHue::getUrl(QString route) { - return QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route); -} - -void LedDevicePhilipsHue::saveStates(unsigned int nLights) { - // Clear saved lamps. - lights.clear(); - // Use json parser to parse reponse. - Json::Reader reader; - Json::FastWriter writer; - // Read light ids if none have been supplied by the user. - if (lightIds.size() != nLights) { - lightIds.clear(); - // - QByteArray response = get("lights"); - Json::Value json; - if (!reader.parse(QString(response).toStdString(), json)) { - throw std::runtime_error(("No lights found at " + getUrl("lights")).toStdString()); - } - // Loop over all children. - for (Json::ValueIterator it = json.begin(); it != json.end() && lightIds.size() < nLights; it++) { - int lightId = atoi(it.key().asCString()); - lightIds.push_back(lightId); - std::cout << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): found light with id " << lightId - << "." << std::endl; - } - // Check if we found enough lights. - if (lightIds.size() != nLights) { - throw std::runtime_error(("Not enough lights found at " + getUrl("lights")).toStdString()); - } - } - // Iterate lights. - for (unsigned int i = 0; i < nLights; i++) { - // Read the response. - QByteArray response = get(getRoute(lightIds.at(i))); - // Parse JSON. - Json::Value json; - if (!reader.parse(QString(response).toStdString(), json)) { - // Error occured, break loop. - std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got invalid response from light " - << getUrl(getRoute(lightIds.at(i))).toStdString() << "." << std::endl; - break; - } - // Get state object values which are subject to change. - Json::Value state(Json::objectValue); - if (!json.isMember("state")) { - std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no state for light from " - << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; - break; - } - if (!json["state"].isMember("on")) { - std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no valid state from light " - << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; - break; - } - state["on"] = json["state"]["on"]; - if (json["state"]["on"] == true) { - state["xy"] = json["state"]["xy"]; - state["bri"] = json["state"]["bri"]; - } - // Determine the model id. - QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", ""); - QString originalState = QString(writer.write(state).c_str()).trimmed(); - // Save state object. - lights.push_back(PhilipsHueLight(lightIds.at(i), originalState, modelId)); - } -} - -void LedDevicePhilipsHue::switchOn(unsigned int nLights) { - for (PhilipsHueLight light : lights) { - put(getStateRoute(light.id), "{\"on\": true}"); - } -} - -void LedDevicePhilipsHue::restoreStates() { - for (PhilipsHueLight light : lights) { - put(getStateRoute(light.id), light.originalState); - } - // Clear saved light states. - lights.clear(); -} - -bool LedDevicePhilipsHue::areStatesSaved() { - return !lights.empty(); -} +// Local-Hyperion includes +#include "LedDevicePhilipsHue.h" + +// jsoncpp includes +#include + +// qt includes +#include +#include +#include + +#include +#include + +bool operator ==(CiColor p1, CiColor p2) { + return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri); +} + +bool operator !=(CiColor p1, CiColor p2) { + return !(p1 == p2); +} + +PhilipsHueLight::PhilipsHueLight(unsigned int id, QString originalState, QString modelId) : + id(id), originalState(originalState) { + // Hue system model ids (http://www.developers.meethue.com/documentation/supported-lights). + // Light strips, color iris, ... + const std::set GAMUT_A_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012", + "LLC013", "LLC014", "LST001" }; + // Hue bulbs, spots, ... + const std::set GAMUT_B_MODEL_IDS = { "LCT001", "LCT002", "LCT003", "LCT007", "LLM001" }; + // Hue Lightstrip plus, go ... + const std::set GAMUT_C_MODEL_IDS = { "LLC020", "LST002" }; + // Find id in the sets and set the appropiate color space. + if (GAMUT_A_MODEL_IDS.find(modelId) != GAMUT_A_MODEL_IDS.end()) { + colorSpace.red = {0.703f, 0.296f}; + colorSpace.green = {0.2151f, 0.7106f}; + colorSpace.blue = {0.138f, 0.08f}; + } else if (GAMUT_B_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { + colorSpace.red = {0.675f, 0.322f}; + colorSpace.green = {0.4091f, 0.518f}; + colorSpace.blue = {0.167f, 0.04f}; + } else if (GAMUT_C_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { + colorSpace.red = {0.675f, 0.322f}; + colorSpace.green = {0.2151f, 0.7106f}; + colorSpace.blue = {0.167f, 0.04f}; + } else { + colorSpace.red = {1.0f, 0.0f}; + colorSpace.green = {0.0f, 1.0f}; + colorSpace.blue = {0.0f, 0.0f}; + } + // Initialize black color. + black = rgbToCiColor(0.0f, 0.0f, 0.0f); + // Initialize color with black + color = {black.x, black.y, black.bri}; +} + +float PhilipsHueLight::crossProduct(CiColor p1, CiColor p2) { + return p1.x * p2.y - p1.y * p2.x; +} + +bool PhilipsHueLight::isPointInLampsReach(CiColor p) { + CiColor v1 = { colorSpace.green.x - colorSpace.red.x, colorSpace.green.y - colorSpace.red.y }; + CiColor v2 = { colorSpace.blue.x - colorSpace.red.x, colorSpace.blue.y - colorSpace.red.y }; + CiColor q = { p.x - colorSpace.red.x, p.y - colorSpace.red.y }; + float s = crossProduct(q, v2) / crossProduct(v1, v2); + float t = crossProduct(v1, q) / crossProduct(v1, v2); + if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) { + return true; + } + return false; +} + +CiColor PhilipsHueLight::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) { + CiColor AP = { p.x - a.x, p.y - a.y }; + CiColor AB = { b.x - a.x, b.y - a.y }; + float ab2 = AB.x * AB.x + AB.y * AB.y; + float ap_ab = AP.x * AB.x + AP.y * AB.y; + float t = ap_ab / ab2; + if (t < 0.0f) { + t = 0.0f; + } else if (t > 1.0f) { + t = 1.0f; + } + return {a.x + AB.x * t, a.y + AB.y * t}; +} + +float PhilipsHueLight::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) { + // Horizontal difference. + float dx = p1.x - p2.x; + // Vertical difference. + float dy = p1.y - p2.y; + // Absolute value. + return sqrt(dx * dx + dy * dy); +} + +CiColor PhilipsHueLight::rgbToCiColor(float red, float green, float blue) { + // Apply gamma correction. + float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); + float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); + float b = (blue > 0.04045f) ? powf((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f); + // Convert to XYZ space. + float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; + float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; + float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f; + // Convert to x,y space. + float cx = X / (X + Y + Z); + float cy = Y / (X + Y + Z); + if (std::isnan(cx)) { + cx = 0.0f; + } + if (std::isnan(cy)) { + cy = 0.0f; + } + // Brightness is simply Y in the XYZ space. + CiColor xy = { cx, cy, Y }; + // Check if the given XY value is within the color reach of our lamps. + if (!isPointInLampsReach(xy)) { + // It seems the color is out of reach let's find the closes color we can produce with our lamp and send this XY value out. + CiColor pAB = getClosestPointToPoint(colorSpace.red, colorSpace.green, xy); + CiColor pAC = getClosestPointToPoint(colorSpace.blue, colorSpace.red, xy); + CiColor pBC = getClosestPointToPoint(colorSpace.green, colorSpace.blue, xy); + // Get the distances per point and see which point is closer to our Point. + float dAB = getDistanceBetweenTwoPoints(xy, pAB); + float dAC = getDistanceBetweenTwoPoints(xy, pAC); + float dBC = getDistanceBetweenTwoPoints(xy, pBC); + float lowest = dAB; + CiColor closestPoint = pAB; + if (dAC < lowest) { + lowest = dAC; + closestPoint = pAC; + } + if (dBC < lowest) { + lowest = dBC; + closestPoint = pBC; + } + // Change the xy value to a value which is within the reach of the lamp. + xy.x = closestPoint.x; + xy.y = closestPoint.y; + } + return xy; +} + +LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::string& username, bool switchOffOnBlack, + int transitiontime, std::vector lightIds) : + host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime( + transitiontime), lightIds(lightIds) { + manager = new QNetworkAccessManager(); + timer.setInterval(3000); + timer.setSingleShot(true); + connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates())); +} + +LedDevicePhilipsHue::~LedDevicePhilipsHue() { + delete manager; +} + +int LedDevicePhilipsHue::write(const std::vector & ledValues) { + // Save light states if not done before. + if (!areStatesSaved()) { + saveStates((unsigned int) ledValues.size()); + switchOn((unsigned int) ledValues.size()); + } + // If there are less states saved than colors given, then maybe something went wrong before. + if (lights.size() != ledValues.size()) { + restoreStates(); + return 0; + } + // Iterate through colors and set light states. + unsigned int idx = 0; + for (const ColorRgb& color : ledValues) { + // Get lamp. + PhilipsHueLight& lamp = lights.at(idx); + // Scale colors from [0, 255] to [0, 1] and convert to xy space. + CiColor xy = lamp.rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f); + // Write color if color has been changed. + if (xy != lamp.color) { + // From a color to black. + if (switchOffOnBlack && lamp.color != lamp.black && xy == lamp.black) { + put(getStateRoute(lamp.id), QString("{\"on\": false}")); + } + // From black to a color + else if (switchOffOnBlack && lamp.color == lamp.black && xy != lamp.black) { + // Send adjust color and brightness command in JSON format. + // We have to set the transition time each time. + // Send also command to switch the lamp on. + put(getStateRoute(lamp.id), + QString("{\"on\": true, \"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg( + xy.y).arg(qRound(xy.bri * 255.0f)).arg(transitiontime)); + } + // Normal color change. + else { + // Send adjust color and brightness command in JSON format. + // We have to set the transition time each time. + put(getStateRoute(lamp.id), + QString("{\"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg(xy.y).arg( + qRound(xy.bri * 255.0f)).arg(transitiontime)); + } + } + // Remember last color. + lamp.color = xy; + // Next light id. + idx++; + } + timer.start(); + return 0; +} + +int LedDevicePhilipsHue::switchOff() { + timer.stop(); + // If light states have been saved before, ... + if (areStatesSaved()) { + // ... restore them. + restoreStates(); + } + return 0; +} + +void LedDevicePhilipsHue::put(QString route, QString content) { + QString url = getUrl(route); + // Perfrom request + QNetworkRequest request(url); + 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())); + // Go into the loop until the request is finished. + loop.exec(); + // Free space. + reply->deleteLater(); +} + +QByteArray LedDevicePhilipsHue::get(QString route) { + QString url = getUrl(route); + // Perfrom request + 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. + QByteArray response = reply->readAll(); + // Free space. + reply->deleteLater(); + // Return response + return response; +} + +QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) { + return QString("lights/%1/state").arg(lightId); +} + +QString LedDevicePhilipsHue::getRoute(unsigned int lightId) { + return QString("lights/%1").arg(lightId); +} + +QString LedDevicePhilipsHue::getUrl(QString route) { + return QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route); +} + +void LedDevicePhilipsHue::saveStates(unsigned int nLights) { + // Clear saved lamps. + lights.clear(); + // Use json parser to parse reponse. + Json::Reader reader; + Json::FastWriter writer; + // Read light ids if none have been supplied by the user. + if (lightIds.size() != nLights) { + lightIds.clear(); + // + QByteArray response = get("lights"); + Json::Value json; + if (!reader.parse(QString(response).toStdString(), json)) { + throw std::runtime_error(("No lights found at " + getUrl("lights")).toStdString()); + } + // Loop over all children. + for (Json::ValueIterator it = json.begin(); it != json.end() && lightIds.size() < nLights; it++) { + int lightId = atoi(it.key().asCString()); + lightIds.push_back(lightId); + std::cout << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): found light with id " << lightId + << "." << std::endl; + } + // Check if we found enough lights. + if (lightIds.size() != nLights) { + throw std::runtime_error(("Not enough lights found at " + getUrl("lights")).toStdString()); + } + } + // Iterate lights. + for (unsigned int i = 0; i < nLights; i++) { + // Read the response. + QByteArray response = get(getRoute(lightIds.at(i))); + // Parse JSON. + Json::Value json; + if (!reader.parse(QString(response).toStdString(), json)) { + // Error occured, break loop. + std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got invalid response from light " + << getUrl(getRoute(lightIds.at(i))).toStdString() << "." << std::endl; + break; + } + // Get state object values which are subject to change. + Json::Value state(Json::objectValue); + if (!json.isMember("state")) { + std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no state for light from " + << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; + break; + } + if (!json["state"].isMember("on")) { + std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no valid state from light " + << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; + break; + } + state["on"] = json["state"]["on"]; + if (json["state"]["on"] == true) { + state["xy"] = json["state"]["xy"]; + state["bri"] = json["state"]["bri"]; + } + // Determine the model id. + QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", ""); + QString originalState = QString(writer.write(state).c_str()).trimmed(); + // Save state object. + lights.push_back(PhilipsHueLight(lightIds.at(i), originalState, modelId)); + } +} + +void LedDevicePhilipsHue::switchOn(unsigned int nLights) { + for (PhilipsHueLight light : lights) { + put(getStateRoute(light.id), "{\"on\": true}"); + } +} + +void LedDevicePhilipsHue::restoreStates() { + for (PhilipsHueLight light : lights) { + put(getStateRoute(light.id), light.originalState); + } + // Clear saved light states. + lights.clear(); +} + +bool LedDevicePhilipsHue::areStatesSaved() { + return !lights.empty(); +} diff --git a/test/TestSpi.cpp b/test/TestSpi.cpp index 1a3d5a92..4bddd727 100644 --- a/test/TestSpi.cpp +++ b/test/TestSpi.cpp @@ -1,161 +1,161 @@ - -// STL includes -#include -#include -#include -#include -#include -#include - -// Local includes -#include - -#include "../libsrc/leddevice/LedDeviceWs2801.h" - -void setColor(char* colorStr) -{ - ColorRgb color = ColorRgb::BLACK; - std::cout << "Switching all leds to: "; - if (strncmp("red", colorStr, 3) == 0) - { - std::cout << "red"; - color = ColorRgb::RED; - } - else if (strncmp("green", colorStr, 5) == 0) - { - std::cout << "green"; - color = ColorRgb::GREEN; - } - else if (strncmp("blue", colorStr, 5) == 0) - { - std::cout << "blue"; - color = ColorRgb::BLUE; - } - else if (strncmp("cyan", colorStr, 5) == 0) - { - std::cout << "cyan"; - } - else if (strncmp("gray", colorStr, 4) == 0) - { - std::cout << "gray"; - } - else if (strncmp("white", colorStr, 5) == 0) - { - std::cout << "white"; - color = ColorRgb::WHITE; - } - else if (strncmp("black", colorStr, 5) == 0) - { - std::cout << "black"; - color = ColorRgb::BLACK; - } - std::cout << std::endl; - - unsigned ledCnt = 50; - std::vector buff(ledCnt, color); - - LedDeviceWs2801 ledDevice("/dev/spidev0.0", 40000); - ledDevice.open(); - ledDevice.write(buff); -} - -bool _running = true; -void doCircle() -{ - ColorRgb color_1 = ColorRgb::RED; - ColorRgb color_2 = ColorRgb::YELLOW; - - unsigned ledCnt = 50; - std::vector data(ledCnt, ColorRgb::BLACK); - - LedDeviceWs2801 ledDevice("/dev/spidev0.0", 40000); - ledDevice.open(); - - timespec loopTime; - loopTime.tv_sec = 0; - loopTime.tv_nsec = 100000000; // 100 ms - - int curLed_1 = 0; - int nextLed_1 = 1; - - int curLed_2 = 49; - int nextLed_2 = 48; - - - while (_running) - { - data[curLed_1] = ColorRgb::BLACK; - data[curLed_2] = ColorRgb::BLACK; - - // Move the current and the next pointer - curLed_1 = nextLed_1; - curLed_2 = nextLed_2; - ++nextLed_1; - --nextLed_2; - if (nextLed_1 == int(ledCnt)) - { - nextLed_1 = 0; - } - if (nextLed_2 < 0) - { - nextLed_2 = 49; - } - - data[curLed_1] = color_1; - - data[curLed_2] = color_2; - - ledDevice.write(data); - - nanosleep(&loopTime, NULL); - } - - // Switch the current leds off - data[curLed_1] = ColorRgb::BLACK; - data[curLed_2] = ColorRgb::BLACK; - - ledDevice.write(data); -} - -#include - -void signal_handler(int signum) -{ - _running = false; -} - -int main(int argc, char** argv) -{ - if (sizeof(ColorRgb) != 3) - { - std::cout << "sizeof(ColorRgb) = " << sizeof(ColorRgb) << std::endl; - return -1; - } - - // Install signal handlers to stop loops - signal(SIGTERM, &signal_handler); - signal(SIGINT, &signal_handler); - - if (argc < 2) - { - std::cerr << "Missing argument" << std::endl; - return -1; - } - - if (strncmp("fixed", argv[1], 5) == 0) - { - setColor(argv[2]); - return 0; - } - else if (strncmp("circle", argv[1], 6) == 0) - { - doCircle(); - } - else - { - std::cerr << "Unknown option: " << argv[1] << std::endl; - } - - return 0; -} - + +// STL includes +#include +#include +#include +#include +#include +#include + +// Local includes +#include + +#include "../libsrc/leddevice/LedDeviceWs2801.h" + +void setColor(char* colorStr) +{ + ColorRgb color = ColorRgb::BLACK; + std::cout << "Switching all leds to: "; + if (strncmp("red", colorStr, 3) == 0) + { + std::cout << "red"; + color = ColorRgb::RED; + } + else if (strncmp("green", colorStr, 5) == 0) + { + std::cout << "green"; + color = ColorRgb::GREEN; + } + else if (strncmp("blue", colorStr, 5) == 0) + { + std::cout << "blue"; + color = ColorRgb::BLUE; + } + else if (strncmp("cyan", colorStr, 5) == 0) + { + std::cout << "cyan"; + } + else if (strncmp("gray", colorStr, 4) == 0) + { + std::cout << "gray"; + } + else if (strncmp("white", colorStr, 5) == 0) + { + std::cout << "white"; + color = ColorRgb::WHITE; + } + else if (strncmp("black", colorStr, 5) == 0) + { + std::cout << "black"; + color = ColorRgb::BLACK; + } + std::cout << std::endl; + + unsigned ledCnt = 50; + std::vector buff(ledCnt, color); + + LedDeviceWs2801 ledDevice("/dev/spidev0.0", 40000); + ledDevice.open(); + ledDevice.write(buff); +} + +bool _running = true; +void doCircle() +{ + ColorRgb color_1 = ColorRgb::RED; + ColorRgb color_2 = ColorRgb::YELLOW; + + unsigned ledCnt = 50; + std::vector data(ledCnt, ColorRgb::BLACK); + + LedDeviceWs2801 ledDevice("/dev/spidev0.0", 40000); + ledDevice.open(); + + timespec loopTime; + loopTime.tv_sec = 0; + loopTime.tv_nsec = 100000000; // 100 ms + + int curLed_1 = 0; + int nextLed_1 = 1; + + int curLed_2 = 49; + int nextLed_2 = 48; + + + while (_running) + { + data[curLed_1] = ColorRgb::BLACK; + data[curLed_2] = ColorRgb::BLACK; + + // Move the current and the next pointer + curLed_1 = nextLed_1; + curLed_2 = nextLed_2; + ++nextLed_1; + --nextLed_2; + if (nextLed_1 == int(ledCnt)) + { + nextLed_1 = 0; + } + if (nextLed_2 < 0) + { + nextLed_2 = 49; + } + + data[curLed_1] = color_1; + + data[curLed_2] = color_2; + + ledDevice.write(data); + + nanosleep(&loopTime, NULL); + } + + // Switch the current leds off + data[curLed_1] = ColorRgb::BLACK; + data[curLed_2] = ColorRgb::BLACK; + + ledDevice.write(data); +} + +#include + +void signal_handler(int signum) +{ + _running = false; +} + +int main(int argc, char** argv) +{ + if (sizeof(ColorRgb) != 3) + { + std::cout << "sizeof(ColorRgb) = " << sizeof(ColorRgb) << std::endl; + return -1; + } + + // Install signal handlers to stop loops + signal(SIGTERM, &signal_handler); + signal(SIGINT, &signal_handler); + + if (argc < 2) + { + std::cerr << "Missing argument" << std::endl; + return -1; + } + + if (strncmp("fixed", argv[1], 5) == 0) + { + setColor(argv[2]); + return 0; + } + else if (strncmp("circle", argv[1], 6) == 0) + { + doCircle(); + } + else + { + std::cerr << "Unknown option: " << argv[1] << std::endl; + } + + return 0; +} + From f2e9193987cbe67cfdb00ee3714a36609f7b5a75 Mon Sep 17 00:00:00 2001 From: redPanther Date: Sat, 4 Jun 2016 19:26:34 +0200 Subject: [PATCH 40/63] fix #674 (#676) * implement make install set CMAKE_INSTALL_PREFIX e.g. to /opt to install to /opt/hyperion set ENABLE_SYSTEM_INSTALL to ON to activate installation after compiling use make install or make install/strip (for performance/size optimized binaries - compile in Release to get best performance) * cleanup cmake files use cmake -DINSTALL_PREFIX=/opt/hyperion .. to install all files to hyperion or cmake -DINSTALL_PREFIX=/usr/ to install to usr. install folders are linux standard. bin go to bin folder and additionals (effects) go to share/hyperion * add uninstall target - be patient with that, this will remove files from your system install service files to share/hyperion - if you want to use them you have to make a symlink to your location of service files * optimize build release script install service files into hyperion share folder (services not activated, this must be done by distribution package script) initial support of cmake option -DPLATFORM= option. This selects platform specific cmake flags. no need for -DENABLE_... options (unless you want some special things) automatic detect for apple build * update submodule * fix cmake error when no platform is given * initial support for deb,rpm and tgz packages - no usefull content atm! * make packeages contain usefull stuff * add license make packes more functional. package specific install missing yet * implement debian postinstall * disable rpm generation until it has a working state * add hypercon compat * add posibility for multiple config files. first one found is taken * remove hyperion comaptlayer services is not started automaticly * rework debian postinstall: - remove /opt compatibility complety. This makes more trouble as it is usefull - when hyperiond already started, restart it - cleanup * add deb package dependencies * wipe out last support for /opt installation * change default effect path in config to /usr * revert service files and config files * remove last occurences of ENABLE_PROTOBUF fix cmake warnings and make it ready for cmake 3 fix refactoring of hyperiond.cpp creates no objects for network services Former-commit-id: 56e3e0d1014999b2555418c7b5a2898ac29fb5f1 --- CMakeLists.txt | 6 +- HyperionConfig.h.in | 3 - cmake/qt4/Qt4Macros.cmake | 2 +- dependencies/CMakeLists.txt | 178 +++++++++++++++++------------------ libsrc/CMakeLists.txt | 4 +- src/hyperiond/CMakeLists.txt | 5 +- src/hyperiond/hyperiond.cpp | 7 +- 7 files changed, 98 insertions(+), 107 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cc8b23f..b86f4f15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,9 @@ project(hyperion) # define the minimum cmake version (as required by cmake) cmake_minimum_required(VERSION 2.8) -#set(CMAKE_TOOLCHAIN_FILE /opt/raspberrypi/Toolchain-RaspberryPi.cmake) +IF ( POLICY CMP0026 ) + CMAKE_POLICY( SET CMP0026 OLD ) +ENDIF() SET ( DEFAULT_AMLOGIC OFF ) @@ -55,8 +57,6 @@ message(STATUS "ENABLE_FB = " ${ENABLE_FB}) option(ENABLE_OSX "Enable the osx grabber" ${DEFAULT_OSX} ) message(STATUS "ENABLE_OSX = " ${ENABLE_OSX}) -set(ENABLE_PROTOBUF ON) - option(ENABLE_SPIDEV "Enable the SPIDEV device" ${DEFAULT_SPIDEV} ) message(STATUS "ENABLE_SPIDEV = " ${ENABLE_SPIDEV}) diff --git a/HyperionConfig.h.in b/HyperionConfig.h.in index 7172ec16..135e41f9 100644 --- a/HyperionConfig.h.in +++ b/HyperionConfig.h.in @@ -18,9 +18,6 @@ // Define to enable the spi-device #cmakedefine ENABLE_TINKERFORGE -// Define to enable PROTOBUF server -#cmakedefine ENABLE_PROTOBUF - // Define to enable the framebuffer grabber #cmakedefine ENABLE_FB diff --git a/cmake/qt4/Qt4Macros.cmake b/cmake/qt4/Qt4Macros.cmake index 251d57c3..f2669ffb 100644 --- a/cmake/qt4/Qt4Macros.cmake +++ b/cmake/qt4/Qt4Macros.cmake @@ -202,7 +202,7 @@ macro (QT4_ADD_RESOURCES outfiles ) # let's make a configured file and add it as a dependency so cmake is run # again when dependencies need to be recomputed. QT4_MAKE_OUTPUT_FILE("${infile}" "" "qrc.depends" out_depends) - configure_file("${infile}" "${out_depends}" COPY_ONLY) + configure_file("${infile}" "${out_depends}" COPYONLY) else() # The .qrc file does not exist (yet). Let's add a dependency and hope # that it will be generated later diff --git a/dependencies/CMakeLists.txt b/dependencies/CMakeLists.txt index 0ba08dd5..52d7f741 100644 --- a/dependencies/CMakeLists.txt +++ b/dependencies/CMakeLists.txt @@ -11,100 +11,98 @@ if(ENABLE_WS281XPWM) external/rpi_ws281x/rpihw.c) endif(ENABLE_WS281XPWM) -if(ENABLE_PROTOBUF) - set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared protobuf library") - add_subdirectory(external/protobuf) +set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared protobuf library") +add_subdirectory(external/protobuf) - if(CMAKE_CROSSCOMPILING) - # when crosscompiling import the protoc executable targets from a file generated by a native build - option(IMPORT_PROTOC "Protoc export file (protoc_export.cmake) from a native build" "IMPORT_PROTOC-FILE_NOT_FOUND") - include(${IMPORT_PROTOC}) - else() - # export the protoc compiler so it can be used when cross compiling - export(TARGETS protoc_compiler FILE "${CMAKE_BINARY_DIR}/protoc_export.cmake") +if(CMAKE_CROSSCOMPILING) + # when crosscompiling import the protoc executable targets from a file generated by a native build + option(IMPORT_PROTOC "Protoc export file (protoc_export.cmake) from a native build" "IMPORT_PROTOC-FILE_NOT_FOUND") + include(${IMPORT_PROTOC}) +else() + # export the protoc compiler so it can be used when cross compiling + export(TARGETS protoc_compiler FILE "${CMAKE_BINARY_DIR}/protoc_export.cmake") +endif() + +# define the include for the protobuf library at the parent scope +set(PROTOBUF_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/external/protobuf/src") +set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS} PARENT_SCOPE) + +# define the protoc executable at the parent scope +get_property(PROTOBUF_PROTOC_EXECUTABLE TARGET protoc_compiler PROPERTY LOCATION) +set(PROTOBUF_PROTOC_EXECUTABLE ${PROTOBUF_PROTOC_EXECUTABLE} PARENT_SCOPE) +message(STATUS "Using protobuf compiler: " ${PROTOBUF_PROTOC_EXECUTABLE}) + +#============================================================================= +# Copyright 2009 Kitware, Inc. +# Copyright 2009-2011 Philip Lowman +# Copyright 2008 Esben Mose Hansen, Ange Optimization ApS +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) +function(PROTOBUF_GENERATE_CPP SRCS HDRS) + if(NOT ARGN) + message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files") + return() endif() - # define the include for the protobuf library at the parent scope - set(PROTOBUF_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/external/protobuf/src") - set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS} PARENT_SCOPE) - - # define the protoc executable at the parent scope - get_property(PROTOBUF_PROTOC_EXECUTABLE TARGET protoc_compiler PROPERTY LOCATION) - set(PROTOBUF_PROTOC_EXECUTABLE ${PROTOBUF_PROTOC_EXECUTABLE} PARENT_SCOPE) - message(STATUS "Using protobuf compiler: " ${PROTOBUF_PROTOC_EXECUTABLE}) - - #============================================================================= - # Copyright 2009 Kitware, Inc. - # Copyright 2009-2011 Philip Lowman - # Copyright 2008 Esben Mose Hansen, Ange Optimization ApS - # - # Distributed under the OSI-approved BSD License (the "License"); - # see accompanying file Copyright.txt for details. - # - # This software is distributed WITHOUT ANY WARRANTY; without even the - # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - # See the License for more information. - #============================================================================= - # (To distribute this file outside of CMake, substitute the full - # License text for the above reference.) - function(PROTOBUF_GENERATE_CPP SRCS HDRS) - if(NOT ARGN) - message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files") - return() - endif() - - if(PROTOBUF_GENERATE_CPP_APPEND_PATH) - # Create an include path for each file specified - foreach(FIL ${ARGN}) - get_filename_component(ABS_FIL ${FIL} ABSOLUTE) - get_filename_component(ABS_PATH ${ABS_FIL} PATH) - list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) - if(${_contains_already} EQUAL -1) - list(APPEND _protobuf_include_path -I ${ABS_PATH}) - endif() - endforeach() - else() - set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR}) - endif() - - if(DEFINED PROTOBUF_IMPORT_DIRS) - foreach(DIR ${PROTOBUF_IMPORT_DIRS}) - get_filename_component(ABS_PATH ${DIR} ABSOLUTE) - list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) - if(${_contains_already} EQUAL -1) - list(APPEND _protobuf_include_path -I ${ABS_PATH}) - endif() - endforeach() - endif() - - if(CMAKE_CROSSCOMPILING) - set(PROTOC_DEPENDENCY ${PROTOBUF_PROTOC_EXECUTABLE}) - else() - set(PROTOC_DEPENDENCY protoc_compiler) - endif() - - set(${SRCS}) - set(${HDRS}) + if(PROTOBUF_GENERATE_CPP_APPEND_PATH) + # Create an include path for each file specified foreach(FIL ${ARGN}) get_filename_component(ABS_FIL ${FIL} ABSOLUTE) - get_filename_component(FIL_WE ${FIL} NAME_WE) - - list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc") - list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h") - - add_custom_command( - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc" - "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h" - COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} - ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL} - DEPENDS ${ABS_FIL} ${PROTOC_DEPENDENCY} - COMMENT "Running C++ protocol buffer compiler on ${FIL}" - VERBATIM - ) + get_filename_component(ABS_PATH ${ABS_FIL} PATH) + list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) + if(${_contains_already} EQUAL -1) + list(APPEND _protobuf_include_path -I ${ABS_PATH}) + endif() endforeach() + else() + set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR}) + endif() - set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE) - set(${SRCS} ${${SRCS}} PARENT_SCOPE) - set(${HDRS} ${${HDRS}} PARENT_SCOPE) - endfunction() -endif() + if(DEFINED PROTOBUF_IMPORT_DIRS) + foreach(DIR ${PROTOBUF_IMPORT_DIRS}) + get_filename_component(ABS_PATH ${DIR} ABSOLUTE) + list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) + if(${_contains_already} EQUAL -1) + list(APPEND _protobuf_include_path -I ${ABS_PATH}) + endif() + endforeach() + endif() + + if(CMAKE_CROSSCOMPILING) + set(PROTOC_DEPENDENCY ${PROTOBUF_PROTOC_EXECUTABLE}) + else() + set(PROTOC_DEPENDENCY protoc_compiler) + endif() + + set(${SRCS}) + set(${HDRS}) + foreach(FIL ${ARGN}) + get_filename_component(ABS_FIL ${FIL} ABSOLUTE) + get_filename_component(FIL_WE ${FIL} NAME_WE) + + list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc") + list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h") + + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc" + "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h" + COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} + ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL} + DEPENDS ${ABS_FIL} ${PROTOC_DEPENDENCY} + COMMENT "Running C++ protocol buffer compiler on ${FIL}" + VERBATIM + ) + endforeach() + + set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE) + set(${SRCS} ${${SRCS}} PARENT_SCOPE) + set(${HDRS} ${${HDRS}} PARENT_SCOPE) +endfunction() diff --git a/libsrc/CMakeLists.txt b/libsrc/CMakeLists.txt index 5cba07db..d6b1f044 100644 --- a/libsrc/CMakeLists.txt +++ b/libsrc/CMakeLists.txt @@ -7,9 +7,7 @@ add_subdirectory(hyperion) add_subdirectory(blackborder) add_subdirectory(jsonserver) -if (ENABLE_PROTOBUF) - add_subdirectory(protoserver) -endif () +add_subdirectory(protoserver) if (ENABLE_ZEROCONF) add_subdirectory(bonjour) diff --git a/src/hyperiond/CMakeLists.txt b/src/hyperiond/CMakeLists.txt index 42930d53..ed79f4c1 100644 --- a/src/hyperiond/CMakeLists.txt +++ b/src/hyperiond/CMakeLists.txt @@ -9,6 +9,7 @@ target_link_libraries(hyperiond effectengine jsonserver boblightserver + protoserver ) if (ENABLE_DISPMANX) @@ -31,10 +32,6 @@ if (ENABLE_AMLOGIC) target_link_libraries(hyperiond amlogic-grabber) endif () -if (ENABLE_PROTOBUF) - target_link_libraries(hyperiond protoserver) -endif () - if (ENABLE_ZEROCONF) target_link_libraries(hyperiond bonjour) endif() diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 329fe2db..11ceff52 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -186,7 +186,7 @@ void startXBMCVideoChecker(const Json::Value &config, XBMCVideoChecker* xbmcVide } } -void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonServer* jsonServer, ProtoServer* protoServer, BoblightServer* boblightServer) +void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonServer* &jsonServer, ProtoServer* &protoServer, BoblightServer* &boblightServer) { // Create Json server if configuration is present if (config.isMember("jsonServer")) @@ -194,6 +194,7 @@ void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonSer const Json::Value & jsonServerConfig = config["jsonServer"]; jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt()); std::cout << "INFO: Json server created and started on port " << jsonServer->getPort() << std::endl; + #ifdef ENABLE_ZEROCONF const Json::Value & deviceConfig = config["device"]; const std::string deviceName = deviceConfig.get("name", "").asString(); @@ -215,6 +216,7 @@ void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonSer const Json::Value & protoServerConfig = config["protoServer"]; protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); std::cout << "INFO: Proto server created and started on port " << protoServer->getPort() << std::endl; + #ifdef ENABLE_ZEROCONF const Json::Value & deviceConfig = config["device"]; const std::string deviceName = deviceConfig.get("name", "").asString(); @@ -369,7 +371,7 @@ void startGrabberFramebuffer(const Json::Value &config, Hyperion &hyperion, Prot #ifdef ENABLE_OSX -void startGrabberOsx(const Json::Value &config, Hyperion &hyperion, ProtoServer * protoServer, XBMCVideoChecker* xbmcVideoChecker, OsxWrapper * osxGrabber) +void startGrabberOsx(const Json::Value &config, Hyperion &hyperion, ProtoServer* protoServer, XBMCVideoChecker* xbmcVideoChecker, OsxWrapper * osxGrabber) { // Construct and start the osx grabber if the configuration is present if (config.isMember("osxgrabber") || config.isMember("framegrabber")) @@ -472,7 +474,6 @@ int main(int argc, char** argv) BoblightServer * boblightServer = nullptr; startNetworkServices(config, hyperion, jsonServer, protoServer, boblightServer); - // ---- grabber ----- #ifdef ENABLE_DISPMANX From bab27964f2d2fc1891da4989cca03b90cd6d4159 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Sun, 5 Jun 2016 03:27:47 +1000 Subject: [PATCH 41/63] added multicast reception in the udp effect (#675) * Removed -HUP so the default -TERM signal is sent instead. - hyperiond only listens for TERM and INT. HUP is often used to get an exe to reread its config Changed pgrep to add '-x' so it wont partial match on the exe name. - I have multiple instances with multiple hyperiond-instance1 names - this ensures the service script only kills the right process * reversing errant change to hyperion.systemd.sh * cleaned up a couple of compiler warnings * moved bitpair_to_byte initialiser to (hopefully) work with older GCC * compiler warning in udp driver removed some tabs in ws2812b.cpp * formatting - spaces to tabs * moved rpi_281x to tag sk6812-v1.0 * moving to my fork of rpi_281x * removed dos line endings * Found some more "dos" line ending files * Added multicast support to the udp listener "effect" * the default udp.json will listen to unicast on port 2391 (as it used to) the new udp-mcast.json will listen on multicast 239.255.28.01:2801 Former-commit-id: 5c76fabd3da141094f5434ed869420ad6e581fd8 --- effects/udp-mcast.json | 9 +++++++++ effects/udp.json | 16 ++++++++-------- effects/udp.py | 24 ++++++++++++++++++++---- 3 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 effects/udp-mcast.json diff --git a/effects/udp-mcast.json b/effects/udp-mcast.json new file mode 100644 index 00000000..eb492ffe --- /dev/null +++ b/effects/udp-mcast.json @@ -0,0 +1,9 @@ +{ + "name" : "UDP multicast listener", + "script" : "udp.py", + "args" : + { + "ListenPort" : 2801, + "ListenIP" : "239.255.28.01" + } +} diff --git a/effects/udp.json b/effects/udp.json index 29df0971..0fc6e6e6 100644 --- a/effects/udp.json +++ b/effects/udp.json @@ -1,8 +1,8 @@ -{ - "name" : "UDP listener", - "script" : "udp.py", - "args" : - { - "udpPort" : 2391 - } -} +{ + "name" : "UDP listener", + "script" : "udp.py", + "args" : + { + "ListenPort" : 2391 + } +} diff --git a/effects/udp.py b/effects/udp.py index f8317a20..6f39b1d1 100644 --- a/effects/udp.py +++ b/effects/udp.py @@ -3,17 +3,33 @@ import time import colorsys import socket import errno +import struct # Get the parameters -udpPort = int(hyperion.args.get('udpPort', 2812)) +ListenPort = int(hyperion.args.get('ListenPort', 2801)) +ListenIP = hyperion.args.get('ListenIP', "") +octets = ListenIP.split('.'); -UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) +UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM, socket.IPPROTO_UDP) UDPSock.setblocking(False) -listen_addr = ("",udpPort) -print "udp.py: bind socket port:",udpPort +listen_addr = (ListenIP,ListenPort) UDPSock.bind(listen_addr) +if ListenIP == "": + print "udp.py: Listening on *.*.*.*:"+str(ListenPort) +else: + print "udp.py: Listening on "+ListenIP+":"+str(ListenPort) + +if len(octets) == 4 and int(octets[0]) >= 224 and int(octets[0]) < 240: + print "ListenIP is a multicast address\n" + # Multicast handling + try: + mreq = struct.pack("4sl", socket.inet_aton(ListenIP), socket.INADDR_ANY) + UDPSock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + except socket.error: + print "ERROR enabling multicast\n" + hyperion.setColor(hyperion.ledCount * bytearray((int(0), int(0), int(0))) ) # Start the write data loop From a0b0f6b35dd76095ced79694d499f61123a95301 Mon Sep 17 00:00:00 2001 From: redPanther Date: Sat, 4 Jun 2016 19:58:40 +0200 Subject: [PATCH 42/63] fix for #674 (#677) * implement make install set CMAKE_INSTALL_PREFIX e.g. to /opt to install to /opt/hyperion set ENABLE_SYSTEM_INSTALL to ON to activate installation after compiling use make install or make install/strip (for performance/size optimized binaries - compile in Release to get best performance) * cleanup cmake files use cmake -DINSTALL_PREFIX=/opt/hyperion .. to install all files to hyperion or cmake -DINSTALL_PREFIX=/usr/ to install to usr. install folders are linux standard. bin go to bin folder and additionals (effects) go to share/hyperion * add uninstall target - be patient with that, this will remove files from your system install service files to share/hyperion - if you want to use them you have to make a symlink to your location of service files * optimize build release script install service files into hyperion share folder (services not activated, this must be done by distribution package script) initial support of cmake option -DPLATFORM= option. This selects platform specific cmake flags. no need for -DENABLE_... options (unless you want some special things) automatic detect for apple build * update submodule * fix cmake error when no platform is given * initial support for deb,rpm and tgz packages - no usefull content atm! * make packeages contain usefull stuff * add license make packes more functional. package specific install missing yet * implement debian postinstall * disable rpm generation until it has a working state * add hypercon compat * add posibility for multiple config files. first one found is taken * remove hyperion comaptlayer services is not started automaticly * rework debian postinstall: - remove /opt compatibility complety. This makes more trouble as it is usefull - when hyperiond already started, restart it - cleanup * add deb package dependencies * wipe out last support for /opt installation * change default effect path in config to /usr * revert service files and config files * remove last occurences of ENABLE_PROTOBUF fix cmake warnings and make it ready for cmake 3 fix refactoring of hyperiond.cpp creates no objects for network services * all arguments via reference ... Former-commit-id: 0a7af16c620093b0ecd38f0efc300d7fd30d961d --- src/hyperiond/hyperiond.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 11ceff52..688a77fc 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -242,7 +242,7 @@ void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonSer } #ifdef ENABLE_DISPMANX -void startGrabberDispmanx(const Json::Value &config, Hyperion &hyperion, ProtoServer * protoServer, XBMCVideoChecker* xbmcVideoChecker, DispmanxWrapper * dispmanx) +void startGrabberDispmanx(const Json::Value &config, Hyperion &hyperion, ProtoServer* &protoServer, XBMCVideoChecker* &xbmcVideoChecker, DispmanxWrapper* &dispmanx) { // Construct and start the frame-grabber if the configuration is present if (config.isMember("framegrabber")) @@ -275,7 +275,7 @@ void startGrabberDispmanx(const Json::Value &config, Hyperion &hyperion, ProtoSe #endif #ifdef ENABLE_V4L2 -void startGrabberV4L2(const Json::Value &config, Hyperion &hyperion, ProtoServer * protoServer, V4L2Wrapper * v4l2Grabber ) +void startGrabberV4L2(const Json::Value &config, Hyperion &hyperion, ProtoServer* &protoServer, V4L2Wrapper* &v4l2Grabber ) { // construct and start the v4l2 grabber if the configuration is present if (config.isMember("grabber-v4l2")) @@ -312,7 +312,7 @@ void startGrabberV4L2(const Json::Value &config, Hyperion &hyperion, ProtoServer #endif #ifdef ENABLE_AMLOGIC -void startGrabberAmlogic(const Json::Value &config, Hyperion &hyperion, ProtoServer * protoServer, XBMCVideoChecker* xbmcVideoChecker, AmlogicWrapper * amlGrabber) +void startGrabberAmlogic(const Json::Value &config, Hyperion &hyperion, ProtoServer* &protoServer, XBMCVideoChecker* &xbmcVideoChecker, AmlogicWrapper* &amlGrabber) { // Construct and start the framebuffer grabber if the configuration is present if (config.isMember("amlgrabber")) @@ -341,7 +341,7 @@ void startGrabberAmlogic(const Json::Value &config, Hyperion &hyperion, ProtoSer #ifdef ENABLE_FB -void startGrabberFramebuffer(const Json::Value &config, Hyperion &hyperion, ProtoServer * protoServer, XBMCVideoChecker* xbmcVideoChecker, FramebufferWrapper * fbGrabber) +void startGrabberFramebuffer(const Json::Value &config, Hyperion &hyperion, ProtoServer* &protoServer, XBMCVideoChecker* &xbmcVideoChecker, FramebufferWrapper* &fbGrabber) { // Construct and start the framebuffer grabber if the configuration is present if (config.isMember("framebuffergrabber") || config.isMember("framegrabber")) @@ -371,7 +371,7 @@ void startGrabberFramebuffer(const Json::Value &config, Hyperion &hyperion, Prot #ifdef ENABLE_OSX -void startGrabberOsx(const Json::Value &config, Hyperion &hyperion, ProtoServer* protoServer, XBMCVideoChecker* xbmcVideoChecker, OsxWrapper * osxGrabber) +void startGrabberOsx(const Json::Value &config, Hyperion &hyperion, ProtoServer* &protoServer, XBMCVideoChecker* &xbmcVideoChecker, OsxWrapper* &osxGrabber) { // Construct and start the osx grabber if the configuration is present if (config.isMember("osxgrabber") || config.isMember("framegrabber")) From a5b8aeff54be6adfdff87f6c8f8e3ffeeb62face Mon Sep 17 00:00:00 2001 From: redPanther Date: Sat, 4 Jun 2016 23:09:20 +0200 Subject: [PATCH 43/63] fix for #674 (#679) * implement make install set CMAKE_INSTALL_PREFIX e.g. to /opt to install to /opt/hyperion set ENABLE_SYSTEM_INSTALL to ON to activate installation after compiling use make install or make install/strip (for performance/size optimized binaries - compile in Release to get best performance) * cleanup cmake files use cmake -DINSTALL_PREFIX=/opt/hyperion .. to install all files to hyperion or cmake -DINSTALL_PREFIX=/usr/ to install to usr. install folders are linux standard. bin go to bin folder and additionals (effects) go to share/hyperion * add uninstall target - be patient with that, this will remove files from your system install service files to share/hyperion - if you want to use them you have to make a symlink to your location of service files * optimize build release script install service files into hyperion share folder (services not activated, this must be done by distribution package script) initial support of cmake option -DPLATFORM= option. This selects platform specific cmake flags. no need for -DENABLE_... options (unless you want some special things) automatic detect for apple build * update submodule * fix cmake error when no platform is given * initial support for deb,rpm and tgz packages - no usefull content atm! * make packeages contain usefull stuff * add license make packes more functional. package specific install missing yet * implement debian postinstall * disable rpm generation until it has a working state * add hypercon compat * add posibility for multiple config files. first one found is taken * remove hyperion comaptlayer services is not started automaticly * rework debian postinstall: - remove /opt compatibility complety. This makes more trouble as it is usefull - when hyperiond already started, restart it - cleanup * add deb package dependencies * wipe out last support for /opt installation * change default effect path in config to /usr * revert service files and config files * remove last occurences of ENABLE_PROTOBUF fix cmake warnings and make it ready for cmake 3 fix refactoring of hyperiond.cpp creates no objects for network services * all arguments via reference ... * fix xbmcchecker not working Former-commit-id: 470fbe6f0e6fdadc5aab14e076aa9d4967a4d45d --- src/hyperiond/hyperiond.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 688a77fc..838827a9 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -166,7 +166,7 @@ void startBootsequence(const Json::Value &config, Hyperion &hyperion) // create XBMC video checker if the configuration is present -void startXBMCVideoChecker(const Json::Value &config, XBMCVideoChecker* xbmcVideoChecker) +void startXBMCVideoChecker(const Json::Value &config, XBMCVideoChecker* &xbmcVideoChecker) { if (config.isMember("xbmcVideoChecker")) { From f39f074dcffce544ea4fef741f861a20b3992a77 Mon Sep 17 00:00:00 2001 From: redPanther Date: Sun, 5 Jun 2016 16:08:55 +0200 Subject: [PATCH 44/63] add logger/compiler class (#680) * implement make install set CMAKE_INSTALL_PREFIX e.g. to /opt to install to /opt/hyperion set ENABLE_SYSTEM_INSTALL to ON to activate installation after compiling use make install or make install/strip (for performance/size optimized binaries - compile in Release to get best performance) * cleanup cmake files use cmake -DINSTALL_PREFIX=/opt/hyperion .. to install all files to hyperion or cmake -DINSTALL_PREFIX=/usr/ to install to usr. install folders are linux standard. bin go to bin folder and additionals (effects) go to share/hyperion * add uninstall target - be patient with that, this will remove files from your system install service files to share/hyperion - if you want to use them you have to make a symlink to your location of service files * optimize build release script install service files into hyperion share folder (services not activated, this must be done by distribution package script) initial support of cmake option -DPLATFORM= option. This selects platform specific cmake flags. no need for -DENABLE_... options (unless you want some special things) automatic detect for apple build * update submodule * fix cmake error when no platform is given * initial support for deb,rpm and tgz packages - no usefull content atm! * make packeages contain usefull stuff * add license make packes more functional. package specific install missing yet * implement debian postinstall * disable rpm generation until it has a working state * add hypercon compat * add posibility for multiple config files. first one found is taken * remove hyperion comaptlayer services is not started automaticly * rework debian postinstall: - remove /opt compatibility complety. This makes more trouble as it is usefull - when hyperiond already started, restart it - cleanup * add deb package dependencies * wipe out last support for /opt installation * change default effect path in config to /usr * revert service files and config files * remove last occurences of ENABLE_PROTOBUF fix cmake warnings and make it ready for cmake 3 fix refactoring of hyperiond.cpp creates no objects for network services * all arguments via reference ... * fix xbmcchecker not working * add logger class * - profiler must be activated with ENABLE_PROFILER, otherwise an error will raise -> this should prevent profiler gets into release code * fix profiler Former-commit-id: b716dd40dbf5b837356eec876d85ec71c86d5c6c --- CMakeLists.txt | 3 ++ HyperionConfig.h.in | 4 ++ include/utils/Logger.h | 48 +++++++++++++++++ include/utils/Profiler.h | 37 +++++++++++++ libsrc/utils/CMakeLists.txt | 8 +++ libsrc/utils/Logger.cpp | 100 ++++++++++++++++++++++++++++++++++++ libsrc/utils/Profiler.cpp | 98 +++++++++++++++++++++++++++++++++++ 7 files changed, 298 insertions(+) create mode 100644 include/utils/Logger.h create mode 100644 include/utils/Profiler.h create mode 100644 libsrc/utils/Logger.cpp create mode 100644 libsrc/utils/Profiler.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b86f4f15..b94e3068 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,9 @@ message(STATUS "ENABLE_QT5 = " ${ENABLE_QT5}) option(ENABLE_TESTS "Compile additional test applications" OFF) message(STATUS "ENABLE_TESTS = " ${ENABLE_TESTS}) +option(ENABLE_PROFILER "enable profiler capabilities - not for release code" OFF) +message(STATUS "ENABLE_PROFILER = " ${ENABLE_PROFILER}) + if(ENABLE_FB AND ENABLE_DISPMANX) message(FATAL_ERROR "dispmanx grabber and framebuffer grabber cannot be used at the same time") diff --git a/HyperionConfig.h.in b/HyperionConfig.h.in index 135e41f9..3ce776b5 100644 --- a/HyperionConfig.h.in +++ b/HyperionConfig.h.in @@ -30,4 +30,8 @@ // Define to enable the bonjour/zeroconf publishing #cmakedefine ENABLE_ZEROCONF +// Define to enable profiler for development purpose +#cmakedefine ENABLE_PROFILER + +// the hyperion build id string #define HYPERION_VERSION_ID "${HYPERION_VERSION_ID}" diff --git a/include/utils/Logger.h b/include/utils/Logger.h new file mode 100644 index 00000000..77413150 --- /dev/null +++ b/include/utils/Logger.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include +#include + +// standard log messages +//#define _FUNCNAME_ __PRETTY_FUNCTION__ +#define _FUNCNAME_ __FUNCTION__ + +#define Debug(logger, ...) { (logger)->Message(Logger::DEBUG , __FILE__, _FUNCNAME_, __LINE__, __VA_ARGS__); } +#define Info(logger, ...) { (logger)->Message(Logger::INFO , __FILE__, _FUNCNAME_, __LINE__, __VA_ARGS__); } +#define Warning(logger, ...) { (logger)->Message(Logger::WARNING, __FILE__, _FUNCNAME_, __LINE__, __VA_ARGS__); } +#define Error(logger, ...) { (logger)->Message(Logger::ERROR , __FILE__, _FUNCNAME_, __LINE__, __VA_ARGS__); } + +// conditional log messages +#define DebugIf(condition, logger, ...) { if (condition) {(logger)->Message(Logger::DEBUG , __FILE__, _FUNCNAME_, __LINE__, __VA_ARGS__);} } +#define InfoIf(condition, logger, ...) { if (condition) {(logger)->Message(Logger::INFO , __FILE__, _FUNCNAME_, __LINE__, __VA_ARGS__);} } +#define WarningIf(condition, logger, ...) { if (condition) {(logger)->Message(Logger::WARNING , __FILE__, _FUNCNAME_, __LINE__, __VA_ARGS__);} } +#define ErrorIf(condition, logger, ...) { if (condition) {(logger)->Message(Logger::ERROR , __FILE__, _FUNCNAME_, __LINE__, __VA_ARGS__);} } + +// ================================================================ + +class Logger +{ +public: + enum LogLevel { DEBUG=0, INFO=1,WARNING=2,ERROR=3 }; + + static Logger* getInstance(std::string name="", LogLevel minLevel=Logger::INFO); + + void Message(LogLevel level, const char* sourceFile, const char* func, unsigned int line, const char* fmt, ...); + void setMinLevel(LogLevel level) { _minLevel = level; }; + +protected: + Logger( std::string name="", LogLevel minLevel=INFO); + ~Logger(); + +private: + static std::map *LoggerMap; + + std::string _name; + std::string _appname; + LogLevel _minLevel; + bool _syslogEnabled; + unsigned int _loggerId; +}; + diff --git a/include/utils/Profiler.h b/include/utils/Profiler.h new file mode 100644 index 00000000..0b76f1c9 --- /dev/null +++ b/include/utils/Profiler.h @@ -0,0 +1,37 @@ +#include "utils/Logger.h" +#include +#include +#include +#include +#include + +#ifndef ENABLE_PROFILER + #error "Profiler is not for productive code, enable it via cmake or remove header include" +#endif + +// profiler +#define PROFILER_BLOCK_EXECUTION_TIME Profiler DEBUG_PROFILE__BLOCK__EXECUTION__TIME_messure_object(__FILE__, _FUNCNAME_, __LINE__ ); +#define PROFILER_TIMER_START(stopWatchName) Profiler::TimerStart(stopWatchName, __FILE__, _FUNCNAME_, __LINE__); +#define PROFILER_TIMER_GET(stopWatchName) Profiler::TimerGetTime(stopWatchName, __FILE__, _FUNCNAME_, __LINE__); +#define PROFILER_TIMER_GET_IF(condition, stopWatchName) { if (condition) {Profiler::TimerGetTime(stopWatchName, __FILE__, _FUNCNAME_, __LINE__);} } + + +class Profiler +{ +public: + Profiler(const char* sourceFile, const char* func, unsigned int line); + ~Profiler(); + + static void TimerStart(const std::string stopWatchName, const char* sourceFile, const char* func, unsigned int line); + static void TimerGetTime(const std::string stopWatchName, const char* sourceFile, const char* func, unsigned int line); + +private: + static void initLogger(); + + static Logger* _logger; + const char* _file; + const char* _func; + unsigned int _line; + unsigned int _blockId; + clock_t _startTime; +}; diff --git a/libsrc/utils/CMakeLists.txt b/libsrc/utils/CMakeLists.txt index caf0aabe..3e02ec6b 100644 --- a/libsrc/utils/CMakeLists.txt +++ b/libsrc/utils/CMakeLists.txt @@ -2,6 +2,10 @@ SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/utils) SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/utils) +if ( ENABLE_PROFILER ) + SET ( PROFILER_SOURCE ${CURRENT_HEADER_DIR}/Profiler.h ${CURRENT_SOURCE_DIR}/Profiler.cpp ) +endif() + add_library(hyperion-utils ${CURRENT_HEADER_DIR}/ColorArgb.h ${CURRENT_SOURCE_DIR}/ColorArgb.cpp @@ -16,6 +20,10 @@ add_library(hyperion-utils ${CURRENT_HEADER_DIR}/Image.h ${CURRENT_HEADER_DIR}/Sleep.h + ${CURRENT_HEADER_DIR}/Logger.h + ${CURRENT_SOURCE_DIR}/Logger.cpp + ${PROFILER_SOURCE} + ${CURRENT_HEADER_DIR}/PixelFormat.h ${CURRENT_HEADER_DIR}/VideoMode.h diff --git a/libsrc/utils/Logger.cpp b/libsrc/utils/Logger.cpp new file mode 100644 index 00000000..1b865d43 --- /dev/null +++ b/libsrc/utils/Logger.cpp @@ -0,0 +1,100 @@ +#include "utils/Logger.h" + +#include +#include +#include +#include +#include +#include + +std::string getBaseName( std::string sourceFile) +{ + QFileInfo fi( sourceFile.c_str() ); + return fi.fileName().toStdString(); +} + +static const char * LogLevelStrings[] = { "DEBUG", "INFO", "WARNING", "ERROR" }; +static const int LogLevelSysLog[] = { LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR }; +static unsigned int loggerCount = 0; +static unsigned int loggerId = 0; +std::map *Logger::LoggerMap = nullptr; + + +Logger* Logger::getInstance(std::string name, Logger::LogLevel minLevel) +{ + if (Logger::LoggerMap == nullptr) + { + Logger::LoggerMap = new std::map; + } + + if ( LoggerMap->find(name) == LoggerMap->end() ) + { + Logger* log = new Logger(name,minLevel); + Logger::LoggerMap->emplace(name,log); + return log; + } + + return Logger::LoggerMap->at(name); +} + + + +Logger::Logger ( std::string name, LogLevel minLevel ): + _name(name), + _minLevel(minLevel), + _syslogEnabled(true), + _loggerId(loggerId++) +{ + _appname = std::string(program_invocation_short_name); + std::transform(_appname.begin(), _appname.end(),_appname.begin(), ::toupper); + + loggerCount++; + +// if (pLoggerMap == NULL) +// pLoggerMap = new std::map; +// +// + + if (_syslogEnabled && loggerCount == 1 ) + { + openlog (program_invocation_short_name, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL0); + } +} + +Logger::~Logger() +{ + //LoggerMap.erase(_loggerId); + loggerCount--; + if ( loggerCount == 0 ) + closelog(); +} + + +void Logger::Message(LogLevel level, const char* sourceFile, const char* func, unsigned int line, const char* fmt, ...) +{ + if ( level < _minLevel ) + return; + + char msg[512]; + va_list args; + va_start (args, fmt); + vsprintf (msg,fmt, args); + va_end (args); + + std::string location; + std::string function(func); + if ( level == Logger::DEBUG ) + { + location = "<" + getBaseName(sourceFile) + ":" + QString::number(line).toStdString()+":"+ function + "()> "; + } + + std::cout + << "[" << _appname << " " << _name << "] <" + << LogLevelStrings[level] << "> " << location << msg + << std::endl; + + if ( _syslogEnabled && level >= Logger::WARNING ) + syslog (LogLevelSysLog[level], "%s", msg); +} + + diff --git a/libsrc/utils/Profiler.cpp b/libsrc/utils/Profiler.cpp new file mode 100644 index 00000000..2c076c43 --- /dev/null +++ b/libsrc/utils/Profiler.cpp @@ -0,0 +1,98 @@ +#include "HyperionConfig.h" +#include "utils/Profiler.h" + +#include +#include + +struct StopWatchItem { + const char* sourceFile; + const char* func; + unsigned int line; + clock_t startTime; +}; + +static unsigned int blockCounter = 0; +static std::map GlobalProfilerMap; +Logger* Profiler::_logger = nullptr; + + + +std::string profiler_getBaseName( std::string sourceFile) +{ + QFileInfo fi( sourceFile.c_str() ); + return fi.fileName().toStdString(); +} + +double getClockDelta(clock_t start) +{ + return ((double)(clock() - start) / CLOCKS_PER_SEC) ; +} + + + +Profiler::Profiler(const char* sourceFile, const char* func, unsigned int line) : + _file(sourceFile), + _func(func), + _line(line), + _blockId(blockCounter++), + _startTime(clock()) +{ + Profiler::initLogger(); + _logger->Message(Logger::DEBUG,_file,_func,_line,">>> enter block %d", _blockId); +} + + +Profiler::~Profiler() +{ + _logger->Message( Logger::DEBUG, _file,_func, _line, "<<< exit block %d, executed for %f s", _blockId, getClockDelta(_startTime) ); +} + +void Profiler::initLogger() +{ + if (_logger == nullptr ) + _logger = Logger::getInstance("PROFILER", Logger::DEBUG); +} + +void Profiler::TimerStart(const std::string timerName, const char* sourceFile, const char* func, unsigned int line) +{ + std::pair::iterator,bool> ret; + Profiler::initLogger(); + + StopWatchItem item = {sourceFile, func, line}; + + ret = GlobalProfilerMap.emplace(timerName, item); + if ( ! ret.second ) + { + if ( ret.first->second.sourceFile == sourceFile && ret.first->second.func == func && ret.first->second.line == line ) + { + _logger->Message(Logger::DEBUG, sourceFile, func, line, "restart timer '%s'", timerName.c_str() ); + ret.first->second.startTime = clock(); + } + else + { + _logger->Message(Logger::DEBUG, sourceFile, func, line, "ERROR timer '%s' started in multiple locations. First occurence %s:%d:%s()", + timerName.c_str(), profiler_getBaseName(ret.first->second.sourceFile).c_str(), ret.first->second.line, ret.first->second.func ); + } + } + else + { + _logger->Message(Logger::DEBUG, sourceFile, func, line, "start timer '%s'", timerName.c_str() ); + } +} + + +void Profiler::TimerGetTime(const std::string timerName, const char* sourceFile, const char* func, unsigned int line) +{ + std::map::iterator ret = GlobalProfilerMap.find(timerName); + Profiler::initLogger(); + if (ret != GlobalProfilerMap.end()) + { + _logger->Message(Logger::DEBUG, sourceFile, func, line, "timer '%s' started at %s:%d:%s() took %f s execution time until here", timerName.c_str(), + profiler_getBaseName(ret->second.sourceFile).c_str(), ret->second.line, ret->second.func, getClockDelta(ret->second.startTime) ); + } + else + { + _logger->Message(Logger::DEBUG, sourceFile, func, line, "ERROR timer '%s' not started", timerName.c_str() ); + } +} + From 9578a3e386ba9d266ed380e3c6083aaba04b4a42 Mon Sep 17 00:00:00 2001 From: brindosch Date: Tue, 7 Jun 2016 12:34:50 +0200 Subject: [PATCH 45/63] Kodicheck: Add option for pause modus (#681) * introduce pause mode * fix it fe... * fix * fix compile warning * change solution * fix order * fix * last update * - Former-commit-id: b35c4d672aed5be7a6a694b3c861c6cf287d89df --- include/utils/GrabbingMode.h | 1 + include/xbmcvideochecker/XBMCVideoChecker.h | 9 ++++++--- libsrc/grabber/amlogic/AmlogicWrapper.cpp | 1 + libsrc/grabber/dispmanx/DispmanxWrapper.cpp | 1 + libsrc/grabber/framebuffer/FramebufferWrapper.cpp | 1 + libsrc/grabber/osx/OsxWrapper.cpp | 1 + libsrc/hyperion/hyperion.schema.json | 4 ++++ libsrc/xbmcvideochecker/XBMCVideoChecker.cpp | 11 ++++++++++- src/hyperiond/hyperiond.cpp | 1 + 9 files changed, 26 insertions(+), 4 deletions(-) diff --git a/include/utils/GrabbingMode.h b/include/utils/GrabbingMode.h index fe3b09ee..c97aaa8e 100644 --- a/include/utils/GrabbingMode.h +++ b/include/utils/GrabbingMode.h @@ -9,6 +9,7 @@ enum GrabbingMode GRABBINGMODE_OFF, /** Frame grabbing during video */ GRABBINGMODE_VIDEO, + GRABBINGMODE_PAUSE, GRABBINGMODE_PHOTO, GRABBINGMODE_AUDIO, GRABBINGMODE_MENU, diff --git a/include/xbmcvideochecker/XBMCVideoChecker.h b/include/xbmcvideochecker/XBMCVideoChecker.h index 01401093..9ad30c3b 100644 --- a/include/xbmcvideochecker/XBMCVideoChecker.h +++ b/include/xbmcvideochecker/XBMCVideoChecker.h @@ -41,7 +41,7 @@ public: /// @param grabScreensaver Whether or not to grab when the XBMC screensaver is activated /// @param enable3DDetection Wheter or not to enable the detection of 3D movies playing /// - XBMCVideoChecker(const std::string & address, uint16_t port, bool grabVideo, bool grabPhoto, bool grabAudio, bool grabMenu, bool grabScreensaver, bool enable3DDetection); + XBMCVideoChecker(const std::string & address, uint16_t port, bool grabVideo, bool grabPhoto, bool grabAudio, bool grabMenu, bool grabPause, bool grabScreensaver, bool enable3DDetection); /// /// Start polling XBMC @@ -76,7 +76,7 @@ private: void setGrabbingMode(GrabbingMode grabbingMode); void setScreensaverMode(bool isOnScreensaver); - + /// Set the video mode void setVideoMode(VideoMode videoMode); @@ -117,6 +117,9 @@ private: /// Flag indicating whether or not to grab when XBMC is playing nothing (in menu) const bool _grabMenu; + /// Flag indicating whether or not to grab when the XBMC videoplayer is at pause state + const bool _grabPause; + /// Flag indicating whether or not to grab when the XBMC screensaver is activated const bool _grabScreensaver; @@ -125,7 +128,7 @@ private: /// Flag indicating if XBMC is on screensaver bool _previousScreensaverMode; - + /// Previous emitted grab mode GrabbingMode _previousGrabbingMode; diff --git a/libsrc/grabber/amlogic/AmlogicWrapper.cpp b/libsrc/grabber/amlogic/AmlogicWrapper.cpp index eb47e155..51668b69 100644 --- a/libsrc/grabber/amlogic/AmlogicWrapper.cpp +++ b/libsrc/grabber/amlogic/AmlogicWrapper.cpp @@ -78,6 +78,7 @@ void AmlogicWrapper::setGrabbingMode(const GrabbingMode mode) switch (mode) { case GRABBINGMODE_VIDEO: + case GRABBINGMODE_PAUSE: // _frameGrabber->setFlags(DISPMANX_SNAPSHOT_NO_RGB|DISPMANX_SNAPSHOT_FILL); start(); break; diff --git a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp index bad3807f..23bc22f6 100644 --- a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp +++ b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp @@ -74,6 +74,7 @@ void DispmanxWrapper::setGrabbingMode(const GrabbingMode mode) switch (mode) { case GRABBINGMODE_VIDEO: + case GRABBINGMODE_PAUSE: _frameGrabber->setFlags(DISPMANX_SNAPSHOT_NO_RGB|DISPMANX_SNAPSHOT_FILL); start(); break; diff --git a/libsrc/grabber/framebuffer/FramebufferWrapper.cpp b/libsrc/grabber/framebuffer/FramebufferWrapper.cpp index 25a23311..97734deb 100644 --- a/libsrc/grabber/framebuffer/FramebufferWrapper.cpp +++ b/libsrc/grabber/framebuffer/FramebufferWrapper.cpp @@ -62,6 +62,7 @@ void FramebufferWrapper::setGrabbingMode(const GrabbingMode mode) switch (mode) { case GRABBINGMODE_VIDEO: + case GRABBINGMODE_PAUSE: case GRABBINGMODE_AUDIO: case GRABBINGMODE_PHOTO: case GRABBINGMODE_MENU: diff --git a/libsrc/grabber/osx/OsxWrapper.cpp b/libsrc/grabber/osx/OsxWrapper.cpp index 4111ea0b..53463ee3 100644 --- a/libsrc/grabber/osx/OsxWrapper.cpp +++ b/libsrc/grabber/osx/OsxWrapper.cpp @@ -62,6 +62,7 @@ void OsxWrapper::setGrabbingMode(const GrabbingMode mode) switch (mode) { case GRABBINGMODE_VIDEO: + case GRABBINGMODE_PAUSE: case GRABBINGMODE_AUDIO: case GRABBINGMODE_PHOTO: case GRABBINGMODE_MENU: diff --git a/libsrc/hyperion/hyperion.schema.json b/libsrc/hyperion/hyperion.schema.json index f839b7f1..cd716df7 100644 --- a/libsrc/hyperion/hyperion.schema.json +++ b/libsrc/hyperion/hyperion.schema.json @@ -288,6 +288,10 @@ "type" : "boolean", "required" : true }, + "grabPause" : { + "type" : "boolean", + "required" : false + }, "grabScreensaver" : { "type" : "boolean", "required" : false diff --git a/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp b/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp index 667ad4e4..b8d91c22 100644 --- a/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp +++ b/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp @@ -21,7 +21,7 @@ // {"jsonrpc":"2.0","method":"GUI.GetProperties","params":{"properties":["stereoscopicmode"]},"id":669} // {"id":669,"jsonrpc":"2.0","result":{"stereoscopicmode":{"label":"Nebeneinander","mode":"split_vertical"}}} -XBMCVideoChecker::XBMCVideoChecker(const std::string & address, uint16_t port, bool grabVideo, bool grabPhoto, bool grabAudio, bool grabMenu, bool grabScreensaver, bool enable3DDetection) : +XBMCVideoChecker::XBMCVideoChecker(const std::string & address, uint16_t port, bool grabVideo, bool grabPhoto, bool grabAudio, bool grabMenu, bool grabPause, bool grabScreensaver, bool enable3DDetection) : QObject(), _address(QString::fromStdString(address)), _port(port), @@ -35,6 +35,7 @@ XBMCVideoChecker::XBMCVideoChecker(const std::string & address, uint16_t port, b _grabPhoto(grabPhoto), _grabAudio(grabAudio), _grabMenu(grabMenu), + _grabPause(grabPause), _grabScreensaver(grabScreensaver), _enable3DDetection(enable3DDetection), _previousScreensaverMode(false), @@ -73,6 +74,11 @@ void XBMCVideoChecker::receiveReply() setGrabbingMode(_grabMenu ? GRABBINGMODE_MENU : GRABBINGMODE_OFF); setVideoMode(VIDEO_2D); } + else if (reply.contains("\"method\":\"Player.OnPause\"")) + { + // player at pause + setGrabbingMode(_grabPause ? GRABBINGMODE_PAUSE : GRABBINGMODE_OFF); + } else if (reply.contains("\"method\":\"GUI.OnScreensaverActivated\"")) { setScreensaverMode(!_grabScreensaver); @@ -272,6 +278,9 @@ void XBMCVideoChecker::setGrabbingMode(GrabbingMode newGrabbingMode) case GRABBINGMODE_MENU: std::cout << "KODICHECK INFO: switching to MENU mode" << std::endl; break; + case GRABBINGMODE_PAUSE: + std::cout << "KODICHECK INFO: switching to PAUSE mode" << std::endl; + break; case GRABBINGMODE_OFF: std::cout << "KODICHECK INFO: switching to OFF mode" << std::endl; break; diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 838827a9..110244d8 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -178,6 +178,7 @@ void startXBMCVideoChecker(const Json::Value &config, XBMCVideoChecker* &xbmcVid videoCheckerConfig["grabPictures"].asBool(), videoCheckerConfig["grabAudio"].asBool(), videoCheckerConfig["grabMenu"].asBool(), + videoCheckerConfig.get("grabPause", true).asBool(), videoCheckerConfig.get("grabScreensaver", true).asBool(), videoCheckerConfig.get("enable3DDetection", true).asBool()); From ad65ca2983dd89e5ec0ce27e2bc9641e7854a41e Mon Sep 17 00:00:00 2001 From: brindosch Date: Tue, 7 Jun 2016 13:17:40 +0200 Subject: [PATCH 46/63] atmoorb qt5 fix (#683) Former-commit-id: 64ce9cd676059d5225493a97c89b83f589f68417 --- libsrc/leddevice/LedDeviceAtmoOrb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/leddevice/LedDeviceAtmoOrb.cpp b/libsrc/leddevice/LedDeviceAtmoOrb.cpp index 28532105..5211887d 100644 --- a/libsrc/leddevice/LedDeviceAtmoOrb.cpp +++ b/libsrc/leddevice/LedDeviceAtmoOrb.cpp @@ -30,7 +30,7 @@ LedDeviceAtmoOrb::LedDeviceAtmoOrb( groupAddress = QHostAddress(multicastGroup); udpSocket = new QUdpSocket(this); - udpSocket->bind(multiCastGroupPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); + udpSocket->bind(QHostAddress::AnyIPv4, multiCastGroupPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); joinedMulticastgroup = udpSocket->joinMulticastGroup(groupAddress); } From 614131ebe6d4ffe0759bb0ad3cc6325f47dc5544 Mon Sep 17 00:00:00 2001 From: redPanther Date: Tue, 7 Jun 2016 22:24:29 +0200 Subject: [PATCH 47/63] compile fix, cleanup (#684) * implement make install set CMAKE_INSTALL_PREFIX e.g. to /opt to install to /opt/hyperion set ENABLE_SYSTEM_INSTALL to ON to activate installation after compiling use make install or make install/strip (for performance/size optimized binaries - compile in Release to get best performance) * cleanup cmake files use cmake -DINSTALL_PREFIX=/opt/hyperion .. to install all files to hyperion or cmake -DINSTALL_PREFIX=/usr/ to install to usr. install folders are linux standard. bin go to bin folder and additionals (effects) go to share/hyperion * add uninstall target - be patient with that, this will remove files from your system install service files to share/hyperion - if you want to use them you have to make a symlink to your location of service files * optimize build release script install service files into hyperion share folder (services not activated, this must be done by distribution package script) initial support of cmake option -DPLATFORM= option. This selects platform specific cmake flags. no need for -DENABLE_... options (unless you want some special things) automatic detect for apple build * update submodule * fix cmake error when no platform is given * initial support for deb,rpm and tgz packages - no usefull content atm! * make packeages contain usefull stuff * add license make packes more functional. package specific install missing yet * implement debian postinstall * disable rpm generation until it has a working state * add hypercon compat * add posibility for multiple config files. first one found is taken * remove hyperion comaptlayer services is not started automaticly * rework debian postinstall: - remove /opt compatibility complety. This makes more trouble as it is usefull - when hyperiond already started, restart it - cleanup * add deb package dependencies * wipe out last support for /opt installation * change default effect path in config to /usr * revert service files and config files * remove last occurences of ENABLE_PROTOBUF fix cmake warnings and make it ready for cmake 3 fix refactoring of hyperiond.cpp creates no objects for network services * all arguments via reference ... * fix xbmcchecker not working * add logger class * - profiler must be activated with ENABLE_PROFILER, otherwise an error will raise -> this should prevent profiler gets into release code * fix profiler * make logger compat with older/partial c++11 versions (r.g. debian wheezy) fix description of optionparser fix atmoorb not compile for qt4. now it should compile for qt5 and 4 * make logger compiles with qt5 too fix compiler warnings * remove debug code Former-commit-id: 6aa41351667caed712b1f28010dbedfca8a6a5a0 --- libsrc/grabber/x11/X11Grabber.cpp | 2 +- libsrc/leddevice/LedDeviceAtmoOrb.cpp | 2 +- libsrc/utils/CMakeLists.txt | 7 ++++++- libsrc/utils/Logger.cpp | 3 ++- src/hyperion-aml/hyperion-aml.cpp | 2 +- src/hyperion-framebuffer/hyperion-framebuffer.cpp | 2 +- src/hyperion-osx/hyperion-osx.cpp | 2 +- src/hyperion-x11/hyperion-x11.cpp | 9 +++++---- src/hyperiond/hyperiond.cpp | 10 +++++++++- 9 files changed, 27 insertions(+), 12 deletions(-) diff --git a/libsrc/grabber/x11/X11Grabber.cpp b/libsrc/grabber/x11/X11Grabber.cpp index 5b662288..fb860136 100644 --- a/libsrc/grabber/x11/X11Grabber.cpp +++ b/libsrc/grabber/x11/X11Grabber.cpp @@ -187,7 +187,7 @@ int X11Grabber::updateScreenDimensions() _croppedHeight = (_screenHeight > unsigned(_cropTop + _cropBottom)) ? (_screenHeight - _cropTop - _cropBottom) - : (_croppedHeight = _screenHeight); + : _screenHeight; std::cout << "X11GRABBER INFO: Using "; diff --git a/libsrc/leddevice/LedDeviceAtmoOrb.cpp b/libsrc/leddevice/LedDeviceAtmoOrb.cpp index 5211887d..857fcd37 100644 --- a/libsrc/leddevice/LedDeviceAtmoOrb.cpp +++ b/libsrc/leddevice/LedDeviceAtmoOrb.cpp @@ -30,7 +30,7 @@ LedDeviceAtmoOrb::LedDeviceAtmoOrb( groupAddress = QHostAddress(multicastGroup); udpSocket = new QUdpSocket(this); - udpSocket->bind(QHostAddress::AnyIPv4, multiCastGroupPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); + udpSocket->bind(QHostAddress::Any, multiCastGroupPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); joinedMulticastgroup = udpSocket->joinMulticastGroup(groupAddress); } diff --git a/libsrc/utils/CMakeLists.txt b/libsrc/utils/CMakeLists.txt index 3e02ec6b..8bfd237d 100644 --- a/libsrc/utils/CMakeLists.txt +++ b/libsrc/utils/CMakeLists.txt @@ -49,5 +49,10 @@ add_library(hyperion-utils ${CURRENT_SOURCE_DIR}/jsonschema/JsonSchemaChecker.cpp ) +if(ENABLE_QT5) + qt5_use_modules(hyperion-utils Widgets) +endif() + target_link_libraries(hyperion-utils - jsoncpp) + jsoncpp + ${QT_LIBRARIES}) diff --git a/libsrc/utils/Logger.cpp b/libsrc/utils/Logger.cpp index 1b865d43..b451583b 100644 --- a/libsrc/utils/Logger.cpp +++ b/libsrc/utils/Logger.cpp @@ -30,7 +30,8 @@ Logger* Logger::getInstance(std::string name, Logger::LogLevel minLevel) if ( LoggerMap->find(name) == LoggerMap->end() ) { Logger* log = new Logger(name,minLevel); - Logger::LoggerMap->emplace(name,log); + Logger::LoggerMap->insert(std::pair(name,log)); // compat version, replace it with following line if we have 100% c++11 + //Logger::LoggerMap->emplace(name,log); // not compat with older linux distro's e.g. wheezy return log; } diff --git a/src/hyperion-aml/hyperion-aml.cpp b/src/hyperion-aml/hyperion-aml.cpp index 4932c0dc..efd95fec 100644 --- a/src/hyperion-aml/hyperion-aml.cpp +++ b/src/hyperion-aml/hyperion-aml.cpp @@ -35,7 +35,7 @@ int main(int argc, char ** argv) try { // create the option parser and initialize all parameters - OptionsParser optionParser("X11 capture application for Hyperion"); + OptionsParser optionParser("AmLogic capture application for Hyperion"); ParameterSet & parameters = optionParser.getParameters(); IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default: 10]"); diff --git a/src/hyperion-framebuffer/hyperion-framebuffer.cpp b/src/hyperion-framebuffer/hyperion-framebuffer.cpp index b4c7f830..d33603a0 100644 --- a/src/hyperion-framebuffer/hyperion-framebuffer.cpp +++ b/src/hyperion-framebuffer/hyperion-framebuffer.cpp @@ -27,7 +27,7 @@ int main(int argc, char ** argv) try { // create the option parser and initialize all parameters - OptionsParser optionParser("X11 capture application for Hyperion"); + OptionsParser optionParser("FrameBuffer capture application for Hyperion"); ParameterSet & parameters = optionParser.getParameters(); StringParameter & argDevice = parameters.add ('d', "device", "Set the video device [default: /dev/video0]"); diff --git a/src/hyperion-osx/hyperion-osx.cpp b/src/hyperion-osx/hyperion-osx.cpp index dbb51575..f1d11b74 100644 --- a/src/hyperion-osx/hyperion-osx.cpp +++ b/src/hyperion-osx/hyperion-osx.cpp @@ -27,7 +27,7 @@ int main(int argc, char ** argv) try { // create the option parser and initialize all parameters - OptionsParser optionParser("X11 capture application for Hyperion"); + OptionsParser optionParser("OSX capture application for Hyperion"); ParameterSet & parameters = optionParser.getParameters(); IntParameter & argDisplay = parameters.add ('d', "display", "Set the display to capture [default: 0]"); diff --git a/src/hyperion-x11/hyperion-x11.cpp b/src/hyperion-x11/hyperion-x11.cpp index 1c9f4d65..c308828e 100644 --- a/src/hyperion-x11/hyperion-x11.cpp +++ b/src/hyperion-x11/hyperion-x11.cpp @@ -9,6 +9,7 @@ #include "protoserver/ProtoConnectionWrapper.h" #include "X11Wrapper.h" #include "HyperionConfig.h" +#include "utils/Profiler.h" using namespace vlofgren; @@ -22,10 +23,10 @@ void saveScreenshot(const char * filename, const Image & image) int main(int argc, char ** argv) { - std::cout - << "hyperion-x11:" << std::endl - << "\tversion : " << HYPERION_VERSION_ID << std::endl - << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; + std::cout + << "hyperion-x11:" << std::endl + << "\tversion : " << HYPERION_VERSION_ID << std::endl + << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; QCoreApplication app(argc, argv); diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 110244d8..a8e7a466 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -418,15 +418,23 @@ int main(int argc, char** argv) setlocale(LC_ALL, "C"); QLocale::setDefault(QLocale::c()); - OptionsParser optionParser("X11 capture application for Hyperion"); + OptionsParser optionParser("Hyperion Daemon"); ParameterSet & parameters = optionParser.getParameters(); IntParameter & argParentPid = parameters.add (0x0, "parent", "pid of parent hyperiond"); + SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); argParentPid.setDefault(0); optionParser.parse(argc, const_cast(argv)); const std::vector configFiles = optionParser.getFiles(); + // check if we need to display the usage. exit if we do. + if (argHelp.isSet()) + { + optionParser.usage(); + return 0; + } + if (configFiles.size() == 0) { std::cout << "ERROR: Missing required configuration file. Usage:" << std::endl; From f0dec4cf736aaded2e159454d83f1a550e751210 Mon Sep 17 00:00:00 2001 From: Paulchen-Panther Date: Tue, 7 Jun 2016 23:12:18 +0200 Subject: [PATCH 48/63] Hyperion X11 KodiCheck (#685) * Update X11Grabber.h * Update ProtoConnection.h * Update ProtoConnectionWrapper.h * Update ProtoServer.h * Update X11Grabber.cpp * Update message.proto * Update ProtoClientConnection.cpp * Update ProtoClientConnection.h * Update ProtoConnection.cpp * Update ProtoConnectionWrapper.cpp * Update ProtoServer.cpp * Update hyperion-x11.cpp * Update X11Wrapper.cpp * Update X11Wrapper.h * Update hyperiond.cpp * Update ProtoClientConnection.cpp * Update X11Wrapper.cpp * Update hyperiond.cpp Former-commit-id: a572f275b270217cd8ce8cdd91b3eca3037d6472 --- include/grabber/X11Grabber.h | 6 +- include/protoserver/ProtoConnection.h | 17 +++ include/protoserver/ProtoConnectionWrapper.h | 11 +- include/protoserver/ProtoServer.h | 9 ++ libsrc/grabber/x11/X11Grabber.cpp | 5 + libsrc/protoserver/ProtoClientConnection.cpp | 28 +++++ libsrc/protoserver/ProtoClientConnection.h | 13 +- libsrc/protoserver/ProtoConnection.cpp | 118 +++++++++++------- libsrc/protoserver/ProtoConnectionWrapper.cpp | 2 + libsrc/protoserver/ProtoServer.cpp | 4 + libsrc/protoserver/message.proto | 19 ++- src/hyperion-x11/X11Wrapper.cpp | 23 ++++ src/hyperion-x11/X11Wrapper.h | 17 +++ src/hyperion-x11/hyperion-x11.cpp | 4 + src/hyperiond/hyperiond.cpp | 9 +- 15 files changed, 235 insertions(+), 50 deletions(-) diff --git a/include/grabber/X11Grabber.h b/include/grabber/X11Grabber.h index 5c2dd3b2..7715299f 100644 --- a/include/grabber/X11Grabber.h +++ b/include/grabber/X11Grabber.h @@ -19,7 +19,11 @@ public: virtual ~X11Grabber(); - int open(); + /// + /// Set the video mode (2D/3D) + /// @param[in] mode The new video mode + /// + void setVideoMode(const VideoMode videoMode); bool Setup(); diff --git a/include/protoserver/ProtoConnection.h b/include/protoserver/ProtoConnection.h index a6480eb6..54586ecc 100644 --- a/include/protoserver/ProtoConnection.h +++ b/include/protoserver/ProtoConnection.h @@ -13,6 +13,8 @@ // hyperion util #include #include +#include +#include // jsoncpp includes #include @@ -82,6 +84,18 @@ private slots: /// Try to connect to the Hyperion host void connectToHost(); + /// + /// Slot called when new data has arrived + /// + void readData(); + +signals: + + /// + /// XBMC Video Checker Message + /// + void setGrabbingMode(const GrabbingMode mode); + void setVideoMode(const VideoMode videoMode); private: @@ -109,4 +123,7 @@ private: QTimer _timer; QAbstractSocket::SocketState _prevSocketState; + + /// The buffer used for reading data from the socket + QByteArray _receiveBuffer; }; diff --git a/include/protoserver/ProtoConnectionWrapper.h b/include/protoserver/ProtoConnectionWrapper.h index 7d2f3f6c..62ce0f35 100644 --- a/include/protoserver/ProtoConnectionWrapper.h +++ b/include/protoserver/ProtoConnectionWrapper.h @@ -4,11 +4,13 @@ // hyperion includes #include #include +#include +#include // hyperion proto includes #include "protoserver/ProtoConnection.h" -/// This class handles callbacks from the V4L2 grabber +/// This class handles callbacks from the V4L2 and X11 grabber class ProtoConnectionWrapper : public QObject { Q_OBJECT @@ -16,6 +18,13 @@ class ProtoConnectionWrapper : public QObject public: ProtoConnectionWrapper(const std::string & address, int priority, int duration_ms, bool skipProtoReply); virtual ~ProtoConnectionWrapper(); + +signals: + /// + /// Forwarding XBMC Video Checker Message + /// + void setGrabbingMode(const GrabbingMode mode); + void setVideoMode(const VideoMode videoMode); public slots: /// Handle a single image diff --git a/include/protoserver/ProtoServer.h b/include/protoserver/ProtoServer.h index 520848a9..f62425a3 100644 --- a/include/protoserver/ProtoServer.h +++ b/include/protoserver/ProtoServer.h @@ -15,6 +15,8 @@ // hyperion includes #include #include +#include +#include // forward decl class ProtoClientConnection; @@ -50,6 +52,13 @@ public: public slots: void sendImageToProtoSlaves(int priority, const Image & image, int duration_ms); +signals: + /// + /// Forwarding XBMC Checker + /// + void grabbingMode(const GrabbingMode mode); + void videoMode(const VideoMode VideoMode); + private slots: /// /// Slot which is called when a client tries to create a new connection diff --git a/libsrc/grabber/x11/X11Grabber.cpp b/libsrc/grabber/x11/X11Grabber.cpp index fb860136..9aa56232 100644 --- a/libsrc/grabber/x11/X11Grabber.cpp +++ b/libsrc/grabber/x11/X11Grabber.cpp @@ -40,6 +40,11 @@ X11Grabber::~X11Grabber() } } +void X11Grabber::setVideoMode(const VideoMode videoMode) +{ + _imageResampler.set3D(videoMode); +} + void X11Grabber::freeResources() { // Cleanup allocated resources of the X11 grab diff --git a/libsrc/protoserver/ProtoClientConnection.cpp b/libsrc/protoserver/ProtoClientConnection.cpp index d1f087cd..9082635e 100644 --- a/libsrc/protoserver/ProtoClientConnection.cpp +++ b/libsrc/protoserver/ProtoClientConnection.cpp @@ -79,6 +79,32 @@ void ProtoClientConnection::socketClosed() emit connectionClosed(this); } +void ProtoClientConnection::setGrabbingMode(const GrabbingMode mode) +{ + int grabbing_mode = (int)mode; + proto::HyperionReply gMode; + + // create proto message + gMode.set_type(proto::HyperionReply::GRABBING); + gMode.set_grabbing(grabbing_mode); + + // send message + sendMessage(gMode); +} + +void ProtoClientConnection::setVideoMode(const VideoMode videoMode) +{ + int video_Mode = (int)videoMode; + proto::HyperionReply vMode; + + // create proto message + vMode.set_type(proto::HyperionReply::VIDEO); + vMode.set_grabbing(video_Mode); + + // send message + sendMessage(vMode); +} + void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message) { // forward messages @@ -208,6 +234,7 @@ void ProtoClientConnection::sendSuccessReply() { // create reply proto::HyperionReply reply; + reply.set_type(proto::HyperionReply::REPLY); reply.set_success(true); // send reply @@ -218,6 +245,7 @@ void ProtoClientConnection::sendErrorReply(const std::string &error) { // create reply proto::HyperionReply reply; + reply.set_type(proto::HyperionReply::REPLY); reply.set_success(false); reply.set_error(error); diff --git a/libsrc/protoserver/ProtoClientConnection.h b/libsrc/protoserver/ProtoClientConnection.h index c68f56e0..ca22e778 100644 --- a/libsrc/protoserver/ProtoClientConnection.h +++ b/libsrc/protoserver/ProtoClientConnection.h @@ -11,6 +11,10 @@ // Hyperion includes #include +//Utils includes +#include +#include + // proto includes #include "message.pb.h" #include "protoserver/ProtoConnection.h" @@ -18,7 +22,7 @@ class ImageProcessor; /// -/// The Connection object created by \a ProtoServer when a new connection is establshed +/// The Connection object created by a ProtoServer when a new connection is establshed /// class ProtoClientConnection : public QObject { @@ -36,6 +40,13 @@ public: /// Destructor /// ~ProtoClientConnection(); + +public slots: + /// + /// Send XBMC Video Checker message to connected client + /// + void setGrabbingMode(const GrabbingMode mode); + void setVideoMode(const VideoMode videoMode); signals: /// diff --git a/libsrc/protoserver/ProtoConnection.cpp b/libsrc/protoserver/ProtoConnection.cpp index d4850d48..3492a7ec 100644 --- a/libsrc/protoserver/ProtoConnection.cpp +++ b/libsrc/protoserver/ProtoConnection.cpp @@ -35,7 +35,8 @@ ProtoConnection::ProtoConnection(const std::string & a) : _timer.setInterval(5000); _timer.setSingleShot(false); - connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()) ); + connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost())); + connect(&_socket, SIGNAL(readyRead()), this, SLOT(readData())); _timer.start(); } @@ -45,6 +46,44 @@ ProtoConnection::~ProtoConnection() _socket.close(); } +void ProtoConnection::readData() +{ + _receiveBuffer += _socket.readAll(); + + // check if we can read a message size + if (_receiveBuffer.size() <= 4) + { + return; + } + + // read the message size + uint32_t messageSize = + ((_receiveBuffer[0]<<24) & 0xFF000000) | + ((_receiveBuffer[1]<<16) & 0x00FF0000) | + ((_receiveBuffer[2]<< 8) & 0x0000FF00) | + ((_receiveBuffer[3] ) & 0x000000FF); + + // check if we can read a complete message + if ((uint32_t) _receiveBuffer.size() < messageSize + 4) + { + return; + } + + // read a message + proto::HyperionReply reply; + + if (!reply.ParseFromArray(_receiveBuffer.data() + 4, messageSize)) + { + std::cerr << "PROTOCONNECTION ERROR: Unable to parse message" << std::endl; + return; + } + + parseReply(reply); + + // remove message data from buffer + _receiveBuffer = _receiveBuffer.mid(messageSize + 4); +} + void ProtoConnection::setSkipReply(bool skip) { _skipReply = skip; @@ -157,58 +196,51 @@ void ProtoConnection::sendMessage(const proto::HyperionRequest &message) std::cerr << "PROTOCONNECTION ERROR: Error while writing data to host" << std::endl; return; } - - if (!_skipReply) - { - // read reply data - QByteArray serializedReply; - length = -1; - while (length < 0 && serializedReply.size() < length+4) - { - // receive reply - if (!_socket.waitForReadyRead()) - { - std::cerr << "PROTOCONNECTION ERROR: Error while reading data from host" << std::endl; - return; - } - - serializedReply += _socket.readAll(); - - if (length < 0 && serializedReply.size() >= 4) - { - // read the message size - length = - ((serializedReply[0]<<24) & 0xFF000000) | - ((serializedReply[1]<<16) & 0x00FF0000) | - ((serializedReply[2]<< 8) & 0x0000FF00) | - ((serializedReply[3] ) & 0x000000FF); - } - } - - // parse reply data - proto::HyperionReply reply; - reply.ParseFromArray(serializedReply.constData()+4, length); - - // parse reply message - parseReply(reply); - } } bool ProtoConnection::parseReply(const proto::HyperionReply &reply) { bool success = false; - - if (!reply.success()) + + switch (reply.type()) { - if (reply.has_error()) + case proto::HyperionReply::REPLY: { - throw std::runtime_error("PROTOCONNECTION ERROR: " + reply.error()); + if (!_skipReply) + { + if (!reply.success()) + { + if (reply.has_error()) + { + throw std::runtime_error("PROTOCONNECTION ERROR: " + reply.error()); + } + else + { + throw std::runtime_error("PROTOCONNECTION ERROR: No error info"); + } + } + else + { + success = true; + } + } + break; } - else + case proto::HyperionReply::GRABBING: { - throw std::runtime_error("PROTOCONNECTION ERROR: No error info"); + int grabbing = reply.has_grabbing() ? reply.grabbing() : 6; + GrabbingMode gMode = (GrabbingMode)grabbing; + emit setGrabbingMode(gMode); + break; + } + case proto::HyperionReply::VIDEO: + { + int video = reply.has_video() ? reply.video() : 0; + VideoMode vMode = (VideoMode)video; + emit setVideoMode(vMode); + break; } } - + return success; } diff --git a/libsrc/protoserver/ProtoConnectionWrapper.cpp b/libsrc/protoserver/ProtoConnectionWrapper.cpp index e1c5b8d4..3c2ad0cd 100644 --- a/libsrc/protoserver/ProtoConnectionWrapper.cpp +++ b/libsrc/protoserver/ProtoConnectionWrapper.cpp @@ -7,6 +7,8 @@ ProtoConnectionWrapper::ProtoConnectionWrapper(const std::string & address, int _connection(address) { _connection.setSkipReply(skipProtoReply); + connect(&_connection, SIGNAL(setGrabbingMode(GrabbingMode)), this, SIGNAL(setGrabbingMode(GrabbingMode))); + connect(&_connection, SIGNAL(setVideoMode(VideoMode)), this, SIGNAL(setVideoMode(VideoMode))); } ProtoConnectionWrapper::~ProtoConnectionWrapper() diff --git a/libsrc/protoserver/ProtoServer.cpp b/libsrc/protoserver/ProtoServer.cpp index 1abafb0c..eef471bf 100644 --- a/libsrc/protoserver/ProtoServer.cpp +++ b/libsrc/protoserver/ProtoServer.cpp @@ -64,6 +64,10 @@ void ProtoServer::newConnection() // register slot for cleaning up after the connection closed connect(connection, SIGNAL(connectionClosed(ProtoClientConnection*)), this, SLOT(closedConnection(ProtoClientConnection*))); connect(connection, SIGNAL(newMessage(const proto::HyperionRequest*)), this, SLOT(newMessage(const proto::HyperionRequest*))); + + // register forward signal for xbmc checker + connect(this, SIGNAL(grabbingMode(GrabbingMode)), connection, SLOT(setGrabbingMode(GrabbingMode))); + connect(this, SIGNAL(videoMode(VideoMode)), connection, SLOT(setVideoMode(VideoMode))); } } diff --git a/libsrc/protoserver/message.proto b/libsrc/protoserver/message.proto index 33c995b3..aff897bd 100644 --- a/libsrc/protoserver/message.proto +++ b/libsrc/protoserver/message.proto @@ -61,9 +61,24 @@ message ClearRequest { } message HyperionReply { + enum Type { + REPLY = 1; + GRABBING = 2; + VIDEO = 3; + } + + // Identifies which field is filled in. + required Type type = 1; + // flag indication success or failure - required bool success = 1; + optional bool success = 2; // string indicating the reason for failure (if applicable) - optional string error = 2; + optional string error = 3; + + // XBMC Video Checker Proto Messages for Grabbing mode + optional int32 grabbing = 4; + + // XBMC Video Checker Proto Messages for Video mode + optional int32 video = 5; } diff --git a/src/hyperion-x11/X11Wrapper.cpp b/src/hyperion-x11/X11Wrapper.cpp index e417a07b..66c74693 100644 --- a/src/hyperion-x11/X11Wrapper.cpp +++ b/src/hyperion-x11/X11Wrapper.cpp @@ -39,3 +39,26 @@ void X11Wrapper::capture() const Image & screenshot = _grabber.grab(); emit sig_screenshot(screenshot); } + +void X11Wrapper::setGrabbingMode(const GrabbingMode mode) +{ + switch (mode) + { + case GRABBINGMODE_VIDEO: + case GRABBINGMODE_PAUSE: + case GRABBINGMODE_AUDIO: + case GRABBINGMODE_PHOTO: + case GRABBINGMODE_MENU: + case GRABBINGMODE_INVALID: + start(); + break; + case GRABBINGMODE_OFF: + stop(); + break; + } +} + +void X11Wrapper::setVideoMode(const VideoMode mode) +{ + _grabber.setVideoMode(mode); +} diff --git a/src/hyperion-x11/X11Wrapper.h b/src/hyperion-x11/X11Wrapper.h index b672c3a0..c16487eb 100644 --- a/src/hyperion-x11/X11Wrapper.h +++ b/src/hyperion-x11/X11Wrapper.h @@ -5,6 +5,10 @@ // Hyperion-X11 includes #include +//Utils includes +#include +#include + class X11Wrapper : public QObject { Q_OBJECT @@ -25,6 +29,19 @@ public: signals: void sig_screenshot(const Image & screenshot); +public slots: + /// + /// Set the grabbing mode + /// @param[in] mode The new grabbing mode + /// + void setGrabbingMode(const GrabbingMode mode); + + /// + /// Set the video mode (2D/3D) + /// @param[in] mode The new video mode + /// + void setVideoMode(const VideoMode videoMode); + private slots: /// /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot diff --git a/src/hyperion-x11/hyperion-x11.cpp b/src/hyperion-x11/hyperion-x11.cpp index c308828e..855a3ab1 100644 --- a/src/hyperion-x11/hyperion-x11.cpp +++ b/src/hyperion-x11/hyperion-x11.cpp @@ -104,6 +104,10 @@ int main(int argc, char ** argv) // Connect the screen capturing to the proto processing QObject::connect(&x11Wrapper, SIGNAL(sig_screenshot(const Image &)), &protoWrapper, SLOT(receiveImage(Image))); + + // Connect the XBMC Video Checker to the proto processing + QObject::connect(&protoWrapper, SIGNAL(setGrabbingMode(GrabbingMode)), &x11Wrapper, SLOT(setGrabbingMode(GrabbingMode))); + QObject::connect(&protoWrapper, SIGNAL(setVideoMode(VideoMode)), &x11Wrapper, SLOT(setVideoMode(VideoMode))); // Start the capturing x11Wrapper.start(); diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index a8e7a466..b2b0c1b8 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -187,7 +187,7 @@ void startXBMCVideoChecker(const Json::Value &config, XBMCVideoChecker* &xbmcVid } } -void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonServer* &jsonServer, ProtoServer* &protoServer, BoblightServer* &boblightServer) +void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonServer* &jsonServer, ProtoServer* &protoServer, BoblightServer* &boblightServer, XBMCVideoChecker* &xbmcVideoChecker) { // Create Json server if configuration is present if (config.isMember("jsonServer")) @@ -216,6 +216,11 @@ void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonSer { const Json::Value & protoServerConfig = config["protoServer"]; protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); + if (xbmcVideoChecker != nullptr) + { + QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), protoServer, SIGNAL(grabbingMode(GrabbingMode))); + QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), protoServer, SIGNAL(videoMode(VideoMode))); + } std::cout << "INFO: Proto server created and started on port " << protoServer->getPort() << std::endl; #ifdef ENABLE_ZEROCONF @@ -481,7 +486,7 @@ int main(int argc, char** argv) JsonServer * jsonServer = nullptr; ProtoServer * protoServer = nullptr; BoblightServer * boblightServer = nullptr; - startNetworkServices(config, hyperion, jsonServer, protoServer, boblightServer); + startNetworkServices(config, hyperion, jsonServer, protoServer, boblightServer, xbmcVideoChecker); // ---- grabber ----- From 986409fbdaa945a4f4e2ecc846e42c3b18563412 Mon Sep 17 00:00:00 2001 From: redPanther Date: Wed, 8 Jun 2016 11:53:01 +0200 Subject: [PATCH 49/63] make proto and json server permanent. An unconfigured p/j server means server with default values (#687) Former-commit-id: ef0ac6711dbd44b6867527be60ed62c345ef6df7 --- src/hyperiond/hyperiond.cpp | 74 ++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index b2b0c1b8..e1c7d842 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -190,53 +190,59 @@ void startXBMCVideoChecker(const Json::Value &config, XBMCVideoChecker* &xbmcVid void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonServer* &jsonServer, ProtoServer* &protoServer, BoblightServer* &boblightServer, XBMCVideoChecker* &xbmcVideoChecker) { // Create Json server if configuration is present + unsigned int jsonPort = 19444; if (config.isMember("jsonServer")) { const Json::Value & jsonServerConfig = config["jsonServer"]; - jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt()); - std::cout << "INFO: Json server created and started on port " << jsonServer->getPort() << std::endl; - -#ifdef ENABLE_ZEROCONF - const Json::Value & deviceConfig = config["device"]; - const std::string deviceName = deviceConfig.get("name", "").asString(); - - const std::string hostname = QHostInfo::localHostName().toStdString(); - const std::string mDNSDescr = jsonServerConfig.get("mDNSDescr", hostname).asString(); - const std::string mDNSService = jsonServerConfig.get("mDNSService", "_hyperiond_json._tcp").asString(); - BonjourServiceRegister *bonjourRegister_json; - bonjourRegister_json = new BonjourServiceRegister(); - bonjourRegister_json->registerService(BonjourRecord((deviceName + " @ " + mDNSDescr).c_str(), mDNSService.c_str(), - QString()), jsonServerConfig["port"].asUInt()); - std::cout << "INFO: Json mDNS responder started" << std::endl; -#endif + //jsonEnable = jsonServerConfig.get("enable", true).asBool(); + jsonPort = jsonServerConfig.get("port", 19444).asUInt(); } + jsonServer = new JsonServer(&hyperion, jsonPort ); + std::cout << "INFO: Json server created and started on port " << jsonServer->getPort() << std::endl; + // Create Proto server if configuration is present + unsigned int protoPort = 19445; if (config.isMember("protoServer")) { const Json::Value & protoServerConfig = config["protoServer"]; - protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); - if (xbmcVideoChecker != nullptr) - { - QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), protoServer, SIGNAL(grabbingMode(GrabbingMode))); - QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), protoServer, SIGNAL(videoMode(VideoMode))); - } - std::cout << "INFO: Proto server created and started on port " << protoServer->getPort() << std::endl; + //protoEnable = protoServerConfig.get("enable", true).asBool(); + protonPort = protoServerConfig.get("port", 19445).asUInt(); + } + + protoServer = new ProtoServer(&hyperion, protoPort ); + if (xbmcVideoChecker != nullptr) + { + QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), protoServer, SIGNAL(grabbingMode(GrabbingMode))); + QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), protoServer, SIGNAL(videoMode(VideoMode))); + } + std::cout << "INFO: Proto server created and started on port " << protoServer->getPort() << std::endl; #ifdef ENABLE_ZEROCONF - const Json::Value & deviceConfig = config["device"]; - const std::string deviceName = deviceConfig.get("name", "").asString(); + const Json::Value & deviceConfig = config["device"]; + const std::string deviceName = deviceConfig.get("name", "").asString(); - const std::string hostname = QHostInfo::localHostName().toStdString(); - const std::string mDNSDescr = protoServerConfig.get("mDNSDescr", hostname).asString(); - const std::string mDNSService = protoServerConfig.get("mDNSService", "_hyperiond_proto._tcp").asString(); - BonjourServiceRegister *bonjourRegister_proto; - bonjourRegister_proto = new BonjourServiceRegister(); - bonjourRegister_proto->registerService(BonjourRecord((deviceName + " @ " + mDNSDescr).c_str(), mDNSService.c_str(), - QString()), protoServerConfig["port"].asUInt()); - std::cout << "INFO: Proto mDNS responder started" << std::endl; + const std::string hostname = QHostInfo::localHostName().toStdString(); + const std::string mDNSDescr = jsonServerConfig.get("mDNSDescr", hostname).asString(); + const std::string mDNSService = jsonServerConfig.get("mDNSService", "_hyperiond_json._tcp").asString(); + BonjourServiceRegister *bonjourRegister_json; + bonjourRegister_json = new BonjourServiceRegister(); + bonjourRegister_json->registerService(BonjourRecord((deviceName + " @ " + mDNSDescr).c_str(), mDNSService.c_str(), + QString()), jsonServerConfig["port"].asUInt()); + std::cout << "INFO: Json mDNS responder started" << std::endl; + + const Json::Value & deviceConfig = config["device"]; + const std::string deviceName = deviceConfig.get("name", "").asString(); + + const std::string hostname = QHostInfo::localHostName().toStdString(); + const std::string mDNSDescr = protoServerConfig.get("mDNSDescr", hostname).asString(); + const std::string mDNSService = protoServerConfig.get("mDNSService", "_hyperiond_proto._tcp").asString(); + BonjourServiceRegister *bonjourRegister_proto; + bonjourRegister_proto = new BonjourServiceRegister(); + bonjourRegister_proto->registerService(BonjourRecord((deviceName + " @ " + mDNSDescr).c_str(), mDNSService.c_str(), + QString()), protoServerConfig["port"].asUInt()); + std::cout << "INFO: Proto mDNS responder started" << std::endl; #endif - } // Create Boblight server if configuration is present if (config.isMember("boblightServer")) From 5b47855bc3cd46764791143c2cce364983a10c25 Mon Sep 17 00:00:00 2001 From: redPanther Date: Fri, 10 Jun 2016 09:00:53 +0200 Subject: [PATCH 50/63] Refactoring - typo fix (#689) * make proto and json server permanent. An unconfigured p/j server means server with default values * fix typo Former-commit-id: 81ee35ccf348f1fe4dc554f2df03878d9c870f6f --- src/hyperiond/hyperiond.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index e1c7d842..6a41edc0 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -207,7 +207,7 @@ void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonSer { const Json::Value & protoServerConfig = config["protoServer"]; //protoEnable = protoServerConfig.get("enable", true).asBool(); - protonPort = protoServerConfig.get("port", 19445).asUInt(); + protoPort = protoServerConfig.get("port", 19445).asUInt(); } protoServer = new ProtoServer(&hyperion, protoPort ); From c5cdd3961587971cdc54daf1e9e33a8bf069cfb8 Mon Sep 17 00:00:00 2001 From: brindosch Date: Fri, 10 Jun 2016 13:15:49 +0200 Subject: [PATCH 51/63] disable zeroconf Former-commit-id: b3e29c20a4b0a5407eb385b6f0579bc142a183a2 --- bin/create_all_releases.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/create_all_releases.sh b/bin/create_all_releases.sh index a6ef53c2..614325ae 100644 --- a/bin/create_all_releases.sh +++ b/bin/create_all_releases.sh @@ -13,7 +13,7 @@ make_release() mkdir -p build-${RELEASE} mkdir -p deploy/${RELEASE} cd build-${RELEASE} - cmake -DCMAKE_INSTALL_PREFIX=/usr -DPLATFORM=${PLATFORM} $@ -DENABLE_ZEROCONF=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. || exit 1 + cmake -DCMAKE_INSTALL_PREFIX=/usr -DPLATFORM=${PLATFORM} $@ -DCMAKE_BUILD_TYPE=Release -Wno-dev .. || exit 1 make -j $(nproc) || exit 1 #strip bin/* make package -j $(nproc) From 611067a5cff0b21128e950e14e41e677e6d29d9a Mon Sep 17 00:00:00 2001 From: brindosch Date: Fri, 10 Jun 2016 16:52:49 +0200 Subject: [PATCH 52/63] rm profiler at x11 Former-commit-id: 8b8229b82c1d942c2259c4a4ce2e1d4e5ca88092 --- src/hyperion-x11/hyperion-x11.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hyperion-x11/hyperion-x11.cpp b/src/hyperion-x11/hyperion-x11.cpp index 855a3ab1..8c399aff 100644 --- a/src/hyperion-x11/hyperion-x11.cpp +++ b/src/hyperion-x11/hyperion-x11.cpp @@ -9,7 +9,6 @@ #include "protoserver/ProtoConnectionWrapper.h" #include "X11Wrapper.h" #include "HyperionConfig.h" -#include "utils/Profiler.h" using namespace vlofgren; From afb7efaa949332cb78b730f61aa039dc89976b94 Mon Sep 17 00:00:00 2001 From: brindosch Date: Fri, 10 Jun 2016 18:28:26 +0200 Subject: [PATCH 53/63] update service Former-commit-id: cf849922ce2b4ce89b97475e5ff246d6d929998a --- bin/service/hyperion.init.sh | 2 +- bin/service/hyperion.initctl.sh | 2 +- bin/service/hyperion.systemd.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/service/hyperion.init.sh b/bin/service/hyperion.init.sh index f296a458..5911557d 100644 --- a/bin/service/hyperion.init.sh +++ b/bin/service/hyperion.init.sh @@ -13,7 +13,7 @@ ### END INIT INFO DAEMON=hyperiond -DAEMONOPTS="/opt/hyperion/hyperion.config.json /etc/hyperion/hyperion.config.json" +DAEMONOPTS="/etc/hyperion/hyperion.config.json" DAEMON_PATH="/usr/bin" NAME=$DAEMON diff --git a/bin/service/hyperion.initctl.sh b/bin/service/hyperion.initctl.sh index 774e20b9..86ef5923 100644 --- a/bin/service/hyperion.initctl.sh +++ b/bin/service/hyperion.initctl.sh @@ -8,4 +8,4 @@ stop on (runlevel [!2345]) respawn -exec /usr/bin/hyperiond /opt/hyperion/hyperion.config.json /etc/hyperion/hyperion.config.json +exec /usr/bin/hyperiond /etc/hyperion/hyperion.config.json diff --git a/bin/service/hyperion.systemd.sh b/bin/service/hyperion.systemd.sh index 8fe2bc40..1ec4124c 100644 --- a/bin/service/hyperion.systemd.sh +++ b/bin/service/hyperion.systemd.sh @@ -6,7 +6,7 @@ Type=simple User=root Group=root UMask=007 -ExecStart=/usr/bin/hyperiond /opt/hyperion/hyperion.config.json /etc/hyperion/hyperion.config.json +ExecStart=/usr/bin/hyperiond /etc/hyperion/hyperion.config.json ExecReload=/bin/kill -HUP $MAINPID Restart=on-failure TimeoutStopSec=10 From f04d48063d171f57d3a914288e536e7376b465b3 Mon Sep 17 00:00:00 2001 From: brindosch Date: Fri, 10 Jun 2016 18:32:39 +0200 Subject: [PATCH 54/63] [DO NOT MERGE] Preperation for V1.03.0 (#672) Preperation for V1.03.0 Former-commit-id: d3ef9dbe74df304dd0653818415f10401ac72af4 --- CMakeLists.txt | 4 - bin/create_release.sh | 8 +- bin/install_hyperion.sh | 114 +++-- bin/remove_hyperion.sh | 18 +- ...nfig.json => hyperion.config.json.example} | 94 ++-- config/hyperion_x86.config.json | 430 ------------------ 6 files changed, 124 insertions(+), 544 deletions(-) rename config/{hyperion.config.json => hyperion.config.json.example} (91%) delete mode 100644 config/hyperion_x86.config.json diff --git a/CMakeLists.txt b/CMakeLists.txt index b94e3068..388aab0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,10 +172,6 @@ if(ENABLE_OSX) set(CMAKE_EXE_LINKER_FLAGS "-framework CoreGraphics") endif() -configure_file(bin/install_hyperion.sh ${LIBRARY_OUTPUT_PATH} @ONLY) -configure_file(config/hyperion.config.json ${LIBRARY_OUTPUT_PATH} @ONLY) -configure_file(config/hyperion_x86.config.json ${LIBRARY_OUTPUT_PATH} @ONLY) - # Add the source/lib directories add_subdirectory(dependencies) add_subdirectory(libsrc) diff --git a/bin/create_release.sh b/bin/create_release.sh index 94f90e81..d06024c0 100644 --- a/bin/create_release.sh +++ b/bin/create_release.sh @@ -23,14 +23,14 @@ tar --create --gzip --absolute-names --show-transformed-names --ignore-failed-re --transform "s:$builddir/bin/:hyperion/bin/:" \ --transform "s:$repodir/effects/:hyperion/effects/:" \ --transform "s:$repodir/config/:hyperion/config/:" \ - --transform "s:$repodir/bin/service/hyperion.init.sh:hyperion/init.d/hyperion.init.sh:" \ - --transform "s:$repodir/bin/service/hyperion.systemd.sh:hyperion/init.d/hyperion.systemd.sh:" \ - --transform "s:$repodir/bin/service/hyperion.initctl.sh:hyperion/init.d/hyperion.initctl.sh:" \ + --transform "s:$repodir/bin/service/hyperion.init.sh:hyperion/services/hyperion.init.sh:" \ + --transform "s:$repodir/bin/service/hyperion.systemd.sh:hyperion/services/hyperion.systemd.sh:" \ + --transform "s:$repodir/bin/service/hyperion.initctl.sh:hyperion/services/hyperion.initctl.sh:" \ --transform "s://:/:g" \ "$builddir/bin/hyperion"* \ "$repodir/effects/"* \ "$repodir/bin/service/hyperion.init.sh" \ "$repodir/bin/service/hyperion.systemd.sh" \ "$repodir/bin/service/hyperion.initctl.sh" \ - "$repodir/config/hyperion.config.json" + "$repodir/config/hyperion.config.json.example" diff --git a/bin/install_hyperion.sh b/bin/install_hyperion.sh index 7777f303..05d0515a 100755 --- a/bin/install_hyperion.sh +++ b/bin/install_hyperion.sh @@ -23,7 +23,7 @@ fi #Set welcome message if [ $BETA -eq 1 ]; then WMESSAGE="echo This script will update Hyperion to the latest BETA" -else WMESSAGE="echo This script will install/update Hyperion Ambilight" +else WMESSAGE="echo This script will install/update Hyperion Ambient Light" fi #Welcome message @@ -74,24 +74,34 @@ if [ $BOBLIGHT_PROCNR -eq 1 ]; then exit 1 fi -# Stop hyperion daemon if it is running +#set service script path +SERVICEL="/usr/share/hyperion/services" + +# Stop hyperion daemon if it is running and set service path echo '---> Stop Hyperion, if necessary' if [ $OS_OPENELEC -eq 1 ]; then killall hyperiond 2>/dev/null elif [ $USE_INITCTL -eq 1 ]; then /sbin/initctl stop hyperion 2>/dev/null -elif [ $USE_SERVICE -eq 1 ]; then - /usr/sbin/service hyperion stop 2>/dev/null + SERVICEP="/etc/init" elif [ $USE_SYSTEMD -eq 1 ]; then service hyperion stop 2>/dev/null + SERVICEP="/etc/systemd/system" #many people installed with the official script and this just uses service, if both registered -> dead /usr/sbin/service hyperion stop 2>/dev/null + #Bad workaround for Jessie (systemd) users that used the old official script for install + update-rc.d -f hyperion remove 2>/dev/null + rm /etc/init.d/hyperion 2>/dev/null +elif [ $USE_SERVICE -eq 1 ]; then + /usr/sbin/service hyperion stop 2>/dev/null + SERVICEP="/etc/init.d" fi -#Install dependencies for Hyperion +#Install dependencies for Hyperion and setup preperation if [ $OS_OPENELEC -ne 1 ]; then echo '---> Install/Update Hyperion dependencies (This may take a while)' apt-get -qq update && apt-get -qq --yes install libqtcore4 libqtgui4 libqt4-network libusb-1.0-0 ca-certificates + mkdir /etc/hyperion 2>/dev/null fi #Check, if dtparam=spi=on is in place (not for OPENELEC) @@ -119,15 +129,29 @@ if [ $CPU_RPI -eq 1 ] && [ $OS_OPENELEC -eq 1 ]; then fi fi fi - -#Backup the .conf files, if present -echo '---> Backup Hyperion configuration(s), if present' -rm -f /tmp/*.json 2>/dev/null -if [ $OS_OPENELEC -eq 1 ]; then - cp -v /storage/.config/*.json /tmp 2>/dev/null -else cp -v /opt/hyperion/config/*.json /tmp 2>/dev/null -fi +# compatibility layer to move old configs to new config dir +if [ -f "/opt/hyperion" ]; then + echo '---> Old installation found, move configs to /etc/hyperion/ and move hyperion to /usr/share/hyperion/' + mv /opt/hyperion/config/*.json /etc/hyperion 2>/dev/null + sed -i "s|/opt/hyperion/effects|/usr/share/hyperion/effects|g" /etc/hyperion/*.json + if [ $USE_INITCTL -eq 1 ]; then + sed -i "s|/etc/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEP/hyperion.conf + sed -i "s|/opt/hyperion/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEP/hyperion.conf + initctl reload-configuration + elif [ $OS_OPENELEC -eq 1 ]; then + sleep 0 + elif [ $USE_SYSTEMD -eq 1 ]; then + sed -i "s|/etc/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEP/hyperion.service + sed -i "s|/opt/hyperion/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEP/hyperion.service + systemctl -q daemon-reload + elif [ $USE_SERVICE -eq 1 ]; then + sed -i "s|/etc/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEP/hyperion + sed -i "s|/opt/hyperion/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEP/hyperion + update-rc.d hyperion defaults 98 02 + fi +fi + # Select the appropriate download path if [ $BETA -eq 1 ]; then HYPERION_ADDRESS=https://sourceforge.net/projects/hyperion-project/files/beta @@ -191,32 +215,25 @@ if [ $OS_OPENELEC -eq 1 ]; then curl -# -L --get $OE_DEPENDECIES | tar -C /storage/hyperion/bin -xz #set the executen bit (failsave) chmod +x -R /storage/hyperion/bin - - # /storage/.config is available as samba share. A symbolic link would not be working - false | cp -i /storage/hyperion/config/hyperion.config.json /storage/.config/hyperion.config.json 2>/dev/null else - wget -nv $HYPERION_RELEASE -O - | tar -C /opt -xz - #set the executen bit (failsave) - chmod +x -R /opt/hyperion/bin + BINSP=/usr/share/hyperion/bin + BINTP=/usr/bin + wget -nv $HYPERION_RELEASE -O - | tar -C /usr/share -xz + #set the executen bit (failsave) and move config to /etc/hyperion + chmod +x -R $BINSP # create links to the binaries - ln -fs /opt/hyperion/bin/hyperiond /usr/bin/hyperiond - ln -fs /opt/hyperion/bin/hyperion-remote /usr/bin/hyperion-remote - ln -fs /opt/hyperion/bin/hyperion-v4l2 /usr/bin/hyperion-v4l2 - ln -fs /opt/hyperion/bin/hyperion-dispmanx /usr/bin/hyperion-dispmanx 2>/dev/null - ln -fs /opt/hyperion/bin/hyperion-x11 /usr/bin/hyperion-x11 2>/dev/null -fi - -# Restore backup of .conf files, if present -echo '---> Restore Hyperion configuration(s), if present' -if [ $OS_OPENELEC -eq 1 ]; then - mv -v /tmp/*.json /storage/.config/ 2>/dev/null -else mv -v /tmp/*.json /opt/hyperion/config/ 2>/dev/null + ln -fs $BINSP/hyperiond $BINTP/hyperiond + ln -fs $BINSP/hyperion-remote $BINTP/hyperion-remote + ln -fs $BINSP/hyperion-v4l2 $BINTP/hyperion-v4l2 + ln -fs $BINSP/hyperion-dispmanx $BINTP/hyperion-dispmanx 2>/dev/null + ln -fs $BINSP/hyperion-x11 $BINTP/hyperion-x11 2>/dev/null + ln -fs $BINSP/hyperion-aml $BINTP/hyperion-aml 2>/dev/null fi -# Copy the service control configuration to /etc/int (-n to respect user modified scripts) +# Copy the service control configuration to /etc/init (-n to respect user modified scripts) if [ $USE_INITCTL -eq 1 ]; then echo '---> Installing initctl script' - cp -n /opt/hyperion/init.d/hyperion.initctl.sh /etc/init/hyperion.conf 2>/dev/null + cp -n $SERVICEL/hyperion.initctl.sh $SERVICEP/hyperion.conf 2>/dev/null initctl reload-configuration elif [ $OS_OPENELEC -eq 1 ]; then #modify all old installs with a logfile output @@ -237,34 +254,35 @@ elif [ $OS_OPENELEC -eq 1 ]; then elif [ $USE_SYSTEMD -eq 1 ]; then echo '---> Installing systemd script' #place startup script for systemd and activate - #Problem with systemd to enable symlinks - Bug? Workaround cp -n (overwrite never) - #Bad workaround for Jessie (systemd) users that used the official script for install - update-rc.d -f hyperion remove 2>/dev/null - rm /etc/init.d/hyperion 2>/dev/null - cp -n /opt/hyperion/init.d/hyperion.systemd.sh /etc/systemd/system/hyperion.service + cp -n $SERVICEL/hyperion.systemd.sh $SERVICEP/hyperion.service systemctl -q enable hyperion.service if [ $OS_OSMC -eq 1 ]; then echo '---> Modify systemd script for OSMC usage' - # Wait until kodi is sarted (for kodi checker) - sed -i '/After = mediacenter.service/d' /etc/systemd/system/hyperion.service - sed -i '/Unit/a After = mediacenter.service' /etc/systemd/system/hyperion.service - sed -i 's/User=osmc/User=root/g' /etc/systemd/system/hyperion.service - sed -i 's/Group=osmc/Group=root/g' /etc/systemd/system/hyperion.service + # Wait until kodi is sarted + sed -i '/After = mediacenter.service/d' $SERVICEP/hyperion.service + sed -i '/Unit/a After = mediacenter.service' $SERVICEP/hyperion.service systemctl -q daemon-reload fi elif [ $USE_SERVICE -eq 1 ]; then echo '---> Installing startup script in init.d' # place startup script in init.d and add it to upstart (-s to respect user modified scripts) - ln -s /opt/hyperion/init.d/hyperion.init.sh /etc/init.d/hyperion 2>/dev/null - chmod +x /etc/init.d/hyperion + ln -s $SERVICEL/hyperion.init.sh $SERVICEP/hyperion 2>/dev/null && chmod +x $SERVICEP/hyperion update-rc.d hyperion defaults 98 02 fi +#remove unwanted files/dirs +if [ $OS_OPENELEC -eq 1 ]; then + rm -r /storage/hyperion/services +else + rm -r /usr/share/hyperion/services + rm -r /opt/hyperion 2>/dev/null +fi + #chown the /config/ dir and all configs inside for hypercon config upload for non-root logins if [ $OS_OSMC -eq 1 ]; then - chown -R osmc:osmc /opt/hyperion/config + chown -R osmc:osmc /etc/hyperion/config elif [ $OS_RASPBIAN -eq 1 ]; then - chown -R pi:pi /opt/hyperion/config + chown -R pi:pi /etc/hyperion/config fi # Start the hyperion daemon @@ -311,4 +329,4 @@ if [ $CPU_RPI -eq 1 ] && [ $SPIOK -ne 1 ]; then reboot fi -exit 0 \ No newline at end of file +exit 0 diff --git a/bin/remove_hyperion.sh b/bin/remove_hyperion.sh index b6bf9d1b..da3defe6 100644 --- a/bin/remove_hyperion.sh +++ b/bin/remove_hyperion.sh @@ -40,9 +40,9 @@ if [ "$1" = "" ]; then *) echo "-> Please enter only y or n" esac done - echo "---> You entered \"$CONFIRM\". Remove Hyperion!" fi + # Find out if we are on OpenElec or RasPlex OS_OPENELEC=`grep -m1 -c 'OpenELEC\|RasPlex\|LibreELEC' /etc/issue` @@ -64,10 +64,6 @@ elif [ $USE_SERVICE -eq 1 ]; then /usr/sbin/service hyperion stop 2>/dev/null elif [ $USE_SYSTEMD -eq 1 ]; then service hyperion stop 2>/dev/null -# while [ $SERVICEC -le 20 ]; do -# service hyperion_fw$SERVICEC stop 2>/dev/null -# ((SERVICEC++)) -# done fi #reset count @@ -87,19 +83,11 @@ elif [ $USE_SYSTEMD -eq 1 ]; then # Delete and disable Hyperion systemd script echo '---> Delete and disable Hyperion systemd script' systemctl disable hyperion.service -# while [ $SERVICEC -le 20 ]; do -# systemctl -q disable hyperion_fw$SERVICEC.service 2>/dev/null -# ((SERVICEC++)) -# done rm -v /etc/systemd/system/hyperion* 2>/dev/null elif [ $USE_SERVICE -eq 1 ]; then # Delete and disable Hyperion init.d script echo '---> Delete and disable Hyperion init.d script' update-rc.d -f hyperion remove -# while [ $SERVICEC -le 20 ]; do -# update-rc.d -f hyperion_fw$SERVICEC remove 2>/dev/null -# ((SERVICEC++)) -# done rm /etc/init.d/hyperion* 2>/dev/null fi @@ -117,11 +105,15 @@ else rm -v /usr/bin/hyperion-v4l2 2>/dev/null rm -v /usr/bin/hyperion-dispmanx 2>/dev/null rm -v /usr/bin/hyperion-x11 2>/dev/null + rm -v /usr/bin/hyperion-aml 2>/dev/null rm -v /etc/hyperion.config.json 2>/dev/null echo "---> Remove binaries" rm -rv /opt/hyperion 2>/dev/null + rm -rv /etc/hyperion 2>/dev/null + rm -rv /usr/share/hyperion 2>/dev/null fi echo '*******************************************************************************' echo 'Hyperion successful removed!' echo '*******************************************************************************' exit 0 + \ No newline at end of file diff --git a/config/hyperion.config.json b/config/hyperion.config.json.example similarity index 91% rename from config/hyperion.config.json rename to config/hyperion.config.json.example index 5d549075..0f854473 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json.example @@ -1,12 +1,12 @@ -// Automatically generated configuration file for 'Hyperion daemon' -// Generated by: HyperCon (The Hyperion deamon configuration file builder) -// Created with HyperCon V1.02.0 (30.04.2016) +// This is a example config (hyperion.config.json) with comments, in any case you need to create your own one with HyperCon! +// Webpage: https://www.hyperion-project.org + { /// Device configuration contains the following fields: /// * 'name' : The user friendly name of the device (only used for display purposes) /// * 'type' : The type of the device or leds (known types for now are - /// ---------SPI---------, APA102, WS2801, P9813, LPD6803, LPD8806, ---------PWM---------, WS2812b (just RPi1), WS281X (RPi1, RPi2, RPi3), --------OTHER--------, PhilipsHUE, AtmoOrb, PiBlaster, Tinkerforge, FadeCandy, RawHID (USB), UDP, SEDU, TPM2, USBASP-WS2801, USBASP-WS2812, ------3rd PARTY------, Adalight, AdalightAPA102, AmbiLed, Atmo, Lightpack, Multi-Lightpack, Paintpack, Test (file), None) + /// APA102, WS2801, P9813, LPD6803, LPD8806, ---------PWM---------, WS2812b (just RPi1), WS281X (RPi1, RPi2, RPi3), --------OTHER--------, PhilipsHUE, AtmoOrb, PiBlaster, Tinkerforge, FadeCandy, RawHID (USB), UDP, SEDU, TPM2, USBASP-WS2801, USBASP-WS2812, ------3rd PARTY------, Adalight, AdalightAPA102, AmbiLed, Atmo, Lightpack, Multi-Lightpack, Paintpack, Test (file), None) /// * [device type specific configuration] /// * 'colorOrder' : The order of the color bytes ('rgb', 'rbg', 'bgr', etc.). "device" : @@ -41,6 +41,7 @@ /// tuning parameters: /// - 'saturationGain' The gain adjustement of the saturation /// - 'luminanceGain' The gain adjustement of the luminance + /// - 'luminanceMinimum' The minimum luminance (backlight) /// * 'red'/'green'/'blue' : The manipulation in the Red-Green-Blue color domain with the /// following tuning parameters for each channel: /// - 'threshold' The minimum required input value for the channel to be on @@ -102,7 +103,8 @@ "hsl" : { "saturationGain" : 1.0000, - "luminanceGain" : 1.0000 + "luminanceGain" : 1.0000, + "luminanceMinimum" : 0.0000 }, "red" : { @@ -178,11 +180,11 @@ /// * json : Json server adress and port of your target. Syntax:[IP:PORT] -> ["127.0.0.1:19446"] or more instances to forward ["127.0.0.1:19446","192.168.0.24:19448"] /// HINT: If you redirect to "127.0.0.1" (localhost) you could start a second hyperion with another device/led config! /// Be sure your client(s) is/are listening on the configured ports. The second Hyperion (if used) also needs to be configured! (HyperCon -> External -> Json Server/Proto Server) -// "forwarder" : -// { -// "proto" : ["127.0.0.1:19447"], -// "json" : ["127.0.0.1:19446"] -// }, + "forwarder" : + { + "proto" : ["127.0.0.1:19447"], + "json" : ["127.0.0.1:19446"] + }, /// The configuration for the frame-grabber, contains the following items: /// * width : The width of the grabbed frames [pixels] @@ -205,19 +207,21 @@ /// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show /// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback /// * grabMenu : Flag indicating that the frame-grabber is on(true) at the Kodi menu + /// * grabPause : Flag indicating that the frame-grabber is on(true) at player state "pause" /// * grabScreensaver : Flag indicating that the frame-grabber is on(true) when Kodi is on screensaver /// * enable3DDetection : Flag indicating that the frame-grabber should switch to a 3D compatible modus if a 3D video is playing -// "xbmcVideoChecker" : -// { -// "xbmcAddress" : "127.0.0.1", -// "xbmcTcpPort" : 9090, -// "grabVideo" : true, -// "grabPictures" : true, -// "grabAudio" : true, -// "grabMenu" : false, -// "grabScreensaver" : true, -// "enable3DDetection" : true -// }, + "xbmcVideoChecker" : + { + "xbmcAddress" : "127.0.0.1", + "xbmcTcpPort" : 9090, + "grabVideo" : true, + "grabPictures" : true, + "grabAudio" : true, + "grabMenu" : false, + "grabPause" : false, + "grabScreensaver" : true, + "enable3DDetection" : true + }, /// The configuration of the Json server which enables the json remote interface /// * port : Port at which the json server is started @@ -236,11 +240,11 @@ /// The configuration of the boblight server which enables the boblight remote interface /// * port : Port at which the boblight server is started /// * priority: Priority of the boblight server (Default=900) HINT: lower value result in HIGHER priority! -// "boblightServer" : -// { -// "port" : 19333, -// "priority" : 900 -// }, + "boblightServer" : + { + "port" : 19333, + "priority" : 900 + }, /// Configuration for the embedded V4L2 grabber /// * device : V4L2 Device to use [default="/dev/video0"] @@ -259,25 +263,25 @@ /// * redSignalThreshold : Signal threshold for the red channel between 0.0 and 1.0 [default=0.0] /// * greenSignalThreshold : Signal threshold for the green channel between 0.0 and 1.0 [default=0.0] /// * blueSignalThreshold : Signal threshold for the blue channel between 0.0 and 1.0 [default=0.0] -// "grabber-v4l2" : -// { -// "device" : "/dev/video0", -// "input" : 0, -// "standard" : "no-change", -// "width" : -1, -// "height" : -1, -// "frameDecimation" : 2, -// "sizeDecimation" : 8, -// "priority" : 900, -// "mode" : "2D", -// "cropLeft" : 0, -// "cropRight" : 0, -// "cropTop" : 0, -// "cropBottom" : 0, -// "redSignalThreshold" : 0.0, -// "greenSignalThreshold" : 0.0, -// "blueSignalThreshold" : 0.0 -// }, + "grabber-v4l2" : + { + "device" : "/dev/video0", + "input" : 0, + "standard" : "no-change", + "width" : -1, + "height" : -1, + "frameDecimation" : 2, + "sizeDecimation" : 8, + "priority" : 900, + "mode" : "2D", + "cropLeft" : 0, + "cropRight" : 0, + "cropTop" : 0, + "cropBottom" : 0, + "redSignalThreshold" : 0.0, + "greenSignalThreshold" : 0.0, + "blueSignalThreshold" : 0.0 + }, /// The configuration for each individual led. This contains the specification of the area /// averaged of an input image for each led to determine its color. Each item in the list diff --git a/config/hyperion_x86.config.json b/config/hyperion_x86.config.json deleted file mode 100644 index 329ff248..00000000 --- a/config/hyperion_x86.config.json +++ /dev/null @@ -1,430 +0,0 @@ -// Automatically generated configuration file for 'Hyperion daemon' -// Generated by: HyperCon (The Hyperion deamon configuration file builder - -{ - /// Device configuration contains the following fields: - /// * 'name' : The user friendly name of the device (only used for display purposes) - /// * 'type' : The type of the device or leds (known types for now are 'ws2801', 'ldp8806', - /// 'lpd6803', 'sedu', 'adalight', 'lightpack', 'test' and 'none') - /// * 'output' : The output specification depends on selected device. This can for example be the - /// device specifier, device serial number, or the output file name - /// * 'rate' : The baudrate of the output to the device - /// * 'colorOrder' : The order of the color bytes ('rgb', 'rbg', 'bgr', etc.). - "device" : - { - "name" : "MyPi", - "type" : "adalight", - "output" : "/dev/ttyUSB0", - "rate" : 115200, - "colorOrder" : "rgb" - }, - - /// Color manipulation configuration used to tune the output colors to specific surroundings. - /// The configuration contains a list of color-transforms. Each transform contains the - /// following fields: - /// * 'id' : The unique identifier of the color transformation (eg 'device_1') /// * 'leds' : The indices (or index ranges) of the leds to which this color transform applies - /// (eg '0-5, 9, 11, 12-17'). The indices are zero based. /// * 'hsv' : The manipulation in the Hue-Saturation-Value color domain with the following - /// tuning parameters: - /// - 'saturationGain' The gain adjustement of the saturation - /// - 'valueGain' The gain adjustement of the value - /// * 'red'/'green'/'blue' : The manipulation in the Red-Green-Blue color domain with the - /// following tuning parameters for each channel: - /// - 'threshold' The minimum required input value for the channel to be on - /// (else zero) - /// - 'gamma' The gamma-curve correction factor - /// - 'blacklevel' The lowest possible value (when the channel is black) - /// - 'whitelevel' The highest possible value (when the channel is white) - /// - /// Next to the list with color transforms there is also a smoothing option. - /// * 'smoothing' : Smoothing of the colors in the time-domain with the following tuning - /// parameters: - /// - 'type' The type of smoothing algorithm ('linear' or 'none') - /// - 'time_ms' The time constant for smoothing algorithm in milliseconds - /// - 'updateFrequency' The update frequency of the leds in Hz - "color" : - { - "transform" : - [ - { - "id" : "default", - "leds" : "*", - "hsv" : - { - "saturationGain" : 1.0000, - "valueGain" : 1.0000 - }, - "red" : - { - "threshold" : 0.0000, - "gamma" : 1.0000, - "blacklevel" : 0.0000, - "whitelevel" : 1.0000 - }, - "green" : - { - "threshold" : 0.0000, - "gamma" : 1.0000, - "blacklevel" : 0.0000, - "whitelevel" : 1.0000 - }, - "blue" : - { - "threshold" : 0.0000, - "gamma" : 1.0000, - "blacklevel" : 0.0000, - "whitelevel" : 1.0000 - } - } - ], - "smoothing" : - { - "type" : "none", - "time_ms" : 200, - "updateFrequency" : 20.0000 - } - }, - - /// The configuration for each individual led. This contains the specification of the area - /// averaged of an input image for each led to determine its color. Each item in the list - /// contains the following fields: - /// * index: The index of the led. This determines its location in the string of leds; zero - /// being the first led. - /// * hscan: The fractional part of the image along the horizontal used for the averaging - /// (minimum and maximum inclusive) - /// * vscan: The fractional part of the image along the vertical used for the averaging - /// (minimum and maximum inclusive) - "leds" : - [ - { - "index" : 0, - "hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 1, - "hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 2, - "hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 3, - "hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 4, - "hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 5, - "hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 6, - "hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 7, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 8, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 9, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, - "vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 } - }, - { - "index" : 10, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, - "vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 } - }, - { - "index" : 11, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, - "vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 } - }, - { - "index" : 12, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, - "vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 } - }, - { - "index" : 13, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, - "vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 } - }, - { - "index" : 14, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, - "vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 } - }, - { - "index" : 15, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 } - }, - { - "index" : 16, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 17, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 18, - "hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 19, - "hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 20, - "hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 21, - "hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 22, - "hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 23, - "hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 24, - "hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 25, - "hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 26, - "hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 27, - "hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 28, - "hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 29, - "hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 30, - "hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 31, - "hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 32, - "hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 33, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 34, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 } - }, - { - "index" : 35, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 } - }, - { - "index" : 36, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 } - }, - { - "index" : 37, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 } - }, - { - "index" : 38, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 } - }, - { - "index" : 39, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 } - }, - { - "index" : 40, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 } - }, - { - "index" : 41, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 42, - "hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 43, - "hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 44, - "hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 45, - "hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 46, - "hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 47, - "hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 48, - "hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 49, - "hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - } - ], - - /// The black border configuration, contains the following items: - /// * enable : true if the detector should be activated - /// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0) - "blackborderdetector" : - { - "enable" : true, - "threshold" : 0.01 - }, - - /// 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' - "effects" : - { - "paths" : - [ - "/opt/hyperion/effects" - ] - }, - - "bootsequence" : - { - "effect" : "Rainbow swirl fast", - "duration_ms" : 3000 - }, - - /// The configuration for the frame-grabber, contains the following items: - /// * width : The width of the grabbed frames [pixels] - /// * height : The height of the grabbed frames [pixels] - /// * frequency_Hz : The frequency of the frame grab [Hz] -// "framegrabber" : -// { -// "width" : 64, -// "height" : 64, -// "frequency_Hz" : 10.0 -// }, - - /// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields: - /// * xbmcAddress : The IP address of the XBMC-host - /// * xbmcTcpPort : The TCP-port of the XBMC-server - /// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback - /// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show - /// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback - /// * grabMenu : Flag indicating that the frame-grabber is on(true) in the XBMC menu - /// * grabScreensaver : Flag indicating that the frame-grabber is on(true) when XBMC is on screensaver - /// * enable3DDetection : Flag indicating that the frame-grabber should switch to a 3D compatible modus if a 3D video is playing -// "xbmcVideoChecker" : -// { -// "xbmcAddress" : "127.0.0.1", -// "xbmcTcpPort" : 9090, -// "grabVideo" : true, -// "grabPictures" : true, -// "grabAudio" : true, -// "grabMenu" : false, -// "grabScreensaver" : true, -// "enable3DDetection" : true -// }, - - /// The configuration of the Json server which enables the json remote interface - /// * port : Port at which the json server is started - "jsonServer" : - { - "port" : 19444 - }, - - /// The configuration of the Proto server which enables the protobuffer remote interface - /// * port : Port at which the protobuffer server is started - "protoServer" : - { - "port" : 19445 - }, - - /// The configuration of the boblight server which enables the boblight remote interface - /// * port : Port at which the boblight server is started -// "boblightServer" : -// { -// "port" : 19333 -// }, - - "endOfJson" : "endOfJson" -} From ae40edc57823a39b77350c47066c8bd1749c7bcb Mon Sep 17 00:00:00 2001 From: brindosch Date: Fri, 10 Jun 2016 18:32:50 +0200 Subject: [PATCH 55/63] Add version string to json output (#690) * hyperionversionid * typo * - Former-commit-id: ec5777ccb32fc343ef2f478a7c779a901c8aa489 --- libsrc/jsonserver/JsonClientConnection.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 2f5b13a9..b576c5c3 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -22,6 +22,7 @@ #include #include #include +#include // project includes #include "JsonClientConnection.h" @@ -591,6 +592,14 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &) } } + // Add Hyperion Version, build time + Json::Value & version = info["hyperion_build"] = Json::Value(Json::arrayValue); + Json::Value ver; + ver["version"] = HYPERION_VERSION_ID; + ver["time"] = __DATE__" "__TIME__; + + version.append(ver); + // send the result sendMessage(result); } From b3fa72adba004c13c7e77a506f69c89d91969569 Mon Sep 17 00:00:00 2001 From: brindosch Date: Fri, 10 Jun 2016 18:55:42 +0200 Subject: [PATCH 56/63] fix Former-commit-id: 2019d94e3bb06e23890759aecfd646facbcc0f37 --- libsrc/jsonserver/JsonClientConnection.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index b576c5c3..cfd0887d 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -23,6 +23,7 @@ #include #include #include +#include // project includes #include "JsonClientConnection.h" From 4743208effe23cfca6b0e01b2ab42e120c5b9014 Mon Sep 17 00:00:00 2001 From: brindosch Date: Fri, 10 Jun 2016 19:52:03 +0200 Subject: [PATCH 57/63] silent kodi check Former-commit-id: 45199d123fcf49194aeaaf2df0789dc7ea4df449 --- libsrc/xbmcvideochecker/XBMCVideoChecker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp b/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp index b8d91c22..f638888c 100644 --- a/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp +++ b/libsrc/xbmcvideochecker/XBMCVideoChecker.cpp @@ -59,8 +59,8 @@ void XBMCVideoChecker::receiveReply() { // expect that the reply is received as a single message. Probably oke considering the size of the expected reply QString reply(_socket.readAll()); - - std::cout << "KODICHECK INFO: Kodi Message: " << reply.toStdString() << std::endl; +// silence - no "debug" code should be at the log +// std::cout << "KODICHECK INFO: Kodi Message: " << reply.toStdString() << std::endl; if (reply.contains("\"method\":\"Player.OnPlay\"")) { From 8746e0795cff83b759a986ced8793f1b74b0e40d Mon Sep 17 00:00:00 2001 From: brindosch Date: Fri, 10 Jun 2016 23:54:53 +0200 Subject: [PATCH 58/63] - Former-commit-id: 7aa71ba95e2bb9d76daf612a79fc3f1dd745cf0e --- libsrc/jsonserver/JsonClientConnection.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index cfd0887d..79a749ad 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -23,7 +23,6 @@ #include #include #include -#include // project includes #include "JsonClientConnection.h" @@ -597,7 +596,7 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &) Json::Value & version = info["hyperion_build"] = Json::Value(Json::arrayValue); Json::Value ver; ver["version"] = HYPERION_VERSION_ID; - ver["time"] = __DATE__" "__TIME__; + ver["time"] = __DATE__ " " __TIME__; version.append(ver); From b90fc1d9770a2894c2e4ff21695e7cf4d948b9b9 Mon Sep 17 00:00:00 2001 From: brindosch Date: Sat, 11 Jun 2016 00:28:55 +0200 Subject: [PATCH 59/63] Update install_hyperion.sh Former-commit-id: faba41c021bc2f2e672f6369510f048dc9422668 --- bin/install_hyperion.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/install_hyperion.sh b/bin/install_hyperion.sh index 05d0515a..5fde48f3 100755 --- a/bin/install_hyperion.sh +++ b/bin/install_hyperion.sh @@ -131,7 +131,7 @@ if [ $CPU_RPI -eq 1 ] && [ $OS_OPENELEC -eq 1 ]; then fi # compatibility layer to move old configs to new config dir -if [ -f "/opt/hyperion" ]; then +if [ -f "/opt/hyperion/bin/hyperiond" ]; then echo '---> Old installation found, move configs to /etc/hyperion/ and move hyperion to /usr/share/hyperion/' mv /opt/hyperion/config/*.json /etc/hyperion 2>/dev/null sed -i "s|/opt/hyperion/effects|/usr/share/hyperion/effects|g" /etc/hyperion/*.json From 3445c90757a12b7d5d24e64217ff380374bb9429 Mon Sep 17 00:00:00 2001 From: brindosch Date: Sat, 11 Jun 2016 00:40:09 +0200 Subject: [PATCH 60/63] Update install_hyperion.sh Former-commit-id: 4445a4923822089e0dcb17344c5b61d9da33dde6 --- bin/install_hyperion.sh | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/bin/install_hyperion.sh b/bin/install_hyperion.sh index 5fde48f3..185b991c 100755 --- a/bin/install_hyperion.sh +++ b/bin/install_hyperion.sh @@ -135,19 +135,27 @@ if [ -f "/opt/hyperion/bin/hyperiond" ]; then echo '---> Old installation found, move configs to /etc/hyperion/ and move hyperion to /usr/share/hyperion/' mv /opt/hyperion/config/*.json /etc/hyperion 2>/dev/null sed -i "s|/opt/hyperion/effects|/usr/share/hyperion/effects|g" /etc/hyperion/*.json + CPO1=/etc/hyperion.config.json + CPO2=/opt/hyperion/config/hyperion.config.json + CPN=/etc/hyperion/hyperion.config.json + BPO=/opt/hyperion/bin/hyperiond + BPN=/usr/bin/hyperiond if [ $USE_INITCTL -eq 1 ]; then - sed -i "s|/etc/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEP/hyperion.conf - sed -i "s|/opt/hyperion/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEP/hyperion.conf + sed -i "s|$BPO|$BPN|g" $SERVICEP/hyperion.conf + sed -i "s|$CPO1|$CPN|g" $SERVICEP/hyperion.conf + sed -i "s|$CPO2|$CPN|g" $SERVICEP/hyperion.conf initctl reload-configuration elif [ $OS_OPENELEC -eq 1 ]; then sleep 0 elif [ $USE_SYSTEMD -eq 1 ]; then - sed -i "s|/etc/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEP/hyperion.service - sed -i "s|/opt/hyperion/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEP/hyperion.service + sed -i "s|$BPO|$BPN|g" $SERVICEP/hyperion.conf + sed -i "s|$CPO1|$CPN|g" $SERVICEP/hyperion.service + sed -i "s|$CPO2|$CPN|g" $SERVICEP/hyperion.service systemctl -q daemon-reload elif [ $USE_SERVICE -eq 1 ]; then - sed -i "s|/etc/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEP/hyperion - sed -i "s|/opt/hyperion/hyperion.config.json|/etc/hyperion/hyperion.config.json|g" $SERVICEP/hyperion + sed -i "s|$BPO|$BPN|g" $SERVICEP/hyperion.conf + sed -i "s|$CPO1|$CPN|g" $SERVICEP/hyperion + sed -i "s|$CPO2|$CPN|g" $SERVICEP/hyperion update-rc.d hyperion defaults 98 02 fi fi From 0973a0b09e4abca32518e9bf3d49ecb9a0023771 Mon Sep 17 00:00:00 2001 From: brindosch Date: Sat, 11 Jun 2016 00:40:56 +0200 Subject: [PATCH 61/63] Update install_hyperion.sh Former-commit-id: 660073dc08465a47890a0c4a68c1d7edae7df0cb --- bin/install_hyperion.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/install_hyperion.sh b/bin/install_hyperion.sh index 185b991c..3707f68a 100755 --- a/bin/install_hyperion.sh +++ b/bin/install_hyperion.sh @@ -148,12 +148,12 @@ if [ -f "/opt/hyperion/bin/hyperiond" ]; then elif [ $OS_OPENELEC -eq 1 ]; then sleep 0 elif [ $USE_SYSTEMD -eq 1 ]; then - sed -i "s|$BPO|$BPN|g" $SERVICEP/hyperion.conf + sed -i "s|$BPO|$BPN|g" $SERVICEP/hyperion.service sed -i "s|$CPO1|$CPN|g" $SERVICEP/hyperion.service sed -i "s|$CPO2|$CPN|g" $SERVICEP/hyperion.service systemctl -q daemon-reload elif [ $USE_SERVICE -eq 1 ]; then - sed -i "s|$BPO|$BPN|g" $SERVICEP/hyperion.conf + sed -i "s|$BPO|$BPN|g" $SERVICEP/hyperion sed -i "s|$CPO1|$CPN|g" $SERVICEP/hyperion sed -i "s|$CPO2|$CPN|g" $SERVICEP/hyperion update-rc.d hyperion defaults 98 02 From 41e8f2ef228d88024e263aeaf66f247b7f913040 Mon Sep 17 00:00:00 2001 From: brindosch Date: Sat, 11 Jun 2016 00:47:28 +0200 Subject: [PATCH 62/63] Update install_hyperion.sh Former-commit-id: 6ae380942be446396e05a258a469e62b35c09644 --- bin/install_hyperion.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/install_hyperion.sh b/bin/install_hyperion.sh index 3707f68a..92fff2f6 100755 --- a/bin/install_hyperion.sh +++ b/bin/install_hyperion.sh @@ -288,9 +288,9 @@ fi #chown the /config/ dir and all configs inside for hypercon config upload for non-root logins if [ $OS_OSMC -eq 1 ]; then - chown -R osmc:osmc /etc/hyperion/config + chown -R osmc:osmc /etc/hyperion elif [ $OS_RASPBIAN -eq 1 ]; then - chown -R pi:pi /etc/hyperion/config + chown -R pi:pi /etc/hyperion fi # Start the hyperion daemon From 5cb9505554a92de42f09bdd60dd295e626e7c613 Mon Sep 17 00:00:00 2001 From: brindosch Date: Sat, 11 Jun 2016 00:59:59 +0200 Subject: [PATCH 63/63] Update hyperion.config.json.example Former-commit-id: c5d5f2d4b54f0f6b5172a5e3c6791857fb8e9224 --- config/hyperion.config.json.example | 1 + 1 file changed, 1 insertion(+) diff --git a/config/hyperion.config.json.example b/config/hyperion.config.json.example index 0f854473..de046dbf 100644 --- a/config/hyperion.config.json.example +++ b/config/hyperion.config.json.example @@ -1,4 +1,5 @@ // This is a example config (hyperion.config.json) with comments, in any case you need to create your own one with HyperCon! +// location of all configs: /etc/hyperion // Webpage: https://www.hyperion-project.org

!!O!Jga#TX1Sv3M@qYRTB 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%0AtROBf>0HIAg~M^5jVZe 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%0Av6{th27OK=4{5epG(zcOHlWq@UZ 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