mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
big code cleanup. mostly line endings and indentions (#659)
No functional changes - except protobuffer is mandatory and not optional now. Former-commit-id: 1e6347e708707cc388cdedb8d0352a9f017030b8
This commit is contained in:
parent
667ee80ef6
commit
945f3d1c5b
@ -51,8 +51,7 @@ message(STATUS "ENABLE_FB = " ${ENABLE_FB})
|
||||
option(ENABLE_OSX "Enable the osx grabber" ${DEFAULT_OSX} )
|
||||
message(STATUS "ENABLE_OSX = " ${ENABLE_OSX})
|
||||
|
||||
option(ENABLE_PROTOBUF "Enable PROTOBUF server" ON)
|
||||
message(STATUS "ENABLE_PROTOBUF = " ${ENABLE_PROTOBUF})
|
||||
set(ENABLE_PROTOBUF ON)
|
||||
|
||||
option(ENABLE_SPIDEV "Enable the SPIDEV device" ${DEFAULT_SPIDEV} )
|
||||
message(STATUS "ENABLE_SPIDEV = " ${ENABLE_SPIDEV})
|
||||
@ -78,9 +77,6 @@ message(STATUS "ENABLE_QT5 = " ${ENABLE_QT5})
|
||||
option(ENABLE_TESTS "Compile additional test applications" OFF)
|
||||
message(STATUS "ENABLE_TESTS = " ${ENABLE_TESTS})
|
||||
|
||||
if(ENABLE_V4L2 AND NOT ENABLE_PROTOBUF)
|
||||
message(FATAL_ERROR "V4L2 grabber requires PROTOBUF. Disable V4L2 or enable PROTOBUF")
|
||||
endif()
|
||||
|
||||
if(ENABLE_FB AND ENABLE_DISPMANX)
|
||||
message(FATAL_ERROR "dispmanx grabber and framebuffer grabber cannot be used at the same time")
|
||||
|
@ -1,8 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$#" -ne 2 ] || ! [ -d "$1" ] || ! [ -d "$2" ]; then
|
||||
echo "Usage: $0 <BUILD-DIR> <REPO-DIR>" >&2
|
||||
exit 1
|
||||
echo "Usage: $0 <BUILD-DIR> <REPO-DIR>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
builddir="$1"
|
||||
|
@ -6,15 +6,15 @@ PATH="/sbin:$PATH"
|
||||
|
||||
#Check if HyperCon is logged in as root
|
||||
if [ $(id -u) != 0 ] && [ "$1" = "HyperConRemove" ]; then
|
||||
echo '---> Critical Error: Please connect as user "root" through HyperCon'
|
||||
echo '---> We need admin privileges to remove your Hyperion! -> abort'
|
||||
exit 1
|
||||
echo '---> Critical Error: Please connect as user "root" through HyperCon'
|
||||
echo '---> We need admin privileges to remove your Hyperion! -> abort'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#Check, if script is running as root
|
||||
if [ $(id -u) != 0 ]; then
|
||||
echo '---> Critical Error: Please run the script as root (sudo sh ./remove_hyperion.sh)'
|
||||
exit 1
|
||||
echo '---> Critical Error: Please run the script as root (sudo sh ./remove_hyperion.sh)'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#Welcome message
|
||||
@ -26,21 +26,22 @@ echo '**************************************************************************
|
||||
|
||||
#Skip the prompt if HyperCon Remove
|
||||
if [ "$1" = "" ]; then
|
||||
#Prompt for confirmation to proceed
|
||||
while true
|
||||
do
|
||||
echo -n "---> Do you really want to remove Hyperion and it´s services? (y or n) :"
|
||||
read CONFIRM
|
||||
case $CONFIRM in
|
||||
y|Y|YES|yes|Yes) break ;;
|
||||
n|N|no|NO|No)
|
||||
echo "---> Aborting - you entered \"$CONFIRM\""
|
||||
exit
|
||||
;;
|
||||
*) echo "-> Please enter only y or n"
|
||||
esac
|
||||
done
|
||||
echo "---> You entered \"$CONFIRM\". Remove Hyperion!"
|
||||
#Prompt for confirmation to proceed
|
||||
while true
|
||||
do
|
||||
echo -n "---> Do you really want to remove Hyperion and it´s services? (y or n) :"
|
||||
read CONFIRM
|
||||
case $CONFIRM in
|
||||
y|Y|YES|yes|Yes) break ;;
|
||||
n|N|no|NO|No)
|
||||
echo "---> Aborting - you entered \"$CONFIRM\""
|
||||
exit
|
||||
;;
|
||||
*) echo "-> Please enter only y or n"
|
||||
esac
|
||||
done
|
||||
|
||||
echo "---> You entered \"$CONFIRM\". Remove Hyperion!"
|
||||
fi
|
||||
# Find out if we are on OpenElec or RasPlex
|
||||
OS_OPENELEC=`grep -m1 -c 'OpenELEC\|RasPlex\|LibreELEC' /etc/issue`
|
||||
@ -124,4 +125,3 @@ echo '**************************************************************************
|
||||
echo 'Hyperion successful removed!'
|
||||
echo '*******************************************************************************'
|
||||
exit 0
|
||||
|
@ -8,16 +8,16 @@
|
||||
#
|
||||
|
||||
FIND_PATH(BCM_INCLUDE_DIR
|
||||
bcm_host.h
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/vc/include)
|
||||
bcm_host.h
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/vc/include)
|
||||
|
||||
SET(BCM_INCLUDE_DIRS
|
||||
${BCM_INCLUDE_DIR}
|
||||
${BCM_INCLUDE_DIR}/interface/vcos/pthreads
|
||||
${BCM_INCLUDE_DIR}/interface/vmcs_host/linux)
|
||||
${BCM_INCLUDE_DIR}
|
||||
${BCM_INCLUDE_DIR}/interface/vcos/pthreads
|
||||
${BCM_INCLUDE_DIR}/interface/vmcs_host/linux)
|
||||
|
||||
FIND_LIBRARY(BCM_LIBRARIES
|
||||
NAMES bcm_host
|
||||
PATHS /usr/lib /usr/local/lib /opt/vc/lib)
|
||||
NAMES bcm_host
|
||||
PATHS /usr/lib /usr/local/lib /opt/vc/lib)
|
||||
|
@ -17,5 +17,5 @@ if(APPLE)
|
||||
set(CoreFoundation_FOUND true)
|
||||
set(CoreFoundation_INCLUDE_DIR ${CoreFoundation})
|
||||
set(CoreFoundation_LIBRARY ${CoreFoundation})
|
||||
endif(CoreFoundation)
|
||||
endif(APPLE)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -13,9 +13,9 @@ set(IOKit_LIBRARY)
|
||||
if(APPLE)
|
||||
# The only platform it makes sense to check for IOKit
|
||||
find_library(IOKit IOKit)
|
||||
if(IOKit)
|
||||
set(IOKit_FOUND true)
|
||||
if(IOKit)
|
||||
set(IOKit_FOUND true)
|
||||
set(IOKit_INCLUDE_DIR ${IOKit})
|
||||
set(IOKit_LIBRARY ${IOKit})
|
||||
endif(IOKit)
|
||||
set(IOKit_LIBRARY ${IOKit})
|
||||
endif(IOKit)
|
||||
endif(APPLE)
|
||||
|
@ -10,44 +10,44 @@
|
||||
#
|
||||
|
||||
FIND_PATH(
|
||||
UDEV_INCLUDE_DIR
|
||||
libudev.h
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
${UDEV_PATH_INCLUDES}
|
||||
UDEV_INCLUDE_DIR
|
||||
libudev.h
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
${UDEV_PATH_INCLUDES}
|
||||
)
|
||||
|
||||
FIND_LIBRARY(
|
||||
UDEV_LIBRARIES
|
||||
NAMES udev libudev
|
||||
PATHS
|
||||
/usr/lib${LIB_SUFFIX}
|
||||
/usr/local/lib${LIB_SUFFIX}
|
||||
${UDEV_PATH_LIB}
|
||||
UDEV_LIBRARIES
|
||||
NAMES udev libudev
|
||||
PATHS
|
||||
/usr/lib${LIB_SUFFIX}
|
||||
/usr/local/lib${LIB_SUFFIX}
|
||||
${UDEV_PATH_LIB}
|
||||
)
|
||||
|
||||
IF (UDEV_LIBRARIES AND UDEV_INCLUDE_DIR)
|
||||
SET(UDEV_FOUND "YES")
|
||||
execute_process(COMMAND pkg-config --atleast-version=143 libudev RESULT_VARIABLE UDEV_STABLE)
|
||||
# retvale is 0 of the condition is "true" so we need to negate the value...
|
||||
if (UDEV_STABLE)
|
||||
set(UDEV_STABLE 0)
|
||||
else (UDEV_STABLE)
|
||||
set(UDEV_STABLE 1)
|
||||
endif (UDEV_STABLE)
|
||||
message(STATUS "libudev stable: ${UDEV_STABLE}")
|
||||
ENDIF (UDEV_LIBRARIES AND UDEV_INCLUDE_DIR)
|
||||
SET(UDEV_FOUND "YES")
|
||||
execute_process(COMMAND pkg-config --atleast-version=143 libudev RESULT_VARIABLE UDEV_STABLE)
|
||||
# retvale is 0 of the condition is "true" so we need to negate the value...
|
||||
if (UDEV_STABLE)
|
||||
set(UDEV_STABLE 0)
|
||||
else ()
|
||||
set(UDEV_STABLE 1)
|
||||
endif ()
|
||||
message(STATUS "libudev stable: ${UDEV_STABLE}")
|
||||
ENDIF ()
|
||||
|
||||
IF (UDEV_FOUND)
|
||||
MESSAGE(STATUS "Found UDev: ${UDEV_LIBRARIES}")
|
||||
MESSAGE(STATUS " include: ${UDEV_INCLUDE_DIR}")
|
||||
ELSE (UDEV_FOUND)
|
||||
MESSAGE(STATUS "UDev not found.")
|
||||
MESSAGE(STATUS "UDev: You can specify includes: -DUDEV_PATH_INCLUDES=/opt/udev/include")
|
||||
MESSAGE(STATUS " currently found includes: ${UDEV_INCLUDE_DIR}")
|
||||
MESSAGE(STATUS "UDev: You can specify libs: -DUDEV_PATH_LIB=/opt/udev/lib")
|
||||
MESSAGE(STATUS " currently found libs: ${UDEV_LIBRARIES}")
|
||||
IF (UDev_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find UDev library")
|
||||
ENDIF (UDev_FIND_REQUIRED)
|
||||
ENDIF (UDEV_FOUND)
|
||||
MESSAGE(STATUS "Found UDev: ${UDEV_LIBRARIES}")
|
||||
MESSAGE(STATUS " include: ${UDEV_INCLUDE_DIR}")
|
||||
ELSE ()
|
||||
MESSAGE(STATUS "UDev not found.")
|
||||
MESSAGE(STATUS "UDev: You can specify includes: -DUDEV_PATH_INCLUDES=/opt/udev/include")
|
||||
MESSAGE(STATUS " currently found includes: ${UDEV_INCLUDE_DIR}")
|
||||
MESSAGE(STATUS "UDev: You can specify libs: -DUDEV_PATH_LIB=/opt/udev/lib")
|
||||
MESSAGE(STATUS " currently found libs: ${UDEV_LIBRARIES}")
|
||||
IF (UDev_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find UDev library")
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
@ -44,56 +44,52 @@
|
||||
|
||||
|
||||
if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(LIBUSB_FOUND TRUE)
|
||||
# in cache already
|
||||
set(LIBUSB_FOUND TRUE)
|
||||
else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
|
||||
find_path(LIBUSB_1_INCLUDE_DIR
|
||||
find_path(LIBUSB_1_INCLUDE_DIR
|
||||
NAMES
|
||||
libusb.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
PATH_SUFFIXES
|
||||
libusb-1.0
|
||||
)
|
||||
|
||||
find_library(LIBUSB_1_LIBRARY
|
||||
NAMES
|
||||
libusb.h
|
||||
usb-1.0 usb
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
PATH_SUFFIXES
|
||||
libusb-1.0
|
||||
)
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
|
||||
find_library(LIBUSB_1_LIBRARY
|
||||
NAMES
|
||||
usb-1.0 usb
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
set(LIBUSB_1_INCLUDE_DIRS ${LIBUSB_1_INCLUDE_DIR} )
|
||||
set(LIBUSB_1_LIBRARIES ${LIBUSB_1_LIBRARY} )
|
||||
|
||||
set(LIBUSB_1_INCLUDE_DIRS
|
||||
${LIBUSB_1_INCLUDE_DIR}
|
||||
)
|
||||
set(LIBUSB_1_LIBRARIES
|
||||
${LIBUSB_1_LIBRARY}
|
||||
)
|
||||
if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
|
||||
set(LIBUSB_1_FOUND TRUE)
|
||||
endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
|
||||
|
||||
if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
|
||||
set(LIBUSB_1_FOUND TRUE)
|
||||
endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
|
||||
if (LIBUSB_1_FOUND)
|
||||
if (NOT libusb_1_FIND_QUIETLY)
|
||||
message(STATUS "Found libusb-1.0:")
|
||||
message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}")
|
||||
message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}")
|
||||
endif (NOT libusb_1_FIND_QUIETLY)
|
||||
else (LIBUSB_1_FOUND)
|
||||
unset(LIBUSB_1_LIBRARY CACHE)
|
||||
if (libusb_1_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find libusb")
|
||||
endif (libusb_1_FIND_REQUIRED)
|
||||
endif (LIBUSB_1_FOUND)
|
||||
|
||||
if (LIBUSB_1_FOUND)
|
||||
if (NOT libusb_1_FIND_QUIETLY)
|
||||
message(STATUS "Found libusb-1.0:")
|
||||
message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}")
|
||||
message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}")
|
||||
endif (NOT libusb_1_FIND_QUIETLY)
|
||||
else (LIBUSB_1_FOUND)
|
||||
unset(LIBUSB_1_LIBRARY CACHE)
|
||||
if (libusb_1_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find libusb")
|
||||
endif (libusb_1_FIND_REQUIRED)
|
||||
endif (LIBUSB_1_FOUND)
|
||||
|
||||
# show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES)
|
||||
# show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES)
|
||||
|
||||
endif (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
|
||||
|
@ -1,22 +1,22 @@
|
||||
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
|
||||
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||
foreach(file ${files})
|
||||
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
exec_program(
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval
|
||||
)
|
||||
if(NOT "${rm_retval}" STREQUAL 0)
|
||||
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||
endif(NOT "${rm_retval}" STREQUAL 0)
|
||||
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
exec_program(
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval
|
||||
)
|
||||
if(NOT "${rm_retval}" STREQUAL 0)
|
||||
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||
endif(NOT "${rm_retval}" STREQUAL 0)
|
||||
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
endforeach(file)
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"name" : "Snake",
|
||||
"script" : "snake.py",
|
||||
"args" :
|
||||
{
|
||||
"rotation-time" : 12.0,
|
||||
"color" : [255, 0, 0],
|
||||
"percentage" : 10
|
||||
}
|
||||
}
|
||||
{
|
||||
"name" : "Snake",
|
||||
"script" : "snake.py",
|
||||
"args" :
|
||||
{
|
||||
"rotation-time" : 12.0,
|
||||
"color" : [255, 0, 0],
|
||||
"percentage" : 10
|
||||
}
|
||||
}
|
||||
|
@ -23,103 +23,103 @@
|
||||
/// @see http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html
|
||||
class V4L2Grabber : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
V4L2Grabber(const std::string & device,
|
||||
int input,
|
||||
VideoStandard videoStandard, PixelFormat pixelFormat,
|
||||
int width,
|
||||
int height,
|
||||
int frameDecimation,
|
||||
int horizontalPixelDecimation,
|
||||
int verticalPixelDecimation);
|
||||
virtual ~V4L2Grabber();
|
||||
V4L2Grabber(const std::string & device,
|
||||
int input,
|
||||
VideoStandard videoStandard, PixelFormat pixelFormat,
|
||||
int width,
|
||||
int height,
|
||||
int frameDecimation,
|
||||
int horizontalPixelDecimation,
|
||||
int verticalPixelDecimation);
|
||||
virtual ~V4L2Grabber();
|
||||
|
||||
public slots:
|
||||
void setCropping(int cropLeft,
|
||||
int cropRight,
|
||||
int cropTop,
|
||||
int cropBottom);
|
||||
void setCropping(int cropLeft,
|
||||
int cropRight,
|
||||
int cropTop,
|
||||
int cropBottom);
|
||||
|
||||
void set3D(VideoMode mode);
|
||||
void set3D(VideoMode mode);
|
||||
|
||||
void setSignalThreshold(double redSignalThreshold,
|
||||
double greenSignalThreshold,
|
||||
double blueSignalThreshold,
|
||||
int noSignalCounterThreshold);
|
||||
void setSignalThreshold(double redSignalThreshold,
|
||||
double greenSignalThreshold,
|
||||
double blueSignalThreshold,
|
||||
int noSignalCounterThreshold);
|
||||
|
||||
void start();
|
||||
void start();
|
||||
|
||||
void stop();
|
||||
void stop();
|
||||
|
||||
signals:
|
||||
void newFrame(const Image<ColorRgb> & image);
|
||||
void newFrame(const Image<ColorRgb> & image);
|
||||
|
||||
private slots:
|
||||
int read_frame();
|
||||
int read_frame();
|
||||
|
||||
private:
|
||||
void open_device();
|
||||
void open_device();
|
||||
|
||||
void close_device();
|
||||
void close_device();
|
||||
|
||||
void init_read(unsigned int buffer_size);
|
||||
void init_read(unsigned int buffer_size);
|
||||
|
||||
void init_mmap();
|
||||
void init_mmap();
|
||||
|
||||
void init_userp(unsigned int buffer_size);
|
||||
void init_userp(unsigned int buffer_size);
|
||||
|
||||
void init_device(VideoStandard videoStandard, int input);
|
||||
void init_device(VideoStandard videoStandard, int input);
|
||||
|
||||
void uninit_device();
|
||||
void uninit_device();
|
||||
|
||||
void start_capturing();
|
||||
void start_capturing();
|
||||
|
||||
void stop_capturing();
|
||||
void stop_capturing();
|
||||
|
||||
bool process_image(const void *p, int size);
|
||||
bool process_image(const void *p, int size);
|
||||
|
||||
void process_image(const uint8_t *p);
|
||||
void process_image(const uint8_t *p);
|
||||
|
||||
int xioctl(int request, void *arg);
|
||||
int xioctl(int request, void *arg);
|
||||
|
||||
void throw_exception(const std::string &error);
|
||||
void throw_exception(const std::string &error);
|
||||
|
||||
void throw_errno_exception(const std::string &error);
|
||||
void throw_errno_exception(const std::string &error);
|
||||
|
||||
private:
|
||||
enum io_method {
|
||||
IO_METHOD_READ,
|
||||
IO_METHOD_MMAP,
|
||||
IO_METHOD_USERPTR
|
||||
};
|
||||
enum io_method {
|
||||
IO_METHOD_READ,
|
||||
IO_METHOD_MMAP,
|
||||
IO_METHOD_USERPTR
|
||||
};
|
||||
|
||||
struct buffer {
|
||||
void *start;
|
||||
size_t length;
|
||||
};
|
||||
struct buffer {
|
||||
void *start;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
private:
|
||||
const std::string _deviceName;
|
||||
const io_method _ioMethod;
|
||||
int _fileDescriptor;
|
||||
std::vector<buffer> _buffers;
|
||||
const std::string _deviceName;
|
||||
const io_method _ioMethod;
|
||||
int _fileDescriptor;
|
||||
std::vector<buffer> _buffers;
|
||||
|
||||
PixelFormat _pixelFormat;
|
||||
int _width;
|
||||
int _height;
|
||||
int _lineLength;
|
||||
int _frameByteSize;
|
||||
int _frameDecimation;
|
||||
int _noSignalCounterThreshold;
|
||||
PixelFormat _pixelFormat;
|
||||
int _width;
|
||||
int _height;
|
||||
int _lineLength;
|
||||
int _frameByteSize;
|
||||
int _frameDecimation;
|
||||
int _noSignalCounterThreshold;
|
||||
|
||||
ColorRgb _noSignalThresholdColor;
|
||||
ColorRgb _noSignalThresholdColor;
|
||||
|
||||
int _currentFrame;
|
||||
int _noSignalCounter;
|
||||
int _currentFrame;
|
||||
int _noSignalCounter;
|
||||
|
||||
QSocketNotifier * _streamNotifier;
|
||||
QSocketNotifier * _streamNotifier;
|
||||
|
||||
ImageResampler _imageResampler;
|
||||
ImageResampler _imageResampler;
|
||||
};
|
||||
|
@ -15,7 +15,7 @@ class X11Grabber
|
||||
{
|
||||
public:
|
||||
|
||||
X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation);
|
||||
X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation);
|
||||
|
||||
virtual ~X11Grabber();
|
||||
|
||||
@ -26,16 +26,16 @@ public:
|
||||
Image<ColorRgb> & grab();
|
||||
|
||||
private:
|
||||
ImageResampler _imageResampler;
|
||||
|
||||
bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable;
|
||||
int _cropLeft;
|
||||
int _cropRight;
|
||||
int _cropTop;
|
||||
int _cropBottom;
|
||||
|
||||
XImage* _xImage;
|
||||
XShmSegmentInfo _shminfo;
|
||||
ImageResampler _imageResampler;
|
||||
|
||||
bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable;
|
||||
int _cropLeft;
|
||||
int _cropRight;
|
||||
int _cropTop;
|
||||
int _cropBottom;
|
||||
|
||||
XImage* _xImage;
|
||||
XShmSegmentInfo _shminfo;
|
||||
|
||||
/// Reference to the X11 display (nullptr if not opened)
|
||||
Display* _x11Display;
|
||||
|
@ -23,90 +23,90 @@
|
||||
class ProtoConnection : public QObject
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
/// @param address The address of the Hyperion server (for example "192.168.0.32:19444)
|
||||
///
|
||||
ProtoConnection(const std::string & address);
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
/// @param address The address of the Hyperion server (for example "192.168.0.32:19444)
|
||||
///
|
||||
ProtoConnection(const std::string & address);
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
~ProtoConnection();
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
~ProtoConnection();
|
||||
|
||||
/// Do not read reply messages from Hyperion if set to true
|
||||
void setSkipReply(bool skip);
|
||||
/// Do not read reply messages from Hyperion if set to true
|
||||
void setSkipReply(bool skip);
|
||||
|
||||
///
|
||||
/// Set all leds to the specified color
|
||||
///
|
||||
/// @param color The color
|
||||
/// @param priority The priority
|
||||
/// @param duration The duration in milliseconds
|
||||
///
|
||||
void setColor(const ColorRgb & color, int priority, int duration = 1);
|
||||
///
|
||||
/// Set all leds to the specified color
|
||||
///
|
||||
/// @param color The color
|
||||
/// @param priority The priority
|
||||
/// @param duration The duration in milliseconds
|
||||
///
|
||||
void setColor(const ColorRgb & color, int priority, int duration = 1);
|
||||
|
||||
///
|
||||
/// Set the leds according to the given image (assume the image is stretched to the display size)
|
||||
///
|
||||
/// @param image The image
|
||||
/// @param priority The priority
|
||||
/// @param duration The duration in milliseconds
|
||||
///
|
||||
void setImage(const Image<ColorRgb> & image, int priority, int duration = -1);
|
||||
///
|
||||
/// Set the leds according to the given image (assume the image is stretched to the display size)
|
||||
///
|
||||
/// @param image The image
|
||||
/// @param priority The priority
|
||||
/// @param duration The duration in milliseconds
|
||||
///
|
||||
void setImage(const Image<ColorRgb> & image, int priority, int duration = -1);
|
||||
|
||||
///
|
||||
/// Clear the given priority channel
|
||||
///
|
||||
/// @param priority The priority
|
||||
///
|
||||
void clear(int priority);
|
||||
///
|
||||
/// Clear the given priority channel
|
||||
///
|
||||
/// @param priority The priority
|
||||
///
|
||||
void clear(int priority);
|
||||
|
||||
///
|
||||
/// Clear all priority channels
|
||||
///
|
||||
void clearAll();
|
||||
///
|
||||
/// Clear all priority channels
|
||||
///
|
||||
void clearAll();
|
||||
|
||||
///
|
||||
/// Send a command message and receive its reply
|
||||
///
|
||||
/// @param message The message to send
|
||||
///
|
||||
void sendMessage(const proto::HyperionRequest & message);
|
||||
///
|
||||
/// Send a command message and receive its reply
|
||||
///
|
||||
/// @param message The message to send
|
||||
///
|
||||
void sendMessage(const proto::HyperionRequest & message);
|
||||
|
||||
private slots:
|
||||
/// Try to connect to the Hyperion host
|
||||
void connectToHost();
|
||||
/// Try to connect to the Hyperion host
|
||||
void connectToHost();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
///
|
||||
/// Parse a reply message
|
||||
///
|
||||
/// @param reply The received reply
|
||||
///
|
||||
/// @return true if the reply indicates success
|
||||
///
|
||||
bool parseReply(const proto::HyperionReply & reply);
|
||||
///
|
||||
/// Parse a reply message
|
||||
///
|
||||
/// @param reply The received reply
|
||||
///
|
||||
/// @return true if the reply indicates success
|
||||
///
|
||||
bool parseReply(const proto::HyperionReply & reply);
|
||||
|
||||
private:
|
||||
/// The TCP-Socket with the connection to the server
|
||||
QTcpSocket _socket;
|
||||
/// The TCP-Socket with the connection to the server
|
||||
QTcpSocket _socket;
|
||||
|
||||
/// Host address
|
||||
QString _host;
|
||||
/// Host address
|
||||
QString _host;
|
||||
|
||||
/// Host port
|
||||
uint16_t _port;
|
||||
/// Host port
|
||||
uint16_t _port;
|
||||
|
||||
/// Skip receiving reply messages from Hyperion if set
|
||||
bool _skipReply;
|
||||
/// Skip receiving reply messages from Hyperion if set
|
||||
bool _skipReply;
|
||||
|
||||
QTimer _timer;
|
||||
QAbstractSocket::SocketState _prevSocketState;
|
||||
QTimer _timer;
|
||||
QAbstractSocket::SocketState _prevSocketState;
|
||||
};
|
||||
|
@ -11,24 +11,24 @@
|
||||
/// This class handles callbacks from the V4L2 grabber
|
||||
class ProtoConnectionWrapper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ProtoConnectionWrapper(const std::string & address, int priority, int duration_ms, bool skipProtoReply);
|
||||
virtual ~ProtoConnectionWrapper();
|
||||
ProtoConnectionWrapper(const std::string & address, int priority, int duration_ms, bool skipProtoReply);
|
||||
virtual ~ProtoConnectionWrapper();
|
||||
|
||||
public slots:
|
||||
/// Handle a single image
|
||||
/// @param image The image to process
|
||||
void receiveImage(const Image<ColorRgb> & image);
|
||||
/// Handle a single image
|
||||
/// @param image The image to process
|
||||
void receiveImage(const Image<ColorRgb> & image);
|
||||
|
||||
private:
|
||||
/// Priority for calls to Hyperion
|
||||
const int _priority;
|
||||
/// Priority for calls to Hyperion
|
||||
const int _priority;
|
||||
|
||||
/// Duration for color calls to Hyperion
|
||||
const int _duration_ms;
|
||||
/// Duration for color calls to Hyperion
|
||||
const int _duration_ms;
|
||||
|
||||
/// Hyperion proto connection object
|
||||
ProtoConnection _connection;
|
||||
/// Hyperion proto connection object
|
||||
ProtoConnection _connection;
|
||||
};
|
||||
|
@ -13,221 +13,221 @@ class Image
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Pixel_T pixel_type;
|
||||
typedef Pixel_T pixel_type;
|
||||
|
||||
///
|
||||
/// Default constructor for an image
|
||||
///
|
||||
Image() :
|
||||
_width(1),
|
||||
_height(1),
|
||||
_pixels(new Pixel_T[2]),
|
||||
_endOfPixels(_pixels + 1)
|
||||
{
|
||||
memset(_pixels, 0, 2*sizeof(Pixel_T));
|
||||
}
|
||||
///
|
||||
/// Default constructor for an image
|
||||
///
|
||||
Image() :
|
||||
_width(1),
|
||||
_height(1),
|
||||
_pixels(new Pixel_T[2]),
|
||||
_endOfPixels(_pixels + 1)
|
||||
{
|
||||
memset(_pixels, 0, 2*sizeof(Pixel_T));
|
||||
}
|
||||
|
||||
///
|
||||
/// Constructor for an image with specified width and height
|
||||
///
|
||||
/// @param width The width of the image
|
||||
/// @param height The height of the image
|
||||
///
|
||||
Image(const unsigned width, const unsigned height) :
|
||||
_width(width),
|
||||
_height(height),
|
||||
_pixels(new Pixel_T[width * height + 1]),
|
||||
_endOfPixels(_pixels + width * height)
|
||||
{
|
||||
memset(_pixels, 0, (_width*_height+1)*sizeof(Pixel_T));
|
||||
}
|
||||
///
|
||||
/// Constructor for an image with specified width and height
|
||||
///
|
||||
/// @param width The width of the image
|
||||
/// @param height The height of the image
|
||||
///
|
||||
Image(const unsigned width, const unsigned height) :
|
||||
_width(width),
|
||||
_height(height),
|
||||
_pixels(new Pixel_T[width * height + 1]),
|
||||
_endOfPixels(_pixels + width * height)
|
||||
{
|
||||
memset(_pixels, 0, (_width*_height+1)*sizeof(Pixel_T));
|
||||
}
|
||||
|
||||
///
|
||||
/// Constructor for an image with specified width and height
|
||||
///
|
||||
/// @param width The width of the image
|
||||
/// @param height The height of the image
|
||||
/// @param background The color of the image
|
||||
///
|
||||
Image(const unsigned width, const unsigned height, const Pixel_T background) :
|
||||
_width(width),
|
||||
_height(height),
|
||||
_pixels(new Pixel_T[width * height + 1]),
|
||||
_endOfPixels(_pixels + width * height)
|
||||
{
|
||||
std::fill(_pixels, _endOfPixels, background);
|
||||
}
|
||||
///
|
||||
/// Constructor for an image with specified width and height
|
||||
///
|
||||
/// @param width The width of the image
|
||||
/// @param height The height of the image
|
||||
/// @param background The color of the image
|
||||
///
|
||||
Image(const unsigned width, const unsigned height, const Pixel_T background) :
|
||||
_width(width),
|
||||
_height(height),
|
||||
_pixels(new Pixel_T[width * height + 1]),
|
||||
_endOfPixels(_pixels + width * height)
|
||||
{
|
||||
std::fill(_pixels, _endOfPixels, background);
|
||||
}
|
||||
|
||||
///
|
||||
/// Copy constructor for an image
|
||||
///
|
||||
Image(const Image & other) :
|
||||
_width(other._width),
|
||||
_height(other._height),
|
||||
_pixels(new Pixel_T[other._width * other._height + 1]),
|
||||
_endOfPixels(_pixels + other._width * other._height)
|
||||
{
|
||||
memcpy(_pixels, other._pixels, other._width * other._height * sizeof(Pixel_T));
|
||||
}
|
||||
///
|
||||
/// Copy constructor for an image
|
||||
///
|
||||
Image(const Image & other) :
|
||||
_width(other._width),
|
||||
_height(other._height),
|
||||
_pixels(new Pixel_T[other._width * other._height + 1]),
|
||||
_endOfPixels(_pixels + other._width * other._height)
|
||||
{
|
||||
memcpy(_pixels, other._pixels, other._width * other._height * sizeof(Pixel_T));
|
||||
}
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
~Image()
|
||||
{
|
||||
delete[] _pixels;
|
||||
}
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
~Image()
|
||||
{
|
||||
delete[] _pixels;
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns the width of the image
|
||||
///
|
||||
/// @return The width of the image
|
||||
///
|
||||
inline unsigned width() const
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
///
|
||||
/// Returns the width of the image
|
||||
///
|
||||
/// @return The width of the image
|
||||
///
|
||||
inline unsigned width() const
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns the height of the image
|
||||
///
|
||||
/// @return The height of the image
|
||||
///
|
||||
inline unsigned height() const
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
///
|
||||
/// Returns the height of the image
|
||||
///
|
||||
/// @return The height of the image
|
||||
///
|
||||
inline unsigned height() const
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
uint8_t red(const unsigned pixel) const
|
||||
{
|
||||
return (_pixels + pixel)->red;
|
||||
}
|
||||
uint8_t red(const unsigned pixel) const
|
||||
{
|
||||
return (_pixels + pixel)->red;
|
||||
}
|
||||
|
||||
uint8_t green(const unsigned pixel) const
|
||||
{
|
||||
return (_pixels + pixel)->green;
|
||||
}
|
||||
uint8_t green(const unsigned pixel) const
|
||||
{
|
||||
return (_pixels + pixel)->green;
|
||||
}
|
||||
|
||||
uint8_t blue(const unsigned pixel) const
|
||||
{
|
||||
return (_pixels + pixel)->blue;
|
||||
}
|
||||
uint8_t blue(const unsigned pixel) const
|
||||
{
|
||||
return (_pixels + pixel)->blue;
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a const reference to a specified pixel in the image
|
||||
///
|
||||
/// @param x The x index
|
||||
/// @param y The y index
|
||||
///
|
||||
/// @return const reference to specified pixel
|
||||
///
|
||||
const Pixel_T& operator()(const unsigned x, const unsigned y) const
|
||||
{
|
||||
return _pixels[toIndex(x,y)];
|
||||
}
|
||||
///
|
||||
/// Returns a const reference to a specified pixel in the image
|
||||
///
|
||||
/// @param x The x index
|
||||
/// @param y The y index
|
||||
///
|
||||
/// @return const reference to specified pixel
|
||||
///
|
||||
const Pixel_T& operator()(const unsigned x, const unsigned y) const
|
||||
{
|
||||
return _pixels[toIndex(x,y)];
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a reference to a specified pixel in the image
|
||||
///
|
||||
/// @param x The x index
|
||||
/// @param y The y index
|
||||
///
|
||||
/// @return reference to specified pixel
|
||||
///
|
||||
Pixel_T& operator()(const unsigned x, const unsigned y)
|
||||
{
|
||||
return _pixels[toIndex(x,y)];
|
||||
}
|
||||
///
|
||||
/// Returns a reference to a specified pixel in the image
|
||||
///
|
||||
/// @param x The x index
|
||||
/// @param y The y index
|
||||
///
|
||||
/// @return reference to specified pixel
|
||||
///
|
||||
Pixel_T& operator()(const unsigned x, const unsigned y)
|
||||
{
|
||||
return _pixels[toIndex(x,y)];
|
||||
}
|
||||
|
||||
/// Resize the image
|
||||
/// @param width The width of the image
|
||||
/// @param height The height of the image
|
||||
void resize(const unsigned width, const unsigned height)
|
||||
{
|
||||
if ((width*height) > unsigned((_endOfPixels-_pixels)))
|
||||
{
|
||||
delete[] _pixels;
|
||||
_pixels = new Pixel_T[width*height + 1];
|
||||
_endOfPixels = _pixels + width*height;
|
||||
}
|
||||
/// Resize the image
|
||||
/// @param width The width of the image
|
||||
/// @param height The height of the image
|
||||
void resize(const unsigned width, const unsigned height)
|
||||
{
|
||||
if ((width*height) > unsigned((_endOfPixels-_pixels)))
|
||||
{
|
||||
delete[] _pixels;
|
||||
_pixels = new Pixel_T[width*height + 1];
|
||||
_endOfPixels = _pixels + width*height;
|
||||
}
|
||||
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
///
|
||||
/// Copies another image into this image. The images should have exactly the same size.
|
||||
///
|
||||
/// @param other The image to copy into this
|
||||
///
|
||||
void copy(const Image<Pixel_T>& other)
|
||||
{
|
||||
assert(other._width == _width);
|
||||
assert(other._height == _height);
|
||||
///
|
||||
/// Copies another image into this image. The images should have exactly the same size.
|
||||
///
|
||||
/// @param other The image to copy into this
|
||||
///
|
||||
void copy(const Image<Pixel_T>& other)
|
||||
{
|
||||
assert(other._width == _width);
|
||||
assert(other._height == _height);
|
||||
|
||||
memcpy(_pixels, other._pixels, _width*_height*sizeof(Pixel_T));
|
||||
}
|
||||
memcpy(_pixels, other._pixels, _width*_height*sizeof(Pixel_T));
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a memory pointer to the first pixel in the image
|
||||
/// @return The memory pointer to the first pixel
|
||||
///
|
||||
Pixel_T* memptr()
|
||||
{
|
||||
return _pixels;
|
||||
}
|
||||
///
|
||||
/// Returns a memory pointer to the first pixel in the image
|
||||
/// @return The memory pointer to the first pixel
|
||||
///
|
||||
Pixel_T* memptr()
|
||||
{
|
||||
return _pixels;
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a const memory pointer to the first pixel in the image
|
||||
/// @return The const memory pointer to the first pixel
|
||||
///
|
||||
const Pixel_T* memptr() const
|
||||
{
|
||||
return _pixels;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Convert image of any color order to a RGB image.
|
||||
///
|
||||
/// @param[out] image The image that buffers the output
|
||||
///
|
||||
void toRgb(Image<ColorRgb>& image)
|
||||
{
|
||||
image.resize(_width, _height);
|
||||
const unsigned imageSize = _width * _height;
|
||||
///
|
||||
/// Returns a const memory pointer to the first pixel in the image
|
||||
/// @return The const memory pointer to the first pixel
|
||||
///
|
||||
const Pixel_T* memptr() const
|
||||
{
|
||||
return _pixels;
|
||||
}
|
||||
|
||||
for (unsigned idx=0; idx<imageSize; idx++)
|
||||
{
|
||||
const Pixel_T color = memptr()[idx];
|
||||
image.memptr()[idx] = ColorRgb{color.red, color.green, color.blue};
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// 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:
|
||||
|
||||
///
|
||||
/// Translate x and y coordinate to index of the underlying vector
|
||||
///
|
||||
/// @param x The x index
|
||||
/// @param y The y index
|
||||
///
|
||||
/// @return The index into the underlying data-vector
|
||||
///
|
||||
inline unsigned toIndex(const unsigned x, const unsigned y) const
|
||||
{
|
||||
return y*_width + x;
|
||||
}
|
||||
///
|
||||
/// Translate x and y coordinate to index of the underlying vector
|
||||
///
|
||||
/// @param x The x index
|
||||
/// @param y The y index
|
||||
///
|
||||
/// @return The index into the underlying data-vector
|
||||
///
|
||||
inline unsigned toIndex(const unsigned x, const unsigned y) const
|
||||
{
|
||||
return y*_width + x;
|
||||
}
|
||||
|
||||
private:
|
||||
/// The width of the image
|
||||
unsigned _width;
|
||||
/// The height of the image
|
||||
unsigned _height;
|
||||
/// The width of the image
|
||||
unsigned _width;
|
||||
/// The height of the image
|
||||
unsigned _height;
|
||||
|
||||
/// The pixels of the image
|
||||
Pixel_T* _pixels;
|
||||
/// The pixels of the image
|
||||
Pixel_T* _pixels;
|
||||
|
||||
/// Pointer to the last(extra) pixel
|
||||
Pixel_T* _endOfPixels;
|
||||
/// Pointer to the last(extra) pixel
|
||||
Pixel_T* _endOfPixels;
|
||||
};
|
||||
|
@ -8,22 +8,21 @@
|
||||
class ImageResampler
|
||||
{
|
||||
public:
|
||||
ImageResampler();
|
||||
~ImageResampler();
|
||||
ImageResampler();
|
||||
~ImageResampler();
|
||||
|
||||
void setHorizontalPixelDecimation(int decimator);
|
||||
void setHorizontalPixelDecimation(int decimator);
|
||||
|
||||
void setVerticalPixelDecimation(int decimator);
|
||||
void setVerticalPixelDecimation(int decimator);
|
||||
|
||||
void setCropping(int cropLeft,
|
||||
int cropRight,
|
||||
int cropTop,
|
||||
int cropBottom);
|
||||
void setCropping(int cropLeft,
|
||||
int cropRight,
|
||||
int cropTop,
|
||||
int cropBottom);
|
||||
|
||||
void set3D(VideoMode mode);
|
||||
void set3D(VideoMode mode);
|
||||
|
||||
void processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat,
|
||||
Image<ColorRgb> & outputImage) const;
|
||||
void processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat, Image<ColorRgb> & outputImage) const;
|
||||
|
||||
private:
|
||||
static inline uint8_t clamp(int x);
|
||||
|
@ -11,9 +11,9 @@ enum PixelFormat {
|
||||
PIXELFORMAT_UYVY,
|
||||
PIXELFORMAT_BGR16,
|
||||
PIXELFORMAT_BGR24,
|
||||
PIXELFORMAT_RGB32,
|
||||
PIXELFORMAT_BGR32,
|
||||
PIXELFORMAT_NO_CHANGE
|
||||
PIXELFORMAT_RGB32,
|
||||
PIXELFORMAT_BGR32,
|
||||
PIXELFORMAT_NO_CHANGE
|
||||
};
|
||||
|
||||
inline PixelFormat parsePixelFormat(std::string pixelFormat)
|
||||
@ -29,22 +29,22 @@ inline PixelFormat parsePixelFormat(std::string pixelFormat)
|
||||
{
|
||||
return PIXELFORMAT_UYVY;
|
||||
}
|
||||
else if (pixelFormat == "bgr16")
|
||||
{
|
||||
return PIXELFORMAT_BGR16;
|
||||
}
|
||||
else if (pixelFormat == "bgr24")
|
||||
{
|
||||
return PIXELFORMAT_BGR24;
|
||||
}
|
||||
else if (pixelFormat == "rgb32")
|
||||
{
|
||||
return PIXELFORMAT_RGB32;
|
||||
}
|
||||
else if (pixelFormat == "bgr32")
|
||||
{
|
||||
return PIXELFORMAT_BGR32;
|
||||
}
|
||||
else if (pixelFormat == "bgr16")
|
||||
{
|
||||
return PIXELFORMAT_BGR16;
|
||||
}
|
||||
else if (pixelFormat == "bgr24")
|
||||
{
|
||||
return PIXELFORMAT_BGR24;
|
||||
}
|
||||
else if (pixelFormat == "rgb32")
|
||||
{
|
||||
return PIXELFORMAT_RGB32;
|
||||
}
|
||||
else if (pixelFormat == "bgr32")
|
||||
{
|
||||
return PIXELFORMAT_BGR32;
|
||||
}
|
||||
|
||||
// return the default NO_CHANGE
|
||||
return PIXELFORMAT_NO_CHANGE;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
class Sleep : protected QThread {
|
||||
public:
|
||||
static inline void msleep(unsigned long msecs) {
|
||||
QThread::msleep(msecs);
|
||||
}
|
||||
static inline void msleep(unsigned long msecs) {
|
||||
QThread::msleep(msecs);
|
||||
}
|
||||
};
|
||||
|
@ -1,192 +1,192 @@
|
||||
#pragma once
|
||||
|
||||
// stl includes
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
// jsoncpp includes
|
||||
#include <json/json.h>
|
||||
|
||||
|
||||
/// JsonSchemaChecker is a very basic implementation of json schema.
|
||||
/// The json schema definition draft can be found at
|
||||
/// http://tools.ietf.org/html/draft-zyp-json-schema-03
|
||||
///
|
||||
/// The following keywords are supported:
|
||||
/// - type
|
||||
/// - required
|
||||
/// - properties
|
||||
/// - items
|
||||
/// - enum
|
||||
/// - minimum
|
||||
/// - maximum
|
||||
/// - addtionalProperties
|
||||
/// - minItems
|
||||
/// - maxItems
|
||||
///
|
||||
/// And the non-standard:
|
||||
/// - dependencies
|
||||
class JsonSchemaChecker
|
||||
{
|
||||
public:
|
||||
JsonSchemaChecker();
|
||||
virtual ~JsonSchemaChecker();
|
||||
|
||||
///
|
||||
/// @param schema The schema to use
|
||||
/// @return true upon succes
|
||||
///
|
||||
bool setSchema(const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// @brief Validate a JSON structure
|
||||
/// @param value The JSON value to check
|
||||
/// @return true when the arguments is valid according to the schema
|
||||
///
|
||||
bool validate(const Json::Value & value);
|
||||
|
||||
///
|
||||
/// @return A list of error messages
|
||||
///
|
||||
const std::list<std::string> & getMessages() const;
|
||||
|
||||
private:
|
||||
///
|
||||
/// Validates a json-value against a given schema. Results are stored in the members of this
|
||||
/// class (_error & _messages)
|
||||
///
|
||||
/// @param[in] value The value to validate
|
||||
/// @param[in] schema The schema against which the value is validated
|
||||
///
|
||||
void validate(const Json::Value &value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Adds the given message to the message-queue (with reference to current line-number)
|
||||
///
|
||||
/// @param[in] message The message to add to the queue
|
||||
///
|
||||
void setMessage(const std::string & message);
|
||||
|
||||
///
|
||||
/// Retrieves all references from the json-value as specified by the schema
|
||||
///
|
||||
/// @param[in] value The json-value
|
||||
/// @param[in] schema The schema
|
||||
///
|
||||
void collectDependencies(const Json::Value & value, const Json::Value &schema);
|
||||
|
||||
private:
|
||||
// attribute check functions
|
||||
///
|
||||
/// Checks if the given value is of the specified type. If the type does not match _error is set
|
||||
/// to true and an error-message is added to the message-queue
|
||||
///
|
||||
/// @param[in] value The given value
|
||||
/// @param[in] schema The specified type (as json-value)
|
||||
///
|
||||
void checkType(const Json::Value & value, const Json::Value & schema);
|
||||
///
|
||||
/// Checks is required properties of an json-object exist and if all properties are of the
|
||||
/// correct format. If this is not the case _error is set to true and an error-message is added
|
||||
/// to the message-queue.
|
||||
///
|
||||
/// @param[in] value The given json-object
|
||||
/// @param[in] schema The schema of the json-object
|
||||
///
|
||||
void checkProperties(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Verifies the additional configured properties of an json-object. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The given json-object
|
||||
/// @param schema The schema for the json-object
|
||||
/// @param ignoredProperties The properties that were ignored
|
||||
///
|
||||
void checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties);
|
||||
|
||||
///
|
||||
/// Checks if references are configued and used correctly. If this is not the case _error is set
|
||||
/// to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The given json-object
|
||||
/// @param schemaLink The schema of the json-object
|
||||
///
|
||||
void checkDependencies(const Json::Value & value, const Json::Value & schemaLink);
|
||||
|
||||
///
|
||||
/// Checks if the given value is larger or equal to the specified value. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param[in] value The given value
|
||||
/// @param[in] schema The minimum value (as json-value)
|
||||
///
|
||||
void checkMinimum(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if the given value is smaller or equal to the specified value. If this is not the
|
||||
/// case _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param[in] value The given value
|
||||
/// @param[in] schema The maximum value (as json-value)
|
||||
///
|
||||
void checkMaximum(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Validates all the items of an array.
|
||||
///
|
||||
/// @param value The json-array
|
||||
/// @param schema The schema for the items in the array
|
||||
///
|
||||
void checkItems(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if a given array has at least a minimum number of items. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The json-array
|
||||
/// @param schema The minimum size specification (as json-value)
|
||||
///
|
||||
void checkMinItems(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if a given array has at most a maximum number of items. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The json-array
|
||||
/// @param schema The maximum size specification (as json-value)
|
||||
///
|
||||
void checkMaxItems(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if a given array contains only unique items. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The json-array
|
||||
/// @param schema Bool to enable the check (as json-value)
|
||||
///
|
||||
void checkUniqueItems(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if an enum value is actually a valid value for that enum. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The enum value
|
||||
/// @param schema The enum schema definition
|
||||
///
|
||||
void checkEnum(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
private:
|
||||
/// The schema of the entire json-configuration
|
||||
Json::Value _schema;
|
||||
|
||||
/// The current location into a json-configuration structure being checked
|
||||
std::list<std::string> _currentPath;
|
||||
/// The result messages collected during the schema verification
|
||||
std::list<std::string> _messages;
|
||||
/// Flag indicating an error occured during validation
|
||||
bool _error;
|
||||
|
||||
/// A list with references (string => json-value)
|
||||
std::map<std::string, const Json::Value *> _references; // ref 2 value
|
||||
};
|
||||
#pragma once
|
||||
|
||||
// stl includes
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
// jsoncpp includes
|
||||
#include <json/json.h>
|
||||
|
||||
|
||||
/// JsonSchemaChecker is a very basic implementation of json schema.
|
||||
/// The json schema definition draft can be found at
|
||||
/// http://tools.ietf.org/html/draft-zyp-json-schema-03
|
||||
///
|
||||
/// The following keywords are supported:
|
||||
/// - type
|
||||
/// - required
|
||||
/// - properties
|
||||
/// - items
|
||||
/// - enum
|
||||
/// - minimum
|
||||
/// - maximum
|
||||
/// - addtionalProperties
|
||||
/// - minItems
|
||||
/// - maxItems
|
||||
///
|
||||
/// And the non-standard:
|
||||
/// - dependencies
|
||||
class JsonSchemaChecker
|
||||
{
|
||||
public:
|
||||
JsonSchemaChecker();
|
||||
virtual ~JsonSchemaChecker();
|
||||
|
||||
///
|
||||
/// @param schema The schema to use
|
||||
/// @return true upon succes
|
||||
///
|
||||
bool setSchema(const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// @brief Validate a JSON structure
|
||||
/// @param value The JSON value to check
|
||||
/// @return true when the arguments is valid according to the schema
|
||||
///
|
||||
bool validate(const Json::Value & value);
|
||||
|
||||
///
|
||||
/// @return A list of error messages
|
||||
///
|
||||
const std::list<std::string> & getMessages() const;
|
||||
|
||||
private:
|
||||
///
|
||||
/// Validates a json-value against a given schema. Results are stored in the members of this
|
||||
/// class (_error & _messages)
|
||||
///
|
||||
/// @param[in] value The value to validate
|
||||
/// @param[in] schema The schema against which the value is validated
|
||||
///
|
||||
void validate(const Json::Value &value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Adds the given message to the message-queue (with reference to current line-number)
|
||||
///
|
||||
/// @param[in] message The message to add to the queue
|
||||
///
|
||||
void setMessage(const std::string & message);
|
||||
|
||||
///
|
||||
/// Retrieves all references from the json-value as specified by the schema
|
||||
///
|
||||
/// @param[in] value The json-value
|
||||
/// @param[in] schema The schema
|
||||
///
|
||||
void collectDependencies(const Json::Value & value, const Json::Value &schema);
|
||||
|
||||
private:
|
||||
// attribute check functions
|
||||
///
|
||||
/// Checks if the given value is of the specified type. If the type does not match _error is set
|
||||
/// to true and an error-message is added to the message-queue
|
||||
///
|
||||
/// @param[in] value The given value
|
||||
/// @param[in] schema The specified type (as json-value)
|
||||
///
|
||||
void checkType(const Json::Value & value, const Json::Value & schema);
|
||||
///
|
||||
/// Checks is required properties of an json-object exist and if all properties are of the
|
||||
/// correct format. If this is not the case _error is set to true and an error-message is added
|
||||
/// to the message-queue.
|
||||
///
|
||||
/// @param[in] value The given json-object
|
||||
/// @param[in] schema The schema of the json-object
|
||||
///
|
||||
void checkProperties(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Verifies the additional configured properties of an json-object. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The given json-object
|
||||
/// @param schema The schema for the json-object
|
||||
/// @param ignoredProperties The properties that were ignored
|
||||
///
|
||||
void checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties);
|
||||
|
||||
///
|
||||
/// Checks if references are configued and used correctly. If this is not the case _error is set
|
||||
/// to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The given json-object
|
||||
/// @param schemaLink The schema of the json-object
|
||||
///
|
||||
void checkDependencies(const Json::Value & value, const Json::Value & schemaLink);
|
||||
|
||||
///
|
||||
/// Checks if the given value is larger or equal to the specified value. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param[in] value The given value
|
||||
/// @param[in] schema The minimum value (as json-value)
|
||||
///
|
||||
void checkMinimum(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if the given value is smaller or equal to the specified value. If this is not the
|
||||
/// case _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param[in] value The given value
|
||||
/// @param[in] schema The maximum value (as json-value)
|
||||
///
|
||||
void checkMaximum(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Validates all the items of an array.
|
||||
///
|
||||
/// @param value The json-array
|
||||
/// @param schema The schema for the items in the array
|
||||
///
|
||||
void checkItems(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if a given array has at least a minimum number of items. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The json-array
|
||||
/// @param schema The minimum size specification (as json-value)
|
||||
///
|
||||
void checkMinItems(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if a given array has at most a maximum number of items. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The json-array
|
||||
/// @param schema The maximum size specification (as json-value)
|
||||
///
|
||||
void checkMaxItems(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if a given array contains only unique items. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The json-array
|
||||
/// @param schema Bool to enable the check (as json-value)
|
||||
///
|
||||
void checkUniqueItems(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if an enum value is actually a valid value for that enum. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The enum value
|
||||
/// @param schema The enum schema definition
|
||||
///
|
||||
void checkEnum(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
private:
|
||||
/// The schema of the entire json-configuration
|
||||
Json::Value _schema;
|
||||
|
||||
/// The current location into a json-configuration structure being checked
|
||||
std::list<std::string> _currentPath;
|
||||
/// The result messages collected during the schema verification
|
||||
std::list<std::string> _messages;
|
||||
/// Flag indicating an error occured during validation
|
||||
bool _error;
|
||||
|
||||
/// A list with references (string => json-value)
|
||||
std::map<std::string, const Json::Value *> _references; // ref 2 value
|
||||
};
|
||||
|
@ -9,7 +9,7 @@ add_subdirectory(jsonserver)
|
||||
|
||||
if (ENABLE_PROTOBUF)
|
||||
add_subdirectory(protoserver)
|
||||
endif (ENABLE_PROTOBUF)
|
||||
endif ()
|
||||
|
||||
add_subdirectory(boblightserver)
|
||||
add_subdirectory(leddevice)
|
||||
|
@ -1,23 +1,23 @@
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/blackborder)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/blackborder)
|
||||
|
||||
SET(Blackborder_HEADERS
|
||||
${CURRENT_HEADER_DIR}/BlackBorderDetector.h
|
||||
${CURRENT_HEADER_DIR}/BlackBorderProcessor.h
|
||||
)
|
||||
|
||||
SET(Blackborder_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/BlackBorderDetector.cpp
|
||||
${CURRENT_SOURCE_DIR}/BlackBorderProcessor.cpp
|
||||
)
|
||||
|
||||
add_library(blackborder
|
||||
${Blackborder_HEADERS}
|
||||
${Blackborder_SOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(blackborder
|
||||
hyperion-utils
|
||||
)
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/blackborder)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/blackborder)
|
||||
|
||||
SET(Blackborder_HEADERS
|
||||
${CURRENT_HEADER_DIR}/BlackBorderDetector.h
|
||||
${CURRENT_HEADER_DIR}/BlackBorderProcessor.h
|
||||
)
|
||||
|
||||
SET(Blackborder_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/BlackBorderDetector.cpp
|
||||
${CURRENT_SOURCE_DIR}/BlackBorderProcessor.cpp
|
||||
)
|
||||
|
||||
add_library(blackborder
|
||||
${Blackborder_HEADERS}
|
||||
${Blackborder_SOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(blackborder
|
||||
hyperion-utils
|
||||
)
|
||||
|
@ -1,40 +1,40 @@
|
||||
|
||||
# Define the current source locations
|
||||
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/boblightserver)
|
||||
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/boblightserver)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
set(BoblightServer_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/BoblightServer.h
|
||||
${CURRENT_SOURCE_DIR}/BoblightClientConnection.h
|
||||
)
|
||||
|
||||
set(BoblightServer_HEADERS
|
||||
)
|
||||
|
||||
set(BoblightServer_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/BoblightServer.cpp
|
||||
${CURRENT_SOURCE_DIR}/BoblightClientConnection.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_wrap_cpp(BoblightServer_HEADERS_MOC ${BoblightServer_QT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
qt4_wrap_cpp(BoblightServer_HEADERS_MOC ${BoblightServer_QT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_library(boblightserver
|
||||
${BoblightServer_HEADERS}
|
||||
${BoblightServer_QT_HEADERS}
|
||||
${BoblightServer_SOURCES}
|
||||
${BoblightServer_HEADERS_MOC}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(boblightserver Widgets)
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
target_link_libraries(boblightserver
|
||||
hyperion
|
||||
hyperion-utils
|
||||
${QT_LIBRARIES})
|
||||
|
||||
# Define the current source locations
|
||||
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/boblightserver)
|
||||
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/boblightserver)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
set(BoblightServer_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/BoblightServer.h
|
||||
${CURRENT_SOURCE_DIR}/BoblightClientConnection.h
|
||||
)
|
||||
|
||||
set(BoblightServer_HEADERS
|
||||
)
|
||||
|
||||
set(BoblightServer_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/BoblightServer.cpp
|
||||
${CURRENT_SOURCE_DIR}/BoblightClientConnection.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_wrap_cpp(BoblightServer_HEADERS_MOC ${BoblightServer_QT_HEADERS})
|
||||
else()
|
||||
qt4_wrap_cpp(BoblightServer_HEADERS_MOC ${BoblightServer_QT_HEADERS})
|
||||
endif()
|
||||
|
||||
add_library(boblightserver
|
||||
${BoblightServer_HEADERS}
|
||||
${BoblightServer_QT_HEADERS}
|
||||
${BoblightServer_SOURCES}
|
||||
${BoblightServer_HEADERS_MOC}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(boblightserver Widgets)
|
||||
endif()
|
||||
|
||||
target_link_libraries(boblightserver
|
||||
hyperion
|
||||
hyperion-utils
|
||||
${QT_LIBRARIES})
|
||||
|
@ -13,8 +13,8 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/effectengine)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(EffectEngineQT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/EffectEngine.h
|
||||
${CURRENT_SOURCE_DIR}/Effect.h
|
||||
${CURRENT_HEADER_DIR}/EffectEngine.h
|
||||
${CURRENT_SOURCE_DIR}/Effect.h
|
||||
)
|
||||
|
||||
SET(EffectEngineHEADERS
|
||||
@ -22,35 +22,34 @@ SET(EffectEngineHEADERS
|
||||
)
|
||||
|
||||
SET(EffectEngineSOURCES
|
||||
${CURRENT_SOURCE_DIR}/EffectEngine.cpp
|
||||
${CURRENT_SOURCE_DIR}/Effect.cpp
|
||||
${CURRENT_SOURCE_DIR}/EffectEngine.cpp
|
||||
${CURRENT_SOURCE_DIR}/Effect.cpp
|
||||
)
|
||||
|
||||
|
||||
set(EffectEngine_RESOURCES ${CURRENT_SOURCE_DIR}/EffectEngine.qrc)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS})
|
||||
qt5_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress")
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS})
|
||||
qt4_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress")
|
||||
endif(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS})
|
||||
qt5_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress")
|
||||
else()
|
||||
QT4_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS})
|
||||
qt4_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress")
|
||||
endif()
|
||||
|
||||
add_library(effectengine
|
||||
${EffectEngineHEADERS}
|
||||
${EffectEngineQT_HEADERS}
|
||||
${EffectEngineHEADERS_MOC}
|
||||
${EffectEngine_RESOURCES_RCC}
|
||||
${EffectEngineSOURCES}
|
||||
${EffectEngineHEADERS}
|
||||
${EffectEngineQT_HEADERS}
|
||||
${EffectEngineHEADERS_MOC}
|
||||
${EffectEngine_RESOURCES_RCC}
|
||||
${EffectEngineSOURCES}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(effectengine Widgets)
|
||||
endif(ENABLE_QT5)
|
||||
qt5_use_modules(effectengine Widgets)
|
||||
endif()
|
||||
|
||||
target_link_libraries(effectengine
|
||||
hyperion
|
||||
jsoncpp
|
||||
${QT_LIBRARIES}
|
||||
${PYTHON_LIBRARIES})
|
||||
hyperion
|
||||
jsoncpp
|
||||
${QT_LIBRARIES}
|
||||
${PYTHON_LIBRARIES})
|
||||
|
@ -1,342 +1,342 @@
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"properties" : {
|
||||
"device" : {
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"properties" : {
|
||||
"name" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"type" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"output" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"rate" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0
|
||||
},
|
||||
"colorOrder" : {
|
||||
"type" : "string",
|
||||
"required" : false
|
||||
},
|
||||
"bgr-output" : { // deprecated
|
||||
"type" : "boolean",
|
||||
"required" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"color": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties": {
|
||||
"hsv" : {
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"saturationGain" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
},
|
||||
"valueGain" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"red": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"green": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"blue": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"smoothing" : {
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"type" : {
|
||||
"type" : "enum",
|
||||
"required" : true,
|
||||
"values" : ["none", "linear"]
|
||||
},
|
||||
"time_ms" : {
|
||||
"type" : "integer",
|
||||
"required" : false,
|
||||
"minimum" : 10
|
||||
},
|
||||
"updateFrequency" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.001
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"leds": {
|
||||
"type":"array",
|
||||
"required":true,
|
||||
"items": {
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"index": {
|
||||
"type":"integer",
|
||||
"required":true
|
||||
},
|
||||
"hscan": {
|
||||
"type":"object",
|
||||
"required":true,
|
||||
"properties": {
|
||||
"minimum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
},
|
||||
"maximum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"vscan": {
|
||||
"type":"object",
|
||||
"required":true,
|
||||
"properties": {
|
||||
"minimum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
},
|
||||
"maximum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
"effects" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"paths" : {
|
||||
"type" : "array",
|
||||
"required" : false,
|
||||
"items" : {
|
||||
"type" : "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"blackborderdetector" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"enable" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"xbmcVideoChecker" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"xbmcAddress" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"xbmcTcpPort" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
},
|
||||
"grabVideo" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabPictures" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabAudio" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabMenu" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"bootsequence" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"path" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"effect" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"framegrabber" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"width" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
},
|
||||
"height" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
},
|
||||
"frequency_Hz" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"jsonServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"protoServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"boblightServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"properties" : {
|
||||
"device" : {
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"properties" : {
|
||||
"name" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"type" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"output" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"rate" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0
|
||||
},
|
||||
"colorOrder" : {
|
||||
"type" : "string",
|
||||
"required" : false
|
||||
},
|
||||
"bgr-output" : { // deprecated
|
||||
"type" : "boolean",
|
||||
"required" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"color": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties": {
|
||||
"hsv" : {
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"saturationGain" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
},
|
||||
"valueGain" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"red": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"green": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"blue": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"smoothing" : {
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"type" : {
|
||||
"type" : "enum",
|
||||
"required" : true,
|
||||
"values" : ["none", "linear"]
|
||||
},
|
||||
"time_ms" : {
|
||||
"type" : "integer",
|
||||
"required" : false,
|
||||
"minimum" : 10
|
||||
},
|
||||
"updateFrequency" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.001
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"leds": {
|
||||
"type":"array",
|
||||
"required":true,
|
||||
"items": {
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"index": {
|
||||
"type":"integer",
|
||||
"required":true
|
||||
},
|
||||
"hscan": {
|
||||
"type":"object",
|
||||
"required":true,
|
||||
"properties": {
|
||||
"minimum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
},
|
||||
"maximum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"vscan": {
|
||||
"type":"object",
|
||||
"required":true,
|
||||
"properties": {
|
||||
"minimum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
},
|
||||
"maximum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
"effects" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"paths" : {
|
||||
"type" : "array",
|
||||
"required" : false,
|
||||
"items" : {
|
||||
"type" : "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"blackborderdetector" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"enable" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"xbmcVideoChecker" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"xbmcAddress" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"xbmcTcpPort" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
},
|
||||
"grabVideo" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabPictures" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabAudio" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabMenu" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"bootsequence" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"path" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"effect" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"framegrabber" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"width" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
},
|
||||
"height" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
},
|
||||
"frequency_Hz" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"jsonServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"protoServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"boblightServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
|
@ -1,23 +1,23 @@
|
||||
if (ENABLE_AMLOGIC)
|
||||
add_subdirectory(amlogic)
|
||||
endif (ENABLE_AMLOGIC)
|
||||
|
||||
if (ENABLE_DISPMANX)
|
||||
add_subdirectory(dispmanx)
|
||||
endif (ENABLE_DISPMANX)
|
||||
|
||||
if (ENABLE_FB)
|
||||
add_subdirectory(framebuffer)
|
||||
endif (ENABLE_FB)
|
||||
|
||||
if (ENABLE_OSX)
|
||||
add_subdirectory(osx)
|
||||
endif()
|
||||
|
||||
if (ENABLE_V4L2)
|
||||
add_subdirectory(v4l2)
|
||||
endif (ENABLE_V4L2)
|
||||
|
||||
if (ENABLE_X11)
|
||||
add_subdirectory(x11)
|
||||
endif()
|
||||
if (ENABLE_AMLOGIC)
|
||||
add_subdirectory(amlogic)
|
||||
endif (ENABLE_AMLOGIC)
|
||||
|
||||
if (ENABLE_DISPMANX)
|
||||
add_subdirectory(dispmanx)
|
||||
endif (ENABLE_DISPMANX)
|
||||
|
||||
if (ENABLE_FB)
|
||||
add_subdirectory(framebuffer)
|
||||
endif (ENABLE_FB)
|
||||
|
||||
if (ENABLE_OSX)
|
||||
add_subdirectory(osx)
|
||||
endif()
|
||||
|
||||
if (ENABLE_V4L2)
|
||||
add_subdirectory(v4l2)
|
||||
endif (ENABLE_V4L2)
|
||||
|
||||
if (ENABLE_X11)
|
||||
add_subdirectory(x11)
|
||||
endif()
|
||||
|
@ -1,33 +1,33 @@
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/amlogic)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(AmlogicQT_HEADERS ${CURRENT_HEADER_DIR}/AmlogicWrapper.h)
|
||||
|
||||
SET(AmlogicHEADERS
|
||||
${CURRENT_HEADER_DIR}/AmlogicGrabber.h
|
||||
)
|
||||
|
||||
SET(AmlogicSOURCES
|
||||
${CURRENT_SOURCE_DIR}/AmlogicWrapper.cpp
|
||||
${CURRENT_SOURCE_DIR}/AmlogicGrabber.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(AmlogicHEADERS_MOC ${AmlogicQT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(AmlogicHEADERS_MOC ${AmlogicQT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_library(amlogic-grabber
|
||||
${AmlogicHEADERS}
|
||||
${AmlogicQT_HEADERS}
|
||||
${AmlogicHEADERS_MOC}
|
||||
${AmlogicSOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(amlogic-grabber
|
||||
hyperion
|
||||
${QT_LIBRARIES})
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/amlogic)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(AmlogicQT_HEADERS ${CURRENT_HEADER_DIR}/AmlogicWrapper.h)
|
||||
|
||||
SET(AmlogicHEADERS
|
||||
${CURRENT_HEADER_DIR}/AmlogicGrabber.h
|
||||
)
|
||||
|
||||
SET(AmlogicSOURCES
|
||||
${CURRENT_SOURCE_DIR}/AmlogicWrapper.cpp
|
||||
${CURRENT_SOURCE_DIR}/AmlogicGrabber.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(AmlogicHEADERS_MOC ${AmlogicQT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(AmlogicHEADERS_MOC ${AmlogicQT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_library(amlogic-grabber
|
||||
${AmlogicHEADERS}
|
||||
${AmlogicQT_HEADERS}
|
||||
${AmlogicHEADERS_MOC}
|
||||
${AmlogicSOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(amlogic-grabber
|
||||
hyperion
|
||||
${QT_LIBRARIES})
|
||||
|
@ -1,41 +1,41 @@
|
||||
|
||||
# Find the BCM-package (VC control)
|
||||
find_package(BCM REQUIRED)
|
||||
include_directories(${BCM_INCLUDE_DIRS})
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(DispmanxGrabberQT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/DispmanxWrapper.h
|
||||
)
|
||||
|
||||
SET(DispmanxGrabberHEADERS
|
||||
${CURRENT_HEADER_DIR}/DispmanxFrameGrabber.h
|
||||
)
|
||||
|
||||
SET(DispmanxGrabberSOURCES
|
||||
${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp
|
||||
${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_library(dispmanx-grabber
|
||||
${DispmanxGrabberHEADERS}
|
||||
${DispmanxGrabberQT_HEADERS}
|
||||
${DispmanxGrabberHEADERS_MOC}
|
||||
${DispmanxGrabberSOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(dispmanx-grabber
|
||||
hyperion
|
||||
${QT_LIBRARIES}
|
||||
${BCM_LIBRARIES}
|
||||
)
|
||||
|
||||
# Find the BCM-package (VC control)
|
||||
find_package(BCM REQUIRED)
|
||||
include_directories(${BCM_INCLUDE_DIRS})
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(DispmanxGrabberQT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/DispmanxWrapper.h
|
||||
)
|
||||
|
||||
SET(DispmanxGrabberHEADERS
|
||||
${CURRENT_HEADER_DIR}/DispmanxFrameGrabber.h
|
||||
)
|
||||
|
||||
SET(DispmanxGrabberSOURCES
|
||||
${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp
|
||||
${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
|
||||
else()
|
||||
QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
|
||||
endif()
|
||||
|
||||
add_library(dispmanx-grabber
|
||||
${DispmanxGrabberHEADERS}
|
||||
${DispmanxGrabberQT_HEADERS}
|
||||
${DispmanxGrabberHEADERS_MOC}
|
||||
${DispmanxGrabberSOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(dispmanx-grabber
|
||||
hyperion
|
||||
${QT_LIBRARIES}
|
||||
${BCM_LIBRARIES}
|
||||
)
|
||||
|
@ -9,31 +9,31 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/framebuffer)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(FramebufferGrabberQT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/FramebufferWrapper.h
|
||||
${CURRENT_HEADER_DIR}/FramebufferWrapper.h
|
||||
)
|
||||
|
||||
SET(FramebufferGrabberHEADERS
|
||||
${CURRENT_HEADER_DIR}/FramebufferFrameGrabber.h
|
||||
${CURRENT_HEADER_DIR}/FramebufferFrameGrabber.h
|
||||
)
|
||||
|
||||
SET(FramebufferGrabberSOURCES
|
||||
${CURRENT_SOURCE_DIR}/FramebufferWrapper.cpp
|
||||
${CURRENT_SOURCE_DIR}/FramebufferFrameGrabber.cpp
|
||||
${CURRENT_SOURCE_DIR}/FramebufferWrapper.cpp
|
||||
${CURRENT_SOURCE_DIR}/FramebufferFrameGrabber.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
else()
|
||||
QT4_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
endif()
|
||||
|
||||
add_library(framebuffer-grabber
|
||||
${FramebufferGrabberHEADERS}
|
||||
${FramebufferGrabberQT_HEADERS}
|
||||
${FramebufferGrabberHEADERS_MOC}
|
||||
${FramebufferGrabberSOURCES}
|
||||
${FramebufferGrabberHEADERS}
|
||||
${FramebufferGrabberQT_HEADERS}
|
||||
${FramebufferGrabberHEADERS_MOC}
|
||||
${FramebufferGrabberSOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(framebuffer-grabber
|
||||
hyperion
|
||||
${QT_LIBRARIES})
|
||||
hyperion
|
||||
${QT_LIBRARIES})
|
||||
|
@ -4,31 +4,31 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/osx)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(OsxGrabberQT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/OsxWrapper.h
|
||||
${CURRENT_HEADER_DIR}/OsxWrapper.h
|
||||
)
|
||||
|
||||
SET(OsxGrabberHEADERS
|
||||
${CURRENT_HEADER_DIR}/OsxFrameGrabber.h
|
||||
${CURRENT_HEADER_DIR}/OsxFrameGrabber.h
|
||||
)
|
||||
|
||||
SET(OsxGrabberSOURCES
|
||||
${CURRENT_SOURCE_DIR}/OsxWrapper.cpp
|
||||
${CURRENT_SOURCE_DIR}/OsxFrameGrabber.cpp
|
||||
${CURRENT_SOURCE_DIR}/OsxWrapper.cpp
|
||||
${CURRENT_SOURCE_DIR}/OsxFrameGrabber.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
else()
|
||||
QT4_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
endif()
|
||||
|
||||
add_library(osx-grabber
|
||||
${OsxGrabberHEADERS}
|
||||
${OsxGrabberQT_HEADERS}
|
||||
${OsxGrabberHEADERS_MOC}
|
||||
${OsxGrabberSOURCES}
|
||||
${OsxGrabberHEADERS}
|
||||
${OsxGrabberQT_HEADERS}
|
||||
${OsxGrabberHEADERS_MOC}
|
||||
${OsxGrabberSOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(osx-grabber
|
||||
hyperion
|
||||
${QT_LIBRARIES})
|
||||
hyperion
|
||||
${QT_LIBRARIES})
|
||||
|
@ -1,39 +1,39 @@
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/v4l2)
|
||||
|
||||
SET(V4L2_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/V4L2Grabber.h
|
||||
${CURRENT_HEADER_DIR}/V4L2Wrapper.h
|
||||
)
|
||||
|
||||
SET(V4L2_HEADERS
|
||||
${CURRENT_HEADER_DIR}/VideoStandard.h
|
||||
)
|
||||
|
||||
SET(V4L2_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/V4L2Grabber.cpp
|
||||
${CURRENT_SOURCE_DIR}/V4L2Wrapper.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_library(v4l2-grabber
|
||||
${V4L2_HEADERS}
|
||||
${V4L2_SOURCES}
|
||||
${V4L2_QT_HEADERS}
|
||||
${V4L2_HEADERS_MOC}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(v4l2-grabber Widgets)
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
target_link_libraries(v4l2-grabber
|
||||
hyperion
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/v4l2)
|
||||
|
||||
SET(V4L2_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/V4L2Grabber.h
|
||||
${CURRENT_HEADER_DIR}/V4L2Wrapper.h
|
||||
)
|
||||
|
||||
SET(V4L2_HEADERS
|
||||
${CURRENT_HEADER_DIR}/VideoStandard.h
|
||||
)
|
||||
|
||||
SET(V4L2_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/V4L2Grabber.cpp
|
||||
${CURRENT_SOURCE_DIR}/V4L2Wrapper.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS})
|
||||
else()
|
||||
QT4_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS})
|
||||
endif()
|
||||
|
||||
add_library(v4l2-grabber
|
||||
${V4L2_HEADERS}
|
||||
${V4L2_SOURCES}
|
||||
${V4L2_QT_HEADERS}
|
||||
${V4L2_HEADERS_MOC}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(v4l2-grabber Widgets)
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
target_link_libraries(v4l2-grabber
|
||||
hyperion
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,20 +19,20 @@ SET(X11_HEADERS
|
||||
)
|
||||
|
||||
SET(X11_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/X11Grabber.cpp
|
||||
${CURRENT_SOURCE_DIR}/X11Grabber.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS})
|
||||
else()
|
||||
QT4_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS})
|
||||
endif()
|
||||
|
||||
add_library(x11-grabber
|
||||
${X11_HEADERS}
|
||||
${X11_SOURCES}
|
||||
${X11_QT_HEADERS}
|
||||
${X11_HEADERS_MOC}
|
||||
${X11_HEADERS}
|
||||
${X11_SOURCES}
|
||||
${X11_QT_HEADERS}
|
||||
${X11_HEADERS_MOC}
|
||||
)
|
||||
|
||||
target_link_libraries(x11-grabber
|
||||
|
@ -6,107 +6,108 @@
|
||||
#include <grabber/X11Grabber.h>
|
||||
|
||||
X11Grabber::X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) :
|
||||
_imageResampler(),
|
||||
_useXGetImage(useXGetImage),
|
||||
_cropLeft(cropLeft),
|
||||
_cropRight(cropRight),
|
||||
_cropTop(cropTop),
|
||||
_cropBottom(cropBottom),
|
||||
_x11Display(nullptr),
|
||||
_pixmap(None),
|
||||
_srcFormat(nullptr),
|
||||
_dstFormat(nullptr),
|
||||
_srcPicture(None),
|
||||
_dstPicture(None),
|
||||
_screenWidth(0),
|
||||
_screenHeight(0),
|
||||
_croppedWidth(0),
|
||||
_croppedHeight(0),
|
||||
_image(0,0)
|
||||
_imageResampler(),
|
||||
_useXGetImage(useXGetImage),
|
||||
_cropLeft(cropLeft),
|
||||
_cropRight(cropRight),
|
||||
_cropTop(cropTop),
|
||||
_cropBottom(cropBottom),
|
||||
_x11Display(nullptr),
|
||||
_pixmap(None),
|
||||
_srcFormat(nullptr),
|
||||
_dstFormat(nullptr),
|
||||
_srcPicture(None),
|
||||
_dstPicture(None),
|
||||
_screenWidth(0),
|
||||
_screenHeight(0),
|
||||
_croppedWidth(0),
|
||||
_croppedHeight(0),
|
||||
_image(0,0)
|
||||
{
|
||||
_imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation);
|
||||
_imageResampler.setVerticalPixelDecimation(verticalPixelDecimation);
|
||||
_imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XShmGetImage or XGetImage
|
||||
memset(&_pictAttr, 0, sizeof(_pictAttr));
|
||||
_pictAttr.repeat = RepeatNone;
|
||||
_imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation);
|
||||
_imageResampler.setVerticalPixelDecimation(verticalPixelDecimation);
|
||||
_imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XShmGetImage or XGetImage
|
||||
memset(&_pictAttr, 0, sizeof(_pictAttr));
|
||||
_pictAttr.repeat = RepeatNone;
|
||||
}
|
||||
|
||||
X11Grabber::~X11Grabber()
|
||||
{
|
||||
if (_x11Display != nullptr)
|
||||
{
|
||||
freeResources();
|
||||
XCloseDisplay(_x11Display);
|
||||
}
|
||||
if (_x11Display != nullptr)
|
||||
{
|
||||
freeResources();
|
||||
XCloseDisplay(_x11Display);
|
||||
}
|
||||
}
|
||||
|
||||
void X11Grabber::freeResources()
|
||||
{
|
||||
// Cleanup allocated resources of the X11 grab
|
||||
XDestroyImage(_xImage);
|
||||
if(_XShmAvailable && !_useXGetImage) {
|
||||
XShmDetach(_x11Display, &_shminfo);
|
||||
shmdt(_shminfo.shmaddr);
|
||||
shmctl(_shminfo.shmid, IPC_RMID, 0);
|
||||
}
|
||||
if (_XRenderAvailable && !_useXGetImage) {
|
||||
XRenderFreePicture(_x11Display, _srcPicture);
|
||||
XRenderFreePicture(_x11Display, _dstPicture);
|
||||
XFreePixmap(_x11Display, _pixmap);
|
||||
}
|
||||
// Cleanup allocated resources of the X11 grab
|
||||
XDestroyImage(_xImage);
|
||||
if(_XShmAvailable && !_useXGetImage) {
|
||||
XShmDetach(_x11Display, &_shminfo);
|
||||
shmdt(_shminfo.shmaddr);
|
||||
shmctl(_shminfo.shmid, IPC_RMID, 0);
|
||||
}
|
||||
if (_XRenderAvailable && !_useXGetImage) {
|
||||
XRenderFreePicture(_x11Display, _srcPicture);
|
||||
XRenderFreePicture(_x11Display, _dstPicture);
|
||||
XFreePixmap(_x11Display, _pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
void X11Grabber::setupResources()
|
||||
{
|
||||
if(_XShmAvailable && !_useXGetImage) {
|
||||
_xImage = XShmCreateImage(_x11Display, _windowAttr.visual,
|
||||
_windowAttr.depth, ZPixmap, NULL, &_shminfo,
|
||||
_croppedWidth, _croppedHeight);
|
||||
if(_XShmAvailable && !_useXGetImage) {
|
||||
_xImage = XShmCreateImage(_x11Display, _windowAttr.visual,
|
||||
_windowAttr.depth, ZPixmap, NULL, &_shminfo,
|
||||
_croppedWidth, _croppedHeight);
|
||||
|
||||
_shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777);
|
||||
_xImage->data = (char*)shmat(_shminfo.shmid,0,0);
|
||||
_shminfo.shmaddr = _xImage->data;
|
||||
_shminfo.readOnly = False;
|
||||
|
||||
_shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777);
|
||||
_xImage->data = (char*)shmat(_shminfo.shmid,0,0);
|
||||
_shminfo.shmaddr = _xImage->data;
|
||||
_shminfo.readOnly = False;
|
||||
|
||||
XShmAttach(_x11Display, &_shminfo);
|
||||
}
|
||||
if (_XRenderAvailable && !_useXGetImage) {
|
||||
if(_XShmPixmapAvailable) {
|
||||
_pixmap = XShmCreatePixmap(_x11Display, _window, _xImage->data, &_shminfo, _croppedWidth, _croppedHeight, _windowAttr.depth);
|
||||
} else {
|
||||
_pixmap = XCreatePixmap(_x11Display, _window, _croppedWidth, _croppedHeight, _windowAttr.depth);
|
||||
}
|
||||
_srcFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual);
|
||||
_dstFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual);
|
||||
_srcPicture = XRenderCreatePicture(_x11Display, _window, _srcFormat, CPRepeat, &_pictAttr);
|
||||
_dstPicture = XRenderCreatePicture(_x11Display, _pixmap, _dstFormat, CPRepeat, &_pictAttr);
|
||||
XRenderSetPictureFilter(_x11Display, _srcPicture, "bilinear", NULL, 0);
|
||||
}
|
||||
if (_XRenderAvailable && !_useXGetImage) {
|
||||
if(_XShmPixmapAvailable) {
|
||||
_pixmap = XShmCreatePixmap(_x11Display, _window, _xImage->data, &_shminfo, _croppedWidth, _croppedHeight, _windowAttr.depth);
|
||||
} else {
|
||||
_pixmap = XCreatePixmap(_x11Display, _window, _croppedWidth, _croppedHeight, _windowAttr.depth);
|
||||
}
|
||||
_srcFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual);
|
||||
_dstFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual);
|
||||
_srcPicture = XRenderCreatePicture(_x11Display, _window, _srcFormat, CPRepeat, &_pictAttr);
|
||||
_dstPicture = XRenderCreatePicture(_x11Display, _pixmap, _dstFormat, CPRepeat, &_pictAttr);
|
||||
XRenderSetPictureFilter(_x11Display, _srcPicture, "bilinear", NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool X11Grabber::Setup()
|
||||
{
|
||||
_x11Display = XOpenDisplay(NULL);
|
||||
if (_x11Display == nullptr)
|
||||
{
|
||||
std::cerr << "X11GRABBER ERROR: Unable to open display";
|
||||
if (getenv("DISPLAY"))
|
||||
std::cerr << " " << std::string(getenv("DISPLAY")) << std::endl;
|
||||
else
|
||||
std::cerr << ". DISPLAY environment variable not set" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
_window = DefaultRootWindow(_x11Display);
|
||||
_x11Display = XOpenDisplay(NULL);
|
||||
if (_x11Display == nullptr)
|
||||
{
|
||||
std::cerr << "X11GRABBER ERROR: Unable to open display";
|
||||
if (getenv("DISPLAY")) {
|
||||
std::cerr << " " << std::string(getenv("DISPLAY")) << std::endl;
|
||||
} else {
|
||||
std::cerr << ". DISPLAY environment variable not set" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_window = DefaultRootWindow(_x11Display);
|
||||
|
||||
int dummy, pixmaps_supported;
|
||||
|
||||
_XRenderAvailable = XRenderQueryExtension(_x11Display, &dummy, &dummy);
|
||||
_XShmAvailable = XShmQueryExtension(_x11Display);
|
||||
XShmQueryVersion(_x11Display, &dummy, &dummy, &pixmaps_supported);
|
||||
_XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_x11Display) == ZPixmap;
|
||||
int dummy, pixmaps_supported;
|
||||
|
||||
_XRenderAvailable = XRenderQueryExtension(_x11Display, &dummy, &dummy);
|
||||
_XShmAvailable = XShmQueryExtension(_x11Display);
|
||||
XShmQueryVersion(_x11Display, &dummy, &dummy, &pixmaps_supported);
|
||||
_XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_x11Display) == ZPixmap;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
Image<ColorRgb> & X11Grabber::grab()
|
||||
@ -129,75 +130,74 @@ Image<ColorRgb> & X11Grabber::grab()
|
||||
_croppedHeight); // height
|
||||
|
||||
XSync(_x11Display, False);
|
||||
|
||||
if (_XShmAvailable) {
|
||||
XShmGetImage(_x11Display, _pixmap, _xImage, 0, 0, AllPlanes);
|
||||
} else {
|
||||
_xImage = XGetImage(_x11Display, _pixmap, 0, 0, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap);
|
||||
}
|
||||
} else {
|
||||
if (_XShmAvailable && !_useXGetImage) {
|
||||
XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes);
|
||||
} else {
|
||||
_xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap);
|
||||
}
|
||||
}
|
||||
|
||||
if (_xImage == nullptr)
|
||||
{
|
||||
std::cerr << "X11GRABBER ERROR: Grab failed" << std::endl;
|
||||
return _image;
|
||||
}
|
||||
|
||||
_imageResampler.processImage(reinterpret_cast<const uint8_t *>(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, _image);
|
||||
if (_XShmAvailable) {
|
||||
XShmGetImage(_x11Display, _pixmap, _xImage, 0, 0, AllPlanes);
|
||||
} else {
|
||||
_xImage = XGetImage(_x11Display, _pixmap, 0, 0, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap);
|
||||
}
|
||||
} else {
|
||||
if (_XShmAvailable && !_useXGetImage) {
|
||||
XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes);
|
||||
} else {
|
||||
_xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap);
|
||||
}
|
||||
}
|
||||
|
||||
return _image;
|
||||
if (_xImage == nullptr)
|
||||
{
|
||||
std::cerr << "X11GRABBER ERROR: Grab failed" << std::endl;
|
||||
return _image;
|
||||
}
|
||||
|
||||
_imageResampler.processImage(reinterpret_cast<const uint8_t *>(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, _image);
|
||||
|
||||
return _image;
|
||||
}
|
||||
|
||||
int X11Grabber::updateScreenDimensions()
|
||||
{
|
||||
const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr);
|
||||
if (status == 0)
|
||||
{
|
||||
std::cerr << "X11GRABBER ERROR: Failed to obtain window attributes" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr);
|
||||
if (status == 0)
|
||||
{
|
||||
std::cerr << "X11GRABBER ERROR: Failed to obtain window attributes" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height))
|
||||
{
|
||||
// No update required
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cout << "X11GRABBER INFO: Update of screen resolution: [" << _screenWidth << "x" << _screenHeight <<"] => ";
|
||||
if (_screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height))
|
||||
{
|
||||
// No update required
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cout << "X11GRABBER INFO: Update of screen resolution: [" << _screenWidth << "x" << _screenHeight <<"] => ";
|
||||
|
||||
if (_screenWidth || _screenHeight)
|
||||
freeResources();
|
||||
|
||||
_screenWidth = _windowAttr.width;
|
||||
_screenHeight = _windowAttr.height;
|
||||
|
||||
std::cout << "[" << _screenWidth << "x" << _screenHeight <<"]" << std::endl;
|
||||
|
||||
if (_screenWidth > unsigned(_cropLeft + _cropRight))
|
||||
_croppedWidth = _screenWidth - _cropLeft - _cropRight;
|
||||
else
|
||||
_croppedWidth = _screenWidth;
|
||||
|
||||
if (_screenHeight > unsigned(_cropTop + _cropBottom))
|
||||
_croppedHeight = _screenHeight - _cropTop - _cropBottom;
|
||||
else
|
||||
_croppedHeight = _screenHeight;
|
||||
|
||||
std::cout << "X11GRABBER INFO: Using ";
|
||||
|
||||
if (_XRenderAvailable && !_useXGetImage) {
|
||||
std::cout << "XRender for grabbing" << std::endl;
|
||||
} else {
|
||||
std::cout << "XGetImage for grabbing" << std::endl;
|
||||
}
|
||||
|
||||
setupResources();
|
||||
if (_screenWidth || _screenHeight) {
|
||||
freeResources();
|
||||
}
|
||||
|
||||
return 0;
|
||||
_screenWidth = _windowAttr.width;
|
||||
_screenHeight = _windowAttr.height;
|
||||
|
||||
std::cout << "[" << _screenWidth << "x" << _screenHeight <<"]" << std::endl;
|
||||
|
||||
_croppedWidth = (_screenWidth > unsigned(_cropLeft + _cropRight))
|
||||
? (_screenWidth - _cropLeft - _cropRight)
|
||||
: _screenWidth;
|
||||
|
||||
_croppedHeight = (_screenHeight > unsigned(_cropTop + _cropBottom))
|
||||
? (_screenHeight - _cropTop - _cropBottom)
|
||||
: (_croppedHeight = _screenHeight);
|
||||
|
||||
std::cout << "X11GRABBER INFO: Using ";
|
||||
|
||||
if (_XRenderAvailable && !_useXGetImage) {
|
||||
std::cout << "XRender for grabbing" << std::endl;
|
||||
} else {
|
||||
std::cout << "XGetImage for grabbing" << std::endl;
|
||||
}
|
||||
|
||||
setupResources();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,72 +1,72 @@
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(Hyperion_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/Hyperion.h
|
||||
|
||||
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h
|
||||
)
|
||||
|
||||
SET(Hyperion_HEADERS
|
||||
${CURRENT_HEADER_DIR}/ImageProcessor.h
|
||||
${CURRENT_HEADER_DIR}/ImageProcessorFactory.h
|
||||
${CURRENT_HEADER_DIR}/ImageToLedsMap.h
|
||||
${CURRENT_HEADER_DIR}/LedString.h
|
||||
${CURRENT_HEADER_DIR}/PriorityMuxer.h
|
||||
|
||||
${CURRENT_SOURCE_DIR}/MultiColorTransform.h
|
||||
${CURRENT_SOURCE_DIR}/MultiColorCorrection.h
|
||||
${CURRENT_SOURCE_DIR}/MultiColorAdjustment.h
|
||||
${CURRENT_HEADER_DIR}/MessageForwarder.h
|
||||
)
|
||||
|
||||
SET(Hyperion_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/Hyperion.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageProcessor.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedString.cpp
|
||||
${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp
|
||||
|
||||
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
|
||||
${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp
|
||||
${CURRENT_SOURCE_DIR}/MultiColorCorrection.cpp
|
||||
${CURRENT_SOURCE_DIR}/MultiColorAdjustment.cpp
|
||||
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp
|
||||
${CURRENT_SOURCE_DIR}/MessageForwarder.cpp
|
||||
)
|
||||
|
||||
set(Hyperion_RESOURCES
|
||||
${CURRENT_SOURCE_DIR}/resource.qrc
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
|
||||
QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
|
||||
QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_library(hyperion
|
||||
${Hyperion_HEADERS}
|
||||
${Hyperion_QT_HEADERS}
|
||||
${Hyperion_HEADERS_MOC}
|
||||
${Hyperion_SOURCES}
|
||||
${Hyperion_RESOURCES_RCC}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(hyperion Widgets)
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
target_link_libraries(hyperion
|
||||
blackborder
|
||||
hyperion-utils
|
||||
leddevice
|
||||
effectengine
|
||||
serialport
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(Hyperion_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/Hyperion.h
|
||||
|
||||
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h
|
||||
)
|
||||
|
||||
SET(Hyperion_HEADERS
|
||||
${CURRENT_HEADER_DIR}/ImageProcessor.h
|
||||
${CURRENT_HEADER_DIR}/ImageProcessorFactory.h
|
||||
${CURRENT_HEADER_DIR}/ImageToLedsMap.h
|
||||
${CURRENT_HEADER_DIR}/LedString.h
|
||||
${CURRENT_HEADER_DIR}/PriorityMuxer.h
|
||||
|
||||
${CURRENT_SOURCE_DIR}/MultiColorTransform.h
|
||||
${CURRENT_SOURCE_DIR}/MultiColorCorrection.h
|
||||
${CURRENT_SOURCE_DIR}/MultiColorAdjustment.h
|
||||
${CURRENT_HEADER_DIR}/MessageForwarder.h
|
||||
)
|
||||
|
||||
SET(Hyperion_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/Hyperion.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageProcessor.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedString.cpp
|
||||
${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp
|
||||
|
||||
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
|
||||
${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp
|
||||
${CURRENT_SOURCE_DIR}/MultiColorCorrection.cpp
|
||||
${CURRENT_SOURCE_DIR}/MultiColorAdjustment.cpp
|
||||
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp
|
||||
${CURRENT_SOURCE_DIR}/MessageForwarder.cpp
|
||||
)
|
||||
|
||||
SET(Hyperion_RESOURCES
|
||||
${CURRENT_SOURCE_DIR}/resource.qrc
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
|
||||
QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
|
||||
else()
|
||||
QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
|
||||
QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
|
||||
endif()
|
||||
|
||||
add_library(hyperion
|
||||
${Hyperion_HEADERS}
|
||||
${Hyperion_QT_HEADERS}
|
||||
${Hyperion_HEADERS_MOC}
|
||||
${Hyperion_SOURCES}
|
||||
${Hyperion_RESOURCES_RCC}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(hyperion Widgets)
|
||||
endif()
|
||||
|
||||
target_link_libraries(hyperion
|
||||
blackborder
|
||||
hyperion-utils
|
||||
leddevice
|
||||
effectengine
|
||||
serialport
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
@ -1,382 +1,382 @@
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"properties" : {
|
||||
"device" : {
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"properties" : {
|
||||
"name" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"type" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"output" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"rate" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0
|
||||
},
|
||||
"colorOrder" : {
|
||||
"type" : "string",
|
||||
"required" : false
|
||||
},
|
||||
"bgr-output" : { // deprecated
|
||||
"type" : "boolean",
|
||||
"required" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"color": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties": {
|
||||
"hsv" : {
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"saturationGain" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
},
|
||||
"valueGain" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"hsl" : {
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"saturationGain" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
},
|
||||
"luminanceGain" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
},
|
||||
"luminanceMinimum" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"red": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"green": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"blue": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"smoothing" : {
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"type" : {
|
||||
"type" : "enum",
|
||||
"required" : true,
|
||||
"values" : ["none", "linear"]
|
||||
},
|
||||
"time_ms" : {
|
||||
"type" : "integer",
|
||||
"required" : false,
|
||||
"minimum" : 10
|
||||
},
|
||||
"updateFrequency" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.001
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"leds": {
|
||||
"type":"array",
|
||||
"required":true,
|
||||
"items": {
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"index": {
|
||||
"type":"integer",
|
||||
"required":true
|
||||
},
|
||||
"hscan": {
|
||||
"type":"object",
|
||||
"required":true,
|
||||
"properties": {
|
||||
"minimum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
},
|
||||
"maximum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"vscan": {
|
||||
"type":"object",
|
||||
"required":true,
|
||||
"properties": {
|
||||
"minimum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
},
|
||||
"maximum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"colorOrder" : {
|
||||
"type" : "string",
|
||||
"required" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
"effects" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"paths" : {
|
||||
"type" : "array",
|
||||
"required" : false,
|
||||
"items" : {
|
||||
"type" : "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"blackborderdetector" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"enable" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"threshold" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"xbmcVideoChecker" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"xbmcAddress" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"xbmcTcpPort" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
},
|
||||
"grabVideo" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabPictures" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabAudio" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabMenu" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabScreensaver" : {
|
||||
"type" : "boolean",
|
||||
"required" : false
|
||||
},
|
||||
"enable3DDetection" : {
|
||||
"type" : "boolean",
|
||||
"required" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"bootsequence" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"path" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"effect" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"framegrabber" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"width" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
},
|
||||
"height" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
},
|
||||
"frequency_Hz" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"jsonServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"protoServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"boblightServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"properties" : {
|
||||
"device" : {
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"properties" : {
|
||||
"name" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"type" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"output" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"rate" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0
|
||||
},
|
||||
"colorOrder" : {
|
||||
"type" : "string",
|
||||
"required" : false
|
||||
},
|
||||
"bgr-output" : { // deprecated
|
||||
"type" : "boolean",
|
||||
"required" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"color": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties": {
|
||||
"hsv" : {
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"saturationGain" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
},
|
||||
"valueGain" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"hsl" : {
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"saturationGain" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
},
|
||||
"luminanceGain" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
},
|
||||
"luminanceMinimum" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"red": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"green": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"blue": {
|
||||
"type":"object",
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"smoothing" : {
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"type" : {
|
||||
"type" : "enum",
|
||||
"required" : true,
|
||||
"values" : ["none", "linear"]
|
||||
},
|
||||
"time_ms" : {
|
||||
"type" : "integer",
|
||||
"required" : false,
|
||||
"minimum" : 10
|
||||
},
|
||||
"updateFrequency" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.001
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"leds": {
|
||||
"type":"array",
|
||||
"required":true,
|
||||
"items": {
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"index": {
|
||||
"type":"integer",
|
||||
"required":true
|
||||
},
|
||||
"hscan": {
|
||||
"type":"object",
|
||||
"required":true,
|
||||
"properties": {
|
||||
"minimum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
},
|
||||
"maximum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"vscan": {
|
||||
"type":"object",
|
||||
"required":true,
|
||||
"properties": {
|
||||
"minimum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
},
|
||||
"maximum": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"colorOrder" : {
|
||||
"type" : "string",
|
||||
"required" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
"effects" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"paths" : {
|
||||
"type" : "array",
|
||||
"required" : false,
|
||||
"items" : {
|
||||
"type" : "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"blackborderdetector" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"enable" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"threshold" : {
|
||||
"type" : "number",
|
||||
"required" : false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"xbmcVideoChecker" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"xbmcAddress" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"xbmcTcpPort" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
},
|
||||
"grabVideo" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabPictures" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabAudio" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabMenu" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"grabScreensaver" : {
|
||||
"type" : "boolean",
|
||||
"required" : false
|
||||
},
|
||||
"enable3DDetection" : {
|
||||
"type" : "boolean",
|
||||
"required" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"bootsequence" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"path" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"effect" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"framegrabber" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"width" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
},
|
||||
"height" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
},
|
||||
"frequency_Hz" : {
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"jsonServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"protoServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"boblightServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
|
@ -1,48 +1,48 @@
|
||||
|
||||
# Define the current source locations
|
||||
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/jsonserver)
|
||||
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/jsonserver)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
set(JsonServer_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/JsonServer.h
|
||||
${CURRENT_SOURCE_DIR}/JsonClientConnection.h
|
||||
)
|
||||
|
||||
set(JsonServer_HEADERS
|
||||
)
|
||||
|
||||
set(JsonServer_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/JsonServer.cpp
|
||||
${CURRENT_SOURCE_DIR}/JsonClientConnection.cpp
|
||||
)
|
||||
|
||||
set(JsonServer_RESOURCES
|
||||
${CURRENT_SOURCE_DIR}/JsonSchemas.qrc
|
||||
)
|
||||
if(ENABLE_QT5)
|
||||
qt5_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS})
|
||||
qt5_add_resources(JsonServer_RESOURCES_RCC ${JsonServer_RESOURCES} OPTIONS "-no-compress")
|
||||
else(ENABLE_QT5)
|
||||
qt4_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS})
|
||||
qt4_add_resources(JsonServer_RESOURCES_RCC ${JsonServer_RESOURCES} OPTIONS "-no-compress")
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_library(jsonserver
|
||||
${JsonServer_HEADERS}
|
||||
${JsonServer_QT_HEADERS}
|
||||
${JsonServer_SOURCES}
|
||||
${JsonServer_RESOURCES}
|
||||
${JsonServer_HEADERS_MOC}
|
||||
${JsonServer_RESOURCES_RCC}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(jsonserver Widgets Network)
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
target_link_libraries(jsonserver
|
||||
hyperion
|
||||
hyperion-utils
|
||||
jsoncpp
|
||||
${QT_LIBRARIES})
|
||||
|
||||
# Define the current source locations
|
||||
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/jsonserver)
|
||||
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/jsonserver)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
set(JsonServer_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/JsonServer.h
|
||||
${CURRENT_SOURCE_DIR}/JsonClientConnection.h
|
||||
)
|
||||
|
||||
set(JsonServer_HEADERS
|
||||
)
|
||||
|
||||
set(JsonServer_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/JsonServer.cpp
|
||||
${CURRENT_SOURCE_DIR}/JsonClientConnection.cpp
|
||||
)
|
||||
|
||||
set(JsonServer_RESOURCES
|
||||
${CURRENT_SOURCE_DIR}/JsonSchemas.qrc
|
||||
)
|
||||
if(ENABLE_QT5)
|
||||
qt5_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS})
|
||||
qt5_add_resources(JsonServer_RESOURCES_RCC ${JsonServer_RESOURCES} OPTIONS "-no-compress")
|
||||
else()
|
||||
qt4_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS})
|
||||
qt4_add_resources(JsonServer_RESOURCES_RCC ${JsonServer_RESOURCES} OPTIONS "-no-compress")
|
||||
endif()
|
||||
|
||||
add_library(jsonserver
|
||||
${JsonServer_HEADERS}
|
||||
${JsonServer_QT_HEADERS}
|
||||
${JsonServer_SOURCES}
|
||||
${JsonServer_RESOURCES}
|
||||
${JsonServer_HEADERS_MOC}
|
||||
${JsonServer_RESOURCES_RCC}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(jsonserver Widgets Network)
|
||||
endif()
|
||||
|
||||
target_link_libraries(jsonserver
|
||||
hyperion
|
||||
hyperion-utils
|
||||
jsoncpp
|
||||
${QT_LIBRARIES})
|
||||
|
@ -1,165 +1,166 @@
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/leddevice)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/leddevice)
|
||||
|
||||
#add libusb and pthreads (required for the Lighpack usb device)
|
||||
find_package(libusb-1.0 REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
include_directories(
|
||||
../../include/hidapi
|
||||
${LIBUSB_1_INCLUDE_DIRS}) # for Lightpack device
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(Leddevice_QT_HEADERS
|
||||
${CURRENT_SOURCE_DIR}/LedRs232Device.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAdalight.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAdalightApa102.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAmbiLed.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAtmoOrb.h
|
||||
${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.h
|
||||
${CURRENT_SOURCE_DIR}/LedHIDDevice.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceRawHID.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFile.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h
|
||||
)
|
||||
|
||||
SET(Leddevice_HEADERS
|
||||
${CURRENT_HEADER_DIR}/LedDevice.h
|
||||
${CURRENT_HEADER_DIR}/LedDeviceFactory.h
|
||||
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceLightpack.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.h
|
||||
${CURRENT_SOURCE_DIR}/LedDevicePaintpack.h
|
||||
${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceSedu.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFile.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceUdp.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceTpm2.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAtmo.h
|
||||
)
|
||||
|
||||
SET(Leddevice_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFactory.cpp
|
||||
|
||||
${CURRENT_SOURCE_DIR}/LedRs232Device.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedHIDDevice.cpp
|
||||
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAdalight.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAdalightApa102.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAmbiLed.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAtmoOrb.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceRawHID.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceLightpack.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDevicePaintpack.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFile.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceTpm2.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAtmo.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_SPIDEV)
|
||||
SET(Leddevice_HEADERS
|
||||
${Leddevice_HEADERS}
|
||||
${CURRENT_SOURCE_DIR}/LedSpiDevice.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceP9813.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAPA102.h
|
||||
)
|
||||
SET(Leddevice_SOURCES
|
||||
${Leddevice_SOURCES}
|
||||
${CURRENT_SOURCE_DIR}/LedSpiDevice.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceP9813.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAPA102.cpp
|
||||
)
|
||||
endif(ENABLE_SPIDEV)
|
||||
|
||||
if(ENABLE_WS2812BPWM)
|
||||
SET(Leddevice_HEADERS
|
||||
${Leddevice_HEADERS}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.h
|
||||
)
|
||||
SET(Leddevice_SOURCES
|
||||
${Leddevice_SOURCES}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.cpp
|
||||
)
|
||||
endif(ENABLE_WS2812BPWM)
|
||||
|
||||
if(ENABLE_WS281XPWM)
|
||||
include_directories(../../dependencies/external/rpi_ws281x)
|
||||
SET(Leddevice_HEADERS
|
||||
${Leddevice_HEADERS}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWS281x.h
|
||||
)
|
||||
SET(Leddevice_SOURCES
|
||||
${Leddevice_SOURCES}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWS281x.cpp
|
||||
)
|
||||
endif(ENABLE_WS281XPWM)
|
||||
|
||||
if(ENABLE_TINKERFORGE)
|
||||
SET(Leddevice_HEADERS
|
||||
${Leddevice_HEADERS}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.h
|
||||
)
|
||||
SET(Leddevice_SOURCES
|
||||
${Leddevice_SOURCES}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.cpp
|
||||
)
|
||||
endif(ENABLE_TINKERFORGE)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
|
||||
add_library(leddevice
|
||||
${Leddevice_HEADERS}
|
||||
${Leddevice_QT_HEADERS}
|
||||
${Leddevice_HEADERS_MOC}
|
||||
${Leddevice_SOURCES}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(leddevice Widgets Network)
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
target_link_libraries(leddevice
|
||||
hyperion-utils
|
||||
serialport
|
||||
${LIBUSB_1_LIBRARIES} #apt-get install libusb-1.0-0-dev
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
||||
if(ENABLE_TINKERFORGE)
|
||||
target_link_libraries(leddevice tinkerforge)
|
||||
endif()
|
||||
|
||||
if(ENABLE_WS281XPWM)
|
||||
target_link_libraries(leddevice ws281x)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
target_link_libraries(leddevice hidapi-mac)
|
||||
else()
|
||||
target_link_libraries(leddevice hidapi-libusb)
|
||||
endif()
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/leddevice)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/leddevice)
|
||||
|
||||
#add libusb and pthreads (required for the Lighpack usb device)
|
||||
find_package(libusb-1.0 REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
include_directories(
|
||||
../../include/hidapi
|
||||
${LIBUSB_1_INCLUDE_DIRS}
|
||||
) # for Lightpack device
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(Leddevice_QT_HEADERS
|
||||
${CURRENT_SOURCE_DIR}/LedRs232Device.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAdalight.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAdalightApa102.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAmbiLed.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAtmoOrb.h
|
||||
${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.h
|
||||
${CURRENT_SOURCE_DIR}/LedHIDDevice.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceRawHID.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFile.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h
|
||||
)
|
||||
|
||||
SET(Leddevice_HEADERS
|
||||
${CURRENT_HEADER_DIR}/LedDevice.h
|
||||
${CURRENT_HEADER_DIR}/LedDeviceFactory.h
|
||||
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceLightpack.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.h
|
||||
${CURRENT_SOURCE_DIR}/LedDevicePaintpack.h
|
||||
${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceSedu.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFile.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceUdp.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceTpm2.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAtmo.h
|
||||
)
|
||||
|
||||
SET(Leddevice_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFactory.cpp
|
||||
|
||||
${CURRENT_SOURCE_DIR}/LedRs232Device.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedHIDDevice.cpp
|
||||
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAdalight.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAdalightApa102.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAmbiLed.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAtmoOrb.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceRawHID.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceLightpack.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDevicePaintpack.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFile.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceTpm2.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAtmo.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_SPIDEV)
|
||||
SET(Leddevice_HEADERS
|
||||
${Leddevice_HEADERS}
|
||||
${CURRENT_SOURCE_DIR}/LedSpiDevice.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceP9813.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAPA102.h
|
||||
)
|
||||
SET(Leddevice_SOURCES
|
||||
${Leddevice_SOURCES}
|
||||
${CURRENT_SOURCE_DIR}/LedSpiDevice.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceP9813.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.cpp
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceAPA102.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_WS2812BPWM)
|
||||
SET(Leddevice_HEADERS
|
||||
${Leddevice_HEADERS}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.h
|
||||
)
|
||||
SET(Leddevice_SOURCES
|
||||
${Leddevice_SOURCES}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_WS281XPWM)
|
||||
include_directories(../../dependencies/external/rpi_ws281x)
|
||||
SET(Leddevice_HEADERS
|
||||
${Leddevice_HEADERS}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWS281x.h
|
||||
)
|
||||
SET(Leddevice_SOURCES
|
||||
${Leddevice_SOURCES}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWS281x.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_TINKERFORGE)
|
||||
SET(Leddevice_HEADERS
|
||||
${Leddevice_HEADERS}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.h
|
||||
)
|
||||
SET(Leddevice_SOURCES
|
||||
${Leddevice_SOURCES}
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS})
|
||||
else()
|
||||
QT4_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS})
|
||||
endif()
|
||||
|
||||
|
||||
add_library(leddevice
|
||||
${Leddevice_HEADERS}
|
||||
${Leddevice_QT_HEADERS}
|
||||
${Leddevice_HEADERS_MOC}
|
||||
${Leddevice_SOURCES}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(leddevice Widgets Network)
|
||||
endif()
|
||||
|
||||
target_link_libraries(leddevice
|
||||
hyperion-utils
|
||||
serialport
|
||||
${LIBUSB_1_LIBRARIES} #apt-get install libusb-1.0-0-dev
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
||||
if(ENABLE_TINKERFORGE)
|
||||
target_link_libraries(leddevice tinkerforge)
|
||||
endif()
|
||||
|
||||
if(ENABLE_WS281XPWM)
|
||||
target_link_libraries(leddevice ws281x)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
target_link_libraries(leddevice hidapi-mac)
|
||||
else()
|
||||
target_link_libraries(leddevice hidapi-libusb)
|
||||
endif()
|
||||
|
@ -1,152 +1,158 @@
|
||||
// Local-Hyperion includes
|
||||
#include "LedDeviceAtmoOrb.h"
|
||||
|
||||
// qt includes
|
||||
#include <QtCore/qmath.h>
|
||||
#include <QEventLoop>
|
||||
#include <QtNetwork>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
AtmoOrbLight::AtmoOrbLight(unsigned int id) {
|
||||
// Not implemented
|
||||
}
|
||||
|
||||
LedDeviceAtmoOrb::LedDeviceAtmoOrb(const std::string &output, bool useOrbSmoothing,
|
||||
int transitiontime, int skipSmoothingDiff, int port, int numLeds, std::vector<unsigned int> orbIds) :
|
||||
multicastGroup(output.c_str()), useOrbSmoothing(useOrbSmoothing), transitiontime(transitiontime), skipSmoothingDiff(skipSmoothingDiff),
|
||||
multiCastGroupPort(port), numLeds(numLeds), orbIds(orbIds) {
|
||||
manager = new QNetworkAccessManager();
|
||||
groupAddress = QHostAddress(multicastGroup);
|
||||
|
||||
udpSocket = new QUdpSocket(this);
|
||||
udpSocket->bind(multiCastGroupPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
|
||||
|
||||
joinedMulticastgroup = udpSocket->joinMulticastGroup(groupAddress);
|
||||
}
|
||||
|
||||
int LedDeviceAtmoOrb::write(const std::vector <ColorRgb> &ledValues) {
|
||||
|
||||
// If not in multicast group return
|
||||
if (!joinedMulticastgroup) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Command options:
|
||||
//
|
||||
// 1 = force off
|
||||
// 2 = use lamp smoothing and validate by Orb ID
|
||||
// 4 = validate by Orb ID
|
||||
|
||||
// When setting useOrbSmoothing = true it's recommended to disable Hyperion's own smoothing as it will conflict (double smoothing)
|
||||
int commandType = 4;
|
||||
if(useOrbSmoothing)
|
||||
{
|
||||
commandType = 2;
|
||||
}
|
||||
|
||||
// Iterate through colors and set Orb color
|
||||
// Start off with idx 1 as 0 is reserved for controlling all orbs at once
|
||||
unsigned int idx = 1;
|
||||
|
||||
for (const ColorRgb &color : ledValues) {
|
||||
// Retrieve last send colors
|
||||
int lastRed = lastColorRedMap[idx];
|
||||
int lastGreen = lastColorGreenMap[idx];
|
||||
int lastBlue = lastColorBlueMap[idx];
|
||||
|
||||
// If color difference is higher than skipSmoothingDiff than we skip Orb smoothing (if enabled) and send it right away
|
||||
if ((skipSmoothingDiff != 0 && useOrbSmoothing) && (abs(color.red - lastRed) >= skipSmoothingDiff || abs(color.blue - lastBlue) >= skipSmoothingDiff ||
|
||||
abs(color.green - lastGreen) >= skipSmoothingDiff))
|
||||
{
|
||||
// Skip Orb smoothing when using (command type 4)
|
||||
for (unsigned int i = 0; i < orbIds.size(); i++) {
|
||||
if (orbIds[i] == idx) {
|
||||
setColor(idx, color, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Send color
|
||||
for (unsigned int i = 0; i < orbIds.size(); i++) {
|
||||
if (orbIds[i] == idx) {
|
||||
setColor(idx, color, commandType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store last colors send for light id
|
||||
lastColorRedMap[idx] = color.red;
|
||||
lastColorGreenMap[idx] = color.green;
|
||||
lastColorBlueMap[idx] = color.blue;
|
||||
|
||||
// Next light id.
|
||||
idx++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LedDeviceAtmoOrb::setColor(unsigned int orbId, const ColorRgb &color, int commandType) {
|
||||
QByteArray bytes;
|
||||
bytes.resize(5 + numLeds * 3);
|
||||
bytes.fill('\0');
|
||||
|
||||
// Command identifier: C0FFEE
|
||||
bytes[0] = 0xC0;
|
||||
bytes[1] = 0xFF;
|
||||
bytes[2] = 0xEE;
|
||||
|
||||
// Command type
|
||||
bytes[3] = commandType;
|
||||
|
||||
// Orb ID
|
||||
bytes[4] = orbId;
|
||||
|
||||
// RED / GREEN / BLUE
|
||||
bytes[5] = color.red;
|
||||
bytes[6] = color.green;
|
||||
bytes[7] = color.blue;
|
||||
|
||||
sendCommand(bytes);
|
||||
}
|
||||
|
||||
void LedDeviceAtmoOrb::sendCommand(const QByteArray &bytes) {
|
||||
QByteArray datagram = bytes;
|
||||
udpSocket->writeDatagram(datagram.data(), datagram.size(),
|
||||
groupAddress, multiCastGroupPort);
|
||||
}
|
||||
|
||||
int LedDeviceAtmoOrb::switchOff() {
|
||||
for (unsigned int i = 0; i < orbIds.size(); i++) {
|
||||
QByteArray bytes;
|
||||
bytes.resize(5 + numLeds * 3);
|
||||
bytes.fill('\0');
|
||||
|
||||
// Command identifier: C0FFEE
|
||||
bytes[0] = 0xC0;
|
||||
bytes[1] = 0xFF;
|
||||
bytes[2] = 0xEE;
|
||||
|
||||
// Command type
|
||||
bytes[3] = 1;
|
||||
|
||||
// Orb ID
|
||||
bytes[4] = orbIds[i];
|
||||
|
||||
// RED / GREEN / BLUE
|
||||
bytes[5] = 0;
|
||||
bytes[6] = 0;
|
||||
bytes[7] = 0;
|
||||
|
||||
sendCommand(bytes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LedDeviceAtmoOrb::~LedDeviceAtmoOrb() {
|
||||
delete manager;
|
||||
}
|
||||
// Local-Hyperion includes
|
||||
#include "LedDeviceAtmoOrb.h"
|
||||
|
||||
// qt includes
|
||||
#include <QtCore/qmath.h>
|
||||
#include <QEventLoop>
|
||||
#include <QtNetwork>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
AtmoOrbLight::AtmoOrbLight(unsigned int id) {
|
||||
// Not implemented
|
||||
}
|
||||
|
||||
LedDeviceAtmoOrb::LedDeviceAtmoOrb(
|
||||
const std::string &output,
|
||||
bool useOrbSmoothing,
|
||||
int transitiontime,
|
||||
int skipSmoothingDiff,
|
||||
int port,
|
||||
int numLeds,
|
||||
std::vector<unsigned int> orbIds) :
|
||||
multicastGroup(output.c_str()), useOrbSmoothing(useOrbSmoothing), transitiontime(transitiontime), skipSmoothingDiff(skipSmoothingDiff),
|
||||
multiCastGroupPort(port), numLeds(numLeds), orbIds(orbIds)
|
||||
{
|
||||
manager = new QNetworkAccessManager();
|
||||
groupAddress = QHostAddress(multicastGroup);
|
||||
|
||||
udpSocket = new QUdpSocket(this);
|
||||
udpSocket->bind(multiCastGroupPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
|
||||
|
||||
joinedMulticastgroup = udpSocket->joinMulticastGroup(groupAddress);
|
||||
}
|
||||
|
||||
int LedDeviceAtmoOrb::write(const std::vector <ColorRgb> &ledValues) {
|
||||
// If not in multicast group return
|
||||
if (!joinedMulticastgroup) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Command options:
|
||||
//
|
||||
// 1 = force off
|
||||
// 2 = use lamp smoothing and validate by Orb ID
|
||||
// 4 = validate by Orb ID
|
||||
|
||||
// When setting useOrbSmoothing = true it's recommended to disable Hyperion's own smoothing as it will conflict (double smoothing)
|
||||
int commandType = 4;
|
||||
if(useOrbSmoothing)
|
||||
{
|
||||
commandType = 2;
|
||||
}
|
||||
|
||||
// Iterate through colors and set Orb color
|
||||
// Start off with idx 1 as 0 is reserved for controlling all orbs at once
|
||||
unsigned int idx = 1;
|
||||
|
||||
for (const ColorRgb &color : ledValues) {
|
||||
// Retrieve last send colors
|
||||
int lastRed = lastColorRedMap[idx];
|
||||
int lastGreen = lastColorGreenMap[idx];
|
||||
int lastBlue = lastColorBlueMap[idx];
|
||||
|
||||
// If color difference is higher than skipSmoothingDiff than we skip Orb smoothing (if enabled) and send it right away
|
||||
if ((skipSmoothingDiff != 0 && useOrbSmoothing) && (abs(color.red - lastRed) >= skipSmoothingDiff || abs(color.blue - lastBlue) >= skipSmoothingDiff ||
|
||||
abs(color.green - lastGreen) >= skipSmoothingDiff))
|
||||
{
|
||||
// Skip Orb smoothing when using (command type 4)
|
||||
for (unsigned int i = 0; i < orbIds.size(); i++) {
|
||||
if (orbIds[i] == idx) {
|
||||
setColor(idx, color, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Send color
|
||||
for (unsigned int i = 0; i < orbIds.size(); i++) {
|
||||
if (orbIds[i] == idx) {
|
||||
setColor(idx, color, commandType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store last colors send for light id
|
||||
lastColorRedMap[idx] = color.red;
|
||||
lastColorGreenMap[idx] = color.green;
|
||||
lastColorBlueMap[idx] = color.blue;
|
||||
|
||||
// Next light id.
|
||||
idx++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LedDeviceAtmoOrb::setColor(unsigned int orbId, const ColorRgb &color, int commandType) {
|
||||
QByteArray bytes;
|
||||
bytes.resize(5 + numLeds * 3);
|
||||
bytes.fill('\0');
|
||||
|
||||
// Command identifier: C0FFEE
|
||||
bytes[0] = 0xC0;
|
||||
bytes[1] = 0xFF;
|
||||
bytes[2] = 0xEE;
|
||||
|
||||
// Command type
|
||||
bytes[3] = commandType;
|
||||
|
||||
// Orb ID
|
||||
bytes[4] = orbId;
|
||||
|
||||
// RED / GREEN / BLUE
|
||||
bytes[5] = color.red;
|
||||
bytes[6] = color.green;
|
||||
bytes[7] = color.blue;
|
||||
|
||||
sendCommand(bytes);
|
||||
}
|
||||
|
||||
void LedDeviceAtmoOrb::sendCommand(const QByteArray &bytes) {
|
||||
QByteArray datagram = bytes;
|
||||
udpSocket->writeDatagram(datagram.data(), datagram.size(),
|
||||
groupAddress, multiCastGroupPort);
|
||||
}
|
||||
|
||||
int LedDeviceAtmoOrb::switchOff() {
|
||||
for (unsigned int i = 0; i < orbIds.size(); i++) {
|
||||
QByteArray bytes;
|
||||
bytes.resize(5 + numLeds * 3);
|
||||
bytes.fill('\0');
|
||||
|
||||
// Command identifier: C0FFEE
|
||||
bytes[0] = 0xC0;
|
||||
bytes[1] = 0xFF;
|
||||
bytes[2] = 0xEE;
|
||||
|
||||
// Command type
|
||||
bytes[3] = 1;
|
||||
|
||||
// Orb ID
|
||||
bytes[4] = orbIds[i];
|
||||
|
||||
// RED / GREEN / BLUE
|
||||
bytes[5] = 0;
|
||||
bytes[6] = 0;
|
||||
bytes[7] = 0;
|
||||
|
||||
sendCommand(bytes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LedDeviceAtmoOrb::~LedDeviceAtmoOrb() {
|
||||
delete manager;
|
||||
}
|
||||
|
@ -1,132 +1,132 @@
|
||||
#pragma once
|
||||
|
||||
// STL includes
|
||||
#include <string>
|
||||
|
||||
// Qt includes
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QHostAddress>
|
||||
|
||||
// Leddevice includes
|
||||
#include <leddevice/LedDevice.h>
|
||||
|
||||
class QUdpSocket;
|
||||
|
||||
class AtmoOrbLight {
|
||||
public:
|
||||
unsigned int id;
|
||||
|
||||
///
|
||||
/// Constructs the light.
|
||||
///
|
||||
/// @param id the orb id
|
||||
AtmoOrbLight(unsigned int id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation for the AtmoOrb
|
||||
*
|
||||
* To use set the device to "atmoorb".
|
||||
*
|
||||
* @author RickDB (github)
|
||||
*/
|
||||
class LedDeviceAtmoOrb : public QObject, public LedDevice {
|
||||
Q_OBJECT
|
||||
public:
|
||||
// Last send color map
|
||||
QMap<int, int> lastColorRedMap;
|
||||
QMap<int, int> lastColorGreenMap;
|
||||
QMap<int, int> lastColorBlueMap;
|
||||
|
||||
// Multicast status
|
||||
bool joinedMulticastgroup;
|
||||
|
||||
///
|
||||
/// Constructs the device.
|
||||
///
|
||||
/// @param output is the multicast address of Orbs
|
||||
///
|
||||
/// @param transitiontime is optional and not used at the moment
|
||||
///
|
||||
/// @param useOrbSmoothing use Orbs own (external) smoothing algorithm (default: false)
|
||||
///
|
||||
/// @param skipSmoothingDiff minimal color (0-255) difference to override smoothing so that if current and previously received colors are higher than set dif we override smoothing
|
||||
///
|
||||
/// @param port is the multicast port.
|
||||
///
|
||||
/// @param numLeds is the total amount of leds per Orb
|
||||
///
|
||||
/// @param array containing orb ids
|
||||
///
|
||||
LedDeviceAtmoOrb(const std::string &output, bool useOrbSmoothing =
|
||||
false, int transitiontime = 0, int skipSmoothingDiff = 0, int port = 49692, int numLeds = 24,
|
||||
std::vector<unsigned int> orbIds = std::vector < unsigned int>());
|
||||
|
||||
///
|
||||
/// Destructor of this device
|
||||
///
|
||||
virtual ~LedDeviceAtmoOrb();
|
||||
|
||||
///
|
||||
/// Sends the given led-color values to the Orbs
|
||||
///
|
||||
/// @param ledValues The color-value per led
|
||||
///
|
||||
/// @return Zero on success else negative
|
||||
///
|
||||
virtual int write(const std::vector <ColorRgb> &ledValues);
|
||||
|
||||
virtual int switchOff();
|
||||
|
||||
private:
|
||||
/// QNetworkAccessManager object for sending requests.
|
||||
QNetworkAccessManager *manager;
|
||||
|
||||
/// String containing multicast group IP address
|
||||
QString multicastGroup;
|
||||
|
||||
/// use Orbs own (external) smoothing algorithm
|
||||
bool useOrbSmoothing;
|
||||
|
||||
/// Transition time between colors (not implemented)
|
||||
int transitiontime;
|
||||
|
||||
// Maximum allowed color difference, will skip Orb (external) smoothing once reached
|
||||
int skipSmoothingDiff;
|
||||
|
||||
/// Multicast port to send data to
|
||||
int multiCastGroupPort;
|
||||
|
||||
/// Number of leds in Orb, used to determine buffer size
|
||||
int numLeds;
|
||||
|
||||
/// QHostAddress object of multicast group IP address
|
||||
QHostAddress groupAddress;
|
||||
|
||||
/// QUdpSocket object used to send data over
|
||||
QUdpSocket *udpSocket;
|
||||
|
||||
/// Array of the orb ids.
|
||||
std::vector<unsigned int> orbIds;
|
||||
|
||||
///
|
||||
/// Set Orbcolor
|
||||
///
|
||||
/// @param orbId the orb id
|
||||
///
|
||||
/// @param color which color to set
|
||||
///
|
||||
///
|
||||
/// @param commandType which type of command to send (off / smoothing / etc..)
|
||||
///
|
||||
void setColor(unsigned int orbId, const ColorRgb &color, int commandType);
|
||||
|
||||
///
|
||||
/// Send Orb command
|
||||
///
|
||||
/// @param bytes the byte array containing command to send over multicast
|
||||
///
|
||||
void sendCommand(const QByteArray &bytes);
|
||||
#pragma once
|
||||
|
||||
// STL includes
|
||||
#include <string>
|
||||
|
||||
// Qt includes
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QHostAddress>
|
||||
|
||||
// Leddevice includes
|
||||
#include <leddevice/LedDevice.h>
|
||||
|
||||
class QUdpSocket;
|
||||
|
||||
class AtmoOrbLight {
|
||||
public:
|
||||
unsigned int id;
|
||||
|
||||
///
|
||||
/// Constructs the light.
|
||||
///
|
||||
/// @param id the orb id
|
||||
AtmoOrbLight(unsigned int id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation for the AtmoOrb
|
||||
*
|
||||
* To use set the device to "atmoorb".
|
||||
*
|
||||
* @author RickDB (github)
|
||||
*/
|
||||
class LedDeviceAtmoOrb : public QObject, public LedDevice {
|
||||
Q_OBJECT
|
||||
public:
|
||||
// Last send color map
|
||||
QMap<int, int> lastColorRedMap;
|
||||
QMap<int, int> lastColorGreenMap;
|
||||
QMap<int, int> lastColorBlueMap;
|
||||
|
||||
// Multicast status
|
||||
bool joinedMulticastgroup;
|
||||
|
||||
///
|
||||
/// Constructs the device.
|
||||
///
|
||||
/// @param output is the multicast address of Orbs
|
||||
///
|
||||
/// @param transitiontime is optional and not used at the moment
|
||||
///
|
||||
/// @param useOrbSmoothing use Orbs own (external) smoothing algorithm (default: false)
|
||||
///
|
||||
/// @param skipSmoothingDiff minimal color (0-255) difference to override smoothing so that if current and previously received colors are higher than set dif we override smoothing
|
||||
///
|
||||
/// @param port is the multicast port.
|
||||
///
|
||||
/// @param numLeds is the total amount of leds per Orb
|
||||
///
|
||||
/// @param array containing orb ids
|
||||
///
|
||||
LedDeviceAtmoOrb(const std::string &output, bool useOrbSmoothing =
|
||||
false, int transitiontime = 0, int skipSmoothingDiff = 0, int port = 49692, int numLeds = 24,
|
||||
std::vector<unsigned int> orbIds = std::vector < unsigned int>());
|
||||
|
||||
///
|
||||
/// Destructor of this device
|
||||
///
|
||||
virtual ~LedDeviceAtmoOrb();
|
||||
|
||||
///
|
||||
/// Sends the given led-color values to the Orbs
|
||||
///
|
||||
/// @param ledValues The color-value per led
|
||||
///
|
||||
/// @return Zero on success else negative
|
||||
///
|
||||
virtual int write(const std::vector <ColorRgb> &ledValues);
|
||||
|
||||
virtual int switchOff();
|
||||
|
||||
private:
|
||||
/// QNetworkAccessManager object for sending requests.
|
||||
QNetworkAccessManager *manager;
|
||||
|
||||
/// String containing multicast group IP address
|
||||
QString multicastGroup;
|
||||
|
||||
/// use Orbs own (external) smoothing algorithm
|
||||
bool useOrbSmoothing;
|
||||
|
||||
/// Transition time between colors (not implemented)
|
||||
int transitiontime;
|
||||
|
||||
// Maximum allowed color difference, will skip Orb (external) smoothing once reached
|
||||
int skipSmoothingDiff;
|
||||
|
||||
/// Multicast port to send data to
|
||||
int multiCastGroupPort;
|
||||
|
||||
/// Number of leds in Orb, used to determine buffer size
|
||||
int numLeds;
|
||||
|
||||
/// QHostAddress object of multicast group IP address
|
||||
QHostAddress groupAddress;
|
||||
|
||||
/// QUdpSocket object used to send data over
|
||||
QUdpSocket *udpSocket;
|
||||
|
||||
/// Array of the orb ids.
|
||||
std::vector<unsigned int> orbIds;
|
||||
|
||||
///
|
||||
/// Set Orbcolor
|
||||
///
|
||||
/// @param orbId the orb id
|
||||
///
|
||||
/// @param color which color to set
|
||||
///
|
||||
///
|
||||
/// @param commandType which type of command to send (off / smoothing / etc..)
|
||||
///
|
||||
void setColor(unsigned int orbId, const ColorRgb &color, int commandType);
|
||||
|
||||
///
|
||||
/// Send Orb command
|
||||
///
|
||||
/// @param bytes the byte array containing command to send over multicast
|
||||
///
|
||||
void sendCommand(const QByteArray &bytes);
|
||||
};
|
@ -1,50 +1,50 @@
|
||||
// STL includes
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
// Linux includes
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
// hyperion local includes
|
||||
#include "LedDeviceLpd6803.h"
|
||||
|
||||
LedDeviceLpd6803::LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate) :
|
||||
LedSpiDevice(outputDevice, baudrate),
|
||||
_ledBuffer(0)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
int LedDeviceLpd6803::write(const std::vector<ColorRgb> &ledValues)
|
||||
{
|
||||
unsigned messageLength = 4 + 2*ledValues.size() + ledValues.size()/8 + 1;
|
||||
// Reconfigure if the current connfiguration does not match the required configuration
|
||||
if (messageLength != _ledBuffer.size())
|
||||
{
|
||||
// Initialise the buffer
|
||||
_ledBuffer.resize(messageLength, 0x00);
|
||||
}
|
||||
|
||||
// Copy the colors from the ColorRgb vector to the Ldp6803 data vector
|
||||
for (unsigned iLed=0; iLed<ledValues.size(); ++iLed)
|
||||
{
|
||||
const ColorRgb& rgb = ledValues[iLed];
|
||||
|
||||
_ledBuffer[4 + 2 * iLed] = 0x80 | ((rgb.red & 0xf8) >> 1) | (rgb.green >> 6);
|
||||
_ledBuffer[5 + 2 * iLed] = ((rgb.green & 0x38) << 2) | (rgb.blue >> 3);
|
||||
}
|
||||
|
||||
// Write the data
|
||||
if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LedDeviceLpd6803::switchOff()
|
||||
{
|
||||
return write(std::vector<ColorRgb>(_ledBuffer.size(), ColorRgb{0,0,0}));
|
||||
}
|
||||
// STL includes
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
// Linux includes
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
// hyperion local includes
|
||||
#include "LedDeviceLpd6803.h"
|
||||
|
||||
LedDeviceLpd6803::LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate) :
|
||||
LedSpiDevice(outputDevice, baudrate),
|
||||
_ledBuffer(0)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
int LedDeviceLpd6803::write(const std::vector<ColorRgb> &ledValues)
|
||||
{
|
||||
unsigned messageLength = 4 + 2*ledValues.size() + ledValues.size()/8 + 1;
|
||||
// Reconfigure if the current connfiguration does not match the required configuration
|
||||
if (messageLength != _ledBuffer.size())
|
||||
{
|
||||
// Initialise the buffer
|
||||
_ledBuffer.resize(messageLength, 0x00);
|
||||
}
|
||||
|
||||
// Copy the colors from the ColorRgb vector to the Ldp6803 data vector
|
||||
for (unsigned iLed=0; iLed<ledValues.size(); ++iLed)
|
||||
{
|
||||
const ColorRgb& rgb = ledValues[iLed];
|
||||
|
||||
_ledBuffer[4 + 2 * iLed] = 0x80 | ((rgb.red & 0xf8) >> 1) | (rgb.green >> 6);
|
||||
_ledBuffer[5 + 2 * iLed] = ((rgb.green & 0x38) << 2) | (rgb.blue >> 3);
|
||||
}
|
||||
|
||||
// Write the data
|
||||
if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LedDeviceLpd6803::switchOff()
|
||||
{
|
||||
return write(std::vector<ColorRgb>(_ledBuffer.size(), ColorRgb{0,0,0}));
|
||||
}
|
||||
|
@ -1,42 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
// Local hyperion incluse
|
||||
#include "LedSpiDevice.h"
|
||||
|
||||
///
|
||||
/// Implementation of the LedDevice interface for writing to LDP6803 led device.
|
||||
///
|
||||
/// 00000000 00000000 00000000 00000000 1RRRRRGG GGGBBBBB 1RRRRRGG GGGBBBBB ...
|
||||
/// |---------------------------------| |---------------| |---------------|
|
||||
/// 32 zeros to start the frame Led1 Led2 ...
|
||||
///
|
||||
/// For each led, the first bit is always 1, and then you have 5 bits each for red, green and blue
|
||||
/// (R, G and B in the above illustration) making 16 bits per led. Total bytes = 4 + (2 x number of
|
||||
/// leds)
|
||||
///
|
||||
class LedDeviceLpd6803 : public LedSpiDevice
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Constructs the LedDevice for a string containing leds of the type LDP6803
|
||||
///
|
||||
/// @param[in] outputDevice The name of the output device (eg '/dev/spidev0.0')
|
||||
/// @param[in] baudrate The used baudrate for writing to the output device
|
||||
///
|
||||
LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate);
|
||||
|
||||
///
|
||||
/// Writes the led color values to the led-device
|
||||
///
|
||||
/// @param ledValues The color-value per led
|
||||
/// @return Zero on succes else negative
|
||||
///
|
||||
virtual int write(const std::vector<ColorRgb> &ledValues);
|
||||
|
||||
/// Switch the leds off
|
||||
virtual int switchOff();
|
||||
|
||||
private:
|
||||
/// The buffer containing the packed RGB values
|
||||
std::vector<uint8_t> _ledBuffer;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
// Local hyperion incluse
|
||||
#include "LedSpiDevice.h"
|
||||
|
||||
///
|
||||
/// Implementation of the LedDevice interface for writing to LDP6803 led device.
|
||||
///
|
||||
/// 00000000 00000000 00000000 00000000 1RRRRRGG GGGBBBBB 1RRRRRGG GGGBBBBB ...
|
||||
/// |---------------------------------| |---------------| |---------------|
|
||||
/// 32 zeros to start the frame Led1 Led2 ...
|
||||
///
|
||||
/// For each led, the first bit is always 1, and then you have 5 bits each for red, green and blue
|
||||
/// (R, G and B in the above illustration) making 16 bits per led. Total bytes = 4 + (2 x number of
|
||||
/// leds)
|
||||
///
|
||||
class LedDeviceLpd6803 : public LedSpiDevice
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Constructs the LedDevice for a string containing leds of the type LDP6803
|
||||
///
|
||||
/// @param[in] outputDevice The name of the output device (eg '/dev/spidev0.0')
|
||||
/// @param[in] baudrate The used baudrate for writing to the output device
|
||||
///
|
||||
LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate);
|
||||
|
||||
///
|
||||
/// Writes the led color values to the led-device
|
||||
///
|
||||
/// @param ledValues The color-value per led
|
||||
/// @return Zero on succes else negative
|
||||
///
|
||||
virtual int write(const std::vector<ColorRgb> &ledValues);
|
||||
|
||||
/// Switch the leds off
|
||||
virtual int switchOff();
|
||||
|
||||
private:
|
||||
/// The buffer containing the packed RGB values
|
||||
std::vector<uint8_t> _ledBuffer;
|
||||
};
|
||||
|
@ -1,54 +1,54 @@
|
||||
// STL includes
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
// Linux includes
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
// hyperion local includes
|
||||
#include "LedDeviceLpd8806.h"
|
||||
|
||||
LedDeviceLpd8806::LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate) :
|
||||
LedSpiDevice(outputDevice, baudrate),
|
||||
_ledBuffer(0)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
int LedDeviceLpd8806::write(const std::vector<ColorRgb> &ledValues)
|
||||
{
|
||||
const unsigned clearSize = ledValues.size()/32+1;
|
||||
// Reconfigure if the current connfiguration does not match the required configuration
|
||||
if (3*ledValues.size() + clearSize != _ledBuffer.size())
|
||||
{
|
||||
// Initialise the buffer
|
||||
_ledBuffer.resize(3*ledValues.size() + clearSize, 0x00);
|
||||
|
||||
// Perform an initial reset to start accepting data on the first led
|
||||
writeBytes(clearSize, _ledBuffer.data());
|
||||
}
|
||||
|
||||
// Copy the colors from the ColorRgb vector to the Ldp8806 data vector
|
||||
for (unsigned iLed=0; iLed<ledValues.size(); ++iLed)
|
||||
{
|
||||
const ColorRgb& rgb = ledValues[iLed];
|
||||
|
||||
_ledBuffer[iLed*3] = 0x80 | (rgb.red >> 1);
|
||||
_ledBuffer[iLed*3+1] = 0x80 | (rgb.green >> 1);
|
||||
_ledBuffer[iLed*3+2] = 0x80 | (rgb.blue >> 1);
|
||||
}
|
||||
|
||||
// Write the data
|
||||
if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LedDeviceLpd8806::switchOff()
|
||||
{
|
||||
return write(std::vector<ColorRgb>(_ledBuffer.size(), ColorRgb{0,0,0}));
|
||||
}
|
||||
// STL includes
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
// Linux includes
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
// hyperion local includes
|
||||
#include "LedDeviceLpd8806.h"
|
||||
|
||||
LedDeviceLpd8806::LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate) :
|
||||
LedSpiDevice(outputDevice, baudrate),
|
||||
_ledBuffer(0)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
int LedDeviceLpd8806::write(const std::vector<ColorRgb> &ledValues)
|
||||
{
|
||||
const unsigned clearSize = ledValues.size()/32+1;
|
||||
// Reconfigure if the current connfiguration does not match the required configuration
|
||||
if (3*ledValues.size() + clearSize != _ledBuffer.size())
|
||||
{
|
||||
// Initialise the buffer
|
||||
_ledBuffer.resize(3*ledValues.size() + clearSize, 0x00);
|
||||
|
||||
// Perform an initial reset to start accepting data on the first led
|
||||
writeBytes(clearSize, _ledBuffer.data());
|
||||
}
|
||||
|
||||
// Copy the colors from the ColorRgb vector to the Ldp8806 data vector
|
||||
for (unsigned iLed=0; iLed<ledValues.size(); ++iLed)
|
||||
{
|
||||
const ColorRgb& rgb = ledValues[iLed];
|
||||
|
||||
_ledBuffer[iLed*3] = 0x80 | (rgb.red >> 1);
|
||||
_ledBuffer[iLed*3+1] = 0x80 | (rgb.green >> 1);
|
||||
_ledBuffer[iLed*3+2] = 0x80 | (rgb.blue >> 1);
|
||||
}
|
||||
|
||||
// Write the data
|
||||
if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LedDeviceLpd8806::switchOff()
|
||||
{
|
||||
return write(std::vector<ColorRgb>(_ledBuffer.size(), ColorRgb{0,0,0}));
|
||||
}
|
||||
|
@ -1,103 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
// Local hyperion incluse
|
||||
#include "LedSpiDevice.h"
|
||||
|
||||
///
|
||||
/// Implementation of the LedDevice interface for writing to LPD8806 led device.
|
||||
///
|
||||
/// The following description is copied from 'adafruit' (github.com/adafruit/LPD8806)
|
||||
///
|
||||
/// Clearing up some misconceptions about how the LPD8806 drivers work:
|
||||
///
|
||||
/// The LPD8806 is not a FIFO shift register. The first data out controls the
|
||||
/// LED *closest* to the processor (unlike a typical shift register, where the
|
||||
/// first data out winds up at the *furthest* LED). Each LED driver 'fills up'
|
||||
/// with data and then passes through all subsequent bytes until a latch
|
||||
/// condition takes place. This is actually pretty common among LED drivers.
|
||||
///
|
||||
/// All color data bytes have the high bit (128) set, with the remaining
|
||||
/// seven bits containing a brightness value (0-127). A byte with the high
|
||||
/// bit clear has special meaning (explained later).
|
||||
///
|
||||
/// The rest gets bizarre...
|
||||
///
|
||||
/// The LPD8806 does not perform an in-unison latch (which would display the
|
||||
/// newly-transmitted data all at once). Rather, each individual byte (even
|
||||
/// the separate G, R, B components of each LED) is latched AS IT ARRIVES...
|
||||
/// or more accurately, as the first bit of the subsequent byte arrives and
|
||||
/// is passed through. So the strip actually refreshes at the speed the data
|
||||
/// is issued, not instantaneously (this can be observed by greatly reducing
|
||||
/// the data rate). This has implications for POV displays and light painting
|
||||
/// applications. The 'subsequent' rule also means that at least one extra
|
||||
/// byte must follow the last pixel, in order for the final blue LED to latch.
|
||||
///
|
||||
/// To reset the pass-through behavior and begin sending new data to the start
|
||||
/// of the strip, a number of zero bytes must be issued (remember, all color
|
||||
/// data bytes have the high bit set, thus are in the range 128 to 255, so the
|
||||
/// zero is 'special'). This should be done before each full payload of color
|
||||
/// values to the strip. Curiously, zero bytes can only travel one meter (32
|
||||
/// LEDs) down the line before needing backup; the next meter requires an
|
||||
/// extra zero byte, and so forth. Longer strips will require progressively
|
||||
/// more zeros. *(see note below)
|
||||
///
|
||||
/// In the interest of efficiency, it's possible to combine the former EOD
|
||||
/// extra latch byte and the latter zero reset...the same data can do double
|
||||
/// duty, latching the last blue LED while also resetting the strip for the
|
||||
/// next payload.
|
||||
///
|
||||
/// So: reset byte(s) of suitable length are issued once at startup to 'prime'
|
||||
/// the strip to a known ready state. After each subsequent LED color payload,
|
||||
/// these reset byte(s) are then issued at the END of each payload, both to
|
||||
/// latch the last LED and to prep the strip for the start of the next payload
|
||||
/// (even if that data does not arrive immediately). This avoids a tiny bit
|
||||
/// of latency as the new color payload can begin issuing immediately on some
|
||||
/// signal, such as a timer or GPIO trigger.
|
||||
///
|
||||
/// Technically these zero byte(s) are not a latch, as the color data (save
|
||||
/// for the last byte) is already latched. It's a start-of-data marker, or
|
||||
/// an indicator to clear the thing-that's-not-a-shift-register. But for
|
||||
/// conversational consistency with other LED drivers, we'll refer to it as
|
||||
/// a 'latch' anyway.
|
||||
///
|
||||
/// This has been validated independently with multiple customers'
|
||||
/// hardware. Please do not report as a bug or issue pull requests for
|
||||
/// this. Fewer zeros sometimes gives the *illusion* of working, the first
|
||||
/// payload will correctly load and latch, but subsequent frames will drop
|
||||
/// data at the end. The data shortfall won't always be visually apparent
|
||||
/// depending on the color data loaded on the prior and subsequent frames.
|
||||
/// Tested. Confirmed. Fact.
|
||||
///
|
||||
///
|
||||
/// The summary of the story is that the following needs to be writen on the spi-device:
|
||||
/// 1RRRRRRR 1GGGGGGG 1BBBBBBB 1RRRRRRR 1GGGGGGG ... ... 1GGGGGGG 1BBBBBBB 00000000 00000000 ...
|
||||
/// |---------led_1----------| |---------led_2-- -led_n----------| |----clear data--
|
||||
///
|
||||
/// The number of zeroes in the 'clear data' is (#led/32 + 1)bytes (or *8 for bits)
|
||||
///
|
||||
class LedDeviceLpd8806 : public LedSpiDevice
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Constructs the LedDevice for a string containing leds of the type LPD8806
|
||||
///
|
||||
/// @param[in] outputDevice The name of the output device (eg '/dev/spidev0.0')
|
||||
/// @param[in] baudrate The used baudrate for writing to the output device
|
||||
///
|
||||
LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate);
|
||||
|
||||
///
|
||||
/// Writes the led color values to the led-device
|
||||
///
|
||||
/// @param ledValues The color-value per led
|
||||
/// @return Zero on succes else negative
|
||||
///
|
||||
virtual int write(const std::vector<ColorRgb> &ledValues);
|
||||
|
||||
/// Switch the leds off
|
||||
virtual int switchOff();
|
||||
|
||||
private:
|
||||
/// The buffer containing the packed RGB values
|
||||
std::vector<uint8_t> _ledBuffer;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
// Local hyperion incluse
|
||||
#include "LedSpiDevice.h"
|
||||
|
||||
///
|
||||
/// Implementation of the LedDevice interface for writing to LPD8806 led device.
|
||||
///
|
||||
/// The following description is copied from 'adafruit' (github.com/adafruit/LPD8806)
|
||||
///
|
||||
/// Clearing up some misconceptions about how the LPD8806 drivers work:
|
||||
///
|
||||
/// The LPD8806 is not a FIFO shift register. The first data out controls the
|
||||
/// LED *closest* to the processor (unlike a typical shift register, where the
|
||||
/// first data out winds up at the *furthest* LED). Each LED driver 'fills up'
|
||||
/// with data and then passes through all subsequent bytes until a latch
|
||||
/// condition takes place. This is actually pretty common among LED drivers.
|
||||
///
|
||||
/// All color data bytes have the high bit (128) set, with the remaining
|
||||
/// seven bits containing a brightness value (0-127). A byte with the high
|
||||
/// bit clear has special meaning (explained later).
|
||||
///
|
||||
/// The rest gets bizarre...
|
||||
///
|
||||
/// The LPD8806 does not perform an in-unison latch (which would display the
|
||||
/// newly-transmitted data all at once). Rather, each individual byte (even
|
||||
/// the separate G, R, B components of each LED) is latched AS IT ARRIVES...
|
||||
/// or more accurately, as the first bit of the subsequent byte arrives and
|
||||
/// is passed through. So the strip actually refreshes at the speed the data
|
||||
/// is issued, not instantaneously (this can be observed by greatly reducing
|
||||
/// the data rate). This has implications for POV displays and light painting
|
||||
/// applications. The 'subsequent' rule also means that at least one extra
|
||||
/// byte must follow the last pixel, in order for the final blue LED to latch.
|
||||
///
|
||||
/// To reset the pass-through behavior and begin sending new data to the start
|
||||
/// of the strip, a number of zero bytes must be issued (remember, all color
|
||||
/// data bytes have the high bit set, thus are in the range 128 to 255, so the
|
||||
/// zero is 'special'). This should be done before each full payload of color
|
||||
/// values to the strip. Curiously, zero bytes can only travel one meter (32
|
||||
/// LEDs) down the line before needing backup; the next meter requires an
|
||||
/// extra zero byte, and so forth. Longer strips will require progressively
|
||||
/// more zeros. *(see note below)
|
||||
///
|
||||
/// In the interest of efficiency, it's possible to combine the former EOD
|
||||
/// extra latch byte and the latter zero reset...the same data can do double
|
||||
/// duty, latching the last blue LED while also resetting the strip for the
|
||||
/// next payload.
|
||||
///
|
||||
/// So: reset byte(s) of suitable length are issued once at startup to 'prime'
|
||||
/// the strip to a known ready state. After each subsequent LED color payload,
|
||||
/// these reset byte(s) are then issued at the END of each payload, both to
|
||||
/// latch the last LED and to prep the strip for the start of the next payload
|
||||
/// (even if that data does not arrive immediately). This avoids a tiny bit
|
||||
/// of latency as the new color payload can begin issuing immediately on some
|
||||
/// signal, such as a timer or GPIO trigger.
|
||||
///
|
||||
/// Technically these zero byte(s) are not a latch, as the color data (save
|
||||
/// for the last byte) is already latched. It's a start-of-data marker, or
|
||||
/// an indicator to clear the thing-that's-not-a-shift-register. But for
|
||||
/// conversational consistency with other LED drivers, we'll refer to it as
|
||||
/// a 'latch' anyway.
|
||||
///
|
||||
/// This has been validated independently with multiple customers'
|
||||
/// hardware. Please do not report as a bug or issue pull requests for
|
||||
/// this. Fewer zeros sometimes gives the *illusion* of working, the first
|
||||
/// payload will correctly load and latch, but subsequent frames will drop
|
||||
/// data at the end. The data shortfall won't always be visually apparent
|
||||
/// depending on the color data loaded on the prior and subsequent frames.
|
||||
/// Tested. Confirmed. Fact.
|
||||
///
|
||||
///
|
||||
/// The summary of the story is that the following needs to be writen on the spi-device:
|
||||
/// 1RRRRRRR 1GGGGGGG 1BBBBBBB 1RRRRRRR 1GGGGGGG ... ... 1GGGGGGG 1BBBBBBB 00000000 00000000 ...
|
||||
/// |---------led_1----------| |---------led_2-- -led_n----------| |----clear data--
|
||||
///
|
||||
/// The number of zeroes in the 'clear data' is (#led/32 + 1)bytes (or *8 for bits)
|
||||
///
|
||||
class LedDeviceLpd8806 : public LedSpiDevice
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Constructs the LedDevice for a string containing leds of the type LPD8806
|
||||
///
|
||||
/// @param[in] outputDevice The name of the output device (eg '/dev/spidev0.0')
|
||||
/// @param[in] baudrate The used baudrate for writing to the output device
|
||||
///
|
||||
LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate);
|
||||
|
||||
///
|
||||
/// Writes the led color values to the led-device
|
||||
///
|
||||
/// @param ledValues The color-value per led
|
||||
/// @return Zero on succes else negative
|
||||
///
|
||||
virtual int write(const std::vector<ColorRgb> &ledValues);
|
||||
|
||||
/// Switch the leds off
|
||||
virtual int switchOff();
|
||||
|
||||
private:
|
||||
/// The buffer containing the packed RGB values
|
||||
std::vector<uint8_t> _ledBuffer;
|
||||
};
|
||||
|
@ -1,342 +1,342 @@
|
||||
// Local-Hyperion includes
|
||||
#include "LedDevicePhilipsHue.h"
|
||||
|
||||
// jsoncpp includes
|
||||
#include <json/json.h>
|
||||
|
||||
// qt includes
|
||||
#include <QtCore/qmath.h>
|
||||
#include <QEventLoop>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <set>
|
||||
|
||||
bool operator ==(CiColor p1, CiColor p2) {
|
||||
return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri);
|
||||
}
|
||||
|
||||
bool operator !=(CiColor p1, CiColor p2) {
|
||||
return !(p1 == p2);
|
||||
}
|
||||
|
||||
PhilipsHueLight::PhilipsHueLight(unsigned int id, QString originalState, QString modelId) :
|
||||
id(id), originalState(originalState) {
|
||||
// Hue system model ids (http://www.developers.meethue.com/documentation/supported-lights).
|
||||
// Light strips, color iris, ...
|
||||
const std::set<QString> GAMUT_A_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012",
|
||||
"LLC013", "LLC014", "LST001" };
|
||||
// Hue bulbs, spots, ...
|
||||
const std::set<QString> GAMUT_B_MODEL_IDS = { "LCT001", "LCT002", "LCT003", "LCT007", "LLM001" };
|
||||
// Hue Lightstrip plus, go ...
|
||||
const std::set<QString> GAMUT_C_MODEL_IDS = { "LLC020", "LST002" };
|
||||
// Find id in the sets and set the appropiate color space.
|
||||
if (GAMUT_A_MODEL_IDS.find(modelId) != GAMUT_A_MODEL_IDS.end()) {
|
||||
colorSpace.red = {0.703f, 0.296f};
|
||||
colorSpace.green = {0.2151f, 0.7106f};
|
||||
colorSpace.blue = {0.138f, 0.08f};
|
||||
} else if (GAMUT_B_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) {
|
||||
colorSpace.red = {0.675f, 0.322f};
|
||||
colorSpace.green = {0.4091f, 0.518f};
|
||||
colorSpace.blue = {0.167f, 0.04f};
|
||||
} else if (GAMUT_C_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) {
|
||||
colorSpace.red = {0.675f, 0.322f};
|
||||
colorSpace.green = {0.2151f, 0.7106f};
|
||||
colorSpace.blue = {0.167f, 0.04f};
|
||||
} else {
|
||||
colorSpace.red = {1.0f, 0.0f};
|
||||
colorSpace.green = {0.0f, 1.0f};
|
||||
colorSpace.blue = {0.0f, 0.0f};
|
||||
}
|
||||
// Initialize black color.
|
||||
black = rgbToCiColor(0.0f, 0.0f, 0.0f);
|
||||
// Initialize color with black
|
||||
color = {black.x, black.y, black.bri};
|
||||
}
|
||||
|
||||
float PhilipsHueLight::crossProduct(CiColor p1, CiColor p2) {
|
||||
return p1.x * p2.y - p1.y * p2.x;
|
||||
}
|
||||
|
||||
bool PhilipsHueLight::isPointInLampsReach(CiColor p) {
|
||||
CiColor v1 = { colorSpace.green.x - colorSpace.red.x, colorSpace.green.y - colorSpace.red.y };
|
||||
CiColor v2 = { colorSpace.blue.x - colorSpace.red.x, colorSpace.blue.y - colorSpace.red.y };
|
||||
CiColor q = { p.x - colorSpace.red.x, p.y - colorSpace.red.y };
|
||||
float s = crossProduct(q, v2) / crossProduct(v1, v2);
|
||||
float t = crossProduct(v1, q) / crossProduct(v1, v2);
|
||||
if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CiColor PhilipsHueLight::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) {
|
||||
CiColor AP = { p.x - a.x, p.y - a.y };
|
||||
CiColor AB = { b.x - a.x, b.y - a.y };
|
||||
float ab2 = AB.x * AB.x + AB.y * AB.y;
|
||||
float ap_ab = AP.x * AB.x + AP.y * AB.y;
|
||||
float t = ap_ab / ab2;
|
||||
if (t < 0.0f) {
|
||||
t = 0.0f;
|
||||
} else if (t > 1.0f) {
|
||||
t = 1.0f;
|
||||
}
|
||||
return {a.x + AB.x * t, a.y + AB.y * t};
|
||||
}
|
||||
|
||||
float PhilipsHueLight::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) {
|
||||
// Horizontal difference.
|
||||
float dx = p1.x - p2.x;
|
||||
// Vertical difference.
|
||||
float dy = p1.y - p2.y;
|
||||
// Absolute value.
|
||||
return sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
CiColor PhilipsHueLight::rgbToCiColor(float red, float green, float blue) {
|
||||
// Apply gamma correction.
|
||||
float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f);
|
||||
float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f);
|
||||
float b = (blue > 0.04045f) ? powf((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f);
|
||||
// Convert to XYZ space.
|
||||
float X = r * 0.649926f + g * 0.103455f + b * 0.197109f;
|
||||
float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f;
|
||||
float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f;
|
||||
// Convert to x,y space.
|
||||
float cx = X / (X + Y + Z);
|
||||
float cy = Y / (X + Y + Z);
|
||||
if (isnan(cx)) {
|
||||
cx = 0.0f;
|
||||
}
|
||||
if (isnan(cy)) {
|
||||
cy = 0.0f;
|
||||
}
|
||||
// Brightness is simply Y in the XYZ space.
|
||||
CiColor xy = { cx, cy, Y };
|
||||
// Check if the given XY value is within the color reach of our lamps.
|
||||
if (!isPointInLampsReach(xy)) {
|
||||
// It seems the color is out of reach let's find the closes color we can produce with our lamp and send this XY value out.
|
||||
CiColor pAB = getClosestPointToPoint(colorSpace.red, colorSpace.green, xy);
|
||||
CiColor pAC = getClosestPointToPoint(colorSpace.blue, colorSpace.red, xy);
|
||||
CiColor pBC = getClosestPointToPoint(colorSpace.green, colorSpace.blue, xy);
|
||||
// Get the distances per point and see which point is closer to our Point.
|
||||
float dAB = getDistanceBetweenTwoPoints(xy, pAB);
|
||||
float dAC = getDistanceBetweenTwoPoints(xy, pAC);
|
||||
float dBC = getDistanceBetweenTwoPoints(xy, pBC);
|
||||
float lowest = dAB;
|
||||
CiColor closestPoint = pAB;
|
||||
if (dAC < lowest) {
|
||||
lowest = dAC;
|
||||
closestPoint = pAC;
|
||||
}
|
||||
if (dBC < lowest) {
|
||||
lowest = dBC;
|
||||
closestPoint = pBC;
|
||||
}
|
||||
// Change the xy value to a value which is within the reach of the lamp.
|
||||
xy.x = closestPoint.x;
|
||||
xy.y = closestPoint.y;
|
||||
}
|
||||
return xy;
|
||||
}
|
||||
|
||||
LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::string& username, bool switchOffOnBlack,
|
||||
int transitiontime, std::vector<unsigned int> lightIds) :
|
||||
host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime(
|
||||
transitiontime), lightIds(lightIds) {
|
||||
manager = new QNetworkAccessManager();
|
||||
timer.setInterval(3000);
|
||||
timer.setSingleShot(true);
|
||||
connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates()));
|
||||
}
|
||||
|
||||
LedDevicePhilipsHue::~LedDevicePhilipsHue() {
|
||||
delete manager;
|
||||
}
|
||||
|
||||
int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues) {
|
||||
// Save light states if not done before.
|
||||
if (!areStatesSaved()) {
|
||||
saveStates((unsigned int) ledValues.size());
|
||||
switchOn((unsigned int) ledValues.size());
|
||||
}
|
||||
// If there are less states saved than colors given, then maybe something went wrong before.
|
||||
if (lights.size() != ledValues.size()) {
|
||||
restoreStates();
|
||||
return 0;
|
||||
}
|
||||
// Iterate through colors and set light states.
|
||||
unsigned int idx = 0;
|
||||
for (const ColorRgb& color : ledValues) {
|
||||
// Get lamp.
|
||||
PhilipsHueLight& lamp = lights.at(idx);
|
||||
// Scale colors from [0, 255] to [0, 1] and convert to xy space.
|
||||
CiColor xy = lamp.rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f);
|
||||
// Write color if color has been changed.
|
||||
if (xy != lamp.color) {
|
||||
// Switch on if the lamp has been previously switched off.
|
||||
if (switchOffOnBlack && lamp.color == lamp.black) {
|
||||
put(getStateRoute(lamp.id), QString("{\"on\": true}"));
|
||||
}
|
||||
// Send adjust color and brightness command in JSON format.
|
||||
// We have to set the transition time each time.
|
||||
put(getStateRoute(lamp.id),
|
||||
QString("{\"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg(xy.y).arg(
|
||||
qRound(xy.bri * 255.0f)).arg(transitiontime));
|
||||
|
||||
}
|
||||
// Switch lamp off if switchOffOnBlack is enabled and the lamp is currently on.
|
||||
if (switchOffOnBlack) {
|
||||
// From black to a color.
|
||||
if (lamp.color == lamp.black && xy != lamp.black) {
|
||||
put(getStateRoute(lamp.id), QString("{\"on\": true}"));
|
||||
}
|
||||
// From a color to black.
|
||||
else if (lamp.color != lamp.black && xy == lamp.black) {
|
||||
put(getStateRoute(lamp.id), QString("{\"on\": false}"));
|
||||
}
|
||||
}
|
||||
// Remember last color.
|
||||
lamp.color = xy;
|
||||
// Next light id.
|
||||
idx++;
|
||||
}
|
||||
timer.start();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LedDevicePhilipsHue::switchOff() {
|
||||
timer.stop();
|
||||
// If light states have been saved before, ...
|
||||
if (areStatesSaved()) {
|
||||
// ... restore them.
|
||||
restoreStates();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LedDevicePhilipsHue::put(QString route, QString content) {
|
||||
QString url = getUrl(route);
|
||||
// Perfrom request
|
||||
QNetworkRequest request(url);
|
||||
QNetworkReply* reply = manager->put(request, content.toLatin1());
|
||||
// Connect finished signal to quit slot of the loop.
|
||||
QEventLoop loop;
|
||||
loop.connect(reply, SIGNAL(finished()), SLOT(quit()));
|
||||
// Go into the loop until the request is finished.
|
||||
loop.exec();
|
||||
// Free space.
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
QByteArray LedDevicePhilipsHue::get(QString route) {
|
||||
QString url = getUrl(route);
|
||||
// Perfrom request
|
||||
QNetworkRequest request(url);
|
||||
QNetworkReply* reply = manager->get(request);
|
||||
// Connect requestFinished signal to quit slot of the loop.
|
||||
QEventLoop loop;
|
||||
loop.connect(reply, SIGNAL(finished()), SLOT(quit()));
|
||||
// Go into the loop until the request is finished.
|
||||
loop.exec();
|
||||
// Read all data of the response.
|
||||
QByteArray response = reply->readAll();
|
||||
// Free space.
|
||||
reply->deleteLater();
|
||||
// Return response
|
||||
return response;
|
||||
}
|
||||
|
||||
QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) {
|
||||
return QString("lights/%1/state").arg(lightId);
|
||||
}
|
||||
|
||||
QString LedDevicePhilipsHue::getRoute(unsigned int lightId) {
|
||||
return QString("lights/%1").arg(lightId);
|
||||
}
|
||||
|
||||
QString LedDevicePhilipsHue::getUrl(QString route) {
|
||||
return QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route);
|
||||
}
|
||||
|
||||
void LedDevicePhilipsHue::saveStates(unsigned int nLights) {
|
||||
// Clear saved lamps.
|
||||
lights.clear();
|
||||
// Use json parser to parse reponse.
|
||||
Json::Reader reader;
|
||||
Json::FastWriter writer;
|
||||
// Read light ids if none have been supplied by the user.
|
||||
if (lightIds.size() != nLights) {
|
||||
lightIds.clear();
|
||||
//
|
||||
QByteArray response = get("lights");
|
||||
Json::Value json;
|
||||
if (!reader.parse(QString(response).toStdString(), json)) {
|
||||
throw std::runtime_error(("No lights found at " + getUrl("lights")).toStdString());
|
||||
}
|
||||
// Loop over all children.
|
||||
for (Json::ValueIterator it = json.begin(); it != json.end() && lightIds.size() < nLights; it++) {
|
||||
int lightId = atoi(it.key().asCString());
|
||||
lightIds.push_back(lightId);
|
||||
std::cout << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): found light with id " << lightId
|
||||
<< "." << std::endl;
|
||||
}
|
||||
// Check if we found enough lights.
|
||||
if (lightIds.size() != nLights) {
|
||||
throw std::runtime_error(("Not enough lights found at " + getUrl("lights")).toStdString());
|
||||
}
|
||||
}
|
||||
// Iterate lights.
|
||||
for (unsigned int i = 0; i < nLights; i++) {
|
||||
// Read the response.
|
||||
QByteArray response = get(getRoute(lightIds.at(i)));
|
||||
// Parse JSON.
|
||||
Json::Value json;
|
||||
if (!reader.parse(QString(response).toStdString(), json)) {
|
||||
// Error occured, break loop.
|
||||
std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got invalid response from light "
|
||||
<< getUrl(getRoute(lightIds.at(i))).toStdString() << "." << std::endl;
|
||||
break;
|
||||
}
|
||||
// Get state object values which are subject to change.
|
||||
Json::Value state(Json::objectValue);
|
||||
if (!json.isMember("state")) {
|
||||
std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no state for light from "
|
||||
<< getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl;
|
||||
break;
|
||||
}
|
||||
if (!json["state"].isMember("on")) {
|
||||
std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no valid state from light "
|
||||
<< getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl;
|
||||
break;
|
||||
}
|
||||
state["on"] = json["state"]["on"];
|
||||
if (json["state"]["on"] == true) {
|
||||
state["xy"] = json["state"]["xy"];
|
||||
state["bri"] = json["state"]["bri"];
|
||||
}
|
||||
// Determine the model id.
|
||||
QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", "");
|
||||
QString originalState = QString(writer.write(state).c_str()).trimmed();
|
||||
// Save state object.
|
||||
lights.push_back(PhilipsHueLight(lightIds.at(i), originalState, modelId));
|
||||
}
|
||||
}
|
||||
|
||||
void LedDevicePhilipsHue::switchOn(unsigned int nLights) {
|
||||
for (PhilipsHueLight light : lights) {
|
||||
put(getStateRoute(light.id), "{\"on\": true}");
|
||||
}
|
||||
}
|
||||
|
||||
void LedDevicePhilipsHue::restoreStates() {
|
||||
for (PhilipsHueLight light : lights) {
|
||||
put(getStateRoute(light.id), light.originalState);
|
||||
}
|
||||
// Clear saved light states.
|
||||
lights.clear();
|
||||
}
|
||||
|
||||
bool LedDevicePhilipsHue::areStatesSaved() {
|
||||
return !lights.empty();
|
||||
}
|
||||
// Local-Hyperion includes
|
||||
#include "LedDevicePhilipsHue.h"
|
||||
|
||||
// jsoncpp includes
|
||||
#include <json/json.h>
|
||||
|
||||
// qt includes
|
||||
#include <QtCore/qmath.h>
|
||||
#include <QEventLoop>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <set>
|
||||
|
||||
bool operator ==(CiColor p1, CiColor p2) {
|
||||
return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri);
|
||||
}
|
||||
|
||||
bool operator !=(CiColor p1, CiColor p2) {
|
||||
return !(p1 == p2);
|
||||
}
|
||||
|
||||
PhilipsHueLight::PhilipsHueLight(unsigned int id, QString originalState, QString modelId) :
|
||||
id(id), originalState(originalState) {
|
||||
// Hue system model ids (http://www.developers.meethue.com/documentation/supported-lights).
|
||||
// Light strips, color iris, ...
|
||||
const std::set<QString> GAMUT_A_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012",
|
||||
"LLC013", "LLC014", "LST001" };
|
||||
// Hue bulbs, spots, ...
|
||||
const std::set<QString> GAMUT_B_MODEL_IDS = { "LCT001", "LCT002", "LCT003", "LCT007", "LLM001" };
|
||||
// Hue Lightstrip plus, go ...
|
||||
const std::set<QString> GAMUT_C_MODEL_IDS = { "LLC020", "LST002" };
|
||||
// Find id in the sets and set the appropiate color space.
|
||||
if (GAMUT_A_MODEL_IDS.find(modelId) != GAMUT_A_MODEL_IDS.end()) {
|
||||
colorSpace.red = {0.703f, 0.296f};
|
||||
colorSpace.green = {0.2151f, 0.7106f};
|
||||
colorSpace.blue = {0.138f, 0.08f};
|
||||
} else if (GAMUT_B_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) {
|
||||
colorSpace.red = {0.675f, 0.322f};
|
||||
colorSpace.green = {0.4091f, 0.518f};
|
||||
colorSpace.blue = {0.167f, 0.04f};
|
||||
} else if (GAMUT_C_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) {
|
||||
colorSpace.red = {0.675f, 0.322f};
|
||||
colorSpace.green = {0.2151f, 0.7106f};
|
||||
colorSpace.blue = {0.167f, 0.04f};
|
||||
} else {
|
||||
colorSpace.red = {1.0f, 0.0f};
|
||||
colorSpace.green = {0.0f, 1.0f};
|
||||
colorSpace.blue = {0.0f, 0.0f};
|
||||
}
|
||||
// Initialize black color.
|
||||
black = rgbToCiColor(0.0f, 0.0f, 0.0f);
|
||||
// Initialize color with black
|
||||
color = {black.x, black.y, black.bri};
|
||||
}
|
||||
|
||||
float PhilipsHueLight::crossProduct(CiColor p1, CiColor p2) {
|
||||
return p1.x * p2.y - p1.y * p2.x;
|
||||
}
|
||||
|
||||
bool PhilipsHueLight::isPointInLampsReach(CiColor p) {
|
||||
CiColor v1 = { colorSpace.green.x - colorSpace.red.x, colorSpace.green.y - colorSpace.red.y };
|
||||
CiColor v2 = { colorSpace.blue.x - colorSpace.red.x, colorSpace.blue.y - colorSpace.red.y };
|
||||
CiColor q = { p.x - colorSpace.red.x, p.y - colorSpace.red.y };
|
||||
float s = crossProduct(q, v2) / crossProduct(v1, v2);
|
||||
float t = crossProduct(v1, q) / crossProduct(v1, v2);
|
||||
if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CiColor PhilipsHueLight::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) {
|
||||
CiColor AP = { p.x - a.x, p.y - a.y };
|
||||
CiColor AB = { b.x - a.x, b.y - a.y };
|
||||
float ab2 = AB.x * AB.x + AB.y * AB.y;
|
||||
float ap_ab = AP.x * AB.x + AP.y * AB.y;
|
||||
float t = ap_ab / ab2;
|
||||
if (t < 0.0f) {
|
||||
t = 0.0f;
|
||||
} else if (t > 1.0f) {
|
||||
t = 1.0f;
|
||||
}
|
||||
return {a.x + AB.x * t, a.y + AB.y * t};
|
||||
}
|
||||
|
||||
float PhilipsHueLight::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) {
|
||||
// Horizontal difference.
|
||||
float dx = p1.x - p2.x;
|
||||
// Vertical difference.
|
||||
float dy = p1.y - p2.y;
|
||||
// Absolute value.
|
||||
return sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
CiColor PhilipsHueLight::rgbToCiColor(float red, float green, float blue) {
|
||||
// Apply gamma correction.
|
||||
float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f);
|
||||
float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f);
|
||||
float b = (blue > 0.04045f) ? powf((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f);
|
||||
// Convert to XYZ space.
|
||||
float X = r * 0.649926f + g * 0.103455f + b * 0.197109f;
|
||||
float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f;
|
||||
float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f;
|
||||
// Convert to x,y space.
|
||||
float cx = X / (X + Y + Z);
|
||||
float cy = Y / (X + Y + Z);
|
||||
if (isnan(cx)) {
|
||||
cx = 0.0f;
|
||||
}
|
||||
if (isnan(cy)) {
|
||||
cy = 0.0f;
|
||||
}
|
||||
// Brightness is simply Y in the XYZ space.
|
||||
CiColor xy = { cx, cy, Y };
|
||||
// Check if the given XY value is within the color reach of our lamps.
|
||||
if (!isPointInLampsReach(xy)) {
|
||||
// It seems the color is out of reach let's find the closes color we can produce with our lamp and send this XY value out.
|
||||
CiColor pAB = getClosestPointToPoint(colorSpace.red, colorSpace.green, xy);
|
||||
CiColor pAC = getClosestPointToPoint(colorSpace.blue, colorSpace.red, xy);
|
||||
CiColor pBC = getClosestPointToPoint(colorSpace.green, colorSpace.blue, xy);
|
||||
// Get the distances per point and see which point is closer to our Point.
|
||||
float dAB = getDistanceBetweenTwoPoints(xy, pAB);
|
||||
float dAC = getDistanceBetweenTwoPoints(xy, pAC);
|
||||
float dBC = getDistanceBetweenTwoPoints(xy, pBC);
|
||||
float lowest = dAB;
|
||||
CiColor closestPoint = pAB;
|
||||
if (dAC < lowest) {
|
||||
lowest = dAC;
|
||||
closestPoint = pAC;
|
||||
}
|
||||
if (dBC < lowest) {
|
||||
lowest = dBC;
|
||||
closestPoint = pBC;
|
||||
}
|
||||
// Change the xy value to a value which is within the reach of the lamp.
|
||||
xy.x = closestPoint.x;
|
||||
xy.y = closestPoint.y;
|
||||
}
|
||||
return xy;
|
||||
}
|
||||
|
||||
LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::string& username, bool switchOffOnBlack,
|
||||
int transitiontime, std::vector<unsigned int> lightIds) :
|
||||
host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime(
|
||||
transitiontime), lightIds(lightIds) {
|
||||
manager = new QNetworkAccessManager();
|
||||
timer.setInterval(3000);
|
||||
timer.setSingleShot(true);
|
||||
connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates()));
|
||||
}
|
||||
|
||||
LedDevicePhilipsHue::~LedDevicePhilipsHue() {
|
||||
delete manager;
|
||||
}
|
||||
|
||||
int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues) {
|
||||
// Save light states if not done before.
|
||||
if (!areStatesSaved()) {
|
||||
saveStates((unsigned int) ledValues.size());
|
||||
switchOn((unsigned int) ledValues.size());
|
||||
}
|
||||
// If there are less states saved than colors given, then maybe something went wrong before.
|
||||
if (lights.size() != ledValues.size()) {
|
||||
restoreStates();
|
||||
return 0;
|
||||
}
|
||||
// Iterate through colors and set light states.
|
||||
unsigned int idx = 0;
|
||||
for (const ColorRgb& color : ledValues) {
|
||||
// Get lamp.
|
||||
PhilipsHueLight& lamp = lights.at(idx);
|
||||
// Scale colors from [0, 255] to [0, 1] and convert to xy space.
|
||||
CiColor xy = lamp.rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f);
|
||||
// Write color if color has been changed.
|
||||
if (xy != lamp.color) {
|
||||
// Switch on if the lamp has been previously switched off.
|
||||
if (switchOffOnBlack && lamp.color == lamp.black) {
|
||||
put(getStateRoute(lamp.id), QString("{\"on\": true}"));
|
||||
}
|
||||
// Send adjust color and brightness command in JSON format.
|
||||
// We have to set the transition time each time.
|
||||
put(getStateRoute(lamp.id),
|
||||
QString("{\"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg(xy.y).arg(
|
||||
qRound(xy.bri * 255.0f)).arg(transitiontime));
|
||||
|
||||
}
|
||||
// Switch lamp off if switchOffOnBlack is enabled and the lamp is currently on.
|
||||
if (switchOffOnBlack) {
|
||||
// From black to a color.
|
||||
if (lamp.color == lamp.black && xy != lamp.black) {
|
||||
put(getStateRoute(lamp.id), QString("{\"on\": true}"));
|
||||
}
|
||||
// From a color to black.
|
||||
else if (lamp.color != lamp.black && xy == lamp.black) {
|
||||
put(getStateRoute(lamp.id), QString("{\"on\": false}"));
|
||||
}
|
||||
}
|
||||
// Remember last color.
|
||||
lamp.color = xy;
|
||||
// Next light id.
|
||||
idx++;
|
||||
}
|
||||
timer.start();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LedDevicePhilipsHue::switchOff() {
|
||||
timer.stop();
|
||||
// If light states have been saved before, ...
|
||||
if (areStatesSaved()) {
|
||||
// ... restore them.
|
||||
restoreStates();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LedDevicePhilipsHue::put(QString route, QString content) {
|
||||
QString url = getUrl(route);
|
||||
// Perfrom request
|
||||
QNetworkRequest request(url);
|
||||
QNetworkReply* reply = manager->put(request, content.toLatin1());
|
||||
// Connect finished signal to quit slot of the loop.
|
||||
QEventLoop loop;
|
||||
loop.connect(reply, SIGNAL(finished()), SLOT(quit()));
|
||||
// Go into the loop until the request is finished.
|
||||
loop.exec();
|
||||
// Free space.
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
QByteArray LedDevicePhilipsHue::get(QString route) {
|
||||
QString url = getUrl(route);
|
||||
// Perfrom request
|
||||
QNetworkRequest request(url);
|
||||
QNetworkReply* reply = manager->get(request);
|
||||
// Connect requestFinished signal to quit slot of the loop.
|
||||
QEventLoop loop;
|
||||
loop.connect(reply, SIGNAL(finished()), SLOT(quit()));
|
||||
// Go into the loop until the request is finished.
|
||||
loop.exec();
|
||||
// Read all data of the response.
|
||||
QByteArray response = reply->readAll();
|
||||
// Free space.
|
||||
reply->deleteLater();
|
||||
// Return response
|
||||
return response;
|
||||
}
|
||||
|
||||
QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) {
|
||||
return QString("lights/%1/state").arg(lightId);
|
||||
}
|
||||
|
||||
QString LedDevicePhilipsHue::getRoute(unsigned int lightId) {
|
||||
return QString("lights/%1").arg(lightId);
|
||||
}
|
||||
|
||||
QString LedDevicePhilipsHue::getUrl(QString route) {
|
||||
return QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route);
|
||||
}
|
||||
|
||||
void LedDevicePhilipsHue::saveStates(unsigned int nLights) {
|
||||
// Clear saved lamps.
|
||||
lights.clear();
|
||||
// Use json parser to parse reponse.
|
||||
Json::Reader reader;
|
||||
Json::FastWriter writer;
|
||||
// Read light ids if none have been supplied by the user.
|
||||
if (lightIds.size() != nLights) {
|
||||
lightIds.clear();
|
||||
//
|
||||
QByteArray response = get("lights");
|
||||
Json::Value json;
|
||||
if (!reader.parse(QString(response).toStdString(), json)) {
|
||||
throw std::runtime_error(("No lights found at " + getUrl("lights")).toStdString());
|
||||
}
|
||||
// Loop over all children.
|
||||
for (Json::ValueIterator it = json.begin(); it != json.end() && lightIds.size() < nLights; it++) {
|
||||
int lightId = atoi(it.key().asCString());
|
||||
lightIds.push_back(lightId);
|
||||
std::cout << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): found light with id " << lightId
|
||||
<< "." << std::endl;
|
||||
}
|
||||
// Check if we found enough lights.
|
||||
if (lightIds.size() != nLights) {
|
||||
throw std::runtime_error(("Not enough lights found at " + getUrl("lights")).toStdString());
|
||||
}
|
||||
}
|
||||
// Iterate lights.
|
||||
for (unsigned int i = 0; i < nLights; i++) {
|
||||
// Read the response.
|
||||
QByteArray response = get(getRoute(lightIds.at(i)));
|
||||
// Parse JSON.
|
||||
Json::Value json;
|
||||
if (!reader.parse(QString(response).toStdString(), json)) {
|
||||
// Error occured, break loop.
|
||||
std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got invalid response from light "
|
||||
<< getUrl(getRoute(lightIds.at(i))).toStdString() << "." << std::endl;
|
||||
break;
|
||||
}
|
||||
// Get state object values which are subject to change.
|
||||
Json::Value state(Json::objectValue);
|
||||
if (!json.isMember("state")) {
|
||||
std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no state for light from "
|
||||
<< getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl;
|
||||
break;
|
||||
}
|
||||
if (!json["state"].isMember("on")) {
|
||||
std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no valid state from light "
|
||||
<< getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl;
|
||||
break;
|
||||
}
|
||||
state["on"] = json["state"]["on"];
|
||||
if (json["state"]["on"] == true) {
|
||||
state["xy"] = json["state"]["xy"];
|
||||
state["bri"] = json["state"]["bri"];
|
||||
}
|
||||
// Determine the model id.
|
||||
QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", "");
|
||||
QString originalState = QString(writer.write(state).c_str()).trimmed();
|
||||
// Save state object.
|
||||
lights.push_back(PhilipsHueLight(lightIds.at(i), originalState, modelId));
|
||||
}
|
||||
}
|
||||
|
||||
void LedDevicePhilipsHue::switchOn(unsigned int nLights) {
|
||||
for (PhilipsHueLight light : lights) {
|
||||
put(getStateRoute(light.id), "{\"on\": true}");
|
||||
}
|
||||
}
|
||||
|
||||
void LedDevicePhilipsHue::restoreStates() {
|
||||
for (PhilipsHueLight light : lights) {
|
||||
put(getStateRoute(light.id), light.originalState);
|
||||
}
|
||||
// Clear saved light states.
|
||||
lights.clear();
|
||||
}
|
||||
|
||||
bool LedDevicePhilipsHue::areStatesSaved() {
|
||||
return !lights.empty();
|
||||
}
|
||||
|
@ -1,236 +1,236 @@
|
||||
#pragma once
|
||||
|
||||
// STL includes
|
||||
#include <string>
|
||||
|
||||
// Qt includes
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QTimer>
|
||||
// Leddevice includes
|
||||
#include <leddevice/LedDevice.h>
|
||||
|
||||
/**
|
||||
* A color point in the color space of the hue system.
|
||||
*/
|
||||
struct CiColor {
|
||||
/// X component.
|
||||
float x;
|
||||
/// Y component.
|
||||
float y;
|
||||
/// The brightness.
|
||||
float bri;
|
||||
};
|
||||
|
||||
bool operator==(CiColor p1, CiColor p2);
|
||||
bool operator!=(CiColor p1, CiColor p2);
|
||||
|
||||
/**
|
||||
* Color triangle to define an available color space for the hue lamps.
|
||||
*/
|
||||
struct CiColorTriangle {
|
||||
CiColor red, green, blue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple class to hold the id, the latest color, the color space and the original state.
|
||||
*/
|
||||
class PhilipsHueLight {
|
||||
public:
|
||||
unsigned int id;
|
||||
CiColor black;
|
||||
CiColor color;
|
||||
CiColorTriangle colorSpace;
|
||||
QString originalState;
|
||||
|
||||
///
|
||||
/// Constructs the light.
|
||||
///
|
||||
/// @param id the light id
|
||||
///
|
||||
/// @param originalState the json string of the original state
|
||||
///
|
||||
/// @param modelId the model id of the hue lamp which is used to determine the color space
|
||||
///
|
||||
PhilipsHueLight(unsigned int id, QString originalState, QString modelId);
|
||||
|
||||
///
|
||||
/// Converts an RGB color to the Hue xy color space and brightness.
|
||||
/// https://github.com/PhilipsHue/PhilipsHueSDK-iOS-OSX/blob/master/ApplicationDesignNotes/RGB%20to%20xy%20Color%20conversion.md
|
||||
///
|
||||
/// @param red the red component in [0, 1]
|
||||
///
|
||||
/// @param green the green component in [0, 1]
|
||||
///
|
||||
/// @param blue the blue component in [0, 1]
|
||||
///
|
||||
/// @return color point
|
||||
///
|
||||
CiColor rgbToCiColor(float red, float green, float blue);
|
||||
|
||||
///
|
||||
/// @param p the color point to check
|
||||
///
|
||||
/// @return true if the color point is covered by the lamp color space
|
||||
///
|
||||
bool isPointInLampsReach(CiColor p);
|
||||
|
||||
///
|
||||
/// @param p1 point one
|
||||
///
|
||||
/// @param p2 point tow
|
||||
///
|
||||
/// @return the cross product between p1 and p2
|
||||
///
|
||||
float crossProduct(CiColor p1, CiColor p2);
|
||||
|
||||
///
|
||||
/// @param a reference point one
|
||||
///
|
||||
/// @param b reference point two
|
||||
///
|
||||
/// @param p the point to which the closest point is to be found
|
||||
///
|
||||
/// @return the closest color point of p to a and b
|
||||
///
|
||||
CiColor getClosestPointToPoint(CiColor a, CiColor b, CiColor p);
|
||||
|
||||
///
|
||||
/// @param p1 point one
|
||||
///
|
||||
/// @param p2 point tow
|
||||
///
|
||||
/// @return the distance between the two points
|
||||
///
|
||||
float getDistanceBetweenTwoPoints(CiColor p1, CiColor p2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation for the Philips Hue system.
|
||||
*
|
||||
* To use set the device to "philipshue".
|
||||
* Uses the official Philips Hue API (http://developers.meethue.com).
|
||||
* Framegrabber must be limited to 10 Hz / numer of lights to avoid rate limitation by the hue bridge.
|
||||
* Create a new API user name "newdeveloper" on the bridge (http://developers.meethue.com/gettingstarted.html)
|
||||
*
|
||||
* @author ntim (github), bimsarck (github)
|
||||
*/
|
||||
class LedDevicePhilipsHue: public QObject, public LedDevice {
|
||||
Q_OBJECT
|
||||
public:
|
||||
///
|
||||
/// Constructs the device.
|
||||
///
|
||||
/// @param output the ip address of the bridge
|
||||
///
|
||||
/// @param username username of the hue bridge (default: newdeveloper)
|
||||
///
|
||||
/// @param switchOffOnBlack kill lights for black (default: false)
|
||||
///
|
||||
/// @param transitiontime the time duration a light change takes in multiples of 100 ms (default: 400 ms).
|
||||
///
|
||||
/// @param lightIds light ids of the lights to control if not starting at one in ascending order.
|
||||
///
|
||||
LedDevicePhilipsHue(const std::string& output, const std::string& username = "newdeveloper", bool switchOffOnBlack =
|
||||
false, int transitiontime = 1, std::vector<unsigned int> lightIds = std::vector<unsigned int>());
|
||||
|
||||
///
|
||||
/// Destructor of this device
|
||||
///
|
||||
virtual ~LedDevicePhilipsHue();
|
||||
|
||||
///
|
||||
/// Sends the given led-color values via put request to the hue system
|
||||
///
|
||||
/// @param ledValues The color-value per led
|
||||
///
|
||||
/// @return Zero on success else negative
|
||||
///
|
||||
virtual int write(const std::vector<ColorRgb> & ledValues);
|
||||
|
||||
/// Restores the original state of the leds.
|
||||
virtual int switchOff();
|
||||
|
||||
private slots:
|
||||
/// Restores the status of all lights.
|
||||
void restoreStates();
|
||||
|
||||
private:
|
||||
/// Array to save the lamps.
|
||||
std::vector<PhilipsHueLight> lights;
|
||||
/// Ip address of the bridge
|
||||
QString host;
|
||||
/// User name for the API ("newdeveloper")
|
||||
QString username;
|
||||
/// QNetworkAccessManager object for sending requests.
|
||||
#pragma once
|
||||
|
||||
// STL includes
|
||||
#include <string>
|
||||
|
||||
// Qt includes
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QTimer>
|
||||
// Leddevice includes
|
||||
#include <leddevice/LedDevice.h>
|
||||
|
||||
/**
|
||||
* A color point in the color space of the hue system.
|
||||
*/
|
||||
struct CiColor {
|
||||
/// X component.
|
||||
float x;
|
||||
/// Y component.
|
||||
float y;
|
||||
/// The brightness.
|
||||
float bri;
|
||||
};
|
||||
|
||||
bool operator==(CiColor p1, CiColor p2);
|
||||
bool operator!=(CiColor p1, CiColor p2);
|
||||
|
||||
/**
|
||||
* Color triangle to define an available color space for the hue lamps.
|
||||
*/
|
||||
struct CiColorTriangle {
|
||||
CiColor red, green, blue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple class to hold the id, the latest color, the color space and the original state.
|
||||
*/
|
||||
class PhilipsHueLight {
|
||||
public:
|
||||
unsigned int id;
|
||||
CiColor black;
|
||||
CiColor color;
|
||||
CiColorTriangle colorSpace;
|
||||
QString originalState;
|
||||
|
||||
///
|
||||
/// Constructs the light.
|
||||
///
|
||||
/// @param id the light id
|
||||
///
|
||||
/// @param originalState the json string of the original state
|
||||
///
|
||||
/// @param modelId the model id of the hue lamp which is used to determine the color space
|
||||
///
|
||||
PhilipsHueLight(unsigned int id, QString originalState, QString modelId);
|
||||
|
||||
///
|
||||
/// Converts an RGB color to the Hue xy color space and brightness.
|
||||
/// https://github.com/PhilipsHue/PhilipsHueSDK-iOS-OSX/blob/master/ApplicationDesignNotes/RGB%20to%20xy%20Color%20conversion.md
|
||||
///
|
||||
/// @param red the red component in [0, 1]
|
||||
///
|
||||
/// @param green the green component in [0, 1]
|
||||
///
|
||||
/// @param blue the blue component in [0, 1]
|
||||
///
|
||||
/// @return color point
|
||||
///
|
||||
CiColor rgbToCiColor(float red, float green, float blue);
|
||||
|
||||
///
|
||||
/// @param p the color point to check
|
||||
///
|
||||
/// @return true if the color point is covered by the lamp color space
|
||||
///
|
||||
bool isPointInLampsReach(CiColor p);
|
||||
|
||||
///
|
||||
/// @param p1 point one
|
||||
///
|
||||
/// @param p2 point tow
|
||||
///
|
||||
/// @return the cross product between p1 and p2
|
||||
///
|
||||
float crossProduct(CiColor p1, CiColor p2);
|
||||
|
||||
///
|
||||
/// @param a reference point one
|
||||
///
|
||||
/// @param b reference point two
|
||||
///
|
||||
/// @param p the point to which the closest point is to be found
|
||||
///
|
||||
/// @return the closest color point of p to a and b
|
||||
///
|
||||
CiColor getClosestPointToPoint(CiColor a, CiColor b, CiColor p);
|
||||
|
||||
///
|
||||
/// @param p1 point one
|
||||
///
|
||||
/// @param p2 point tow
|
||||
///
|
||||
/// @return the distance between the two points
|
||||
///
|
||||
float getDistanceBetweenTwoPoints(CiColor p1, CiColor p2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation for the Philips Hue system.
|
||||
*
|
||||
* To use set the device to "philipshue".
|
||||
* Uses the official Philips Hue API (http://developers.meethue.com).
|
||||
* Framegrabber must be limited to 10 Hz / numer of lights to avoid rate limitation by the hue bridge.
|
||||
* Create a new API user name "newdeveloper" on the bridge (http://developers.meethue.com/gettingstarted.html)
|
||||
*
|
||||
* @author ntim (github), bimsarck (github)
|
||||
*/
|
||||
class LedDevicePhilipsHue: public QObject, public LedDevice {
|
||||
Q_OBJECT
|
||||
public:
|
||||
///
|
||||
/// Constructs the device.
|
||||
///
|
||||
/// @param output the ip address of the bridge
|
||||
///
|
||||
/// @param username username of the hue bridge (default: newdeveloper)
|
||||
///
|
||||
/// @param switchOffOnBlack kill lights for black (default: false)
|
||||
///
|
||||
/// @param transitiontime the time duration a light change takes in multiples of 100 ms (default: 400 ms).
|
||||
///
|
||||
/// @param lightIds light ids of the lights to control if not starting at one in ascending order.
|
||||
///
|
||||
LedDevicePhilipsHue(const std::string& output, const std::string& username = "newdeveloper", bool switchOffOnBlack =
|
||||
false, int transitiontime = 1, std::vector<unsigned int> lightIds = std::vector<unsigned int>());
|
||||
|
||||
///
|
||||
/// Destructor of this device
|
||||
///
|
||||
virtual ~LedDevicePhilipsHue();
|
||||
|
||||
///
|
||||
/// Sends the given led-color values via put request to the hue system
|
||||
///
|
||||
/// @param ledValues The color-value per led
|
||||
///
|
||||
/// @return Zero on success else negative
|
||||
///
|
||||
virtual int write(const std::vector<ColorRgb> & ledValues);
|
||||
|
||||
/// Restores the original state of the leds.
|
||||
virtual int switchOff();
|
||||
|
||||
private slots:
|
||||
/// Restores the status of all lights.
|
||||
void restoreStates();
|
||||
|
||||
private:
|
||||
/// Array to save the lamps.
|
||||
std::vector<PhilipsHueLight> lights;
|
||||
/// Ip address of the bridge
|
||||
QString host;
|
||||
/// User name for the API ("newdeveloper")
|
||||
QString username;
|
||||
/// QNetworkAccessManager object for sending requests.
|
||||
QNetworkAccessManager* manager;
|
||||
/// Use timer to reset lights when we got into "GRABBINGMODE_OFF".
|
||||
QTimer timer;
|
||||
///
|
||||
bool switchOffOnBlack;
|
||||
/// Transition time in multiples of 100 ms.
|
||||
/// The default of the Hue lights will be 400 ms, but we want to have it snapier
|
||||
int transitiontime;
|
||||
/// Array of the light ids.
|
||||
std::vector<unsigned int> lightIds;
|
||||
|
||||
///
|
||||
/// Sends a HTTP GET request (blocking).
|
||||
///
|
||||
/// @param route the URI of the request
|
||||
///
|
||||
/// @return response of the request
|
||||
///
|
||||
QByteArray get(QString route);
|
||||
|
||||
///
|
||||
/// Sends a HTTP PUT request (non-blocking).
|
||||
///
|
||||
/// @param route the URI of the request
|
||||
///
|
||||
/// @param content content of the request
|
||||
///
|
||||
void put(QString route, QString content);
|
||||
|
||||
///
|
||||
/// @param lightId the id of the hue light (starting from 1)
|
||||
///
|
||||
/// @return the URI of the light state for PUT requests.
|
||||
///
|
||||
QString getStateRoute(unsigned int lightId);
|
||||
|
||||
///
|
||||
/// @param lightId the id of the hue light (starting from 1)
|
||||
///
|
||||
/// @return the URI of the light for GET requests.
|
||||
///
|
||||
QString getRoute(unsigned int lightId);
|
||||
|
||||
///
|
||||
/// @param route
|
||||
///
|
||||
/// @return the full URL of the request.
|
||||
///
|
||||
QString getUrl(QString route);
|
||||
|
||||
///
|
||||
/// Queries the status of all lights and saves it.
|
||||
///
|
||||
/// @param nLights the number of lights
|
||||
///
|
||||
void saveStates(unsigned int nLights);
|
||||
|
||||
///
|
||||
/// Switches the leds on.
|
||||
///
|
||||
/// @param nLights the number of lights
|
||||
///
|
||||
void switchOn(unsigned int nLights);
|
||||
|
||||
///
|
||||
/// @return true if light states have been saved.
|
||||
///
|
||||
bool areStatesSaved();
|
||||
|
||||
};
|
||||
/// Use timer to reset lights when we got into "GRABBINGMODE_OFF".
|
||||
QTimer timer;
|
||||
///
|
||||
bool switchOffOnBlack;
|
||||
/// Transition time in multiples of 100 ms.
|
||||
/// The default of the Hue lights will be 400 ms, but we want to have it snapier
|
||||
int transitiontime;
|
||||
/// Array of the light ids.
|
||||
std::vector<unsigned int> lightIds;
|
||||
|
||||
///
|
||||
/// Sends a HTTP GET request (blocking).
|
||||
///
|
||||
/// @param route the URI of the request
|
||||
///
|
||||
/// @return response of the request
|
||||
///
|
||||
QByteArray get(QString route);
|
||||
|
||||
///
|
||||
/// Sends a HTTP PUT request (non-blocking).
|
||||
///
|
||||
/// @param route the URI of the request
|
||||
///
|
||||
/// @param content content of the request
|
||||
///
|
||||
void put(QString route, QString content);
|
||||
|
||||
///
|
||||
/// @param lightId the id of the hue light (starting from 1)
|
||||
///
|
||||
/// @return the URI of the light state for PUT requests.
|
||||
///
|
||||
QString getStateRoute(unsigned int lightId);
|
||||
|
||||
///
|
||||
/// @param lightId the id of the hue light (starting from 1)
|
||||
///
|
||||
/// @return the URI of the light for GET requests.
|
||||
///
|
||||
QString getRoute(unsigned int lightId);
|
||||
|
||||
///
|
||||
/// @param route
|
||||
///
|
||||
/// @return the full URL of the request.
|
||||
///
|
||||
QString getUrl(QString route);
|
||||
|
||||
///
|
||||
/// Queries the status of all lights and saves it.
|
||||
///
|
||||
/// @param nLights the number of lights
|
||||
///
|
||||
void saveStates(unsigned int nLights);
|
||||
|
||||
///
|
||||
/// Switches the leds on.
|
||||
///
|
||||
/// @param nLights the number of lights
|
||||
///
|
||||
void switchOn(unsigned int nLights);
|
||||
|
||||
///
|
||||
/// @return true if light states have been saved.
|
||||
///
|
||||
bool areStatesSaved();
|
||||
|
||||
};
|
||||
|
@ -16,18 +16,18 @@ LedDeviceTpm2::LedDeviceTpm2(const std::string& outputDevice, const unsigned bau
|
||||
|
||||
int LedDeviceTpm2::write(const std::vector<ColorRgb> &ledValues)
|
||||
{
|
||||
if (_ledBuffer.size() == 0)
|
||||
{
|
||||
_ledBuffer.resize(5 + 3*ledValues.size());
|
||||
_ledBuffer[0] = 0xC9; // block-start byte
|
||||
_ledBuffer[1] = 0xDA; // DATA frame
|
||||
_ledBuffer[2] = ((3 * ledValues.size()) >> 8) & 0xFF; // frame size high byte
|
||||
_ledBuffer[3] = (3 * ledValues.size()) & 0xFF; // frame size low byte
|
||||
_ledBuffer.back() = 0x36; // block-end byte
|
||||
}
|
||||
if (_ledBuffer.size() == 0)
|
||||
{
|
||||
_ledBuffer.resize(5 + 3*ledValues.size());
|
||||
_ledBuffer[0] = 0xC9; // block-start byte
|
||||
_ledBuffer[1] = 0xDA; // DATA frame
|
||||
_ledBuffer[2] = ((3 * ledValues.size()) >> 8) & 0xFF; // frame size high byte
|
||||
_ledBuffer[3] = (3 * ledValues.size()) & 0xFF; // frame size low byte
|
||||
_ledBuffer.back() = 0x36; // block-end byte
|
||||
}
|
||||
|
||||
// write data
|
||||
memcpy(4 + _ledBuffer.data(), ledValues.data(), ledValues.size() * 3);
|
||||
// write data
|
||||
memcpy(4 + _ledBuffer.data(), ledValues.data(), ledValues.size() * 3);
|
||||
return writeBytes(_ledBuffer.size(), _ledBuffer.data());
|
||||
}
|
||||
|
||||
|
@ -25,55 +25,54 @@ LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate, c
|
||||
//LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate) :
|
||||
// _ofs(output.empty()?"/home/pi/LedDevice.out":output.c_str())
|
||||
{
|
||||
|
||||
std::string hostname;
|
||||
std::string port;
|
||||
ledprotocol = protocol;
|
||||
leds_per_pkt = ((maxPacket-4)/3);
|
||||
if (leds_per_pkt <= 0) {
|
||||
leds_per_pkt = 200;
|
||||
}
|
||||
std::string hostname;
|
||||
std::string port;
|
||||
ledprotocol = protocol;
|
||||
leds_per_pkt = ((maxPacket-4)/3);
|
||||
if (leds_per_pkt <= 0) {
|
||||
leds_per_pkt = 200;
|
||||
}
|
||||
|
||||
//printf ("leds_per_pkt is %d\n", leds_per_pkt);
|
||||
int got_colon=0;
|
||||
for (unsigned int i=0; i<output.length(); i++) {
|
||||
if (output[i] == ':') {
|
||||
got_colon++;
|
||||
} else if (got_colon == 0) {
|
||||
hostname+=output[i];
|
||||
} else {
|
||||
port+=output[i];
|
||||
int got_colon=0;
|
||||
for (unsigned int i=0; i<output.length(); i++) {
|
||||
if (output[i] == ':') {
|
||||
got_colon++;
|
||||
} else if (got_colon == 0) {
|
||||
hostname+=output[i];
|
||||
} else {
|
||||
port+=output[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
//std::cout << "output " << output << " hostname " << hostname << " port " << port <<std::endl;
|
||||
assert(got_colon==1);
|
||||
//std::cout << "output " << output << " hostname " << hostname << " port " << port <<std::endl;
|
||||
assert(got_colon==1);
|
||||
|
||||
int rv;
|
||||
int rv;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
|
||||
if ((rv = getaddrinfo(hostname.c_str() , port.c_str(), &hints, &servinfo)) != 0) {
|
||||
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
|
||||
assert(rv==0);
|
||||
}
|
||||
if ((rv = getaddrinfo(hostname.c_str() , port.c_str(), &hints, &servinfo)) != 0) {
|
||||
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
|
||||
assert(rv==0);
|
||||
}
|
||||
|
||||
// loop through all the results and make a socket
|
||||
for(p = servinfo; p != NULL; p = p->ai_next) {
|
||||
if ((sockfd = socket(p->ai_family, p->ai_socktype,
|
||||
p->ai_protocol)) == -1) {
|
||||
perror("talker: socket");
|
||||
continue;
|
||||
}
|
||||
// loop through all the results and make a socket
|
||||
for(p = servinfo; p != NULL; p = p->ai_next) {
|
||||
if ((sockfd = socket(p->ai_family, p->ai_socktype,
|
||||
p->ai_protocol)) == -1) {
|
||||
perror("talker: socket");
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (p == NULL) {
|
||||
fprintf(stderr, "talker: failed to create socket\n");
|
||||
assert(p!=NULL);
|
||||
}
|
||||
if (p == NULL) {
|
||||
fprintf(stderr, "talker: failed to create socket\n");
|
||||
assert(p!=NULL);
|
||||
}
|
||||
}
|
||||
|
||||
LedDeviceUdp::~LedDeviceUdp()
|
||||
@ -99,7 +98,7 @@ int LedDeviceUdp::write(const std::vector<ColorRgb> & ledValues)
|
||||
udpbuffer[i++] = color.green;
|
||||
udpbuffer[i++] = color.blue;
|
||||
}
|
||||
//printf ("c.red %d sz c.red %d\n", color.red, sizeof(color.red));
|
||||
//printf ("c.red %d sz c.red %d\n", color.red, sizeof(color.red));
|
||||
}
|
||||
sendto(sockfd, udpbuffer, i, 0, p->ai_addr, p->ai_addrlen);
|
||||
}
|
||||
@ -153,7 +152,6 @@ int LedDeviceUdp::write(const std::vector<ColorRgb> & ledValues)
|
||||
udpbuffer[udpPtr++] = ledCtr%256; // low byte
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ledprotocol == 3) {
|
||||
@ -172,7 +170,6 @@ int LedDeviceUdp::write(const std::vector<ColorRgb> & ledValues)
|
||||
udpbuffer[udpPtr++] = fragment_number++;
|
||||
udpbuffer[udpPtr++] = fragments;
|
||||
|
||||
|
||||
for (const ColorRgb& color : ledValues)
|
||||
{
|
||||
if (udpPtr<4090) {
|
||||
@ -201,6 +198,6 @@ int LedDeviceUdp::write(const std::vector<ColorRgb> & ledValues)
|
||||
|
||||
int LedDeviceUdp::switchOff()
|
||||
{
|
||||
// return write(std::vector<ColorRgb>(mLedCount, ColorRgb{0,0,0}));
|
||||
// return write(std::vector<ColorRgb>(mLedCount, ColorRgb{0,0,0}));
|
||||
return 0;
|
||||
}
|
||||
|
@ -86,17 +86,17 @@
|
||||
// Raspberry Pi low-level peripherals:
|
||||
// http://elinux.org/RPi_Low-level_peripherals
|
||||
//
|
||||
// Richard Hirst's nice, clean code:
|
||||
// https://github.com/richardghirst/PiBits/blob/master/PiFmDma/PiFmDma.c
|
||||
// Richard Hirst's nice, clean code:
|
||||
// https://github.com/richardghirst/PiBits/blob/master/PiFmDma/PiFmDma.c
|
||||
//
|
||||
// PWM clock register:
|
||||
// http://www.raspberrypi.org/forums/viewtopic.php?t=8467&p=124620
|
||||
//
|
||||
// Simple (because it's in assembly) PWM+DMA setup:
|
||||
// https://github.com/mikedurso/rpi-projects/blob/master/asm-nyancat/rpi-nyancat.s
|
||||
// Simple (because it's in assembly) PWM+DMA setup:
|
||||
// https://github.com/mikedurso/rpi-projects/blob/master/asm-nyancat/rpi-nyancat.s
|
||||
//
|
||||
// Adafruit's NeoPixel driver:
|
||||
// https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp
|
||||
// Adafruit's NeoPixel driver:
|
||||
// https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp
|
||||
|
||||
// Hyperion includes
|
||||
#include <leddevice/LedDevice.h>
|
||||
|
@ -1,61 +1,61 @@
|
||||
|
||||
# Define the current source locations
|
||||
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/protoserver)
|
||||
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/protoserver)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${PROTOBUF_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
set(ProtoServer_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/ProtoServer.h
|
||||
${CURRENT_HEADER_DIR}/ProtoConnection.h
|
||||
${CURRENT_SOURCE_DIR}/ProtoClientConnection.h
|
||||
${CURRENT_HEADER_DIR}/ProtoConnectionWrapper.h
|
||||
)
|
||||
|
||||
set(ProtoServer_HEADERS
|
||||
)
|
||||
|
||||
set(ProtoServer_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/ProtoServer.cpp
|
||||
${CURRENT_SOURCE_DIR}/ProtoClientConnection.cpp
|
||||
${CURRENT_SOURCE_DIR}/ProtoConnection.cpp
|
||||
${CURRENT_SOURCE_DIR}/ProtoConnectionWrapper.cpp
|
||||
)
|
||||
|
||||
set(ProtoServer_PROTOS
|
||||
${CURRENT_SOURCE_DIR}/message.proto
|
||||
)
|
||||
|
||||
protobuf_generate_cpp(ProtoServer_PROTO_SRCS ProtoServer_PROTO_HDRS
|
||||
${ProtoServer_PROTOS}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
qt4_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
add_library(protoserver
|
||||
${ProtoServer_HEADERS}
|
||||
${ProtoServer_QT_HEADERS}
|
||||
${ProtoServer_SOURCES}
|
||||
${ProtoServer_HEADERS_MOC}
|
||||
${ProtoServer_PROTOS}
|
||||
${ProtoServer_PROTO_SRCS}
|
||||
${ProtoServer_PROTO_HDRS}
|
||||
)
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(protoserver Widgets)
|
||||
endif(ENABLE_QT5)
|
||||
|
||||
target_link_libraries(protoserver
|
||||
hyperion
|
||||
hyperion-utils
|
||||
protobuf
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
||||
# Define the current source locations
|
||||
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/protoserver)
|
||||
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/protoserver)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${PROTOBUF_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
set(ProtoServer_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/ProtoServer.h
|
||||
${CURRENT_HEADER_DIR}/ProtoConnection.h
|
||||
${CURRENT_SOURCE_DIR}/ProtoClientConnection.h
|
||||
${CURRENT_HEADER_DIR}/ProtoConnectionWrapper.h
|
||||
)
|
||||
|
||||
set(ProtoServer_HEADERS
|
||||
)
|
||||
|
||||
set(ProtoServer_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/ProtoServer.cpp
|
||||
${CURRENT_SOURCE_DIR}/ProtoClientConnection.cpp
|
||||
${CURRENT_SOURCE_DIR}/ProtoConnection.cpp
|
||||
${CURRENT_SOURCE_DIR}/ProtoConnectionWrapper.cpp
|
||||
)
|
||||
|
||||
set(ProtoServer_PROTOS
|
||||
${CURRENT_SOURCE_DIR}/message.proto
|
||||
)
|
||||
|
||||
protobuf_generate_cpp(ProtoServer_PROTO_SRCS ProtoServer_PROTO_HDRS
|
||||
${ProtoServer_PROTOS}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS})
|
||||
else()
|
||||
qt4_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS})
|
||||
endif()
|
||||
|
||||
add_library(protoserver
|
||||
${ProtoServer_HEADERS}
|
||||
${ProtoServer_QT_HEADERS}
|
||||
${ProtoServer_SOURCES}
|
||||
${ProtoServer_HEADERS_MOC}
|
||||
${ProtoServer_PROTOS}
|
||||
${ProtoServer_PROTO_SRCS}
|
||||
${ProtoServer_PROTO_HDRS}
|
||||
)
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(protoserver Widgets)
|
||||
endif()
|
||||
|
||||
target_link_libraries(protoserver
|
||||
hyperion
|
||||
hyperion-utils
|
||||
protobuf
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
@ -8,207 +8,207 @@
|
||||
#include "protoserver/ProtoConnection.h"
|
||||
|
||||
ProtoConnection::ProtoConnection(const std::string & a) :
|
||||
_socket(),
|
||||
_skipReply(false),
|
||||
_prevSocketState(QAbstractSocket::UnconnectedState)
|
||||
_socket(),
|
||||
_skipReply(false),
|
||||
_prevSocketState(QAbstractSocket::UnconnectedState)
|
||||
{
|
||||
QString address(a.c_str());
|
||||
QStringList parts = address.split(":");
|
||||
if (parts.size() != 2)
|
||||
{
|
||||
throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong address: Unable to parse address (%1)").arg(address).toStdString());
|
||||
}
|
||||
_host = parts[0];
|
||||
QString address(a.c_str());
|
||||
QStringList parts = address.split(":");
|
||||
if (parts.size() != 2)
|
||||
{
|
||||
throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong address: Unable to parse address (%1)").arg(address).toStdString());
|
||||
}
|
||||
_host = parts[0];
|
||||
|
||||
bool ok;
|
||||
_port = parts[1].toUShort(&ok);
|
||||
if (!ok)
|
||||
{
|
||||
throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong port: Unable to parse the port number (%1)").arg(parts[1]).toStdString());
|
||||
}
|
||||
bool ok;
|
||||
_port = parts[1].toUShort(&ok);
|
||||
if (!ok)
|
||||
{
|
||||
throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong port: Unable to parse the port number (%1)").arg(parts[1]).toStdString());
|
||||
}
|
||||
|
||||
// try to connect to host
|
||||
std::cout << "PROTOCONNECTION INFO: Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
|
||||
connectToHost();
|
||||
// try to connect to host
|
||||
std::cout << "PROTOCONNECTION INFO: Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
|
||||
connectToHost();
|
||||
|
||||
// start the connection timer
|
||||
_timer.setInterval(5000);
|
||||
_timer.setSingleShot(false);
|
||||
// start the connection timer
|
||||
_timer.setInterval(5000);
|
||||
_timer.setSingleShot(false);
|
||||
|
||||
connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()) );
|
||||
_timer.start();
|
||||
connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()) );
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
ProtoConnection::~ProtoConnection()
|
||||
{
|
||||
_timer.stop();
|
||||
_socket.close();
|
||||
_timer.stop();
|
||||
_socket.close();
|
||||
}
|
||||
|
||||
void ProtoConnection::setSkipReply(bool skip)
|
||||
{
|
||||
_skipReply = skip;
|
||||
_skipReply = skip;
|
||||
}
|
||||
|
||||
void ProtoConnection::setColor(const ColorRgb & color, int priority, int duration)
|
||||
{
|
||||
proto::HyperionRequest request;
|
||||
request.set_command(proto::HyperionRequest::COLOR);
|
||||
proto::ColorRequest * colorRequest = request.MutableExtension(proto::ColorRequest::colorRequest);
|
||||
colorRequest->set_rgbcolor((color.red << 16) | (color.green << 8) | color.blue);
|
||||
colorRequest->set_priority(priority);
|
||||
colorRequest->set_duration(duration);
|
||||
proto::HyperionRequest request;
|
||||
request.set_command(proto::HyperionRequest::COLOR);
|
||||
proto::ColorRequest * colorRequest = request.MutableExtension(proto::ColorRequest::colorRequest);
|
||||
colorRequest->set_rgbcolor((color.red << 16) | (color.green << 8) | color.blue);
|
||||
colorRequest->set_priority(priority);
|
||||
colorRequest->set_duration(duration);
|
||||
|
||||
// send command message
|
||||
sendMessage(request);
|
||||
// send command message
|
||||
sendMessage(request);
|
||||
}
|
||||
|
||||
void ProtoConnection::setImage(const Image<ColorRgb> &image, int priority, int duration)
|
||||
{
|
||||
proto::HyperionRequest request;
|
||||
request.set_command(proto::HyperionRequest::IMAGE);
|
||||
proto::ImageRequest * imageRequest = request.MutableExtension(proto::ImageRequest::imageRequest);
|
||||
imageRequest->set_imagedata(image.memptr(), image.width() * image.height() * 3);
|
||||
imageRequest->set_imagewidth(image.width());
|
||||
imageRequest->set_imageheight(image.height());
|
||||
imageRequest->set_priority(priority);
|
||||
imageRequest->set_duration(duration);
|
||||
proto::HyperionRequest request;
|
||||
request.set_command(proto::HyperionRequest::IMAGE);
|
||||
proto::ImageRequest * imageRequest = request.MutableExtension(proto::ImageRequest::imageRequest);
|
||||
imageRequest->set_imagedata(image.memptr(), image.width() * image.height() * 3);
|
||||
imageRequest->set_imagewidth(image.width());
|
||||
imageRequest->set_imageheight(image.height());
|
||||
imageRequest->set_priority(priority);
|
||||
imageRequest->set_duration(duration);
|
||||
|
||||
// send command message
|
||||
sendMessage(request);
|
||||
// send command message
|
||||
sendMessage(request);
|
||||
}
|
||||
|
||||
void ProtoConnection::clear(int priority)
|
||||
{
|
||||
proto::HyperionRequest request;
|
||||
request.set_command(proto::HyperionRequest::CLEAR);
|
||||
proto::ClearRequest * clearRequest = request.MutableExtension(proto::ClearRequest::clearRequest);
|
||||
clearRequest->set_priority(priority);
|
||||
proto::HyperionRequest request;
|
||||
request.set_command(proto::HyperionRequest::CLEAR);
|
||||
proto::ClearRequest * clearRequest = request.MutableExtension(proto::ClearRequest::clearRequest);
|
||||
clearRequest->set_priority(priority);
|
||||
|
||||
// send command message
|
||||
sendMessage(request);
|
||||
// send command message
|
||||
sendMessage(request);
|
||||
}
|
||||
|
||||
void ProtoConnection::clearAll()
|
||||
{
|
||||
proto::HyperionRequest request;
|
||||
request.set_command(proto::HyperionRequest::CLEARALL);
|
||||
proto::HyperionRequest request;
|
||||
request.set_command(proto::HyperionRequest::CLEARALL);
|
||||
|
||||
// send command message
|
||||
sendMessage(request);
|
||||
// send command message
|
||||
sendMessage(request);
|
||||
}
|
||||
|
||||
void ProtoConnection::connectToHost()
|
||||
{
|
||||
// try connection only when
|
||||
if (_socket.state() == QAbstractSocket::UnconnectedState)
|
||||
{
|
||||
_socket.connectToHost(_host, _port);
|
||||
//_socket.waitForConnected(1000);
|
||||
}
|
||||
// try connection only when
|
||||
if (_socket.state() == QAbstractSocket::UnconnectedState)
|
||||
{
|
||||
_socket.connectToHost(_host, _port);
|
||||
//_socket.waitForConnected(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void ProtoConnection::sendMessage(const proto::HyperionRequest &message)
|
||||
{
|
||||
// print out connection message only when state is changed
|
||||
if (_socket.state() != _prevSocketState )
|
||||
{
|
||||
switch (_socket.state() )
|
||||
{
|
||||
case QAbstractSocket::UnconnectedState:
|
||||
std::cout << "PROTOCONNECTION INFO: No connection to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
|
||||
break;
|
||||
// print out connection message only when state is changed
|
||||
if (_socket.state() != _prevSocketState )
|
||||
{
|
||||
switch (_socket.state() )
|
||||
{
|
||||
case QAbstractSocket::UnconnectedState:
|
||||
std::cout << "PROTOCONNECTION INFO: No connection to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
|
||||
break;
|
||||
|
||||
case QAbstractSocket::ConnectedState:
|
||||
std::cout << "PROTOCONNECTION INFO: Connected to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
|
||||
break;
|
||||
case QAbstractSocket::ConnectedState:
|
||||
std::cout << "PROTOCONNECTION INFO: Connected to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
|
||||
break;
|
||||
|
||||
default:
|
||||
//std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
|
||||
break;
|
||||
}
|
||||
_prevSocketState = _socket.state();
|
||||
}
|
||||
default:
|
||||
//std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
|
||||
break;
|
||||
}
|
||||
_prevSocketState = _socket.state();
|
||||
}
|
||||
|
||||
|
||||
if (_socket.state() != QAbstractSocket::ConnectedState)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_socket.state() != QAbstractSocket::ConnectedState)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We only get here if we are connected
|
||||
// We only get here if we are connected
|
||||
|
||||
// serialize message (FastWriter already appends a newline)
|
||||
std::string serializedMessage = message.SerializeAsString();
|
||||
// serialize message (FastWriter already appends a newline)
|
||||
std::string serializedMessage = message.SerializeAsString();
|
||||
|
||||
int length = serializedMessage.size();
|
||||
const uint8_t header[] = {
|
||||
uint8_t((length >> 24) & 0xFF),
|
||||
uint8_t((length >> 16) & 0xFF),
|
||||
uint8_t((length >> 8) & 0xFF),
|
||||
uint8_t((length ) & 0xFF)};
|
||||
int length = serializedMessage.size();
|
||||
const uint8_t header[] = {
|
||||
uint8_t((length >> 24) & 0xFF),
|
||||
uint8_t((length >> 16) & 0xFF),
|
||||
uint8_t((length >> 8) & 0xFF),
|
||||
uint8_t((length ) & 0xFF)};
|
||||
|
||||
// write message
|
||||
int count = 0;
|
||||
count += _socket.write(reinterpret_cast<const char *>(header), 4);
|
||||
count += _socket.write(reinterpret_cast<const char *>(serializedMessage.data()), length);
|
||||
if (!_socket.waitForBytesWritten())
|
||||
{
|
||||
std::cerr << "PROTOCONNECTION ERROR: Error while writing data to host" << std::endl;
|
||||
return;
|
||||
}
|
||||
// write message
|
||||
int count = 0;
|
||||
count += _socket.write(reinterpret_cast<const char *>(header), 4);
|
||||
count += _socket.write(reinterpret_cast<const char *>(serializedMessage.data()), length);
|
||||
if (!_socket.waitForBytesWritten())
|
||||
{
|
||||
std::cerr << "PROTOCONNECTION ERROR: Error while writing data to host" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_skipReply)
|
||||
{
|
||||
// read reply data
|
||||
QByteArray serializedReply;
|
||||
length = -1;
|
||||
while (length < 0 && serializedReply.size() < length+4)
|
||||
{
|
||||
// receive reply
|
||||
if (!_socket.waitForReadyRead())
|
||||
{
|
||||
std::cerr << "PROTOCONNECTION ERROR: Error while reading data from host" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (!_skipReply)
|
||||
{
|
||||
// read reply data
|
||||
QByteArray serializedReply;
|
||||
length = -1;
|
||||
while (length < 0 && serializedReply.size() < length+4)
|
||||
{
|
||||
// receive reply
|
||||
if (!_socket.waitForReadyRead())
|
||||
{
|
||||
std::cerr << "PROTOCONNECTION ERROR: Error while reading data from host" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
serializedReply += _socket.readAll();
|
||||
serializedReply += _socket.readAll();
|
||||
|
||||
if (length < 0 && serializedReply.size() >= 4)
|
||||
{
|
||||
// read the message size
|
||||
length =
|
||||
((serializedReply[0]<<24) & 0xFF000000) |
|
||||
((serializedReply[1]<<16) & 0x00FF0000) |
|
||||
((serializedReply[2]<< 8) & 0x0000FF00) |
|
||||
((serializedReply[3] ) & 0x000000FF);
|
||||
}
|
||||
}
|
||||
if (length < 0 && serializedReply.size() >= 4)
|
||||
{
|
||||
// read the message size
|
||||
length =
|
||||
((serializedReply[0]<<24) & 0xFF000000) |
|
||||
((serializedReply[1]<<16) & 0x00FF0000) |
|
||||
((serializedReply[2]<< 8) & 0x0000FF00) |
|
||||
((serializedReply[3] ) & 0x000000FF);
|
||||
}
|
||||
}
|
||||
|
||||
// parse reply data
|
||||
proto::HyperionReply reply;
|
||||
reply.ParseFromArray(serializedReply.constData()+4, length);
|
||||
// parse reply data
|
||||
proto::HyperionReply reply;
|
||||
reply.ParseFromArray(serializedReply.constData()+4, length);
|
||||
|
||||
// parse reply message
|
||||
parseReply(reply);
|
||||
}
|
||||
// parse reply message
|
||||
parseReply(reply);
|
||||
}
|
||||
}
|
||||
|
||||
bool ProtoConnection::parseReply(const proto::HyperionReply &reply)
|
||||
{
|
||||
bool success = false;
|
||||
bool success = false;
|
||||
|
||||
if (!reply.success())
|
||||
{
|
||||
if (reply.has_error())
|
||||
{
|
||||
throw std::runtime_error("PROTOCONNECTION ERROR: " + reply.error());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("PROTOCONNECTION ERROR: No error info");
|
||||
}
|
||||
}
|
||||
if (!reply.success())
|
||||
{
|
||||
if (reply.has_error())
|
||||
{
|
||||
throw std::runtime_error("PROTOCONNECTION ERROR: " + reply.error());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("PROTOCONNECTION ERROR: No error info");
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
return success;
|
||||
}
|
||||
|
@ -2,11 +2,11 @@
|
||||
#include "protoserver/ProtoConnectionWrapper.h"
|
||||
|
||||
ProtoConnectionWrapper::ProtoConnectionWrapper(const std::string & address, int priority, int duration_ms, bool skipProtoReply) :
|
||||
_priority(priority),
|
||||
_duration_ms(duration_ms),
|
||||
_connection(address)
|
||||
_priority(priority),
|
||||
_duration_ms(duration_ms),
|
||||
_connection(address)
|
||||
{
|
||||
_connection.setSkipReply(skipProtoReply);
|
||||
_connection.setSkipReply(skipProtoReply);
|
||||
}
|
||||
|
||||
ProtoConnectionWrapper::~ProtoConnectionWrapper()
|
||||
@ -15,5 +15,5 @@ ProtoConnectionWrapper::~ProtoConnectionWrapper()
|
||||
|
||||
void ProtoConnectionWrapper::receiveImage(const Image<ColorRgb> & image)
|
||||
{
|
||||
_connection.setImage(image, _priority, _duration_ms);
|
||||
_connection.setImage(image, _priority, _duration_ms);
|
||||
}
|
||||
|
@ -1,41 +1,41 @@
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/utils)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/utils)
|
||||
|
||||
add_library(hyperion-utils
|
||||
${CURRENT_HEADER_DIR}/ColorArgb.h
|
||||
${CURRENT_SOURCE_DIR}/ColorArgb.cpp
|
||||
${CURRENT_HEADER_DIR}/ColorBgr.h
|
||||
${CURRENT_SOURCE_DIR}/ColorBgr.cpp
|
||||
${CURRENT_HEADER_DIR}/ColorRgb.h
|
||||
${CURRENT_SOURCE_DIR}/ColorRgb.cpp
|
||||
${CURRENT_HEADER_DIR}/ColorRgba.h
|
||||
${CURRENT_SOURCE_DIR}/ColorRgba.cpp
|
||||
${CURRENT_HEADER_DIR}/Image.h
|
||||
${CURRENT_HEADER_DIR}/Sleep.h
|
||||
|
||||
${CURRENT_HEADER_DIR}/PixelFormat.h
|
||||
${CURRENT_HEADER_DIR}/VideoMode.h
|
||||
|
||||
${CURRENT_HEADER_DIR}/ImageResampler.h
|
||||
${CURRENT_SOURCE_DIR}/ImageResampler.cpp
|
||||
|
||||
${CURRENT_HEADER_DIR}/HsvTransform.h
|
||||
${CURRENT_SOURCE_DIR}/HsvTransform.cpp
|
||||
${CURRENT_HEADER_DIR}/HslTransform.h
|
||||
${CURRENT_SOURCE_DIR}/HslTransform.cpp
|
||||
${CURRENT_HEADER_DIR}/RgbChannelTransform.h
|
||||
${CURRENT_SOURCE_DIR}/RgbChannelTransform.cpp
|
||||
${CURRENT_HEADER_DIR}/RgbChannelCorrection.h
|
||||
${CURRENT_SOURCE_DIR}/RgbChannelCorrection.cpp
|
||||
${CURRENT_HEADER_DIR}/RgbChannelAdjustment.h
|
||||
${CURRENT_SOURCE_DIR}/RgbChannelAdjustment.cpp
|
||||
|
||||
${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h
|
||||
${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h
|
||||
${CURRENT_SOURCE_DIR}/jsonschema/JsonSchemaChecker.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(hyperion-utils
|
||||
jsoncpp)
|
||||
|
||||
# Define the current source locations
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/utils)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/utils)
|
||||
|
||||
add_library(hyperion-utils
|
||||
${CURRENT_HEADER_DIR}/ColorArgb.h
|
||||
${CURRENT_SOURCE_DIR}/ColorArgb.cpp
|
||||
${CURRENT_HEADER_DIR}/ColorBgr.h
|
||||
${CURRENT_SOURCE_DIR}/ColorBgr.cpp
|
||||
${CURRENT_HEADER_DIR}/ColorRgb.h
|
||||
${CURRENT_SOURCE_DIR}/ColorRgb.cpp
|
||||
${CURRENT_HEADER_DIR}/ColorRgba.h
|
||||
${CURRENT_SOURCE_DIR}/ColorRgba.cpp
|
||||
${CURRENT_HEADER_DIR}/Image.h
|
||||
${CURRENT_HEADER_DIR}/Sleep.h
|
||||
|
||||
${CURRENT_HEADER_DIR}/PixelFormat.h
|
||||
${CURRENT_HEADER_DIR}/VideoMode.h
|
||||
|
||||
${CURRENT_HEADER_DIR}/ImageResampler.h
|
||||
${CURRENT_SOURCE_DIR}/ImageResampler.cpp
|
||||
|
||||
${CURRENT_HEADER_DIR}/HsvTransform.h
|
||||
${CURRENT_SOURCE_DIR}/HsvTransform.cpp
|
||||
${CURRENT_HEADER_DIR}/HslTransform.h
|
||||
${CURRENT_SOURCE_DIR}/HslTransform.cpp
|
||||
${CURRENT_HEADER_DIR}/RgbChannelTransform.h
|
||||
${CURRENT_SOURCE_DIR}/RgbChannelTransform.cpp
|
||||
${CURRENT_HEADER_DIR}/RgbChannelCorrection.h
|
||||
${CURRENT_SOURCE_DIR}/RgbChannelCorrection.cpp
|
||||
${CURRENT_HEADER_DIR}/RgbChannelAdjustment.h
|
||||
${CURRENT_SOURCE_DIR}/RgbChannelAdjustment.cpp
|
||||
|
||||
${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h
|
||||
${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h
|
||||
${CURRENT_SOURCE_DIR}/jsonschema/JsonSchemaChecker.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(hyperion-utils
|
||||
jsoncpp)
|
||||
|
@ -1,464 +1,464 @@
|
||||
// stdlib includes
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
// Utils-Jsonschema includes
|
||||
#include <utils/jsonschema/JsonSchemaChecker.h>
|
||||
|
||||
JsonSchemaChecker::JsonSchemaChecker()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
JsonSchemaChecker::~JsonSchemaChecker()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
bool JsonSchemaChecker::setSchema(const Json::Value & schema)
|
||||
{
|
||||
_schema = schema;
|
||||
|
||||
// TODO: check the schema
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonSchemaChecker::validate(const Json::Value & value)
|
||||
{
|
||||
// initialize state
|
||||
_error = false;
|
||||
_messages.clear();
|
||||
_currentPath.clear();
|
||||
_currentPath.push_back("[root]");
|
||||
_references.clear();
|
||||
|
||||
// collect dependencies
|
||||
collectDependencies(value, _schema);
|
||||
|
||||
// validate
|
||||
validate(value, _schema);
|
||||
|
||||
return !_error;
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::collectDependencies(const Json::Value & value, const Json::Value &schema)
|
||||
{
|
||||
assert (schema.isObject());
|
||||
|
||||
// check if id is present
|
||||
if (schema.isMember("id"))
|
||||
{
|
||||
// strore reference
|
||||
assert (schema["id"].isString());
|
||||
std::ostringstream ref;
|
||||
ref << "$(" << schema["id"].asString() << ")";
|
||||
_references[ref.str()] = &value;
|
||||
}
|
||||
|
||||
// check the current json value
|
||||
if (schema.isMember("properties"))
|
||||
{
|
||||
const Json::Value & properties = schema["properties"];
|
||||
assert(properties.isObject());
|
||||
|
||||
for (Json::Value::const_iterator j = properties.begin(); j != properties.end(); ++j)
|
||||
{
|
||||
std::string property = j.memberName();
|
||||
if (value.isMember(property))
|
||||
{
|
||||
collectDependencies(value[property], properties[property]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::validate(const Json::Value & value, const Json::Value &schema)
|
||||
{
|
||||
assert (schema.isObject());
|
||||
|
||||
// check the current json value
|
||||
for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i)
|
||||
{
|
||||
std::string attribute = i.memberName();
|
||||
const Json::Value & attributeValue = *i;
|
||||
|
||||
if (attribute == "type")
|
||||
checkType(value, attributeValue);
|
||||
else if (attribute == "properties")
|
||||
checkProperties(value, attributeValue);
|
||||
else if (attribute == "additionalProperties")
|
||||
{
|
||||
// ignore the properties which are handled by the properties attribute (if present)
|
||||
Json::Value::Members ignoredProperties;
|
||||
if (schema.isMember("properties")) {
|
||||
const Json::Value & props = schema["properties"];
|
||||
ignoredProperties = props.getMemberNames();
|
||||
}
|
||||
|
||||
checkAdditionalProperties(value, attributeValue, ignoredProperties);
|
||||
}
|
||||
else if (attribute == "dependencies")
|
||||
checkDependencies(value, attributeValue);
|
||||
else if (attribute == "minimum")
|
||||
checkMinimum(value, attributeValue);
|
||||
else if (attribute == "maximum")
|
||||
checkMaximum(value, attributeValue);
|
||||
else if (attribute == "items")
|
||||
checkItems(value, attributeValue);
|
||||
else if (attribute == "minItems")
|
||||
checkMinItems(value, attributeValue);
|
||||
else if (attribute == "maxItems")
|
||||
checkMaxItems(value, attributeValue);
|
||||
else if (attribute == "uniqueItems")
|
||||
checkUniqueItems(value, attributeValue);
|
||||
else if (attribute == "enum")
|
||||
checkEnum(value, attributeValue);
|
||||
else if (attribute == "required")
|
||||
; // nothing to do. value is present so always oke
|
||||
else if (attribute == "id")
|
||||
; // references have already been collected
|
||||
else
|
||||
{
|
||||
// no check function defined for this attribute
|
||||
setMessage(std::string("No check function defined for attribute ") + attribute);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::setMessage(const std::string & message)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
std::copy(_currentPath.begin(), _currentPath.end(), std::ostream_iterator<std::string>(oss, ""));
|
||||
oss << ": " << message;
|
||||
_messages.push_back(oss.str());
|
||||
}
|
||||
|
||||
const std::list<std::string> & JsonSchemaChecker::getMessages() const
|
||||
{
|
||||
return _messages;
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkType(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isString());
|
||||
|
||||
std::string type = schema.asString();
|
||||
bool wrongType = false;
|
||||
if (type == "string")
|
||||
wrongType = !value.isString();
|
||||
else if (type == "number")
|
||||
wrongType = !value.isNumeric();
|
||||
else if (type == "integer")
|
||||
wrongType = !value.isIntegral();
|
||||
else if (type == "double")
|
||||
wrongType = !value.isDouble();
|
||||
else if (type == "boolean")
|
||||
wrongType = !value.isBool();
|
||||
else if (type == "object")
|
||||
wrongType = !value.isObject();
|
||||
else if (type == "array")
|
||||
wrongType = !value.isArray();
|
||||
else if (type == "null")
|
||||
wrongType = !value.isNull();
|
||||
else if (type == "enum")
|
||||
wrongType = !value.isString();
|
||||
else if (type == "any")
|
||||
wrongType = false;
|
||||
// else
|
||||
// assert(false);
|
||||
|
||||
if (wrongType)
|
||||
{
|
||||
_error = true;
|
||||
setMessage(type + " expected");
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkProperties(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isObject());
|
||||
|
||||
if (!value.isObject())
|
||||
{
|
||||
_error = true;
|
||||
setMessage("properies attribute is only valid for objects");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i)
|
||||
{
|
||||
std::string property = i.memberName();
|
||||
const Json::Value & propertyValue = *i;
|
||||
|
||||
assert(propertyValue.isObject());
|
||||
|
||||
_currentPath.push_back(std::string(".") + property);
|
||||
if (value.isMember(property))
|
||||
{
|
||||
validate(value[property], propertyValue);
|
||||
}
|
||||
else if (propertyValue.get("required", false).asBool())
|
||||
{
|
||||
_error = true;
|
||||
setMessage("missing member");
|
||||
}
|
||||
_currentPath.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties)
|
||||
{
|
||||
if (!value.isObject())
|
||||
{
|
||||
_error = true;
|
||||
setMessage("additional properies attribute is only valid for objects");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Json::Value::const_iterator i = value.begin(); i != value.end(); ++i)
|
||||
{
|
||||
std::string property = i.memberName();
|
||||
if (std::find(ignoredProperties.begin(), ignoredProperties.end(), property) == ignoredProperties.end())
|
||||
{
|
||||
// property has no property definition. check against the definition for additional properties
|
||||
_currentPath.push_back(std::string(".") + property);
|
||||
if (schema.isBool())
|
||||
{
|
||||
if (schema.asBool() == false)
|
||||
{
|
||||
_error = true;
|
||||
setMessage("no schema definition");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
validate(value[property], schema);
|
||||
}
|
||||
_currentPath.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkDependencies(const Json::Value & value, const Json::Value & schemaLink)
|
||||
{
|
||||
if (!value.isObject())
|
||||
{
|
||||
_error = true;
|
||||
setMessage("dependencies attribute is only valid for objects");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(schemaLink.isString());
|
||||
std::map<std::string, const Json::Value *>::iterator iter = _references.find(schemaLink.asString());
|
||||
if (iter == _references.end())
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "reference " << schemaLink.asString() << " could not be resolved";
|
||||
setMessage(oss.str());
|
||||
return;
|
||||
}
|
||||
const Json::Value & schema = *(iter->second);
|
||||
|
||||
std::list<std::string> requiredProperties;
|
||||
if (schema.isString())
|
||||
{
|
||||
requiredProperties.push_back(schema.asString());
|
||||
}
|
||||
else if (schema.isArray())
|
||||
{
|
||||
for (Json::UInt i = 0; i < schema.size(); ++i)
|
||||
{
|
||||
assert(schema[i].isString());
|
||||
requiredProperties.push_back(schema[i].asString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "Exepected reference " << schemaLink.asString() << " to resolve to a string or array";
|
||||
setMessage(oss.str());
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::list<std::string>::const_iterator i = requiredProperties.begin(); i != requiredProperties.end(); ++i)
|
||||
{
|
||||
if (!value.isMember(*i))
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "missing member " << *i;
|
||||
setMessage(oss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkMinimum(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isNumeric());
|
||||
|
||||
if (!value.isNumeric())
|
||||
{
|
||||
// only for numeric
|
||||
_error = true;
|
||||
setMessage("minimum check only for numeric fields");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.asDouble() < schema.asDouble())
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "value is too small (minimum=" << schema.asDouble() << ")";
|
||||
setMessage(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkMaximum(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isNumeric());
|
||||
|
||||
if (!value.isNumeric())
|
||||
{
|
||||
// only for numeric
|
||||
_error = true;
|
||||
setMessage("maximum check only for numeric fields");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.asDouble() > schema.asDouble())
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "value is too large (maximum=" << schema.asDouble() << ")";
|
||||
setMessage(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkItems(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isObject());
|
||||
|
||||
if (!value.isArray())
|
||||
{
|
||||
// only for arrays
|
||||
_error = true;
|
||||
setMessage("items only valid for arrays");
|
||||
return;
|
||||
}
|
||||
|
||||
for(Json::ArrayIndex i = 0; i < value.size(); ++i)
|
||||
{
|
||||
// validate each item
|
||||
std::ostringstream oss;
|
||||
oss << "[" << i << "]";
|
||||
_currentPath.push_back(oss.str());
|
||||
validate(value[i], schema);
|
||||
_currentPath.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkMinItems(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isIntegral());
|
||||
|
||||
if (!value.isArray())
|
||||
{
|
||||
// only for arrays
|
||||
_error = true;
|
||||
setMessage("minItems only valid for arrays");
|
||||
return;
|
||||
}
|
||||
|
||||
int minimum = schema.asInt();
|
||||
|
||||
if (static_cast<int>(value.size()) < minimum)
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "array is too small (minimum=" << minimum << ")";
|
||||
setMessage(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkMaxItems(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isIntegral());
|
||||
|
||||
if (!value.isArray())
|
||||
{
|
||||
// only for arrays
|
||||
_error = true;
|
||||
setMessage("maxItems only valid for arrays");
|
||||
return;
|
||||
}
|
||||
|
||||
int maximum = schema.asInt();
|
||||
|
||||
if (static_cast<int>(value.size()) > maximum)
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "array is too large (maximum=" << maximum << ")";
|
||||
setMessage(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkUniqueItems(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isBool());
|
||||
|
||||
if (!value.isArray())
|
||||
{
|
||||
// only for arrays
|
||||
_error = true;
|
||||
setMessage("uniqueItems only valid for arrays");
|
||||
return;
|
||||
}
|
||||
|
||||
if (schema.asBool() == true)
|
||||
{
|
||||
// make sure no two items are identical
|
||||
|
||||
for(Json::UInt i = 0; i < value.size(); ++i)
|
||||
{
|
||||
for (Json::UInt j = i+1; j < value.size(); ++j)
|
||||
{
|
||||
if (value[i] == value[j])
|
||||
{
|
||||
// found a value twice
|
||||
_error = true;
|
||||
setMessage("array must have unique values");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkEnum(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isArray());
|
||||
|
||||
for(Json::ArrayIndex i = 0; i < schema.size(); ++i)
|
||||
{
|
||||
if (schema[i] == value)
|
||||
{
|
||||
// found enum value. done.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing found
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "Unknown enum value (allowed values are: ";
|
||||
std::string values = Json::FastWriter().write(schema);
|
||||
oss << values.substr(0, values.size()-1); // The writer append a new line which we don't want
|
||||
oss << ")";
|
||||
setMessage(oss.str());
|
||||
}
|
||||
// stdlib includes
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
// Utils-Jsonschema includes
|
||||
#include <utils/jsonschema/JsonSchemaChecker.h>
|
||||
|
||||
JsonSchemaChecker::JsonSchemaChecker()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
JsonSchemaChecker::~JsonSchemaChecker()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
bool JsonSchemaChecker::setSchema(const Json::Value & schema)
|
||||
{
|
||||
_schema = schema;
|
||||
|
||||
// TODO: check the schema
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonSchemaChecker::validate(const Json::Value & value)
|
||||
{
|
||||
// initialize state
|
||||
_error = false;
|
||||
_messages.clear();
|
||||
_currentPath.clear();
|
||||
_currentPath.push_back("[root]");
|
||||
_references.clear();
|
||||
|
||||
// collect dependencies
|
||||
collectDependencies(value, _schema);
|
||||
|
||||
// validate
|
||||
validate(value, _schema);
|
||||
|
||||
return !_error;
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::collectDependencies(const Json::Value & value, const Json::Value &schema)
|
||||
{
|
||||
assert (schema.isObject());
|
||||
|
||||
// check if id is present
|
||||
if (schema.isMember("id"))
|
||||
{
|
||||
// strore reference
|
||||
assert (schema["id"].isString());
|
||||
std::ostringstream ref;
|
||||
ref << "$(" << schema["id"].asString() << ")";
|
||||
_references[ref.str()] = &value;
|
||||
}
|
||||
|
||||
// check the current json value
|
||||
if (schema.isMember("properties"))
|
||||
{
|
||||
const Json::Value & properties = schema["properties"];
|
||||
assert(properties.isObject());
|
||||
|
||||
for (Json::Value::const_iterator j = properties.begin(); j != properties.end(); ++j)
|
||||
{
|
||||
std::string property = j.memberName();
|
||||
if (value.isMember(property))
|
||||
{
|
||||
collectDependencies(value[property], properties[property]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::validate(const Json::Value & value, const Json::Value &schema)
|
||||
{
|
||||
assert (schema.isObject());
|
||||
|
||||
// check the current json value
|
||||
for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i)
|
||||
{
|
||||
std::string attribute = i.memberName();
|
||||
const Json::Value & attributeValue = *i;
|
||||
|
||||
if (attribute == "type")
|
||||
checkType(value, attributeValue);
|
||||
else if (attribute == "properties")
|
||||
checkProperties(value, attributeValue);
|
||||
else if (attribute == "additionalProperties")
|
||||
{
|
||||
// ignore the properties which are handled by the properties attribute (if present)
|
||||
Json::Value::Members ignoredProperties;
|
||||
if (schema.isMember("properties")) {
|
||||
const Json::Value & props = schema["properties"];
|
||||
ignoredProperties = props.getMemberNames();
|
||||
}
|
||||
|
||||
checkAdditionalProperties(value, attributeValue, ignoredProperties);
|
||||
}
|
||||
else if (attribute == "dependencies")
|
||||
checkDependencies(value, attributeValue);
|
||||
else if (attribute == "minimum")
|
||||
checkMinimum(value, attributeValue);
|
||||
else if (attribute == "maximum")
|
||||
checkMaximum(value, attributeValue);
|
||||
else if (attribute == "items")
|
||||
checkItems(value, attributeValue);
|
||||
else if (attribute == "minItems")
|
||||
checkMinItems(value, attributeValue);
|
||||
else if (attribute == "maxItems")
|
||||
checkMaxItems(value, attributeValue);
|
||||
else if (attribute == "uniqueItems")
|
||||
checkUniqueItems(value, attributeValue);
|
||||
else if (attribute == "enum")
|
||||
checkEnum(value, attributeValue);
|
||||
else if (attribute == "required")
|
||||
; // nothing to do. value is present so always oke
|
||||
else if (attribute == "id")
|
||||
; // references have already been collected
|
||||
else
|
||||
{
|
||||
// no check function defined for this attribute
|
||||
setMessage(std::string("No check function defined for attribute ") + attribute);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::setMessage(const std::string & message)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
std::copy(_currentPath.begin(), _currentPath.end(), std::ostream_iterator<std::string>(oss, ""));
|
||||
oss << ": " << message;
|
||||
_messages.push_back(oss.str());
|
||||
}
|
||||
|
||||
const std::list<std::string> & JsonSchemaChecker::getMessages() const
|
||||
{
|
||||
return _messages;
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkType(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isString());
|
||||
|
||||
std::string type = schema.asString();
|
||||
bool wrongType = false;
|
||||
if (type == "string")
|
||||
wrongType = !value.isString();
|
||||
else if (type == "number")
|
||||
wrongType = !value.isNumeric();
|
||||
else if (type == "integer")
|
||||
wrongType = !value.isIntegral();
|
||||
else if (type == "double")
|
||||
wrongType = !value.isDouble();
|
||||
else if (type == "boolean")
|
||||
wrongType = !value.isBool();
|
||||
else if (type == "object")
|
||||
wrongType = !value.isObject();
|
||||
else if (type == "array")
|
||||
wrongType = !value.isArray();
|
||||
else if (type == "null")
|
||||
wrongType = !value.isNull();
|
||||
else if (type == "enum")
|
||||
wrongType = !value.isString();
|
||||
else if (type == "any")
|
||||
wrongType = false;
|
||||
// else
|
||||
// assert(false);
|
||||
|
||||
if (wrongType)
|
||||
{
|
||||
_error = true;
|
||||
setMessage(type + " expected");
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkProperties(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isObject());
|
||||
|
||||
if (!value.isObject())
|
||||
{
|
||||
_error = true;
|
||||
setMessage("properies attribute is only valid for objects");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i)
|
||||
{
|
||||
std::string property = i.memberName();
|
||||
const Json::Value & propertyValue = *i;
|
||||
|
||||
assert(propertyValue.isObject());
|
||||
|
||||
_currentPath.push_back(std::string(".") + property);
|
||||
if (value.isMember(property))
|
||||
{
|
||||
validate(value[property], propertyValue);
|
||||
}
|
||||
else if (propertyValue.get("required", false).asBool())
|
||||
{
|
||||
_error = true;
|
||||
setMessage("missing member");
|
||||
}
|
||||
_currentPath.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties)
|
||||
{
|
||||
if (!value.isObject())
|
||||
{
|
||||
_error = true;
|
||||
setMessage("additional properies attribute is only valid for objects");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Json::Value::const_iterator i = value.begin(); i != value.end(); ++i)
|
||||
{
|
||||
std::string property = i.memberName();
|
||||
if (std::find(ignoredProperties.begin(), ignoredProperties.end(), property) == ignoredProperties.end())
|
||||
{
|
||||
// property has no property definition. check against the definition for additional properties
|
||||
_currentPath.push_back(std::string(".") + property);
|
||||
if (schema.isBool())
|
||||
{
|
||||
if (schema.asBool() == false)
|
||||
{
|
||||
_error = true;
|
||||
setMessage("no schema definition");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
validate(value[property], schema);
|
||||
}
|
||||
_currentPath.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkDependencies(const Json::Value & value, const Json::Value & schemaLink)
|
||||
{
|
||||
if (!value.isObject())
|
||||
{
|
||||
_error = true;
|
||||
setMessage("dependencies attribute is only valid for objects");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(schemaLink.isString());
|
||||
std::map<std::string, const Json::Value *>::iterator iter = _references.find(schemaLink.asString());
|
||||
if (iter == _references.end())
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "reference " << schemaLink.asString() << " could not be resolved";
|
||||
setMessage(oss.str());
|
||||
return;
|
||||
}
|
||||
const Json::Value & schema = *(iter->second);
|
||||
|
||||
std::list<std::string> requiredProperties;
|
||||
if (schema.isString())
|
||||
{
|
||||
requiredProperties.push_back(schema.asString());
|
||||
}
|
||||
else if (schema.isArray())
|
||||
{
|
||||
for (Json::UInt i = 0; i < schema.size(); ++i)
|
||||
{
|
||||
assert(schema[i].isString());
|
||||
requiredProperties.push_back(schema[i].asString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "Exepected reference " << schemaLink.asString() << " to resolve to a string or array";
|
||||
setMessage(oss.str());
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::list<std::string>::const_iterator i = requiredProperties.begin(); i != requiredProperties.end(); ++i)
|
||||
{
|
||||
if (!value.isMember(*i))
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "missing member " << *i;
|
||||
setMessage(oss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkMinimum(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isNumeric());
|
||||
|
||||
if (!value.isNumeric())
|
||||
{
|
||||
// only for numeric
|
||||
_error = true;
|
||||
setMessage("minimum check only for numeric fields");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.asDouble() < schema.asDouble())
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "value is too small (minimum=" << schema.asDouble() << ")";
|
||||
setMessage(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkMaximum(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isNumeric());
|
||||
|
||||
if (!value.isNumeric())
|
||||
{
|
||||
// only for numeric
|
||||
_error = true;
|
||||
setMessage("maximum check only for numeric fields");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.asDouble() > schema.asDouble())
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "value is too large (maximum=" << schema.asDouble() << ")";
|
||||
setMessage(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkItems(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isObject());
|
||||
|
||||
if (!value.isArray())
|
||||
{
|
||||
// only for arrays
|
||||
_error = true;
|
||||
setMessage("items only valid for arrays");
|
||||
return;
|
||||
}
|
||||
|
||||
for(Json::ArrayIndex i = 0; i < value.size(); ++i)
|
||||
{
|
||||
// validate each item
|
||||
std::ostringstream oss;
|
||||
oss << "[" << i << "]";
|
||||
_currentPath.push_back(oss.str());
|
||||
validate(value[i], schema);
|
||||
_currentPath.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkMinItems(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isIntegral());
|
||||
|
||||
if (!value.isArray())
|
||||
{
|
||||
// only for arrays
|
||||
_error = true;
|
||||
setMessage("minItems only valid for arrays");
|
||||
return;
|
||||
}
|
||||
|
||||
int minimum = schema.asInt();
|
||||
|
||||
if (static_cast<int>(value.size()) < minimum)
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "array is too small (minimum=" << minimum << ")";
|
||||
setMessage(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkMaxItems(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isIntegral());
|
||||
|
||||
if (!value.isArray())
|
||||
{
|
||||
// only for arrays
|
||||
_error = true;
|
||||
setMessage("maxItems only valid for arrays");
|
||||
return;
|
||||
}
|
||||
|
||||
int maximum = schema.asInt();
|
||||
|
||||
if (static_cast<int>(value.size()) > maximum)
|
||||
{
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "array is too large (maximum=" << maximum << ")";
|
||||
setMessage(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkUniqueItems(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isBool());
|
||||
|
||||
if (!value.isArray())
|
||||
{
|
||||
// only for arrays
|
||||
_error = true;
|
||||
setMessage("uniqueItems only valid for arrays");
|
||||
return;
|
||||
}
|
||||
|
||||
if (schema.asBool() == true)
|
||||
{
|
||||
// make sure no two items are identical
|
||||
|
||||
for(Json::UInt i = 0; i < value.size(); ++i)
|
||||
{
|
||||
for (Json::UInt j = i+1; j < value.size(); ++j)
|
||||
{
|
||||
if (value[i] == value[j])
|
||||
{
|
||||
// found a value twice
|
||||
_error = true;
|
||||
setMessage("array must have unique values");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JsonSchemaChecker::checkEnum(const Json::Value & value, const Json::Value & schema)
|
||||
{
|
||||
assert(schema.isArray());
|
||||
|
||||
for(Json::ArrayIndex i = 0; i < schema.size(); ++i)
|
||||
{
|
||||
if (schema[i] == value)
|
||||
{
|
||||
// found enum value. done.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing found
|
||||
_error = true;
|
||||
std::ostringstream oss;
|
||||
oss << "Unknown enum value (allowed values are: ";
|
||||
std::string values = Json::FastWriter().write(schema);
|
||||
oss << values.substr(0, values.size()-1); // The writer append a new line which we don't want
|
||||
oss << ")";
|
||||
setMessage(oss.str());
|
||||
}
|
||||
|
@ -5,33 +5,33 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/xbmcvideochecker)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(XBMCVideoChecker_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/XBMCVideoChecker.h
|
||||
${CURRENT_HEADER_DIR}/XBMCVideoChecker.h
|
||||
)
|
||||
|
||||
SET(XBMCVideoChecker_HEADERS
|
||||
)
|
||||
|
||||
SET(XBMCVideoChecker_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/XBMCVideoChecker.cpp
|
||||
${CURRENT_SOURCE_DIR}/XBMCVideoChecker.cpp
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(XBMCVideoChecker_HEADERS_MOC ${XBMCVideoChecker_QT_HEADERS})
|
||||
else(ENABLE_QT5)
|
||||
QT4_WRAP_CPP(XBMCVideoChecker_HEADERS_MOC ${XBMCVideoChecker_QT_HEADERS})
|
||||
endif(ENABLE_QT5)
|
||||
QT5_WRAP_CPP(XBMCVideoChecker_HEADERS_MOC ${XBMCVideoChecker_QT_HEADERS})
|
||||
else()
|
||||
QT4_WRAP_CPP(XBMCVideoChecker_HEADERS_MOC ${XBMCVideoChecker_QT_HEADERS})
|
||||
endif()
|
||||
|
||||
add_library(xbmcvideochecker
|
||||
${XBMCVideoChecker_HEADERS}
|
||||
${XBMCVideoChecker_QT_HEADERS}
|
||||
${XBMCVideoChecker_HEADERS_MOC}
|
||||
${XBMCVideoChecker_SOURCES}
|
||||
${XBMCVideoChecker_HEADERS}
|
||||
${XBMCVideoChecker_QT_HEADERS}
|
||||
${XBMCVideoChecker_HEADERS_MOC}
|
||||
${XBMCVideoChecker_SOURCES}
|
||||
)
|
||||
|
||||
if(ENABLE_QT5)
|
||||
qt5_use_modules(xbmcvideochecker Widgets)
|
||||
endif(ENABLE_QT5)
|
||||
qt5_use_modules(xbmcvideochecker Widgets)
|
||||
endif()
|
||||
|
||||
target_link_libraries(xbmcvideochecker
|
||||
hyperion
|
||||
${QT_LIBRARIES})
|
||||
hyperion
|
||||
${QT_LIBRARIES})
|
||||
|
@ -2,30 +2,27 @@ add_subdirectory(hyperiond)
|
||||
add_subdirectory(hyperion-remote)
|
||||
|
||||
# The following clients depend on the protobuf library
|
||||
if(ENABLE_PROTOBUF)
|
||||
|
||||
if (ENABLE_AMLOGIC)
|
||||
add_subdirectory(hyperion-aml)
|
||||
endif()
|
||||
|
||||
if(ENABLE_V4L2)
|
||||
add_subdirectory(hyperion-v4l2)
|
||||
endif()
|
||||
|
||||
if(ENABLE_X11)
|
||||
add_subdirectory(hyperion-x11)
|
||||
endif()
|
||||
|
||||
if(ENABLE_DISPMANX)
|
||||
add_subdirectory(hyperion-dispmanx)
|
||||
endif()
|
||||
|
||||
if(ENABLE_FB)
|
||||
add_subdirectory(hyperion-framebuffer)
|
||||
endif()
|
||||
|
||||
if(ENABLE_OSX)
|
||||
add_subdirectory(hyperion-osx)
|
||||
endif()
|
||||
|
||||
if (ENABLE_AMLOGIC)
|
||||
add_subdirectory(hyperion-aml)
|
||||
endif()
|
||||
|
||||
if(ENABLE_V4L2)
|
||||
add_subdirectory(hyperion-v4l2)
|
||||
endif()
|
||||
|
||||
if(ENABLE_X11)
|
||||
add_subdirectory(hyperion-x11)
|
||||
endif()
|
||||
|
||||
if(ENABLE_DISPMANX)
|
||||
add_subdirectory(hyperion-dispmanx)
|
||||
endif()
|
||||
|
||||
if(ENABLE_FB)
|
||||
add_subdirectory(hyperion-framebuffer)
|
||||
endif()
|
||||
|
||||
if(ENABLE_OSX)
|
||||
add_subdirectory(hyperion-osx)
|
||||
endif()
|
||||
|
||||
|
@ -3,14 +3,14 @@
|
||||
#include "AmlogicWrapper.h"
|
||||
|
||||
AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) :
|
||||
_timer(this),
|
||||
_grabber(grabWidth, grabHeight)
|
||||
_timer(this),
|
||||
_grabber(grabWidth, grabHeight)
|
||||
{
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(updateRate_Hz);
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(updateRate_Hz);
|
||||
|
||||
// Connect capturing to the timeout signal of the timer
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
|
||||
// Connect capturing to the timeout signal of the timer
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
|
||||
}
|
||||
|
||||
const Image<ColorRgb> & AmlogicWrapper::getScreenshot()
|
||||
@ -21,12 +21,12 @@ const Image<ColorRgb> & AmlogicWrapper::getScreenshot()
|
||||
|
||||
void AmlogicWrapper::start()
|
||||
{
|
||||
_timer.start();
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
void AmlogicWrapper::stop()
|
||||
{
|
||||
_timer.stop();
|
||||
_timer.stop();
|
||||
}
|
||||
|
||||
void AmlogicWrapper::capture()
|
||||
|
@ -7,16 +7,16 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe
|
||||
const unsigned cropLeft, const unsigned cropRight,
|
||||
const unsigned cropTop, const unsigned cropBottom,
|
||||
const unsigned updateRate_Hz) :
|
||||
_timer(this),
|
||||
_grabber(grabWidth, grabHeight)
|
||||
_timer(this),
|
||||
_grabber(grabWidth, grabHeight)
|
||||
{
|
||||
_grabber.setVideoMode(videoMode);
|
||||
_grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom);
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(updateRate_Hz);
|
||||
_grabber.setVideoMode(videoMode);
|
||||
_grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom);
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(updateRate_Hz);
|
||||
|
||||
// Connect capturing to the timeout signal of the timer
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
|
||||
// Connect capturing to the timeout signal of the timer
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
|
||||
}
|
||||
|
||||
const Image<ColorRgb> & DispmanxWrapper::getScreenshot()
|
||||
@ -27,12 +27,12 @@ const Image<ColorRgb> & DispmanxWrapper::getScreenshot()
|
||||
|
||||
void DispmanxWrapper::start()
|
||||
{
|
||||
_timer.start();
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
void DispmanxWrapper::stop()
|
||||
{
|
||||
_timer.stop();
|
||||
_timer.stop();
|
||||
}
|
||||
|
||||
void DispmanxWrapper::capture()
|
||||
|
@ -3,14 +3,14 @@
|
||||
#include "FramebufferWrapper.h"
|
||||
|
||||
FramebufferWrapper::FramebufferWrapper(const std::string & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) :
|
||||
_timer(this),
|
||||
_grabber(device,grabWidth, grabHeight)
|
||||
_timer(this),
|
||||
_grabber(device,grabWidth, grabHeight)
|
||||
{
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(updateRate_Hz);
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(updateRate_Hz);
|
||||
|
||||
// Connect capturing to the timeout signal of the timer
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
|
||||
// Connect capturing to the timeout signal of the timer
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
|
||||
}
|
||||
|
||||
const Image<ColorRgb> & FramebufferWrapper::getScreenshot()
|
||||
@ -21,12 +21,12 @@ const Image<ColorRgb> & FramebufferWrapper::getScreenshot()
|
||||
|
||||
void FramebufferWrapper::start()
|
||||
{
|
||||
_timer.start();
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
void FramebufferWrapper::stop()
|
||||
{
|
||||
_timer.stop();
|
||||
_timer.stop();
|
||||
}
|
||||
|
||||
void FramebufferWrapper::capture()
|
||||
|
@ -3,14 +3,14 @@
|
||||
#include "OsxWrapper.h"
|
||||
|
||||
OsxWrapper::OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) :
|
||||
_timer(this),
|
||||
_grabber(display,grabWidth, grabHeight)
|
||||
_timer(this),
|
||||
_grabber(display,grabWidth, grabHeight)
|
||||
{
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(updateRate_Hz);
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(updateRate_Hz);
|
||||
|
||||
// Connect capturing to the timeout signal of the timer
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
|
||||
// Connect capturing to the timeout signal of the timer
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
|
||||
}
|
||||
|
||||
const Image<ColorRgb> & OsxWrapper::getScreenshot()
|
||||
|
@ -10,34 +10,34 @@ using namespace vlofgren;
|
||||
typedef vlofgren::PODParameter<PixelFormat> PixelFormatParameter;
|
||||
|
||||
namespace vlofgren {
|
||||
/// Translates a string (as passed on the commandline) to a pixel format
|
||||
///
|
||||
/// @param[in] s The string (as passed on the commandline)
|
||||
/// @return The pixel format
|
||||
/// @throws Parameter::ParameterRejected If the string did not result in a pixel format
|
||||
template<>
|
||||
PixelFormat PixelFormatParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
|
||||
{
|
||||
QString input = QString::fromStdString(s).toLower();
|
||||
/// Translates a string (as passed on the commandline) to a pixel format
|
||||
///
|
||||
/// @param[in] s The string (as passed on the commandline)
|
||||
/// @return The pixel format
|
||||
/// @throws Parameter::ParameterRejected If the string did not result in a pixel format
|
||||
template<>
|
||||
PixelFormat PixelFormatParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
|
||||
{
|
||||
QString input = QString::fromStdString(s).toLower();
|
||||
|
||||
if (input == "yuyv")
|
||||
{
|
||||
return PIXELFORMAT_YUYV;
|
||||
}
|
||||
else if (input == "uyvy")
|
||||
{
|
||||
return PIXELFORMAT_UYVY;
|
||||
}
|
||||
else if (input == "rgb32")
|
||||
{
|
||||
return PIXELFORMAT_RGB32;
|
||||
}
|
||||
else if (input == "no-change")
|
||||
{
|
||||
return PIXELFORMAT_NO_CHANGE;
|
||||
}
|
||||
if (input == "yuyv")
|
||||
{
|
||||
return PIXELFORMAT_YUYV;
|
||||
}
|
||||
else if (input == "uyvy")
|
||||
{
|
||||
return PIXELFORMAT_UYVY;
|
||||
}
|
||||
else if (input == "rgb32")
|
||||
{
|
||||
return PIXELFORMAT_RGB32;
|
||||
}
|
||||
else if (input == "no-change")
|
||||
{
|
||||
return PIXELFORMAT_NO_CHANGE;
|
||||
}
|
||||
|
||||
throw Parameter::ParameterRejected("Invalid value for pixel format. Valid values are: YUYV, UYVY, RGB32, and NO-CHANGE");
|
||||
return PIXELFORMAT_NO_CHANGE;
|
||||
}
|
||||
throw Parameter::ParameterRejected("Invalid value for pixel format. Valid values are: YUYV, UYVY, RGB32, and NO-CHANGE");
|
||||
return PIXELFORMAT_NO_CHANGE;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "ScreenshotHandler.h"
|
||||
|
||||
ScreenshotHandler::ScreenshotHandler(const std::string & filename) :
|
||||
_filename(filename)
|
||||
_filename(filename)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -31,150 +31,150 @@ using namespace vlofgren;
|
||||
// save the image as screenshot
|
||||
void saveScreenshot(void *, 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("screenshot.png");
|
||||
// store as PNG
|
||||
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
|
||||
pngImage.save("screenshot.png");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::cout
|
||||
<< "hyperion-v4l2:" << std::endl
|
||||
<< "\tversion : " << HYPERION_VERSION_ID << std::endl
|
||||
<< "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl;
|
||||
<< "hyperion-v4l2:" << std::endl
|
||||
<< "\tversion : " << HYPERION_VERSION_ID << std::endl
|
||||
<< "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl;
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
// force the locale
|
||||
setlocale(LC_ALL, "C");
|
||||
QLocale::setDefault(QLocale::c());
|
||||
// force the locale
|
||||
setlocale(LC_ALL, "C");
|
||||
QLocale::setDefault(QLocale::c());
|
||||
|
||||
// register the image type to use in signals
|
||||
qRegisterMetaType<Image<ColorRgb>>("Image<ColorRgb>");
|
||||
// register the image type to use in signals
|
||||
qRegisterMetaType<Image<ColorRgb>>("Image<ColorRgb>");
|
||||
|
||||
try
|
||||
{
|
||||
// create the option parser and initialize all parameters
|
||||
OptionsParser optionParser("V4L capture application for Hyperion");
|
||||
ParameterSet & parameters = optionParser.getParameters();
|
||||
try
|
||||
{
|
||||
// create the option parser and initialize all parameters
|
||||
OptionsParser optionParser("V4L capture application for Hyperion");
|
||||
ParameterSet & parameters = optionParser.getParameters();
|
||||
|
||||
StringParameter & argDevice = parameters.add<StringParameter> ('d', "device", "The device to use [default: /dev/video0]");
|
||||
VideoStandardParameter & argVideoStandard = parameters.add<VideoStandardParameter>('v', "video-standard", "The used video standard. Valid values are PAL or NTSC (optional)");
|
||||
PixelFormatParameter & argPixelFormat = parameters.add<PixelFormatParameter> (0x0, "pixel-format", "The use pixel format. Valid values are YUYV, UYVY, and RGB32 (optional)");
|
||||
IntParameter & argInput = parameters.add<IntParameter> (0x0, "input", "Input channel (optional)");
|
||||
IntParameter & argWidth = parameters.add<IntParameter> (0x0, "width", "Try to set the width of the video input (optional)");
|
||||
IntParameter & argHeight = parameters.add<IntParameter> (0x0, "height", "Try to set the height of the video input (optional)");
|
||||
IntParameter & argCropWidth = parameters.add<IntParameter> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]");
|
||||
IntParameter & argCropHeight = parameters.add<IntParameter> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]");
|
||||
IntParameter & argCropLeft = parameters.add<IntParameter> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
|
||||
IntParameter & argCropRight = parameters.add<IntParameter> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
|
||||
IntParameter & argCropTop = parameters.add<IntParameter> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");
|
||||
IntParameter & argCropBottom = parameters.add<IntParameter> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)");
|
||||
IntParameter & argSizeDecimation = parameters.add<IntParameter> ('s', "size-decimator", "Decimation factor for the output size [default=1]");
|
||||
IntParameter & argFrameDecimation = parameters.add<IntParameter> ('f', "frame-decimator", "Decimation factor for the video frames [default=1]");
|
||||
SwitchParameter<> & argScreenshot = parameters.add<SwitchParameter<>> (0x0, "screenshot", "Take a single screenshot, save it to file and quit");
|
||||
DoubleParameter & argSignalThreshold = parameters.add<DoubleParameter> ('t', "signal-threshold", "The signal threshold for detecting the presence of a signal. Value should be between 0.0 and 1.0.");
|
||||
DoubleParameter & argRedSignalThreshold = parameters.add<DoubleParameter> (0x0, "red-threshold", "The red signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
|
||||
DoubleParameter & argGreenSignalThreshold = parameters.add<DoubleParameter> (0x0, "green-threshold", "The green signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
|
||||
DoubleParameter & argBlueSignalThreshold = parameters.add<DoubleParameter> (0x0, "blue-threshold", "The blue signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
|
||||
SwitchParameter<> & arg3DSBS = parameters.add<SwitchParameter<>> (0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
|
||||
SwitchParameter<> & arg3DTAB = parameters.add<SwitchParameter<>> (0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
|
||||
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");
|
||||
StringParameter & argDevice = parameters.add<StringParameter> ('d', "device", "The device to use [default: /dev/video0]");
|
||||
VideoStandardParameter & argVideoStandard = parameters.add<VideoStandardParameter>('v', "video-standard", "The used video standard. Valid values are PAL or NTSC (optional)");
|
||||
PixelFormatParameter & argPixelFormat = parameters.add<PixelFormatParameter> (0x0, "pixel-format", "The use pixel format. Valid values are YUYV, UYVY, and RGB32 (optional)");
|
||||
IntParameter & argInput = parameters.add<IntParameter> (0x0, "input", "Input channel (optional)");
|
||||
IntParameter & argWidth = parameters.add<IntParameter> (0x0, "width", "Try to set the width of the video input (optional)");
|
||||
IntParameter & argHeight = parameters.add<IntParameter> (0x0, "height", "Try to set the height of the video input (optional)");
|
||||
IntParameter & argCropWidth = parameters.add<IntParameter> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]");
|
||||
IntParameter & argCropHeight = parameters.add<IntParameter> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]");
|
||||
IntParameter & argCropLeft = parameters.add<IntParameter> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
|
||||
IntParameter & argCropRight = parameters.add<IntParameter> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
|
||||
IntParameter & argCropTop = parameters.add<IntParameter> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");
|
||||
IntParameter & argCropBottom = parameters.add<IntParameter> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)");
|
||||
IntParameter & argSizeDecimation = parameters.add<IntParameter> ('s', "size-decimator", "Decimation factor for the output size [default=1]");
|
||||
IntParameter & argFrameDecimation = parameters.add<IntParameter> ('f', "frame-decimator", "Decimation factor for the video frames [default=1]");
|
||||
SwitchParameter<> & argScreenshot = parameters.add<SwitchParameter<>> (0x0, "screenshot", "Take a single screenshot, save it to file and quit");
|
||||
DoubleParameter & argSignalThreshold = parameters.add<DoubleParameter> ('t', "signal-threshold", "The signal threshold for detecting the presence of a signal. Value should be between 0.0 and 1.0.");
|
||||
DoubleParameter & argRedSignalThreshold = parameters.add<DoubleParameter> (0x0, "red-threshold", "The red signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
|
||||
DoubleParameter & argGreenSignalThreshold = parameters.add<DoubleParameter> (0x0, "green-threshold", "The green signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
|
||||
DoubleParameter & argBlueSignalThreshold = parameters.add<DoubleParameter> (0x0, "blue-threshold", "The blue signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
|
||||
SwitchParameter<> & arg3DSBS = parameters.add<SwitchParameter<>> (0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
|
||||
SwitchParameter<> & arg3DTAB = parameters.add<SwitchParameter<>> (0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
|
||||
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
|
||||
argDevice.setDefault("/dev/video0");
|
||||
argVideoStandard.setDefault(VIDEOSTANDARD_NO_CHANGE);
|
||||
argPixelFormat.setDefault(PIXELFORMAT_NO_CHANGE);
|
||||
argInput.setDefault(-1);
|
||||
argWidth.setDefault(-1);
|
||||
argHeight.setDefault(-1);
|
||||
argCropWidth.setDefault(0);
|
||||
argCropHeight.setDefault(0);
|
||||
argSizeDecimation.setDefault(1);
|
||||
argFrameDecimation.setDefault(1);
|
||||
argAddress.setDefault("127.0.0.1:19445");
|
||||
argPriority.setDefault(800);
|
||||
argSignalThreshold.setDefault(-1);
|
||||
// set defaults
|
||||
argDevice.setDefault("/dev/video0");
|
||||
argVideoStandard.setDefault(VIDEOSTANDARD_NO_CHANGE);
|
||||
argPixelFormat.setDefault(PIXELFORMAT_NO_CHANGE);
|
||||
argInput.setDefault(-1);
|
||||
argWidth.setDefault(-1);
|
||||
argHeight.setDefault(-1);
|
||||
argCropWidth.setDefault(0);
|
||||
argCropHeight.setDefault(0);
|
||||
argSizeDecimation.setDefault(1);
|
||||
argFrameDecimation.setDefault(1);
|
||||
argAddress.setDefault("127.0.0.1:19445");
|
||||
argPriority.setDefault(800);
|
||||
argSignalThreshold.setDefault(-1);
|
||||
|
||||
// parse all options
|
||||
optionParser.parse(argc, const_cast<const char **>(argv));
|
||||
// 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;
|
||||
}
|
||||
// check if we need to display the usage. exit if we do.
|
||||
if (argHelp.isSet())
|
||||
{
|
||||
optionParser.usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// cropping values if not defined
|
||||
if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue());
|
||||
if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue());
|
||||
if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue());
|
||||
if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue());
|
||||
// cropping values if not defined
|
||||
if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue());
|
||||
if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue());
|
||||
if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue());
|
||||
if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue());
|
||||
|
||||
// initialize the grabber
|
||||
V4L2Grabber grabber(
|
||||
argDevice.getValue(),
|
||||
argInput.getValue(),
|
||||
argVideoStandard.getValue(),
|
||||
argPixelFormat.getValue(),
|
||||
argWidth.getValue(),
|
||||
argHeight.getValue(),
|
||||
std::max(1, argFrameDecimation.getValue()),
|
||||
std::max(1, argSizeDecimation.getValue()),
|
||||
std::max(1, argSizeDecimation.getValue()));
|
||||
// initialize the grabber
|
||||
V4L2Grabber grabber(
|
||||
argDevice.getValue(),
|
||||
argInput.getValue(),
|
||||
argVideoStandard.getValue(),
|
||||
argPixelFormat.getValue(),
|
||||
argWidth.getValue(),
|
||||
argHeight.getValue(),
|
||||
std::max(1, argFrameDecimation.getValue()),
|
||||
std::max(1, argSizeDecimation.getValue()),
|
||||
std::max(1, argSizeDecimation.getValue()));
|
||||
|
||||
// set signal detection
|
||||
grabber.setSignalThreshold(
|
||||
std::min(1.0, std::max(0.0, argRedSignalThreshold.isSet() ? argRedSignalThreshold.getValue() : argSignalThreshold.getValue())),
|
||||
std::min(1.0, std::max(0.0, argGreenSignalThreshold.isSet() ? argGreenSignalThreshold.getValue() : argSignalThreshold.getValue())),
|
||||
std::min(1.0, std::max(0.0, argBlueSignalThreshold.isSet() ? argBlueSignalThreshold.getValue() : argSignalThreshold.getValue())),
|
||||
50);
|
||||
// set signal detection
|
||||
grabber.setSignalThreshold(
|
||||
std::min(1.0, std::max(0.0, argRedSignalThreshold.isSet() ? argRedSignalThreshold.getValue() : argSignalThreshold.getValue())),
|
||||
std::min(1.0, std::max(0.0, argGreenSignalThreshold.isSet() ? argGreenSignalThreshold.getValue() : argSignalThreshold.getValue())),
|
||||
std::min(1.0, std::max(0.0, argBlueSignalThreshold.isSet() ? argBlueSignalThreshold.getValue() : argSignalThreshold.getValue())),
|
||||
50);
|
||||
|
||||
// set cropping values
|
||||
grabber.setCropping(
|
||||
std::max(0, argCropLeft.getValue()),
|
||||
std::max(0, argCropRight.getValue()),
|
||||
std::max(0, argCropTop.getValue()),
|
||||
std::max(0, argCropBottom.getValue()));
|
||||
// set cropping values
|
||||
grabber.setCropping(
|
||||
std::max(0, argCropLeft.getValue()),
|
||||
std::max(0, argCropRight.getValue()),
|
||||
std::max(0, argCropTop.getValue()),
|
||||
std::max(0, argCropBottom.getValue()));
|
||||
|
||||
// set 3D mode if applicable
|
||||
if (arg3DSBS.isSet())
|
||||
{
|
||||
grabber.set3D(VIDEO_3DSBS);
|
||||
}
|
||||
else if (arg3DTAB.isSet())
|
||||
{
|
||||
grabber.set3D(VIDEO_3DTAB);
|
||||
}
|
||||
// set 3D mode if applicable
|
||||
if (arg3DSBS.isSet())
|
||||
{
|
||||
grabber.set3D(VIDEO_3DSBS);
|
||||
}
|
||||
else if (arg3DTAB.isSet())
|
||||
{
|
||||
grabber.set3D(VIDEO_3DTAB);
|
||||
}
|
||||
|
||||
// run the grabber
|
||||
if (argScreenshot.isSet())
|
||||
{
|
||||
ScreenshotHandler handler("screenshot.png");
|
||||
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
|
||||
grabber.start();
|
||||
QCoreApplication::exec();
|
||||
grabber.stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
ProtoConnectionWrapper handler(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet());
|
||||
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
|
||||
grabber.start();
|
||||
QCoreApplication::exec();
|
||||
grabber.stop();
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error & e)
|
||||
{
|
||||
// An error occured. Display error and quit
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
// run the grabber
|
||||
if (argScreenshot.isSet())
|
||||
{
|
||||
ScreenshotHandler handler("screenshot.png");
|
||||
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
|
||||
grabber.start();
|
||||
QCoreApplication::exec();
|
||||
grabber.stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
ProtoConnectionWrapper handler(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet());
|
||||
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
|
||||
grabber.start();
|
||||
QCoreApplication::exec();
|
||||
grabber.stop();
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error & e)
|
||||
{
|
||||
// An error occured. Display error and quit
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -3,39 +3,39 @@
|
||||
#include "X11Wrapper.h"
|
||||
|
||||
X11Wrapper::X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) :
|
||||
_timer(this),
|
||||
_grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation)
|
||||
_timer(this),
|
||||
_grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation)
|
||||
{
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(grabInterval);
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(grabInterval);
|
||||
|
||||
// Connect capturing to the timeout signal of the timer
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
|
||||
// Connect capturing to the timeout signal of the timer
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
|
||||
}
|
||||
|
||||
const Image<ColorRgb> & X11Wrapper::getScreenshot()
|
||||
{
|
||||
const Image<ColorRgb> & screenshot = _grabber.grab();
|
||||
return screenshot;
|
||||
const Image<ColorRgb> & screenshot = _grabber.grab();
|
||||
return screenshot;
|
||||
}
|
||||
|
||||
void X11Wrapper::start()
|
||||
{
|
||||
_timer.start();
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
void X11Wrapper::stop()
|
||||
{
|
||||
_timer.stop();
|
||||
_timer.stop();
|
||||
}
|
||||
|
||||
bool X11Wrapper::displayInit()
|
||||
{
|
||||
return _grabber.Setup();
|
||||
return _grabber.Setup();
|
||||
}
|
||||
|
||||
void X11Wrapper::capture()
|
||||
{
|
||||
const Image<ColorRgb> & screenshot = _grabber.grab();
|
||||
emit sig_screenshot(screenshot);
|
||||
const Image<ColorRgb> & screenshot = _grabber.grab();
|
||||
emit sig_screenshot(screenshot);
|
||||
}
|
||||
|
@ -7,35 +7,35 @@
|
||||
|
||||
class X11Wrapper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation);
|
||||
X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation);
|
||||
|
||||
const Image<ColorRgb> & getScreenshot();
|
||||
const Image<ColorRgb> & getScreenshot();
|
||||
|
||||
///
|
||||
/// Starts the timed capturing of screenshots
|
||||
///
|
||||
void start();
|
||||
///
|
||||
/// Starts the timed capturing of screenshots
|
||||
///
|
||||
void start();
|
||||
|
||||
void stop();
|
||||
|
||||
bool displayInit();
|
||||
void stop();
|
||||
|
||||
bool displayInit();
|
||||
|
||||
signals:
|
||||
void sig_screenshot(const Image<ColorRgb> & screenshot);
|
||||
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();
|
||||
///
|
||||
/// Performs a single screenshot capture and publishes the capture screenshot on the screenshot
|
||||
/// signal.
|
||||
///
|
||||
void capture();
|
||||
|
||||
private:
|
||||
/// The QT timer to generate capture-publish events
|
||||
QTimer _timer;
|
||||
/// The QT timer to generate capture-publish events
|
||||
QTimer _timer;
|
||||
|
||||
/// The grabber for creating screenshots
|
||||
X11Grabber _grabber;
|
||||
/// The grabber for creating screenshots
|
||||
X11Grabber _grabber;
|
||||
};
|
||||
|
@ -15,108 +15,108 @@ 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);
|
||||
// store as PNG
|
||||
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
|
||||
pngImage.save(filename);
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
std::cout
|
||||
<< "hyperion-x11:" << std::endl
|
||||
<< "\tversion : " << HYPERION_VERSION_ID << std::endl
|
||||
<< "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl;
|
||||
<< "hyperion-x11:" << std::endl
|
||||
<< "\tversion : " << HYPERION_VERSION_ID << std::endl
|
||||
<< "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl;
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
try
|
||||
{
|
||||
// create the option parser and initialize all parameters
|
||||
OptionsParser optionParser("X11 capture application for Hyperion");
|
||||
ParameterSet & parameters = optionParser.getParameters();
|
||||
try
|
||||
{
|
||||
// create the option parser and initialize all parameters
|
||||
OptionsParser optionParser("X11 capture application for Hyperion");
|
||||
ParameterSet & parameters = optionParser.getParameters();
|
||||
|
||||
IntParameter & argFps = parameters.add<IntParameter> ('f', "framerate", "Capture frame rate [default: 10]");
|
||||
SwitchParameter<> & argXGetImage = parameters.add<SwitchParameter<>> ('x', "xgetimage", "Use XGetImage instead of XRender");
|
||||
IntParameter & argCropWidth = parameters.add<IntParameter> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]");
|
||||
IntParameter & argCropHeight = parameters.add<IntParameter> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]");
|
||||
IntParameter & argCropLeft = parameters.add<IntParameter> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
|
||||
IntParameter & argCropRight = parameters.add<IntParameter> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
|
||||
IntParameter & argCropTop = parameters.add<IntParameter> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");
|
||||
IntParameter & argCropBottom = parameters.add<IntParameter> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)");
|
||||
IntParameter & argSizeDecimation = parameters.add<IntParameter> ('s', "size-decimator", "Decimation factor for the output size [default=8]");
|
||||
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");
|
||||
IntParameter & argFps = parameters.add<IntParameter> ('f', "framerate", "Capture frame rate [default: 10]");
|
||||
SwitchParameter<> & argXGetImage = parameters.add<SwitchParameter<>> ('x', "xgetimage", "Use XGetImage instead of XRender");
|
||||
IntParameter & argCropWidth = parameters.add<IntParameter> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]");
|
||||
IntParameter & argCropHeight = parameters.add<IntParameter> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]");
|
||||
IntParameter & argCropLeft = parameters.add<IntParameter> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
|
||||
IntParameter & argCropRight = parameters.add<IntParameter> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
|
||||
IntParameter & argCropTop = parameters.add<IntParameter> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");
|
||||
IntParameter & argCropBottom = parameters.add<IntParameter> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)");
|
||||
IntParameter & argSizeDecimation = parameters.add<IntParameter> ('s', "size-decimator", "Decimation factor for the output size [default=8]");
|
||||
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);
|
||||
argCropWidth.setDefault(0);
|
||||
argCropHeight.setDefault(0);
|
||||
argSizeDecimation.setDefault(8);
|
||||
argAddress.setDefault("127.0.0.1:19445");
|
||||
argPriority.setDefault(800);
|
||||
// set defaults
|
||||
argFps.setDefault(10);
|
||||
argCropWidth.setDefault(0);
|
||||
argCropHeight.setDefault(0);
|
||||
argSizeDecimation.setDefault(8);
|
||||
argAddress.setDefault("127.0.0.1:19445");
|
||||
argPriority.setDefault(800);
|
||||
|
||||
// parse all options
|
||||
optionParser.parse(argc, const_cast<const char **>(argv));
|
||||
// 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;
|
||||
}
|
||||
// check if we need to display the usage. exit if we do.
|
||||
if (argHelp.isSet())
|
||||
{
|
||||
optionParser.usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// cropping values if not defined
|
||||
if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue());
|
||||
if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue());
|
||||
if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue());
|
||||
if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue());
|
||||
// cropping values if not defined
|
||||
if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue());
|
||||
if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue());
|
||||
if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue());
|
||||
if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue());
|
||||
|
||||
// Create the X11 grabbing stuff
|
||||
int grabInterval = 1000 / argFps.getValue();
|
||||
bool useXGetImage = argXGetImage.isSet();
|
||||
X11Wrapper x11Wrapper(
|
||||
grabInterval,
|
||||
useXGetImage,
|
||||
argCropLeft.getValue(),
|
||||
argCropRight.getValue(),
|
||||
argCropTop.getValue(),
|
||||
argCropBottom.getValue(),
|
||||
argSizeDecimation.getValue(), // horizontal decimation
|
||||
argSizeDecimation.getValue()); // vertical decimation
|
||||
// Create the X11 grabbing stuff
|
||||
int grabInterval = 1000 / argFps.getValue();
|
||||
bool useXGetImage = argXGetImage.isSet();
|
||||
X11Wrapper x11Wrapper(
|
||||
grabInterval,
|
||||
useXGetImage,
|
||||
argCropLeft.getValue(),
|
||||
argCropRight.getValue(),
|
||||
argCropTop.getValue(),
|
||||
argCropBottom.getValue(),
|
||||
argSizeDecimation.getValue(), // horizontal decimation
|
||||
argSizeDecimation.getValue()); // vertical decimation
|
||||
|
||||
if (!x11Wrapper.displayInit())
|
||||
return -1;
|
||||
|
||||
if (argScreenshot.isSet())
|
||||
{
|
||||
// Capture a single screenshot and finish
|
||||
const Image<ColorRgb> & screenshot = x11Wrapper.getScreenshot();
|
||||
saveScreenshot("screenshot.png", screenshot);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create the Proto-connection with hyperiond
|
||||
ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet());
|
||||
if (argScreenshot.isSet())
|
||||
{
|
||||
// Capture a single screenshot and finish
|
||||
const Image<ColorRgb> & screenshot = x11Wrapper.getScreenshot();
|
||||
saveScreenshot("screenshot.png", screenshot);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create the Proto-connection with hyperiond
|
||||
ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet());
|
||||
|
||||
// Connect the screen capturing to the proto processing
|
||||
QObject::connect(&x11Wrapper, SIGNAL(sig_screenshot(const Image<ColorRgb> &)), &protoWrapper, SLOT(receiveImage(Image<ColorRgb>)));
|
||||
// Connect the screen capturing to the proto processing
|
||||
QObject::connect(&x11Wrapper, SIGNAL(sig_screenshot(const Image<ColorRgb> &)), &protoWrapper, SLOT(receiveImage(Image<ColorRgb>)));
|
||||
|
||||
// Start the capturing
|
||||
x11Wrapper.start();
|
||||
// Start the capturing
|
||||
x11Wrapper.start();
|
||||
|
||||
// Start the application
|
||||
app.exec();
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error & e)
|
||||
{
|
||||
// An error occured. Display error and quit
|
||||
std::cerr << e.what() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
// Start the application
|
||||
app.exec();
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error & e)
|
||||
{
|
||||
// An error occured. Display error and quit
|
||||
std::cerr << e.what() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -51,10 +51,8 @@
|
||||
// JsonServer includes
|
||||
#include <jsonserver/JsonServer.h>
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
// ProtoServer includes
|
||||
#include <protoserver/ProtoServer.h>
|
||||
#endif
|
||||
|
||||
// BoblightServer includes
|
||||
#include <boblightserver/BoblightServer.h>
|
||||
@ -208,7 +206,6 @@ int main(int argc, char** argv)
|
||||
std::cout << "INFO: Json server created and started on port " << jsonServer->getPort() << std::endl;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
// Create Proto server if configuration is present
|
||||
ProtoServer * protoServer = nullptr;
|
||||
if (config.isMember("protoServer"))
|
||||
@ -217,7 +214,6 @@ int main(int argc, char** argv)
|
||||
protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() );
|
||||
std::cout << "INFO: Proto server created and started on port " << protoServer->getPort() << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create Boblight server if configuration is present
|
||||
BoblightServer * boblightServer = nullptr;
|
||||
@ -254,9 +250,7 @@ int main(int argc, char** argv)
|
||||
QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), dispmanx, SLOT(setVideoMode(VideoMode)));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
QObject::connect(dispmanx, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
#endif
|
||||
|
||||
dispmanx->start();
|
||||
std::cout << "INFO: Frame grabber created and started" << std::endl;
|
||||
@ -297,9 +291,7 @@ int main(int argc, char** argv)
|
||||
grabberConfig.get("cropTop", 0).asInt(),
|
||||
grabberConfig.get("cropBottom", 0).asInt());
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
QObject::connect(v4l2Grabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
#endif
|
||||
|
||||
v4l2Grabber->start();
|
||||
std::cout << "INFO: V4L2 grabber created and started" << std::endl;
|
||||
@ -331,9 +323,7 @@ int main(int argc, char** argv)
|
||||
QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), amlGrabber, SLOT(setVideoMode(VideoMode)));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
QObject::connect(amlGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
#endif
|
||||
|
||||
amlGrabber->start();
|
||||
std::cout << "INFO: AMLOGIC grabber created and started" << std::endl;
|
||||
@ -365,9 +355,7 @@ int main(int argc, char** argv)
|
||||
QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), fbGrabber, SLOT(setVideoMode(VideoMode)));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
QObject::connect(fbGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
#endif
|
||||
|
||||
fbGrabber->start();
|
||||
std::cout << "INFO: Framebuffer grabber created and started" << std::endl;
|
||||
@ -405,9 +393,7 @@ int main(int argc, char** argv)
|
||||
QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), osxGrabber, SLOT(setVideoMode(VideoMode)));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
QObject::connect(osxGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
#endif
|
||||
|
||||
osxGrabber->start();
|
||||
std::cout << "INFO: OSX grabber created and started" << std::endl;
|
||||
@ -445,9 +431,7 @@ int main(int argc, char** argv)
|
||||
#endif
|
||||
delete xbmcVideoChecker;
|
||||
delete jsonServer;
|
||||
#ifdef ENABLE_PROTOBUF
|
||||
delete protoServer;
|
||||
#endif
|
||||
delete boblightServer;
|
||||
|
||||
// leave application
|
||||
|
Loading…
Reference in New Issue
Block a user