mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Merge remote-tracking branch 'refs/remotes/origin/Beta'
Former-commit-id: 55e158c5ccd60cff7d5fbd3fd4267e620792fd35
This commit is contained in:
commit
d2f47251f5
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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/jgarff/rpi_ws281x
|
||||
url = https://github.com/penfold42/rpi_ws281x.git
|
||||
branch = sk6812
|
||||
|
101
CMakeLists.txt
101
CMakeLists.txt
@ -1,28 +1,63 @@
|
||||
# Define the main-project name
|
||||
project(Hyperion)
|
||||
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 )
|
||||
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 )
|
||||
SET ( DEFAULT_ZEROCONF OFF )
|
||||
|
||||
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()
|
||||
endif ()
|
||||
|
||||
# set the build options
|
||||
option(ENABLE_AMLOGIC "Enable the AMLOGIC video grabber" OFF)
|
||||
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})
|
||||
|
||||
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)
|
||||
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)
|
||||
@ -31,13 +66,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)
|
||||
@ -46,22 +81,21 @@ 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(ENABLE_V4L2 AND NOT ENABLE_PROTOBUF)
|
||||
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")
|
||||
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()
|
||||
|
||||
SET ( PROTOBUF_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/proto )
|
||||
SET ( PROTOBUF_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/proto )
|
||||
@ -85,10 +119,10 @@ 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)
|
||||
@ -113,10 +147,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 +158,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)
|
||||
@ -138,18 +172,21 @@ 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)
|
||||
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)
|
||||
|
||||
# enable make package - no code after this line !
|
||||
include (${CMAKE_CURRENT_SOURCE_DIR}/cmake/packages.cmake)
|
||||
|
19
CODING_STYLE.md
Normal file
19
CODING_STYLE.md
Normal file
@ -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
|
||||
}
|
||||
|
||||
```
|
@ -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
|
||||
|
||||
@ -30,4 +27,11 @@
|
||||
// Define to enable the osx grabber
|
||||
#cmakedefine ENABLE_OSX
|
||||
|
||||
// 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}"
|
||||
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -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.
|
@ -1,43 +1,34 @@
|
||||
#!/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 <release name> <platform> [<cmake args ...>]
|
||||
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}
|
||||
mkdir -p deploy/${RELEASE}
|
||||
cd build-${RELEASE}
|
||||
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)
|
||||
mv hyperion-*-ambilight.* ../deploy/${RELEASE}
|
||||
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-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}
|
||||
|
||||
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
|
||||
|
||||
|
@ -23,18 +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/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" \
|
||||
"$repodir/bin/service/hyperion.initctl.sh" \
|
||||
"$repodir/config/hyperion.config.json"
|
||||
"$repodir/config/hyperion.config.json.example"
|
||||
|
||||
|
@ -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)
|
||||
@ -120,12 +130,34 @@ if [ $CPU_RPI -eq 1 ] && [ $OS_OPENELEC -eq 1 ]; then
|
||||
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
|
||||
# compatibility layer to move old configs to new config dir
|
||||
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|$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|$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
|
||||
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
|
||||
|
||||
# Select the appropriate download path
|
||||
@ -191,34 +223,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
|
||||
# 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
|
||||
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
|
||||
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
|
||||
|
||||
# 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
|
||||
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
|
||||
@ -239,34 +262,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
|
||||
elif [ $OS_RASPBIAN -eq 1 ]; then
|
||||
chown -R pi:pi /opt/hyperion/config
|
||||
chown -R pi:pi /etc/hyperion
|
||||
fi
|
||||
|
||||
# Start the hyperion daemon
|
||||
|
@ -26,22 +26,23 @@ 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`
|
||||
|
||||
@ -63,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
|
||||
@ -86,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
|
||||
|
||||
@ -116,9 +105,12 @@ 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!'
|
||||
|
165
bin/scripts/setup_hyperion_forward.sh
Normal file
165
bin/scripts/setup_hyperion_forward.sh
Normal file
@ -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 '*******************************************************************************'
|
@ -13,7 +13,7 @@
|
||||
### END INIT INFO
|
||||
|
||||
DAEMON=hyperiond
|
||||
DAEMONOPTS="/opt/hyperion/config/hyperion.config.json"
|
||||
DAEMONOPTS="/etc/hyperion/hyperion.config.json"
|
||||
DAEMON_PATH="/usr/bin"
|
||||
|
||||
NAME=$DAEMON
|
||||
|
@ -8,4 +8,4 @@ stop on (runlevel [!2345])
|
||||
|
||||
respawn
|
||||
|
||||
exec /usr/bin/hyperiond /opt/hyperion/config/hyperion.config.json
|
||||
exec /usr/bin/hyperiond /etc/hyperion/hyperion.config.json
|
||||
|
@ -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 /etc/hyperion/hyperion.config.json
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
Restart=on-failure
|
||||
TimeoutStopSec=10
|
||||
|
@ -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()
|
||||
|
@ -32,16 +32,16 @@ IF (UDEV_LIBRARIES AND UDEV_INCLUDE_DIR)
|
||||
# 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)
|
||||
else ()
|
||||
set(UDEV_STABLE 1)
|
||||
endif (UDEV_STABLE)
|
||||
endif ()
|
||||
message(STATUS "libudev stable: ${UDEV_STABLE}")
|
||||
ENDIF (UDEV_LIBRARIES AND UDEV_INCLUDE_DIR)
|
||||
ENDIF ()
|
||||
|
||||
IF (UDEV_FOUND)
|
||||
MESSAGE(STATUS "Found UDev: ${UDEV_LIBRARIES}")
|
||||
MESSAGE(STATUS " include: ${UDEV_INCLUDE_DIR}")
|
||||
ELSE (UDEV_FOUND)
|
||||
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}")
|
||||
@ -49,5 +49,5 @@ ELSE (UDEV_FOUND)
|
||||
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)
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
@ -69,12 +69,8 @@ else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
|
||||
/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)
|
||||
|
22
cmake/cmake_uninstall.cmake.in
Normal file
22
cmake/cmake_uninstall.cmake.in
Normal file
@ -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)
|
||||
|
87
cmake/debian/postinst
Normal file
87
cmake/debian/postinst
Normal file
@ -0,0 +1,87 @@
|
||||
#!/bin/sh
|
||||
|
||||
install_file()
|
||||
{
|
||||
src="$1"
|
||||
dest="$2"
|
||||
|
||||
if [ -e "$dest" ] && ! cmp --quiet "$src" "$dest"
|
||||
then
|
||||
echo "INFO: $dest exists, new version copied to ${dest}.new"
|
||||
cp "$src" "${dest}.new"
|
||||
return 1
|
||||
fi
|
||||
|
||||
cp "$src" "${dest}"
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
$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)
|
||||
# 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
|
||||
|
||||
else
|
||||
echo "- init deamon: sysV"
|
||||
# sysV
|
||||
$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
|
||||
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
|
||||
|
32
cmake/packages.cmake
Normal file
32
cmake/packages.cmake
Normal file
@ -0,0 +1,32 @@
|
||||
# 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), libusb-1.0-0, libpython2.7, libc6" )
|
||||
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 )
|
@ -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
|
||||
|
57
cmake/rpm/postinst
Normal file
57
cmake/rpm/postinst
Normal file
@ -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"
|
||||
|
@ -1,12 +1,13 @@
|
||||
// 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!
|
||||
// location of all configs: /etc/hyperion
|
||||
// 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 +42,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 +104,8 @@
|
||||
"hsl" :
|
||||
{
|
||||
"saturationGain" : 1.0000,
|
||||
"luminanceGain" : 1.0000
|
||||
"luminanceGain" : 1.0000,
|
||||
"luminanceMinimum" : 0.0000
|
||||
},
|
||||
"red" :
|
||||
{
|
||||
@ -178,11 +181,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 +208,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 +241,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 +264,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
|
@ -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" :
|
||||
[
|
||||
"/home/dincs/projects/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"
|
||||
}
|
58
dependencies/CMakeLists.txt
vendored
58
dependencies/CMakeLists.txt
vendored
@ -11,43 +11,42 @@ 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)
|
||||
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()
|
||||
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()
|
||||
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 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})
|
||||
# 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 <philip@yhbt.com>
|
||||
# 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)
|
||||
#=============================================================================
|
||||
# Copyright 2009 Kitware, Inc.
|
||||
# Copyright 2009-2011 Philip Lowman <philip@yhbt.com>
|
||||
# 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()
|
||||
@ -106,5 +105,4 @@ if(ENABLE_PROTOBUF)
|
||||
set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
|
||||
set(${SRCS} ${${SRCS}} PARENT_SCOPE)
|
||||
set(${HDRS} ${${HDRS}} PARENT_SCOPE)
|
||||
endfunction()
|
||||
endif()
|
||||
endfunction()
|
||||
|
2
dependencies/external/rpi_ws281x
vendored
2
dependencies/external/rpi_ws281x
vendored
@ -1 +1 @@
|
||||
Subproject commit e053bc9be127d1f4f0cffd10e7892cd32657ecf7
|
||||
Subproject commit dfcf740848898b432fe3a3170417de60f81521ee
|
@ -1,57 +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
|
||||
|
Binary file not shown.
@ -1,165 +0,0 @@
|
||||
// Automatically generated configuration file for 'Hyperion daemon'
|
||||
// Generated by: HyperCon (The Hyperion deamon configuration file builder)
|
||||
// Created with HyperCon V1.00.0 (11.03.2016)
|
||||
|
||||
{
|
||||
/// 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
|
||||
/// APA102, Adalight, AdalightAPA102, AmbiLed, Atmo, Hyperion-USBASP-WS2801, Hyperion-USBASP-WS2812, Lightberry, Lightpack, LPD6803, LPD8806, Multi-Lightpack, P9813, Paintpack, PhilipsHUE, PiBlaster, SEDU, Test, ThinkerForge, TPM2, WS2801, WS2812b, None)
|
||||
/// * [device type specific configuration]
|
||||
/// * 'colorOrder' : The order of the color bytes ('rgb', 'rbg', 'bgr', etc.).
|
||||
///
|
||||
/// * 'Specific for AtmoOrb:
|
||||
/// * 'transitiontime' : Set the time of transition between color of Orb (not implemented)
|
||||
/// * 'port' : Multicast UDP port
|
||||
/// * 'numLeds' : Number of leds in Orb
|
||||
/// * 'orbIds' : The Orb ids to use
|
||||
/// * 'switchOffOnBlack': Define if Orb is to switch off when black is detected
|
||||
"device" :
|
||||
{
|
||||
"name" : "MyPi",
|
||||
"type" : "atmoorb",
|
||||
"output" : "239.15.18.2",
|
||||
"transitiontime" : 0,
|
||||
"port" : 49692,
|
||||
"numLeds" : 24,
|
||||
"orbIds" : "1",
|
||||
"switchOffOnBlack" : true,
|
||||
"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
|
||||
/// - 'updateDelay' The delay of the output to leds (in periods of smoothing)
|
||||
"color" :
|
||||
{
|
||||
"transform" :
|
||||
[
|
||||
{
|
||||
"id" : "default",
|
||||
"leds" : "*",
|
||||
"hsv" :
|
||||
{
|
||||
"saturationGain" : 1.0000,
|
||||
"valueGain" : 1.0000
|
||||
},
|
||||
"red" :
|
||||
{
|
||||
"threshold" : 0.0000,
|
||||
"gamma" : 2.2000,
|
||||
"blacklevel" : 0.0000,
|
||||
"whitelevel" : 1.0000
|
||||
},
|
||||
"green" :
|
||||
{
|
||||
"threshold" : 0.0000,
|
||||
"gamma" : 2.2000,
|
||||
"blacklevel" : 0.0000,
|
||||
"whitelevel" : 1.0000
|
||||
},
|
||||
"blue" :
|
||||
{
|
||||
"threshold" : 0.0000,
|
||||
"gamma" : 2.2000,
|
||||
"blacklevel" : 0.0000,
|
||||
"whitelevel" : 1.0000
|
||||
}
|
||||
}
|
||||
],
|
||||
"smoothing" :
|
||||
{
|
||||
"type" : "linear",
|
||||
"time_ms" : 100,
|
||||
"updateFrequency" : 60.0000,
|
||||
"updateDelay" : 0
|
||||
}
|
||||
},
|
||||
|
||||
/// The black border configuration, contains the following items:
|
||||
/// * enable : true if the detector should be activated
|
||||
/// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0)
|
||||
/// * unknownFrameCnt : Number of frames without any detection before the border is set to 0 (default 600)
|
||||
/// * borderFrameCnt : Number of frames before a consistent detected border gets set (default 50)
|
||||
/// * maxInconsistentCnt : Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency
|
||||
/// * blurRemoveCnt : Number of pixels that get removed from the detected border to cut away blur (default 1)
|
||||
/// * mode : Border detection mode (values=default,classic,osd)
|
||||
"blackborderdetector" :
|
||||
{
|
||||
"enable" : false,
|
||||
"threshold" : 0.01,
|
||||
"unknownFrameCnt" : 600,
|
||||
"borderFrameCnt" : 50,
|
||||
"maxInconsistentCnt" : 10,
|
||||
"blurRemoveCnt" : 1,
|
||||
"mode" : "default"
|
||||
},
|
||||
|
||||
/// The configuration of the effect engine, contains the following items:
|
||||
/// * paths : An array with absolute location(s) of directories with effects
|
||||
/// * color : Set static color after boot -> set effect to "" (empty) and input the values [R,G,B] and set duration_ms NOT to 0 (use 1) instead
|
||||
/// * effect : The effect selected as 'boot sequence'
|
||||
/// * duration_ms : The duration of the selected effect (0=endless)
|
||||
/// * priority : The priority of the selected effect/static color (default=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"
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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)
|
@ -4,7 +4,7 @@
|
||||
"args" :
|
||||
{
|
||||
"rotationTime" : 60.0,
|
||||
"color" : [0,0,255],
|
||||
"colorRandom" : true,
|
||||
"hueChange" : 30.0,
|
||||
"blobs" : 5,
|
||||
"reverse" : false,
|
||||
|
@ -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
|
||||
|
9
effects/udp-mcast.json
Normal file
9
effects/udp-mcast.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name" : "UDP multicast listener",
|
||||
"script" : "udp.py",
|
||||
"args" :
|
||||
{
|
||||
"ListenPort" : 2801,
|
||||
"ListenIP" : "239.255.28.01"
|
||||
}
|
||||
}
|
@ -3,6 +3,6 @@
|
||||
"script" : "udp.py",
|
||||
"args" :
|
||||
{
|
||||
"udpPort" : 2391
|
||||
"ListenPort" : 2391
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
60
include/bonjour/bonjourrecord.h
Executable file
60
include/bonjour/bonjourrecord.h
Executable file
@ -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 <QtCore/QMetaType>
|
||||
#include <QtCore/QString>
|
||||
|
||||
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
|
66
include/bonjour/bonjourserviceregister.h
Executable file
66
include/bonjour/bonjourserviceregister.h
Executable file
@ -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 <QtCore/QObject>
|
||||
|
||||
#include "bonjourrecord.h"
|
||||
class QSocketNotifier;
|
||||
|
||||
#include <dns_sd.h>
|
||||
|
||||
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
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
// X11 includes
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include <sys/ipc.h>
|
||||
@ -16,11 +15,15 @@ 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();
|
||||
|
||||
int open();
|
||||
///
|
||||
/// Set the video mode (2D/3D)
|
||||
/// @param[in] mode The new video mode
|
||||
///
|
||||
void setVideoMode(const VideoMode videoMode);
|
||||
|
||||
bool Setup();
|
||||
|
||||
@ -29,6 +32,7 @@ public:
|
||||
private:
|
||||
ImageResampler _imageResampler;
|
||||
|
||||
bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable;
|
||||
int _cropLeft;
|
||||
int _cropRight;
|
||||
int _cropTop;
|
||||
@ -42,6 +46,13 @@ private:
|
||||
Window _window;
|
||||
XWindowAttributes _windowAttr;
|
||||
|
||||
Pixmap _pixmap;
|
||||
XRenderPictFormat* _srcFormat;
|
||||
XRenderPictFormat* _dstFormat;
|
||||
XRenderPictureAttributes _pictAttr;
|
||||
Picture _srcPicture;
|
||||
Picture _dstPicture;
|
||||
|
||||
unsigned _screenWidth;
|
||||
unsigned _screenHeight;
|
||||
unsigned _croppedWidth;
|
||||
|
@ -79,6 +79,12 @@ public:
|
||||
///
|
||||
unsigned getLedCount() const;
|
||||
|
||||
///
|
||||
/// Returns the current priority
|
||||
///
|
||||
/// @return The current priority
|
||||
///
|
||||
int getCurrentPriority() const;
|
||||
///
|
||||
/// Returns a list of active priorities
|
||||
///
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
// Utility includes
|
||||
#include <utils/ColorRgb.h>
|
||||
#include <utils/ColorRgbw.h>
|
||||
#include <utils/RgbToRgbw.h>
|
||||
|
||||
///
|
||||
/// Interface (pure virtual base class) for LedDevices.
|
||||
|
@ -13,6 +13,8 @@
|
||||
// hyperion util
|
||||
#include <utils/Image.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
#include <utils/GrabbingMode.h>
|
||||
#include <utils/VideoMode.h>
|
||||
|
||||
// jsoncpp includes
|
||||
#include <message.pb.h>
|
||||
@ -23,7 +25,7 @@
|
||||
class ProtoConnection : public QObject
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
///
|
||||
@ -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;
|
||||
};
|
||||
|
@ -4,11 +4,13 @@
|
||||
// hyperion includes
|
||||
#include <utils/Image.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
#include <utils/GrabbingMode.h>
|
||||
#include <utils/VideoMode.h>
|
||||
|
||||
// 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
|
||||
@ -17,6 +19,13 @@ 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
|
||||
/// @param image The image to process
|
||||
|
@ -15,6 +15,8 @@
|
||||
// hyperion includes
|
||||
#include <utils/Image.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
#include <utils/GrabbingMode.h>
|
||||
#include <utils/VideoMode.h>
|
||||
|
||||
// forward decl
|
||||
class ProtoClientConnection;
|
||||
@ -50,6 +52,13 @@ public:
|
||||
public slots:
|
||||
void sendImageToProtoSlaves(int priority, const Image<ColorRgb> & 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
|
||||
|
65
include/utils/ColorRgbw.h
Normal file
65
include/utils/ColorRgbw.h
Normal file
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
// STL includes
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
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);
|
||||
}
|
@ -9,6 +9,7 @@ enum GrabbingMode
|
||||
GRABBINGMODE_OFF,
|
||||
/** Frame grabbing during video */
|
||||
GRABBINGMODE_VIDEO,
|
||||
GRABBINGMODE_PAUSE,
|
||||
GRABBINGMODE_PHOTO,
|
||||
GRABBINGMODE_AUDIO,
|
||||
GRABBINGMODE_MENU,
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -22,8 +22,7 @@ public:
|
||||
|
||||
void set3D(VideoMode mode);
|
||||
|
||||
void processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat,
|
||||
Image<ColorRgb> & outputImage) const;
|
||||
void processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat, Image<ColorRgb> & outputImage) const;
|
||||
|
||||
private:
|
||||
static inline uint8_t clamp(int x);
|
||||
|
48
include/utils/Logger.h
Normal file
48
include/utils/Logger.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <map>
|
||||
|
||||
// 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<std::string,Logger*> *LoggerMap;
|
||||
|
||||
std::string _name;
|
||||
std::string _appname;
|
||||
LogLevel _minLevel;
|
||||
bool _syslogEnabled;
|
||||
unsigned int _loggerId;
|
||||
};
|
||||
|
37
include/utils/Profiler.h
Normal file
37
include/utils/Profiler.h
Normal file
@ -0,0 +1,37 @@
|
||||
#include "utils/Logger.h"
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <map>
|
||||
|
||||
#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;
|
||||
};
|
4
include/utils/RgbToRgbw.h
Normal file
4
include/utils/RgbToRgbw.h
Normal file
@ -0,0 +1,4 @@
|
||||
#include <utils/ColorRgb.h>
|
||||
#include <utils/ColorRgbw.h>
|
||||
|
||||
void Rgb_to_Rgbw(ColorRgb input, ColorRgbw * output, std::string _whiteAlgorithm);
|
@ -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
|
||||
@ -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;
|
||||
|
||||
|
@ -7,9 +7,11 @@ add_subdirectory(hyperion)
|
||||
add_subdirectory(blackborder)
|
||||
add_subdirectory(jsonserver)
|
||||
|
||||
if (ENABLE_PROTOBUF)
|
||||
add_subdirectory(protoserver)
|
||||
endif (ENABLE_PROTOBUF)
|
||||
add_subdirectory(protoserver)
|
||||
|
||||
if (ENABLE_ZEROCONF)
|
||||
add_subdirectory(bonjour)
|
||||
endif (ENABLE_ZEROCONF)
|
||||
|
||||
add_subdirectory(boblightserver)
|
||||
add_subdirectory(leddevice)
|
||||
|
@ -18,10 +18,10 @@ set(BoblightServer_SOURCES
|
||||
)
|
||||
|
||||
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)
|
||||
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}
|
||||
@ -31,8 +31,8 @@ add_library(boblightserver
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(boblightserver Widgets)
|
||||
endif(ENABLE_QT5)
|
||||
qt5_use_modules(boblightserver Widgets)
|
||||
endif()
|
||||
|
||||
target_link_libraries(boblightserver
|
||||
hyperion
|
||||
|
52
libsrc/bonjour/CMakeLists.txt
Normal file
52
libsrc/bonjour/CMakeLists.txt
Normal file
@ -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})
|
102
libsrc/bonjour/bonjourserviceregister.cpp
Executable file
102
libsrc/bonjour/bonjourserviceregister.cpp
Executable file
@ -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 <bonjour/bonjourserviceregister.h>
|
||||
|
||||
|
||||
#include <QtCore/QSocketNotifier>
|
||||
|
||||
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<BonjourServiceRegister *>(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);
|
||||
}
|
||||
}
|
15
libsrc/bonjour/fortuneserver.pro
Executable file
15
libsrc/bonjour/fortuneserver.pro
Executable file
@ -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
|
||||
}
|
39
libsrc/bonjour/main.cpp
Executable file
39
libsrc/bonjour/main.cpp
Executable file
@ -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 <QApplication>
|
||||
#include <QtCore>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
96
libsrc/bonjour/server.cpp
Executable file
96
libsrc/bonjour/server.cpp
Executable file
@ -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 <QtGui>
|
||||
#include <QtNetwork>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#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();
|
||||
}
|
52
libsrc/bonjour/server.h
Executable file
52
libsrc/bonjour/server.h
Executable file
@ -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 <QDialog>
|
||||
|
||||
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
|
@ -26,16 +26,15 @@ SET(EffectEngineSOURCES
|
||||
${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}
|
||||
@ -46,8 +45,8 @@ add_library(effectengine
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(effectengine Widgets)
|
||||
endif(ENABLE_QT5)
|
||||
qt5_use_modules(effectengine Widgets)
|
||||
endif()
|
||||
|
||||
target_link_libraries(effectengine
|
||||
hyperion
|
||||
|
@ -35,12 +35,9 @@ 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;
|
||||
}
|
||||
|
||||
int efxCount = 0;
|
||||
QStringList filenames = directory.entryList(QStringList() << "*.json", QDir::Files, QDir::Name | QDir::IgnoreCase);
|
||||
foreach (const QString & filename, filenames)
|
||||
{
|
||||
@ -48,8 +45,16 @@ EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectCo
|
||||
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
|
||||
|
@ -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;
|
||||
|
@ -23,9 +23,9 @@ SET(DispmanxGrabberSOURCES
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
else()
|
||||
QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
endif()
|
||||
|
||||
add_library(dispmanx-grabber
|
||||
${DispmanxGrabberHEADERS}
|
||||
|
@ -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<ColorRgba> & 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);
|
||||
|
@ -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;
|
||||
@ -94,3 +95,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);
|
||||
}
|
||||
|
@ -23,9 +23,9 @@ SET(FramebufferGrabberSOURCES
|
||||
|
||||
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}
|
||||
|
@ -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:
|
||||
|
@ -18,9 +18,9 @@ SET(OsxGrabberSOURCES
|
||||
|
||||
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}
|
||||
|
@ -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:
|
||||
|
@ -17,10 +17,10 @@ SET(V4L2_SOURCES
|
||||
)
|
||||
|
||||
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)
|
||||
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}
|
||||
|
@ -23,10 +23,10 @@ SET(X11_SOURCES
|
||||
)
|
||||
|
||||
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}
|
||||
|
@ -2,19 +2,22 @@
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
|
||||
// X11 includes
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
// X11Grabber includes
|
||||
#include <grabber/X11Grabber.h>
|
||||
|
||||
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()
|
||||
@ -35,26 +40,53 @@ X11Grabber::~X11Grabber()
|
||||
}
|
||||
}
|
||||
|
||||
void X11Grabber::setVideoMode(const VideoMode videoMode)
|
||||
{
|
||||
_imageResampler.set3D(videoMode);
|
||||
}
|
||||
|
||||
void X11Grabber::freeResources()
|
||||
{
|
||||
// Cleanup allocated resources of the X11 grab
|
||||
XShmDetach(_x11Display, &_shminfo);
|
||||
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);
|
||||
|
||||
_shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777);
|
||||
_shminfo.shmaddr = _xImage->data = (char*)shmat(_shminfo.shmid,0,0);
|
||||
_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);
|
||||
}
|
||||
}
|
||||
|
||||
bool X11Grabber::Setup()
|
||||
@ -63,23 +95,60 @@ bool X11Grabber::Setup()
|
||||
if (_x11Display == nullptr)
|
||||
{
|
||||
std::cerr << "X11GRABBER ERROR: Unable to open display";
|
||||
if (getenv("DISPLAY"))
|
||||
if (getenv("DISPLAY")) {
|
||||
std::cerr << " " << std::string(getenv("DISPLAY")) << std::endl;
|
||||
else
|
||||
} 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;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Image<ColorRgb> & X11Grabber::grab()
|
||||
{
|
||||
updateScreenDimensions();
|
||||
|
||||
XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, 0x00FFFFFF);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (_xImage == nullptr)
|
||||
{
|
||||
std::cerr << "X11GRABBER ERROR: Grab failed" << std::endl;
|
||||
@ -108,23 +177,30 @@ int X11Grabber::updateScreenDimensions()
|
||||
|
||||
std::cout << "X11GRABBER INFO: Update of screen resolution: [" << _screenWidth << "x" << _screenHeight <<"] => ";
|
||||
|
||||
if (_screenWidth || _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;
|
||||
_croppedWidth = (_screenWidth > unsigned(_cropLeft + _cropRight))
|
||||
? (_screenWidth - _cropLeft - _cropRight)
|
||||
: _screenWidth;
|
||||
|
||||
if (_screenHeight > unsigned(_cropTop + _cropBottom))
|
||||
_croppedHeight = _screenHeight - _cropTop - _cropBottom;
|
||||
else
|
||||
_croppedHeight = _screenHeight;
|
||||
_croppedHeight = (_screenHeight > unsigned(_cropTop + _cropBottom))
|
||||
? (_screenHeight - _cropTop - _cropBottom)
|
||||
: _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();
|
||||
|
||||
|
@ -38,17 +38,17 @@ SET(Hyperion_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/MessageForwarder.cpp
|
||||
)
|
||||
|
||||
set(Hyperion_RESOURCES
|
||||
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)
|
||||
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}
|
||||
@ -59,8 +59,8 @@ add_library(hyperion
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(hyperion Widgets)
|
||||
endif(ENABLE_QT5)
|
||||
qt5_use_modules(hyperion Widgets)
|
||||
endif()
|
||||
|
||||
target_link_libraries(hyperion
|
||||
blackborder
|
||||
|
@ -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)
|
||||
@ -479,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();
|
||||
@ -617,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"])),
|
||||
@ -818,6 +819,11 @@ void Hyperion::clearall()
|
||||
_effectEngine->allChannelsCleared();
|
||||
}
|
||||
|
||||
int Hyperion::getCurrentPriority() const
|
||||
{
|
||||
return _muxer.getCurrentPriority();
|
||||
}
|
||||
|
||||
QList<int> Hyperion::getActivePriorities() const
|
||||
{
|
||||
return _muxer.getPriorities();
|
||||
@ -860,9 +866,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<ColorRgb> correctedColors = _raw2ledCorrection->applyCorrection(priorityInfo.ledColors);
|
||||
std::vector<ColorRgb> adjustedColors = _raw2ledAdjustment->applyAdjustment(priorityInfo.ledColors);
|
||||
std::vector<ColorRgb> transformColors =_raw2ledTransform->applyTransform(adjustedColors);
|
||||
std::vector<ColorRgb> ledColors = _raw2ledTemperature->applyCorrection(transformColors);
|
||||
std::vector<ColorRgb> transformColors =_raw2ledTransform->applyTransform(priorityInfo.ledColors);
|
||||
std::vector<ColorRgb> adjustedColors = _raw2ledAdjustment->applyAdjustment(transformColors);
|
||||
std::vector<ColorRgb> ledColors = _raw2ledTemperature->applyCorrection(adjustedColors);
|
||||
const std::vector<Led>& leds = _ledString.leds();
|
||||
int i = 0;
|
||||
for (ColorRgb& color : ledColors)
|
||||
@ -885,18 +891,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;
|
||||
}
|
||||
}
|
||||
|
@ -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,6 +110,7 @@ void LinearColorSmoothing::queueColors(const std::vector<ColorRgb> & ledColors)
|
||||
if (_outputDelay == 0)
|
||||
{
|
||||
// No output delay => immediate write
|
||||
if ( _writeToLedsEnable )
|
||||
_ledDevice->write(ledColors);
|
||||
}
|
||||
else
|
||||
@ -116,6 +120,7 @@ void LinearColorSmoothing::queueColors(const std::vector<ColorRgb> & ledColors)
|
||||
// If the delay-buffer is filled pop the front and write to device
|
||||
if (_outputQueue.size() > _outputDelay)
|
||||
{
|
||||
if ( _writeToLedsEnable )
|
||||
_ledDevice->write(_outputQueue.front());
|
||||
_outputQueue.pop_front();
|
||||
}
|
||||
|
@ -80,4 +80,6 @@ private:
|
||||
/** The output queue */
|
||||
std::list<std::vector<ColorRgb> > _outputQueue;
|
||||
|
||||
// prevent sending data to device when no intput data is sent
|
||||
bool _writeToLedsEnable;
|
||||
};
|
||||
|
@ -89,13 +89,15 @@ std::vector<ColorRgb> MultiColorAdjustment::applyAdjustment(const std::vector<Co
|
||||
ColorRgb& color = ledColors[i];
|
||||
|
||||
int RR = adjustment->_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;
|
||||
|
@ -68,6 +68,11 @@
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
},
|
||||
"luminanceMinimum" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
@ -283,6 +288,10 @@
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabPause" : {
|
||||
"type" : "boolean",
|
||||
"required" : false
|
||||
},
|
||||
"grabScreensaver" : {
|
||||
"type" : "boolean",
|
||||
"required" : false
|
||||
|
@ -21,12 +21,12 @@ 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)
|
||||
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}
|
||||
@ -38,8 +38,8 @@ add_library(jsonserver
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(jsonserver Widgets Network)
|
||||
endif(ENABLE_QT5)
|
||||
qt5_use_modules(jsonserver Widgets Network)
|
||||
endif()
|
||||
|
||||
target_link_libraries(jsonserver
|
||||
hyperion
|
||||
|
@ -1,6 +1,7 @@
|
||||
// system includes
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
|
||||
// stl includes
|
||||
#include <iostream>
|
||||
@ -21,6 +22,7 @@
|
||||
#include <hyperion/ColorCorrection.h>
|
||||
#include <hyperion/ColorAdjustment.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
#include <HyperionConfig.h>
|
||||
|
||||
// project includes
|
||||
#include "JsonClientConnection.h"
|
||||
@ -455,6 +457,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());
|
||||
@ -529,6 +532,74 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &)
|
||||
activeEffects.append(activeEffect);
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// 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<int>::max())
|
||||
{
|
||||
Json::Value LEDcolor;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
@ -590,6 +661,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"];
|
||||
|
@ -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()
|
||||
|
@ -35,6 +35,11 @@
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
},
|
||||
"luminanceMinimum" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
},
|
||||
"threshold": {
|
||||
"type": "array",
|
||||
"required": false,
|
||||
|
@ -9,7 +9,8 @@ find_package(Threads REQUIRED)
|
||||
|
||||
include_directories(
|
||||
../../include/hidapi
|
||||
${LIBUSB_1_INCLUDE_DIRS}) # for Lightpack device
|
||||
${LIBUSB_1_INCLUDE_DIRS}
|
||||
) # for Lightpack device
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(Leddevice_QT_HEADERS
|
||||
@ -37,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
|
||||
@ -61,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
|
||||
@ -75,6 +80,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,32 +90,33 @@ 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)
|
||||
endif()
|
||||
|
||||
if(ENABLE_WS2812BPWM)
|
||||
SET(Leddevice_HEADERS
|
||||
SET(Leddevice_HEADERS
|
||||
${Leddevice_HEADERS}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.h
|
||||
)
|
||||
SET(Leddevice_SOURCES
|
||||
SET(Leddevice_SOURCES
|
||||
${Leddevice_SOURCES}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.cpp
|
||||
)
|
||||
endif(ENABLE_WS2812BPWM)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_WS281XPWM)
|
||||
include_directories(../../dependencies/external/rpi_ws281x)
|
||||
SET(Leddevice_HEADERS
|
||||
include_directories(../../dependencies/external/rpi_ws281x)
|
||||
SET(Leddevice_HEADERS
|
||||
${Leddevice_HEADERS}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWS281x.h
|
||||
)
|
||||
SET(Leddevice_SOURCES
|
||||
SET(Leddevice_SOURCES
|
||||
${Leddevice_SOURCES}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWS281x.cpp
|
||||
)
|
||||
endif(ENABLE_WS281XPWM)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_TINKERFORGE)
|
||||
SET(Leddevice_HEADERS
|
||||
@ -120,13 +127,13 @@ if(ENABLE_TINKERFORGE)
|
||||
${Leddevice_SOURCES}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.cpp
|
||||
)
|
||||
endif(ENABLE_TINKERFORGE)
|
||||
endif()
|
||||
|
||||
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)
|
||||
QT5_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS})
|
||||
else()
|
||||
QT4_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS})
|
||||
endif()
|
||||
|
||||
|
||||
add_library(leddevice
|
||||
@ -137,8 +144,8 @@ add_library(leddevice
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(leddevice Widgets Network)
|
||||
endif(ENABLE_QT5)
|
||||
qt5_use_modules(leddevice Widgets Network)
|
||||
endif()
|
||||
|
||||
target_link_libraries(leddevice
|
||||
hyperion-utils
|
||||
|
@ -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<ColorRgb> &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<unsigned int>(((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<unsigned int>(((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<ColorRgb>(_ledBuffer.size(), ColorRgb{0,0,0}));
|
||||
return write(std::vector<ColorRgb>(_mLedCount, ColorRgb{0,0,0}));
|
||||
}
|
||||
|
@ -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<uint8_t> _ledBuffer;
|
||||
unsigned int _HW_ledcount;
|
||||
unsigned int _mLedCount;
|
||||
|
||||
};
|
||||
|
@ -15,21 +15,27 @@ 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<unsigned int> orbIds) :
|
||||
LedDeviceAtmoOrb::LedDeviceAtmoOrb(
|
||||
const std::string &output,
|
||||
bool useOrbSmoothing,
|
||||
int transitiontime,
|
||||
int skipSmoothingDiff,
|
||||
int port,
|
||||
int numLeds,
|
||||
std::vector<unsigned int> orbIds) :
|
||||
multicastGroup(output.c_str()), useOrbSmoothing(useOrbSmoothing), transitiontime(transitiontime), skipSmoothingDiff(skipSmoothingDiff),
|
||||
multiCastGroupPort(port), numLeds(numLeds), orbIds(orbIds) {
|
||||
multiCastGroupPort(port), numLeds(numLeds), orbIds(orbIds)
|
||||
{
|
||||
manager = new QNetworkAccessManager();
|
||||
groupAddress = QHostAddress(multicastGroup);
|
||||
|
||||
udpSocket = new QUdpSocket(this);
|
||||
udpSocket->bind(multiCastGroupPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
|
||||
udpSocket->bind(QHostAddress::Any, multiCastGroupPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
|
||||
|
||||
joinedMulticastgroup = udpSocket->joinMulticastGroup(groupAddress);
|
||||
}
|
||||
|
||||
int LedDeviceAtmoOrb::write(const std::vector <ColorRgb> &ledValues) {
|
||||
|
||||
// If not in multicast group return
|
||||
if (!joinedMulticastgroup) {
|
||||
return 0;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "LedDeviceLpd8806.h"
|
||||
#include "LedDeviceP9813.h"
|
||||
#include "LedDeviceWs2801.h"
|
||||
#include "LedDeviceWs2812SPI.h"
|
||||
#include "LedDeviceAPA102.h"
|
||||
#endif
|
||||
|
||||
@ -32,6 +33,7 @@
|
||||
#include "LedDeviceFile.h"
|
||||
#include "LedDeviceFadeCandy.h"
|
||||
#include "LedDeviceUdp.h"
|
||||
#include "LedDeviceUdpRaw.h"
|
||||
#include "LedDeviceHyperionUsbasp.h"
|
||||
#include "LedDevicePhilipsHue.h"
|
||||
#include "LedDeviceTpm2.h"
|
||||
@ -124,8 +126,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;
|
||||
@ -141,6 +144,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")
|
||||
@ -306,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();
|
||||
@ -340,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
|
||||
@ -349,6 +375,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;
|
||||
}
|
||||
|
@ -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.
|
||||
@ -174,26 +174,26 @@ int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues) {
|
||||
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}"));
|
||||
// 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));
|
||||
|
||||
}
|
||||
// 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.
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
@ -25,7 +25,6 @@ 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;
|
||||
@ -45,7 +44,7 @@ LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate, c
|
||||
port+=output[i];
|
||||
}
|
||||
}
|
||||
//std::cout << "output " << output << " hostname " << hostname << " port " << port <<std::endl;
|
||||
//std::cout << "output " << output << " hostname " << hostname << " port " << port <<std::endl;
|
||||
assert(got_colon==1);
|
||||
|
||||
int rv;
|
||||
@ -153,8 +152,47 @@ int LedDeviceUdp::write(const std::vector<ColorRgb> & ledValues)
|
||||
udpbuffer[udpPtr++] = ledCtr%256; // low byte
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
41
libsrc/leddevice/LedDeviceUdpRaw.cpp
Normal file
41
libsrc/leddevice/LedDeviceUdpRaw.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
// STL includes
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
// Linux includes
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
// 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<ColorRgb> &ledValues)
|
||||
{
|
||||
mLedCount = ledValues.size();
|
||||
|
||||
const unsigned dataLen = ledValues.size() * sizeof(ColorRgb);
|
||||
const uint8_t * dataPtr = reinterpret_cast<const uint8_t *>(ledValues.data());
|
||||
|
||||
return writeBytes(dataLen, dataPtr);
|
||||
}
|
||||
|
||||
int LedDeviceUdpRaw::switchOff()
|
||||
{
|
||||
return write(std::vector<ColorRgb>(mLedCount, ColorRgb{0,0,0}));
|
||||
}
|
43
libsrc/leddevice/LedDeviceUdpRaw.h
Normal file
43
libsrc/leddevice/LedDeviceUdpRaw.h
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
// STL includes
|
||||
#include <string>
|
||||
|
||||
// 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<ColorRgb> &ledValues);
|
||||
|
||||
/// Switch the leds off
|
||||
virtual int switchOff();
|
||||
|
||||
private:
|
||||
|
||||
/// the number of leds (needed when switching off)
|
||||
size_t mLedCount;
|
||||
};
|
@ -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;
|
||||
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<ColorRgb> &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;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user