mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Merge pull request #4 from tvdzwan/master
Updating Former-commit-id: f2babbeab3f8dd80e92b37be5fd0c25c1b45a76b
This commit is contained in:
commit
9d01c84494
@ -91,9 +91,6 @@ include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
# Prefer static linking over dynamic
|
||||
#set(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so")
|
||||
|
||||
set(CMAKE_BUILD_TYPE "Debug")
|
||||
#set(CMAKE_BUILD_TYPE "Release")
|
||||
|
||||
# enable C++11
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall")
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -std=c++11 -Wall")
|
||||
|
@ -24,11 +24,11 @@ mkdir "$HYPERION_DIR/build"
|
||||
cd "$HYPERION_DIR/build"
|
||||
|
||||
# run cmake to generate make files on the raspberry pi
|
||||
cmake ..
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -Wno-dev ..
|
||||
# or if you are not compiling on the raspberry pi and need to disable the Dispmanx grabber and support for spi devices
|
||||
cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_X11=ON ..
|
||||
cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_X11=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev ..
|
||||
# as an alternative for the dispmanx grabber on non-rpi devices (e.g. cubox-i) you could try the framebuffer grabber
|
||||
cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_FB=ON ..
|
||||
cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_FB=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev ..
|
||||
# for OSX build you need XCode, qt4 libraries and cmake. You can use macport (homebrew might work too) to install them
|
||||
sudo port install qt4-mac
|
||||
sudo port install cmake
|
||||
@ -36,6 +36,12 @@ cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_V4L2=OFF -DENABLE_OSX=O
|
||||
|
||||
# run make to build Hyperion
|
||||
make
|
||||
# or if you have a system with more then 1 cpu core
|
||||
make -j 4
|
||||
# "4" is the number of cpu cores (e.g. 4 on RPi2), this makes compile faster
|
||||
|
||||
#after compile, to remove any stuff not needed for a release version.
|
||||
strip bin/*
|
||||
|
||||
# The binaries are build in "$HYPERION_DIR/build/bin". You could copy those to /usr/bin
|
||||
sudo cp ./bin/hyperion-remote /usr/bin/
|
||||
|
@ -24,6 +24,8 @@ tar --create --verbose --gzip --absolute-names --show-transformed-names --ignore
|
||||
--transform "s:$repodir/effects/:hyperion/effects/:" \
|
||||
--transform "s:$repodir/config/:hyperion/config/:" \
|
||||
--transform "s:$repodir/bin/hyperion.init.sh:hyperion/init.d/hyperion.init.sh:" \
|
||||
--transform "s:$repodir/bin/hyperion.systemd.sh:hyperion/init.d/hyperion.systemd.sh:" \
|
||||
--transform "s:$repodir/bin/hyperion.initctl.sh:hyperion/init.d/hyperion.initctl.sh:" \
|
||||
--transform "s://:/:g" \
|
||||
"$builddir/bin/hyperiond" \
|
||||
"$builddir/bin/hyperion-remote" \
|
||||
@ -32,5 +34,7 @@ tar --create --verbose --gzip --absolute-names --show-transformed-names --ignore
|
||||
"$builddir/bin/dispmanx2png" \
|
||||
"$repodir/effects/"* \
|
||||
"$repodir/bin/hyperion.init.sh" \
|
||||
"$repodir/bin/hyperion.systemd.sh" \
|
||||
"$repodir/bin/hyperion.initctl.sh" \
|
||||
"$repodir/config/hyperion.config.json"
|
||||
|
||||
|
@ -1,7 +1,16 @@
|
||||
#!/bin/bash
|
||||
# Hyperion daemon
|
||||
# Hyperion daemon service
|
||||
# description: Hyperion daemon
|
||||
# processname: hyperiond
|
||||
### BEGIN INIT INFO
|
||||
# Provides: Hyperion
|
||||
# Required-Start: $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Hyperion Ambilight init.d Service.
|
||||
# Description: Hyperion Ambilight init.d Service.
|
||||
### END INIT INFO
|
||||
|
||||
DAEMON=hyperiond
|
||||
DAEMONOPTS="/etc/hyperion.config.json"
|
||||
|
17
bin/hyperion.initctl.sh
Normal file
17
bin/hyperion.initctl.sh
Normal file
@ -0,0 +1,17 @@
|
||||
## Hyperion daemon initctl script
|
||||
|
||||
description "hyperion"
|
||||
author "poljvd & tvdzwan"
|
||||
|
||||
start on (runlevel [2345])
|
||||
stop on (runlevel [!2345])
|
||||
|
||||
respawn
|
||||
|
||||
pre-start script
|
||||
#comment out the following 2 lines for x32/64
|
||||
modprobe spidev
|
||||
/usr/bin/gpio2spi
|
||||
end script
|
||||
|
||||
exec /usr/bin/hyperiond /etc/hyperion.config.json
|
15
bin/hyperion.systemd.sh
Normal file
15
bin/hyperion.systemd.sh
Normal file
@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=Hyperion Systemd service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
Group=root
|
||||
UMask=007
|
||||
ExecStart=/opt/hyperion/bin/hyperiond /etc/hyperion.config.json
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
Restart=on-failure
|
||||
TimeoutStopSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
105
bin/remove_hyperion.sh
Normal file
105
bin/remove_hyperion.sh
Normal file
@ -0,0 +1,105 @@
|
||||
#!/bin/sh
|
||||
# Script to remove Hyperion and all services
|
||||
|
||||
# Make sure /sbin is on the path (for service to find sub scripts)
|
||||
PATH="/sbin:$PATH"
|
||||
|
||||
#Check if HyperCon is logged in as root
|
||||
if [ $(id -u) != 0 ] && [ "$1" = "HyperConRemove" ]; then
|
||||
echo '---> Critical Error: Please connect as user "root" through HyperCon'
|
||||
echo '---> We need admin privileges to remove your Hyperion! -> abort'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#Check, if script is running as root
|
||||
if [ $(id -u) != 0 ]; then
|
||||
echo '---> Critical Error: Please run the script as root (sudo sh ./remove_hyperion.sh)'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#Welcome message
|
||||
echo '*******************************************************************************'
|
||||
echo 'This script will remove Hyperion and it´s services'
|
||||
echo '-----> Please BACKUP your hyperion.config.json if necessary <-----'
|
||||
echo '*******************************************************************************'
|
||||
|
||||
#Skip the prompt if HyperCon Remove
|
||||
if [ "$1" = "" ]; then
|
||||
#Prompt for confirmation to proceed
|
||||
while true
|
||||
do
|
||||
echo -n "---> Do you really want to remove Hyperion and it´s services? (y or n) :"
|
||||
read CONFIRM
|
||||
case $CONFIRM in
|
||||
y|Y|YES|yes|Yes) break ;;
|
||||
n|N|no|NO|No)
|
||||
echo "---> Aborting - you entered \"$CONFIRM\""
|
||||
exit
|
||||
;;
|
||||
*) echo "-> Please enter only y or n"
|
||||
esac
|
||||
done
|
||||
echo "---> You entered \"$CONFIRM\". Remove Hyperion!"
|
||||
fi
|
||||
# Find out if we are on OpenElec
|
||||
OS_OPENELEC=`grep -m1 -c OpenELEC /etc/issue`
|
||||
|
||||
# check which init script we should use
|
||||
USE_SYSTEMD=`grep -m1 -c systemd /proc/1/comm`
|
||||
USE_INITCTL=`which /sbin/initctl | wc -l`
|
||||
USE_SERVICE=`which /usr/sbin/service | wc -l`
|
||||
|
||||
# Stop hyperion daemon if it is running
|
||||
echo '---> Stop Hyperion, if necessary'
|
||||
if [ $OS_OPENELEC -eq 1 ]; then
|
||||
killall hyperiond 2>/dev/null
|
||||
elif [ $USE_INITCTL -eq 1 ]; then
|
||||
/sbin/initctl stop hyperion 2>/dev/null
|
||||
elif [ $USE_SERVICE -eq 1 ]; then
|
||||
/usr/sbin/service hyperion stop 2>/dev/null
|
||||
elif [ $USE_SYSTEMD -eq 1 ]; then
|
||||
service hyperion stop 2>/dev/null
|
||||
fi
|
||||
|
||||
#Disabling and delete service files
|
||||
if [ $USE_INITCTL -eq 1 ]; then
|
||||
echo '---> Delete and disable Hyperion initctl script'
|
||||
rm -v /etc/init/hyperion 2>/dev/null
|
||||
initctl reload-configuration
|
||||
elif [ $OS_OPENELEC -eq 1 ]; then
|
||||
# Remove Hyperion from OpenELEC autostart.sh
|
||||
echo "---> Remove Hyperion from OpenELEC autostart.sh"
|
||||
sed -i "/hyperiond/d" /storage/.config/autostart.sh 2>/dev/null
|
||||
elif [ $USE_SYSTEMD -eq 1 ]; then
|
||||
# Delete and disable Hyperion systemd script
|
||||
echo '---> Delete and disable Hyperion systemd script'
|
||||
systemctl disable hyperion.service
|
||||
rm -v /etc/systemd/system/hyperion.service 2>/dev/null
|
||||
elif [ $USE_SERVICE -eq 1 ]; then
|
||||
# Delete and disable Hyperion init.d script
|
||||
echo '---> Delete and disable Hyperion init.d script'
|
||||
update-rc.d -f hyperion remove
|
||||
rm /etc/init.d/hyperion 2>/dev/null
|
||||
fi
|
||||
|
||||
# Delete Hyperion binaries
|
||||
if [ $OS_OPENELEC -eq 1 ]; then
|
||||
# Remove OpenELEC Hyperion binaries and configs
|
||||
echo '---> Remove the OpenELEC Hyperion binaries and hyperion.config.json'
|
||||
rm -rv /storage/hyperion 2>/dev/null
|
||||
rm -v /storage/.config/hyperion.config.json 2>/dev/null
|
||||
else
|
||||
#Remove binaries on all distributions/systems (not OpenELEC)
|
||||
echo "---> Remove links to the binaries"
|
||||
rm -v /usr/bin/hyperiond 2>/dev/null
|
||||
rm -v /usr/bin/hyperion-remote 2>/dev/null
|
||||
rm -v /usr/bin/hyperion-v4l2 2>/dev/null
|
||||
rm -v /etc/hyperion.config.json 2>/dev/null
|
||||
echo "---> Remove binaries"
|
||||
rm -rv /opt/hyperion 2>/dev/null
|
||||
fi
|
||||
echo '*******************************************************************************'
|
||||
echo 'Hyperion successful removed!'
|
||||
echo '*******************************************************************************'
|
||||
exit 0
|
||||
|
@ -4,22 +4,16 @@
|
||||
{
|
||||
/// Device configuration contains the following fields:
|
||||
/// * 'name' : The user friendly name of the device (only used for display purposes)
|
||||
/// * 'type' : The type of the device or leds (known types for now are 'ws2801', 'ldp8806',
|
||||
/// 'lpd6803', 'sedu', 'adalight', 'lightpack', 'philipshue', 'test' and 'none')
|
||||
/// * 'output' : The output specification depends on selected device. This can for example be the
|
||||
/// device specifier, device serial number, or the output file name
|
||||
/// * 'rate' : The baudrate of the output to the device
|
||||
/// * 'type' : The type of the device or leds (known types for now are
|
||||
/// APA102, Adalight, AmbiLed, Atmo, Hyperion-USBASP-WS2801, Hyperion-USBASP-WS2812, Lightberry, Lightpack, LPD6803, LPD8806, Multi-Lightpack, P9813, Paintpack, PhilipsHUE, PiBlaster, SEDU, Test, ThinkerForge, TPM2, WS2801, WS2812b, None)
|
||||
/// * [device type specific configuration]
|
||||
/// * 'colorOrder' : The order of the color bytes ('rgb', 'rbg', 'bgr', etc.).
|
||||
/// Specific of Philips Hue:
|
||||
/// * 'username' : The name of user registred on the Philips Hue Bridge
|
||||
/// * 'switchOffOnBlack' : Define if Hue light switch off when black is detected
|
||||
/// * 'transitiontime' : Set the time of transition between color of Hue light
|
||||
"device" :
|
||||
{
|
||||
"name" : "MyPi",
|
||||
"type" : "ws2801",
|
||||
"output" : "/dev/spidev0.0",
|
||||
"rate" : 250000,
|
||||
"rate" : 1000000,
|
||||
"colorOrder" : "rgb"
|
||||
},
|
||||
|
||||
@ -45,6 +39,7 @@
|
||||
/// - 'type' The type of smoothing algorithm ('linear' or 'none')
|
||||
/// - 'time_ms' The time constant for smoothing algorithm in milliseconds
|
||||
/// - 'updateFrequency' The update frequency of the leds in Hz
|
||||
/// - 'updateDelay' The delay of the output to leds (in periods of smoothing)
|
||||
"color" :
|
||||
{
|
||||
"transform" :
|
||||
@ -82,13 +77,156 @@
|
||||
],
|
||||
"smoothing" :
|
||||
{
|
||||
"type" : "none",
|
||||
"type" : "linear",
|
||||
"time_ms" : 200,
|
||||
"updateFrequency" : 20.0000,
|
||||
"updateDelay" : 0
|
||||
}
|
||||
},
|
||||
|
||||
/// The black border configuration, contains the following items:
|
||||
/// * enable : true if the detector should be activated
|
||||
/// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0)
|
||||
/// * unknownFrameCnt : Number of frames without any detection before the border is set to 0 (default 600)
|
||||
/// * borderFrameCnt : Number of frames before a consistent detected border gets set (default 50)
|
||||
/// * maxInconsistentCnt : Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency
|
||||
/// * blurRemoveCnt : Number of pixels that get removed from the detected border to cut away blur (default 1)
|
||||
/// * mode : Border detection mode (values=default,classic,osd)
|
||||
"blackborderdetector" :
|
||||
{
|
||||
"enable" : true,
|
||||
"threshold" : 0.0,
|
||||
"unknownFrameCnt" : 600,
|
||||
"borderFrameCnt" : 50,
|
||||
"maxInconsistentCnt" : 10,
|
||||
"blurRemoveCnt" : 1,
|
||||
"mode" : "default"
|
||||
},
|
||||
|
||||
/// The configuration of the effect engine, contains the following items:
|
||||
/// * paths : An array with absolute location(s) of directories with effects
|
||||
/// * color : Set static color after boot -> set effect to "" (empty) and input the values [R,G,B] and set duration_ms NOT to 0 (use 1) instead
|
||||
/// * effect : The effect selected as 'boot sequence'
|
||||
/// * duration_ms : The duration of the selected effect (0=endless)
|
||||
/// * priority : The priority of the selected effect/static color (default=0)
|
||||
"effects" :
|
||||
{
|
||||
"paths" :
|
||||
[
|
||||
"/opt/hyperion/effects"
|
||||
]
|
||||
},
|
||||
|
||||
"bootsequence" :
|
||||
{
|
||||
"color" : [0,0,0],
|
||||
"effect" : "Rainbow swirl fast",
|
||||
"duration_ms" : 3000,
|
||||
"priority" : 990
|
||||
},
|
||||
|
||||
/// The configuration of the Json/Proto forwarder. Forward messages to multiple instances of Hyperion on same and/or other hosts
|
||||
/// 'proto' is mostly used for video streams and 'json' for effects
|
||||
/// * proto : Proto server adress and port of your target. Syntax:[IP:PORT] -> ["127.0.0.1:19447"] or more instances to forward ["127.0.0.1:19447","192.168.0.24:19449"]
|
||||
/// * json : Json server adress and port of your target. Syntax:[IP:PORT] -> ["127.0.0.1:19446"] or more instances to forward ["127.0.0.1:19446","192.168.0.24:19448"]
|
||||
/// HINT: If you redirect to "127.0.0.1" (localhost) you could start a second hyperion with another device/led config!
|
||||
/// Be sure your client(s) is/are listening on the configured ports. The second Hyperion (if used) also needs to be configured! (HyperCon -> External -> Json Server/Proto Server)
|
||||
// "forwarder" :
|
||||
// {
|
||||
// "proto" : ["127.0.0.1:19447"],
|
||||
// "json" : ["127.0.0.1:19446"]
|
||||
// },
|
||||
|
||||
/// The configuration for the frame-grabber, contains the following items:
|
||||
/// * width : The width of the grabbed frames [pixels]
|
||||
/// * height : The height of the grabbed frames [pixels]
|
||||
/// * frequency_Hz : The frequency of the frame grab [Hz]
|
||||
"framegrabber" :
|
||||
{
|
||||
"width" : 80,
|
||||
"height" : 45,
|
||||
"frequency_Hz" : 10.0
|
||||
},
|
||||
|
||||
/// The configuration of the Kodi connection used to enable and disable the frame-grabber. Contains the following fields:
|
||||
/// * xbmcAddress : The IP address of the Kodi-host
|
||||
/// * xbmcTcpPort : The TCP-port of the Kodi-server
|
||||
/// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback
|
||||
/// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show
|
||||
/// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback
|
||||
/// * grabMenu : Flag indicating that the frame-grabber is on(true) at the Kodi menu
|
||||
/// * grabScreensaver : Flag indicating that the frame-grabber is on(true) when Kodi is on screensaver
|
||||
/// * enable3DDetection : Flag indicating that the frame-grabber should switch to a 3D compatible modus if a 3D video is playing
|
||||
// "xbmcVideoChecker" :
|
||||
// {
|
||||
// "xbmcAddress" : "127.0.0.1",
|
||||
// "xbmcTcpPort" : 9090,
|
||||
// "grabVideo" : true,
|
||||
// "grabPictures" : true,
|
||||
// "grabAudio" : true,
|
||||
// "grabMenu" : false,
|
||||
// "grabScreensaver" : true,
|
||||
// "enable3DDetection" : true
|
||||
// },
|
||||
|
||||
/// The configuration of the Json server which enables the json remote interface
|
||||
/// * port : Port at which the json server is started
|
||||
"jsonServer" :
|
||||
{
|
||||
"port" : 19444
|
||||
},
|
||||
|
||||
/// The configuration of the Proto server which enables the protobuffer remote interface
|
||||
/// * port : Port at which the protobuffer server is started
|
||||
"protoServer" :
|
||||
{
|
||||
"port" : 19445
|
||||
},
|
||||
|
||||
/// The configuration of the boblight server which enables the boblight remote interface
|
||||
/// * port : Port at which the boblight server is started
|
||||
// "boblightServer" :
|
||||
// {
|
||||
// "port" : 19333
|
||||
// },
|
||||
|
||||
/// Configuration for the embedded V4L2 grabber
|
||||
/// * device : V4L2 Device to use [default="/dev/video0"]
|
||||
/// * input : V4L2 input to use [default=0]
|
||||
/// * standard : Video standard (no-change/PAL/NTSC) [default="no-change"]
|
||||
/// * width : V4L2 width to set [default=-1]
|
||||
/// * height : V4L2 height to set [default=-1]
|
||||
/// * frameDecimation : Frame decimation factor [default=2]
|
||||
/// * sizeDecimation : Size decimation factor [default=8]
|
||||
/// * priority : Hyperion priority channel [default=800]
|
||||
/// * mode : 3D mode to use 2D/3DSBS/3DTAB (note: no autodetection) [default="2D"]
|
||||
/// * cropLeft : Cropping from the left [default=0]
|
||||
/// * cropRight : Cropping from the right [default=0]
|
||||
/// * cropTop : Cropping from the top [default=0]
|
||||
/// * cropBottom : Cropping from the bottom [default=0]
|
||||
/// * redSignalThreshold : Signal threshold for the red channel between 0.0 and 1.0 [default=0.0]
|
||||
/// * greenSignalThreshold : Signal threshold for the green channel between 0.0 and 1.0 [default=0.0]
|
||||
/// * blueSignalThreshold : Signal threshold for the blue channel between 0.0 and 1.0 [default=0.0]
|
||||
// "grabber-v4l2" :
|
||||
// {
|
||||
// "device" : "/dev/video0",
|
||||
// "input" : 0,
|
||||
// "standard" : "no-change",
|
||||
// "width" : -1,
|
||||
// "height" : -1,
|
||||
// "frameDecimation" : 2,
|
||||
// "sizeDecimation" : 8,
|
||||
// "priority" : 800,
|
||||
// "mode" : "2D",
|
||||
// "cropLeft" : 0,
|
||||
// "cropRight" : 0,
|
||||
// "cropTop" : 0,
|
||||
// "cropBottom" : 0,
|
||||
// "redSignalThreshold" : 0.0,
|
||||
// "greenSignalThreshold" : 0.0,
|
||||
// "blueSignalThreshold" : 0.0
|
||||
// },
|
||||
|
||||
/// The configuration for each individual led. This contains the specification of the area
|
||||
/// averaged of an input image for each led to determine its color. Each item in the list
|
||||
/// contains the following fields:
|
||||
@ -102,47 +240,47 @@
|
||||
[
|
||||
{
|
||||
"index" : 0,
|
||||
"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 },
|
||||
"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 1,
|
||||
"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 },
|
||||
"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 2,
|
||||
"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 },
|
||||
"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 3,
|
||||
"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 },
|
||||
"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 4,
|
||||
"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 },
|
||||
"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 5,
|
||||
"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 },
|
||||
"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 6,
|
||||
"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 },
|
||||
"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 7,
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 },
|
||||
"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 8,
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
@ -182,271 +320,155 @@
|
||||
},
|
||||
{
|
||||
"index" : 16,
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 17,
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 18,
|
||||
"index" : 17,
|
||||
"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 19,
|
||||
"index" : 18,
|
||||
"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 20,
|
||||
"index" : 19,
|
||||
"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 21,
|
||||
"index" : 20,
|
||||
"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 22,
|
||||
"index" : 21,
|
||||
"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 23,
|
||||
"index" : 22,
|
||||
"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 24,
|
||||
"index" : 23,
|
||||
"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 25,
|
||||
"index" : 24,
|
||||
"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 25,
|
||||
"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 26,
|
||||
"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 },
|
||||
"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 27,
|
||||
"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 },
|
||||
"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 28,
|
||||
"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 },
|
||||
"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 29,
|
||||
"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 },
|
||||
"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 30,
|
||||
"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 },
|
||||
"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 31,
|
||||
"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 },
|
||||
"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 32,
|
||||
"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 33,
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 34,
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 }
|
||||
},
|
||||
{
|
||||
"index" : 35,
|
||||
"index" : 33,
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 }
|
||||
},
|
||||
{
|
||||
"index" : 36,
|
||||
"index" : 34,
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 }
|
||||
},
|
||||
{
|
||||
"index" : 37,
|
||||
"index" : 35,
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 }
|
||||
},
|
||||
{
|
||||
"index" : 38,
|
||||
"index" : 36,
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 }
|
||||
},
|
||||
{
|
||||
"index" : 39,
|
||||
"index" : 37,
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 }
|
||||
},
|
||||
{
|
||||
"index" : 40,
|
||||
"index" : 38,
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 41,
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 42,
|
||||
"index" : 39,
|
||||
"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 43,
|
||||
"index" : 40,
|
||||
"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 44,
|
||||
"index" : 41,
|
||||
"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 45,
|
||||
"index" : 42,
|
||||
"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 46,
|
||||
"index" : 43,
|
||||
"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 47,
|
||||
"index" : 44,
|
||||
"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 48,
|
||||
"index" : 45,
|
||||
"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 49,
|
||||
"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
}
|
||||
],
|
||||
|
||||
/// The black border configuration, contains the following items:
|
||||
/// * enable : true if the detector should be activated
|
||||
/// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0)
|
||||
/// * unknownFrameCnt : Number of frames without any detection before the border is set to 0 (default 600) - optional
|
||||
/// * borderFrameCnt : Number of frames before a consistent detected border gets set (default 50) - optional
|
||||
/// * maxInconsistentCnt : Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency - optional
|
||||
/// * blurRemoveCnt : Number of pixels that get removed from the detected border to cut away blur (default 1) - optional
|
||||
/// * mode : Border detection mode (values "default","classic","osd") - optional
|
||||
|
||||
"blackborderdetector" :
|
||||
{
|
||||
"enable" : true,
|
||||
"threshold" : 0.01,
|
||||
"unknownFrameCnt": 600,
|
||||
"borderFrameCnt" : 50,
|
||||
"maxInconsistentCnt" : 10,
|
||||
"blurRemoveCnt": 1,
|
||||
"mode" : "default"
|
||||
},
|
||||
|
||||
/// The configuration of the effect engine, contains the following items:
|
||||
/// * paths : An array with absolute location(s) of directories with effects
|
||||
/// * bootsequence : The effect selected as 'boot sequence'
|
||||
/// * effect : name of the effect you want to start. Set to empty if no effect wanted
|
||||
/// * color : switch to static color after effect is done
|
||||
/// * duration_ms : duration of boot effect in ms. 0 means effect stays forever
|
||||
/// * priority : priority of boot effect and static color
|
||||
"effects" :
|
||||
{
|
||||
"paths" :
|
||||
[
|
||||
"/opt/hyperion/effects"
|
||||
]
|
||||
},
|
||||
|
||||
"bootsequence" :
|
||||
{
|
||||
"color" : [0,0,0],
|
||||
"effect" : "Rainbow swirl fast",
|
||||
"duration_ms" : 3000,
|
||||
"priority" : 0
|
||||
},
|
||||
|
||||
/// The configuration for the frame-grabber, contains the following items:
|
||||
/// * width : The width of the grabbed frames [pixels]
|
||||
/// * height : The height of the grabbed frames [pixels]
|
||||
/// * frequency_Hz : The frequency of the frame grab [Hz]
|
||||
"framegrabber" :
|
||||
{
|
||||
"width" : 64,
|
||||
"height" : 64,
|
||||
"frequency_Hz" : 10.0
|
||||
},
|
||||
|
||||
/// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields:
|
||||
/// * xbmcAddress : The IP address of the XBMC-host
|
||||
/// * xbmcTcpPort : The TCP-port of the XBMC-server
|
||||
/// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback
|
||||
/// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show
|
||||
/// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback
|
||||
/// * grabMenu : Flag indicating that the frame-grabber is on(true) in the XBMC menu
|
||||
/// * grabScreensaver : Flag indicating that the frame-grabber is on(true) when XBMC is on screensaver
|
||||
/// * enable3DDetection : Flag indicating that the frame-grabber should switch to a 3D compatible modus if a 3D video is playing
|
||||
"xbmcVideoChecker" :
|
||||
{
|
||||
"xbmcAddress" : "127.0.0.1",
|
||||
"xbmcTcpPort" : 9090,
|
||||
"grabVideo" : true,
|
||||
"grabPictures" : true,
|
||||
"grabAudio" : true,
|
||||
"grabMenu" : false,
|
||||
"grabScreensaver" : true,
|
||||
"enable3DDetection" : true
|
||||
},
|
||||
|
||||
/// The configuration of the Json server which enables the json remote interface
|
||||
/// * port : Port at which the json server is started
|
||||
"jsonServer" :
|
||||
{
|
||||
"port" : 19444
|
||||
},
|
||||
|
||||
/// The configuration of the Proto server which enables the protobuffer remote interface
|
||||
/// * port : Port at which the protobuffer server is started
|
||||
"protoServer" :
|
||||
{
|
||||
"port" : 19445
|
||||
},
|
||||
|
||||
/// The configuration of the boblight server which enables the boblight remote interface
|
||||
/// * port : Port at which the boblight server is started
|
||||
// "boblightServer" :
|
||||
// {
|
||||
// "port" : 19333
|
||||
// },
|
||||
|
||||
"endOfJson" : "endOfJson"
|
||||
}
|
||||
|
@ -19,6 +19,21 @@
|
||||
"colorOrder" : "rgb"
|
||||
},
|
||||
|
||||
/// Configuration for message forwarding to other hyperions
|
||||
/// protobuffer and json remote interface are forwarded to configured hosts
|
||||
/// 'proto' is mostly used for video streams and 'json' for effects
|
||||
///
|
||||
/// ** pay attention which port you use. use correct ports for protols **
|
||||
///
|
||||
/// * 'proto' : list of host in form of <ip>:<port>
|
||||
/// * 'json' : list of host in form of <ip>:<port>
|
||||
/// "forwarder" :
|
||||
/// {
|
||||
/// "proto" : [ "127.0.0.1:19445","192.168.178.88:19445" ],
|
||||
/// "json" : [ "127.0.0.1:19444","192.168.178.88:19444" ]
|
||||
/// },
|
||||
|
||||
|
||||
/// Color manipulation configuration used to tune the output colors to specific surroundings.
|
||||
/// The configuration contains a list of color-transforms. Each transform contains the
|
||||
/// following fields:
|
||||
|
10
effects/cinema-fade-in.json
Normal file
10
effects/cinema-fade-in.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name" : "Cinema brighten lights",
|
||||
"script" : "fade.py",
|
||||
"args" :
|
||||
{
|
||||
"fade-time" : 5.0,
|
||||
"color-start" : [ 136, 97, 7 ],
|
||||
"color-end" : [ 238, 173, 47 ]
|
||||
}
|
||||
}
|
10
effects/cinema-fade-off.json
Normal file
10
effects/cinema-fade-off.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name" : "Cinema dim lights",
|
||||
"script" : "fade.py",
|
||||
"args" :
|
||||
{
|
||||
"fade-time" : 5.0,
|
||||
"color-start" : [ 238, 173, 47 ],
|
||||
"color-end" : [ 136, 97, 7 ]
|
||||
}
|
||||
}
|
27
effects/fade.py
Normal file
27
effects/fade.py
Normal file
@ -0,0 +1,27 @@
|
||||
import hyperion, time
|
||||
|
||||
# Get the parameters
|
||||
fadeTime = float(hyperion.args.get('fade-time', 5.0))
|
||||
colorStart = hyperion.args.get('color-start', (255,174,11))
|
||||
colorEnd = hyperion.args.get('color-end', (100,100,100))
|
||||
|
||||
color_step = (
|
||||
(colorEnd[0] - colorStart[0]) / 256.0,
|
||||
(colorEnd[1] - colorStart[1]) / 256.0,
|
||||
(colorEnd[2] - colorStart[2]) / 256.0
|
||||
)
|
||||
|
||||
# fade color
|
||||
calcChannel = lambda i: min(max(int(colorStart[i] + color_step[i]*step),0),255)
|
||||
for step in range(256):
|
||||
if hyperion.abort():
|
||||
break
|
||||
|
||||
hyperion.setColor( calcChannel(0),calcChannel(1),calcChannel(2) )
|
||||
time.sleep( fadeTime / 256 )
|
||||
|
||||
# maintain color until effect end
|
||||
hyperion.setColor(colorEnd[0],colorEnd[1],colorEnd[2])
|
||||
while not hyperion.abort():
|
||||
time.sleep(1)
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"name" : "Knight rider",
|
||||
"script" : "knight-rider.py",
|
||||
"args" :
|
||||
{
|
||||
"speed" : 1.0,
|
||||
"fadeFactor" : 0.7,
|
||||
"color" : [255,0,0]
|
||||
}
|
||||
}
|
||||
{
|
||||
"name" : "Knight rider",
|
||||
"script" : "knight-rider.py",
|
||||
"args" :
|
||||
{
|
||||
"speed" : 1.0,
|
||||
"fadeFactor" : 0.7,
|
||||
"color" : [255,0,0]
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name" : "Blue mood blobs",
|
||||
"script" : "mood-blobs.py",
|
||||
"args" :
|
||||
{
|
||||
"rotationTime" : 60.0,
|
||||
"color" : [0,0,255],
|
||||
"hueChange" : 60.0,
|
||||
"blobs" : 5,
|
||||
"reverse" : false
|
||||
}
|
||||
}
|
||||
{
|
||||
"name" : "Blue mood blobs",
|
||||
"script" : "mood-blobs.py",
|
||||
"args" :
|
||||
{
|
||||
"rotationTime" : 60.0,
|
||||
"color" : [0,0,255],
|
||||
"hueChange" : 60.0,
|
||||
"blobs" : 5,
|
||||
"reverse" : false
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name" : "Green mood blobs",
|
||||
"script" : "mood-blobs.py",
|
||||
"args" :
|
||||
{
|
||||
"rotationTime" : 60.0,
|
||||
"color" : [0,255,0],
|
||||
"hueChange" : 60.0,
|
||||
"blobs" : 5,
|
||||
"reverse" : false
|
||||
}
|
||||
}
|
||||
{
|
||||
"name" : "Green mood blobs",
|
||||
"script" : "mood-blobs.py",
|
||||
"args" :
|
||||
{
|
||||
"rotationTime" : 60.0,
|
||||
"color" : [0,255,0],
|
||||
"hueChange" : 60.0,
|
||||
"blobs" : 5,
|
||||
"reverse" : false
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name" : "Red mood blobs",
|
||||
"script" : "mood-blobs.py",
|
||||
"args" :
|
||||
{
|
||||
"rotationTime" : 60.0,
|
||||
"color" : [255,0,0],
|
||||
"hueChange" : 60.0,
|
||||
"blobs" : 5,
|
||||
"reverse" : false
|
||||
}
|
||||
}
|
||||
{
|
||||
"name" : "Red mood blobs",
|
||||
"script" : "mood-blobs.py",
|
||||
"args" :
|
||||
{
|
||||
"rotationTime" : 60.0,
|
||||
"color" : [255,0,0],
|
||||
"hueChange" : 60.0,
|
||||
"blobs" : 5,
|
||||
"reverse" : false
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"name" : "Rainbow mood",
|
||||
"script" : "rainbow-mood.py",
|
||||
"args" :
|
||||
{
|
||||
"rotation-time" : 60.0,
|
||||
"brightness" : 1.0,
|
||||
"reverse" : false
|
||||
}
|
||||
}
|
||||
{
|
||||
"name" : "Rainbow mood",
|
||||
"script" : "rainbow-mood.py",
|
||||
"args" :
|
||||
{
|
||||
"rotation-time" : 60.0,
|
||||
"brightness" : 1.0,
|
||||
"reverse" : false
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"name" : "Rainbow swirl fast",
|
||||
"script" : "rainbow-swirl.py",
|
||||
"args" :
|
||||
{
|
||||
"rotation-time" : 3.0,
|
||||
"brightness" : 1.0,
|
||||
"reverse" : false
|
||||
}
|
||||
}
|
||||
{
|
||||
"name" : "Rainbow swirl fast",
|
||||
"script" : "rainbow-swirl.py",
|
||||
"args" :
|
||||
{
|
||||
"rotation-time" : 3.0,
|
||||
"brightness" : 1.0,
|
||||
"reverse" : false
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"name" : "Rainbow swirl",
|
||||
"script" : "rainbow-swirl.py",
|
||||
"args" :
|
||||
{
|
||||
"rotation-time" : 20.0,
|
||||
"brightness" : 1.0,
|
||||
"reverse" : false
|
||||
}
|
||||
}
|
||||
{
|
||||
"name" : "Rainbow swirl",
|
||||
"script" : "rainbow-swirl.py",
|
||||
"args" :
|
||||
{
|
||||
"rotation-time" : 20.0,
|
||||
"brightness" : 1.0,
|
||||
"reverse" : false
|
||||
}
|
||||
}
|
||||
|
9
effects/random.json
Normal file
9
effects/random.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name" : "Random",
|
||||
"script" : "random.py",
|
||||
"args" :
|
||||
{
|
||||
"speed" : 1.0,
|
||||
"saturation" : 1.0
|
||||
}
|
||||
}
|
21
effects/random.py
Normal file
21
effects/random.py
Normal file
@ -0,0 +1,21 @@
|
||||
import hyperion, time, colorsys, random
|
||||
|
||||
# get args
|
||||
sleepTime = float(hyperion.args.get('speed', 1.0))
|
||||
saturation = float(hyperion.args.get('saturation', 1.0))
|
||||
ledData = bytearray()
|
||||
|
||||
# Initialize the led data
|
||||
for i in range(hyperion.ledCount):
|
||||
ledData += bytearray((0,0,0))
|
||||
|
||||
# Start the write data loop
|
||||
while not hyperion.abort():
|
||||
hyperion.setColor(ledData)
|
||||
for i in range(hyperion.ledCount):
|
||||
if random.randrange(10) == 1:
|
||||
rgb = colorsys.hsv_to_rgb(random.random(), saturation, random.random())
|
||||
ledData[i*3 ] = int(255*rgb[0])
|
||||
ledData[i*3+1] = int(255*rgb[1])
|
||||
ledData[i*3+2] = int(255*rgb[2])
|
||||
time.sleep(sleepTime)
|
10
effects/running_dots.json
Normal file
10
effects/running_dots.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name" : "Running dots",
|
||||
"script" : "running_dots.py",
|
||||
"args" :
|
||||
{
|
||||
"speed" : 1.5,
|
||||
"whiteLevel" : 100,
|
||||
"colorLevel" : 230
|
||||
}
|
||||
}
|
43
effects/running_dots.py
Normal file
43
effects/running_dots.py
Normal file
@ -0,0 +1,43 @@
|
||||
import hyperion, time, colorsys, random
|
||||
|
||||
# get options from args
|
||||
sleepTime = float(hyperion.args.get('speed', 1.5)) * 0.005
|
||||
whiteLevel = int(hyperion.args.get('whiteLevel', 0))
|
||||
lvl = int(hyperion.args.get('colorLevel', 220))
|
||||
|
||||
# check value
|
||||
whiteLevel = min( whiteLevel, 254 )
|
||||
lvl = min( lvl, 255 )
|
||||
|
||||
if whiteLevel >= lvl:
|
||||
lvl = 255
|
||||
|
||||
# Initialize the led data
|
||||
ledData = bytearray()
|
||||
for i in range(hyperion.ledCount):
|
||||
ledData += bytearray((0,0,0))
|
||||
|
||||
runners = [
|
||||
{ "pos":0, "step": 4, "lvl":lvl},
|
||||
{ "pos":1, "step": 5, "lvl":lvl},
|
||||
{ "pos":2, "step": 6, "lvl":lvl},
|
||||
{ "pos":0, "step": 7, "lvl":lvl},
|
||||
{ "pos":1, "step": 8, "lvl":lvl},
|
||||
{ "pos":2, "step": 9, "lvl":lvl},
|
||||
#{ "pos":0, "step":10, "lvl":lvl},
|
||||
#{ "pos":1, "step":11, "lvl":lvl},
|
||||
#{ "pos":2, "step":12, "lvl":lvl},
|
||||
]
|
||||
|
||||
# Start the write data loop
|
||||
counter = 0
|
||||
while not hyperion.abort():
|
||||
counter += 1
|
||||
for r in runners:
|
||||
if counter % r["step"] == 0:
|
||||
ledData[r["pos"]] = whiteLevel
|
||||
r["pos"] = (r["pos"]+3) % (hyperion.ledCount*3)
|
||||
ledData[r["pos"]] = r["lvl"]
|
||||
|
||||
hyperion.setColor(ledData)
|
||||
time.sleep(sleepTime)
|
11
effects/shutdown.json
Normal file
11
effects/shutdown.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name" : "System Shutdown",
|
||||
"script" : "shutdown.py",
|
||||
"args" :
|
||||
{
|
||||
"speed" : 1.2,
|
||||
"alarm-color" : [255,0,0],
|
||||
"post-color" : [255,174,11],
|
||||
"shutdown-enabled" : false
|
||||
}
|
||||
}
|
49
effects/shutdown.py
Normal file
49
effects/shutdown.py
Normal file
@ -0,0 +1,49 @@
|
||||
import hyperion, time, subprocess
|
||||
|
||||
def setPixel(x,y,rgb):
|
||||
global imageData, width
|
||||
offset = y*width*3 + x*3
|
||||
if offset+2 < len(imageData):
|
||||
imageData[offset] = rgb[0]
|
||||
imageData[offset+1] = rgb[1]
|
||||
imageData[offset+2] = rgb[2]
|
||||
|
||||
# Initialize the led data and args
|
||||
sleepTime = float(hyperion.args.get('speed', 1.0))*0.5
|
||||
alarmColor = hyperion.args.get('alarm-color', (255,0,0))
|
||||
postColor = hyperion.args.get('post-color', (255,174,11))
|
||||
off = bool(hyperion.args.get('shutdown-enabled', False))
|
||||
width = 12
|
||||
height = 10
|
||||
|
||||
imageData = bytearray(height * width * (0,0,0))
|
||||
|
||||
# Start the write data loop
|
||||
for i in range(6):
|
||||
if hyperion.abort():
|
||||
off = False
|
||||
break
|
||||
if i % 2:
|
||||
hyperion.setColor(alarmColor[0], alarmColor[1], alarmColor[2])
|
||||
else:
|
||||
hyperion.setColor(0, 0, 0)
|
||||
time.sleep(sleepTime)
|
||||
|
||||
for y in range(height,0,-1):
|
||||
if hyperion.abort():
|
||||
off = False
|
||||
break
|
||||
for x in range(width):
|
||||
setPixel(x, y-1, alarmColor)
|
||||
hyperion.setImage(width, height, imageData)
|
||||
time.sleep(sleepTime)
|
||||
time.sleep(1)
|
||||
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
setPixel(x, y, postColor)
|
||||
hyperion.setImage(width, height, imageData)
|
||||
time.sleep(2)
|
||||
|
||||
if off and not hyperion.abort():
|
||||
subprocess.call("halt")
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"name" : "Snake",
|
||||
"script" : "snake.py",
|
||||
"args" :
|
||||
{
|
||||
"rotation-time" : 10.0,
|
||||
"color" : [255, 0, 0],
|
||||
"percentage" : 25
|
||||
}
|
||||
}
|
||||
{
|
||||
"name" : "Snake",
|
||||
"script" : "snake.py",
|
||||
"args" :
|
||||
{
|
||||
"rotation-time" : 12.0,
|
||||
"color" : [255, 0, 0],
|
||||
"percentage" : 10
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ for i in range(hyperion.ledCount-snakeLeds):
|
||||
ledData += bytearray((0, 0, 0))
|
||||
|
||||
for i in range(1,snakeLeds+1):
|
||||
rgb = colorsys.hsv_to_rgb(hsv[0], hsv[1], hsv[2]/i)
|
||||
rgb = colorsys.hsv_to_rgb(hsv[0], hsv[1], hsv[2]*(snakeLeds-i)/snakeLeds)
|
||||
ledData += bytearray((int(rgb[0]*255), int(rgb[1]*255), int(rgb[2]*255)))
|
||||
|
||||
# Calculate the sleep time and rotation increment
|
||||
|
14
effects/sparks-color.json
Normal file
14
effects/sparks-color.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name" : "Sparks Color",
|
||||
"script" : "sparks.py",
|
||||
"args" :
|
||||
{
|
||||
"rotation-time" : 3.0,
|
||||
"sleep-time" : 0.05,
|
||||
"brightness" : 1.0,
|
||||
"saturation" : 1.0,
|
||||
"reverse" : false,
|
||||
"color" : [255,255,255],
|
||||
"random-color" : true
|
||||
}
|
||||
}
|
14
effects/sparks.json
Normal file
14
effects/sparks.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name" : "Sparks",
|
||||
"script" : "sparks.py",
|
||||
"args" :
|
||||
{
|
||||
"rotation-time" : 3.0,
|
||||
"sleep-time" : 0.05,
|
||||
"brightness" : 1.0,
|
||||
"saturation" : 1.0,
|
||||
"reverse" : false,
|
||||
"color" : [255,255,255],
|
||||
"random-color" : false
|
||||
}
|
||||
}
|
37
effects/sparks.py
Normal file
37
effects/sparks.py
Normal file
@ -0,0 +1,37 @@
|
||||
import hyperion, time, colorsys, random
|
||||
|
||||
# Get the parameters
|
||||
rotationTime = float(hyperion.args.get('rotation-time', 3.0))
|
||||
sleepTime = float(hyperion.args.get('sleep-time', 0.05))
|
||||
brightness = float(hyperion.args.get('brightness', 1.0))
|
||||
saturation = float(hyperion.args.get('saturation', 1.0))
|
||||
reverse = bool(hyperion.args.get('reverse', False))
|
||||
color = list(hyperion.args.get('color', (255,255,255)))
|
||||
randomColor = bool(hyperion.args.get('random-color', False))
|
||||
|
||||
# Check parameters
|
||||
rotationTime = max(0.1, rotationTime)
|
||||
brightness = max(0.0, min(brightness, 1.0))
|
||||
saturation = max(0.0, min(saturation, 1.0))
|
||||
|
||||
# Initialize the led data
|
||||
ledData = bytearray()
|
||||
for i in range(hyperion.ledCount):
|
||||
ledData += bytearray((0, 0, 0))
|
||||
|
||||
# Start the write data loop
|
||||
while not hyperion.abort():
|
||||
ledData[:] = bytearray(3*hyperion.ledCount)
|
||||
for i in range(hyperion.ledCount):
|
||||
if random.random() < 0.005:
|
||||
|
||||
if randomColor:
|
||||
rgb = colorsys.hsv_to_rgb(random.random(), 1, 1)
|
||||
for n in range(3):
|
||||
color[n] = int(rgb[n]*255)
|
||||
|
||||
for n in range(3):
|
||||
ledData[i*3+n] = color[n]
|
||||
|
||||
hyperion.setColor(ledData)
|
||||
time.sleep(sleepTime)
|
@ -1,6 +1,4 @@
|
||||
import hyperion
|
||||
import time
|
||||
import colorsys
|
||||
import hyperion, time
|
||||
|
||||
# Get the rotation time
|
||||
color = hyperion.args.get('color', (255,255,255))
|
||||
@ -12,13 +10,9 @@ frequency = min(100.0, frequency)
|
||||
# Compute the strobe interval
|
||||
sleepTime = 1.0 / frequency
|
||||
|
||||
# Initialize the led data
|
||||
blackLedsData = bytearray(hyperion.ledCount * ( 0, 0, 0))
|
||||
whiteLedsData = bytearray(hyperion.ledCount * color)
|
||||
|
||||
# Start the write data loop
|
||||
while not hyperion.abort():
|
||||
hyperion.setColor(blackLedsData)
|
||||
hyperion.setColor(0, 0, 0)
|
||||
time.sleep(sleepTime)
|
||||
hyperion.setColor(whiteLedsData)
|
||||
hyperion.setColor(color[0], color[1], color[2])
|
||||
time.sleep(sleepTime)
|
||||
|
8
effects/traces.json
Normal file
8
effects/traces.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name" : "Color traces",
|
||||
"script" : "traces.py",
|
||||
"args" :
|
||||
{
|
||||
"speed" : 1.0
|
||||
}
|
||||
}
|
34
effects/traces.py
Normal file
34
effects/traces.py
Normal file
@ -0,0 +1,34 @@
|
||||
import hyperion
|
||||
import time
|
||||
import colorsys
|
||||
import random
|
||||
|
||||
# Initialize the led data
|
||||
ledData = bytearray()
|
||||
for i in range(hyperion.ledCount):
|
||||
ledData += bytearray((0,0,0))
|
||||
|
||||
sleepTime = float(hyperion.args.get('speed', 1.0)) * 0.004
|
||||
|
||||
runners = [
|
||||
{ "i":0, "pos":0, "c":0, "step":9 , "lvl":255},
|
||||
{ "i":1, "pos":0, "c":0, "step":8 , "lvl":255},
|
||||
{ "i":2, "pos":0, "c":0, "step":7 , "lvl":255},
|
||||
{ "i":0, "pos":0, "c":0, "step":6 , "lvl":100},
|
||||
{ "i":1, "pos":0, "c":0, "step":5 , "lvl":100},
|
||||
{ "i":2, "pos":0, "c":0, "step":4, "lvl":100},
|
||||
]
|
||||
|
||||
# Start the write data loop
|
||||
while not hyperion.abort():
|
||||
for r in runners:
|
||||
if r["c"] == 0:
|
||||
#ledData[r["pos"]*3+r["i"]] = 0
|
||||
r["c"] = r["step"]
|
||||
r["pos"] = (r["pos"]+1)%hyperion.ledCount
|
||||
ledData[r["pos"]*3+r["i"]] = int(r["lvl"]*(0.2+0.8*random.random()))
|
||||
else:
|
||||
r["c"] -= 1
|
||||
|
||||
hyperion.setColor(ledData)
|
||||
time.sleep(sleepTime)
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name" : "X-Mas",
|
||||
"script" : "x-mas.py",
|
||||
"args" :
|
||||
{
|
||||
"sleepTime" : 0.75
|
||||
}
|
||||
}
|
||||
{
|
||||
"name" : "X-Mas",
|
||||
"script" : "x-mas.py",
|
||||
"args" :
|
||||
{
|
||||
"sleepTime" : 0.75
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +68,9 @@ public slots:
|
||||
///
|
||||
void setVideoMode(const VideoMode videoMode);
|
||||
|
||||
signals:
|
||||
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
|
||||
|
||||
private:
|
||||
/// The update rate [Hz]
|
||||
const int _updateInterval_ms;
|
||||
@ -91,4 +94,7 @@ private:
|
||||
|
||||
/// Pointer to Hyperion for writing led values
|
||||
Hyperion * _hyperion;
|
||||
|
||||
// forwarding enabled
|
||||
bool _forward;
|
||||
};
|
||||
|
@ -68,6 +68,9 @@ public slots:
|
||||
///
|
||||
void setVideoMode(const VideoMode videoMode);
|
||||
|
||||
signals:
|
||||
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
|
||||
|
||||
private:
|
||||
/// The update rate [Hz]
|
||||
const int _updateInterval_ms;
|
||||
@ -91,4 +94,7 @@ private:
|
||||
|
||||
/// Pointer to Hyperion for writing led values
|
||||
Hyperion * _hyperion;
|
||||
|
||||
// forwarding enabled
|
||||
bool _forward;
|
||||
};
|
||||
|
@ -68,6 +68,9 @@ public slots:
|
||||
///
|
||||
void setVideoMode(const VideoMode videoMode);
|
||||
|
||||
signals:
|
||||
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
|
||||
|
||||
private:
|
||||
/// The update rate [Hz]
|
||||
const int _updateInterval_ms;
|
||||
|
@ -69,6 +69,9 @@ public slots:
|
||||
///
|
||||
void setVideoMode(const VideoMode videoMode);
|
||||
|
||||
signals:
|
||||
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
|
||||
|
||||
private:
|
||||
/// The update rate [Hz]
|
||||
const int _updateInterval_ms;
|
||||
|
@ -44,6 +44,7 @@ public slots:
|
||||
|
||||
signals:
|
||||
void emitColors(int priority, const std::vector<ColorRgb> &ledColors, const int timeout_ms);
|
||||
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
|
||||
|
||||
private slots:
|
||||
void newFrame(const Image<ColorRgb> & image);
|
||||
|
@ -13,6 +13,7 @@
|
||||
// Hyperion includes
|
||||
#include <hyperion/LedString.h>
|
||||
#include <hyperion/PriorityMuxer.h>
|
||||
#include <hyperion/MessageForwarder.h>
|
||||
|
||||
// Effect engine includes
|
||||
#include <effectengine/EffectDefinition.h>
|
||||
@ -125,6 +126,10 @@ public slots:
|
||||
/// Tell Hyperion that the transforms have changed and the leds need to be updated
|
||||
void transformsUpdated();
|
||||
|
||||
/// Returns MessageForwarder Object
|
||||
/// @return instance of message forwarder object
|
||||
MessageForwarder * getForwarder();
|
||||
|
||||
///
|
||||
/// Clears the given priority channel. This will switch the led-colors to the colors of the next
|
||||
/// lower priority channel (or off if no more channels are set)
|
||||
@ -168,6 +173,7 @@ public:
|
||||
static RgbChannelTransform * createRgbChannelTransform(const Json::Value& colorConfig);
|
||||
|
||||
static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice);
|
||||
static MessageForwarder * createMessageForwarder(const Json::Value & forwarderConfig);
|
||||
|
||||
signals:
|
||||
/// Signal which is emitted when a priority channel is actively cleared
|
||||
@ -201,6 +207,9 @@ private:
|
||||
/// Effect engine
|
||||
EffectEngine * _effectEngine;
|
||||
|
||||
// proto and json Message forwarder
|
||||
MessageForwarder * _messageForwarder;
|
||||
|
||||
/// The timer for handling priority channel timeouts
|
||||
QTimer _timer;
|
||||
};
|
||||
|
38
include/hyperion/MessageForwarder.h
Normal file
38
include/hyperion/MessageForwarder.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
// STL includes
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
// QT includes
|
||||
#include <QList>
|
||||
#include <QStringList>
|
||||
#include <QHostAddress>
|
||||
|
||||
// Utils includes
|
||||
#include <utils/ColorRgb.h>
|
||||
class MessageForwarder
|
||||
{
|
||||
public:
|
||||
|
||||
struct JsonSlaveAddress {
|
||||
QHostAddress addr;
|
||||
quint16 port;
|
||||
};
|
||||
|
||||
MessageForwarder();
|
||||
~MessageForwarder();
|
||||
|
||||
void addJsonSlave(std::string slave);
|
||||
void addProtoSlave(std::string slave);
|
||||
|
||||
bool protoForwardingEnabled();
|
||||
QStringList getProtoSlaves();
|
||||
QList<MessageForwarder::JsonSlaveAddress> getJsonSlaves();
|
||||
|
||||
private:
|
||||
QStringList _protoSlaves;
|
||||
QList<MessageForwarder::JsonSlaveAddress> _jsonSlaves;
|
||||
};
|
@ -7,6 +7,7 @@
|
||||
#include <QColor>
|
||||
#include <QImage>
|
||||
#include <QTcpSocket>
|
||||
#include <QTimer>
|
||||
#include <QMap>
|
||||
|
||||
// hyperion util
|
||||
@ -19,8 +20,11 @@
|
||||
///
|
||||
/// Connection class to setup an connection to the hyperion server and execute commands
|
||||
///
|
||||
class ProtoConnection
|
||||
class ProtoConnection : public QObject
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
///
|
||||
/// Constructor
|
||||
@ -67,10 +71,6 @@ public:
|
||||
///
|
||||
void clearAll();
|
||||
|
||||
private:
|
||||
/// Try to connect to the Hyperion host
|
||||
void connectToHost();
|
||||
|
||||
///
|
||||
/// Send a command message and receive its reply
|
||||
///
|
||||
@ -78,6 +78,13 @@ private:
|
||||
///
|
||||
void sendMessage(const proto::HyperionRequest & message);
|
||||
|
||||
private slots:
|
||||
/// Try to connect to the Hyperion host
|
||||
void connectToHost();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
///
|
||||
/// Parse a reply message
|
||||
///
|
||||
@ -99,4 +106,7 @@ private:
|
||||
|
||||
/// Skip receiving reply messages from Hyperion if set
|
||||
bool _skipReply;
|
||||
|
||||
QTimer _timer;
|
||||
QAbstractSocket::SocketState _prevSocketState;
|
||||
};
|
||||
|
@ -6,11 +6,23 @@
|
||||
// Qt includes
|
||||
#include <QTcpServer>
|
||||
#include <QSet>
|
||||
#include <QList>
|
||||
#include <QStringList>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/Hyperion.h>
|
||||
|
||||
// hyperion includes
|
||||
#include <utils/Image.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
|
||||
// forward decl
|
||||
class ProtoClientConnection;
|
||||
class ProtoConnection;
|
||||
|
||||
namespace proto {
|
||||
class HyperionRequest;
|
||||
}
|
||||
|
||||
///
|
||||
/// This class creates a TCP server which accepts connections wich can then send
|
||||
@ -35,6 +47,9 @@ public:
|
||||
///
|
||||
uint16_t getPort() const;
|
||||
|
||||
public slots:
|
||||
void sendImageToProtoSlaves(int priority, const Image<ColorRgb> & image, int duration_ms);
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// Slot which is called when a client tries to create a new connection
|
||||
@ -47,6 +62,8 @@ private slots:
|
||||
///
|
||||
void closedConnection(ProtoClientConnection * connection);
|
||||
|
||||
void newMessage(const proto::HyperionRequest * message);
|
||||
|
||||
private:
|
||||
/// Hyperion instance
|
||||
Hyperion * _hyperion;
|
||||
@ -56,4 +73,9 @@ private:
|
||||
|
||||
/// List with open connections
|
||||
QSet<ProtoClientConnection *> _openConnections;
|
||||
QStringList _forwardClients;
|
||||
|
||||
/// Hyperion proto connection object for forwarding
|
||||
QList<ProtoConnection*> _proxy_connections;
|
||||
|
||||
};
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <utils/ColorRgb.h>
|
||||
|
||||
|
||||
template <typename Pixel_T>
|
||||
class Image
|
||||
@ -183,6 +185,25 @@ public:
|
||||
{
|
||||
return _pixels;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Convert image of any color order to a RGB image.
|
||||
///
|
||||
/// @param[out] image The image that buffers the output
|
||||
///
|
||||
void toRgb(Image<ColorRgb>& image)
|
||||
{
|
||||
image.resize(_width, _height);
|
||||
const unsigned imageSize = _width * _height;
|
||||
|
||||
for (unsigned idx=0; idx<imageSize; idx++)
|
||||
{
|
||||
const Pixel_T color = memptr()[idx];
|
||||
image.memptr()[idx] = ColorRgb{color.red, color.green, color.blue};
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
///
|
||||
|
@ -1,5 +1,7 @@
|
||||
|
||||
find_package(PythonLibs REQUIRED)
|
||||
#OpenElec uses 2.7, if you want to compile for OpenElec require 2.7
|
||||
#find_package(PythonLibs 2.7 REQUIRED)
|
||||
|
||||
# Include the python directory. Also include the parent (which is for example /usr/include)
|
||||
# which may be required when it is not includes by the (cross-) compiler by default.
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
// Local includes
|
||||
#include "AmlogicGrabber.h"
|
||||
#include <grabber/AmlogicGrabber.h>
|
||||
|
||||
// Flags copied from 'include/linux/amlogic/amports/amvideocap.h' at https://github.com/codesnake/linux-amlogic
|
||||
#define AMVIDEOCAP_IOC_MAGIC 'V'
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
// Amlogic grabber includes
|
||||
#include <grabber/AmlogicWrapper.h>
|
||||
#include "AmlogicGrabber.h"
|
||||
#include <grabber/AmlogicGrabber.h>
|
||||
|
||||
|
||||
AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion) :
|
||||
@ -26,6 +26,7 @@ AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeig
|
||||
// Configure the timer to generate events every n milliseconds
|
||||
_timer.setInterval(_updateInterval_ms);
|
||||
_timer.setSingleShot(false);
|
||||
_forward = _hyperion->getForwarder()->protoForwardingEnabled();
|
||||
|
||||
_processor->setSize(grabWidth, grabHeight);
|
||||
|
||||
@ -55,8 +56,14 @@ void AmlogicWrapper::action()
|
||||
return;
|
||||
}
|
||||
|
||||
_processor->process(_image, _ledColors);
|
||||
if ( _forward )
|
||||
{
|
||||
Image<ColorRgb> image_rgb;
|
||||
_image.toRgb(image_rgb);
|
||||
emit emitImage(_priority, image_rgb, _timeout_ms);
|
||||
}
|
||||
|
||||
_processor->process(_image, _ledColors);
|
||||
_hyperion->setColors(_priority, _ledColors, _timeout_ms);
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/amlogic)
|
||||
SET(AmlogicQT_HEADERS ${CURRENT_HEADER_DIR}/AmlogicWrapper.h)
|
||||
|
||||
SET(AmlogicHEADERS
|
||||
${CURRENT_SOURCE_DIR}/AmlogicGrabber.h
|
||||
${CURRENT_HEADER_DIR}/AmlogicGrabber.h
|
||||
)
|
||||
|
||||
SET(AmlogicSOURCES
|
||||
|
@ -1,40 +1,41 @@
|
||||
|
||||
# Find the BCM-package (VC control)
|
||||
find_package(BCM REQUIRED)
|
||||
include_directories(${BCM_INCLUDE_DIRS})
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(DispmanxGrabberQT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/DispmanxWrapper.h
|
||||
)
|
||||
|
||||
SET(DispmanxGrabberHEADERS
|
||||
${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.h
|
||||
)
|
||||
|
||||
SET(DispmanxGrabberSOURCES
|
||||
${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp
|
||||
${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_library(dispmanx-grabber
|
||||
${DispmanxGrabberHEADERS}
|
||||
${DispmanxGrabberQT_HEADERS}
|
||||
${DispmanxGrabberHEADERS_MOC}
|
||||
${DispmanxGrabberSOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(dispmanx-grabber
|
||||
hyperion
|
||||
${QT_LIBRARIES}
|
||||
${BCM_LIBRARIES})
|
||||
|
||||
# Find the BCM-package (VC control)
|
||||
find_package(BCM REQUIRED)
|
||||
include_directories(${BCM_INCLUDE_DIRS})
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(DispmanxGrabberQT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/DispmanxWrapper.h
|
||||
)
|
||||
|
||||
SET(DispmanxGrabberHEADERS
|
||||
${CURRENT_HEADER_DIR}/DispmanxFrameGrabber.h
|
||||
)
|
||||
|
||||
SET(DispmanxGrabberSOURCES
|
||||
${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp
|
||||
${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_library(dispmanx-grabber
|
||||
${DispmanxGrabberHEADERS}
|
||||
${DispmanxGrabberQT_HEADERS}
|
||||
${DispmanxGrabberHEADERS_MOC}
|
||||
${DispmanxGrabberSOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(dispmanx-grabber
|
||||
hyperion
|
||||
${QT_LIBRARIES}
|
||||
${BCM_LIBRARIES}
|
||||
)
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <iostream>
|
||||
|
||||
// Local includes
|
||||
#include "DispmanxFrameGrabber.h"
|
||||
#include "grabber/DispmanxFrameGrabber.h"
|
||||
|
||||
DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned height) :
|
||||
_vc_display(0),
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
// Dispmanx grabber includes
|
||||
#include <grabber/DispmanxWrapper.h>
|
||||
#include "DispmanxFrameGrabber.h"
|
||||
#include <grabber/DispmanxFrameGrabber.h>
|
||||
|
||||
|
||||
DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion) :
|
||||
@ -28,6 +28,7 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe
|
||||
_timer.setSingleShot(false);
|
||||
|
||||
_processor->setSize(grabWidth, grabHeight);
|
||||
_forward = _hyperion->getForwarder()->protoForwardingEnabled();
|
||||
|
||||
// Connect the QTimer to this
|
||||
QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(action()));
|
||||
@ -51,10 +52,17 @@ void DispmanxWrapper::action()
|
||||
// Grab frame into the allocated image
|
||||
_frameGrabber->grabFrame(_image);
|
||||
|
||||
_processor->process(_image, _ledColors);
|
||||
if ( _forward )
|
||||
{
|
||||
Image<ColorRgb> image_rgb;
|
||||
_image.toRgb(image_rgb);
|
||||
emit emitImage(_priority, image_rgb, _timeout_ms);
|
||||
}
|
||||
|
||||
_processor->process(_image, _ledColors);
|
||||
_hyperion->setColors(_priority, _ledColors, _timeout_ms);
|
||||
}
|
||||
|
||||
void DispmanxWrapper::stop()
|
||||
{
|
||||
// Stop the timer, effectivly stopping the process
|
||||
|
@ -46,8 +46,9 @@ void FramebufferWrapper::action()
|
||||
// Grab frame into the allocated image
|
||||
_frameGrabber->grabFrame(_image);
|
||||
|
||||
_processor->process(_image, _ledColors);
|
||||
emit emitImage(_priority, _image, _timeout_ms);
|
||||
|
||||
_processor->process(_image, _ledColors);
|
||||
_hyperion->setColors(_priority, _ledColors, _timeout_ms);
|
||||
}
|
||||
void FramebufferWrapper::stop()
|
||||
|
@ -46,8 +46,9 @@ void OsxWrapper::action()
|
||||
// Grab frame into the allocated image
|
||||
_frameGrabber->grabFrame(_image);
|
||||
|
||||
_processor->process(_image, _ledColors);
|
||||
emit emitImage(_priority, _image, _timeout_ms);
|
||||
|
||||
_processor->process(_image, _ledColors);
|
||||
_hyperion->setColors(_priority, _ledColors, _timeout_ms);
|
||||
}
|
||||
void OsxWrapper::stop()
|
||||
|
@ -94,6 +94,9 @@ void V4L2Wrapper::newFrame(const Image<ColorRgb> &image)
|
||||
// process the new image
|
||||
_processor->process(image, _ledColors);
|
||||
|
||||
// forward to other hyperions
|
||||
emit emitImage(_priority, image, _timeout_ms);
|
||||
|
||||
// send colors to Hyperion
|
||||
emit emitColors(_priority, _ledColors, _timeout_ms);
|
||||
}
|
||||
|
@ -1,66 +1,68 @@
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(Hyperion_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/Hyperion.h
|
||||
|
||||
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h
|
||||
)
|
||||
|
||||
SET(Hyperion_HEADERS
|
||||
${CURRENT_HEADER_DIR}/ImageProcessor.h
|
||||
${CURRENT_HEADER_DIR}/ImageProcessorFactory.h
|
||||
${CURRENT_HEADER_DIR}/ImageToLedsMap.h
|
||||
${CURRENT_HEADER_DIR}/LedString.h
|
||||
${CURRENT_HEADER_DIR}/PriorityMuxer.h
|
||||
|
||||
${CURRENT_SOURCE_DIR}/MultiColorTransform.h
|
||||
)
|
||||
|
||||
SET(Hyperion_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/Hyperion.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageProcessor.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedString.cpp
|
||||
${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp
|
||||
|
||||
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
|
||||
${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp
|
||||
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp
|
||||
)
|
||||
|
||||
set(Hyperion_RESOURCES
|
||||
${CURRENT_SOURCE_DIR}/resource.qrc
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
|
||||
QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
|
||||
QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_library(hyperion
|
||||
${Hyperion_HEADERS}
|
||||
${Hyperion_QT_HEADERS}
|
||||
${Hyperion_HEADERS_MOC}
|
||||
${Hyperion_SOURCES}
|
||||
${Hyperion_RESOURCES_RCC}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(hyperion Widgets)
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
target_link_libraries(hyperion
|
||||
blackborder
|
||||
hyperion-utils
|
||||
leddevice
|
||||
effectengine
|
||||
serialport
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(Hyperion_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/Hyperion.h
|
||||
|
||||
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h
|
||||
)
|
||||
|
||||
SET(Hyperion_HEADERS
|
||||
${CURRENT_HEADER_DIR}/ImageProcessor.h
|
||||
${CURRENT_HEADER_DIR}/ImageProcessorFactory.h
|
||||
${CURRENT_HEADER_DIR}/ImageToLedsMap.h
|
||||
${CURRENT_HEADER_DIR}/LedString.h
|
||||
${CURRENT_HEADER_DIR}/PriorityMuxer.h
|
||||
|
||||
${CURRENT_SOURCE_DIR}/MultiColorTransform.h
|
||||
${CURRENT_HEADER_DIR}/MessageForwarder.h
|
||||
)
|
||||
|
||||
SET(Hyperion_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/Hyperion.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageProcessor.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedString.cpp
|
||||
${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp
|
||||
|
||||
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
|
||||
${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp
|
||||
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp
|
||||
${CURRENT_SOURCE_DIR}/MessageForwarder.cpp
|
||||
)
|
||||
|
||||
set(Hyperion_RESOURCES
|
||||
${CURRENT_SOURCE_DIR}/resource.qrc
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
|
||||
QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
|
||||
QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_library(hyperion
|
||||
${Hyperion_HEADERS}
|
||||
${Hyperion_QT_HEADERS}
|
||||
${Hyperion_HEADERS_MOC}
|
||||
${Hyperion_SOURCES}
|
||||
${Hyperion_RESOURCES_RCC}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(hyperion Widgets)
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
target_link_libraries(hyperion
|
||||
blackborder
|
||||
hyperion-utils
|
||||
leddevice
|
||||
effectengine
|
||||
serialport
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
@ -267,12 +267,45 @@ LedDevice * Hyperion::createColorSmoothing(const Json::Value & smoothingConfig,
|
||||
}
|
||||
|
||||
|
||||
MessageForwarder * Hyperion::createMessageForwarder(const Json::Value & forwarderConfig)
|
||||
{
|
||||
MessageForwarder * forwarder = new MessageForwarder();
|
||||
if ( ! forwarderConfig.isNull() )
|
||||
{
|
||||
if ( ! forwarderConfig["json"].isNull() && forwarderConfig["json"].isArray() )
|
||||
{
|
||||
for (const Json::Value& addr : forwarderConfig["json"])
|
||||
{
|
||||
std::cout << "Json forward to " << addr.asString() << std::endl;
|
||||
forwarder->addJsonSlave(addr.asString());
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! forwarderConfig["proto"].isNull() && forwarderConfig["proto"].isArray() )
|
||||
{
|
||||
for (const Json::Value& addr : forwarderConfig["proto"])
|
||||
{
|
||||
std::cout << "Proto forward to " << addr.asString() << std::endl;
|
||||
forwarder->addProtoSlave(addr.asString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return forwarder;
|
||||
}
|
||||
|
||||
MessageForwarder * Hyperion::getForwarder()
|
||||
{
|
||||
return _messageForwarder;
|
||||
}
|
||||
|
||||
Hyperion::Hyperion(const Json::Value &jsonConfig) :
|
||||
_ledString(createLedString(jsonConfig["leds"], createColorOrder(jsonConfig["device"]))),
|
||||
_muxer(_ledString.leds().size()),
|
||||
_raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])),
|
||||
_device(LedDeviceFactory::construct(jsonConfig["device"])),
|
||||
_effectEngine(nullptr),
|
||||
_messageForwarder(createMessageForwarder(jsonConfig["forwarder"])),
|
||||
_timer()
|
||||
{
|
||||
if (!_raw2ledTransform->verifyTransforms())
|
||||
@ -314,6 +347,9 @@ Hyperion::~Hyperion()
|
||||
|
||||
// delete the color transform
|
||||
delete _raw2ledTransform;
|
||||
|
||||
// delete the message forwarder
|
||||
delete _messageForwarder;
|
||||
}
|
||||
|
||||
unsigned Hyperion::getLedCount() const
|
||||
|
51
libsrc/hyperion/MessageForwarder.cpp
Normal file
51
libsrc/hyperion/MessageForwarder.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
// STL includes
|
||||
#include <stdexcept>
|
||||
|
||||
#include <hyperion/MessageForwarder.h>
|
||||
|
||||
|
||||
MessageForwarder::MessageForwarder()
|
||||
{
|
||||
}
|
||||
|
||||
MessageForwarder::~MessageForwarder()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void MessageForwarder::addJsonSlave(std::string slave)
|
||||
{
|
||||
QStringList parts = QString(slave.c_str()).split(":");
|
||||
if (parts.size() != 2)
|
||||
throw std::runtime_error(QString("Wrong address: unable to parse address (%1)").arg(slave.c_str()).toStdString());
|
||||
|
||||
bool ok;
|
||||
quint16 port = parts[1].toUShort(&ok);
|
||||
if (!ok)
|
||||
throw std::runtime_error(QString("Wrong address: Unable to parse the port number (%1)").arg(parts[1]).toStdString());
|
||||
|
||||
JsonSlaveAddress c;
|
||||
c.addr = QHostAddress(parts[0]);
|
||||
c.port = port;
|
||||
_jsonSlaves << c;
|
||||
}
|
||||
|
||||
void MessageForwarder::addProtoSlave(std::string slave)
|
||||
{
|
||||
_protoSlaves << QString(slave.c_str());
|
||||
}
|
||||
|
||||
QStringList MessageForwarder::getProtoSlaves()
|
||||
{
|
||||
return _protoSlaves;
|
||||
}
|
||||
|
||||
QList<MessageForwarder::JsonSlaveAddress> MessageForwarder::getJsonSlaves()
|
||||
{
|
||||
return _jsonSlaves;
|
||||
}
|
||||
|
||||
bool MessageForwarder::protoForwardingEnabled()
|
||||
{
|
||||
return ! _protoSlaves.empty();
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
// hyperion util includes
|
||||
#include <hyperion/ImageProcessorFactory.h>
|
||||
#include <hyperion/ImageProcessor.h>
|
||||
#include <hyperion/MessageForwarder.h>
|
||||
#include <hyperion/ColorTransform.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
|
||||
@ -250,8 +251,27 @@ void JsonClientConnection::handleMessage(const std::string &messageString)
|
||||
handleNotImplemented();
|
||||
}
|
||||
|
||||
|
||||
void JsonClientConnection::forwardJsonMessage(const Json::Value & message)
|
||||
{
|
||||
QTcpSocket client;
|
||||
QList<MessageForwarder::JsonSlaveAddress> list = _hyperion->getForwarder()->getJsonSlaves();
|
||||
|
||||
for ( int i=0; i<list.size(); i++ )
|
||||
{
|
||||
client.connectToHost(list.at(i).addr, list.at(i).port);
|
||||
if ( client.waitForConnected(500) )
|
||||
{
|
||||
sendMessage(message,&client);
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonClientConnection::handleColorCommand(const Json::Value &message)
|
||||
{
|
||||
forwardJsonMessage(message);
|
||||
|
||||
// extract parameters
|
||||
int priority = message["priority"].asInt();
|
||||
int duration = message.get("duration", -1).asInt();
|
||||
@ -289,6 +309,8 @@ void JsonClientConnection::handleColorCommand(const Json::Value &message)
|
||||
|
||||
void JsonClientConnection::handleImageCommand(const Json::Value &message)
|
||||
{
|
||||
forwardJsonMessage(message);
|
||||
|
||||
// extract parameters
|
||||
int priority = message["priority"].asInt();
|
||||
int duration = message.get("duration", -1).asInt();
|
||||
@ -320,6 +342,8 @@ void JsonClientConnection::handleImageCommand(const Json::Value &message)
|
||||
|
||||
void JsonClientConnection::handleEffectCommand(const Json::Value &message)
|
||||
{
|
||||
forwardJsonMessage(message);
|
||||
|
||||
// extract parameters
|
||||
int priority = message["priority"].asInt();
|
||||
int duration = message.get("duration", -1).asInt();
|
||||
@ -418,6 +442,8 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &)
|
||||
|
||||
void JsonClientConnection::handleClearCommand(const Json::Value &message)
|
||||
{
|
||||
forwardJsonMessage(message);
|
||||
|
||||
// extract parameters
|
||||
int priority = message["priority"].asInt();
|
||||
|
||||
@ -428,8 +454,10 @@ void JsonClientConnection::handleClearCommand(const Json::Value &message)
|
||||
sendSuccessReply();
|
||||
}
|
||||
|
||||
void JsonClientConnection::handleClearallCommand(const Json::Value &)
|
||||
void JsonClientConnection::handleClearallCommand(const Json::Value & message)
|
||||
{
|
||||
forwardJsonMessage(message);
|
||||
|
||||
// clear priority
|
||||
_hyperion->clearall();
|
||||
|
||||
@ -530,10 +558,51 @@ void JsonClientConnection::sendMessage(const Json::Value &message)
|
||||
|
||||
response.append(serializedReply.c_str(), serializedReply.length());
|
||||
|
||||
_socket->write(response.data(), response.length());
|
||||
_socket->write(response.data(), response.length());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void JsonClientConnection::sendMessage(const Json::Value & message, QTcpSocket * socket)
|
||||
{
|
||||
// serialize message (FastWriter already appends a newline)
|
||||
std::string serializedMessage = Json::FastWriter().write(message);
|
||||
|
||||
// write message
|
||||
socket->write(serializedMessage.c_str());
|
||||
if (!socket->waitForBytesWritten())
|
||||
{
|
||||
//std::cout << "Error while writing data to host" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// read reply data
|
||||
QByteArray serializedReply;
|
||||
while (!serializedReply.contains('\n'))
|
||||
{
|
||||
// receive reply
|
||||
if (!socket->waitForReadyRead())
|
||||
{
|
||||
//std::cout << "Error while reading data from host" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
serializedReply += socket->readAll();
|
||||
}
|
||||
int bytes = serializedReply.indexOf('\n') + 1; // Find the end of message
|
||||
|
||||
// parse reply data
|
||||
Json::Reader jsonReader;
|
||||
Json::Value reply;
|
||||
if (!jsonReader.parse(serializedReply.constData(), serializedReply.constData() + bytes, reply))
|
||||
{
|
||||
//std::cout << "Error while parsing reply: invalid json" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void JsonClientConnection::sendSuccessReply()
|
||||
{
|
||||
// create reply
|
||||
|
@ -124,6 +124,7 @@ private:
|
||||
/// @param message The JSON message to send
|
||||
///
|
||||
void sendMessage(const Json::Value & message);
|
||||
void sendMessage(const Json::Value & message, QTcpSocket * socket);
|
||||
|
||||
///
|
||||
/// Send a standard reply indicating success
|
||||
@ -147,6 +148,11 @@ private:
|
||||
///
|
||||
void handleWebSocketFrame();
|
||||
|
||||
///
|
||||
/// forward json message
|
||||
///
|
||||
void forwardJsonMessage(const Json::Value & message);
|
||||
|
||||
private:
|
||||
///
|
||||
/// Check if a JSON messag is valid according to a given JSON schema
|
||||
|
@ -16,6 +16,14 @@ JsonServer::JsonServer(Hyperion *hyperion, uint16_t port) :
|
||||
throw std::runtime_error("Json server could not bind to port");
|
||||
}
|
||||
|
||||
QList<MessageForwarder::JsonSlaveAddress> list = _hyperion->getForwarder()->getJsonSlaves();
|
||||
for ( int i=0; i<list.size(); i++ )
|
||||
{
|
||||
if ( list.at(i).addr == QHostAddress::LocalHost && list.at(i).port == port ) {
|
||||
throw std::runtime_error("Loop between proto server and forwarder detected. Fix your config!");
|
||||
}
|
||||
}
|
||||
|
||||
// Set trigger for incoming connections
|
||||
connect(&_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "LedDeviceFadeCandy.h"
|
||||
|
||||
static const ssize_t MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds
|
||||
static const ssize_t OPC_SET_PIXELS = 0; // OPC command codes
|
||||
static const ssize_t OPC_HEADER_SIZE = 4; // OPC header size
|
||||
static const signed MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds
|
||||
static const unsigned OPC_SET_PIXELS = 0; // OPC command codes
|
||||
static const unsigned OPC_HEADER_SIZE = 4; // OPC header size
|
||||
|
||||
|
||||
LedDeviceFadeCandy::LedDeviceFadeCandy(const std::string& host, const uint16_t port, const unsigned channel) :
|
||||
|
@ -81,6 +81,9 @@ void ProtoClientConnection::socketClosed()
|
||||
|
||||
void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message)
|
||||
{
|
||||
// forward messages
|
||||
emit newMessage(&message);
|
||||
|
||||
switch (message.command())
|
||||
{
|
||||
case proto::HyperionRequest::COLOR:
|
||||
|
@ -6,12 +6,14 @@
|
||||
// Qt includes
|
||||
#include <QByteArray>
|
||||
#include <QTcpSocket>
|
||||
#include <QStringList>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/Hyperion.h>
|
||||
|
||||
// proto includes
|
||||
#include "message.pb.h"
|
||||
#include "protoserver/ProtoConnection.h"
|
||||
|
||||
class ImageProcessor;
|
||||
|
||||
@ -41,6 +43,7 @@ signals:
|
||||
/// @param connection This connection object
|
||||
///
|
||||
void connectionClosed(ProtoClientConnection * connection);
|
||||
void newMessage(const proto::HyperionRequest * message);
|
||||
|
||||
private slots:
|
||||
///
|
||||
|
@ -9,7 +9,8 @@
|
||||
|
||||
ProtoConnection::ProtoConnection(const std::string & a) :
|
||||
_socket(),
|
||||
_skipReply(false)
|
||||
_skipReply(false),
|
||||
_prevSocketState(QAbstractSocket::UnconnectedState)
|
||||
{
|
||||
QString address(a.c_str());
|
||||
QStringList parts = address.split(":");
|
||||
@ -29,10 +30,18 @@ ProtoConnection::ProtoConnection(const std::string & a) :
|
||||
// try to connect to host
|
||||
std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
|
||||
connectToHost();
|
||||
|
||||
// start the connection timer
|
||||
_timer.setInterval(5000);
|
||||
_timer.setSingleShot(false);
|
||||
|
||||
connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()) );
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
ProtoConnection::~ProtoConnection()
|
||||
{
|
||||
_timer.stop();
|
||||
_socket.close();
|
||||
}
|
||||
|
||||
@ -91,20 +100,37 @@ void ProtoConnection::clearAll()
|
||||
|
||||
void ProtoConnection::connectToHost()
|
||||
{
|
||||
_socket.connectToHost(_host, _port);
|
||||
if (_socket.waitForConnected()) {
|
||||
std::cout << "Connected to Hyperion host" << std::endl;
|
||||
// try connection only when
|
||||
if (_socket.state() == QAbstractSocket::UnconnectedState)
|
||||
{
|
||||
_socket.connectToHost(_host, _port);
|
||||
//_socket.waitForConnected(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void ProtoConnection::sendMessage(const proto::HyperionRequest &message)
|
||||
{
|
||||
if (_socket.state() == QAbstractSocket::UnconnectedState)
|
||||
// print out connection message only when state is changed
|
||||
if (_socket.state() != _prevSocketState )
|
||||
{
|
||||
std::cout << "Currently disconnected: trying to connect to host" << std::endl;
|
||||
connectToHost();
|
||||
switch (_socket.state() )
|
||||
{
|
||||
case QAbstractSocket::UnconnectedState:
|
||||
std::cout << "No connection to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
|
||||
break;
|
||||
|
||||
case QAbstractSocket::ConnectedState:
|
||||
std::cout << "Connected to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
|
||||
break;
|
||||
|
||||
default:
|
||||
//std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
|
||||
break;
|
||||
}
|
||||
_prevSocketState = _socket.state();
|
||||
}
|
||||
|
||||
|
||||
if (_socket.state() != QAbstractSocket::ConnectedState)
|
||||
{
|
||||
return;
|
||||
|
@ -2,7 +2,9 @@
|
||||
#include <stdexcept>
|
||||
|
||||
// project includes
|
||||
#include <hyperion/MessageForwarder.h>
|
||||
#include <protoserver/ProtoServer.h>
|
||||
#include "protoserver/ProtoConnection.h"
|
||||
#include "ProtoClientConnection.h"
|
||||
|
||||
ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port) :
|
||||
@ -11,6 +13,20 @@ ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port) :
|
||||
_server(),
|
||||
_openConnections()
|
||||
{
|
||||
|
||||
MessageForwarder * forwarder = hyperion->getForwarder();
|
||||
QStringList slaves = forwarder->getProtoSlaves();
|
||||
|
||||
for (int i = 0; i < slaves.size(); ++i) {
|
||||
if ( QString("127.0.0.1:%1").arg(port) == slaves.at(i) ) {
|
||||
throw std::runtime_error("Loop between proto server and forwarder detected. Fix your config!");
|
||||
}
|
||||
|
||||
ProtoConnection* p = new ProtoConnection(slaves.at(i).toLocal8Bit().constData());
|
||||
p->setSkipReply(true);
|
||||
_proxy_connections << p;
|
||||
}
|
||||
|
||||
if (!_server.listen(QHostAddress::Any, port))
|
||||
{
|
||||
throw std::runtime_error("Proto server could not bind to port");
|
||||
@ -25,6 +41,9 @@ ProtoServer::~ProtoServer()
|
||||
foreach (ProtoClientConnection * connection, _openConnections) {
|
||||
delete connection;
|
||||
}
|
||||
|
||||
while (!_proxy_connections.isEmpty())
|
||||
delete _proxy_connections.takeFirst();
|
||||
}
|
||||
|
||||
uint16_t ProtoServer::getPort() const
|
||||
@ -44,9 +63,23 @@ void ProtoServer::newConnection()
|
||||
|
||||
// register slot for cleaning up after the connection closed
|
||||
connect(connection, SIGNAL(connectionClosed(ProtoClientConnection*)), this, SLOT(closedConnection(ProtoClientConnection*)));
|
||||
connect(connection, SIGNAL(newMessage(const proto::HyperionRequest*)), this, SLOT(newMessage(const proto::HyperionRequest*)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ProtoServer::newMessage(const proto::HyperionRequest * message)
|
||||
{
|
||||
for (int i = 0; i < _proxy_connections.size(); ++i)
|
||||
_proxy_connections.at(i)->sendMessage(*message);
|
||||
}
|
||||
|
||||
void ProtoServer::sendImageToProtoSlaves(int priority, const Image<ColorRgb> & image, int duration_ms)
|
||||
{
|
||||
for (int i = 0; i < _proxy_connections.size(); ++i)
|
||||
_proxy_connections.at(i)->setImage(image, priority, duration_ms);
|
||||
}
|
||||
|
||||
void ProtoServer::closedConnection(ProtoClientConnection *connection)
|
||||
{
|
||||
std::cout << "Proto connection closed" << std::endl;
|
||||
|
@ -15,4 +15,9 @@ if(ENABLE_PROTOBUF)
|
||||
if(ENABLE_X11)
|
||||
add_subdirectory(hyperion-x11)
|
||||
endif()
|
||||
|
||||
if(ENABLE_DISPMANX)
|
||||
add_subdirectory(hyperion-dispmanx)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
38
src/hyperion-aml/AmlogicWrapper.cpp
Normal file
38
src/hyperion-aml/AmlogicWrapper.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
|
||||
// Hyperion-AmLogic includes
|
||||
#include "AmlogicWrapper.h"
|
||||
|
||||
AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) :
|
||||
_timer(this),
|
||||
_grabber(grabWidth, grabHeight)
|
||||
{
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(updateRate_Hz);
|
||||
|
||||
// Connect capturing to the timeout signal of the timer
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
|
||||
}
|
||||
|
||||
const Image<ColorRgb> & AmlogicWrapper::getScreenshot()
|
||||
{
|
||||
capture();
|
||||
return _screenshot_rgb;
|
||||
}
|
||||
|
||||
void AmlogicWrapper::start()
|
||||
{
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
void AmlogicWrapper::stop()
|
||||
{
|
||||
_timer.stop();
|
||||
}
|
||||
|
||||
void AmlogicWrapper::capture()
|
||||
{
|
||||
_grabber.grabFrame(_screenshot);
|
||||
_screenshot.toRgb(_screenshot_rgb);
|
||||
|
||||
emit sig_screenshot(_screenshot_rgb);
|
||||
}
|
43
src/hyperion-aml/AmlogicWrapper.h
Normal file
43
src/hyperion-aml/AmlogicWrapper.h
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
// QT includes
|
||||
#include <QTimer>
|
||||
|
||||
// Hyperion-Dispmanx includes
|
||||
#include <grabber/AmlogicGrabber.h>
|
||||
|
||||
class AmlogicWrapper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz);
|
||||
|
||||
const Image<ColorRgb> & getScreenshot();
|
||||
|
||||
///
|
||||
/// Starts the timed capturing of screenshots
|
||||
///
|
||||
void start();
|
||||
|
||||
void stop();
|
||||
|
||||
signals:
|
||||
void sig_screenshot(const Image<ColorRgb> & screenshot);
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// Performs a single screenshot capture and publishes the capture screenshot on the screenshot signal.
|
||||
///
|
||||
void capture();
|
||||
|
||||
private:
|
||||
/// The QT timer to generate capture-publish events
|
||||
QTimer _timer;
|
||||
|
||||
/// The grabber for creating screenshots
|
||||
AmlogicGrabber _grabber;
|
||||
|
||||
// image buffers
|
||||
Image<ColorRgb> _screenshot_rgb;
|
||||
Image<ColorBgr> _screenshot;
|
||||
|
||||
};
|
@ -14,6 +14,7 @@ include_directories(
|
||||
)
|
||||
|
||||
set(Hyperion_AML_QT_HEADERS
|
||||
AmlogicWrapper.h
|
||||
)
|
||||
|
||||
set(Hyperion_AML_HEADERS
|
||||
@ -21,12 +22,13 @@ set(Hyperion_AML_HEADERS
|
||||
|
||||
set(Hyperion_AML_SOURCES
|
||||
hyperion-aml.cpp
|
||||
AmlogicWrapper.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS})
|
||||
QT5_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS})
|
||||
QT4_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_executable(hyperion-amlogic
|
||||
|
@ -7,16 +7,16 @@
|
||||
// getoptPlusPLus includes
|
||||
#include <getoptPlusPlus/getoptpp.h>
|
||||
|
||||
#include "../../libsrc/grabber/amlogic/AmlogicGrabber.h"
|
||||
#include <protoserver/ProtoConnectionWrapper.h>
|
||||
#include "AmlogicWrapper.h"
|
||||
|
||||
using namespace vlofgren;
|
||||
|
||||
// save the image as screenshot
|
||||
void saveScreenshot(const char * filename, const Image<ColorBgr> & image)
|
||||
void saveScreenshot(const char * filename, const Image<ColorRgb> & image)
|
||||
{
|
||||
// store as PNG
|
||||
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
|
||||
pngImage = pngImage.rgbSwapped();
|
||||
pngImage.save(filename);
|
||||
}
|
||||
|
||||
@ -30,16 +30,17 @@ int main(int argc, char ** argv)
|
||||
OptionsParser optionParser("X11 capture application for Hyperion");
|
||||
ParameterSet & parameters = optionParser.getParameters();
|
||||
|
||||
//IntParameter & argFps = parameters.add<IntParameter> ('f', "framerate", "Capture frame rate [default=10]");
|
||||
IntParameter & argFps = parameters.add<IntParameter> ('f', "framerate", "Capture frame rate [default=10]");
|
||||
IntParameter & argWidth = parameters.add<IntParameter> (0x0, "width", "Width of the captured image [default=128]");
|
||||
IntParameter & argHeight = parameters.add<IntParameter> (0x0, "height", "Height of the captured image [default=128]");
|
||||
SwitchParameter<> & argScreenshot = parameters.add<SwitchParameter<>> (0x0, "screenshot", "Take a single screenshot, save it to file and quit");
|
||||
StringParameter & argAddress = parameters.add<StringParameter> ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]");
|
||||
IntParameter & argPriority = parameters.add<IntParameter> ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]");
|
||||
//SwitchParameter<> & argSkipReply = parameters.add<SwitchParameter<>> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
|
||||
SwitchParameter<> & argSkipReply = parameters.add<SwitchParameter<>> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
|
||||
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<>> ('h', "help", "Show this help message and exit");
|
||||
|
||||
// set defaults
|
||||
argFps.setDefault(10);
|
||||
argWidth.setDefault(160);
|
||||
argHeight.setDefault(160);
|
||||
argAddress.setDefault("127.0.0.1:19445");
|
||||
@ -57,29 +58,36 @@ int main(int argc, char ** argv)
|
||||
|
||||
int width = argWidth.getValue();
|
||||
int height = argHeight.getValue();
|
||||
if (width < 160 || height < 60)
|
||||
if (width < 160 || height < 160)
|
||||
{
|
||||
std::cout << "Minimum width and height is 160" << std::endl;
|
||||
width = std::max(160, width);
|
||||
height = std::max(160, height);
|
||||
}
|
||||
|
||||
int grabInterval = 1000 / argFps.getValue();
|
||||
AmlogicWrapper amlWrapper(argWidth.getValue(),argHeight.getValue(),grabInterval);
|
||||
|
||||
if (argScreenshot.isSet())
|
||||
{
|
||||
|
||||
// Create the grabber
|
||||
AmlogicGrabber amlGrabber(width, height);
|
||||
|
||||
// Capture a single screenshot and finish
|
||||
Image<ColorBgr> screenshot;
|
||||
amlGrabber.grabFrame(screenshot);
|
||||
const Image<ColorRgb> & screenshot = amlWrapper.getScreenshot();
|
||||
saveScreenshot("screenshot.png", screenshot);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO[TvdZ]: Implement the proto-client mechanisme
|
||||
std::cerr << "The PROTO-interface has not been implemented yet" << std::endl;
|
||||
}
|
||||
// Create the Proto-connection with hyperiond
|
||||
ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet());
|
||||
|
||||
// Connect the screen capturing to the proto processing
|
||||
QObject::connect(&amlWrapper, SIGNAL(sig_screenshot(const Image<ColorRgb> &)), &protoWrapper, SLOT(receiveImage(Image<ColorRgb>)));
|
||||
|
||||
// Start the capturing
|
||||
amlWrapper.start();
|
||||
|
||||
// Start the application
|
||||
app.exec();
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error & e)
|
||||
{
|
||||
|
65
src/hyperion-dispmanx/CMakeLists.txt
Normal file
65
src/hyperion-dispmanx/CMakeLists.txt
Normal file
@ -0,0 +1,65 @@
|
||||
# Configure minimum CMAKE version
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
# Set the project name
|
||||
project(hyperion-dispmanx)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
else(ENABLE_QT5)
|
||||
# find Qt4
|
||||
find_package(Qt4 REQUIRED QtCore QtGui QtNetwork )
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
# Find the BCM-package (VC control)
|
||||
find_package(BCM REQUIRED)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver
|
||||
${QT_INCLUDES}
|
||||
${BCM_INCLUDE_DIRS}
|
||||
${PROTOBUF_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(Hyperion_Dispmanx_QT_HEADERS
|
||||
DispmanxWrapper.h)
|
||||
|
||||
set(Hyperion_Dispmanx_HEADERS
|
||||
)
|
||||
|
||||
set(Hyperion_Dispmanx_SOURCES
|
||||
hyperion-dispmanx.cpp
|
||||
DispmanxWrapper.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(Hyperion_Dispmanx_HEADERS_MOC ${Hyperion_Dispmanx_QT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(Hyperion_Dispmanx_HEADERS_MOC ${Hyperion_Dispmanx_QT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_executable( ${PROJECT_NAME}
|
||||
${Hyperion_Dispmanx_HEADERS}
|
||||
${Hyperion_Dispmanx_SOURCES}
|
||||
${Hyperion_Dispmanx_HEADERS_MOC}
|
||||
)
|
||||
|
||||
target_link_libraries( ${PROJECT_NAME}
|
||||
getoptPlusPlus
|
||||
blackborder
|
||||
hyperion-utils
|
||||
protoserver
|
||||
dispmanx-grabber
|
||||
${Dispmanx_LIBRARIES}
|
||||
pthread
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(hyperion-dispmanx Widgets Core Gui Network)
|
||||
else(ENABLE_QT5)
|
||||
qt4_use_modules(hyperion-dispmanx
|
||||
Core
|
||||
Gui
|
||||
Network
|
||||
)
|
||||
endif(ENABLE_QT5)
|
38
src/hyperion-dispmanx/DispmanxWrapper.cpp
Normal file
38
src/hyperion-dispmanx/DispmanxWrapper.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
|
||||
// Hyperion-Dispmanx includes
|
||||
#include "DispmanxWrapper.h"
|
||||
|
||||
DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) :
|
||||
_timer(this),
|
||||
_grabber(grabWidth, grabHeight)
|
||||
{
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(updateRate_Hz);
|
||||
|
||||
// Connect capturing to the timeout signal of the timer
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
|
||||
}
|
||||
|
||||
const Image<ColorRgb> & DispmanxWrapper::getScreenshot()
|
||||
{
|
||||
capture();
|
||||
return _screenshot_rgb;
|
||||
}
|
||||
|
||||
void DispmanxWrapper::start()
|
||||
{
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
void DispmanxWrapper::stop()
|
||||
{
|
||||
_timer.stop();
|
||||
}
|
||||
|
||||
void DispmanxWrapper::capture()
|
||||
{
|
||||
_grabber.grabFrame(_screenshot);
|
||||
_screenshot.toRgb(_screenshot_rgb);
|
||||
|
||||
emit sig_screenshot(_screenshot_rgb);
|
||||
}
|
42
src/hyperion-dispmanx/DispmanxWrapper.h
Normal file
42
src/hyperion-dispmanx/DispmanxWrapper.h
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
// QT includes
|
||||
#include <QTimer>
|
||||
|
||||
// Hyperion-Dispmanx includes
|
||||
#include <grabber/DispmanxFrameGrabber.h>
|
||||
|
||||
class DispmanxWrapper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz);
|
||||
|
||||
const Image<ColorRgb> & getScreenshot();
|
||||
|
||||
///
|
||||
/// Starts the timed capturing of screenshots
|
||||
///
|
||||
void start();
|
||||
|
||||
void stop();
|
||||
|
||||
signals:
|
||||
void sig_screenshot(const Image<ColorRgb> & screenshot);
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// Performs a single screenshot capture and publishes the capture screenshot on the screenshot
|
||||
/// signal.
|
||||
///
|
||||
void capture();
|
||||
|
||||
private:
|
||||
/// The QT timer to generate capture-publish events
|
||||
QTimer _timer;
|
||||
|
||||
/// The grabber for creating screenshots
|
||||
DispmanxFrameGrabber _grabber;
|
||||
Image<ColorRgb> _screenshot_rgb;
|
||||
Image<ColorRgba> _screenshot;
|
||||
|
||||
};
|
92
src/hyperion-dispmanx/hyperion-dispmanx.cpp
Normal file
92
src/hyperion-dispmanx/hyperion-dispmanx.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
|
||||
// QT includes
|
||||
#include <QCoreApplication>
|
||||
#include <QImage>
|
||||
|
||||
// getoptPlusPLus includes
|
||||
#include <getoptPlusPlus/getoptpp.h>
|
||||
|
||||
#include <protoserver/ProtoConnectionWrapper.h>
|
||||
#include "DispmanxWrapper.h"
|
||||
|
||||
using namespace vlofgren;
|
||||
|
||||
// save the image as screenshot
|
||||
void saveScreenshot(const char * filename, const Image<ColorRgb> & image)
|
||||
{
|
||||
// store as PNG
|
||||
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
|
||||
pngImage.save(filename);
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
try
|
||||
{
|
||||
// create the option parser and initialize all parameters
|
||||
OptionsParser optionParser("Dispmanx capture application for Hyperion");
|
||||
ParameterSet & parameters = optionParser.getParameters();
|
||||
|
||||
IntParameter & argFps = parameters.add<IntParameter> ('f', "framerate", "Capture frame rate [default=10]");
|
||||
IntParameter & argWidth = parameters.add<IntParameter> (0x0, "width", "The width of the grabbed frames [pixels]");
|
||||
IntParameter & argHeight = parameters.add<IntParameter> (0x0, "height", "The height of the grabbed frames");
|
||||
|
||||
SwitchParameter<> & argScreenshot = parameters.add<SwitchParameter<>> (0x0, "screenshot", "Take a single screenshot, save it to file and quit");
|
||||
StringParameter & argAddress = parameters.add<StringParameter> ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]");
|
||||
IntParameter & argPriority = parameters.add<IntParameter> ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]");
|
||||
SwitchParameter<> & argSkipReply = parameters.add<SwitchParameter<>> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
|
||||
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<>> ('h', "help", "Show this help message and exit");
|
||||
|
||||
// set defaults
|
||||
argFps.setDefault(10);
|
||||
argWidth.setDefault(64);
|
||||
argHeight.setDefault(64);
|
||||
argAddress.setDefault("127.0.0.1:19445");
|
||||
argPriority.setDefault(800);
|
||||
|
||||
// parse all options
|
||||
optionParser.parse(argc, const_cast<const char **>(argv));
|
||||
|
||||
// check if we need to display the usage. exit if we do.
|
||||
if (argHelp.isSet())
|
||||
{
|
||||
optionParser.usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create the dispmanx grabbing stuff
|
||||
int grabInterval = 1000 / argFps.getValue();
|
||||
DispmanxWrapper dispmanxWrapper(argWidth.getValue(),argHeight.getValue(),grabInterval);
|
||||
|
||||
if (argScreenshot.isSet())
|
||||
{
|
||||
// Capture a single screenshot and finish
|
||||
const Image<ColorRgb> & screenshot = dispmanxWrapper.getScreenshot();
|
||||
saveScreenshot("screenshot.png", screenshot);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create the Proto-connection with hyperiond
|
||||
ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet());
|
||||
|
||||
// Connect the screen capturing to the proto processing
|
||||
QObject::connect(&dispmanxWrapper, SIGNAL(sig_screenshot(const Image<ColorRgb> &)), &protoWrapper, SLOT(receiveImage(Image<ColorRgb>)));
|
||||
|
||||
// Start the capturing
|
||||
dispmanxWrapper.start();
|
||||
|
||||
// Start the application
|
||||
app.exec();
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error & e)
|
||||
{
|
||||
// An error occured. Display error and quit
|
||||
std::cerr << e.what() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
// C++ includes
|
||||
#include <cassert>
|
||||
#include <csignal>
|
||||
#include <vector>
|
||||
|
||||
// QT includes
|
||||
#include <QCoreApplication>
|
||||
@ -188,6 +189,39 @@ int main(int argc, char** argv)
|
||||
std::cout << "XBMC video checker created and started" << std::endl;
|
||||
}
|
||||
|
||||
// ---- network services -----
|
||||
|
||||
// Create Json server if configuration is present
|
||||
JsonServer * jsonServer = nullptr;
|
||||
if (config.isMember("jsonServer"))
|
||||
{
|
||||
const Json::Value & jsonServerConfig = config["jsonServer"];
|
||||
jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt());
|
||||
std::cout << "Json server created and started on port " << jsonServer->getPort() << std::endl;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
// Create Proto server if configuration is present
|
||||
ProtoServer * protoServer = nullptr;
|
||||
if (config.isMember("protoServer"))
|
||||
{
|
||||
const Json::Value & protoServerConfig = config["protoServer"];
|
||||
protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() );
|
||||
std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create Boblight server if configuration is present
|
||||
BoblightServer * boblightServer = nullptr;
|
||||
if (config.isMember("boblightServer"))
|
||||
{
|
||||
const Json::Value & boblightServerConfig = config["boblightServer"];
|
||||
boblightServer = new BoblightServer(&hyperion, boblightServerConfig["port"].asUInt());
|
||||
std::cout << "Boblight server created and started on port " << boblightServer->getPort() << std::endl;
|
||||
}
|
||||
|
||||
// ---- grabber -----
|
||||
|
||||
#ifdef ENABLE_DISPMANX
|
||||
// Construct and start the frame-grabber if the configuration is present
|
||||
DispmanxWrapper * dispmanx = nullptr;
|
||||
@ -206,6 +240,10 @@ int main(int argc, char** argv)
|
||||
QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), dispmanx, SLOT(setVideoMode(VideoMode)));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
QObject::connect(dispmanx, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
#endif
|
||||
|
||||
dispmanx->start();
|
||||
std::cout << "Frame grabber created and started" << std::endl;
|
||||
}
|
||||
@ -213,7 +251,7 @@ int main(int argc, char** argv)
|
||||
#if !defined(ENABLE_OSX) && !defined(ENABLE_FB)
|
||||
if (config.isMember("framegrabber"))
|
||||
{
|
||||
std::cerr << "The dispmanx framegrabber can not be instantiated, becuse it has been left out from the build" << std::endl;
|
||||
std::cerr << "The dispmanx framegrabber can not be instantiated, because it has been left out from the build" << std::endl;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -245,14 +283,19 @@ int main(int argc, char** argv)
|
||||
grabberConfig.get("cropTop", 0).asInt(),
|
||||
grabberConfig.get("cropBottom", 0).asInt());
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
QObject::connect(v4l2Grabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
#endif
|
||||
|
||||
v4l2Grabber->start();
|
||||
std::cout << "V4l2 grabber created and started" << std::endl;
|
||||
}
|
||||
#else
|
||||
if (config.isMember("grabber-v4l2"))
|
||||
{
|
||||
std::cerr << "The v4l2 grabber can not be instantiated, becuse it has been left out from the build" << std::endl;
|
||||
std::cerr << "The v4l2 grabber can not be instantiated, because it has been left out from the build" << std::endl;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_AMLOGIC
|
||||
@ -273,6 +316,10 @@ int main(int argc, char** argv)
|
||||
QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), amlGrabber, SLOT(setVideoMode(VideoMode)));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
QObject::connect(amlGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
#endif
|
||||
|
||||
amlGrabber->start();
|
||||
std::cout << "AMLOGIC grabber created and started" << std::endl;
|
||||
}
|
||||
@ -302,18 +349,22 @@ int main(int argc, char** argv)
|
||||
QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), fbGrabber, SLOT(setVideoMode(VideoMode)));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
QObject::connect(fbGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
#endif
|
||||
|
||||
fbGrabber->start();
|
||||
std::cout << "Framebuffer grabber created and started" << std::endl;
|
||||
}
|
||||
#else
|
||||
if (config.isMember("framebuffergrabber"))
|
||||
{
|
||||
std::cerr << "The framebuffer grabber can not be instantiated, becuse it has been left out from the build" << std::endl;
|
||||
std::cerr << "The framebuffer grabber can not be instantiated, because it has been left out from the build" << std::endl;
|
||||
}
|
||||
#if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX)
|
||||
else if (config.isMember("framegrabber"))
|
||||
{
|
||||
std::cerr << "The framebuffer grabber can not be instantiated, becuse it has been left out from the build" << std::endl;
|
||||
std::cerr << "The framebuffer grabber can not be instantiated, because it has been left out from the build" << std::endl;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -336,6 +387,10 @@ int main(int argc, char** argv)
|
||||
QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), osxGrabber, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), osxGrabber, SLOT(setVideoMode(VideoMode)));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
QObject::connect(osxGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
#endif
|
||||
|
||||
osxGrabber->start();
|
||||
std::cout << "OSX grabber created and started" << std::endl;
|
||||
@ -343,44 +398,16 @@ int main(int argc, char** argv)
|
||||
#else
|
||||
if (config.isMember("osxgrabber"))
|
||||
{
|
||||
std::cerr << "The osx grabber can not be instantiated, becuse it has been left out from the build" << std::endl;
|
||||
std::cerr << "The osx grabber can not be instantiated, because it has been left out from the build" << std::endl;
|
||||
}
|
||||
#if !defined(ENABLE_DISPMANX) && !defined(ENABLE_FB)
|
||||
else if (config.isMember("framegrabber"))
|
||||
{
|
||||
std::cerr << "The osx grabber can not be instantiated, becuse it has been left out from the build" << std::endl;
|
||||
std::cerr << "The osx grabber can not be instantiated, because it has been left out from the build" << std::endl;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Create Json server if configuration is present
|
||||
JsonServer * jsonServer = nullptr;
|
||||
if (config.isMember("jsonServer"))
|
||||
{
|
||||
const Json::Value & jsonServerConfig = config["jsonServer"];
|
||||
jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt());
|
||||
std::cout << "Json server created and started on port " << jsonServer->getPort() << std::endl;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
// Create Proto server if configuration is present
|
||||
ProtoServer * protoServer = nullptr;
|
||||
if (config.isMember("protoServer"))
|
||||
{
|
||||
const Json::Value & protoServerConfig = config["protoServer"];
|
||||
protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt());
|
||||
std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create Boblight server if configuration is present
|
||||
BoblightServer * boblightServer = nullptr;
|
||||
if (config.isMember("boblightServer"))
|
||||
{
|
||||
const Json::Value & boblightServerConfig = config["boblightServer"];
|
||||
boblightServer = new BoblightServer(&hyperion, boblightServerConfig["port"].asUInt());
|
||||
std::cout << "Boblight server created and started on port " << boblightServer->getPort() << std::endl;
|
||||
}
|
||||
|
||||
// run the application
|
||||
int rc = app.exec();
|
||||
|
@ -4,22 +4,42 @@
|
||||
|
||||
// Utils includes
|
||||
#include <utils/Image.h>
|
||||
#include <utils/ColorRgba.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
#include <utils/ColorBgr.h>
|
||||
#include <hyperion/ImageProcessor.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "Constructing image" << std::endl;
|
||||
Image<ColorRgb> image(64, 64, ColorRgb::BLACK);
|
||||
int width = 64;
|
||||
int height = 64;
|
||||
Image<ColorRgb> image_rgb(width, height, ColorRgb::BLACK);
|
||||
Image<ColorBgr> image_bgr(image_rgb.width(), image_rgb.height(), ColorBgr::BLACK);
|
||||
|
||||
std::cout << "Writing image" << std::endl;
|
||||
for (unsigned y=0; y<64; ++y)
|
||||
unsigned l = width * height;
|
||||
|
||||
// BGR
|
||||
for (unsigned i=0; i<l; ++i)
|
||||
image_bgr.memptr()[i] = ColorBgr{0,128,255};
|
||||
|
||||
|
||||
// to RGB
|
||||
image_bgr.toRgb(image_rgb);
|
||||
|
||||
// test
|
||||
for (unsigned i=0; i<l; ++i)
|
||||
{
|
||||
for (unsigned x=0; x<64; ++x)
|
||||
{
|
||||
image(x,y) = ColorRgb::RED;
|
||||
}
|
||||
const ColorRgb rgb = image_rgb.memptr()[i];
|
||||
if ( rgb.red != 255 || rgb.green != 128 || rgb.blue != 0 )
|
||||
std::cout << "RGB error idx " << i << " " << rgb << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::cout << "Finished (destruction will be performed)" << std::endl;
|
||||
|
||||
return 0;
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <getoptPlusPlus/getoptpp.h>
|
||||
|
||||
// Dispmanx grabber includes
|
||||
#include <grabber/dispmanx/DispmanxFrameGrabber.h>
|
||||
#include <grabber/DispmanxFrameGrabber.h>
|
||||
|
||||
using namespace vlofgren;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user