big code cleanup. mostly line endings and indentions (#659)

No functional changes - except protobuffer is mandatory and not optional now.

Former-commit-id: 1e6347e708
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} )
message(STATUS "ENABLE_OSX = " ${ENABLE_OSX})
option(ENABLE_PROTOBUF "Enable PROTOBUF server" ON)
message(STATUS "ENABLE_PROTOBUF = " ${ENABLE_PROTOBUF})
set(ENABLE_PROTOBUF ON)
option(ENABLE_SPIDEV "Enable the SPIDEV device" ${DEFAULT_SPIDEV} )
message(STATUS "ENABLE_SPIDEV = " ${ENABLE_SPIDEV})
@ -78,9 +77,6 @@ message(STATUS "ENABLE_QT5 = " ${ENABLE_QT5})
option(ENABLE_TESTS "Compile additional test applications" OFF)
message(STATUS "ENABLE_TESTS = " ${ENABLE_TESTS})
if(ENABLE_V4L2 AND NOT ENABLE_PROTOBUF)
message(FATAL_ERROR "V4L2 grabber requires PROTOBUF. Disable V4L2 or enable PROTOBUF")
endif()
if(ENABLE_FB AND ENABLE_DISPMANX)
message(FATAL_ERROR "dispmanx grabber and framebuffer grabber cannot be used at the same time")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -44,56 +44,52 @@
if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
# in cache already
set(LIBUSB_FOUND TRUE)
# in cache already
set(LIBUSB_FOUND TRUE)
else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
find_path(LIBUSB_1_INCLUDE_DIR
find_path(LIBUSB_1_INCLUDE_DIR
NAMES
libusb.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
PATH_SUFFIXES
libusb-1.0
)
find_library(LIBUSB_1_LIBRARY
NAMES
libusb.h
usb-1.0 usb
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
PATH_SUFFIXES
libusb-1.0
)
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
find_library(LIBUSB_1_LIBRARY
NAMES
usb-1.0 usb
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
set(LIBUSB_1_INCLUDE_DIRS ${LIBUSB_1_INCLUDE_DIR} )
set(LIBUSB_1_LIBRARIES ${LIBUSB_1_LIBRARY} )
set(LIBUSB_1_INCLUDE_DIRS
${LIBUSB_1_INCLUDE_DIR}
)
set(LIBUSB_1_LIBRARIES
${LIBUSB_1_LIBRARY}
)
if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
set(LIBUSB_1_FOUND TRUE)
endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
set(LIBUSB_1_FOUND TRUE)
endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
if (LIBUSB_1_FOUND)
if (NOT libusb_1_FIND_QUIETLY)
message(STATUS "Found libusb-1.0:")
message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}")
message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}")
endif (NOT libusb_1_FIND_QUIETLY)
else (LIBUSB_1_FOUND)
unset(LIBUSB_1_LIBRARY CACHE)
if (libusb_1_FIND_REQUIRED)
message(FATAL_ERROR "Could not find libusb")
endif (libusb_1_FIND_REQUIRED)
endif (LIBUSB_1_FOUND)
if (LIBUSB_1_FOUND)
if (NOT libusb_1_FIND_QUIETLY)
message(STATUS "Found libusb-1.0:")
message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}")
message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}")
endif (NOT libusb_1_FIND_QUIETLY)
else (LIBUSB_1_FOUND)
unset(LIBUSB_1_LIBRARY CACHE)
if (libusb_1_FIND_REQUIRED)
message(FATAL_ERROR "Could not find libusb")
endif (libusb_1_FIND_REQUIRED)
endif (LIBUSB_1_FOUND)
# show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view
mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES)
# show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view
mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES)
endif (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,103 +23,103 @@
/// @see http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html
class V4L2Grabber : public QObject
{
Q_OBJECT
Q_OBJECT
public:
V4L2Grabber(const std::string & device,
int input,
VideoStandard videoStandard, PixelFormat pixelFormat,
int width,
int height,
int frameDecimation,
int horizontalPixelDecimation,
int verticalPixelDecimation);
virtual ~V4L2Grabber();
V4L2Grabber(const std::string & device,
int input,
VideoStandard videoStandard, PixelFormat pixelFormat,
int width,
int height,
int frameDecimation,
int horizontalPixelDecimation,
int verticalPixelDecimation);
virtual ~V4L2Grabber();
public slots:
void setCropping(int cropLeft,
int cropRight,
int cropTop,
int cropBottom);
void setCropping(int cropLeft,
int cropRight,
int cropTop,
int cropBottom);
void set3D(VideoMode mode);
void set3D(VideoMode mode);
void setSignalThreshold(double redSignalThreshold,
double greenSignalThreshold,
double blueSignalThreshold,
int noSignalCounterThreshold);
void setSignalThreshold(double redSignalThreshold,
double greenSignalThreshold,
double blueSignalThreshold,
int noSignalCounterThreshold);
void start();
void start();
void stop();
void stop();
signals:
void newFrame(const Image<ColorRgb> & image);
void newFrame(const Image<ColorRgb> & image);
private slots:
int read_frame();
int read_frame();
private:
void open_device();
void open_device();
void close_device();
void close_device();
void init_read(unsigned int buffer_size);
void init_read(unsigned int buffer_size);
void init_mmap();
void init_mmap();
void init_userp(unsigned int buffer_size);
void init_userp(unsigned int buffer_size);
void init_device(VideoStandard videoStandard, int input);
void init_device(VideoStandard videoStandard, int input);
void uninit_device();
void uninit_device();
void start_capturing();
void start_capturing();
void stop_capturing();
void stop_capturing();
bool process_image(const void *p, int size);
bool process_image(const void *p, int size);
void process_image(const uint8_t *p);
void process_image(const uint8_t *p);
int xioctl(int request, void *arg);
int xioctl(int request, void *arg);
void throw_exception(const std::string &error);
void throw_exception(const std::string &error);
void throw_errno_exception(const std::string &error);
void throw_errno_exception(const std::string &error);
private:
enum io_method {
IO_METHOD_READ,
IO_METHOD_MMAP,
IO_METHOD_USERPTR
};
enum io_method {
IO_METHOD_READ,
IO_METHOD_MMAP,
IO_METHOD_USERPTR
};
struct buffer {
void *start;
size_t length;
};
struct buffer {
void *start;
size_t length;
};
private:
const std::string _deviceName;
const io_method _ioMethod;
int _fileDescriptor;
std::vector<buffer> _buffers;
const std::string _deviceName;
const io_method _ioMethod;
int _fileDescriptor;
std::vector<buffer> _buffers;
PixelFormat _pixelFormat;
int _width;
int _height;
int _lineLength;
int _frameByteSize;
int _frameDecimation;
int _noSignalCounterThreshold;
PixelFormat _pixelFormat;
int _width;
int _height;
int _lineLength;
int _frameByteSize;
int _frameDecimation;
int _noSignalCounterThreshold;
ColorRgb _noSignalThresholdColor;
ColorRgb _noSignalThresholdColor;
int _currentFrame;
int _noSignalCounter;
int _currentFrame;
int _noSignalCounter;
QSocketNotifier * _streamNotifier;
QSocketNotifier * _streamNotifier;
ImageResampler _imageResampler;
ImageResampler _imageResampler;
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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
SET(FramebufferGrabberQT_HEADERS
${CURRENT_HEADER_DIR}/FramebufferWrapper.h
${CURRENT_HEADER_DIR}/FramebufferWrapper.h
)
SET(FramebufferGrabberHEADERS
${CURRENT_HEADER_DIR}/FramebufferFrameGrabber.h
${CURRENT_HEADER_DIR}/FramebufferFrameGrabber.h
)
SET(FramebufferGrabberSOURCES
${CURRENT_SOURCE_DIR}/FramebufferWrapper.cpp
${CURRENT_SOURCE_DIR}/FramebufferFrameGrabber.cpp
${CURRENT_SOURCE_DIR}/FramebufferWrapper.cpp
${CURRENT_SOURCE_DIR}/FramebufferFrameGrabber.cpp
)
if(ENABLE_QT5)
QT5_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS})
else(ENABLE_QT5)
else()
QT4_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS})
endif(ENABLE_QT5)
endif()
add_library(framebuffer-grabber
${FramebufferGrabberHEADERS}
${FramebufferGrabberQT_HEADERS}
${FramebufferGrabberHEADERS_MOC}
${FramebufferGrabberSOURCES}
${FramebufferGrabberHEADERS}
${FramebufferGrabberQT_HEADERS}
${FramebufferGrabberHEADERS_MOC}
${FramebufferGrabberSOURCES}
)
target_link_libraries(framebuffer-grabber
hyperion
${QT_LIBRARIES})
hyperion
${QT_LIBRARIES})

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
SET(OsxGrabberQT_HEADERS
${CURRENT_HEADER_DIR}/OsxWrapper.h
${CURRENT_HEADER_DIR}/OsxWrapper.h
)
SET(OsxGrabberHEADERS
${CURRENT_HEADER_DIR}/OsxFrameGrabber.h
${CURRENT_HEADER_DIR}/OsxFrameGrabber.h
)
SET(OsxGrabberSOURCES
${CURRENT_SOURCE_DIR}/OsxWrapper.cpp
${CURRENT_SOURCE_DIR}/OsxFrameGrabber.cpp
${CURRENT_SOURCE_DIR}/OsxWrapper.cpp
${CURRENT_SOURCE_DIR}/OsxFrameGrabber.cpp
)
if(ENABLE_QT5)
QT5_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS})
else(ENABLE_QT5)
else()
QT4_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS})
endif(ENABLE_QT5)
endif()
add_library(osx-grabber
${OsxGrabberHEADERS}
${OsxGrabberQT_HEADERS}
${OsxGrabberHEADERS_MOC}
${OsxGrabberSOURCES}
${OsxGrabberHEADERS}
${OsxGrabberQT_HEADERS}
${OsxGrabberHEADERS_MOC}
${OsxGrabberSOURCES}
)
target_link_libraries(osx-grabber
hyperion
${QT_LIBRARIES})
hyperion
${QT_LIBRARIES})

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,30 +2,27 @@ add_subdirectory(hyperiond)
add_subdirectory(hyperion-remote)
# The following clients depend on the protobuf library
if(ENABLE_PROTOBUF)
if (ENABLE_AMLOGIC)
add_subdirectory(hyperion-aml)
endif()
if(ENABLE_V4L2)
add_subdirectory(hyperion-v4l2)
endif()
if(ENABLE_X11)
add_subdirectory(hyperion-x11)
endif()
if(ENABLE_DISPMANX)
add_subdirectory(hyperion-dispmanx)
endif()
if(ENABLE_FB)
add_subdirectory(hyperion-framebuffer)
endif()
if(ENABLE_OSX)
add_subdirectory(hyperion-osx)
endif()
if (ENABLE_AMLOGIC)
add_subdirectory(hyperion-aml)
endif()
if(ENABLE_V4L2)
add_subdirectory(hyperion-v4l2)
endif()
if(ENABLE_X11)
add_subdirectory(hyperion-x11)
endif()
if(ENABLE_DISPMANX)
add_subdirectory(hyperion-dispmanx)
endif()
if(ENABLE_FB)
add_subdirectory(hyperion-framebuffer)
endif()
if(ENABLE_OSX)
add_subdirectory(hyperion-osx)
endif()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -31,150 +31,150 @@ using namespace vlofgren;
// save the image as screenshot
void saveScreenshot(void *, const Image<ColorRgb> & image)
{
// store as PNG
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
pngImage.save("screenshot.png");
// store as PNG
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
pngImage.save("screenshot.png");
}
int main(int argc, char** argv)
{
std::cout
<< "hyperion-v4l2:" << std::endl
<< "\tversion : " << HYPERION_VERSION_ID << std::endl
<< "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl;
<< "hyperion-v4l2:" << std::endl
<< "\tversion : " << HYPERION_VERSION_ID << std::endl
<< "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl;
QCoreApplication app(argc, argv);
QCoreApplication app(argc, argv);
// force the locale
setlocale(LC_ALL, "C");
QLocale::setDefault(QLocale::c());
// force the locale
setlocale(LC_ALL, "C");
QLocale::setDefault(QLocale::c());
// register the image type to use in signals
qRegisterMetaType<Image<ColorRgb>>("Image<ColorRgb>");
// register the image type to use in signals
qRegisterMetaType<Image<ColorRgb>>("Image<ColorRgb>");
try
{
// create the option parser and initialize all parameters
OptionsParser optionParser("V4L capture application for Hyperion");
ParameterSet & parameters = optionParser.getParameters();
try
{
// create the option parser and initialize all parameters
OptionsParser optionParser("V4L capture application for Hyperion");
ParameterSet & parameters = optionParser.getParameters();
StringParameter & argDevice = parameters.add<StringParameter> ('d', "device", "The device to use [default: /dev/video0]");
VideoStandardParameter & argVideoStandard = parameters.add<VideoStandardParameter>('v', "video-standard", "The used video standard. Valid values are PAL or NTSC (optional)");
PixelFormatParameter & argPixelFormat = parameters.add<PixelFormatParameter> (0x0, "pixel-format", "The use pixel format. Valid values are YUYV, UYVY, and RGB32 (optional)");
IntParameter & argInput = parameters.add<IntParameter> (0x0, "input", "Input channel (optional)");
IntParameter & argWidth = parameters.add<IntParameter> (0x0, "width", "Try to set the width of the video input (optional)");
IntParameter & argHeight = parameters.add<IntParameter> (0x0, "height", "Try to set the height of the video input (optional)");
IntParameter & argCropWidth = parameters.add<IntParameter> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]");
IntParameter & argCropHeight = parameters.add<IntParameter> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]");
IntParameter & argCropLeft = parameters.add<IntParameter> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
IntParameter & argCropRight = parameters.add<IntParameter> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
IntParameter & argCropTop = parameters.add<IntParameter> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");
IntParameter & argCropBottom = parameters.add<IntParameter> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)");
IntParameter & argSizeDecimation = parameters.add<IntParameter> ('s', "size-decimator", "Decimation factor for the output size [default=1]");
IntParameter & argFrameDecimation = parameters.add<IntParameter> ('f', "frame-decimator", "Decimation factor for the video frames [default=1]");
SwitchParameter<> & argScreenshot = parameters.add<SwitchParameter<>> (0x0, "screenshot", "Take a single screenshot, save it to file and quit");
DoubleParameter & argSignalThreshold = parameters.add<DoubleParameter> ('t', "signal-threshold", "The signal threshold for detecting the presence of a signal. Value should be between 0.0 and 1.0.");
DoubleParameter & argRedSignalThreshold = parameters.add<DoubleParameter> (0x0, "red-threshold", "The red signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
DoubleParameter & argGreenSignalThreshold = parameters.add<DoubleParameter> (0x0, "green-threshold", "The green signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
DoubleParameter & argBlueSignalThreshold = parameters.add<DoubleParameter> (0x0, "blue-threshold", "The blue signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
SwitchParameter<> & arg3DSBS = parameters.add<SwitchParameter<>> (0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
SwitchParameter<> & arg3DTAB = parameters.add<SwitchParameter<>> (0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
StringParameter & argAddress = parameters.add<StringParameter> ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]");
IntParameter & argPriority = parameters.add<IntParameter> ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]");
SwitchParameter<> & argSkipReply = parameters.add<SwitchParameter<>> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<>> ('h', "help", "Show this help message and exit");
StringParameter & argDevice = parameters.add<StringParameter> ('d', "device", "The device to use [default: /dev/video0]");
VideoStandardParameter & argVideoStandard = parameters.add<VideoStandardParameter>('v', "video-standard", "The used video standard. Valid values are PAL or NTSC (optional)");
PixelFormatParameter & argPixelFormat = parameters.add<PixelFormatParameter> (0x0, "pixel-format", "The use pixel format. Valid values are YUYV, UYVY, and RGB32 (optional)");
IntParameter & argInput = parameters.add<IntParameter> (0x0, "input", "Input channel (optional)");
IntParameter & argWidth = parameters.add<IntParameter> (0x0, "width", "Try to set the width of the video input (optional)");
IntParameter & argHeight = parameters.add<IntParameter> (0x0, "height", "Try to set the height of the video input (optional)");
IntParameter & argCropWidth = parameters.add<IntParameter> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]");
IntParameter & argCropHeight = parameters.add<IntParameter> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]");
IntParameter & argCropLeft = parameters.add<IntParameter> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
IntParameter & argCropRight = parameters.add<IntParameter> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
IntParameter & argCropTop = parameters.add<IntParameter> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");
IntParameter & argCropBottom = parameters.add<IntParameter> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)");
IntParameter & argSizeDecimation = parameters.add<IntParameter> ('s', "size-decimator", "Decimation factor for the output size [default=1]");
IntParameter & argFrameDecimation = parameters.add<IntParameter> ('f', "frame-decimator", "Decimation factor for the video frames [default=1]");
SwitchParameter<> & argScreenshot = parameters.add<SwitchParameter<>> (0x0, "screenshot", "Take a single screenshot, save it to file and quit");
DoubleParameter & argSignalThreshold = parameters.add<DoubleParameter> ('t', "signal-threshold", "The signal threshold for detecting the presence of a signal. Value should be between 0.0 and 1.0.");
DoubleParameter & argRedSignalThreshold = parameters.add<DoubleParameter> (0x0, "red-threshold", "The red signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
DoubleParameter & argGreenSignalThreshold = parameters.add<DoubleParameter> (0x0, "green-threshold", "The green signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
DoubleParameter & argBlueSignalThreshold = parameters.add<DoubleParameter> (0x0, "blue-threshold", "The blue signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
SwitchParameter<> & arg3DSBS = parameters.add<SwitchParameter<>> (0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
SwitchParameter<> & arg3DTAB = parameters.add<SwitchParameter<>> (0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
StringParameter & argAddress = parameters.add<StringParameter> ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]");
IntParameter & argPriority = parameters.add<IntParameter> ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]");
SwitchParameter<> & argSkipReply = parameters.add<SwitchParameter<>> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<>> ('h', "help", "Show this help message and exit");
// set defaults
argDevice.setDefault("/dev/video0");
argVideoStandard.setDefault(VIDEOSTANDARD_NO_CHANGE);
argPixelFormat.setDefault(PIXELFORMAT_NO_CHANGE);
argInput.setDefault(-1);
argWidth.setDefault(-1);
argHeight.setDefault(-1);
argCropWidth.setDefault(0);
argCropHeight.setDefault(0);
argSizeDecimation.setDefault(1);
argFrameDecimation.setDefault(1);
argAddress.setDefault("127.0.0.1:19445");
argPriority.setDefault(800);
argSignalThreshold.setDefault(-1);
// set defaults
argDevice.setDefault("/dev/video0");
argVideoStandard.setDefault(VIDEOSTANDARD_NO_CHANGE);
argPixelFormat.setDefault(PIXELFORMAT_NO_CHANGE);
argInput.setDefault(-1);
argWidth.setDefault(-1);
argHeight.setDefault(-1);
argCropWidth.setDefault(0);
argCropHeight.setDefault(0);
argSizeDecimation.setDefault(1);
argFrameDecimation.setDefault(1);
argAddress.setDefault("127.0.0.1:19445");
argPriority.setDefault(800);
argSignalThreshold.setDefault(-1);
// parse all options
optionParser.parse(argc, const_cast<const char **>(argv));
// parse all options
optionParser.parse(argc, const_cast<const char **>(argv));
// check if we need to display the usage. exit if we do.
if (argHelp.isSet())
{
optionParser.usage();
return 0;
}
// check if we need to display the usage. exit if we do.
if (argHelp.isSet())
{
optionParser.usage();
return 0;
}
// cropping values if not defined
if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue());
if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue());
if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue());
if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue());
// cropping values if not defined
if (!argCropLeft.isSet()) argCropLeft.setDefault(argCropWidth.getValue());
if (!argCropRight.isSet()) argCropRight.setDefault(argCropWidth.getValue());
if (!argCropTop.isSet()) argCropTop.setDefault(argCropHeight.getValue());
if (!argCropBottom.isSet()) argCropBottom.setDefault(argCropHeight.getValue());
// initialize the grabber
V4L2Grabber grabber(
argDevice.getValue(),
argInput.getValue(),
argVideoStandard.getValue(),
argPixelFormat.getValue(),
argWidth.getValue(),
argHeight.getValue(),
std::max(1, argFrameDecimation.getValue()),
std::max(1, argSizeDecimation.getValue()),
std::max(1, argSizeDecimation.getValue()));
// initialize the grabber
V4L2Grabber grabber(
argDevice.getValue(),
argInput.getValue(),
argVideoStandard.getValue(),
argPixelFormat.getValue(),
argWidth.getValue(),
argHeight.getValue(),
std::max(1, argFrameDecimation.getValue()),
std::max(1, argSizeDecimation.getValue()),
std::max(1, argSizeDecimation.getValue()));
// set signal detection
grabber.setSignalThreshold(
std::min(1.0, std::max(0.0, argRedSignalThreshold.isSet() ? argRedSignalThreshold.getValue() : argSignalThreshold.getValue())),
std::min(1.0, std::max(0.0, argGreenSignalThreshold.isSet() ? argGreenSignalThreshold.getValue() : argSignalThreshold.getValue())),
std::min(1.0, std::max(0.0, argBlueSignalThreshold.isSet() ? argBlueSignalThreshold.getValue() : argSignalThreshold.getValue())),
50);
// set signal detection
grabber.setSignalThreshold(
std::min(1.0, std::max(0.0, argRedSignalThreshold.isSet() ? argRedSignalThreshold.getValue() : argSignalThreshold.getValue())),
std::min(1.0, std::max(0.0, argGreenSignalThreshold.isSet() ? argGreenSignalThreshold.getValue() : argSignalThreshold.getValue())),
std::min(1.0, std::max(0.0, argBlueSignalThreshold.isSet() ? argBlueSignalThreshold.getValue() : argSignalThreshold.getValue())),
50);
// set cropping values
grabber.setCropping(
std::max(0, argCropLeft.getValue()),
std::max(0, argCropRight.getValue()),
std::max(0, argCropTop.getValue()),
std::max(0, argCropBottom.getValue()));
// set cropping values
grabber.setCropping(
std::max(0, argCropLeft.getValue()),
std::max(0, argCropRight.getValue()),
std::max(0, argCropTop.getValue()),
std::max(0, argCropBottom.getValue()));
// set 3D mode if applicable
if (arg3DSBS.isSet())
{
grabber.set3D(VIDEO_3DSBS);
}
else if (arg3DTAB.isSet())
{
grabber.set3D(VIDEO_3DTAB);
}
// set 3D mode if applicable
if (arg3DSBS.isSet())
{
grabber.set3D(VIDEO_3DSBS);
}
else if (arg3DTAB.isSet())
{
grabber.set3D(VIDEO_3DTAB);
}
// run the grabber
if (argScreenshot.isSet())
{
ScreenshotHandler handler("screenshot.png");
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
grabber.start();
QCoreApplication::exec();
grabber.stop();
}
else
{
ProtoConnectionWrapper handler(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet());
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
grabber.start();
QCoreApplication::exec();
grabber.stop();
}
}
catch (const std::runtime_error & e)
{
// An error occured. Display error and quit
std::cerr << e.what() << std::endl;
return 1;
}
// run the grabber
if (argScreenshot.isSet())
{
ScreenshotHandler handler("screenshot.png");
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
grabber.start();
QCoreApplication::exec();
grabber.stop();
}
else
{
ProtoConnectionWrapper handler(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet());
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
grabber.start();
QCoreApplication::exec();
grabber.stop();
}
}
catch (const std::runtime_error & e)
{
// An error occured. Display error and quit
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
return 0;
}

View File

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

View File

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

View File

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

View File

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