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:
redPanther 2016-05-26 23:44:27 +02:00 committed by brindosch
parent 667ee80ef6
commit 945f3d1c5b
73 changed files with 4941 additions and 4966 deletions

View File

@ -51,8 +51,7 @@ message(STATUS "ENABLE_FB = " ${ENABLE_FB})
option(ENABLE_OSX "Enable the osx grabber" ${DEFAULT_OSX} ) option(ENABLE_OSX "Enable the osx grabber" ${DEFAULT_OSX} )
message(STATUS "ENABLE_OSX = " ${ENABLE_OSX}) message(STATUS "ENABLE_OSX = " ${ENABLE_OSX})
option(ENABLE_PROTOBUF "Enable PROTOBUF server" ON) set(ENABLE_PROTOBUF ON)
message(STATUS "ENABLE_PROTOBUF = " ${ENABLE_PROTOBUF})
option(ENABLE_SPIDEV "Enable the SPIDEV device" ${DEFAULT_SPIDEV} ) option(ENABLE_SPIDEV "Enable the SPIDEV device" ${DEFAULT_SPIDEV} )
message(STATUS "ENABLE_SPIDEV = " ${ENABLE_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) option(ENABLE_TESTS "Compile additional test applications" OFF)
message(STATUS "ENABLE_TESTS = " ${ENABLE_TESTS}) 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) if(ENABLE_FB AND ENABLE_DISPMANX)
message(FATAL_ERROR "dispmanx grabber and framebuffer grabber cannot be used at the same time") message(FATAL_ERROR "dispmanx grabber and framebuffer grabber cannot be used at the same time")

View File

@ -1,8 +1,8 @@
#!/bin/sh #!/bin/sh
if [ "$#" -ne 2 ] || ! [ -d "$1" ] || ! [ -d "$2" ]; then if [ "$#" -ne 2 ] || ! [ -d "$1" ] || ! [ -d "$2" ]; then
echo "Usage: $0 <BUILD-DIR> <REPO-DIR>" >&2 echo "Usage: $0 <BUILD-DIR> <REPO-DIR>" >&2
exit 1 exit 1
fi fi
builddir="$1" builddir="$1"

View File

@ -6,15 +6,15 @@ PATH="/sbin:$PATH"
#Check if HyperCon is logged in as root #Check if HyperCon is logged in as root
if [ $(id -u) != 0 ] && [ "$1" = "HyperConRemove" ]; then if [ $(id -u) != 0 ] && [ "$1" = "HyperConRemove" ]; then
echo '---> Critical Error: Please connect as user "root" through HyperCon' echo '---> Critical Error: Please connect as user "root" through HyperCon'
echo '---> We need admin privileges to remove your Hyperion! -> abort' echo '---> We need admin privileges to remove your Hyperion! -> abort'
exit 1 exit 1
fi fi
#Check, if script is running as root #Check, if script is running as root
if [ $(id -u) != 0 ]; then if [ $(id -u) != 0 ]; then
echo '---> Critical Error: Please run the script as root (sudo sh ./remove_hyperion.sh)' echo '---> Critical Error: Please run the script as root (sudo sh ./remove_hyperion.sh)'
exit 1 exit 1
fi fi
#Welcome message #Welcome message
@ -26,21 +26,22 @@ echo '**************************************************************************
#Skip the prompt if HyperCon Remove #Skip the prompt if HyperCon Remove
if [ "$1" = "" ]; then if [ "$1" = "" ]; then
#Prompt for confirmation to proceed #Prompt for confirmation to proceed
while true while true
do do
echo -n "---> Do you really want to remove Hyperion and it´s services? (y or n) :" echo -n "---> Do you really want to remove Hyperion and it´s services? (y or n) :"
read CONFIRM read CONFIRM
case $CONFIRM in case $CONFIRM in
y|Y|YES|yes|Yes) break ;; y|Y|YES|yes|Yes) break ;;
n|N|no|NO|No) n|N|no|NO|No)
echo "---> Aborting - you entered \"$CONFIRM\"" echo "---> Aborting - you entered \"$CONFIRM\""
exit exit
;; ;;
*) echo "-> Please enter only y or n" *) echo "-> Please enter only y or n"
esac esac
done done
echo "---> You entered \"$CONFIRM\". Remove Hyperion!"
echo "---> You entered \"$CONFIRM\". Remove Hyperion!"
fi fi
# Find out if we are on OpenElec or RasPlex # Find out if we are on OpenElec or RasPlex
OS_OPENELEC=`grep -m1 -c 'OpenELEC\|RasPlex\|LibreELEC' /etc/issue` OS_OPENELEC=`grep -m1 -c 'OpenELEC\|RasPlex\|LibreELEC' /etc/issue`
@ -124,4 +125,3 @@ echo '**************************************************************************
echo 'Hyperion successful removed!' echo 'Hyperion successful removed!'
echo '*******************************************************************************' echo '*******************************************************************************'
exit 0 exit 0

View File

@ -8,16 +8,16 @@
# #
FIND_PATH(BCM_INCLUDE_DIR FIND_PATH(BCM_INCLUDE_DIR
bcm_host.h bcm_host.h
/usr/include /usr/include
/usr/local/include /usr/local/include
/opt/vc/include) /opt/vc/include)
SET(BCM_INCLUDE_DIRS SET(BCM_INCLUDE_DIRS
${BCM_INCLUDE_DIR} ${BCM_INCLUDE_DIR}
${BCM_INCLUDE_DIR}/interface/vcos/pthreads ${BCM_INCLUDE_DIR}/interface/vcos/pthreads
${BCM_INCLUDE_DIR}/interface/vmcs_host/linux) ${BCM_INCLUDE_DIR}/interface/vmcs_host/linux)
FIND_LIBRARY(BCM_LIBRARIES FIND_LIBRARY(BCM_LIBRARIES
NAMES bcm_host NAMES bcm_host
PATHS /usr/lib /usr/local/lib /opt/vc/lib) PATHS /usr/lib /usr/local/lib /opt/vc/lib)

View File

@ -17,5 +17,5 @@ if(APPLE)
set(CoreFoundation_FOUND true) set(CoreFoundation_FOUND true)
set(CoreFoundation_INCLUDE_DIR ${CoreFoundation}) set(CoreFoundation_INCLUDE_DIR ${CoreFoundation})
set(CoreFoundation_LIBRARY ${CoreFoundation}) set(CoreFoundation_LIBRARY ${CoreFoundation})
endif(CoreFoundation) endif()
endif(APPLE) endif()

View File

@ -13,9 +13,9 @@ set(IOKit_LIBRARY)
if(APPLE) if(APPLE)
# The only platform it makes sense to check for IOKit # The only platform it makes sense to check for IOKit
find_library(IOKit IOKit) find_library(IOKit IOKit)
if(IOKit) if(IOKit)
set(IOKit_FOUND true) set(IOKit_FOUND true)
set(IOKit_INCLUDE_DIR ${IOKit}) set(IOKit_INCLUDE_DIR ${IOKit})
set(IOKit_LIBRARY ${IOKit}) set(IOKit_LIBRARY ${IOKit})
endif(IOKit) endif(IOKit)
endif(APPLE) endif(APPLE)

View File

@ -10,44 +10,44 @@
# #
FIND_PATH( FIND_PATH(
UDEV_INCLUDE_DIR UDEV_INCLUDE_DIR
libudev.h libudev.h
/usr/include /usr/include
/usr/local/include /usr/local/include
${UDEV_PATH_INCLUDES} ${UDEV_PATH_INCLUDES}
) )
FIND_LIBRARY( FIND_LIBRARY(
UDEV_LIBRARIES UDEV_LIBRARIES
NAMES udev libudev NAMES udev libudev
PATHS PATHS
/usr/lib${LIB_SUFFIX} /usr/lib${LIB_SUFFIX}
/usr/local/lib${LIB_SUFFIX} /usr/local/lib${LIB_SUFFIX}
${UDEV_PATH_LIB} ${UDEV_PATH_LIB}
) )
IF (UDEV_LIBRARIES AND UDEV_INCLUDE_DIR) IF (UDEV_LIBRARIES AND UDEV_INCLUDE_DIR)
SET(UDEV_FOUND "YES") SET(UDEV_FOUND "YES")
execute_process(COMMAND pkg-config --atleast-version=143 libudev RESULT_VARIABLE UDEV_STABLE) 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... # retvale is 0 of the condition is "true" so we need to negate the value...
if (UDEV_STABLE) if (UDEV_STABLE)
set(UDEV_STABLE 0) set(UDEV_STABLE 0)
else (UDEV_STABLE) else ()
set(UDEV_STABLE 1) set(UDEV_STABLE 1)
endif (UDEV_STABLE) endif ()
message(STATUS "libudev stable: ${UDEV_STABLE}") message(STATUS "libudev stable: ${UDEV_STABLE}")
ENDIF (UDEV_LIBRARIES AND UDEV_INCLUDE_DIR) ENDIF ()
IF (UDEV_FOUND) IF (UDEV_FOUND)
MESSAGE(STATUS "Found UDev: ${UDEV_LIBRARIES}") MESSAGE(STATUS "Found UDev: ${UDEV_LIBRARIES}")
MESSAGE(STATUS " include: ${UDEV_INCLUDE_DIR}") MESSAGE(STATUS " include: ${UDEV_INCLUDE_DIR}")
ELSE (UDEV_FOUND) ELSE ()
MESSAGE(STATUS "UDev not found.") MESSAGE(STATUS "UDev not found.")
MESSAGE(STATUS "UDev: You can specify includes: -DUDEV_PATH_INCLUDES=/opt/udev/include") MESSAGE(STATUS "UDev: You can specify includes: -DUDEV_PATH_INCLUDES=/opt/udev/include")
MESSAGE(STATUS " currently found includes: ${UDEV_INCLUDE_DIR}") MESSAGE(STATUS " currently found includes: ${UDEV_INCLUDE_DIR}")
MESSAGE(STATUS "UDev: You can specify libs: -DUDEV_PATH_LIB=/opt/udev/lib") MESSAGE(STATUS "UDev: You can specify libs: -DUDEV_PATH_LIB=/opt/udev/lib")
MESSAGE(STATUS " currently found libs: ${UDEV_LIBRARIES}") MESSAGE(STATUS " currently found libs: ${UDEV_LIBRARIES}")
IF (UDev_FIND_REQUIRED) IF (UDev_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find UDev library") MESSAGE(FATAL_ERROR "Could not find UDev library")
ENDIF (UDev_FIND_REQUIRED) ENDIF ()
ENDIF (UDEV_FOUND) ENDIF ()

View File

@ -44,56 +44,52 @@
if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
# in cache already # in cache already
set(LIBUSB_FOUND TRUE) set(LIBUSB_FOUND TRUE)
else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) 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 NAMES
libusb.h usb-1.0 usb
PATHS PATHS
/usr/include /usr/lib
/usr/local/include /usr/local/lib
/opt/local/include /opt/local/lib
/sw/include /sw/lib
PATH_SUFFIXES )
libusb-1.0
)
find_library(LIBUSB_1_LIBRARY set(LIBUSB_1_INCLUDE_DIRS ${LIBUSB_1_INCLUDE_DIR} )
NAMES set(LIBUSB_1_LIBRARIES ${LIBUSB_1_LIBRARY} )
usb-1.0 usb
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
set(LIBUSB_1_INCLUDE_DIRS if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
${LIBUSB_1_INCLUDE_DIR} set(LIBUSB_1_FOUND TRUE)
) endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
set(LIBUSB_1_LIBRARIES
${LIBUSB_1_LIBRARY}
)
if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES) if (LIBUSB_1_FOUND)
set(LIBUSB_1_FOUND TRUE) if (NOT libusb_1_FIND_QUIETLY)
endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES) 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) # show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view
if (NOT libusb_1_FIND_QUIETLY) mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES)
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)
endif (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) endif (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)

View File

@ -1,22 +1,22 @@
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 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") endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}") string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files}) foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}") message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program( exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval RETURN_VALUE rm_retval
) )
if(NOT "${rm_retval}" STREQUAL 0) if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif(NOT "${rm_retval}" STREQUAL 0) endif(NOT "${rm_retval}" STREQUAL 0)
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.") message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
endforeach(file) endforeach(file)

View File

@ -1,10 +1,10 @@
{ {
"name" : "Knight rider", "name" : "Knight rider",
"script" : "knight-rider.py", "script" : "knight-rider.py",
"args" : "args" :
{ {
"speed" : 1.0, "speed" : 1.0,
"fadeFactor" : 0.7, "fadeFactor" : 0.7,
"color" : [255,0,0] "color" : [255,0,0]
} }
} }

View File

@ -1,12 +1,12 @@
{ {
"name" : "Blue mood blobs", "name" : "Blue mood blobs",
"script" : "mood-blobs.py", "script" : "mood-blobs.py",
"args" : "args" :
{ {
"rotationTime" : 60.0, "rotationTime" : 60.0,
"color" : [0,0,255], "color" : [0,0,255],
"hueChange" : 60.0, "hueChange" : 60.0,
"blobs" : 5, "blobs" : 5,
"reverse" : false "reverse" : false
} }
} }

View File

@ -1,12 +1,12 @@
{ {
"name" : "Green mood blobs", "name" : "Green mood blobs",
"script" : "mood-blobs.py", "script" : "mood-blobs.py",
"args" : "args" :
{ {
"rotationTime" : 60.0, "rotationTime" : 60.0,
"color" : [0,255,0], "color" : [0,255,0],
"hueChange" : 60.0, "hueChange" : 60.0,
"blobs" : 5, "blobs" : 5,
"reverse" : false "reverse" : false
} }
} }

View File

@ -1,12 +1,12 @@
{ {
"name" : "Red mood blobs", "name" : "Red mood blobs",
"script" : "mood-blobs.py", "script" : "mood-blobs.py",
"args" : "args" :
{ {
"rotationTime" : 60.0, "rotationTime" : 60.0,
"color" : [255,0,0], "color" : [255,0,0],
"hueChange" : 60.0, "hueChange" : 60.0,
"blobs" : 5, "blobs" : 5,
"reverse" : false "reverse" : false
} }
} }

View File

@ -1,10 +1,10 @@
{ {
"name" : "Rainbow mood", "name" : "Rainbow mood",
"script" : "rainbow-mood.py", "script" : "rainbow-mood.py",
"args" : "args" :
{ {
"rotation-time" : 60.0, "rotation-time" : 60.0,
"brightness" : 1.0, "brightness" : 1.0,
"reverse" : false "reverse" : false
} }
} }

View File

@ -1,10 +1,10 @@
{ {
"name" : "Rainbow swirl fast", "name" : "Rainbow swirl fast",
"script" : "rainbow-swirl.py", "script" : "rainbow-swirl.py",
"args" : "args" :
{ {
"rotation-time" : 3.0, "rotation-time" : 3.0,
"brightness" : 1.0, "brightness" : 1.0,
"reverse" : false "reverse" : false
} }
} }

View File

@ -1,10 +1,10 @@
{ {
"name" : "Rainbow swirl", "name" : "Rainbow swirl",
"script" : "rainbow-swirl.py", "script" : "rainbow-swirl.py",
"args" : "args" :
{ {
"rotation-time" : 20.0, "rotation-time" : 20.0,
"brightness" : 1.0, "brightness" : 1.0,
"reverse" : false "reverse" : false
} }
} }

View File

@ -1,10 +1,10 @@
{ {
"name" : "Snake", "name" : "Snake",
"script" : "snake.py", "script" : "snake.py",
"args" : "args" :
{ {
"rotation-time" : 12.0, "rotation-time" : 12.0,
"color" : [255, 0, 0], "color" : [255, 0, 0],
"percentage" : 10 "percentage" : 10
} }
} }

View File

@ -23,103 +23,103 @@
/// @see http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html /// @see http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html
class V4L2Grabber : public QObject class V4L2Grabber : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
V4L2Grabber(const std::string & device, V4L2Grabber(const std::string & device,
int input, int input,
VideoStandard videoStandard, PixelFormat pixelFormat, VideoStandard videoStandard, PixelFormat pixelFormat,
int width, int width,
int height, int height,
int frameDecimation, int frameDecimation,
int horizontalPixelDecimation, int horizontalPixelDecimation,
int verticalPixelDecimation); int verticalPixelDecimation);
virtual ~V4L2Grabber(); virtual ~V4L2Grabber();
public slots: public slots:
void setCropping(int cropLeft, void setCropping(int cropLeft,
int cropRight, int cropRight,
int cropTop, int cropTop,
int cropBottom); int cropBottom);
void set3D(VideoMode mode); void set3D(VideoMode mode);
void setSignalThreshold(double redSignalThreshold, void setSignalThreshold(double redSignalThreshold,
double greenSignalThreshold, double greenSignalThreshold,
double blueSignalThreshold, double blueSignalThreshold,
int noSignalCounterThreshold); int noSignalCounterThreshold);
void start(); void start();
void stop(); void stop();
signals: signals:
void newFrame(const Image<ColorRgb> & image); void newFrame(const Image<ColorRgb> & image);
private slots: private slots:
int read_frame(); int read_frame();
private: 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: private:
enum io_method { enum io_method {
IO_METHOD_READ, IO_METHOD_READ,
IO_METHOD_MMAP, IO_METHOD_MMAP,
IO_METHOD_USERPTR IO_METHOD_USERPTR
}; };
struct buffer { struct buffer {
void *start; void *start;
size_t length; size_t length;
}; };
private: private:
const std::string _deviceName; const std::string _deviceName;
const io_method _ioMethod; const io_method _ioMethod;
int _fileDescriptor; int _fileDescriptor;
std::vector<buffer> _buffers; std::vector<buffer> _buffers;
PixelFormat _pixelFormat; PixelFormat _pixelFormat;
int _width; int _width;
int _height; int _height;
int _lineLength; int _lineLength;
int _frameByteSize; int _frameByteSize;
int _frameDecimation; int _frameDecimation;
int _noSignalCounterThreshold; int _noSignalCounterThreshold;
ColorRgb _noSignalThresholdColor; ColorRgb _noSignalThresholdColor;
int _currentFrame; int _currentFrame;
int _noSignalCounter; int _noSignalCounter;
QSocketNotifier * _streamNotifier; QSocketNotifier * _streamNotifier;
ImageResampler _imageResampler; ImageResampler _imageResampler;
}; };

View File

@ -15,7 +15,7 @@ class X11Grabber
{ {
public: 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(); virtual ~X11Grabber();
@ -26,16 +26,16 @@ public:
Image<ColorRgb> & grab(); Image<ColorRgb> & grab();
private: private:
ImageResampler _imageResampler; ImageResampler _imageResampler;
bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable; bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable;
int _cropLeft; int _cropLeft;
int _cropRight; int _cropRight;
int _cropTop; int _cropTop;
int _cropBottom; int _cropBottom;
XImage* _xImage; XImage* _xImage;
XShmSegmentInfo _shminfo; XShmSegmentInfo _shminfo;
/// Reference to the X11 display (nullptr if not opened) /// Reference to the X11 display (nullptr if not opened)
Display* _x11Display; Display* _x11Display;

View File

@ -23,90 +23,90 @@
class ProtoConnection : public QObject class ProtoConnection : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
/// ///
/// Constructor /// Constructor
/// ///
/// @param address The address of the Hyperion server (for example "192.168.0.32:19444) /// @param address The address of the Hyperion server (for example "192.168.0.32:19444)
/// ///
ProtoConnection(const std::string & address); ProtoConnection(const std::string & address);
/// ///
/// Destructor /// Destructor
/// ///
~ProtoConnection(); ~ProtoConnection();
/// Do not read reply messages from Hyperion if set to true /// Do not read reply messages from Hyperion if set to true
void setSkipReply(bool skip); void setSkipReply(bool skip);
/// ///
/// Set all leds to the specified color /// Set all leds to the specified color
/// ///
/// @param color The color /// @param color The color
/// @param priority The priority /// @param priority The priority
/// @param duration The duration in milliseconds /// @param duration The duration in milliseconds
/// ///
void setColor(const ColorRgb & color, int priority, int duration = 1); 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) /// Set the leds according to the given image (assume the image is stretched to the display size)
/// ///
/// @param image The image /// @param image The image
/// @param priority The priority /// @param priority The priority
/// @param duration The duration in milliseconds /// @param duration The duration in milliseconds
/// ///
void setImage(const Image<ColorRgb> & image, int priority, int duration = -1); void setImage(const Image<ColorRgb> & image, int priority, int duration = -1);
/// ///
/// Clear the given priority channel /// Clear the given priority channel
/// ///
/// @param priority The priority /// @param priority The priority
/// ///
void clear(int priority); void clear(int priority);
/// ///
/// Clear all priority channels /// Clear all priority channels
/// ///
void clearAll(); void clearAll();
/// ///
/// Send a command message and receive its reply /// Send a command message and receive its reply
/// ///
/// @param message The message to send /// @param message The message to send
/// ///
void sendMessage(const proto::HyperionRequest & message); void sendMessage(const proto::HyperionRequest & message);
private slots: private slots:
/// Try to connect to the Hyperion host /// Try to connect to the Hyperion host
void connectToHost(); void connectToHost();
private: private:
/// ///
/// Parse a reply message /// Parse a reply message
/// ///
/// @param reply The received reply /// @param reply The received reply
/// ///
/// @return true if the reply indicates success /// @return true if the reply indicates success
/// ///
bool parseReply(const proto::HyperionReply & reply); bool parseReply(const proto::HyperionReply & reply);
private: private:
/// The TCP-Socket with the connection to the server /// The TCP-Socket with the connection to the server
QTcpSocket _socket; QTcpSocket _socket;
/// Host address /// Host address
QString _host; QString _host;
/// Host port /// Host port
uint16_t _port; uint16_t _port;
/// Skip receiving reply messages from Hyperion if set /// Skip receiving reply messages from Hyperion if set
bool _skipReply; bool _skipReply;
QTimer _timer; QTimer _timer;
QAbstractSocket::SocketState _prevSocketState; QAbstractSocket::SocketState _prevSocketState;
}; };

View File

@ -11,24 +11,24 @@
/// This class handles callbacks from the V4L2 grabber /// This class handles callbacks from the V4L2 grabber
class ProtoConnectionWrapper : public QObject class ProtoConnectionWrapper : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
ProtoConnectionWrapper(const std::string & address, int priority, int duration_ms, bool skipProtoReply); ProtoConnectionWrapper(const std::string & address, int priority, int duration_ms, bool skipProtoReply);
virtual ~ProtoConnectionWrapper(); virtual ~ProtoConnectionWrapper();
public slots: public slots:
/// Handle a single image /// Handle a single image
/// @param image The image to process /// @param image The image to process
void receiveImage(const Image<ColorRgb> & image); void receiveImage(const Image<ColorRgb> & image);
private: private:
/// Priority for calls to Hyperion /// Priority for calls to Hyperion
const int _priority; const int _priority;
/// Duration for color calls to Hyperion /// Duration for color calls to Hyperion
const int _duration_ms; const int _duration_ms;
/// Hyperion proto connection object /// Hyperion proto connection object
ProtoConnection _connection; ProtoConnection _connection;
}; };

View File

@ -13,221 +13,221 @@ class Image
{ {
public: public:
typedef Pixel_T pixel_type; typedef Pixel_T pixel_type;
/// ///
/// Default constructor for an image /// Default constructor for an image
/// ///
Image() : Image() :
_width(1), _width(1),
_height(1), _height(1),
_pixels(new Pixel_T[2]), _pixels(new Pixel_T[2]),
_endOfPixels(_pixels + 1) _endOfPixels(_pixels + 1)
{ {
memset(_pixels, 0, 2*sizeof(Pixel_T)); memset(_pixels, 0, 2*sizeof(Pixel_T));
} }
/// ///
/// Constructor for an image with specified width and height /// Constructor for an image with specified width and height
/// ///
/// @param width The width of the image /// @param width The width of the image
/// @param height The height of the image /// @param height The height of the image
/// ///
Image(const unsigned width, const unsigned height) : Image(const unsigned width, const unsigned height) :
_width(width), _width(width),
_height(height), _height(height),
_pixels(new Pixel_T[width * height + 1]), _pixels(new Pixel_T[width * height + 1]),
_endOfPixels(_pixels + width * height) _endOfPixels(_pixels + width * height)
{ {
memset(_pixels, 0, (_width*_height+1)*sizeof(Pixel_T)); memset(_pixels, 0, (_width*_height+1)*sizeof(Pixel_T));
} }
/// ///
/// Constructor for an image with specified width and height /// Constructor for an image with specified width and height
/// ///
/// @param width The width of the image /// @param width The width of the image
/// @param height The height of the image /// @param height The height of the image
/// @param background The color of the image /// @param background The color of the image
/// ///
Image(const unsigned width, const unsigned height, const Pixel_T background) : Image(const unsigned width, const unsigned height, const Pixel_T background) :
_width(width), _width(width),
_height(height), _height(height),
_pixels(new Pixel_T[width * height + 1]), _pixels(new Pixel_T[width * height + 1]),
_endOfPixels(_pixels + width * height) _endOfPixels(_pixels + width * height)
{ {
std::fill(_pixels, _endOfPixels, background); std::fill(_pixels, _endOfPixels, background);
} }
/// ///
/// Copy constructor for an image /// Copy constructor for an image
/// ///
Image(const Image & other) : Image(const Image & other) :
_width(other._width), _width(other._width),
_height(other._height), _height(other._height),
_pixels(new Pixel_T[other._width * other._height + 1]), _pixels(new Pixel_T[other._width * other._height + 1]),
_endOfPixels(_pixels + other._width * other._height) _endOfPixels(_pixels + other._width * other._height)
{ {
memcpy(_pixels, other._pixels, other._width * other._height * sizeof(Pixel_T)); memcpy(_pixels, other._pixels, other._width * other._height * sizeof(Pixel_T));
} }
/// ///
/// Destructor /// Destructor
/// ///
~Image() ~Image()
{ {
delete[] _pixels; delete[] _pixels;
} }
/// ///
/// Returns the width of the image /// Returns the width of the image
/// ///
/// @return The width of the image /// @return The width of the image
/// ///
inline unsigned width() const inline unsigned width() const
{ {
return _width; return _width;
} }
/// ///
/// Returns the height of the image /// Returns the height of the image
/// ///
/// @return The height of the image /// @return The height of the image
/// ///
inline unsigned height() const inline unsigned height() const
{ {
return _height; return _height;
} }
uint8_t red(const unsigned pixel) const uint8_t red(const unsigned pixel) const
{ {
return (_pixels + pixel)->red; return (_pixels + pixel)->red;
} }
uint8_t green(const unsigned pixel) const uint8_t green(const unsigned pixel) const
{ {
return (_pixels + pixel)->green; return (_pixels + pixel)->green;
} }
uint8_t blue(const unsigned pixel) const uint8_t blue(const unsigned pixel) const
{ {
return (_pixels + pixel)->blue; return (_pixels + pixel)->blue;
} }
/// ///
/// Returns a const reference to a specified pixel in the image /// Returns a const reference to a specified pixel in the image
/// ///
/// @param x The x index /// @param x The x index
/// @param y The y index /// @param y The y index
/// ///
/// @return const reference to specified pixel /// @return const reference to specified pixel
/// ///
const Pixel_T& operator()(const unsigned x, const unsigned y) const const Pixel_T& operator()(const unsigned x, const unsigned y) const
{ {
return _pixels[toIndex(x,y)]; return _pixels[toIndex(x,y)];
} }
/// ///
/// Returns a reference to a specified pixel in the image /// Returns a reference to a specified pixel in the image
/// ///
/// @param x The x index /// @param x The x index
/// @param y The y index /// @param y The y index
/// ///
/// @return reference to specified pixel /// @return reference to specified pixel
/// ///
Pixel_T& operator()(const unsigned x, const unsigned y) Pixel_T& operator()(const unsigned x, const unsigned y)
{ {
return _pixels[toIndex(x,y)]; return _pixels[toIndex(x,y)];
} }
/// Resize the image /// Resize the image
/// @param width The width of the image /// @param width The width of the image
/// @param height The height of the image /// @param height The height of the image
void resize(const unsigned width, const unsigned height) void resize(const unsigned width, const unsigned height)
{ {
if ((width*height) > unsigned((_endOfPixels-_pixels))) if ((width*height) > unsigned((_endOfPixels-_pixels)))
{ {
delete[] _pixels; delete[] _pixels;
_pixels = new Pixel_T[width*height + 1]; _pixels = new Pixel_T[width*height + 1];
_endOfPixels = _pixels + width*height; _endOfPixels = _pixels + width*height;
} }
_width = width; _width = width;
_height = height; _height = height;
} }
/// ///
/// Copies another image into this image. The images should have exactly the same size. /// Copies another image into this image. The images should have exactly the same size.
/// ///
/// @param other The image to copy into this /// @param other The image to copy into this
/// ///
void copy(const Image<Pixel_T>& other) void copy(const Image<Pixel_T>& other)
{ {
assert(other._width == _width); assert(other._width == _width);
assert(other._height == _height); 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 /// Returns a memory pointer to the first pixel in the image
/// @return The memory pointer to the first pixel /// @return The memory pointer to the first pixel
/// ///
Pixel_T* memptr() Pixel_T* memptr()
{ {
return _pixels; return _pixels;
} }
/// ///
/// Returns a const memory pointer to the first pixel in the image /// Returns a const memory pointer to the first pixel in the image
/// @return The const memory pointer to the first pixel /// @return The const memory pointer to the first pixel
/// ///
const Pixel_T* memptr() const const Pixel_T* memptr() const
{ {
return _pixels; return _pixels;
} }
///
/// Convert image of any color order to a RGB image.
///
/// @param[out] image The image that buffers the output
///
void toRgb(Image<ColorRgb>& image)
{
image.resize(_width, _height);
const unsigned imageSize = _width * _height;
for (unsigned idx=0; idx<imageSize; idx++)
{ ///
const Pixel_T color = memptr()[idx]; /// Convert image of any color order to a RGB image.
image.memptr()[idx] = ColorRgb{color.red, color.green, color.blue}; ///
} /// @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: private:
/// ///
/// Translate x and y coordinate to index of the underlying vector /// Translate x and y coordinate to index of the underlying vector
/// ///
/// @param x The x index /// @param x The x index
/// @param y The y index /// @param y The y index
/// ///
/// @return The index into the underlying data-vector /// @return The index into the underlying data-vector
/// ///
inline unsigned toIndex(const unsigned x, const unsigned y) const inline unsigned toIndex(const unsigned x, const unsigned y) const
{ {
return y*_width + x; return y*_width + x;
} }
private: private:
/// The width of the image /// The width of the image
unsigned _width; unsigned _width;
/// The height of the image /// The height of the image
unsigned _height; unsigned _height;
/// The pixels of the image /// The pixels of the image
Pixel_T* _pixels; Pixel_T* _pixels;
/// Pointer to the last(extra) pixel /// Pointer to the last(extra) pixel
Pixel_T* _endOfPixels; Pixel_T* _endOfPixels;
}; };

View File

@ -8,22 +8,21 @@
class ImageResampler class ImageResampler
{ {
public: 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, void setCropping(int cropLeft,
int cropRight, int cropRight,
int cropTop, int cropTop,
int cropBottom); int cropBottom);
void set3D(VideoMode mode); void set3D(VideoMode mode);
void processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat, void processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat, Image<ColorRgb> & outputImage) const;
Image<ColorRgb> & outputImage) const;
private: private:
static inline uint8_t clamp(int x); static inline uint8_t clamp(int x);

View File

@ -11,9 +11,9 @@ enum PixelFormat {
PIXELFORMAT_UYVY, PIXELFORMAT_UYVY,
PIXELFORMAT_BGR16, PIXELFORMAT_BGR16,
PIXELFORMAT_BGR24, PIXELFORMAT_BGR24,
PIXELFORMAT_RGB32, PIXELFORMAT_RGB32,
PIXELFORMAT_BGR32, PIXELFORMAT_BGR32,
PIXELFORMAT_NO_CHANGE PIXELFORMAT_NO_CHANGE
}; };
inline PixelFormat parsePixelFormat(std::string pixelFormat) inline PixelFormat parsePixelFormat(std::string pixelFormat)
@ -29,22 +29,22 @@ inline PixelFormat parsePixelFormat(std::string pixelFormat)
{ {
return PIXELFORMAT_UYVY; return PIXELFORMAT_UYVY;
} }
else if (pixelFormat == "bgr16") else if (pixelFormat == "bgr16")
{ {
return PIXELFORMAT_BGR16; return PIXELFORMAT_BGR16;
} }
else if (pixelFormat == "bgr24") else if (pixelFormat == "bgr24")
{ {
return PIXELFORMAT_BGR24; return PIXELFORMAT_BGR24;
} }
else if (pixelFormat == "rgb32") else if (pixelFormat == "rgb32")
{ {
return PIXELFORMAT_RGB32; return PIXELFORMAT_RGB32;
} }
else if (pixelFormat == "bgr32") else if (pixelFormat == "bgr32")
{ {
return PIXELFORMAT_BGR32; return PIXELFORMAT_BGR32;
} }
// return the default NO_CHANGE // return the default NO_CHANGE
return PIXELFORMAT_NO_CHANGE; return PIXELFORMAT_NO_CHANGE;

View File

@ -4,7 +4,7 @@
class Sleep : protected QThread { class Sleep : protected QThread {
public: public:
static inline void msleep(unsigned long msecs) { static inline void msleep(unsigned long msecs) {
QThread::msleep(msecs); QThread::msleep(msecs);
} }
}; };

View File

@ -1,192 +1,192 @@
#pragma once #pragma once
// stl includes // stl includes
#include <string> #include <string>
#include <list> #include <list>
// jsoncpp includes // jsoncpp includes
#include <json/json.h> #include <json/json.h>
/// JsonSchemaChecker is a very basic implementation of json schema. /// JsonSchemaChecker is a very basic implementation of json schema.
/// The json schema definition draft can be found at /// The json schema definition draft can be found at
/// http://tools.ietf.org/html/draft-zyp-json-schema-03 /// http://tools.ietf.org/html/draft-zyp-json-schema-03
/// ///
/// The following keywords are supported: /// The following keywords are supported:
/// - type /// - type
/// - required /// - required
/// - properties /// - properties
/// - items /// - items
/// - enum /// - enum
/// - minimum /// - minimum
/// - maximum /// - maximum
/// - addtionalProperties /// - addtionalProperties
/// - minItems /// - minItems
/// - maxItems /// - maxItems
/// ///
/// And the non-standard: /// And the non-standard:
/// - dependencies /// - dependencies
class JsonSchemaChecker class JsonSchemaChecker
{ {
public: public:
JsonSchemaChecker(); JsonSchemaChecker();
virtual ~JsonSchemaChecker(); virtual ~JsonSchemaChecker();
/// ///
/// @param schema The schema to use /// @param schema The schema to use
/// @return true upon succes /// @return true upon succes
/// ///
bool setSchema(const Json::Value & schema); bool setSchema(const Json::Value & schema);
/// ///
/// @brief Validate a JSON structure /// @brief Validate a JSON structure
/// @param value The JSON value to check /// @param value The JSON value to check
/// @return true when the arguments is valid according to the schema /// @return true when the arguments is valid according to the schema
/// ///
bool validate(const Json::Value & value); bool validate(const Json::Value & value);
/// ///
/// @return A list of error messages /// @return A list of error messages
/// ///
const std::list<std::string> & getMessages() const; const std::list<std::string> & getMessages() const;
private: private:
/// ///
/// Validates a json-value against a given schema. Results are stored in the members of this /// Validates a json-value against a given schema. Results are stored in the members of this
/// class (_error & _messages) /// class (_error & _messages)
/// ///
/// @param[in] value The value to validate /// @param[in] value The value to validate
/// @param[in] schema The schema against which the value is validated /// @param[in] schema The schema against which the value is validated
/// ///
void validate(const Json::Value &value, const Json::Value & schema); void validate(const Json::Value &value, const Json::Value & schema);
/// ///
/// Adds the given message to the message-queue (with reference to current line-number) /// Adds the given message to the message-queue (with reference to current line-number)
/// ///
/// @param[in] message The message to add to the queue /// @param[in] message The message to add to the queue
/// ///
void setMessage(const std::string & message); void setMessage(const std::string & message);
/// ///
/// Retrieves all references from the json-value as specified by the schema /// Retrieves all references from the json-value as specified by the schema
/// ///
/// @param[in] value The json-value /// @param[in] value The json-value
/// @param[in] schema The schema /// @param[in] schema The schema
/// ///
void collectDependencies(const Json::Value & value, const Json::Value &schema); void collectDependencies(const Json::Value & value, const Json::Value &schema);
private: private:
// attribute check functions // attribute check functions
/// ///
/// Checks if the given value is of the specified type. If the type does not match _error is set /// 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 /// to true and an error-message is added to the message-queue
/// ///
/// @param[in] value The given value /// @param[in] value The given value
/// @param[in] schema The specified type (as json-value) /// @param[in] schema The specified type (as json-value)
/// ///
void checkType(const Json::Value & value, const Json::Value & schema); 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 /// 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 /// correct format. If this is not the case _error is set to true and an error-message is added
/// to the message-queue. /// to the message-queue.
/// ///
/// @param[in] value The given json-object /// @param[in] value The given json-object
/// @param[in] schema The schema of the json-object /// @param[in] schema The schema of the json-object
/// ///
void checkProperties(const Json::Value & value, const Json::Value & schema); 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 /// 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. /// _error is set to true and an error-message is added to the message-queue.
/// ///
/// @param value The given json-object /// @param value The given json-object
/// @param schema The schema for the json-object /// @param schema The schema for the json-object
/// @param ignoredProperties The properties that were ignored /// @param ignoredProperties The properties that were ignored
/// ///
void checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties); 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 /// 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. /// to true and an error-message is added to the message-queue.
/// ///
/// @param value The given json-object /// @param value The given json-object
/// @param schemaLink The schema of the json-object /// @param schemaLink The schema of the json-object
/// ///
void checkDependencies(const Json::Value & value, const Json::Value & schemaLink); 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 /// 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. /// _error is set to true and an error-message is added to the message-queue.
/// ///
/// @param[in] value The given value /// @param[in] value The given value
/// @param[in] schema The minimum value (as json-value) /// @param[in] schema The minimum value (as json-value)
/// ///
void checkMinimum(const Json::Value & value, const Json::Value & schema); 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 /// 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. /// case _error is set to true and an error-message is added to the message-queue.
/// ///
/// @param[in] value The given value /// @param[in] value The given value
/// @param[in] schema The maximum value (as json-value) /// @param[in] schema The maximum value (as json-value)
/// ///
void checkMaximum(const Json::Value & value, const Json::Value & schema); void checkMaximum(const Json::Value & value, const Json::Value & schema);
/// ///
/// Validates all the items of an array. /// Validates all the items of an array.
/// ///
/// @param value The json-array /// @param value The json-array
/// @param schema The schema for the items in the array /// @param schema The schema for the items in the array
/// ///
void checkItems(const Json::Value & value, const Json::Value & schema); 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 /// 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. /// _error is set to true and an error-message is added to the message-queue.
/// ///
/// @param value The json-array /// @param value The json-array
/// @param schema The minimum size specification (as json-value) /// @param schema The minimum size specification (as json-value)
/// ///
void checkMinItems(const Json::Value & value, const Json::Value & schema); 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 /// 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. /// _error is set to true and an error-message is added to the message-queue.
/// ///
/// @param value The json-array /// @param value The json-array
/// @param schema The maximum size specification (as json-value) /// @param schema The maximum size specification (as json-value)
/// ///
void checkMaxItems(const Json::Value & value, const Json::Value & schema); 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 /// 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. /// _error is set to true and an error-message is added to the message-queue.
/// ///
/// @param value The json-array /// @param value The json-array
/// @param schema Bool to enable the check (as json-value) /// @param schema Bool to enable the check (as json-value)
/// ///
void checkUniqueItems(const Json::Value & value, const Json::Value & schema); 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 /// 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. /// _error is set to true and an error-message is added to the message-queue.
/// ///
/// @param value The enum value /// @param value The enum value
/// @param schema The enum schema definition /// @param schema The enum schema definition
/// ///
void checkEnum(const Json::Value & value, const Json::Value & schema); void checkEnum(const Json::Value & value, const Json::Value & schema);
private: private:
/// The schema of the entire json-configuration /// The schema of the entire json-configuration
Json::Value _schema; Json::Value _schema;
/// The current location into a json-configuration structure being checked /// The current location into a json-configuration structure being checked
std::list<std::string> _currentPath; std::list<std::string> _currentPath;
/// The result messages collected during the schema verification /// The result messages collected during the schema verification
std::list<std::string> _messages; std::list<std::string> _messages;
/// Flag indicating an error occured during validation /// Flag indicating an error occured during validation
bool _error; bool _error;
/// A list with references (string => json-value) /// A list with references (string => json-value)
std::map<std::string, const Json::Value *> _references; // ref 2 value std::map<std::string, const Json::Value *> _references; // ref 2 value
}; };

View File

@ -9,7 +9,7 @@ add_subdirectory(jsonserver)
if (ENABLE_PROTOBUF) if (ENABLE_PROTOBUF)
add_subdirectory(protoserver) add_subdirectory(protoserver)
endif (ENABLE_PROTOBUF) endif ()
add_subdirectory(boblightserver) add_subdirectory(boblightserver)
add_subdirectory(leddevice) add_subdirectory(leddevice)

View File

@ -1,23 +1,23 @@
# Define the current source locations # Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/blackborder) SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/blackborder)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/blackborder) SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/blackborder)
SET(Blackborder_HEADERS SET(Blackborder_HEADERS
${CURRENT_HEADER_DIR}/BlackBorderDetector.h ${CURRENT_HEADER_DIR}/BlackBorderDetector.h
${CURRENT_HEADER_DIR}/BlackBorderProcessor.h ${CURRENT_HEADER_DIR}/BlackBorderProcessor.h
) )
SET(Blackborder_SOURCES SET(Blackborder_SOURCES
${CURRENT_SOURCE_DIR}/BlackBorderDetector.cpp ${CURRENT_SOURCE_DIR}/BlackBorderDetector.cpp
${CURRENT_SOURCE_DIR}/BlackBorderProcessor.cpp ${CURRENT_SOURCE_DIR}/BlackBorderProcessor.cpp
) )
add_library(blackborder add_library(blackborder
${Blackborder_HEADERS} ${Blackborder_HEADERS}
${Blackborder_SOURCES} ${Blackborder_SOURCES}
) )
target_link_libraries(blackborder target_link_libraries(blackborder
hyperion-utils hyperion-utils
) )

View File

@ -1,40 +1,40 @@
# Define the current source locations # Define the current source locations
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/boblightserver) set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/boblightserver)
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/boblightserver) set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/boblightserver)
# Group the headers that go through the MOC compiler # Group the headers that go through the MOC compiler
set(BoblightServer_QT_HEADERS set(BoblightServer_QT_HEADERS
${CURRENT_HEADER_DIR}/BoblightServer.h ${CURRENT_HEADER_DIR}/BoblightServer.h
${CURRENT_SOURCE_DIR}/BoblightClientConnection.h ${CURRENT_SOURCE_DIR}/BoblightClientConnection.h
) )
set(BoblightServer_HEADERS set(BoblightServer_HEADERS
) )
set(BoblightServer_SOURCES set(BoblightServer_SOURCES
${CURRENT_SOURCE_DIR}/BoblightServer.cpp ${CURRENT_SOURCE_DIR}/BoblightServer.cpp
${CURRENT_SOURCE_DIR}/BoblightClientConnection.cpp ${CURRENT_SOURCE_DIR}/BoblightClientConnection.cpp
) )
if(ENABLE_QT5) if(ENABLE_QT5)
qt5_wrap_cpp(BoblightServer_HEADERS_MOC ${BoblightServer_QT_HEADERS}) qt5_wrap_cpp(BoblightServer_HEADERS_MOC ${BoblightServer_QT_HEADERS})
else(ENABLE_QT5) else()
qt4_wrap_cpp(BoblightServer_HEADERS_MOC ${BoblightServer_QT_HEADERS}) qt4_wrap_cpp(BoblightServer_HEADERS_MOC ${BoblightServer_QT_HEADERS})
endif(ENABLE_QT5) endif()
add_library(boblightserver add_library(boblightserver
${BoblightServer_HEADERS} ${BoblightServer_HEADERS}
${BoblightServer_QT_HEADERS} ${BoblightServer_QT_HEADERS}
${BoblightServer_SOURCES} ${BoblightServer_SOURCES}
${BoblightServer_HEADERS_MOC} ${BoblightServer_HEADERS_MOC}
) )
if(ENABLE_QT5) if(ENABLE_QT5)
qt5_use_modules(boblightserver Widgets) qt5_use_modules(boblightserver Widgets)
endif(ENABLE_QT5) endif()
target_link_libraries(boblightserver target_link_libraries(boblightserver
hyperion hyperion
hyperion-utils hyperion-utils
${QT_LIBRARIES}) ${QT_LIBRARIES})

View File

@ -13,8 +13,8 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/effectengine)
# Group the headers that go through the MOC compiler # Group the headers that go through the MOC compiler
SET(EffectEngineQT_HEADERS SET(EffectEngineQT_HEADERS
${CURRENT_HEADER_DIR}/EffectEngine.h ${CURRENT_HEADER_DIR}/EffectEngine.h
${CURRENT_SOURCE_DIR}/Effect.h ${CURRENT_SOURCE_DIR}/Effect.h
) )
SET(EffectEngineHEADERS SET(EffectEngineHEADERS
@ -22,35 +22,34 @@ SET(EffectEngineHEADERS
) )
SET(EffectEngineSOURCES SET(EffectEngineSOURCES
${CURRENT_SOURCE_DIR}/EffectEngine.cpp ${CURRENT_SOURCE_DIR}/EffectEngine.cpp
${CURRENT_SOURCE_DIR}/Effect.cpp ${CURRENT_SOURCE_DIR}/Effect.cpp
) )
set(EffectEngine_RESOURCES ${CURRENT_SOURCE_DIR}/EffectEngine.qrc) set(EffectEngine_RESOURCES ${CURRENT_SOURCE_DIR}/EffectEngine.qrc)
if(ENABLE_QT5) if(ENABLE_QT5)
QT5_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS}) QT5_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS})
qt5_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress") qt5_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress")
else(ENABLE_QT5) else()
QT4_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS}) QT4_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS})
qt4_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress") qt4_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress")
endif(ENABLE_QT5) endif()
add_library(effectengine add_library(effectengine
${EffectEngineHEADERS} ${EffectEngineHEADERS}
${EffectEngineQT_HEADERS} ${EffectEngineQT_HEADERS}
${EffectEngineHEADERS_MOC} ${EffectEngineHEADERS_MOC}
${EffectEngine_RESOURCES_RCC} ${EffectEngine_RESOURCES_RCC}
${EffectEngineSOURCES} ${EffectEngineSOURCES}
) )
if(ENABLE_QT5) if(ENABLE_QT5)
qt5_use_modules(effectengine Widgets) qt5_use_modules(effectengine Widgets)
endif(ENABLE_QT5) endif()
target_link_libraries(effectengine target_link_libraries(effectengine
hyperion hyperion
jsoncpp jsoncpp
${QT_LIBRARIES} ${QT_LIBRARIES}
${PYTHON_LIBRARIES}) ${PYTHON_LIBRARIES})

View File

@ -1,342 +1,342 @@
{ {
"type" : "object", "type" : "object",
"required" : true, "required" : true,
"properties" : { "properties" : {
"device" : { "device" : {
"type" : "object", "type" : "object",
"required" : true, "required" : true,
"properties" : { "properties" : {
"name" : { "name" : {
"type" : "string", "type" : "string",
"required" : true "required" : true
}, },
"type" : { "type" : {
"type" : "string", "type" : "string",
"required" : true "required" : true
}, },
"output" : { "output" : {
"type" : "string", "type" : "string",
"required" : true "required" : true
}, },
"rate" : { "rate" : {
"type" : "integer", "type" : "integer",
"required" : true, "required" : true,
"minimum" : 0 "minimum" : 0
}, },
"colorOrder" : { "colorOrder" : {
"type" : "string", "type" : "string",
"required" : false "required" : false
}, },
"bgr-output" : { // deprecated "bgr-output" : { // deprecated
"type" : "boolean", "type" : "boolean",
"required" : false "required" : false
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"color": { "color": {
"type":"object", "type":"object",
"required":false, "required":false,
"properties": { "properties": {
"hsv" : { "hsv" : {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"saturationGain" : { "saturationGain" : {
"type" : "number", "type" : "number",
"required" : false, "required" : false,
"minimum" : 0.0 "minimum" : 0.0
}, },
"valueGain" : { "valueGain" : {
"type" : "number", "type" : "number",
"required" : false, "required" : false,
"minimum" : 0.0 "minimum" : 0.0
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"red": { "red": {
"type":"object", "type":"object",
"required":false, "required":false,
"properties":{ "properties":{
"gamma": { "gamma": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"blacklevel": { "blacklevel": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"whitelevel": { "whitelevel": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"threshold": { "threshold": {
"type":"number", "type":"number",
"required":false, "required":false,
"minimum" : 0.0, "minimum" : 0.0,
"maximum" : 1.0 "maximum" : 1.0
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"green": { "green": {
"type":"object", "type":"object",
"required":false, "required":false,
"properties":{ "properties":{
"gamma": { "gamma": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"blacklevel": { "blacklevel": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"whitelevel": { "whitelevel": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"threshold": { "threshold": {
"type":"number", "type":"number",
"required":false, "required":false,
"minimum" : 0.0, "minimum" : 0.0,
"maximum" : 1.0 "maximum" : 1.0
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"blue": { "blue": {
"type":"object", "type":"object",
"required":false, "required":false,
"properties":{ "properties":{
"gamma": { "gamma": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"whitelevel": { "whitelevel": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"blacklevel": { "blacklevel": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"threshold": { "threshold": {
"type":"number", "type":"number",
"required":false, "required":false,
"minimum" : 0.0, "minimum" : 0.0,
"maximum" : 1.0 "maximum" : 1.0
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"smoothing" : { "smoothing" : {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"type" : { "type" : {
"type" : "enum", "type" : "enum",
"required" : true, "required" : true,
"values" : ["none", "linear"] "values" : ["none", "linear"]
}, },
"time_ms" : { "time_ms" : {
"type" : "integer", "type" : "integer",
"required" : false, "required" : false,
"minimum" : 10 "minimum" : 10
}, },
"updateFrequency" : { "updateFrequency" : {
"type" : "number", "type" : "number",
"required" : false, "required" : false,
"minimum" : 0.001 "minimum" : 0.001
} }
}, },
"additionalProperties" : false "additionalProperties" : false
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"leds": { "leds": {
"type":"array", "type":"array",
"required":true, "required":true,
"items": { "items": {
"type":"object", "type":"object",
"properties": { "properties": {
"index": { "index": {
"type":"integer", "type":"integer",
"required":true "required":true
}, },
"hscan": { "hscan": {
"type":"object", "type":"object",
"required":true, "required":true,
"properties": { "properties": {
"minimum": { "minimum": {
"type":"number", "type":"number",
"required":true "required":true
}, },
"maximum": { "maximum": {
"type":"number", "type":"number",
"required":true "required":true
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"vscan": { "vscan": {
"type":"object", "type":"object",
"required":true, "required":true,
"properties": { "properties": {
"minimum": { "minimum": {
"type":"number", "type":"number",
"required":true "required":true
}, },
"maximum": { "maximum": {
"type":"number", "type":"number",
"required":true "required":true
} }
}, },
"additionalProperties" : false "additionalProperties" : false
} }
}, },
"additionalProperties" : false "additionalProperties" : false
} }
}, },
"effects" : "effects" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"paths" : { "paths" : {
"type" : "array", "type" : "array",
"required" : false, "required" : false,
"items" : { "items" : {
"type" : "string" "type" : "string"
} }
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"blackborderdetector" : "blackborderdetector" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"enable" : { "enable" : {
"type" : "boolean", "type" : "boolean",
"required" : true "required" : true
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"xbmcVideoChecker" : "xbmcVideoChecker" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"xbmcAddress" : { "xbmcAddress" : {
"type" : "string", "type" : "string",
"required" : true "required" : true
}, },
"xbmcTcpPort" : { "xbmcTcpPort" : {
"type" : "integer", "type" : "integer",
"required" : true "required" : true
}, },
"grabVideo" : { "grabVideo" : {
"type" : "boolean", "type" : "boolean",
"required" : true "required" : true
}, },
"grabPictures" : { "grabPictures" : {
"type" : "boolean", "type" : "boolean",
"required" : true "required" : true
}, },
"grabAudio" : { "grabAudio" : {
"type" : "boolean", "type" : "boolean",
"required" : true "required" : true
}, },
"grabMenu" : { "grabMenu" : {
"type" : "boolean", "type" : "boolean",
"required" : true "required" : true
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"bootsequence" : "bootsequence" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"path" : { "path" : {
"type" : "string", "type" : "string",
"required" : true "required" : true
}, },
"effect" : { "effect" : {
"type" : "string", "type" : "string",
"required" : true "required" : true
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"framegrabber" : "framegrabber" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"width" : { "width" : {
"type" : "integer", "type" : "integer",
"required" : true "required" : true
}, },
"height" : { "height" : {
"type" : "integer", "type" : "integer",
"required" : true "required" : true
}, },
"frequency_Hz" : { "frequency_Hz" : {
"type" : "integer", "type" : "integer",
"required" : true "required" : true
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"jsonServer" : "jsonServer" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"port" : { "port" : {
"type" : "integer", "type" : "integer",
"required" : true, "required" : true,
"minimum" : 0, "minimum" : 0,
"maximum" : 65535 "maximum" : 65535
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"protoServer" : "protoServer" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"port" : { "port" : {
"type" : "integer", "type" : "integer",
"required" : true, "required" : true,
"minimum" : 0, "minimum" : 0,
"maximum" : 65535 "maximum" : 65535
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"boblightServer" : "boblightServer" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"port" : { "port" : {
"type" : "integer", "type" : "integer",
"required" : true, "required" : true,
"minimum" : 0, "minimum" : 0,
"maximum" : 65535 "maximum" : 65535
} }
}, },
"additionalProperties" : false "additionalProperties" : false
} }
}, },
"additionalProperties" : false "additionalProperties" : false
} }

View File

@ -1,23 +1,23 @@
if (ENABLE_AMLOGIC) if (ENABLE_AMLOGIC)
add_subdirectory(amlogic) add_subdirectory(amlogic)
endif (ENABLE_AMLOGIC) endif (ENABLE_AMLOGIC)
if (ENABLE_DISPMANX) if (ENABLE_DISPMANX)
add_subdirectory(dispmanx) add_subdirectory(dispmanx)
endif (ENABLE_DISPMANX) endif (ENABLE_DISPMANX)
if (ENABLE_FB) if (ENABLE_FB)
add_subdirectory(framebuffer) add_subdirectory(framebuffer)
endif (ENABLE_FB) endif (ENABLE_FB)
if (ENABLE_OSX) if (ENABLE_OSX)
add_subdirectory(osx) add_subdirectory(osx)
endif() endif()
if (ENABLE_V4L2) if (ENABLE_V4L2)
add_subdirectory(v4l2) add_subdirectory(v4l2)
endif (ENABLE_V4L2) endif (ENABLE_V4L2)
if (ENABLE_X11) if (ENABLE_X11)
add_subdirectory(x11) add_subdirectory(x11)
endif() endif()

View File

@ -1,33 +1,33 @@
# Define the current source locations # Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/amlogic) SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/amlogic)
# Group the headers that go through the MOC compiler # Group the headers that go through the MOC compiler
SET(AmlogicQT_HEADERS ${CURRENT_HEADER_DIR}/AmlogicWrapper.h) SET(AmlogicQT_HEADERS ${CURRENT_HEADER_DIR}/AmlogicWrapper.h)
SET(AmlogicHEADERS SET(AmlogicHEADERS
${CURRENT_HEADER_DIR}/AmlogicGrabber.h ${CURRENT_HEADER_DIR}/AmlogicGrabber.h
) )
SET(AmlogicSOURCES SET(AmlogicSOURCES
${CURRENT_SOURCE_DIR}/AmlogicWrapper.cpp ${CURRENT_SOURCE_DIR}/AmlogicWrapper.cpp
${CURRENT_SOURCE_DIR}/AmlogicGrabber.cpp ${CURRENT_SOURCE_DIR}/AmlogicGrabber.cpp
) )
if(ENABLE_QT5) if(ENABLE_QT5)
QT5_WRAP_CPP(AmlogicHEADERS_MOC ${AmlogicQT_HEADERS}) QT5_WRAP_CPP(AmlogicHEADERS_MOC ${AmlogicQT_HEADERS})
else(ENABLE_QT5) else(ENABLE_QT5)
QT4_WRAP_CPP(AmlogicHEADERS_MOC ${AmlogicQT_HEADERS}) QT4_WRAP_CPP(AmlogicHEADERS_MOC ${AmlogicQT_HEADERS})
endif(ENABLE_QT5) endif(ENABLE_QT5)
add_library(amlogic-grabber add_library(amlogic-grabber
${AmlogicHEADERS} ${AmlogicHEADERS}
${AmlogicQT_HEADERS} ${AmlogicQT_HEADERS}
${AmlogicHEADERS_MOC} ${AmlogicHEADERS_MOC}
${AmlogicSOURCES} ${AmlogicSOURCES}
) )
target_link_libraries(amlogic-grabber target_link_libraries(amlogic-grabber
hyperion hyperion
${QT_LIBRARIES}) ${QT_LIBRARIES})

View File

@ -1,41 +1,41 @@
# Find the BCM-package (VC control) # Find the BCM-package (VC control)
find_package(BCM REQUIRED) find_package(BCM REQUIRED)
include_directories(${BCM_INCLUDE_DIRS}) include_directories(${BCM_INCLUDE_DIRS})
# Define the current source locations # Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx) SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx)
# Group the headers that go through the MOC compiler # Group the headers that go through the MOC compiler
SET(DispmanxGrabberQT_HEADERS SET(DispmanxGrabberQT_HEADERS
${CURRENT_HEADER_DIR}/DispmanxWrapper.h ${CURRENT_HEADER_DIR}/DispmanxWrapper.h
) )
SET(DispmanxGrabberHEADERS SET(DispmanxGrabberHEADERS
${CURRENT_HEADER_DIR}/DispmanxFrameGrabber.h ${CURRENT_HEADER_DIR}/DispmanxFrameGrabber.h
) )
SET(DispmanxGrabberSOURCES SET(DispmanxGrabberSOURCES
${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp ${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp
${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp
) )
if(ENABLE_QT5) if(ENABLE_QT5)
QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
else(ENABLE_QT5) else()
QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
endif(ENABLE_QT5) endif()
add_library(dispmanx-grabber add_library(dispmanx-grabber
${DispmanxGrabberHEADERS} ${DispmanxGrabberHEADERS}
${DispmanxGrabberQT_HEADERS} ${DispmanxGrabberQT_HEADERS}
${DispmanxGrabberHEADERS_MOC} ${DispmanxGrabberHEADERS_MOC}
${DispmanxGrabberSOURCES} ${DispmanxGrabberSOURCES}
) )
target_link_libraries(dispmanx-grabber target_link_libraries(dispmanx-grabber
hyperion hyperion
${QT_LIBRARIES} ${QT_LIBRARIES}
${BCM_LIBRARIES} ${BCM_LIBRARIES}
) )

View File

@ -9,31 +9,31 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/framebuffer)
# Group the headers that go through the MOC compiler # Group the headers that go through the MOC compiler
SET(FramebufferGrabberQT_HEADERS SET(FramebufferGrabberQT_HEADERS
${CURRENT_HEADER_DIR}/FramebufferWrapper.h ${CURRENT_HEADER_DIR}/FramebufferWrapper.h
) )
SET(FramebufferGrabberHEADERS SET(FramebufferGrabberHEADERS
${CURRENT_HEADER_DIR}/FramebufferFrameGrabber.h ${CURRENT_HEADER_DIR}/FramebufferFrameGrabber.h
) )
SET(FramebufferGrabberSOURCES SET(FramebufferGrabberSOURCES
${CURRENT_SOURCE_DIR}/FramebufferWrapper.cpp ${CURRENT_SOURCE_DIR}/FramebufferWrapper.cpp
${CURRENT_SOURCE_DIR}/FramebufferFrameGrabber.cpp ${CURRENT_SOURCE_DIR}/FramebufferFrameGrabber.cpp
) )
if(ENABLE_QT5) if(ENABLE_QT5)
QT5_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS}) QT5_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS})
else(ENABLE_QT5) else()
QT4_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS}) QT4_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS})
endif(ENABLE_QT5) endif()
add_library(framebuffer-grabber add_library(framebuffer-grabber
${FramebufferGrabberHEADERS} ${FramebufferGrabberHEADERS}
${FramebufferGrabberQT_HEADERS} ${FramebufferGrabberQT_HEADERS}
${FramebufferGrabberHEADERS_MOC} ${FramebufferGrabberHEADERS_MOC}
${FramebufferGrabberSOURCES} ${FramebufferGrabberSOURCES}
) )
target_link_libraries(framebuffer-grabber target_link_libraries(framebuffer-grabber
hyperion hyperion
${QT_LIBRARIES}) ${QT_LIBRARIES})

View File

@ -4,31 +4,31 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/osx)
# Group the headers that go through the MOC compiler # Group the headers that go through the MOC compiler
SET(OsxGrabberQT_HEADERS SET(OsxGrabberQT_HEADERS
${CURRENT_HEADER_DIR}/OsxWrapper.h ${CURRENT_HEADER_DIR}/OsxWrapper.h
) )
SET(OsxGrabberHEADERS SET(OsxGrabberHEADERS
${CURRENT_HEADER_DIR}/OsxFrameGrabber.h ${CURRENT_HEADER_DIR}/OsxFrameGrabber.h
) )
SET(OsxGrabberSOURCES SET(OsxGrabberSOURCES
${CURRENT_SOURCE_DIR}/OsxWrapper.cpp ${CURRENT_SOURCE_DIR}/OsxWrapper.cpp
${CURRENT_SOURCE_DIR}/OsxFrameGrabber.cpp ${CURRENT_SOURCE_DIR}/OsxFrameGrabber.cpp
) )
if(ENABLE_QT5) if(ENABLE_QT5)
QT5_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS}) QT5_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS})
else(ENABLE_QT5) else()
QT4_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS}) QT4_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS})
endif(ENABLE_QT5) endif()
add_library(osx-grabber add_library(osx-grabber
${OsxGrabberHEADERS} ${OsxGrabberHEADERS}
${OsxGrabberQT_HEADERS} ${OsxGrabberQT_HEADERS}
${OsxGrabberHEADERS_MOC} ${OsxGrabberHEADERS_MOC}
${OsxGrabberSOURCES} ${OsxGrabberSOURCES}
) )
target_link_libraries(osx-grabber target_link_libraries(osx-grabber
hyperion hyperion
${QT_LIBRARIES}) ${QT_LIBRARIES})

View File

@ -1,39 +1,39 @@
# Define the current source locations # Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/v4l2) SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/v4l2)
SET(V4L2_QT_HEADERS SET(V4L2_QT_HEADERS
${CURRENT_HEADER_DIR}/V4L2Grabber.h ${CURRENT_HEADER_DIR}/V4L2Grabber.h
${CURRENT_HEADER_DIR}/V4L2Wrapper.h ${CURRENT_HEADER_DIR}/V4L2Wrapper.h
) )
SET(V4L2_HEADERS SET(V4L2_HEADERS
${CURRENT_HEADER_DIR}/VideoStandard.h ${CURRENT_HEADER_DIR}/VideoStandard.h
) )
SET(V4L2_SOURCES SET(V4L2_SOURCES
${CURRENT_SOURCE_DIR}/V4L2Grabber.cpp ${CURRENT_SOURCE_DIR}/V4L2Grabber.cpp
${CURRENT_SOURCE_DIR}/V4L2Wrapper.cpp ${CURRENT_SOURCE_DIR}/V4L2Wrapper.cpp
) )
if(ENABLE_QT5) if(ENABLE_QT5)
QT5_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS}) QT5_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS})
else(ENABLE_QT5) else()
QT4_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS}) QT4_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS})
endif(ENABLE_QT5) endif()
add_library(v4l2-grabber add_library(v4l2-grabber
${V4L2_HEADERS} ${V4L2_HEADERS}
${V4L2_SOURCES} ${V4L2_SOURCES}
${V4L2_QT_HEADERS} ${V4L2_QT_HEADERS}
${V4L2_HEADERS_MOC} ${V4L2_HEADERS_MOC}
) )
if(ENABLE_QT5) if(ENABLE_QT5)
qt5_use_modules(v4l2-grabber Widgets) qt5_use_modules(v4l2-grabber Widgets)
endif(ENABLE_QT5) endif(ENABLE_QT5)
target_link_libraries(v4l2-grabber target_link_libraries(v4l2-grabber
hyperion hyperion
${QT_LIBRARIES} ${QT_LIBRARIES}
) )

File diff suppressed because it is too large Load Diff

View File

@ -19,20 +19,20 @@ SET(X11_HEADERS
) )
SET(X11_SOURCES SET(X11_SOURCES
${CURRENT_SOURCE_DIR}/X11Grabber.cpp ${CURRENT_SOURCE_DIR}/X11Grabber.cpp
) )
if(ENABLE_QT5) if(ENABLE_QT5)
QT5_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS}) QT5_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS})
else(ENABLE_QT5) else()
QT4_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS}) QT4_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS})
endif(ENABLE_QT5) endif()
add_library(x11-grabber add_library(x11-grabber
${X11_HEADERS} ${X11_HEADERS}
${X11_SOURCES} ${X11_SOURCES}
${X11_QT_HEADERS} ${X11_QT_HEADERS}
${X11_HEADERS_MOC} ${X11_HEADERS_MOC}
) )
target_link_libraries(x11-grabber target_link_libraries(x11-grabber

View File

@ -6,107 +6,108 @@
#include <grabber/X11Grabber.h> #include <grabber/X11Grabber.h>
X11Grabber::X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) : X11Grabber::X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) :
_imageResampler(), _imageResampler(),
_useXGetImage(useXGetImage), _useXGetImage(useXGetImage),
_cropLeft(cropLeft), _cropLeft(cropLeft),
_cropRight(cropRight), _cropRight(cropRight),
_cropTop(cropTop), _cropTop(cropTop),
_cropBottom(cropBottom), _cropBottom(cropBottom),
_x11Display(nullptr), _x11Display(nullptr),
_pixmap(None), _pixmap(None),
_srcFormat(nullptr), _srcFormat(nullptr),
_dstFormat(nullptr), _dstFormat(nullptr),
_srcPicture(None), _srcPicture(None),
_dstPicture(None), _dstPicture(None),
_screenWidth(0), _screenWidth(0),
_screenHeight(0), _screenHeight(0),
_croppedWidth(0), _croppedWidth(0),
_croppedHeight(0), _croppedHeight(0),
_image(0,0) _image(0,0)
{ {
_imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation); _imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation);
_imageResampler.setVerticalPixelDecimation(verticalPixelDecimation); _imageResampler.setVerticalPixelDecimation(verticalPixelDecimation);
_imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XShmGetImage or XGetImage _imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XShmGetImage or XGetImage
memset(&_pictAttr, 0, sizeof(_pictAttr)); memset(&_pictAttr, 0, sizeof(_pictAttr));
_pictAttr.repeat = RepeatNone; _pictAttr.repeat = RepeatNone;
} }
X11Grabber::~X11Grabber() X11Grabber::~X11Grabber()
{ {
if (_x11Display != nullptr) if (_x11Display != nullptr)
{ {
freeResources(); freeResources();
XCloseDisplay(_x11Display); XCloseDisplay(_x11Display);
} }
} }
void X11Grabber::freeResources() void X11Grabber::freeResources()
{ {
// Cleanup allocated resources of the X11 grab // Cleanup allocated resources of the X11 grab
XDestroyImage(_xImage); XDestroyImage(_xImage);
if(_XShmAvailable && !_useXGetImage) { if(_XShmAvailable && !_useXGetImage) {
XShmDetach(_x11Display, &_shminfo); XShmDetach(_x11Display, &_shminfo);
shmdt(_shminfo.shmaddr); shmdt(_shminfo.shmaddr);
shmctl(_shminfo.shmid, IPC_RMID, 0); shmctl(_shminfo.shmid, IPC_RMID, 0);
} }
if (_XRenderAvailable && !_useXGetImage) { if (_XRenderAvailable && !_useXGetImage) {
XRenderFreePicture(_x11Display, _srcPicture); XRenderFreePicture(_x11Display, _srcPicture);
XRenderFreePicture(_x11Display, _dstPicture); XRenderFreePicture(_x11Display, _dstPicture);
XFreePixmap(_x11Display, _pixmap); XFreePixmap(_x11Display, _pixmap);
} }
} }
void X11Grabber::setupResources() void X11Grabber::setupResources()
{ {
if(_XShmAvailable && !_useXGetImage) { if(_XShmAvailable && !_useXGetImage) {
_xImage = XShmCreateImage(_x11Display, _windowAttr.visual, _xImage = XShmCreateImage(_x11Display, _windowAttr.visual,
_windowAttr.depth, ZPixmap, NULL, &_shminfo, _windowAttr.depth, ZPixmap, NULL, &_shminfo,
_croppedWidth, _croppedHeight); _croppedWidth, _croppedHeight);
_shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777); _shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777);
_xImage->data = (char*)shmat(_shminfo.shmid,0,0); _xImage->data = (char*)shmat(_shminfo.shmid,0,0);
_shminfo.shmaddr = _xImage->data; _shminfo.shmaddr = _xImage->data;
_shminfo.readOnly = False; _shminfo.readOnly = False;
XShmAttach(_x11Display, &_shminfo); XShmAttach(_x11Display, &_shminfo);
}
if (_XRenderAvailable && !_useXGetImage) {
if(_XShmPixmapAvailable) {
_pixmap = XShmCreatePixmap(_x11Display, _window, _xImage->data, &_shminfo, _croppedWidth, _croppedHeight, _windowAttr.depth);
} else {
_pixmap = XCreatePixmap(_x11Display, _window, _croppedWidth, _croppedHeight, _windowAttr.depth);
} }
_srcFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual); if (_XRenderAvailable && !_useXGetImage) {
_dstFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual); if(_XShmPixmapAvailable) {
_srcPicture = XRenderCreatePicture(_x11Display, _window, _srcFormat, CPRepeat, &_pictAttr); _pixmap = XShmCreatePixmap(_x11Display, _window, _xImage->data, &_shminfo, _croppedWidth, _croppedHeight, _windowAttr.depth);
_dstPicture = XRenderCreatePicture(_x11Display, _pixmap, _dstFormat, CPRepeat, &_pictAttr); } else {
XRenderSetPictureFilter(_x11Display, _srcPicture, "bilinear", NULL, 0); _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() bool X11Grabber::Setup()
{ {
_x11Display = XOpenDisplay(NULL); _x11Display = XOpenDisplay(NULL);
if (_x11Display == nullptr) if (_x11Display == nullptr)
{ {
std::cerr << "X11GRABBER ERROR: Unable to open display"; std::cerr << "X11GRABBER ERROR: Unable to open display";
if (getenv("DISPLAY")) if (getenv("DISPLAY")) {
std::cerr << " " << std::string(getenv("DISPLAY")) << std::endl; std::cerr << " " << std::string(getenv("DISPLAY")) << std::endl;
else } else {
std::cerr << ". DISPLAY environment variable not set" << std::endl; std::cerr << ". DISPLAY environment variable not set" << std::endl;
return false; }
} return false;
}
_window = DefaultRootWindow(_x11Display);
_window = DefaultRootWindow(_x11Display);
int dummy, pixmaps_supported; int dummy, pixmaps_supported;
_XRenderAvailable = XRenderQueryExtension(_x11Display, &dummy, &dummy); _XRenderAvailable = XRenderQueryExtension(_x11Display, &dummy, &dummy);
_XShmAvailable = XShmQueryExtension(_x11Display); _XShmAvailable = XShmQueryExtension(_x11Display);
XShmQueryVersion(_x11Display, &dummy, &dummy, &pixmaps_supported); XShmQueryVersion(_x11Display, &dummy, &dummy, &pixmaps_supported);
_XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_x11Display) == ZPixmap; _XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_x11Display) == ZPixmap;
return true; return true;
} }
Image<ColorRgb> & X11Grabber::grab() Image<ColorRgb> & X11Grabber::grab()
@ -129,75 +130,74 @@ Image<ColorRgb> & X11Grabber::grab()
_croppedHeight); // height _croppedHeight); // height
XSync(_x11Display, False); 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() int X11Grabber::updateScreenDimensions()
{ {
const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr); const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr);
if (status == 0) if (status == 0)
{ {
std::cerr << "X11GRABBER ERROR: Failed to obtain window attributes" << std::endl; std::cerr << "X11GRABBER ERROR: Failed to obtain window attributes" << std::endl;
return -1; return -1;
} }
if (_screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height)) if (_screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height))
{ {
// No update required // No update required
return 0; return 0;
} }
std::cout << "X11GRABBER INFO: Update of screen resolution: [" << _screenWidth << "x" << _screenHeight <<"] => "; std::cout << "X11GRABBER INFO: Update of screen resolution: [" << _screenWidth << "x" << _screenHeight <<"] => ";
if (_screenWidth || _screenHeight) if (_screenWidth || _screenHeight) {
freeResources(); 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();
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;
} }

View File

@ -1,72 +1,72 @@
# Define the current source locations # Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion) SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion) SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion)
# Group the headers that go through the MOC compiler # Group the headers that go through the MOC compiler
SET(Hyperion_QT_HEADERS SET(Hyperion_QT_HEADERS
${CURRENT_HEADER_DIR}/Hyperion.h ${CURRENT_HEADER_DIR}/Hyperion.h
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h
) )
SET(Hyperion_HEADERS SET(Hyperion_HEADERS
${CURRENT_HEADER_DIR}/ImageProcessor.h ${CURRENT_HEADER_DIR}/ImageProcessor.h
${CURRENT_HEADER_DIR}/ImageProcessorFactory.h ${CURRENT_HEADER_DIR}/ImageProcessorFactory.h
${CURRENT_HEADER_DIR}/ImageToLedsMap.h ${CURRENT_HEADER_DIR}/ImageToLedsMap.h
${CURRENT_HEADER_DIR}/LedString.h ${CURRENT_HEADER_DIR}/LedString.h
${CURRENT_HEADER_DIR}/PriorityMuxer.h ${CURRENT_HEADER_DIR}/PriorityMuxer.h
${CURRENT_SOURCE_DIR}/MultiColorTransform.h ${CURRENT_SOURCE_DIR}/MultiColorTransform.h
${CURRENT_SOURCE_DIR}/MultiColorCorrection.h ${CURRENT_SOURCE_DIR}/MultiColorCorrection.h
${CURRENT_SOURCE_DIR}/MultiColorAdjustment.h ${CURRENT_SOURCE_DIR}/MultiColorAdjustment.h
${CURRENT_HEADER_DIR}/MessageForwarder.h ${CURRENT_HEADER_DIR}/MessageForwarder.h
) )
SET(Hyperion_SOURCES SET(Hyperion_SOURCES
${CURRENT_SOURCE_DIR}/Hyperion.cpp ${CURRENT_SOURCE_DIR}/Hyperion.cpp
${CURRENT_SOURCE_DIR}/ImageProcessor.cpp ${CURRENT_SOURCE_DIR}/ImageProcessor.cpp
${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp ${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp
${CURRENT_SOURCE_DIR}/LedString.cpp ${CURRENT_SOURCE_DIR}/LedString.cpp
${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp ${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp ${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp
${CURRENT_SOURCE_DIR}/MultiColorCorrection.cpp ${CURRENT_SOURCE_DIR}/MultiColorCorrection.cpp
${CURRENT_SOURCE_DIR}/MultiColorAdjustment.cpp ${CURRENT_SOURCE_DIR}/MultiColorAdjustment.cpp
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp
${CURRENT_SOURCE_DIR}/MessageForwarder.cpp ${CURRENT_SOURCE_DIR}/MessageForwarder.cpp
) )
set(Hyperion_RESOURCES SET(Hyperion_RESOURCES
${CURRENT_SOURCE_DIR}/resource.qrc ${CURRENT_SOURCE_DIR}/resource.qrc
) )
if(ENABLE_QT5) if(ENABLE_QT5)
QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
else(ENABLE_QT5) else()
QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
endif(ENABLE_QT5) endif()
add_library(hyperion add_library(hyperion
${Hyperion_HEADERS} ${Hyperion_HEADERS}
${Hyperion_QT_HEADERS} ${Hyperion_QT_HEADERS}
${Hyperion_HEADERS_MOC} ${Hyperion_HEADERS_MOC}
${Hyperion_SOURCES} ${Hyperion_SOURCES}
${Hyperion_RESOURCES_RCC} ${Hyperion_RESOURCES_RCC}
) )
if(ENABLE_QT5) if(ENABLE_QT5)
qt5_use_modules(hyperion Widgets) qt5_use_modules(hyperion Widgets)
endif(ENABLE_QT5) endif()
target_link_libraries(hyperion target_link_libraries(hyperion
blackborder blackborder
hyperion-utils hyperion-utils
leddevice leddevice
effectengine effectengine
serialport serialport
${QT_LIBRARIES} ${QT_LIBRARIES}
) )

View File

@ -1,382 +1,382 @@
{ {
"type" : "object", "type" : "object",
"required" : true, "required" : true,
"properties" : { "properties" : {
"device" : { "device" : {
"type" : "object", "type" : "object",
"required" : true, "required" : true,
"properties" : { "properties" : {
"name" : { "name" : {
"type" : "string", "type" : "string",
"required" : true "required" : true
}, },
"type" : { "type" : {
"type" : "string", "type" : "string",
"required" : true "required" : true
}, },
"output" : { "output" : {
"type" : "string", "type" : "string",
"required" : true "required" : true
}, },
"rate" : { "rate" : {
"type" : "integer", "type" : "integer",
"required" : true, "required" : true,
"minimum" : 0 "minimum" : 0
}, },
"colorOrder" : { "colorOrder" : {
"type" : "string", "type" : "string",
"required" : false "required" : false
}, },
"bgr-output" : { // deprecated "bgr-output" : { // deprecated
"type" : "boolean", "type" : "boolean",
"required" : false "required" : false
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"color": { "color": {
"type":"object", "type":"object",
"required":false, "required":false,
"properties": { "properties": {
"hsv" : { "hsv" : {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"saturationGain" : { "saturationGain" : {
"type" : "number", "type" : "number",
"required" : false, "required" : false,
"minimum" : 0.0 "minimum" : 0.0
}, },
"valueGain" : { "valueGain" : {
"type" : "number", "type" : "number",
"required" : false, "required" : false,
"minimum" : 0.0 "minimum" : 0.0
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"hsl" : { "hsl" : {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"saturationGain" : { "saturationGain" : {
"type" : "number", "type" : "number",
"required" : false, "required" : false,
"minimum" : 0.0 "minimum" : 0.0
}, },
"luminanceGain" : { "luminanceGain" : {
"type" : "number", "type" : "number",
"required" : false, "required" : false,
"minimum" : 0.0 "minimum" : 0.0
}, },
"luminanceMinimum" : { "luminanceMinimum" : {
"type" : "number", "type" : "number",
"required" : false, "required" : false,
"minimum" : 0.0 "minimum" : 0.0
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"red": { "red": {
"type":"object", "type":"object",
"required":false, "required":false,
"properties":{ "properties":{
"gamma": { "gamma": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"blacklevel": { "blacklevel": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"whitelevel": { "whitelevel": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"threshold": { "threshold": {
"type":"number", "type":"number",
"required":false, "required":false,
"minimum" : 0.0, "minimum" : 0.0,
"maximum" : 1.0 "maximum" : 1.0
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"green": { "green": {
"type":"object", "type":"object",
"required":false, "required":false,
"properties":{ "properties":{
"gamma": { "gamma": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"blacklevel": { "blacklevel": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"whitelevel": { "whitelevel": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"threshold": { "threshold": {
"type":"number", "type":"number",
"required":false, "required":false,
"minimum" : 0.0, "minimum" : 0.0,
"maximum" : 1.0 "maximum" : 1.0
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"blue": { "blue": {
"type":"object", "type":"object",
"required":false, "required":false,
"properties":{ "properties":{
"gamma": { "gamma": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"whitelevel": { "whitelevel": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"blacklevel": { "blacklevel": {
"type":"number", "type":"number",
"required":false "required":false
}, },
"threshold": { "threshold": {
"type":"number", "type":"number",
"required":false, "required":false,
"minimum" : 0.0, "minimum" : 0.0,
"maximum" : 1.0 "maximum" : 1.0
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"smoothing" : { "smoothing" : {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"type" : { "type" : {
"type" : "enum", "type" : "enum",
"required" : true, "required" : true,
"values" : ["none", "linear"] "values" : ["none", "linear"]
}, },
"time_ms" : { "time_ms" : {
"type" : "integer", "type" : "integer",
"required" : false, "required" : false,
"minimum" : 10 "minimum" : 10
}, },
"updateFrequency" : { "updateFrequency" : {
"type" : "number", "type" : "number",
"required" : false, "required" : false,
"minimum" : 0.001 "minimum" : 0.001
} }
}, },
"additionalProperties" : false "additionalProperties" : false
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"leds": { "leds": {
"type":"array", "type":"array",
"required":true, "required":true,
"items": { "items": {
"type":"object", "type":"object",
"properties": { "properties": {
"index": { "index": {
"type":"integer", "type":"integer",
"required":true "required":true
}, },
"hscan": { "hscan": {
"type":"object", "type":"object",
"required":true, "required":true,
"properties": { "properties": {
"minimum": { "minimum": {
"type":"number", "type":"number",
"required":true "required":true
}, },
"maximum": { "maximum": {
"type":"number", "type":"number",
"required":true "required":true
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"vscan": { "vscan": {
"type":"object", "type":"object",
"required":true, "required":true,
"properties": { "properties": {
"minimum": { "minimum": {
"type":"number", "type":"number",
"required":true "required":true
}, },
"maximum": { "maximum": {
"type":"number", "type":"number",
"required":true "required":true
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"colorOrder" : { "colorOrder" : {
"type" : "string", "type" : "string",
"required" : false "required" : false
} }
}, },
"additionalProperties" : false "additionalProperties" : false
} }
}, },
"effects" : "effects" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"paths" : { "paths" : {
"type" : "array", "type" : "array",
"required" : false, "required" : false,
"items" : { "items" : {
"type" : "string" "type" : "string"
} }
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"blackborderdetector" : "blackborderdetector" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"enable" : { "enable" : {
"type" : "boolean", "type" : "boolean",
"required" : true "required" : true
}, },
"threshold" : { "threshold" : {
"type" : "number", "type" : "number",
"required" : false, "required" : false,
"minimum" : 0.0, "minimum" : 0.0,
"maximum" : 1.0 "maximum" : 1.0
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"xbmcVideoChecker" : "xbmcVideoChecker" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"xbmcAddress" : { "xbmcAddress" : {
"type" : "string", "type" : "string",
"required" : true "required" : true
}, },
"xbmcTcpPort" : { "xbmcTcpPort" : {
"type" : "integer", "type" : "integer",
"required" : true "required" : true
}, },
"grabVideo" : { "grabVideo" : {
"type" : "boolean", "type" : "boolean",
"required" : true "required" : true
}, },
"grabPictures" : { "grabPictures" : {
"type" : "boolean", "type" : "boolean",
"required" : true "required" : true
}, },
"grabAudio" : { "grabAudio" : {
"type" : "boolean", "type" : "boolean",
"required" : true "required" : true
}, },
"grabMenu" : { "grabMenu" : {
"type" : "boolean", "type" : "boolean",
"required" : true "required" : true
}, },
"grabScreensaver" : { "grabScreensaver" : {
"type" : "boolean", "type" : "boolean",
"required" : false "required" : false
}, },
"enable3DDetection" : { "enable3DDetection" : {
"type" : "boolean", "type" : "boolean",
"required" : false "required" : false
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"bootsequence" : "bootsequence" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"path" : { "path" : {
"type" : "string", "type" : "string",
"required" : true "required" : true
}, },
"effect" : { "effect" : {
"type" : "string", "type" : "string",
"required" : true "required" : true
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"framegrabber" : "framegrabber" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"width" : { "width" : {
"type" : "integer", "type" : "integer",
"required" : true "required" : true
}, },
"height" : { "height" : {
"type" : "integer", "type" : "integer",
"required" : true "required" : true
}, },
"frequency_Hz" : { "frequency_Hz" : {
"type" : "integer", "type" : "integer",
"required" : true "required" : true
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"jsonServer" : "jsonServer" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"port" : { "port" : {
"type" : "integer", "type" : "integer",
"required" : true, "required" : true,
"minimum" : 0, "minimum" : 0,
"maximum" : 65535 "maximum" : 65535
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"protoServer" : "protoServer" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"port" : { "port" : {
"type" : "integer", "type" : "integer",
"required" : true, "required" : true,
"minimum" : 0, "minimum" : 0,
"maximum" : 65535 "maximum" : 65535
} }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
"boblightServer" : "boblightServer" :
{ {
"type" : "object", "type" : "object",
"required" : false, "required" : false,
"properties" : { "properties" : {
"port" : { "port" : {
"type" : "integer", "type" : "integer",
"required" : true, "required" : true,
"minimum" : 0, "minimum" : 0,
"maximum" : 65535 "maximum" : 65535
} }
}, },
"additionalProperties" : false "additionalProperties" : false
} }
}, },
"additionalProperties" : false "additionalProperties" : false
} }

View File

@ -1,48 +1,48 @@
# Define the current source locations # Define the current source locations
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/jsonserver) set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/jsonserver)
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/jsonserver) set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/jsonserver)
# Group the headers that go through the MOC compiler # Group the headers that go through the MOC compiler
set(JsonServer_QT_HEADERS set(JsonServer_QT_HEADERS
${CURRENT_HEADER_DIR}/JsonServer.h ${CURRENT_HEADER_DIR}/JsonServer.h
${CURRENT_SOURCE_DIR}/JsonClientConnection.h ${CURRENT_SOURCE_DIR}/JsonClientConnection.h
) )
set(JsonServer_HEADERS set(JsonServer_HEADERS
) )
set(JsonServer_SOURCES set(JsonServer_SOURCES
${CURRENT_SOURCE_DIR}/JsonServer.cpp ${CURRENT_SOURCE_DIR}/JsonServer.cpp
${CURRENT_SOURCE_DIR}/JsonClientConnection.cpp ${CURRENT_SOURCE_DIR}/JsonClientConnection.cpp
) )
set(JsonServer_RESOURCES set(JsonServer_RESOURCES
${CURRENT_SOURCE_DIR}/JsonSchemas.qrc ${CURRENT_SOURCE_DIR}/JsonSchemas.qrc
) )
if(ENABLE_QT5) if(ENABLE_QT5)
qt5_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS}) qt5_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS})
qt5_add_resources(JsonServer_RESOURCES_RCC ${JsonServer_RESOURCES} OPTIONS "-no-compress") qt5_add_resources(JsonServer_RESOURCES_RCC ${JsonServer_RESOURCES} OPTIONS "-no-compress")
else(ENABLE_QT5) else()
qt4_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS}) qt4_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS})
qt4_add_resources(JsonServer_RESOURCES_RCC ${JsonServer_RESOURCES} OPTIONS "-no-compress") qt4_add_resources(JsonServer_RESOURCES_RCC ${JsonServer_RESOURCES} OPTIONS "-no-compress")
endif(ENABLE_QT5) endif()
add_library(jsonserver add_library(jsonserver
${JsonServer_HEADERS} ${JsonServer_HEADERS}
${JsonServer_QT_HEADERS} ${JsonServer_QT_HEADERS}
${JsonServer_SOURCES} ${JsonServer_SOURCES}
${JsonServer_RESOURCES} ${JsonServer_RESOURCES}
${JsonServer_HEADERS_MOC} ${JsonServer_HEADERS_MOC}
${JsonServer_RESOURCES_RCC} ${JsonServer_RESOURCES_RCC}
) )
if(ENABLE_QT5) if(ENABLE_QT5)
qt5_use_modules(jsonserver Widgets Network) qt5_use_modules(jsonserver Widgets Network)
endif(ENABLE_QT5) endif()
target_link_libraries(jsonserver target_link_libraries(jsonserver
hyperion hyperion
hyperion-utils hyperion-utils
jsoncpp jsoncpp
${QT_LIBRARIES}) ${QT_LIBRARIES})

View File

@ -1,165 +1,166 @@
# Define the current source locations # Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/leddevice) SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/leddevice)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/leddevice) SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/leddevice)
#add libusb and pthreads (required for the Lighpack usb device) #add libusb and pthreads (required for the Lighpack usb device)
find_package(libusb-1.0 REQUIRED) find_package(libusb-1.0 REQUIRED)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
include_directories( include_directories(
../../include/hidapi ../../include/hidapi
${LIBUSB_1_INCLUDE_DIRS}) # for Lightpack device ${LIBUSB_1_INCLUDE_DIRS}
) # for Lightpack device
# Group the headers that go through the MOC compiler
SET(Leddevice_QT_HEADERS # Group the headers that go through the MOC compiler
${CURRENT_SOURCE_DIR}/LedRs232Device.h SET(Leddevice_QT_HEADERS
${CURRENT_SOURCE_DIR}/LedDeviceAdalight.h ${CURRENT_SOURCE_DIR}/LedRs232Device.h
${CURRENT_SOURCE_DIR}/LedDeviceAdalightApa102.h ${CURRENT_SOURCE_DIR}/LedDeviceAdalight.h
${CURRENT_SOURCE_DIR}/LedDeviceAmbiLed.h ${CURRENT_SOURCE_DIR}/LedDeviceAdalightApa102.h
${CURRENT_SOURCE_DIR}/LedDeviceAtmoOrb.h ${CURRENT_SOURCE_DIR}/LedDeviceAmbiLed.h
${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.h ${CURRENT_SOURCE_DIR}/LedDeviceAtmoOrb.h
${CURRENT_SOURCE_DIR}/LedHIDDevice.h ${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.h
${CURRENT_SOURCE_DIR}/LedDeviceRawHID.h ${CURRENT_SOURCE_DIR}/LedHIDDevice.h
${CURRENT_SOURCE_DIR}/LedDeviceFile.h ${CURRENT_SOURCE_DIR}/LedDeviceRawHID.h
${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h ${CURRENT_SOURCE_DIR}/LedDeviceFile.h
) ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h
)
SET(Leddevice_HEADERS
${CURRENT_HEADER_DIR}/LedDevice.h SET(Leddevice_HEADERS
${CURRENT_HEADER_DIR}/LedDeviceFactory.h ${CURRENT_HEADER_DIR}/LedDevice.h
${CURRENT_HEADER_DIR}/LedDeviceFactory.h
${CURRENT_SOURCE_DIR}/LedDeviceLightpack.h
${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.h ${CURRENT_SOURCE_DIR}/LedDeviceLightpack.h
${CURRENT_SOURCE_DIR}/LedDevicePaintpack.h ${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.h
${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.h ${CURRENT_SOURCE_DIR}/LedDevicePaintpack.h
${CURRENT_SOURCE_DIR}/LedDeviceSedu.h ${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.h
${CURRENT_SOURCE_DIR}/LedDeviceFile.h ${CURRENT_SOURCE_DIR}/LedDeviceSedu.h
${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h ${CURRENT_SOURCE_DIR}/LedDeviceFile.h
${CURRENT_SOURCE_DIR}/LedDeviceUdp.h ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h
${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h ${CURRENT_SOURCE_DIR}/LedDeviceUdp.h
${CURRENT_SOURCE_DIR}/LedDeviceTpm2.h ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h
${CURRENT_SOURCE_DIR}/LedDeviceAtmo.h ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.h
) ${CURRENT_SOURCE_DIR}/LedDeviceAtmo.h
)
SET(Leddevice_SOURCES
${CURRENT_SOURCE_DIR}/LedDeviceFactory.cpp SET(Leddevice_SOURCES
${CURRENT_SOURCE_DIR}/LedDeviceFactory.cpp
${CURRENT_SOURCE_DIR}/LedRs232Device.cpp
${CURRENT_SOURCE_DIR}/LedHIDDevice.cpp ${CURRENT_SOURCE_DIR}/LedRs232Device.cpp
${CURRENT_SOURCE_DIR}/LedHIDDevice.cpp
${CURRENT_SOURCE_DIR}/LedDeviceAdalight.cpp
${CURRENT_SOURCE_DIR}/LedDeviceAdalightApa102.cpp ${CURRENT_SOURCE_DIR}/LedDeviceAdalight.cpp
${CURRENT_SOURCE_DIR}/LedDeviceAmbiLed.cpp ${CURRENT_SOURCE_DIR}/LedDeviceAdalightApa102.cpp
${CURRENT_SOURCE_DIR}/LedDeviceAtmoOrb.cpp ${CURRENT_SOURCE_DIR}/LedDeviceAmbiLed.cpp
${CURRENT_SOURCE_DIR}/LedDeviceRawHID.cpp ${CURRENT_SOURCE_DIR}/LedDeviceAtmoOrb.cpp
${CURRENT_SOURCE_DIR}/LedDeviceLightpack.cpp ${CURRENT_SOURCE_DIR}/LedDeviceRawHID.cpp
${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.cpp ${CURRENT_SOURCE_DIR}/LedDeviceLightpack.cpp
${CURRENT_SOURCE_DIR}/LedDevicePaintpack.cpp ${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.cpp
${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.cpp ${CURRENT_SOURCE_DIR}/LedDevicePaintpack.cpp
${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp ${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.cpp
${CURRENT_SOURCE_DIR}/LedDeviceFile.cpp ${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp
${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.cpp ${CURRENT_SOURCE_DIR}/LedDeviceFile.cpp
${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.cpp
${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp ${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp
${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp
${CURRENT_SOURCE_DIR}/LedDeviceTpm2.cpp ${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp
${CURRENT_SOURCE_DIR}/LedDeviceAtmo.cpp ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.cpp
) ${CURRENT_SOURCE_DIR}/LedDeviceAtmo.cpp
)
if(ENABLE_SPIDEV)
SET(Leddevice_HEADERS if(ENABLE_SPIDEV)
${Leddevice_HEADERS} SET(Leddevice_HEADERS
${CURRENT_SOURCE_DIR}/LedSpiDevice.h ${Leddevice_HEADERS}
${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.h ${CURRENT_SOURCE_DIR}/LedSpiDevice.h
${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.h ${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.h
${CURRENT_SOURCE_DIR}/LedDeviceP9813.h ${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.h
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h ${CURRENT_SOURCE_DIR}/LedDeviceP9813.h
${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.h ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h
${CURRENT_SOURCE_DIR}/LedDeviceAPA102.h ${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.h
) ${CURRENT_SOURCE_DIR}/LedDeviceAPA102.h
SET(Leddevice_SOURCES )
${Leddevice_SOURCES} SET(Leddevice_SOURCES
${CURRENT_SOURCE_DIR}/LedSpiDevice.cpp ${Leddevice_SOURCES}
${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.cpp ${CURRENT_SOURCE_DIR}/LedSpiDevice.cpp
${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.cpp ${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.cpp
${CURRENT_SOURCE_DIR}/LedDeviceP9813.cpp ${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.cpp
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp ${CURRENT_SOURCE_DIR}/LedDeviceP9813.cpp
${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.cpp ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp
${CURRENT_SOURCE_DIR}/LedDeviceAPA102.cpp ${CURRENT_SOURCE_DIR}/LedDeviceWs2812SPI.cpp
) ${CURRENT_SOURCE_DIR}/LedDeviceAPA102.cpp
endif(ENABLE_SPIDEV) )
endif()
if(ENABLE_WS2812BPWM)
SET(Leddevice_HEADERS if(ENABLE_WS2812BPWM)
${Leddevice_HEADERS} SET(Leddevice_HEADERS
${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.h ${Leddevice_HEADERS}
) ${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.h
SET(Leddevice_SOURCES )
${Leddevice_SOURCES} SET(Leddevice_SOURCES
${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.cpp ${Leddevice_SOURCES}
) ${CURRENT_SOURCE_DIR}/LedDeviceWS2812b.cpp
endif(ENABLE_WS2812BPWM) )
endif()
if(ENABLE_WS281XPWM)
include_directories(../../dependencies/external/rpi_ws281x) if(ENABLE_WS281XPWM)
SET(Leddevice_HEADERS include_directories(../../dependencies/external/rpi_ws281x)
${Leddevice_HEADERS} SET(Leddevice_HEADERS
${CURRENT_SOURCE_DIR}/LedDeviceWS281x.h ${Leddevice_HEADERS}
) ${CURRENT_SOURCE_DIR}/LedDeviceWS281x.h
SET(Leddevice_SOURCES )
${Leddevice_SOURCES} SET(Leddevice_SOURCES
${CURRENT_SOURCE_DIR}/LedDeviceWS281x.cpp ${Leddevice_SOURCES}
) ${CURRENT_SOURCE_DIR}/LedDeviceWS281x.cpp
endif(ENABLE_WS281XPWM) )
endif()
if(ENABLE_TINKERFORGE)
SET(Leddevice_HEADERS if(ENABLE_TINKERFORGE)
${Leddevice_HEADERS} SET(Leddevice_HEADERS
${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.h ${Leddevice_HEADERS}
) ${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.h
SET(Leddevice_SOURCES )
${Leddevice_SOURCES} SET(Leddevice_SOURCES
${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.cpp ${Leddevice_SOURCES}
) ${CURRENT_SOURCE_DIR}/LedDeviceTinkerforge.cpp
endif(ENABLE_TINKERFORGE) )
endif()
if(ENABLE_QT5)
QT5_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS}) if(ENABLE_QT5)
else(ENABLE_QT5) QT5_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS})
QT4_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS}) else()
endif(ENABLE_QT5) QT4_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS})
endif()
add_library(leddevice
${Leddevice_HEADERS} add_library(leddevice
${Leddevice_QT_HEADERS} ${Leddevice_HEADERS}
${Leddevice_HEADERS_MOC} ${Leddevice_QT_HEADERS}
${Leddevice_SOURCES} ${Leddevice_HEADERS_MOC}
) ${Leddevice_SOURCES}
)
if(ENABLE_QT5)
qt5_use_modules(leddevice Widgets Network) if(ENABLE_QT5)
endif(ENABLE_QT5) qt5_use_modules(leddevice Widgets Network)
endif()
target_link_libraries(leddevice
hyperion-utils target_link_libraries(leddevice
serialport hyperion-utils
${LIBUSB_1_LIBRARIES} #apt-get install libusb-1.0-0-dev serialport
${CMAKE_THREAD_LIBS_INIT} ${LIBUSB_1_LIBRARIES} #apt-get install libusb-1.0-0-dev
${QT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
) ${QT_LIBRARIES}
)
if(ENABLE_TINKERFORGE)
target_link_libraries(leddevice tinkerforge) if(ENABLE_TINKERFORGE)
endif() target_link_libraries(leddevice tinkerforge)
endif()
if(ENABLE_WS281XPWM)
target_link_libraries(leddevice ws281x) if(ENABLE_WS281XPWM)
endif() target_link_libraries(leddevice ws281x)
endif()
if(APPLE)
target_link_libraries(leddevice hidapi-mac) if(APPLE)
else() target_link_libraries(leddevice hidapi-mac)
target_link_libraries(leddevice hidapi-libusb) else()
endif() target_link_libraries(leddevice hidapi-libusb)
endif()

View File

@ -1,152 +1,158 @@
// Local-Hyperion includes // Local-Hyperion includes
#include "LedDeviceAtmoOrb.h" #include "LedDeviceAtmoOrb.h"
// qt includes // qt includes
#include <QtCore/qmath.h> #include <QtCore/qmath.h>
#include <QEventLoop> #include <QEventLoop>
#include <QtNetwork> #include <QtNetwork>
#include <QNetworkReply> #include <QNetworkReply>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <set> #include <set>
AtmoOrbLight::AtmoOrbLight(unsigned int id) { AtmoOrbLight::AtmoOrbLight(unsigned int id) {
// Not implemented // Not implemented
} }
LedDeviceAtmoOrb::LedDeviceAtmoOrb(const std::string &output, bool useOrbSmoothing, LedDeviceAtmoOrb::LedDeviceAtmoOrb(
int transitiontime, int skipSmoothingDiff, int port, int numLeds, std::vector<unsigned int> orbIds) : const std::string &output,
multicastGroup(output.c_str()), useOrbSmoothing(useOrbSmoothing), transitiontime(transitiontime), skipSmoothingDiff(skipSmoothingDiff), bool useOrbSmoothing,
multiCastGroupPort(port), numLeds(numLeds), orbIds(orbIds) { int transitiontime,
manager = new QNetworkAccessManager(); int skipSmoothingDiff,
groupAddress = QHostAddress(multicastGroup); int port,
int numLeds,
udpSocket = new QUdpSocket(this); std::vector<unsigned int> orbIds) :
udpSocket->bind(multiCastGroupPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); multicastGroup(output.c_str()), useOrbSmoothing(useOrbSmoothing), transitiontime(transitiontime), skipSmoothingDiff(skipSmoothingDiff),
multiCastGroupPort(port), numLeds(numLeds), orbIds(orbIds)
joinedMulticastgroup = udpSocket->joinMulticastGroup(groupAddress); {
} manager = new QNetworkAccessManager();
groupAddress = QHostAddress(multicastGroup);
int LedDeviceAtmoOrb::write(const std::vector <ColorRgb> &ledValues) {
udpSocket = new QUdpSocket(this);
// If not in multicast group return udpSocket->bind(multiCastGroupPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
if (!joinedMulticastgroup) {
return 0; joinedMulticastgroup = udpSocket->joinMulticastGroup(groupAddress);
} }
// Command options: int LedDeviceAtmoOrb::write(const std::vector <ColorRgb> &ledValues) {
// // If not in multicast group return
// 1 = force off if (!joinedMulticastgroup) {
// 2 = use lamp smoothing and validate by Orb ID return 0;
// 4 = validate by Orb ID }
// When setting useOrbSmoothing = true it's recommended to disable Hyperion's own smoothing as it will conflict (double smoothing) // Command options:
int commandType = 4; //
if(useOrbSmoothing) // 1 = force off
{ // 2 = use lamp smoothing and validate by Orb ID
commandType = 2; // 4 = validate by Orb ID
}
// When setting useOrbSmoothing = true it's recommended to disable Hyperion's own smoothing as it will conflict (double smoothing)
// Iterate through colors and set Orb color int commandType = 4;
// Start off with idx 1 as 0 is reserved for controlling all orbs at once if(useOrbSmoothing)
unsigned int idx = 1; {
commandType = 2;
for (const ColorRgb &color : ledValues) { }
// Retrieve last send colors
int lastRed = lastColorRedMap[idx]; // Iterate through colors and set Orb color
int lastGreen = lastColorGreenMap[idx]; // Start off with idx 1 as 0 is reserved for controlling all orbs at once
int lastBlue = lastColorBlueMap[idx]; unsigned int idx = 1;
// If color difference is higher than skipSmoothingDiff than we skip Orb smoothing (if enabled) and send it right away for (const ColorRgb &color : ledValues) {
if ((skipSmoothingDiff != 0 && useOrbSmoothing) && (abs(color.red - lastRed) >= skipSmoothingDiff || abs(color.blue - lastBlue) >= skipSmoothingDiff || // Retrieve last send colors
abs(color.green - lastGreen) >= skipSmoothingDiff)) int lastRed = lastColorRedMap[idx];
{ int lastGreen = lastColorGreenMap[idx];
// Skip Orb smoothing when using (command type 4) int lastBlue = lastColorBlueMap[idx];
for (unsigned int i = 0; i < orbIds.size(); i++) {
if (orbIds[i] == idx) { // If color difference is higher than skipSmoothingDiff than we skip Orb smoothing (if enabled) and send it right away
setColor(idx, color, 4); 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)
else { for (unsigned int i = 0; i < orbIds.size(); i++) {
// Send color if (orbIds[i] == idx) {
for (unsigned int i = 0; i < orbIds.size(); i++) { setColor(idx, color, 4);
if (orbIds[i] == idx) { }
setColor(idx, color, commandType); }
} }
} else {
} // Send color
for (unsigned int i = 0; i < orbIds.size(); i++) {
// Store last colors send for light id if (orbIds[i] == idx) {
lastColorRedMap[idx] = color.red; setColor(idx, color, commandType);
lastColorGreenMap[idx] = color.green; }
lastColorBlueMap[idx] = color.blue; }
}
// Next light id.
idx++; // Store last colors send for light id
} lastColorRedMap[idx] = color.red;
lastColorGreenMap[idx] = color.green;
return 0; lastColorBlueMap[idx] = color.blue;
}
// Next light id.
void LedDeviceAtmoOrb::setColor(unsigned int orbId, const ColorRgb &color, int commandType) { idx++;
QByteArray bytes; }
bytes.resize(5 + numLeds * 3);
bytes.fill('\0'); return 0;
}
// Command identifier: C0FFEE
bytes[0] = 0xC0; void LedDeviceAtmoOrb::setColor(unsigned int orbId, const ColorRgb &color, int commandType) {
bytes[1] = 0xFF; QByteArray bytes;
bytes[2] = 0xEE; bytes.resize(5 + numLeds * 3);
bytes.fill('\0');
// Command type
bytes[3] = commandType; // Command identifier: C0FFEE
bytes[0] = 0xC0;
// Orb ID bytes[1] = 0xFF;
bytes[4] = orbId; bytes[2] = 0xEE;
// RED / GREEN / BLUE // Command type
bytes[5] = color.red; bytes[3] = commandType;
bytes[6] = color.green;
bytes[7] = color.blue; // Orb ID
bytes[4] = orbId;
sendCommand(bytes);
} // RED / GREEN / BLUE
bytes[5] = color.red;
void LedDeviceAtmoOrb::sendCommand(const QByteArray &bytes) { bytes[6] = color.green;
QByteArray datagram = bytes; bytes[7] = color.blue;
udpSocket->writeDatagram(datagram.data(), datagram.size(),
groupAddress, multiCastGroupPort); sendCommand(bytes);
} }
int LedDeviceAtmoOrb::switchOff() { void LedDeviceAtmoOrb::sendCommand(const QByteArray &bytes) {
for (unsigned int i = 0; i < orbIds.size(); i++) { QByteArray datagram = bytes;
QByteArray bytes; udpSocket->writeDatagram(datagram.data(), datagram.size(),
bytes.resize(5 + numLeds * 3); groupAddress, multiCastGroupPort);
bytes.fill('\0'); }
// Command identifier: C0FFEE int LedDeviceAtmoOrb::switchOff() {
bytes[0] = 0xC0; for (unsigned int i = 0; i < orbIds.size(); i++) {
bytes[1] = 0xFF; QByteArray bytes;
bytes[2] = 0xEE; bytes.resize(5 + numLeds * 3);
bytes.fill('\0');
// Command type
bytes[3] = 1; // Command identifier: C0FFEE
bytes[0] = 0xC0;
// Orb ID bytes[1] = 0xFF;
bytes[4] = orbIds[i]; bytes[2] = 0xEE;
// RED / GREEN / BLUE // Command type
bytes[5] = 0; bytes[3] = 1;
bytes[6] = 0;
bytes[7] = 0; // Orb ID
bytes[4] = orbIds[i];
sendCommand(bytes);
} // RED / GREEN / BLUE
return 0; bytes[5] = 0;
} bytes[6] = 0;
bytes[7] = 0;
LedDeviceAtmoOrb::~LedDeviceAtmoOrb() {
delete manager; sendCommand(bytes);
} }
return 0;
}
LedDeviceAtmoOrb::~LedDeviceAtmoOrb() {
delete manager;
}

View File

@ -1,132 +1,132 @@
#pragma once #pragma once
// STL includes // STL includes
#include <string> #include <string>
// Qt includes // Qt includes
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QHostAddress> #include <QHostAddress>
// Leddevice includes // Leddevice includes
#include <leddevice/LedDevice.h> #include <leddevice/LedDevice.h>
class QUdpSocket; class QUdpSocket;
class AtmoOrbLight { class AtmoOrbLight {
public: public:
unsigned int id; unsigned int id;
/// ///
/// Constructs the light. /// Constructs the light.
/// ///
/// @param id the orb id /// @param id the orb id
AtmoOrbLight(unsigned int id); AtmoOrbLight(unsigned int id);
}; };
/** /**
* Implementation for the AtmoOrb * Implementation for the AtmoOrb
* *
* To use set the device to "atmoorb". * To use set the device to "atmoorb".
* *
* @author RickDB (github) * @author RickDB (github)
*/ */
class LedDeviceAtmoOrb : public QObject, public LedDevice { class LedDeviceAtmoOrb : public QObject, public LedDevice {
Q_OBJECT Q_OBJECT
public: public:
// Last send color map // Last send color map
QMap<int, int> lastColorRedMap; QMap<int, int> lastColorRedMap;
QMap<int, int> lastColorGreenMap; QMap<int, int> lastColorGreenMap;
QMap<int, int> lastColorBlueMap; QMap<int, int> lastColorBlueMap;
// Multicast status // Multicast status
bool joinedMulticastgroup; bool joinedMulticastgroup;
/// ///
/// Constructs the device. /// Constructs the device.
/// ///
/// @param output is the multicast address of Orbs /// @param output is the multicast address of Orbs
/// ///
/// @param transitiontime is optional and not used at the moment /// @param transitiontime is optional and not used at the moment
/// ///
/// @param useOrbSmoothing use Orbs own (external) smoothing algorithm (default: false) /// @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 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 port is the multicast port.
/// ///
/// @param numLeds is the total amount of leds per Orb /// @param numLeds is the total amount of leds per Orb
/// ///
/// @param array containing orb ids /// @param array containing orb ids
/// ///
LedDeviceAtmoOrb(const std::string &output, bool useOrbSmoothing = LedDeviceAtmoOrb(const std::string &output, bool useOrbSmoothing =
false, int transitiontime = 0, int skipSmoothingDiff = 0, int port = 49692, int numLeds = 24, false, int transitiontime = 0, int skipSmoothingDiff = 0, int port = 49692, int numLeds = 24,
std::vector<unsigned int> orbIds = std::vector < unsigned int>()); std::vector<unsigned int> orbIds = std::vector < unsigned int>());
/// ///
/// Destructor of this device /// Destructor of this device
/// ///
virtual ~LedDeviceAtmoOrb(); virtual ~LedDeviceAtmoOrb();
/// ///
/// Sends the given led-color values to the Orbs /// Sends the given led-color values to the Orbs
/// ///
/// @param ledValues The color-value per led /// @param ledValues The color-value per led
/// ///
/// @return Zero on success else negative /// @return Zero on success else negative
/// ///
virtual int write(const std::vector <ColorRgb> &ledValues); virtual int write(const std::vector <ColorRgb> &ledValues);
virtual int switchOff(); virtual int switchOff();
private: private:
/// QNetworkAccessManager object for sending requests. /// QNetworkAccessManager object for sending requests.
QNetworkAccessManager *manager; QNetworkAccessManager *manager;
/// String containing multicast group IP address /// String containing multicast group IP address
QString multicastGroup; QString multicastGroup;
/// use Orbs own (external) smoothing algorithm /// use Orbs own (external) smoothing algorithm
bool useOrbSmoothing; bool useOrbSmoothing;
/// Transition time between colors (not implemented) /// Transition time between colors (not implemented)
int transitiontime; int transitiontime;
// Maximum allowed color difference, will skip Orb (external) smoothing once reached // Maximum allowed color difference, will skip Orb (external) smoothing once reached
int skipSmoothingDiff; int skipSmoothingDiff;
/// Multicast port to send data to /// Multicast port to send data to
int multiCastGroupPort; int multiCastGroupPort;
/// Number of leds in Orb, used to determine buffer size /// Number of leds in Orb, used to determine buffer size
int numLeds; int numLeds;
/// QHostAddress object of multicast group IP address /// QHostAddress object of multicast group IP address
QHostAddress groupAddress; QHostAddress groupAddress;
/// QUdpSocket object used to send data over /// QUdpSocket object used to send data over
QUdpSocket *udpSocket; QUdpSocket *udpSocket;
/// Array of the orb ids. /// Array of the orb ids.
std::vector<unsigned int> orbIds; std::vector<unsigned int> orbIds;
/// ///
/// Set Orbcolor /// Set Orbcolor
/// ///
/// @param orbId the orb id /// @param orbId the orb id
/// ///
/// @param color which color to set /// @param color which color to set
/// ///
/// ///
/// @param commandType which type of command to send (off / smoothing / etc..) /// @param commandType which type of command to send (off / smoothing / etc..)
/// ///
void setColor(unsigned int orbId, const ColorRgb &color, int commandType); void setColor(unsigned int orbId, const ColorRgb &color, int commandType);
/// ///
/// Send Orb command /// Send Orb command
/// ///
/// @param bytes the byte array containing command to send over multicast /// @param bytes the byte array containing command to send over multicast
/// ///
void sendCommand(const QByteArray &bytes); void sendCommand(const QByteArray &bytes);
}; };

View File

@ -1,50 +1,50 @@
// STL includes // STL includes
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
// Linux includes // Linux includes
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
// hyperion local includes // hyperion local includes
#include "LedDeviceLpd6803.h" #include "LedDeviceLpd6803.h"
LedDeviceLpd6803::LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate) : LedDeviceLpd6803::LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate) :
LedSpiDevice(outputDevice, baudrate), LedSpiDevice(outputDevice, baudrate),
_ledBuffer(0) _ledBuffer(0)
{ {
// empty // empty
} }
int LedDeviceLpd6803::write(const std::vector<ColorRgb> &ledValues) int LedDeviceLpd6803::write(const std::vector<ColorRgb> &ledValues)
{ {
unsigned messageLength = 4 + 2*ledValues.size() + ledValues.size()/8 + 1; unsigned messageLength = 4 + 2*ledValues.size() + ledValues.size()/8 + 1;
// Reconfigure if the current connfiguration does not match the required configuration // Reconfigure if the current connfiguration does not match the required configuration
if (messageLength != _ledBuffer.size()) if (messageLength != _ledBuffer.size())
{ {
// Initialise the buffer // Initialise the buffer
_ledBuffer.resize(messageLength, 0x00); _ledBuffer.resize(messageLength, 0x00);
} }
// Copy the colors from the ColorRgb vector to the Ldp6803 data vector // Copy the colors from the ColorRgb vector to the Ldp6803 data vector
for (unsigned iLed=0; iLed<ledValues.size(); ++iLed) for (unsigned iLed=0; iLed<ledValues.size(); ++iLed)
{ {
const ColorRgb& rgb = ledValues[iLed]; const ColorRgb& rgb = ledValues[iLed];
_ledBuffer[4 + 2 * iLed] = 0x80 | ((rgb.red & 0xf8) >> 1) | (rgb.green >> 6); _ledBuffer[4 + 2 * iLed] = 0x80 | ((rgb.red & 0xf8) >> 1) | (rgb.green >> 6);
_ledBuffer[5 + 2 * iLed] = ((rgb.green & 0x38) << 2) | (rgb.blue >> 3); _ledBuffer[5 + 2 * iLed] = ((rgb.green & 0x38) << 2) | (rgb.blue >> 3);
} }
// Write the data // Write the data
if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0) if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0)
{ {
return -1; return -1;
} }
return 0; return 0;
} }
int LedDeviceLpd6803::switchOff() int LedDeviceLpd6803::switchOff()
{ {
return write(std::vector<ColorRgb>(_ledBuffer.size(), ColorRgb{0,0,0})); return write(std::vector<ColorRgb>(_ledBuffer.size(), ColorRgb{0,0,0}));
} }

View File

@ -1,42 +1,42 @@
#pragma once #pragma once
// Local hyperion incluse // Local hyperion incluse
#include "LedSpiDevice.h" #include "LedSpiDevice.h"
/// ///
/// Implementation of the LedDevice interface for writing to LDP6803 led device. /// Implementation of the LedDevice interface for writing to LDP6803 led device.
/// ///
/// 00000000 00000000 00000000 00000000 1RRRRRGG GGGBBBBB 1RRRRRGG GGGBBBBB ... /// 00000000 00000000 00000000 00000000 1RRRRRGG GGGBBBBB 1RRRRRGG GGGBBBBB ...
/// |---------------------------------| |---------------| |---------------| /// |---------------------------------| |---------------| |---------------|
/// 32 zeros to start the frame Led1 Led2 ... /// 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 /// 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 /// (R, G and B in the above illustration) making 16 bits per led. Total bytes = 4 + (2 x number of
/// leds) /// leds)
/// ///
class LedDeviceLpd6803 : public LedSpiDevice class LedDeviceLpd6803 : public LedSpiDevice
{ {
public: public:
/// ///
/// Constructs the LedDevice for a string containing leds of the type LDP6803 /// 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] outputDevice The name of the output device (eg '/dev/spidev0.0')
/// @param[in] baudrate The used baudrate for writing to the output device /// @param[in] baudrate The used baudrate for writing to the output device
/// ///
LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate); LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate);
/// ///
/// Writes the led color values to the led-device /// Writes the led color values to the led-device
/// ///
/// @param ledValues The color-value per led /// @param ledValues The color-value per led
/// @return Zero on succes else negative /// @return Zero on succes else negative
/// ///
virtual int write(const std::vector<ColorRgb> &ledValues); virtual int write(const std::vector<ColorRgb> &ledValues);
/// Switch the leds off /// Switch the leds off
virtual int switchOff(); virtual int switchOff();
private: private:
/// The buffer containing the packed RGB values /// The buffer containing the packed RGB values
std::vector<uint8_t> _ledBuffer; std::vector<uint8_t> _ledBuffer;
}; };

View File

@ -1,54 +1,54 @@
// STL includes // STL includes
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
// Linux includes // Linux includes
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
// hyperion local includes // hyperion local includes
#include "LedDeviceLpd8806.h" #include "LedDeviceLpd8806.h"
LedDeviceLpd8806::LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate) : LedDeviceLpd8806::LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate) :
LedSpiDevice(outputDevice, baudrate), LedSpiDevice(outputDevice, baudrate),
_ledBuffer(0) _ledBuffer(0)
{ {
// empty // empty
} }
int LedDeviceLpd8806::write(const std::vector<ColorRgb> &ledValues) int LedDeviceLpd8806::write(const std::vector<ColorRgb> &ledValues)
{ {
const unsigned clearSize = ledValues.size()/32+1; const unsigned clearSize = ledValues.size()/32+1;
// Reconfigure if the current connfiguration does not match the required configuration // Reconfigure if the current connfiguration does not match the required configuration
if (3*ledValues.size() + clearSize != _ledBuffer.size()) if (3*ledValues.size() + clearSize != _ledBuffer.size())
{ {
// Initialise the buffer // Initialise the buffer
_ledBuffer.resize(3*ledValues.size() + clearSize, 0x00); _ledBuffer.resize(3*ledValues.size() + clearSize, 0x00);
// Perform an initial reset to start accepting data on the first led // Perform an initial reset to start accepting data on the first led
writeBytes(clearSize, _ledBuffer.data()); writeBytes(clearSize, _ledBuffer.data());
} }
// Copy the colors from the ColorRgb vector to the Ldp8806 data vector // Copy the colors from the ColorRgb vector to the Ldp8806 data vector
for (unsigned iLed=0; iLed<ledValues.size(); ++iLed) for (unsigned iLed=0; iLed<ledValues.size(); ++iLed)
{ {
const ColorRgb& rgb = ledValues[iLed]; const ColorRgb& rgb = ledValues[iLed];
_ledBuffer[iLed*3] = 0x80 | (rgb.red >> 1); _ledBuffer[iLed*3] = 0x80 | (rgb.red >> 1);
_ledBuffer[iLed*3+1] = 0x80 | (rgb.green >> 1); _ledBuffer[iLed*3+1] = 0x80 | (rgb.green >> 1);
_ledBuffer[iLed*3+2] = 0x80 | (rgb.blue >> 1); _ledBuffer[iLed*3+2] = 0x80 | (rgb.blue >> 1);
} }
// Write the data // Write the data
if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0) if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0)
{ {
return -1; return -1;
} }
return 0; return 0;
} }
int LedDeviceLpd8806::switchOff() int LedDeviceLpd8806::switchOff()
{ {
return write(std::vector<ColorRgb>(_ledBuffer.size(), ColorRgb{0,0,0})); return write(std::vector<ColorRgb>(_ledBuffer.size(), ColorRgb{0,0,0}));
} }

View File

@ -1,103 +1,103 @@
#pragma once #pragma once
// Local hyperion incluse // Local hyperion incluse
#include "LedSpiDevice.h" #include "LedSpiDevice.h"
/// ///
/// Implementation of the LedDevice interface for writing to LPD8806 led device. /// Implementation of the LedDevice interface for writing to LPD8806 led device.
/// ///
/// The following description is copied from 'adafruit' (github.com/adafruit/LPD8806) /// The following description is copied from 'adafruit' (github.com/adafruit/LPD8806)
/// ///
/// Clearing up some misconceptions about how the LPD8806 drivers work: /// Clearing up some misconceptions about how the LPD8806 drivers work:
/// ///
/// The LPD8806 is not a FIFO shift register. The first data out controls the /// 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 /// 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' /// 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 /// with data and then passes through all subsequent bytes until a latch
/// condition takes place. This is actually pretty common among LED drivers. /// condition takes place. This is actually pretty common among LED drivers.
/// ///
/// All color data bytes have the high bit (128) set, with the remaining /// 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 /// seven bits containing a brightness value (0-127). A byte with the high
/// bit clear has special meaning (explained later). /// bit clear has special meaning (explained later).
/// ///
/// The rest gets bizarre... /// The rest gets bizarre...
/// ///
/// The LPD8806 does not perform an in-unison latch (which would display the /// The LPD8806 does not perform an in-unison latch (which would display the
/// newly-transmitted data all at once). Rather, each individual byte (even /// 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... /// 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 /// 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 passed through. So the strip actually refreshes at the speed the data
/// is issued, not instantaneously (this can be observed by greatly reducing /// is issued, not instantaneously (this can be observed by greatly reducing
/// the data rate). This has implications for POV displays and light painting /// the data rate). This has implications for POV displays and light painting
/// applications. The 'subsequent' rule also means that at least one extra /// 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. /// 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 /// 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 /// 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 /// 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 /// 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 /// 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 /// LEDs) down the line before needing backup; the next meter requires an
/// extra zero byte, and so forth. Longer strips will require progressively /// extra zero byte, and so forth. Longer strips will require progressively
/// more zeros. *(see note below) /// more zeros. *(see note below)
/// ///
/// In the interest of efficiency, it's possible to combine the former EOD /// 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 /// 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 /// duty, latching the last blue LED while also resetting the strip for the
/// next payload. /// next payload.
/// ///
/// So: reset byte(s) of suitable length are issued once at startup to 'prime' /// 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, /// 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 /// 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 /// 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 /// (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 /// of latency as the new color payload can begin issuing immediately on some
/// signal, such as a timer or GPIO trigger. /// signal, such as a timer or GPIO trigger.
/// ///
/// Technically these zero byte(s) are not a latch, as the color data (save /// 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 /// 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 /// 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 /// conversational consistency with other LED drivers, we'll refer to it as
/// a 'latch' anyway. /// a 'latch' anyway.
/// ///
/// This has been validated independently with multiple customers' /// This has been validated independently with multiple customers'
/// hardware. Please do not report as a bug or issue pull requests for /// hardware. Please do not report as a bug or issue pull requests for
/// this. Fewer zeros sometimes gives the *illusion* of working, the first /// this. Fewer zeros sometimes gives the *illusion* of working, the first
/// payload will correctly load and latch, but subsequent frames will drop /// payload will correctly load and latch, but subsequent frames will drop
/// data at the end. The data shortfall won't always be visually apparent /// 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. /// depending on the color data loaded on the prior and subsequent frames.
/// Tested. Confirmed. Fact. /// Tested. Confirmed. Fact.
/// ///
/// ///
/// The summary of the story is that the following needs to be writen on the spi-device: /// 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 ... /// 1RRRRRRR 1GGGGGGG 1BBBBBBB 1RRRRRRR 1GGGGGGG ... ... 1GGGGGGG 1BBBBBBB 00000000 00000000 ...
/// |---------led_1----------| |---------led_2-- -led_n----------| |----clear data-- /// |---------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) /// The number of zeroes in the 'clear data' is (#led/32 + 1)bytes (or *8 for bits)
/// ///
class LedDeviceLpd8806 : public LedSpiDevice class LedDeviceLpd8806 : public LedSpiDevice
{ {
public: public:
/// ///
/// Constructs the LedDevice for a string containing leds of the type LPD8806 /// 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] outputDevice The name of the output device (eg '/dev/spidev0.0')
/// @param[in] baudrate The used baudrate for writing to the output device /// @param[in] baudrate The used baudrate for writing to the output device
/// ///
LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate); LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate);
/// ///
/// Writes the led color values to the led-device /// Writes the led color values to the led-device
/// ///
/// @param ledValues The color-value per led /// @param ledValues The color-value per led
/// @return Zero on succes else negative /// @return Zero on succes else negative
/// ///
virtual int write(const std::vector<ColorRgb> &ledValues); virtual int write(const std::vector<ColorRgb> &ledValues);
/// Switch the leds off /// Switch the leds off
virtual int switchOff(); virtual int switchOff();
private: private:
/// The buffer containing the packed RGB values /// The buffer containing the packed RGB values
std::vector<uint8_t> _ledBuffer; std::vector<uint8_t> _ledBuffer;
}; };

View File

@ -1,342 +1,342 @@
// Local-Hyperion includes // Local-Hyperion includes
#include "LedDevicePhilipsHue.h" #include "LedDevicePhilipsHue.h"
// jsoncpp includes // jsoncpp includes
#include <json/json.h> #include <json/json.h>
// qt includes // qt includes
#include <QtCore/qmath.h> #include <QtCore/qmath.h>
#include <QEventLoop> #include <QEventLoop>
#include <QNetworkReply> #include <QNetworkReply>
#include <stdexcept> #include <stdexcept>
#include <set> #include <set>
bool operator ==(CiColor p1, CiColor p2) { bool operator ==(CiColor p1, CiColor p2) {
return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri); return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri);
} }
bool operator !=(CiColor p1, CiColor p2) { bool operator !=(CiColor p1, CiColor p2) {
return !(p1 == p2); return !(p1 == p2);
} }
PhilipsHueLight::PhilipsHueLight(unsigned int id, QString originalState, QString modelId) : PhilipsHueLight::PhilipsHueLight(unsigned int id, QString originalState, QString modelId) :
id(id), originalState(originalState) { id(id), originalState(originalState) {
// Hue system model ids (http://www.developers.meethue.com/documentation/supported-lights). // Hue system model ids (http://www.developers.meethue.com/documentation/supported-lights).
// Light strips, color iris, ... // Light strips, color iris, ...
const std::set<QString> GAMUT_A_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012", const std::set<QString> GAMUT_A_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012",
"LLC013", "LLC014", "LST001" }; "LLC013", "LLC014", "LST001" };
// Hue bulbs, spots, ... // Hue bulbs, spots, ...
const std::set<QString> GAMUT_B_MODEL_IDS = { "LCT001", "LCT002", "LCT003", "LCT007", "LLM001" }; const std::set<QString> GAMUT_B_MODEL_IDS = { "LCT001", "LCT002", "LCT003", "LCT007", "LLM001" };
// Hue Lightstrip plus, go ... // Hue Lightstrip plus, go ...
const std::set<QString> GAMUT_C_MODEL_IDS = { "LLC020", "LST002" }; const std::set<QString> GAMUT_C_MODEL_IDS = { "LLC020", "LST002" };
// Find id in the sets and set the appropiate color space. // Find id in the sets and set the appropiate color space.
if (GAMUT_A_MODEL_IDS.find(modelId) != GAMUT_A_MODEL_IDS.end()) { if (GAMUT_A_MODEL_IDS.find(modelId) != GAMUT_A_MODEL_IDS.end()) {
colorSpace.red = {0.703f, 0.296f}; colorSpace.red = {0.703f, 0.296f};
colorSpace.green = {0.2151f, 0.7106f}; colorSpace.green = {0.2151f, 0.7106f};
colorSpace.blue = {0.138f, 0.08f}; colorSpace.blue = {0.138f, 0.08f};
} else if (GAMUT_B_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { } else if (GAMUT_B_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) {
colorSpace.red = {0.675f, 0.322f}; colorSpace.red = {0.675f, 0.322f};
colorSpace.green = {0.4091f, 0.518f}; colorSpace.green = {0.4091f, 0.518f};
colorSpace.blue = {0.167f, 0.04f}; colorSpace.blue = {0.167f, 0.04f};
} else if (GAMUT_C_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) { } else if (GAMUT_C_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) {
colorSpace.red = {0.675f, 0.322f}; colorSpace.red = {0.675f, 0.322f};
colorSpace.green = {0.2151f, 0.7106f}; colorSpace.green = {0.2151f, 0.7106f};
colorSpace.blue = {0.167f, 0.04f}; colorSpace.blue = {0.167f, 0.04f};
} else { } else {
colorSpace.red = {1.0f, 0.0f}; colorSpace.red = {1.0f, 0.0f};
colorSpace.green = {0.0f, 1.0f}; colorSpace.green = {0.0f, 1.0f};
colorSpace.blue = {0.0f, 0.0f}; colorSpace.blue = {0.0f, 0.0f};
} }
// Initialize black color. // Initialize black color.
black = rgbToCiColor(0.0f, 0.0f, 0.0f); black = rgbToCiColor(0.0f, 0.0f, 0.0f);
// Initialize color with black // Initialize color with black
color = {black.x, black.y, black.bri}; color = {black.x, black.y, black.bri};
} }
float PhilipsHueLight::crossProduct(CiColor p1, CiColor p2) { float PhilipsHueLight::crossProduct(CiColor p1, CiColor p2) {
return p1.x * p2.y - p1.y * p2.x; return p1.x * p2.y - p1.y * p2.x;
} }
bool PhilipsHueLight::isPointInLampsReach(CiColor p) { bool PhilipsHueLight::isPointInLampsReach(CiColor p) {
CiColor v1 = { colorSpace.green.x - colorSpace.red.x, colorSpace.green.y - colorSpace.red.y }; 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 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 }; CiColor q = { p.x - colorSpace.red.x, p.y - colorSpace.red.y };
float s = crossProduct(q, v2) / crossProduct(v1, v2); float s = crossProduct(q, v2) / crossProduct(v1, v2);
float t = crossProduct(v1, q) / crossProduct(v1, v2); float t = crossProduct(v1, q) / crossProduct(v1, v2);
if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) { if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) {
return true; return true;
} }
return false; return false;
} }
CiColor PhilipsHueLight::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) { CiColor PhilipsHueLight::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) {
CiColor AP = { p.x - a.x, p.y - a.y }; CiColor AP = { p.x - a.x, p.y - a.y };
CiColor AB = { b.x - a.x, b.y - a.y }; CiColor AB = { b.x - a.x, b.y - a.y };
float ab2 = AB.x * AB.x + AB.y * AB.y; float ab2 = AB.x * AB.x + AB.y * AB.y;
float ap_ab = AP.x * AB.x + AP.y * AB.y; float ap_ab = AP.x * AB.x + AP.y * AB.y;
float t = ap_ab / ab2; float t = ap_ab / ab2;
if (t < 0.0f) { if (t < 0.0f) {
t = 0.0f; t = 0.0f;
} else if (t > 1.0f) { } else if (t > 1.0f) {
t = 1.0f; t = 1.0f;
} }
return {a.x + AB.x * t, a.y + AB.y * t}; return {a.x + AB.x * t, a.y + AB.y * t};
} }
float PhilipsHueLight::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) { float PhilipsHueLight::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) {
// Horizontal difference. // Horizontal difference.
float dx = p1.x - p2.x; float dx = p1.x - p2.x;
// Vertical difference. // Vertical difference.
float dy = p1.y - p2.y; float dy = p1.y - p2.y;
// Absolute value. // Absolute value.
return sqrt(dx * dx + dy * dy); return sqrt(dx * dx + dy * dy);
} }
CiColor PhilipsHueLight::rgbToCiColor(float red, float green, float blue) { CiColor PhilipsHueLight::rgbToCiColor(float red, float green, float blue) {
// Apply gamma correction. // Apply gamma correction.
float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); 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 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); float b = (blue > 0.04045f) ? powf((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f);
// Convert to XYZ space. // Convert to XYZ space.
float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; float X = r * 0.649926f + g * 0.103455f + b * 0.197109f;
float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f;
float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f; float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f;
// Convert to x,y space. // Convert to x,y space.
float cx = X / (X + Y + Z); float cx = X / (X + Y + Z);
float cy = Y / (X + Y + Z); float cy = Y / (X + Y + Z);
if (isnan(cx)) { if (isnan(cx)) {
cx = 0.0f; cx = 0.0f;
} }
if (isnan(cy)) { if (isnan(cy)) {
cy = 0.0f; cy = 0.0f;
} }
// Brightness is simply Y in the XYZ space. // Brightness is simply Y in the XYZ space.
CiColor xy = { cx, cy, Y }; CiColor xy = { cx, cy, Y };
// Check if the given XY value is within the color reach of our lamps. // Check if the given XY value is within the color reach of our lamps.
if (!isPointInLampsReach(xy)) { 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. // 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 pAB = getClosestPointToPoint(colorSpace.red, colorSpace.green, xy);
CiColor pAC = getClosestPointToPoint(colorSpace.blue, colorSpace.red, xy); CiColor pAC = getClosestPointToPoint(colorSpace.blue, colorSpace.red, xy);
CiColor pBC = getClosestPointToPoint(colorSpace.green, colorSpace.blue, xy); CiColor pBC = getClosestPointToPoint(colorSpace.green, colorSpace.blue, xy);
// Get the distances per point and see which point is closer to our Point. // Get the distances per point and see which point is closer to our Point.
float dAB = getDistanceBetweenTwoPoints(xy, pAB); float dAB = getDistanceBetweenTwoPoints(xy, pAB);
float dAC = getDistanceBetweenTwoPoints(xy, pAC); float dAC = getDistanceBetweenTwoPoints(xy, pAC);
float dBC = getDistanceBetweenTwoPoints(xy, pBC); float dBC = getDistanceBetweenTwoPoints(xy, pBC);
float lowest = dAB; float lowest = dAB;
CiColor closestPoint = pAB; CiColor closestPoint = pAB;
if (dAC < lowest) { if (dAC < lowest) {
lowest = dAC; lowest = dAC;
closestPoint = pAC; closestPoint = pAC;
} }
if (dBC < lowest) { if (dBC < lowest) {
lowest = dBC; lowest = dBC;
closestPoint = pBC; closestPoint = pBC;
} }
// Change the xy value to a value which is within the reach of the lamp. // Change the xy value to a value which is within the reach of the lamp.
xy.x = closestPoint.x; xy.x = closestPoint.x;
xy.y = closestPoint.y; xy.y = closestPoint.y;
} }
return xy; return xy;
} }
LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::string& username, bool switchOffOnBlack, LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::string& username, bool switchOffOnBlack,
int transitiontime, std::vector<unsigned int> lightIds) : int transitiontime, std::vector<unsigned int> lightIds) :
host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime( host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime(
transitiontime), lightIds(lightIds) { transitiontime), lightIds(lightIds) {
manager = new QNetworkAccessManager(); manager = new QNetworkAccessManager();
timer.setInterval(3000); timer.setInterval(3000);
timer.setSingleShot(true); timer.setSingleShot(true);
connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates())); connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates()));
} }
LedDevicePhilipsHue::~LedDevicePhilipsHue() { LedDevicePhilipsHue::~LedDevicePhilipsHue() {
delete manager; delete manager;
} }
int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues) { int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues) {
// Save light states if not done before. // Save light states if not done before.
if (!areStatesSaved()) { if (!areStatesSaved()) {
saveStates((unsigned int) ledValues.size()); saveStates((unsigned int) ledValues.size());
switchOn((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 there are less states saved than colors given, then maybe something went wrong before.
if (lights.size() != ledValues.size()) { if (lights.size() != ledValues.size()) {
restoreStates(); restoreStates();
return 0; return 0;
} }
// Iterate through colors and set light states. // Iterate through colors and set light states.
unsigned int idx = 0; unsigned int idx = 0;
for (const ColorRgb& color : ledValues) { for (const ColorRgb& color : ledValues) {
// Get lamp. // Get lamp.
PhilipsHueLight& lamp = lights.at(idx); PhilipsHueLight& lamp = lights.at(idx);
// Scale colors from [0, 255] to [0, 1] and convert to xy space. // 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); CiColor xy = lamp.rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f);
// Write color if color has been changed. // Write color if color has been changed.
if (xy != lamp.color) { if (xy != lamp.color) {
// Switch on if the lamp has been previously switched off. // Switch on if the lamp has been previously switched off.
if (switchOffOnBlack && lamp.color == lamp.black) { if (switchOffOnBlack && lamp.color == lamp.black) {
put(getStateRoute(lamp.id), QString("{\"on\": true}")); put(getStateRoute(lamp.id), QString("{\"on\": true}"));
} }
// Send adjust color and brightness command in JSON format. // Send adjust color and brightness command in JSON format.
// We have to set the transition time each time. // We have to set the transition time each time.
put(getStateRoute(lamp.id), put(getStateRoute(lamp.id),
QString("{\"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg(xy.y).arg( QString("{\"xy\": [%1, %2], \"bri\": %3, \"transitiontime\": %4}").arg(xy.x).arg(xy.y).arg(
qRound(xy.bri * 255.0f)).arg(transitiontime)); qRound(xy.bri * 255.0f)).arg(transitiontime));
} }
// Switch lamp off if switchOffOnBlack is enabled and the lamp is currently on. // Switch lamp off if switchOffOnBlack is enabled and the lamp is currently on.
if (switchOffOnBlack) { if (switchOffOnBlack) {
// From black to a color. // From black to a color.
if (lamp.color == lamp.black && xy != lamp.black) { if (lamp.color == lamp.black && xy != lamp.black) {
put(getStateRoute(lamp.id), QString("{\"on\": true}")); put(getStateRoute(lamp.id), QString("{\"on\": true}"));
} }
// From a color to black. // From a color to black.
else if (lamp.color != lamp.black && xy == lamp.black) { else if (lamp.color != lamp.black && xy == lamp.black) {
put(getStateRoute(lamp.id), QString("{\"on\": false}")); put(getStateRoute(lamp.id), QString("{\"on\": false}"));
} }
} }
// Remember last color. // Remember last color.
lamp.color = xy; lamp.color = xy;
// Next light id. // Next light id.
idx++; idx++;
} }
timer.start(); timer.start();
return 0; return 0;
} }
int LedDevicePhilipsHue::switchOff() { int LedDevicePhilipsHue::switchOff() {
timer.stop(); timer.stop();
// If light states have been saved before, ... // If light states have been saved before, ...
if (areStatesSaved()) { if (areStatesSaved()) {
// ... restore them. // ... restore them.
restoreStates(); restoreStates();
} }
return 0; return 0;
} }
void LedDevicePhilipsHue::put(QString route, QString content) { void LedDevicePhilipsHue::put(QString route, QString content) {
QString url = getUrl(route); QString url = getUrl(route);
// Perfrom request // Perfrom request
QNetworkRequest request(url); QNetworkRequest request(url);
QNetworkReply* reply = manager->put(request, content.toLatin1()); QNetworkReply* reply = manager->put(request, content.toLatin1());
// Connect finished signal to quit slot of the loop. // Connect finished signal to quit slot of the loop.
QEventLoop loop; QEventLoop loop;
loop.connect(reply, SIGNAL(finished()), SLOT(quit())); loop.connect(reply, SIGNAL(finished()), SLOT(quit()));
// Go into the loop until the request is finished. // Go into the loop until the request is finished.
loop.exec(); loop.exec();
// Free space. // Free space.
reply->deleteLater(); reply->deleteLater();
} }
QByteArray LedDevicePhilipsHue::get(QString route) { QByteArray LedDevicePhilipsHue::get(QString route) {
QString url = getUrl(route); QString url = getUrl(route);
// Perfrom request // Perfrom request
QNetworkRequest request(url); QNetworkRequest request(url);
QNetworkReply* reply = manager->get(request); QNetworkReply* reply = manager->get(request);
// Connect requestFinished signal to quit slot of the loop. // Connect requestFinished signal to quit slot of the loop.
QEventLoop loop; QEventLoop loop;
loop.connect(reply, SIGNAL(finished()), SLOT(quit())); loop.connect(reply, SIGNAL(finished()), SLOT(quit()));
// Go into the loop until the request is finished. // Go into the loop until the request is finished.
loop.exec(); loop.exec();
// Read all data of the response. // Read all data of the response.
QByteArray response = reply->readAll(); QByteArray response = reply->readAll();
// Free space. // Free space.
reply->deleteLater(); reply->deleteLater();
// Return response // Return response
return response; return response;
} }
QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) { QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) {
return QString("lights/%1/state").arg(lightId); return QString("lights/%1/state").arg(lightId);
} }
QString LedDevicePhilipsHue::getRoute(unsigned int lightId) { QString LedDevicePhilipsHue::getRoute(unsigned int lightId) {
return QString("lights/%1").arg(lightId); return QString("lights/%1").arg(lightId);
} }
QString LedDevicePhilipsHue::getUrl(QString route) { QString LedDevicePhilipsHue::getUrl(QString route) {
return QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route); return QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route);
} }
void LedDevicePhilipsHue::saveStates(unsigned int nLights) { void LedDevicePhilipsHue::saveStates(unsigned int nLights) {
// Clear saved lamps. // Clear saved lamps.
lights.clear(); lights.clear();
// Use json parser to parse reponse. // Use json parser to parse reponse.
Json::Reader reader; Json::Reader reader;
Json::FastWriter writer; Json::FastWriter writer;
// Read light ids if none have been supplied by the user. // Read light ids if none have been supplied by the user.
if (lightIds.size() != nLights) { if (lightIds.size() != nLights) {
lightIds.clear(); lightIds.clear();
// //
QByteArray response = get("lights"); QByteArray response = get("lights");
Json::Value json; Json::Value json;
if (!reader.parse(QString(response).toStdString(), json)) { if (!reader.parse(QString(response).toStdString(), json)) {
throw std::runtime_error(("No lights found at " + getUrl("lights")).toStdString()); throw std::runtime_error(("No lights found at " + getUrl("lights")).toStdString());
} }
// Loop over all children. // Loop over all children.
for (Json::ValueIterator it = json.begin(); it != json.end() && lightIds.size() < nLights; it++) { for (Json::ValueIterator it = json.begin(); it != json.end() && lightIds.size() < nLights; it++) {
int lightId = atoi(it.key().asCString()); int lightId = atoi(it.key().asCString());
lightIds.push_back(lightId); lightIds.push_back(lightId);
std::cout << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): found light with id " << lightId std::cout << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): found light with id " << lightId
<< "." << std::endl; << "." << std::endl;
} }
// Check if we found enough lights. // Check if we found enough lights.
if (lightIds.size() != nLights) { if (lightIds.size() != nLights) {
throw std::runtime_error(("Not enough lights found at " + getUrl("lights")).toStdString()); throw std::runtime_error(("Not enough lights found at " + getUrl("lights")).toStdString());
} }
} }
// Iterate lights. // Iterate lights.
for (unsigned int i = 0; i < nLights; i++) { for (unsigned int i = 0; i < nLights; i++) {
// Read the response. // Read the response.
QByteArray response = get(getRoute(lightIds.at(i))); QByteArray response = get(getRoute(lightIds.at(i)));
// Parse JSON. // Parse JSON.
Json::Value json; Json::Value json;
if (!reader.parse(QString(response).toStdString(), json)) { if (!reader.parse(QString(response).toStdString(), json)) {
// Error occured, break loop. // Error occured, break loop.
std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got invalid response from light " std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got invalid response from light "
<< getUrl(getRoute(lightIds.at(i))).toStdString() << "." << std::endl; << getUrl(getRoute(lightIds.at(i))).toStdString() << "." << std::endl;
break; break;
} }
// Get state object values which are subject to change. // Get state object values which are subject to change.
Json::Value state(Json::objectValue); Json::Value state(Json::objectValue);
if (!json.isMember("state")) { if (!json.isMember("state")) {
std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no state for light from " std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no state for light from "
<< getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl;
break; break;
} }
if (!json["state"].isMember("on")) { if (!json["state"].isMember("on")) {
std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no valid state from light " std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no valid state from light "
<< getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl;
break; break;
} }
state["on"] = json["state"]["on"]; state["on"] = json["state"]["on"];
if (json["state"]["on"] == true) { if (json["state"]["on"] == true) {
state["xy"] = json["state"]["xy"]; state["xy"] = json["state"]["xy"];
state["bri"] = json["state"]["bri"]; state["bri"] = json["state"]["bri"];
} }
// Determine the model id. // Determine the model id.
QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", ""); QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", "");
QString originalState = QString(writer.write(state).c_str()).trimmed(); QString originalState = QString(writer.write(state).c_str()).trimmed();
// Save state object. // Save state object.
lights.push_back(PhilipsHueLight(lightIds.at(i), originalState, modelId)); lights.push_back(PhilipsHueLight(lightIds.at(i), originalState, modelId));
} }
} }
void LedDevicePhilipsHue::switchOn(unsigned int nLights) { void LedDevicePhilipsHue::switchOn(unsigned int nLights) {
for (PhilipsHueLight light : lights) { for (PhilipsHueLight light : lights) {
put(getStateRoute(light.id), "{\"on\": true}"); put(getStateRoute(light.id), "{\"on\": true}");
} }
} }
void LedDevicePhilipsHue::restoreStates() { void LedDevicePhilipsHue::restoreStates() {
for (PhilipsHueLight light : lights) { for (PhilipsHueLight light : lights) {
put(getStateRoute(light.id), light.originalState); put(getStateRoute(light.id), light.originalState);
} }
// Clear saved light states. // Clear saved light states.
lights.clear(); lights.clear();
} }
bool LedDevicePhilipsHue::areStatesSaved() { bool LedDevicePhilipsHue::areStatesSaved() {
return !lights.empty(); return !lights.empty();
} }

View File

@ -1,236 +1,236 @@
#pragma once #pragma once
// STL includes // STL includes
#include <string> #include <string>
// Qt includes // Qt includes
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QTimer> #include <QTimer>
// Leddevice includes // Leddevice includes
#include <leddevice/LedDevice.h> #include <leddevice/LedDevice.h>
/** /**
* A color point in the color space of the hue system. * A color point in the color space of the hue system.
*/ */
struct CiColor { struct CiColor {
/// X component. /// X component.
float x; float x;
/// Y component. /// Y component.
float y; float y;
/// The brightness. /// The brightness.
float bri; float bri;
}; };
bool operator==(CiColor p1, CiColor p2); bool operator==(CiColor p1, CiColor p2);
bool operator!=(CiColor p1, CiColor p2); bool operator!=(CiColor p1, CiColor p2);
/** /**
* Color triangle to define an available color space for the hue lamps. * Color triangle to define an available color space for the hue lamps.
*/ */
struct CiColorTriangle { struct CiColorTriangle {
CiColor red, green, blue; CiColor red, green, blue;
}; };
/** /**
* Simple class to hold the id, the latest color, the color space and the original state. * Simple class to hold the id, the latest color, the color space and the original state.
*/ */
class PhilipsHueLight { class PhilipsHueLight {
public: public:
unsigned int id; unsigned int id;
CiColor black; CiColor black;
CiColor color; CiColor color;
CiColorTriangle colorSpace; CiColorTriangle colorSpace;
QString originalState; QString originalState;
/// ///
/// Constructs the light. /// Constructs the light.
/// ///
/// @param id the light id /// @param id the light id
/// ///
/// @param originalState the json string of the original state /// @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 /// @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); PhilipsHueLight(unsigned int id, QString originalState, QString modelId);
/// ///
/// Converts an RGB color to the Hue xy color space and brightness. /// 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 /// 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 red the red component in [0, 1]
/// ///
/// @param green the green component in [0, 1] /// @param green the green component in [0, 1]
/// ///
/// @param blue the blue component in [0, 1] /// @param blue the blue component in [0, 1]
/// ///
/// @return color point /// @return color point
/// ///
CiColor rgbToCiColor(float red, float green, float blue); CiColor rgbToCiColor(float red, float green, float blue);
/// ///
/// @param p the color point to check /// @param p the color point to check
/// ///
/// @return true if the color point is covered by the lamp color space /// @return true if the color point is covered by the lamp color space
/// ///
bool isPointInLampsReach(CiColor p); bool isPointInLampsReach(CiColor p);
/// ///
/// @param p1 point one /// @param p1 point one
/// ///
/// @param p2 point tow /// @param p2 point tow
/// ///
/// @return the cross product between p1 and p2 /// @return the cross product between p1 and p2
/// ///
float crossProduct(CiColor p1, CiColor p2); float crossProduct(CiColor p1, CiColor p2);
/// ///
/// @param a reference point one /// @param a reference point one
/// ///
/// @param b reference point two /// @param b reference point two
/// ///
/// @param p the point to which the closest point is to be found /// @param p the point to which the closest point is to be found
/// ///
/// @return the closest color point of p to a and b /// @return the closest color point of p to a and b
/// ///
CiColor getClosestPointToPoint(CiColor a, CiColor b, CiColor p); CiColor getClosestPointToPoint(CiColor a, CiColor b, CiColor p);
/// ///
/// @param p1 point one /// @param p1 point one
/// ///
/// @param p2 point tow /// @param p2 point tow
/// ///
/// @return the distance between the two points /// @return the distance between the two points
/// ///
float getDistanceBetweenTwoPoints(CiColor p1, CiColor p2); float getDistanceBetweenTwoPoints(CiColor p1, CiColor p2);
}; };
/** /**
* Implementation for the Philips Hue system. * Implementation for the Philips Hue system.
* *
* To use set the device to "philipshue". * To use set the device to "philipshue".
* Uses the official Philips Hue API (http://developers.meethue.com). * 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. * 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) * Create a new API user name "newdeveloper" on the bridge (http://developers.meethue.com/gettingstarted.html)
* *
* @author ntim (github), bimsarck (github) * @author ntim (github), bimsarck (github)
*/ */
class LedDevicePhilipsHue: public QObject, public LedDevice { class LedDevicePhilipsHue: public QObject, public LedDevice {
Q_OBJECT Q_OBJECT
public: public:
/// ///
/// Constructs the device. /// Constructs the device.
/// ///
/// @param output the ip address of the bridge /// @param output the ip address of the bridge
/// ///
/// @param username username of the hue bridge (default: newdeveloper) /// @param username username of the hue bridge (default: newdeveloper)
/// ///
/// @param switchOffOnBlack kill lights for black (default: false) /// @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 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. /// @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 = 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>()); false, int transitiontime = 1, std::vector<unsigned int> lightIds = std::vector<unsigned int>());
/// ///
/// Destructor of this device /// Destructor of this device
/// ///
virtual ~LedDevicePhilipsHue(); virtual ~LedDevicePhilipsHue();
/// ///
/// Sends the given led-color values via put request to the hue system /// Sends the given led-color values via put request to the hue system
/// ///
/// @param ledValues The color-value per led /// @param ledValues The color-value per led
/// ///
/// @return Zero on success else negative /// @return Zero on success else negative
/// ///
virtual int write(const std::vector<ColorRgb> & ledValues); virtual int write(const std::vector<ColorRgb> & ledValues);
/// Restores the original state of the leds. /// Restores the original state of the leds.
virtual int switchOff(); virtual int switchOff();
private slots: private slots:
/// Restores the status of all lights. /// Restores the status of all lights.
void restoreStates(); void restoreStates();
private: private:
/// Array to save the lamps. /// Array to save the lamps.
std::vector<PhilipsHueLight> lights; std::vector<PhilipsHueLight> lights;
/// Ip address of the bridge /// Ip address of the bridge
QString host; QString host;
/// User name for the API ("newdeveloper") /// User name for the API ("newdeveloper")
QString username; QString username;
/// QNetworkAccessManager object for sending requests. /// QNetworkAccessManager object for sending requests.
QNetworkAccessManager* manager; QNetworkAccessManager* manager;
/// Use timer to reset lights when we got into "GRABBINGMODE_OFF". /// Use timer to reset lights when we got into "GRABBINGMODE_OFF".
QTimer timer; QTimer timer;
/// ///
bool switchOffOnBlack; bool switchOffOnBlack;
/// Transition time in multiples of 100 ms. /// Transition time in multiples of 100 ms.
/// The default of the Hue lights will be 400 ms, but we want to have it snapier /// The default of the Hue lights will be 400 ms, but we want to have it snapier
int transitiontime; int transitiontime;
/// Array of the light ids. /// Array of the light ids.
std::vector<unsigned int> lightIds; std::vector<unsigned int> lightIds;
/// ///
/// Sends a HTTP GET request (blocking). /// Sends a HTTP GET request (blocking).
/// ///
/// @param route the URI of the request /// @param route the URI of the request
/// ///
/// @return response of the request /// @return response of the request
/// ///
QByteArray get(QString route); QByteArray get(QString route);
/// ///
/// Sends a HTTP PUT request (non-blocking). /// Sends a HTTP PUT request (non-blocking).
/// ///
/// @param route the URI of the request /// @param route the URI of the request
/// ///
/// @param content content of the request /// @param content content of the request
/// ///
void put(QString route, QString content); void put(QString route, QString content);
/// ///
/// @param lightId the id of the hue light (starting from 1) /// @param lightId the id of the hue light (starting from 1)
/// ///
/// @return the URI of the light state for PUT requests. /// @return the URI of the light state for PUT requests.
/// ///
QString getStateRoute(unsigned int lightId); QString getStateRoute(unsigned int lightId);
/// ///
/// @param lightId the id of the hue light (starting from 1) /// @param lightId the id of the hue light (starting from 1)
/// ///
/// @return the URI of the light for GET requests. /// @return the URI of the light for GET requests.
/// ///
QString getRoute(unsigned int lightId); QString getRoute(unsigned int lightId);
/// ///
/// @param route /// @param route
/// ///
/// @return the full URL of the request. /// @return the full URL of the request.
/// ///
QString getUrl(QString route); QString getUrl(QString route);
/// ///
/// Queries the status of all lights and saves it. /// Queries the status of all lights and saves it.
/// ///
/// @param nLights the number of lights /// @param nLights the number of lights
/// ///
void saveStates(unsigned int nLights); void saveStates(unsigned int nLights);
/// ///
/// Switches the leds on. /// Switches the leds on.
/// ///
/// @param nLights the number of lights /// @param nLights the number of lights
/// ///
void switchOn(unsigned int nLights); void switchOn(unsigned int nLights);
/// ///
/// @return true if light states have been saved. /// @return true if light states have been saved.
/// ///
bool areStatesSaved(); bool areStatesSaved();
}; };

View File

@ -16,18 +16,18 @@ LedDeviceTpm2::LedDeviceTpm2(const std::string& outputDevice, const unsigned bau
int LedDeviceTpm2::write(const std::vector<ColorRgb> &ledValues) int LedDeviceTpm2::write(const std::vector<ColorRgb> &ledValues)
{ {
if (_ledBuffer.size() == 0) if (_ledBuffer.size() == 0)
{ {
_ledBuffer.resize(5 + 3*ledValues.size()); _ledBuffer.resize(5 + 3*ledValues.size());
_ledBuffer[0] = 0xC9; // block-start byte _ledBuffer[0] = 0xC9; // block-start byte
_ledBuffer[1] = 0xDA; // DATA frame _ledBuffer[1] = 0xDA; // DATA frame
_ledBuffer[2] = ((3 * ledValues.size()) >> 8) & 0xFF; // frame size high byte _ledBuffer[2] = ((3 * ledValues.size()) >> 8) & 0xFF; // frame size high byte
_ledBuffer[3] = (3 * ledValues.size()) & 0xFF; // frame size low byte _ledBuffer[3] = (3 * ledValues.size()) & 0xFF; // frame size low byte
_ledBuffer.back() = 0x36; // block-end byte _ledBuffer.back() = 0x36; // block-end byte
} }
// write data // write data
memcpy(4 + _ledBuffer.data(), ledValues.data(), ledValues.size() * 3); memcpy(4 + _ledBuffer.data(), ledValues.data(), ledValues.size() * 3);
return writeBytes(_ledBuffer.size(), _ledBuffer.data()); return writeBytes(_ledBuffer.size(), _ledBuffer.data());
} }

View File

@ -25,55 +25,54 @@ LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate, c
//LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate) : //LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate) :
// _ofs(output.empty()?"/home/pi/LedDevice.out":output.c_str()) // _ofs(output.empty()?"/home/pi/LedDevice.out":output.c_str())
{ {
std::string hostname;
std::string hostname; std::string port;
std::string port; ledprotocol = protocol;
ledprotocol = protocol; leds_per_pkt = ((maxPacket-4)/3);
leds_per_pkt = ((maxPacket-4)/3); if (leds_per_pkt <= 0) {
if (leds_per_pkt <= 0) { leds_per_pkt = 200;
leds_per_pkt = 200; }
}
//printf ("leds_per_pkt is %d\n", leds_per_pkt); //printf ("leds_per_pkt is %d\n", leds_per_pkt);
int got_colon=0; int got_colon=0;
for (unsigned int i=0; i<output.length(); i++) { for (unsigned int i=0; i<output.length(); i++) {
if (output[i] == ':') { if (output[i] == ':') {
got_colon++; got_colon++;
} else if (got_colon == 0) { } else if (got_colon == 0) {
hostname+=output[i]; hostname+=output[i];
} else { } else {
port+=output[i]; port+=output[i];
}
} }
} //std::cout << "output " << output << " hostname " << hostname << " port " << port <<std::endl;
//std::cout << "output " << output << " hostname " << hostname << " port " << port <<std::endl; assert(got_colon==1);
assert(got_colon==1);
int rv; int rv;
memset(&hints, 0, sizeof hints); memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(hostname.c_str() , port.c_str(), &hints, &servinfo)) != 0) { if ((rv = getaddrinfo(hostname.c_str() , port.c_str(), &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
assert(rv==0); assert(rv==0);
} }
// loop through all the results and make a socket // loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) { for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) { p->ai_protocol)) == -1) {
perror("talker: socket"); perror("talker: socket");
continue; continue;
} }
break; break;
} }
if (p == NULL) { if (p == NULL) {
fprintf(stderr, "talker: failed to create socket\n"); fprintf(stderr, "talker: failed to create socket\n");
assert(p!=NULL); assert(p!=NULL);
} }
} }
LedDeviceUdp::~LedDeviceUdp() LedDeviceUdp::~LedDeviceUdp()
@ -99,7 +98,7 @@ int LedDeviceUdp::write(const std::vector<ColorRgb> & ledValues)
udpbuffer[i++] = color.green; udpbuffer[i++] = color.green;
udpbuffer[i++] = color.blue; 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); 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 udpbuffer[udpPtr++] = ledCtr%256; // low byte
} }
} }
} }
if (ledprotocol == 3) { if (ledprotocol == 3) {
@ -172,7 +170,6 @@ int LedDeviceUdp::write(const std::vector<ColorRgb> & ledValues)
udpbuffer[udpPtr++] = fragment_number++; udpbuffer[udpPtr++] = fragment_number++;
udpbuffer[udpPtr++] = fragments; udpbuffer[udpPtr++] = fragments;
for (const ColorRgb& color : ledValues) for (const ColorRgb& color : ledValues)
{ {
if (udpPtr<4090) { if (udpPtr<4090) {
@ -201,6 +198,6 @@ int LedDeviceUdp::write(const std::vector<ColorRgb> & ledValues)
int LedDeviceUdp::switchOff() 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; return 0;
} }

View File

@ -86,17 +86,17 @@
// Raspberry Pi low-level peripherals: // Raspberry Pi low-level peripherals:
// http://elinux.org/RPi_Low-level_peripherals // http://elinux.org/RPi_Low-level_peripherals
// //
// Richard Hirst's nice, clean code: // Richard Hirst's nice, clean code:
// https://github.com/richardghirst/PiBits/blob/master/PiFmDma/PiFmDma.c // https://github.com/richardghirst/PiBits/blob/master/PiFmDma/PiFmDma.c
// //
// PWM clock register: // PWM clock register:
// http://www.raspberrypi.org/forums/viewtopic.php?t=8467&p=124620 // http://www.raspberrypi.org/forums/viewtopic.php?t=8467&p=124620
// //
// Simple (because it's in assembly) PWM+DMA setup: // Simple (because it's in assembly) PWM+DMA setup:
// https://github.com/mikedurso/rpi-projects/blob/master/asm-nyancat/rpi-nyancat.s // https://github.com/mikedurso/rpi-projects/blob/master/asm-nyancat/rpi-nyancat.s
// //
// Adafruit's NeoPixel driver: // Adafruit's NeoPixel driver:
// https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp // https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp
// Hyperion includes // Hyperion includes
#include <leddevice/LedDevice.h> #include <leddevice/LedDevice.h>

View File

@ -1,61 +1,61 @@
# Define the current source locations # Define the current source locations
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/protoserver) set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/protoserver)
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/protoserver) set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/protoserver)
include_directories( include_directories(
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
${PROTOBUF_INCLUDE_DIRS} ${PROTOBUF_INCLUDE_DIRS}
) )
# Group the headers that go through the MOC compiler # Group the headers that go through the MOC compiler
set(ProtoServer_QT_HEADERS set(ProtoServer_QT_HEADERS
${CURRENT_HEADER_DIR}/ProtoServer.h ${CURRENT_HEADER_DIR}/ProtoServer.h
${CURRENT_HEADER_DIR}/ProtoConnection.h ${CURRENT_HEADER_DIR}/ProtoConnection.h
${CURRENT_SOURCE_DIR}/ProtoClientConnection.h ${CURRENT_SOURCE_DIR}/ProtoClientConnection.h
${CURRENT_HEADER_DIR}/ProtoConnectionWrapper.h ${CURRENT_HEADER_DIR}/ProtoConnectionWrapper.h
) )
set(ProtoServer_HEADERS set(ProtoServer_HEADERS
) )
set(ProtoServer_SOURCES set(ProtoServer_SOURCES
${CURRENT_SOURCE_DIR}/ProtoServer.cpp ${CURRENT_SOURCE_DIR}/ProtoServer.cpp
${CURRENT_SOURCE_DIR}/ProtoClientConnection.cpp ${CURRENT_SOURCE_DIR}/ProtoClientConnection.cpp
${CURRENT_SOURCE_DIR}/ProtoConnection.cpp ${CURRENT_SOURCE_DIR}/ProtoConnection.cpp
${CURRENT_SOURCE_DIR}/ProtoConnectionWrapper.cpp ${CURRENT_SOURCE_DIR}/ProtoConnectionWrapper.cpp
) )
set(ProtoServer_PROTOS set(ProtoServer_PROTOS
${CURRENT_SOURCE_DIR}/message.proto ${CURRENT_SOURCE_DIR}/message.proto
) )
protobuf_generate_cpp(ProtoServer_PROTO_SRCS ProtoServer_PROTO_HDRS protobuf_generate_cpp(ProtoServer_PROTO_SRCS ProtoServer_PROTO_HDRS
${ProtoServer_PROTOS} ${ProtoServer_PROTOS}
) )
if(ENABLE_QT5) if(ENABLE_QT5)
qt5_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS}) qt5_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS})
else(ENABLE_QT5) else()
qt4_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS}) qt4_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS})
endif(ENABLE_QT5) endif()
add_library(protoserver add_library(protoserver
${ProtoServer_HEADERS} ${ProtoServer_HEADERS}
${ProtoServer_QT_HEADERS} ${ProtoServer_QT_HEADERS}
${ProtoServer_SOURCES} ${ProtoServer_SOURCES}
${ProtoServer_HEADERS_MOC} ${ProtoServer_HEADERS_MOC}
${ProtoServer_PROTOS} ${ProtoServer_PROTOS}
${ProtoServer_PROTO_SRCS} ${ProtoServer_PROTO_SRCS}
${ProtoServer_PROTO_HDRS} ${ProtoServer_PROTO_HDRS}
) )
if(ENABLE_QT5) if(ENABLE_QT5)
qt5_use_modules(protoserver Widgets) qt5_use_modules(protoserver Widgets)
endif(ENABLE_QT5) endif()
target_link_libraries(protoserver target_link_libraries(protoserver
hyperion hyperion
hyperion-utils hyperion-utils
protobuf protobuf
${QT_LIBRARIES} ${QT_LIBRARIES}
) )

View File

@ -8,207 +8,207 @@
#include "protoserver/ProtoConnection.h" #include "protoserver/ProtoConnection.h"
ProtoConnection::ProtoConnection(const std::string & a) : ProtoConnection::ProtoConnection(const std::string & a) :
_socket(), _socket(),
_skipReply(false), _skipReply(false),
_prevSocketState(QAbstractSocket::UnconnectedState) _prevSocketState(QAbstractSocket::UnconnectedState)
{ {
QString address(a.c_str()); QString address(a.c_str());
QStringList parts = address.split(":"); QStringList parts = address.split(":");
if (parts.size() != 2) if (parts.size() != 2)
{ {
throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong address: Unable to parse address (%1)").arg(address).toStdString()); throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong address: Unable to parse address (%1)").arg(address).toStdString());
} }
_host = parts[0]; _host = parts[0];
bool ok; bool ok;
_port = parts[1].toUShort(&ok); _port = parts[1].toUShort(&ok);
if (!ok) if (!ok)
{ {
throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong port: Unable to parse the port number (%1)").arg(parts[1]).toStdString()); 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 // try to connect to host
std::cout << "PROTOCONNECTION INFO: Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; std::cout << "PROTOCONNECTION INFO: Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
connectToHost(); connectToHost();
// start the connection timer // start the connection timer
_timer.setInterval(5000); _timer.setInterval(5000);
_timer.setSingleShot(false); _timer.setSingleShot(false);
connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()) ); connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()) );
_timer.start(); _timer.start();
} }
ProtoConnection::~ProtoConnection() ProtoConnection::~ProtoConnection()
{ {
_timer.stop(); _timer.stop();
_socket.close(); _socket.close();
} }
void ProtoConnection::setSkipReply(bool skip) void ProtoConnection::setSkipReply(bool skip)
{ {
_skipReply = skip; _skipReply = skip;
} }
void ProtoConnection::setColor(const ColorRgb & color, int priority, int duration) void ProtoConnection::setColor(const ColorRgb & color, int priority, int duration)
{ {
proto::HyperionRequest request; proto::HyperionRequest request;
request.set_command(proto::HyperionRequest::COLOR); request.set_command(proto::HyperionRequest::COLOR);
proto::ColorRequest * colorRequest = request.MutableExtension(proto::ColorRequest::colorRequest); proto::ColorRequest * colorRequest = request.MutableExtension(proto::ColorRequest::colorRequest);
colorRequest->set_rgbcolor((color.red << 16) | (color.green << 8) | color.blue); colorRequest->set_rgbcolor((color.red << 16) | (color.green << 8) | color.blue);
colorRequest->set_priority(priority); colorRequest->set_priority(priority);
colorRequest->set_duration(duration); colorRequest->set_duration(duration);
// send command message // send command message
sendMessage(request); sendMessage(request);
} }
void ProtoConnection::setImage(const Image<ColorRgb> &image, int priority, int duration) void ProtoConnection::setImage(const Image<ColorRgb> &image, int priority, int duration)
{ {
proto::HyperionRequest request; proto::HyperionRequest request;
request.set_command(proto::HyperionRequest::IMAGE); request.set_command(proto::HyperionRequest::IMAGE);
proto::ImageRequest * imageRequest = request.MutableExtension(proto::ImageRequest::imageRequest); proto::ImageRequest * imageRequest = request.MutableExtension(proto::ImageRequest::imageRequest);
imageRequest->set_imagedata(image.memptr(), image.width() * image.height() * 3); imageRequest->set_imagedata(image.memptr(), image.width() * image.height() * 3);
imageRequest->set_imagewidth(image.width()); imageRequest->set_imagewidth(image.width());
imageRequest->set_imageheight(image.height()); imageRequest->set_imageheight(image.height());
imageRequest->set_priority(priority); imageRequest->set_priority(priority);
imageRequest->set_duration(duration); imageRequest->set_duration(duration);
// send command message // send command message
sendMessage(request); sendMessage(request);
} }
void ProtoConnection::clear(int priority) void ProtoConnection::clear(int priority)
{ {
proto::HyperionRequest request; proto::HyperionRequest request;
request.set_command(proto::HyperionRequest::CLEAR); request.set_command(proto::HyperionRequest::CLEAR);
proto::ClearRequest * clearRequest = request.MutableExtension(proto::ClearRequest::clearRequest); proto::ClearRequest * clearRequest = request.MutableExtension(proto::ClearRequest::clearRequest);
clearRequest->set_priority(priority); clearRequest->set_priority(priority);
// send command message // send command message
sendMessage(request); sendMessage(request);
} }
void ProtoConnection::clearAll() void ProtoConnection::clearAll()
{ {
proto::HyperionRequest request; proto::HyperionRequest request;
request.set_command(proto::HyperionRequest::CLEARALL); request.set_command(proto::HyperionRequest::CLEARALL);
// send command message // send command message
sendMessage(request); sendMessage(request);
} }
void ProtoConnection::connectToHost() void ProtoConnection::connectToHost()
{ {
// try connection only when // try connection only when
if (_socket.state() == QAbstractSocket::UnconnectedState) if (_socket.state() == QAbstractSocket::UnconnectedState)
{ {
_socket.connectToHost(_host, _port); _socket.connectToHost(_host, _port);
//_socket.waitForConnected(1000); //_socket.waitForConnected(1000);
} }
} }
void ProtoConnection::sendMessage(const proto::HyperionRequest &message) void ProtoConnection::sendMessage(const proto::HyperionRequest &message)
{ {
// print out connection message only when state is changed // print out connection message only when state is changed
if (_socket.state() != _prevSocketState ) if (_socket.state() != _prevSocketState )
{ {
switch (_socket.state() ) switch (_socket.state() )
{ {
case QAbstractSocket::UnconnectedState: case QAbstractSocket::UnconnectedState:
std::cout << "PROTOCONNECTION INFO: No connection to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; std::cout << "PROTOCONNECTION INFO: No connection to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
break; break;
case QAbstractSocket::ConnectedState: case QAbstractSocket::ConnectedState:
std::cout << "PROTOCONNECTION INFO: Connected to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; std::cout << "PROTOCONNECTION INFO: Connected to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
break; break;
default: default:
//std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; //std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl;
break; break;
} }
_prevSocketState = _socket.state(); _prevSocketState = _socket.state();
} }
if (_socket.state() != QAbstractSocket::ConnectedState) if (_socket.state() != QAbstractSocket::ConnectedState)
{ {
return; return;
} }
// We only get here if we are connected // We only get here if we are connected
// serialize message (FastWriter already appends a newline) // serialize message (FastWriter already appends a newline)
std::string serializedMessage = message.SerializeAsString(); std::string serializedMessage = message.SerializeAsString();
int length = serializedMessage.size(); int length = serializedMessage.size();
const uint8_t header[] = { const uint8_t header[] = {
uint8_t((length >> 24) & 0xFF), uint8_t((length >> 24) & 0xFF),
uint8_t((length >> 16) & 0xFF), uint8_t((length >> 16) & 0xFF),
uint8_t((length >> 8) & 0xFF), uint8_t((length >> 8) & 0xFF),
uint8_t((length ) & 0xFF)}; uint8_t((length ) & 0xFF)};
// write message // write message
int count = 0; int count = 0;
count += _socket.write(reinterpret_cast<const char *>(header), 4); count += _socket.write(reinterpret_cast<const char *>(header), 4);
count += _socket.write(reinterpret_cast<const char *>(serializedMessage.data()), length); count += _socket.write(reinterpret_cast<const char *>(serializedMessage.data()), length);
if (!_socket.waitForBytesWritten()) if (!_socket.waitForBytesWritten())
{ {
std::cerr << "PROTOCONNECTION ERROR: Error while writing data to host" << std::endl; std::cerr << "PROTOCONNECTION ERROR: Error while writing data to host" << std::endl;
return; return;
} }
if (!_skipReply) if (!_skipReply)
{ {
// read reply data // read reply data
QByteArray serializedReply; QByteArray serializedReply;
length = -1; length = -1;
while (length < 0 && serializedReply.size() < length+4) while (length < 0 && serializedReply.size() < length+4)
{ {
// receive reply // receive reply
if (!_socket.waitForReadyRead()) if (!_socket.waitForReadyRead())
{ {
std::cerr << "PROTOCONNECTION ERROR: Error while reading data from host" << std::endl; std::cerr << "PROTOCONNECTION ERROR: Error while reading data from host" << std::endl;
return; return;
} }
serializedReply += _socket.readAll(); serializedReply += _socket.readAll();
if (length < 0 && serializedReply.size() >= 4) if (length < 0 && serializedReply.size() >= 4)
{ {
// read the message size // read the message size
length = length =
((serializedReply[0]<<24) & 0xFF000000) | ((serializedReply[0]<<24) & 0xFF000000) |
((serializedReply[1]<<16) & 0x00FF0000) | ((serializedReply[1]<<16) & 0x00FF0000) |
((serializedReply[2]<< 8) & 0x0000FF00) | ((serializedReply[2]<< 8) & 0x0000FF00) |
((serializedReply[3] ) & 0x000000FF); ((serializedReply[3] ) & 0x000000FF);
} }
} }
// parse reply data // parse reply data
proto::HyperionReply reply; proto::HyperionReply reply;
reply.ParseFromArray(serializedReply.constData()+4, length); reply.ParseFromArray(serializedReply.constData()+4, length);
// parse reply message // parse reply message
parseReply(reply); parseReply(reply);
} }
} }
bool ProtoConnection::parseReply(const proto::HyperionReply &reply) bool ProtoConnection::parseReply(const proto::HyperionReply &reply)
{ {
bool success = false; bool success = false;
if (!reply.success()) if (!reply.success())
{ {
if (reply.has_error()) if (reply.has_error())
{ {
throw std::runtime_error("PROTOCONNECTION ERROR: " + reply.error()); throw std::runtime_error("PROTOCONNECTION ERROR: " + reply.error());
} }
else else
{ {
throw std::runtime_error("PROTOCONNECTION ERROR: No error info"); throw std::runtime_error("PROTOCONNECTION ERROR: No error info");
} }
} }
return success; return success;
} }

View File

@ -2,11 +2,11 @@
#include "protoserver/ProtoConnectionWrapper.h" #include "protoserver/ProtoConnectionWrapper.h"
ProtoConnectionWrapper::ProtoConnectionWrapper(const std::string & address, int priority, int duration_ms, bool skipProtoReply) : ProtoConnectionWrapper::ProtoConnectionWrapper(const std::string & address, int priority, int duration_ms, bool skipProtoReply) :
_priority(priority), _priority(priority),
_duration_ms(duration_ms), _duration_ms(duration_ms),
_connection(address) _connection(address)
{ {
_connection.setSkipReply(skipProtoReply); _connection.setSkipReply(skipProtoReply);
} }
ProtoConnectionWrapper::~ProtoConnectionWrapper() ProtoConnectionWrapper::~ProtoConnectionWrapper()
@ -15,5 +15,5 @@ ProtoConnectionWrapper::~ProtoConnectionWrapper()
void ProtoConnectionWrapper::receiveImage(const Image<ColorRgb> & image) void ProtoConnectionWrapper::receiveImage(const Image<ColorRgb> & image)
{ {
_connection.setImage(image, _priority, _duration_ms); _connection.setImage(image, _priority, _duration_ms);
} }

View File

@ -1,41 +1,41 @@
# Define the current source locations # Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/utils) SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/utils)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/utils) SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/utils)
add_library(hyperion-utils add_library(hyperion-utils
${CURRENT_HEADER_DIR}/ColorArgb.h ${CURRENT_HEADER_DIR}/ColorArgb.h
${CURRENT_SOURCE_DIR}/ColorArgb.cpp ${CURRENT_SOURCE_DIR}/ColorArgb.cpp
${CURRENT_HEADER_DIR}/ColorBgr.h ${CURRENT_HEADER_DIR}/ColorBgr.h
${CURRENT_SOURCE_DIR}/ColorBgr.cpp ${CURRENT_SOURCE_DIR}/ColorBgr.cpp
${CURRENT_HEADER_DIR}/ColorRgb.h ${CURRENT_HEADER_DIR}/ColorRgb.h
${CURRENT_SOURCE_DIR}/ColorRgb.cpp ${CURRENT_SOURCE_DIR}/ColorRgb.cpp
${CURRENT_HEADER_DIR}/ColorRgba.h ${CURRENT_HEADER_DIR}/ColorRgba.h
${CURRENT_SOURCE_DIR}/ColorRgba.cpp ${CURRENT_SOURCE_DIR}/ColorRgba.cpp
${CURRENT_HEADER_DIR}/Image.h ${CURRENT_HEADER_DIR}/Image.h
${CURRENT_HEADER_DIR}/Sleep.h ${CURRENT_HEADER_DIR}/Sleep.h
${CURRENT_HEADER_DIR}/PixelFormat.h ${CURRENT_HEADER_DIR}/PixelFormat.h
${CURRENT_HEADER_DIR}/VideoMode.h ${CURRENT_HEADER_DIR}/VideoMode.h
${CURRENT_HEADER_DIR}/ImageResampler.h ${CURRENT_HEADER_DIR}/ImageResampler.h
${CURRENT_SOURCE_DIR}/ImageResampler.cpp ${CURRENT_SOURCE_DIR}/ImageResampler.cpp
${CURRENT_HEADER_DIR}/HsvTransform.h ${CURRENT_HEADER_DIR}/HsvTransform.h
${CURRENT_SOURCE_DIR}/HsvTransform.cpp ${CURRENT_SOURCE_DIR}/HsvTransform.cpp
${CURRENT_HEADER_DIR}/HslTransform.h ${CURRENT_HEADER_DIR}/HslTransform.h
${CURRENT_SOURCE_DIR}/HslTransform.cpp ${CURRENT_SOURCE_DIR}/HslTransform.cpp
${CURRENT_HEADER_DIR}/RgbChannelTransform.h ${CURRENT_HEADER_DIR}/RgbChannelTransform.h
${CURRENT_SOURCE_DIR}/RgbChannelTransform.cpp ${CURRENT_SOURCE_DIR}/RgbChannelTransform.cpp
${CURRENT_HEADER_DIR}/RgbChannelCorrection.h ${CURRENT_HEADER_DIR}/RgbChannelCorrection.h
${CURRENT_SOURCE_DIR}/RgbChannelCorrection.cpp ${CURRENT_SOURCE_DIR}/RgbChannelCorrection.cpp
${CURRENT_HEADER_DIR}/RgbChannelAdjustment.h ${CURRENT_HEADER_DIR}/RgbChannelAdjustment.h
${CURRENT_SOURCE_DIR}/RgbChannelAdjustment.cpp ${CURRENT_SOURCE_DIR}/RgbChannelAdjustment.cpp
${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h ${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h
${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h ${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h
${CURRENT_SOURCE_DIR}/jsonschema/JsonSchemaChecker.cpp ${CURRENT_SOURCE_DIR}/jsonschema/JsonSchemaChecker.cpp
) )
target_link_libraries(hyperion-utils target_link_libraries(hyperion-utils
jsoncpp) jsoncpp)

View File

@ -1,464 +1,464 @@
// stdlib includes // stdlib includes
#include <cassert> #include <cassert>
#include <iterator> #include <iterator>
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
// Utils-Jsonschema includes // Utils-Jsonschema includes
#include <utils/jsonschema/JsonSchemaChecker.h> #include <utils/jsonschema/JsonSchemaChecker.h>
JsonSchemaChecker::JsonSchemaChecker() JsonSchemaChecker::JsonSchemaChecker()
{ {
// empty // empty
} }
JsonSchemaChecker::~JsonSchemaChecker() JsonSchemaChecker::~JsonSchemaChecker()
{ {
// empty // empty
} }
bool JsonSchemaChecker::setSchema(const Json::Value & schema) bool JsonSchemaChecker::setSchema(const Json::Value & schema)
{ {
_schema = schema; _schema = schema;
// TODO: check the schema // TODO: check the schema
return true; return true;
} }
bool JsonSchemaChecker::validate(const Json::Value & value) bool JsonSchemaChecker::validate(const Json::Value & value)
{ {
// initialize state // initialize state
_error = false; _error = false;
_messages.clear(); _messages.clear();
_currentPath.clear(); _currentPath.clear();
_currentPath.push_back("[root]"); _currentPath.push_back("[root]");
_references.clear(); _references.clear();
// collect dependencies // collect dependencies
collectDependencies(value, _schema); collectDependencies(value, _schema);
// validate // validate
validate(value, _schema); validate(value, _schema);
return !_error; return !_error;
} }
void JsonSchemaChecker::collectDependencies(const Json::Value & value, const Json::Value &schema) void JsonSchemaChecker::collectDependencies(const Json::Value & value, const Json::Value &schema)
{ {
assert (schema.isObject()); assert (schema.isObject());
// check if id is present // check if id is present
if (schema.isMember("id")) if (schema.isMember("id"))
{ {
// strore reference // strore reference
assert (schema["id"].isString()); assert (schema["id"].isString());
std::ostringstream ref; std::ostringstream ref;
ref << "$(" << schema["id"].asString() << ")"; ref << "$(" << schema["id"].asString() << ")";
_references[ref.str()] = &value; _references[ref.str()] = &value;
} }
// check the current json value // check the current json value
if (schema.isMember("properties")) if (schema.isMember("properties"))
{ {
const Json::Value & properties = schema["properties"]; const Json::Value & properties = schema["properties"];
assert(properties.isObject()); assert(properties.isObject());
for (Json::Value::const_iterator j = properties.begin(); j != properties.end(); ++j) for (Json::Value::const_iterator j = properties.begin(); j != properties.end(); ++j)
{ {
std::string property = j.memberName(); std::string property = j.memberName();
if (value.isMember(property)) if (value.isMember(property))
{ {
collectDependencies(value[property], properties[property]); collectDependencies(value[property], properties[property]);
} }
} }
} }
} }
void JsonSchemaChecker::validate(const Json::Value & value, const Json::Value &schema) void JsonSchemaChecker::validate(const Json::Value & value, const Json::Value &schema)
{ {
assert (schema.isObject()); assert (schema.isObject());
// check the current json value // check the current json value
for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i) for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i)
{ {
std::string attribute = i.memberName(); std::string attribute = i.memberName();
const Json::Value & attributeValue = *i; const Json::Value & attributeValue = *i;
if (attribute == "type") if (attribute == "type")
checkType(value, attributeValue); checkType(value, attributeValue);
else if (attribute == "properties") else if (attribute == "properties")
checkProperties(value, attributeValue); checkProperties(value, attributeValue);
else if (attribute == "additionalProperties") else if (attribute == "additionalProperties")
{ {
// ignore the properties which are handled by the properties attribute (if present) // ignore the properties which are handled by the properties attribute (if present)
Json::Value::Members ignoredProperties; Json::Value::Members ignoredProperties;
if (schema.isMember("properties")) { if (schema.isMember("properties")) {
const Json::Value & props = schema["properties"]; const Json::Value & props = schema["properties"];
ignoredProperties = props.getMemberNames(); ignoredProperties = props.getMemberNames();
} }
checkAdditionalProperties(value, attributeValue, ignoredProperties); checkAdditionalProperties(value, attributeValue, ignoredProperties);
} }
else if (attribute == "dependencies") else if (attribute == "dependencies")
checkDependencies(value, attributeValue); checkDependencies(value, attributeValue);
else if (attribute == "minimum") else if (attribute == "minimum")
checkMinimum(value, attributeValue); checkMinimum(value, attributeValue);
else if (attribute == "maximum") else if (attribute == "maximum")
checkMaximum(value, attributeValue); checkMaximum(value, attributeValue);
else if (attribute == "items") else if (attribute == "items")
checkItems(value, attributeValue); checkItems(value, attributeValue);
else if (attribute == "minItems") else if (attribute == "minItems")
checkMinItems(value, attributeValue); checkMinItems(value, attributeValue);
else if (attribute == "maxItems") else if (attribute == "maxItems")
checkMaxItems(value, attributeValue); checkMaxItems(value, attributeValue);
else if (attribute == "uniqueItems") else if (attribute == "uniqueItems")
checkUniqueItems(value, attributeValue); checkUniqueItems(value, attributeValue);
else if (attribute == "enum") else if (attribute == "enum")
checkEnum(value, attributeValue); checkEnum(value, attributeValue);
else if (attribute == "required") else if (attribute == "required")
; // nothing to do. value is present so always oke ; // nothing to do. value is present so always oke
else if (attribute == "id") else if (attribute == "id")
; // references have already been collected ; // references have already been collected
else else
{ {
// no check function defined for this attribute // no check function defined for this attribute
setMessage(std::string("No check function defined for attribute ") + attribute); setMessage(std::string("No check function defined for attribute ") + attribute);
continue; continue;
} }
} }
} }
void JsonSchemaChecker::setMessage(const std::string & message) void JsonSchemaChecker::setMessage(const std::string & message)
{ {
std::ostringstream oss; std::ostringstream oss;
std::copy(_currentPath.begin(), _currentPath.end(), std::ostream_iterator<std::string>(oss, "")); std::copy(_currentPath.begin(), _currentPath.end(), std::ostream_iterator<std::string>(oss, ""));
oss << ": " << message; oss << ": " << message;
_messages.push_back(oss.str()); _messages.push_back(oss.str());
} }
const std::list<std::string> & JsonSchemaChecker::getMessages() const const std::list<std::string> & JsonSchemaChecker::getMessages() const
{ {
return _messages; return _messages;
} }
void JsonSchemaChecker::checkType(const Json::Value & value, const Json::Value & schema) void JsonSchemaChecker::checkType(const Json::Value & value, const Json::Value & schema)
{ {
assert(schema.isString()); assert(schema.isString());
std::string type = schema.asString(); std::string type = schema.asString();
bool wrongType = false; bool wrongType = false;
if (type == "string") if (type == "string")
wrongType = !value.isString(); wrongType = !value.isString();
else if (type == "number") else if (type == "number")
wrongType = !value.isNumeric(); wrongType = !value.isNumeric();
else if (type == "integer") else if (type == "integer")
wrongType = !value.isIntegral(); wrongType = !value.isIntegral();
else if (type == "double") else if (type == "double")
wrongType = !value.isDouble(); wrongType = !value.isDouble();
else if (type == "boolean") else if (type == "boolean")
wrongType = !value.isBool(); wrongType = !value.isBool();
else if (type == "object") else if (type == "object")
wrongType = !value.isObject(); wrongType = !value.isObject();
else if (type == "array") else if (type == "array")
wrongType = !value.isArray(); wrongType = !value.isArray();
else if (type == "null") else if (type == "null")
wrongType = !value.isNull(); wrongType = !value.isNull();
else if (type == "enum") else if (type == "enum")
wrongType = !value.isString(); wrongType = !value.isString();
else if (type == "any") else if (type == "any")
wrongType = false; wrongType = false;
// else // else
// assert(false); // assert(false);
if (wrongType) if (wrongType)
{ {
_error = true; _error = true;
setMessage(type + " expected"); setMessage(type + " expected");
} }
} }
void JsonSchemaChecker::checkProperties(const Json::Value & value, const Json::Value & schema) void JsonSchemaChecker::checkProperties(const Json::Value & value, const Json::Value & schema)
{ {
assert(schema.isObject()); assert(schema.isObject());
if (!value.isObject()) if (!value.isObject())
{ {
_error = true; _error = true;
setMessage("properies attribute is only valid for objects"); setMessage("properies attribute is only valid for objects");
return; return;
} }
for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i) for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i)
{ {
std::string property = i.memberName(); std::string property = i.memberName();
const Json::Value & propertyValue = *i; const Json::Value & propertyValue = *i;
assert(propertyValue.isObject()); assert(propertyValue.isObject());
_currentPath.push_back(std::string(".") + property); _currentPath.push_back(std::string(".") + property);
if (value.isMember(property)) if (value.isMember(property))
{ {
validate(value[property], propertyValue); validate(value[property], propertyValue);
} }
else if (propertyValue.get("required", false).asBool()) else if (propertyValue.get("required", false).asBool())
{ {
_error = true; _error = true;
setMessage("missing member"); setMessage("missing member");
} }
_currentPath.pop_back(); _currentPath.pop_back();
} }
} }
void JsonSchemaChecker::checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties) void JsonSchemaChecker::checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties)
{ {
if (!value.isObject()) if (!value.isObject())
{ {
_error = true; _error = true;
setMessage("additional properies attribute is only valid for objects"); setMessage("additional properies attribute is only valid for objects");
return; return;
} }
for (Json::Value::const_iterator i = value.begin(); i != value.end(); ++i) for (Json::Value::const_iterator i = value.begin(); i != value.end(); ++i)
{ {
std::string property = i.memberName(); std::string property = i.memberName();
if (std::find(ignoredProperties.begin(), ignoredProperties.end(), property) == ignoredProperties.end()) if (std::find(ignoredProperties.begin(), ignoredProperties.end(), property) == ignoredProperties.end())
{ {
// property has no property definition. check against the definition for additional properties // property has no property definition. check against the definition for additional properties
_currentPath.push_back(std::string(".") + property); _currentPath.push_back(std::string(".") + property);
if (schema.isBool()) if (schema.isBool())
{ {
if (schema.asBool() == false) if (schema.asBool() == false)
{ {
_error = true; _error = true;
setMessage("no schema definition"); setMessage("no schema definition");
} }
} }
else else
{ {
validate(value[property], schema); validate(value[property], schema);
} }
_currentPath.pop_back(); _currentPath.pop_back();
} }
} }
} }
void JsonSchemaChecker::checkDependencies(const Json::Value & value, const Json::Value & schemaLink) void JsonSchemaChecker::checkDependencies(const Json::Value & value, const Json::Value & schemaLink)
{ {
if (!value.isObject()) if (!value.isObject())
{ {
_error = true; _error = true;
setMessage("dependencies attribute is only valid for objects"); setMessage("dependencies attribute is only valid for objects");
return; return;
} }
assert(schemaLink.isString()); assert(schemaLink.isString());
std::map<std::string, const Json::Value *>::iterator iter = _references.find(schemaLink.asString()); std::map<std::string, const Json::Value *>::iterator iter = _references.find(schemaLink.asString());
if (iter == _references.end()) if (iter == _references.end())
{ {
_error = true; _error = true;
std::ostringstream oss; std::ostringstream oss;
oss << "reference " << schemaLink.asString() << " could not be resolved"; oss << "reference " << schemaLink.asString() << " could not be resolved";
setMessage(oss.str()); setMessage(oss.str());
return; return;
} }
const Json::Value & schema = *(iter->second); const Json::Value & schema = *(iter->second);
std::list<std::string> requiredProperties; std::list<std::string> requiredProperties;
if (schema.isString()) if (schema.isString())
{ {
requiredProperties.push_back(schema.asString()); requiredProperties.push_back(schema.asString());
} }
else if (schema.isArray()) else if (schema.isArray())
{ {
for (Json::UInt i = 0; i < schema.size(); ++i) for (Json::UInt i = 0; i < schema.size(); ++i)
{ {
assert(schema[i].isString()); assert(schema[i].isString());
requiredProperties.push_back(schema[i].asString()); requiredProperties.push_back(schema[i].asString());
} }
} }
else else
{ {
_error = true; _error = true;
std::ostringstream oss; std::ostringstream oss;
oss << "Exepected reference " << schemaLink.asString() << " to resolve to a string or array"; oss << "Exepected reference " << schemaLink.asString() << " to resolve to a string or array";
setMessage(oss.str()); setMessage(oss.str());
return; return;
} }
for (std::list<std::string>::const_iterator i = requiredProperties.begin(); i != requiredProperties.end(); ++i) for (std::list<std::string>::const_iterator i = requiredProperties.begin(); i != requiredProperties.end(); ++i)
{ {
if (!value.isMember(*i)) if (!value.isMember(*i))
{ {
_error = true; _error = true;
std::ostringstream oss; std::ostringstream oss;
oss << "missing member " << *i; oss << "missing member " << *i;
setMessage(oss.str()); setMessage(oss.str());
} }
} }
} }
void JsonSchemaChecker::checkMinimum(const Json::Value & value, const Json::Value & schema) void JsonSchemaChecker::checkMinimum(const Json::Value & value, const Json::Value & schema)
{ {
assert(schema.isNumeric()); assert(schema.isNumeric());
if (!value.isNumeric()) if (!value.isNumeric())
{ {
// only for numeric // only for numeric
_error = true; _error = true;
setMessage("minimum check only for numeric fields"); setMessage("minimum check only for numeric fields");
return; return;
} }
if (value.asDouble() < schema.asDouble()) if (value.asDouble() < schema.asDouble())
{ {
_error = true; _error = true;
std::ostringstream oss; std::ostringstream oss;
oss << "value is too small (minimum=" << schema.asDouble() << ")"; oss << "value is too small (minimum=" << schema.asDouble() << ")";
setMessage(oss.str()); setMessage(oss.str());
} }
} }
void JsonSchemaChecker::checkMaximum(const Json::Value & value, const Json::Value & schema) void JsonSchemaChecker::checkMaximum(const Json::Value & value, const Json::Value & schema)
{ {
assert(schema.isNumeric()); assert(schema.isNumeric());
if (!value.isNumeric()) if (!value.isNumeric())
{ {
// only for numeric // only for numeric
_error = true; _error = true;
setMessage("maximum check only for numeric fields"); setMessage("maximum check only for numeric fields");
return; return;
} }
if (value.asDouble() > schema.asDouble()) if (value.asDouble() > schema.asDouble())
{ {
_error = true; _error = true;
std::ostringstream oss; std::ostringstream oss;
oss << "value is too large (maximum=" << schema.asDouble() << ")"; oss << "value is too large (maximum=" << schema.asDouble() << ")";
setMessage(oss.str()); setMessage(oss.str());
} }
} }
void JsonSchemaChecker::checkItems(const Json::Value & value, const Json::Value & schema) void JsonSchemaChecker::checkItems(const Json::Value & value, const Json::Value & schema)
{ {
assert(schema.isObject()); assert(schema.isObject());
if (!value.isArray()) if (!value.isArray())
{ {
// only for arrays // only for arrays
_error = true; _error = true;
setMessage("items only valid for arrays"); setMessage("items only valid for arrays");
return; return;
} }
for(Json::ArrayIndex i = 0; i < value.size(); ++i) for(Json::ArrayIndex i = 0; i < value.size(); ++i)
{ {
// validate each item // validate each item
std::ostringstream oss; std::ostringstream oss;
oss << "[" << i << "]"; oss << "[" << i << "]";
_currentPath.push_back(oss.str()); _currentPath.push_back(oss.str());
validate(value[i], schema); validate(value[i], schema);
_currentPath.pop_back(); _currentPath.pop_back();
} }
} }
void JsonSchemaChecker::checkMinItems(const Json::Value & value, const Json::Value & schema) void JsonSchemaChecker::checkMinItems(const Json::Value & value, const Json::Value & schema)
{ {
assert(schema.isIntegral()); assert(schema.isIntegral());
if (!value.isArray()) if (!value.isArray())
{ {
// only for arrays // only for arrays
_error = true; _error = true;
setMessage("minItems only valid for arrays"); setMessage("minItems only valid for arrays");
return; return;
} }
int minimum = schema.asInt(); int minimum = schema.asInt();
if (static_cast<int>(value.size()) < minimum) if (static_cast<int>(value.size()) < minimum)
{ {
_error = true; _error = true;
std::ostringstream oss; std::ostringstream oss;
oss << "array is too small (minimum=" << minimum << ")"; oss << "array is too small (minimum=" << minimum << ")";
setMessage(oss.str()); setMessage(oss.str());
} }
} }
void JsonSchemaChecker::checkMaxItems(const Json::Value & value, const Json::Value & schema) void JsonSchemaChecker::checkMaxItems(const Json::Value & value, const Json::Value & schema)
{ {
assert(schema.isIntegral()); assert(schema.isIntegral());
if (!value.isArray()) if (!value.isArray())
{ {
// only for arrays // only for arrays
_error = true; _error = true;
setMessage("maxItems only valid for arrays"); setMessage("maxItems only valid for arrays");
return; return;
} }
int maximum = schema.asInt(); int maximum = schema.asInt();
if (static_cast<int>(value.size()) > maximum) if (static_cast<int>(value.size()) > maximum)
{ {
_error = true; _error = true;
std::ostringstream oss; std::ostringstream oss;
oss << "array is too large (maximum=" << maximum << ")"; oss << "array is too large (maximum=" << maximum << ")";
setMessage(oss.str()); setMessage(oss.str());
} }
} }
void JsonSchemaChecker::checkUniqueItems(const Json::Value & value, const Json::Value & schema) void JsonSchemaChecker::checkUniqueItems(const Json::Value & value, const Json::Value & schema)
{ {
assert(schema.isBool()); assert(schema.isBool());
if (!value.isArray()) if (!value.isArray())
{ {
// only for arrays // only for arrays
_error = true; _error = true;
setMessage("uniqueItems only valid for arrays"); setMessage("uniqueItems only valid for arrays");
return; return;
} }
if (schema.asBool() == true) if (schema.asBool() == true)
{ {
// make sure no two items are identical // make sure no two items are identical
for(Json::UInt i = 0; i < value.size(); ++i) for(Json::UInt i = 0; i < value.size(); ++i)
{ {
for (Json::UInt j = i+1; j < value.size(); ++j) for (Json::UInt j = i+1; j < value.size(); ++j)
{ {
if (value[i] == value[j]) if (value[i] == value[j])
{ {
// found a value twice // found a value twice
_error = true; _error = true;
setMessage("array must have unique values"); setMessage("array must have unique values");
} }
} }
} }
} }
} }
void JsonSchemaChecker::checkEnum(const Json::Value & value, const Json::Value & schema) void JsonSchemaChecker::checkEnum(const Json::Value & value, const Json::Value & schema)
{ {
assert(schema.isArray()); assert(schema.isArray());
for(Json::ArrayIndex i = 0; i < schema.size(); ++i) for(Json::ArrayIndex i = 0; i < schema.size(); ++i)
{ {
if (schema[i] == value) if (schema[i] == value)
{ {
// found enum value. done. // found enum value. done.
return; return;
} }
} }
// nothing found // nothing found
_error = true; _error = true;
std::ostringstream oss; std::ostringstream oss;
oss << "Unknown enum value (allowed values are: "; oss << "Unknown enum value (allowed values are: ";
std::string values = Json::FastWriter().write(schema); 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 << values.substr(0, values.size()-1); // The writer append a new line which we don't want
oss << ")"; oss << ")";
setMessage(oss.str()); setMessage(oss.str());
} }

View File

@ -5,33 +5,33 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/xbmcvideochecker)
# Group the headers that go through the MOC compiler # Group the headers that go through the MOC compiler
SET(XBMCVideoChecker_QT_HEADERS SET(XBMCVideoChecker_QT_HEADERS
${CURRENT_HEADER_DIR}/XBMCVideoChecker.h ${CURRENT_HEADER_DIR}/XBMCVideoChecker.h
) )
SET(XBMCVideoChecker_HEADERS SET(XBMCVideoChecker_HEADERS
) )
SET(XBMCVideoChecker_SOURCES SET(XBMCVideoChecker_SOURCES
${CURRENT_SOURCE_DIR}/XBMCVideoChecker.cpp ${CURRENT_SOURCE_DIR}/XBMCVideoChecker.cpp
) )
if(ENABLE_QT5) if(ENABLE_QT5)
QT5_WRAP_CPP(XBMCVideoChecker_HEADERS_MOC ${XBMCVideoChecker_QT_HEADERS}) QT5_WRAP_CPP(XBMCVideoChecker_HEADERS_MOC ${XBMCVideoChecker_QT_HEADERS})
else(ENABLE_QT5) else()
QT4_WRAP_CPP(XBMCVideoChecker_HEADERS_MOC ${XBMCVideoChecker_QT_HEADERS}) QT4_WRAP_CPP(XBMCVideoChecker_HEADERS_MOC ${XBMCVideoChecker_QT_HEADERS})
endif(ENABLE_QT5) endif()
add_library(xbmcvideochecker add_library(xbmcvideochecker
${XBMCVideoChecker_HEADERS} ${XBMCVideoChecker_HEADERS}
${XBMCVideoChecker_QT_HEADERS} ${XBMCVideoChecker_QT_HEADERS}
${XBMCVideoChecker_HEADERS_MOC} ${XBMCVideoChecker_HEADERS_MOC}
${XBMCVideoChecker_SOURCES} ${XBMCVideoChecker_SOURCES}
) )
if(ENABLE_QT5) if(ENABLE_QT5)
qt5_use_modules(xbmcvideochecker Widgets) qt5_use_modules(xbmcvideochecker Widgets)
endif(ENABLE_QT5) endif()
target_link_libraries(xbmcvideochecker target_link_libraries(xbmcvideochecker
hyperion hyperion
${QT_LIBRARIES}) ${QT_LIBRARIES})

View File

@ -2,30 +2,27 @@ add_subdirectory(hyperiond)
add_subdirectory(hyperion-remote) add_subdirectory(hyperion-remote)
# The following clients depend on the protobuf library # The following clients depend on the protobuf library
if(ENABLE_PROTOBUF) if (ENABLE_AMLOGIC)
add_subdirectory(hyperion-aml)
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()
endif() 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()

View File

@ -3,14 +3,14 @@
#include "AmlogicWrapper.h" #include "AmlogicWrapper.h"
AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) :
_timer(this), _timer(this),
_grabber(grabWidth, grabHeight) _grabber(grabWidth, grabHeight)
{ {
_timer.setSingleShot(false); _timer.setSingleShot(false);
_timer.setInterval(updateRate_Hz); _timer.setInterval(updateRate_Hz);
// Connect capturing to the timeout signal of the timer // Connect capturing to the timeout signal of the timer
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
} }
const Image<ColorRgb> & AmlogicWrapper::getScreenshot() const Image<ColorRgb> & AmlogicWrapper::getScreenshot()
@ -21,12 +21,12 @@ const Image<ColorRgb> & AmlogicWrapper::getScreenshot()
void AmlogicWrapper::start() void AmlogicWrapper::start()
{ {
_timer.start(); _timer.start();
} }
void AmlogicWrapper::stop() void AmlogicWrapper::stop()
{ {
_timer.stop(); _timer.stop();
} }
void AmlogicWrapper::capture() void AmlogicWrapper::capture()

View File

@ -7,16 +7,16 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe
const unsigned cropLeft, const unsigned cropRight, const unsigned cropLeft, const unsigned cropRight,
const unsigned cropTop, const unsigned cropBottom, const unsigned cropTop, const unsigned cropBottom,
const unsigned updateRate_Hz) : const unsigned updateRate_Hz) :
_timer(this), _timer(this),
_grabber(grabWidth, grabHeight) _grabber(grabWidth, grabHeight)
{ {
_grabber.setVideoMode(videoMode); _grabber.setVideoMode(videoMode);
_grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom); _grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom);
_timer.setSingleShot(false); _timer.setSingleShot(false);
_timer.setInterval(updateRate_Hz); _timer.setInterval(updateRate_Hz);
// Connect capturing to the timeout signal of the timer // Connect capturing to the timeout signal of the timer
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
} }
const Image<ColorRgb> & DispmanxWrapper::getScreenshot() const Image<ColorRgb> & DispmanxWrapper::getScreenshot()
@ -27,12 +27,12 @@ const Image<ColorRgb> & DispmanxWrapper::getScreenshot()
void DispmanxWrapper::start() void DispmanxWrapper::start()
{ {
_timer.start(); _timer.start();
} }
void DispmanxWrapper::stop() void DispmanxWrapper::stop()
{ {
_timer.stop(); _timer.stop();
} }
void DispmanxWrapper::capture() void DispmanxWrapper::capture()

View File

@ -3,14 +3,14 @@
#include "FramebufferWrapper.h" #include "FramebufferWrapper.h"
FramebufferWrapper::FramebufferWrapper(const std::string & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : FramebufferWrapper::FramebufferWrapper(const std::string & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) :
_timer(this), _timer(this),
_grabber(device,grabWidth, grabHeight) _grabber(device,grabWidth, grabHeight)
{ {
_timer.setSingleShot(false); _timer.setSingleShot(false);
_timer.setInterval(updateRate_Hz); _timer.setInterval(updateRate_Hz);
// Connect capturing to the timeout signal of the timer // Connect capturing to the timeout signal of the timer
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
} }
const Image<ColorRgb> & FramebufferWrapper::getScreenshot() const Image<ColorRgb> & FramebufferWrapper::getScreenshot()
@ -21,12 +21,12 @@ const Image<ColorRgb> & FramebufferWrapper::getScreenshot()
void FramebufferWrapper::start() void FramebufferWrapper::start()
{ {
_timer.start(); _timer.start();
} }
void FramebufferWrapper::stop() void FramebufferWrapper::stop()
{ {
_timer.stop(); _timer.stop();
} }
void FramebufferWrapper::capture() void FramebufferWrapper::capture()

View File

@ -3,14 +3,14 @@
#include "OsxWrapper.h" #include "OsxWrapper.h"
OsxWrapper::OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : OsxWrapper::OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) :
_timer(this), _timer(this),
_grabber(display,grabWidth, grabHeight) _grabber(display,grabWidth, grabHeight)
{ {
_timer.setSingleShot(false); _timer.setSingleShot(false);
_timer.setInterval(updateRate_Hz); _timer.setInterval(updateRate_Hz);
// Connect capturing to the timeout signal of the timer // Connect capturing to the timeout signal of the timer
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
} }
const Image<ColorRgb> & OsxWrapper::getScreenshot() const Image<ColorRgb> & OsxWrapper::getScreenshot()

View File

@ -10,34 +10,34 @@ using namespace vlofgren;
typedef vlofgren::PODParameter<PixelFormat> PixelFormatParameter; typedef vlofgren::PODParameter<PixelFormat> PixelFormatParameter;
namespace vlofgren { namespace vlofgren {
/// Translates a string (as passed on the commandline) to a pixel format /// Translates a string (as passed on the commandline) to a pixel format
/// ///
/// @param[in] s The string (as passed on the commandline) /// @param[in] s The string (as passed on the commandline)
/// @return The pixel format /// @return The pixel format
/// @throws Parameter::ParameterRejected If the string did not result in a pixel format /// @throws Parameter::ParameterRejected If the string did not result in a pixel format
template<> template<>
PixelFormat PixelFormatParameter::validate(const std::string& s) throw (Parameter::ParameterRejected) PixelFormat PixelFormatParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
{ {
QString input = QString::fromStdString(s).toLower(); QString input = QString::fromStdString(s).toLower();
if (input == "yuyv") if (input == "yuyv")
{ {
return PIXELFORMAT_YUYV; return PIXELFORMAT_YUYV;
} }
else if (input == "uyvy") else if (input == "uyvy")
{ {
return PIXELFORMAT_UYVY; return PIXELFORMAT_UYVY;
} }
else if (input == "rgb32") else if (input == "rgb32")
{ {
return PIXELFORMAT_RGB32; return PIXELFORMAT_RGB32;
} }
else if (input == "no-change") else if (input == "no-change")
{ {
return PIXELFORMAT_NO_CHANGE; return PIXELFORMAT_NO_CHANGE;
} }
throw Parameter::ParameterRejected("Invalid value for pixel format. Valid values are: YUYV, UYVY, RGB32, and NO-CHANGE"); throw Parameter::ParameterRejected("Invalid value for pixel format. Valid values are: YUYV, UYVY, RGB32, and NO-CHANGE");
return PIXELFORMAT_NO_CHANGE; return PIXELFORMAT_NO_CHANGE;
} }
} }

View File

@ -6,7 +6,7 @@
#include "ScreenshotHandler.h" #include "ScreenshotHandler.h"
ScreenshotHandler::ScreenshotHandler(const std::string & filename) : ScreenshotHandler::ScreenshotHandler(const std::string & filename) :
_filename(filename) _filename(filename)
{ {
} }

View File

@ -31,150 +31,150 @@ using namespace vlofgren;
// save the image as screenshot // save the image as screenshot
void saveScreenshot(void *, const Image<ColorRgb> & image) void saveScreenshot(void *, const Image<ColorRgb> & image)
{ {
// store as PNG // store as PNG
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
pngImage.save("screenshot.png"); pngImage.save("screenshot.png");
} }
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
std::cout std::cout
<< "hyperion-v4l2:" << std::endl << "hyperion-v4l2:" << std::endl
<< "\tversion : " << HYPERION_VERSION_ID << std::endl << "\tversion : " << HYPERION_VERSION_ID << std::endl
<< "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl;
QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);
// force the locale // force the locale
setlocale(LC_ALL, "C"); setlocale(LC_ALL, "C");
QLocale::setDefault(QLocale::c()); QLocale::setDefault(QLocale::c());
// register the image type to use in signals // register the image type to use in signals
qRegisterMetaType<Image<ColorRgb>>("Image<ColorRgb>"); qRegisterMetaType<Image<ColorRgb>>("Image<ColorRgb>");
try try
{ {
// create the option parser and initialize all parameters // create the option parser and initialize all parameters
OptionsParser optionParser("V4L capture application for Hyperion"); OptionsParser optionParser("V4L capture application for Hyperion");
ParameterSet & parameters = optionParser.getParameters(); ParameterSet & parameters = optionParser.getParameters();
StringParameter & argDevice = parameters.add<StringParameter> ('d', "device", "The device to use [default: /dev/video0]"); 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)"); 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)"); 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 & 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 & 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 & 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 & 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 & 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 & 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 & 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 & 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 & 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 & 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]"); 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"); 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 & 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 & 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 & 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)"); 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<> & 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"); 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]"); 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]"); IntParameter & argPriority = parameters.add<IntParameter> ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]");
SwitchParameter<> & argSkipReply = parameters.add<SwitchParameter<>> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); SwitchParameter<> & argSkipReply = parameters.add<SwitchParameter<>> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<>> ('h', "help", "Show this help message and exit"); SwitchParameter<> & argHelp = parameters.add<SwitchParameter<>> ('h', "help", "Show this help message and exit");
// set defaults // set defaults
argDevice.setDefault("/dev/video0"); argDevice.setDefault("/dev/video0");
argVideoStandard.setDefault(VIDEOSTANDARD_NO_CHANGE); argVideoStandard.setDefault(VIDEOSTANDARD_NO_CHANGE);
argPixelFormat.setDefault(PIXELFORMAT_NO_CHANGE); argPixelFormat.setDefault(PIXELFORMAT_NO_CHANGE);
argInput.setDefault(-1); argInput.setDefault(-1);
argWidth.setDefault(-1); argWidth.setDefault(-1);
argHeight.setDefault(-1); argHeight.setDefault(-1);
argCropWidth.setDefault(0); argCropWidth.setDefault(0);
argCropHeight.setDefault(0); argCropHeight.setDefault(0);
argSizeDecimation.setDefault(1); argSizeDecimation.setDefault(1);
argFrameDecimation.setDefault(1); argFrameDecimation.setDefault(1);
argAddress.setDefault("127.0.0.1:19445"); argAddress.setDefault("127.0.0.1:19445");
argPriority.setDefault(800); argPriority.setDefault(800);
argSignalThreshold.setDefault(-1); argSignalThreshold.setDefault(-1);
// parse all options // parse all options
optionParser.parse(argc, const_cast<const char **>(argv)); optionParser.parse(argc, const_cast<const char **>(argv));
// check if we need to display the usage. exit if we do. // check if we need to display the usage. exit if we do.
if (argHelp.isSet()) if (argHelp.isSet())
{ {
optionParser.usage(); optionParser.usage();
return 0; return 0;
} }
// cropping values if not defined // cropping values if not defined
if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue()); if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue());
if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue()); if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue());
if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue()); if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue());
if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue()); if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue());
// initialize the grabber // initialize the grabber
V4L2Grabber grabber( V4L2Grabber grabber(
argDevice.getValue(), argDevice.getValue(),
argInput.getValue(), argInput.getValue(),
argVideoStandard.getValue(), argVideoStandard.getValue(),
argPixelFormat.getValue(), argPixelFormat.getValue(),
argWidth.getValue(), argWidth.getValue(),
argHeight.getValue(), argHeight.getValue(),
std::max(1, argFrameDecimation.getValue()), std::max(1, argFrameDecimation.getValue()),
std::max(1, argSizeDecimation.getValue()), std::max(1, argSizeDecimation.getValue()),
std::max(1, argSizeDecimation.getValue())); std::max(1, argSizeDecimation.getValue()));
// set signal detection // set signal detection
grabber.setSignalThreshold( grabber.setSignalThreshold(
std::min(1.0, std::max(0.0, argRedSignalThreshold.isSet() ? argRedSignalThreshold.getValue() : argSignalThreshold.getValue())), 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, argGreenSignalThreshold.isSet() ? argGreenSignalThreshold.getValue() : argSignalThreshold.getValue())),
std::min(1.0, std::max(0.0, argBlueSignalThreshold.isSet() ? argBlueSignalThreshold.getValue() : argSignalThreshold.getValue())), std::min(1.0, std::max(0.0, argBlueSignalThreshold.isSet() ? argBlueSignalThreshold.getValue() : argSignalThreshold.getValue())),
50); 50);
// set cropping values // set cropping values
grabber.setCropping( grabber.setCropping(
std::max(0, argCropLeft.getValue()), std::max(0, argCropLeft.getValue()),
std::max(0, argCropRight.getValue()), std::max(0, argCropRight.getValue()),
std::max(0, argCropTop.getValue()), std::max(0, argCropTop.getValue()),
std::max(0, argCropBottom.getValue())); std::max(0, argCropBottom.getValue()));
// set 3D mode if applicable // set 3D mode if applicable
if (arg3DSBS.isSet()) if (arg3DSBS.isSet())
{ {
grabber.set3D(VIDEO_3DSBS); grabber.set3D(VIDEO_3DSBS);
} }
else if (arg3DTAB.isSet()) else if (arg3DTAB.isSet())
{ {
grabber.set3D(VIDEO_3DTAB); grabber.set3D(VIDEO_3DTAB);
} }
// run the grabber // run the grabber
if (argScreenshot.isSet()) if (argScreenshot.isSet())
{ {
ScreenshotHandler handler("screenshot.png"); ScreenshotHandler handler("screenshot.png");
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>))); QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
grabber.start(); grabber.start();
QCoreApplication::exec(); QCoreApplication::exec();
grabber.stop(); grabber.stop();
} }
else else
{ {
ProtoConnectionWrapper handler(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); ProtoConnectionWrapper handler(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet());
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>))); QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
grabber.start(); grabber.start();
QCoreApplication::exec(); QCoreApplication::exec();
grabber.stop(); grabber.stop();
} }
} }
catch (const std::runtime_error & e) catch (const std::runtime_error & e)
{ {
// An error occured. Display error and quit // An error occured. Display error and quit
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
return 1; return 1;
} }
return 0; return 0;
} }

View File

@ -3,39 +3,39 @@
#include "X11Wrapper.h" #include "X11Wrapper.h"
X11Wrapper::X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) : X11Wrapper::X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) :
_timer(this), _timer(this),
_grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation) _grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation)
{ {
_timer.setSingleShot(false); _timer.setSingleShot(false);
_timer.setInterval(grabInterval); _timer.setInterval(grabInterval);
// Connect capturing to the timeout signal of the timer // Connect capturing to the timeout signal of the timer
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
} }
const Image<ColorRgb> & X11Wrapper::getScreenshot() const Image<ColorRgb> & X11Wrapper::getScreenshot()
{ {
const Image<ColorRgb> & screenshot = _grabber.grab(); const Image<ColorRgb> & screenshot = _grabber.grab();
return screenshot; return screenshot;
} }
void X11Wrapper::start() void X11Wrapper::start()
{ {
_timer.start(); _timer.start();
} }
void X11Wrapper::stop() void X11Wrapper::stop()
{ {
_timer.stop(); _timer.stop();
} }
bool X11Wrapper::displayInit() bool X11Wrapper::displayInit()
{ {
return _grabber.Setup(); return _grabber.Setup();
} }
void X11Wrapper::capture() void X11Wrapper::capture()
{ {
const Image<ColorRgb> & screenshot = _grabber.grab(); const Image<ColorRgb> & screenshot = _grabber.grab();
emit sig_screenshot(screenshot); emit sig_screenshot(screenshot);
} }

View File

@ -7,35 +7,35 @@
class X11Wrapper : public QObject class X11Wrapper : public QObject
{ {
Q_OBJECT Q_OBJECT
public: 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 /// Starts the timed capturing of screenshots
/// ///
void start(); void start();
void stop(); void stop();
bool displayInit(); bool displayInit();
signals: signals:
void sig_screenshot(const Image<ColorRgb> & screenshot); void sig_screenshot(const Image<ColorRgb> & screenshot);
private slots: private slots:
/// ///
/// Performs a single screenshot capture and publishes the capture screenshot on the screenshot /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot
/// signal. /// signal.
/// ///
void capture(); void capture();
private: private:
/// The QT timer to generate capture-publish events /// The QT timer to generate capture-publish events
QTimer _timer; QTimer _timer;
/// The grabber for creating screenshots /// The grabber for creating screenshots
X11Grabber _grabber; X11Grabber _grabber;
}; };

View File

@ -15,108 +15,108 @@ using namespace vlofgren;
// save the image as screenshot // save the image as screenshot
void saveScreenshot(const char * filename, const Image<ColorRgb> & image) void saveScreenshot(const char * filename, const Image<ColorRgb> & image)
{ {
// store as PNG // store as PNG
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
pngImage.save(filename); pngImage.save(filename);
} }
int main(int argc, char ** argv) int main(int argc, char ** argv)
{ {
std::cout std::cout
<< "hyperion-x11:" << std::endl << "hyperion-x11:" << std::endl
<< "\tversion : " << HYPERION_VERSION_ID << std::endl << "\tversion : " << HYPERION_VERSION_ID << std::endl
<< "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl;
QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);
try try
{ {
// create the option parser and initialize all parameters // create the option parser and initialize all parameters
OptionsParser optionParser("X11 capture application for Hyperion"); OptionsParser optionParser("X11 capture application for Hyperion");
ParameterSet & parameters = optionParser.getParameters(); ParameterSet & parameters = optionParser.getParameters();
IntParameter & argFps = parameters.add<IntParameter> ('f', "framerate", "Capture frame rate [default: 10]"); IntParameter & argFps = parameters.add<IntParameter> ('f', "framerate", "Capture frame rate [default: 10]");
SwitchParameter<> & argXGetImage = parameters.add<SwitchParameter<>> ('x', "xgetimage", "Use XGetImage instead of XRender"); 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 & 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 & 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 & 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 & 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 & 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 & 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]"); 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"); 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]"); 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]"); IntParameter & argPriority = parameters.add<IntParameter> ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]");
SwitchParameter<> & argSkipReply = parameters.add<SwitchParameter<>> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); SwitchParameter<> & argSkipReply = parameters.add<SwitchParameter<>> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<>> ('h', "help", "Show this help message and exit"); SwitchParameter<> & argHelp = parameters.add<SwitchParameter<>> ('h', "help", "Show this help message and exit");
// set defaults // set defaults
argFps.setDefault(10); argFps.setDefault(10);
argCropWidth.setDefault(0); argCropWidth.setDefault(0);
argCropHeight.setDefault(0); argCropHeight.setDefault(0);
argSizeDecimation.setDefault(8); argSizeDecimation.setDefault(8);
argAddress.setDefault("127.0.0.1:19445"); argAddress.setDefault("127.0.0.1:19445");
argPriority.setDefault(800); argPriority.setDefault(800);
// parse all options // parse all options
optionParser.parse(argc, const_cast<const char **>(argv)); optionParser.parse(argc, const_cast<const char **>(argv));
// check if we need to display the usage. exit if we do. // check if we need to display the usage. exit if we do.
if (argHelp.isSet()) if (argHelp.isSet())
{ {
optionParser.usage(); optionParser.usage();
return 0; return 0;
} }
// cropping values if not defined // cropping values if not defined
if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue()); if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue());
if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue()); if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue());
if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue()); if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue());
if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue()); if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue());
// Create the X11 grabbing stuff // Create the X11 grabbing stuff
int grabInterval = 1000 / argFps.getValue(); int grabInterval = 1000 / argFps.getValue();
bool useXGetImage = argXGetImage.isSet(); bool useXGetImage = argXGetImage.isSet();
X11Wrapper x11Wrapper( X11Wrapper x11Wrapper(
grabInterval, grabInterval,
useXGetImage, useXGetImage,
argCropLeft.getValue(), argCropLeft.getValue(),
argCropRight.getValue(), argCropRight.getValue(),
argCropTop.getValue(), argCropTop.getValue(),
argCropBottom.getValue(), argCropBottom.getValue(),
argSizeDecimation.getValue(), // horizontal decimation argSizeDecimation.getValue(), // horizontal decimation
argSizeDecimation.getValue()); // vertical decimation argSizeDecimation.getValue()); // vertical decimation
if (!x11Wrapper.displayInit()) if (!x11Wrapper.displayInit())
return -1; return -1;
if (argScreenshot.isSet()) if (argScreenshot.isSet())
{ {
// Capture a single screenshot and finish // Capture a single screenshot and finish
const Image<ColorRgb> & screenshot = x11Wrapper.getScreenshot(); const Image<ColorRgb> & screenshot = x11Wrapper.getScreenshot();
saveScreenshot("screenshot.png", screenshot); saveScreenshot("screenshot.png", screenshot);
} }
else else
{ {
// Create the Proto-connection with hyperiond // Create the Proto-connection with hyperiond
ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet());
// Connect the screen capturing to the proto processing // Connect the screen capturing to the proto processing
QObject::connect(&x11Wrapper, SIGNAL(sig_screenshot(const Image<ColorRgb> &)), &protoWrapper, SLOT(receiveImage(Image<ColorRgb>))); QObject::connect(&x11Wrapper, SIGNAL(sig_screenshot(const Image<ColorRgb> &)), &protoWrapper, SLOT(receiveImage(Image<ColorRgb>)));
// Start the capturing // Start the capturing
x11Wrapper.start(); x11Wrapper.start();
// Start the application // Start the application
app.exec(); app.exec();
} }
} }
catch (const std::runtime_error & e) catch (const std::runtime_error & e)
{ {
// An error occured. Display error and quit // An error occured. Display error and quit
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
return -1; return -1;
} }
return 0; return 0;
} }

View File

@ -51,10 +51,8 @@
// JsonServer includes // JsonServer includes
#include <jsonserver/JsonServer.h> #include <jsonserver/JsonServer.h>
#ifdef ENABLE_PROTOBUF
// ProtoServer includes // ProtoServer includes
#include <protoserver/ProtoServer.h> #include <protoserver/ProtoServer.h>
#endif
// BoblightServer includes // BoblightServer includes
#include <boblightserver/BoblightServer.h> #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; std::cout << "INFO: Json server created and started on port " << jsonServer->getPort() << std::endl;
} }
#ifdef ENABLE_PROTOBUF
// Create Proto server if configuration is present // Create Proto server if configuration is present
ProtoServer * protoServer = nullptr; ProtoServer * protoServer = nullptr;
if (config.isMember("protoServer")) if (config.isMember("protoServer"))
@ -217,7 +214,6 @@ int main(int argc, char** argv)
protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() );
std::cout << "INFO: Proto server created and started on port " << protoServer->getPort() << std::endl; std::cout << "INFO: Proto server created and started on port " << protoServer->getPort() << std::endl;
} }
#endif
// Create Boblight server if configuration is present // Create Boblight server if configuration is present
BoblightServer * boblightServer = nullptr; BoblightServer * boblightServer = nullptr;
@ -254,9 +250,7 @@ int main(int argc, char** argv)
QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), dispmanx, SLOT(setVideoMode(VideoMode))); 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)) ); QObject::connect(dispmanx, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
#endif
dispmanx->start(); dispmanx->start();
std::cout << "INFO: Frame grabber created and started" << std::endl; 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("cropTop", 0).asInt(),
grabberConfig.get("cropBottom", 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)) ); QObject::connect(v4l2Grabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
#endif
v4l2Grabber->start(); v4l2Grabber->start();
std::cout << "INFO: V4L2 grabber created and started" << std::endl; 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))); 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)) ); QObject::connect(amlGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
#endif
amlGrabber->start(); amlGrabber->start();
std::cout << "INFO: AMLOGIC grabber created and started" << std::endl; 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))); 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)) ); QObject::connect(fbGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
#endif
fbGrabber->start(); fbGrabber->start();
std::cout << "INFO: Framebuffer grabber created and started" << std::endl; 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))); 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)) ); QObject::connect(osxGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
#endif
osxGrabber->start(); osxGrabber->start();
std::cout << "INFO: OSX grabber created and started" << std::endl; std::cout << "INFO: OSX grabber created and started" << std::endl;
@ -445,9 +431,7 @@ int main(int argc, char** argv)
#endif #endif
delete xbmcVideoChecker; delete xbmcVideoChecker;
delete jsonServer; delete jsonServer;
#ifdef ENABLE_PROTOBUF
delete protoServer; delete protoServer;
#endif
delete boblightServer; delete boblightServer;
// leave application // leave application