mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
QSocket connection added to hyperion-remote
This commit is contained in:
commit
3f4f1eff74
@ -2,7 +2,7 @@
|
||||
# define the minimum cmake version (as required by cmake)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(CMAKE_TOOLCHAIN_FILE /home/johan/raspberrypi/Toolchain-RaspberryPi.cmake)
|
||||
set(CMAKE_TOOLCHAIN_FILE /opt/raspberrypi/Toolchain-RaspberryPi.cmake)
|
||||
|
||||
# Define the main-project name
|
||||
project(Hyperion)
|
||||
@ -29,6 +29,15 @@ set(CMAKE_BUILD_TYPE "Release")
|
||||
# enable C++11
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall")
|
||||
|
||||
# Configure the use of QT4
|
||||
find_package(Qt4 COMPONENTS QtCore REQUIRED QUIET)
|
||||
|
||||
SET(QT_DONT_USE_QTGUI TRUE)
|
||||
SET(QT_USE_QTCONSOLE TRUE)
|
||||
include(${QT_USE_FILE})
|
||||
add_definitions(${QT_DEFINITIONS})
|
||||
link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf)
|
||||
|
||||
configure_file(bin/install_hyperion.sh ${LIBRARY_OUTPUT_PATH} @ONLY)
|
||||
configure_file(config/hyperion.config.json ${LIBRARY_OUTPUT_PATH} @ONLY)
|
||||
configure_file(config/hyperion.schema.json ${LIBRARY_OUTPUT_PATH} @ONLY)
|
||||
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//these definitions can be expanded to make normal prototypes, or functionpointers and dlsym lines
|
||||
|
||||
BOBLIGHT_FUNCTION(void*, boblight_init, ());
|
||||
BOBLIGHT_FUNCTION(void, boblight_destroy, (void* vpboblight));
|
||||
|
||||
BOBLIGHT_FUNCTION(int, boblight_connect, (void* vpboblight, const char* address, int port, int usectimeout));
|
||||
BOBLIGHT_FUNCTION(int, boblight_setpriority, (void* vpboblight, int priority));
|
||||
BOBLIGHT_FUNCTION(const char*, boblight_geterror, (void* vpboblight));
|
||||
BOBLIGHT_FUNCTION(int, boblight_getnrlights, (void* vpboblight));
|
||||
BOBLIGHT_FUNCTION(const char*, boblight_getlightname, (void* vpboblight, int lightnr));
|
||||
|
||||
BOBLIGHT_FUNCTION(int, boblight_getnroptions, (void* vpboblight));
|
||||
BOBLIGHT_FUNCTION(const char*, boblight_getoptiondescript,(void* vpboblight, int option));
|
||||
BOBLIGHT_FUNCTION(int, boblight_setoption, (void* vpboblight, int lightnr, const char* option));
|
||||
BOBLIGHT_FUNCTION(int, boblight_getoption, (void* vpboblight, int lightnr, const char* option, const char** output));
|
||||
|
||||
BOBLIGHT_FUNCTION(void, boblight_setscanrange, (void* vpboblight, int width, int height));
|
||||
|
||||
BOBLIGHT_FUNCTION(int, boblight_addpixel, (void* vpboblight, int lightnr, int* rgb));
|
||||
BOBLIGHT_FUNCTION(void, boblight_addpixelxy, (void* vpboblight, int x, int y, int* rgb));
|
||||
|
||||
BOBLIGHT_FUNCTION(int, boblight_sendrgb, (void* vpboblight, int sync, int* outputused));
|
||||
BOBLIGHT_FUNCTION(int, boblight_ping, (void* vpboblight, int* outputused));
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//if you define BOBLIGHT_DLOPEN, all boblight functions are defined as pointers
|
||||
//you can then call boblight_loadlibrary to load libboblight with dlopen and the function pointers with dlsym
|
||||
//if you pass NULL to boblight_loadlibrary's first argument, the default filename for libboblight is used
|
||||
//if boblight_loadlibrary returns NULL, dlopen and dlsym went ok, if not it returns a char* from dlerror
|
||||
|
||||
//if you want to use the boblight functions from multiple files, you can define BOBLIGHT_DLOPEN in one file,
|
||||
//and define BOBLIGHT_DLOPEN_EXTERN in the other file, the functionpointers are then defined as extern
|
||||
|
||||
#ifndef LIBBOBLIGHT
|
||||
#define LIBBOBLIGHT
|
||||
|
||||
#if !defined(BOBLIGHT_DLOPEN) && !defined(BOBLIGHT_DLOPEN_EXTERN)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//generate normal prototypes
|
||||
#define BOBLIGHT_FUNCTION(returnvalue, name, arguments) returnvalue name arguments
|
||||
#include "boblight-functions.h"
|
||||
#undef BOBLIGHT_FUNCTION
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif defined(BOBLIGHT_DLOPEN)
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stddef.h>
|
||||
|
||||
//generate function pointers
|
||||
#define BOBLIGHT_FUNCTION(returnvalue, name, arguments) returnvalue (* name ) arguments = NULL
|
||||
#include "boblight-functions.h"
|
||||
#undef BOBLIGHT_FUNCTION
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define BOBLIGHT_CAST(value) reinterpret_cast<value>
|
||||
#else
|
||||
#define BOBLIGHT_CAST(value) (value)
|
||||
#endif
|
||||
|
||||
//gets a functionpointer from dlsym, and returns char* from dlerror if it didn't work
|
||||
#define BOBLIGHT_FUNCTION(returnvalue, name, arguments) \
|
||||
name = BOBLIGHT_CAST(returnvalue (*) arguments)(dlsym(p_boblight, #name)); \
|
||||
{ char* error = dlerror(); if (error) return error; }
|
||||
|
||||
void* p_boblight = NULL; //where we put the lib
|
||||
|
||||
//load function pointers
|
||||
char* boblight_loadlibrary(const char* filename)
|
||||
{
|
||||
if (filename == NULL)
|
||||
filename = "libboblight.so";
|
||||
|
||||
if (p_boblight != NULL)
|
||||
{
|
||||
dlclose(p_boblight);
|
||||
p_boblight = NULL;
|
||||
}
|
||||
|
||||
p_boblight = dlopen(filename, RTLD_NOW);
|
||||
if (p_boblight == NULL)
|
||||
return dlerror();
|
||||
|
||||
//generate dlsym lines
|
||||
#include "boblight-functions.h"
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#undef BOBLIGHT_FUNCTION
|
||||
#undef BOBLIGHT_CAST
|
||||
|
||||
//you can define BOBLIGHT_DLOPEN_EXTERN when you load the library in another file
|
||||
#elif defined(BOBLIGHT_DLOPEN_EXTERN)
|
||||
|
||||
extern char* boblight_loadlibrary(const char* filename);
|
||||
extern void* p_boblight;
|
||||
#define BOBLIGHT_FUNCTION(returnvalue, name, arguments) extern returnvalue (* name ) arguments
|
||||
#include "boblight-functions.h"
|
||||
#undef BOBLIGHT_FUNCTION
|
||||
|
||||
#endif //BOBLIGHT_DLOPEN_EXTERN
|
||||
#endif //LIBBOBLIGHT
|
||||
|
32
include/hyperion/DispmanxWrapper.h
Normal file
32
include/hyperion/DispmanxWrapper.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
// QT includes
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
// Forward class declaration
|
||||
class ImageProcessor;
|
||||
class DispmanxFrameGrabber;
|
||||
|
||||
class DispmanxWrapper: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DispmanxWrapper();
|
||||
|
||||
virtual ~DispmanxWrapper();
|
||||
|
||||
public slots:
|
||||
void start();
|
||||
|
||||
void action();
|
||||
|
||||
void stop();
|
||||
|
||||
private:
|
||||
QTimer _timer;
|
||||
|
||||
DispmanxFrameGrabber* _frameGrabber;
|
||||
ImageProcessor* _processor;
|
||||
};
|
||||
|
@ -4,9 +4,14 @@
|
||||
// hyperion-utils includes
|
||||
#include <utils/RgbImage.h>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/LedString.h>
|
||||
#include <hyperion/ImageToLedsMap.h>
|
||||
#include <hyperion/LedDevice.h>
|
||||
#include <hyperion/PriorityMuxer.h>
|
||||
|
||||
// Forward class declaration
|
||||
namespace hyperion { class ColorTransform; }
|
||||
|
||||
|
||||
class Hyperion
|
||||
{
|
||||
@ -15,27 +20,18 @@ public:
|
||||
|
||||
~Hyperion();
|
||||
|
||||
void setInputSize(const unsigned width, const unsigned height);
|
||||
|
||||
RgbImage& image()
|
||||
{
|
||||
return *mImage;
|
||||
}
|
||||
|
||||
void commit();
|
||||
|
||||
void operator() (const RgbImage& inputImage);
|
||||
|
||||
void setColor(const RgbColor& color);
|
||||
void setValue(int priority, std::vector<RgbColor> &ledColors);
|
||||
|
||||
private:
|
||||
void applyTransform(std::vector<RgbColor>& colors) const;
|
||||
|
||||
LedString mLedString;
|
||||
|
||||
RgbImage* mImage;
|
||||
PriorityMuxer mMuxer;
|
||||
|
||||
ImageToLedsMap mLedsMap;
|
||||
hyperion::ColorTransform* mRedTransform;
|
||||
hyperion::ColorTransform* mGreenTransform;
|
||||
hyperion::ColorTransform* mBlueTransform;
|
||||
|
||||
LedDevice* mDevice;
|
||||
};
|
||||
|
72
include/hyperion/ImageProcessor.h
Normal file
72
include/hyperion/ImageProcessor.h
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// Utils includes
|
||||
#include <utils/RgbImage.h>
|
||||
|
||||
#include <hyperion/LedString.h>
|
||||
#include <hyperion/ImageProcessorFactory.h>
|
||||
|
||||
// Forward class declaration
|
||||
namespace hyperion { class ImageToLedsMap;
|
||||
class ColorTransform; }
|
||||
|
||||
/**
|
||||
* The ImageProcessor translates an RGB-image to RGB-values for the leds. The processing is
|
||||
* performed in two steps. First the average color per led-region is computed. Second a
|
||||
* color-tranform is applied based on a gamma-correction.
|
||||
*/
|
||||
class ImageProcessor
|
||||
{
|
||||
public:
|
||||
~ImageProcessor();
|
||||
|
||||
/**
|
||||
* Processes the image to a list of led colors. This will update the size of the buffer-image
|
||||
* if required and call the image-to-leds mapping to determine the mean color per led.
|
||||
*
|
||||
* @param[in] image The image to translate to led values
|
||||
*
|
||||
* @return The color value per led
|
||||
*/
|
||||
std::vector<RgbColor> process(const RgbImage& image);
|
||||
|
||||
// 'IN PLACE' processing functions
|
||||
|
||||
/**
|
||||
* Specifies the width and height of 'incomming' images. This will resize the buffer-image to
|
||||
* match the given size.
|
||||
* NB All earlier obtained references will be invalid.
|
||||
*
|
||||
* @param[in] width The new width of the buffer-image
|
||||
* @param[in] height The new height of the buffer-image
|
||||
*/
|
||||
void setSize(const unsigned width, const unsigned height);
|
||||
|
||||
/**
|
||||
* Returns a reference of the underlying image-buffer. This can be used to write data directly
|
||||
* into the buffer, avoiding a copy inside the process method.
|
||||
*
|
||||
* @return The reference of the underlying image-buffer.
|
||||
*/
|
||||
RgbImage& image();
|
||||
|
||||
/**
|
||||
* Determines the led colors of the image in the buffer.
|
||||
*
|
||||
* @param[out] ledColors The color value per led
|
||||
*/
|
||||
void inplace_process(std::vector<RgbColor>& ledColors);
|
||||
|
||||
private:
|
||||
friend class ImageProcessorFactory;
|
||||
|
||||
ImageProcessor(const LedString &ledString);
|
||||
|
||||
private:
|
||||
const LedString mLedString;
|
||||
|
||||
RgbImage *mBuffer;
|
||||
hyperion::ImageToLedsMap* mImageToLeds;
|
||||
};
|
||||
|
26
include/hyperion/ImageProcessorFactory.h
Normal file
26
include/hyperion/ImageProcessorFactory.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
// STL includes
|
||||
#include <memory>
|
||||
|
||||
// Jsoncpp includes
|
||||
#include <json/json.h>
|
||||
|
||||
#include <hyperion/LedString.h>
|
||||
|
||||
// Forward class declaration
|
||||
class ImageProcessor;
|
||||
|
||||
class ImageProcessorFactory
|
||||
{
|
||||
public:
|
||||
static ImageProcessorFactory& getInstance();
|
||||
|
||||
public:
|
||||
void init(const LedString& ledString);
|
||||
|
||||
ImageProcessor* newImageProcessor() const;
|
||||
|
||||
private:
|
||||
LedString _ledString;
|
||||
};
|
@ -1,27 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// hyperion-utils includes
|
||||
#include <utils/RgbImage.h>
|
||||
|
||||
// hyperion includes
|
||||
#include <hyperion/LedString.h>
|
||||
|
||||
class ImageToLedsMap
|
||||
{
|
||||
public:
|
||||
|
||||
ImageToLedsMap();
|
||||
|
||||
void createMapping(const RgbImage& image, const std::vector<Led>& leds);
|
||||
|
||||
std::vector<RgbColor> getMeanLedColor();
|
||||
|
||||
RgbColor findMeanColor(const std::vector<const RgbColor*>& colors);
|
||||
|
||||
std::vector<RgbColor> getMedianLedColor();
|
||||
|
||||
RgbColor findMedianColor(std::vector<const RgbColor*>& colors);
|
||||
private:
|
||||
std::vector<std::vector<const RgbColor*> > mColorsMap;
|
||||
};
|
@ -45,28 +45,16 @@ struct Led
|
||||
class LedString
|
||||
{
|
||||
public:
|
||||
static LedString construct(const Json::Value& ledConfig, const Json::Value& colorConfig);
|
||||
static LedString construct(const Json::Value& ledConfig);
|
||||
|
||||
LedString();
|
||||
|
||||
~LedString();
|
||||
|
||||
std::vector<Led>& leds();
|
||||
|
||||
const std::vector<Led>& leds() const;
|
||||
|
||||
private:
|
||||
std::vector<Led> mLeds;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Color adjustements per color
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/** The color gradient */
|
||||
double gamma;
|
||||
/** The color offset */
|
||||
double adjust;
|
||||
/** The minimum required level for the led to turn on */
|
||||
double blacklevel;
|
||||
} red, green, blue;
|
||||
};
|
||||
|
55
include/hyperion/PriorityMuxer.h
Normal file
55
include/hyperion/PriorityMuxer.h
Normal file
@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
// STL includes
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
// QT includes
|
||||
#include <QMap>
|
||||
|
||||
// Utils includes
|
||||
#include <utils/RgbColor.h>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/LedDevice.h>
|
||||
|
||||
class PriorityMuxer
|
||||
{
|
||||
public:
|
||||
struct InputInfo
|
||||
{
|
||||
int priority;
|
||||
|
||||
int64_t timeoutTime_ms;
|
||||
std::vector<RgbColor> ledColors;
|
||||
};
|
||||
|
||||
PriorityMuxer();
|
||||
|
||||
~PriorityMuxer();
|
||||
|
||||
int getCurrentPriority() const;
|
||||
|
||||
bool hasPriority(const int priority) const;
|
||||
|
||||
QList<int> getPriorities() const;
|
||||
|
||||
const InputInfo& getInputInfo(const int priority) const;
|
||||
|
||||
void setInput(const int priority, const std::vector<RgbColor>& ledColors, const int64_t timeoutTime_ms=-1);
|
||||
|
||||
void clearInput(const int priority);
|
||||
|
||||
void clearAll();
|
||||
|
||||
void setCurrentTime(const int64_t& now);
|
||||
|
||||
private:
|
||||
int mCurrentPriority;
|
||||
|
||||
QMap<int, InputInfo> mActiveInputs;
|
||||
|
||||
const static int MAX_PRIORITY = std::numeric_limits<int>::max();
|
||||
};
|
@ -5,7 +5,6 @@
|
||||
#include <stdint.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
// Forward class declaration
|
||||
struct RgbColor;
|
||||
|
||||
@ -21,8 +20,12 @@ struct RgbColor
|
||||
static RgbColor BLUE;
|
||||
static RgbColor YELLOW;
|
||||
static RgbColor WHITE;
|
||||
|
||||
};
|
||||
|
||||
static_assert(sizeof(RgbColor) == 3, "Incorrect size of RgbColor");
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const RgbColor& color)
|
||||
{
|
||||
os << "{" << unsigned(color.red) << "," << unsigned(color.green) << "," << unsigned(color.blue) << "}";
|
||||
|
@ -3,25 +3,7 @@
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc)
|
||||
|
||||
add_library(bob2hyperion SHARED
|
||||
bob2hyperion.cpp)
|
||||
|
||||
target_link_libraries(bob2hyperion
|
||||
hyperion
|
||||
hyperion-utils)
|
||||
|
||||
# Find the libPNG
|
||||
find_package(PNG REQUIRED QUIET)
|
||||
|
||||
# Add additional includes dirs
|
||||
include_directories(${PNG_INCLUDE_DIR})
|
||||
|
||||
add_library(bob2hyperion-png SHARED
|
||||
hyperion-png.cpp)
|
||||
|
||||
target_link_libraries(bob2hyperion-png
|
||||
hyperion-png)
|
||||
|
||||
add_subdirectory(hyperion)
|
||||
add_subdirectory(hyperionpng)
|
||||
add_subdirectory(utils)
|
||||
|
||||
add_subdirectory(hyperionpng)
|
||||
|
@ -1,141 +0,0 @@
|
||||
|
||||
// SysLog includes
|
||||
#include <syslog.h>
|
||||
|
||||
// Boblight includes
|
||||
#include "boblight.h"
|
||||
|
||||
// JsonSchema includes
|
||||
#include <utils/jsonschema/JsonFactory.h>
|
||||
|
||||
// Raspilight includes
|
||||
#include <hyperion/Hyperion.h>
|
||||
|
||||
static std::ofstream sDebugStream;
|
||||
|
||||
inline Hyperion* rasp_cast(void* hyperion_ptr)
|
||||
{
|
||||
return reinterpret_cast<Hyperion*>(hyperion_ptr);
|
||||
}
|
||||
|
||||
void* boblight_init()
|
||||
{
|
||||
std::cout << __PRETTY_FUNCTION__ << std::endl;
|
||||
// syslog(LOG_INFO, __PRETTY_FUNCTION__);
|
||||
|
||||
const char* homeDir = getenv("RASPILIGHT_HOME");
|
||||
if (!homeDir)
|
||||
{
|
||||
homeDir = "/etc";
|
||||
}
|
||||
syslog(LOG_INFO, "RASPILIGHT HOME DIR: %s", homeDir);
|
||||
|
||||
const std::string schemaFile = std::string(homeDir) + "/hyperion.schema.json";
|
||||
const std::string configFile = std::string(homeDir) + "/hyperion.config.json";
|
||||
|
||||
Json::Value raspiConfig;
|
||||
if (JsonFactory::load(schemaFile, configFile, raspiConfig) < 0)
|
||||
{
|
||||
syslog(LOG_WARNING, "UNABLE TO LOAD CONFIGURATION");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Hyperion* raspiLight = new Hyperion(raspiConfig);
|
||||
return reinterpret_cast<void*>(raspiLight);
|
||||
}
|
||||
|
||||
void boblight_destroy(void* hyperion_ptr)
|
||||
{
|
||||
syslog(LOG_INFO, __PRETTY_FUNCTION__);
|
||||
|
||||
Hyperion* raspiLight = rasp_cast(hyperion_ptr);
|
||||
|
||||
// Switch all leds to black (off)
|
||||
raspiLight->setColor(RgbColor::BLACK);
|
||||
|
||||
delete raspiLight;
|
||||
|
||||
sDebugStream.close();
|
||||
}
|
||||
|
||||
void boblight_setscanrange(void* hyperion_ptr, int width, int height)
|
||||
{
|
||||
syslog(LOG_INFO, __PRETTY_FUNCTION__);
|
||||
syslog(LOG_INFO, "Configuring scan range [%dx%d]", width, height);
|
||||
|
||||
Hyperion* raspiLight = rasp_cast(hyperion_ptr);
|
||||
raspiLight->setInputSize(width, height);
|
||||
}
|
||||
|
||||
void boblight_addpixelxy(void* hyperion_ptr, int x, int y, int* rgb)
|
||||
{
|
||||
Hyperion* raspiLight = rasp_cast(hyperion_ptr);
|
||||
const RgbColor color = {uint8_t(rgb[0]), uint8_t(rgb[1]), uint8_t(rgb[2])};
|
||||
raspiLight->image().setPixel(x, y, color);
|
||||
}
|
||||
|
||||
int boblight_sendrgb(void* hyperion_ptr, int sync, int* outputused)
|
||||
{
|
||||
Hyperion* raspiLight = rasp_cast(hyperion_ptr);
|
||||
raspiLight->commit();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int boblight_connect(void* hyperion_ptr, const char* address, int port, int usectimeout)
|
||||
{
|
||||
std::cout << "SUCCESFULL NO CONNECTION WITH BOBLIGHT" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* boblight_geterror(void* hyperion_ptr)
|
||||
{
|
||||
return "ERROR";
|
||||
}
|
||||
|
||||
int boblight_setpriority(void* hyperion_ptr, int priority)
|
||||
{
|
||||
std::cout << __PRETTY_FUNCTION__ << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int boblight_getnrlights(void* hyperion_ptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* boblight_getlightname(void* hyperion_ptr, int lightnr)
|
||||
{
|
||||
return "LIGHT_NAME";
|
||||
}
|
||||
|
||||
int boblight_getnroptions(void* hyperion_ptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* boblight_getoptiondescript(void* hyperion_ptr, int option)
|
||||
{
|
||||
return "OPTION-DESCRIPTION";
|
||||
}
|
||||
|
||||
int boblight_setoption(void* hyperion_ptr, int lightnr, const char* option)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int boblight_getoption(void* hyperion_ptr, int lightnr, const char* option, const char** output)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int boblight_addpixel(void* hyperion_ptr, int lightnr, int* rgb)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int boblight_ping(void* hyperion_ptr, int* outputused)
|
||||
{
|
||||
return 1;
|
||||
}
|
@ -1,174 +0,0 @@
|
||||
|
||||
// STL includes
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
// Boblight includes
|
||||
#include <boblight.h>
|
||||
|
||||
// PNGWriter includes
|
||||
#define NO_FREETYPE
|
||||
#include "hyperionpng/pngwriter.h"
|
||||
|
||||
struct RaspiPng
|
||||
{
|
||||
pngwriter writer;
|
||||
unsigned long fileIndex;
|
||||
|
||||
unsigned frameCnt;
|
||||
|
||||
std::ofstream logFile;
|
||||
};
|
||||
|
||||
void* boblight_init()
|
||||
{
|
||||
RaspiPng* raspiPng = new RaspiPng();
|
||||
|
||||
raspiPng->writer.pngwriter_rename("/home/pi/RASPI_0000.png");
|
||||
raspiPng->fileIndex = 0;
|
||||
raspiPng->frameCnt = 0;
|
||||
raspiPng->logFile.open("/home/pi/raspipng.log");
|
||||
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
return reinterpret_cast<void*>(raspiPng);
|
||||
}
|
||||
|
||||
void boblight_destroy(void* vpboblight)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
raspiPng->logFile.close();
|
||||
delete raspiPng;
|
||||
}
|
||||
|
||||
void boblight_setscanrange(void* vpboblight, int width, int height)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << "(" << width << ", " << height << ")" << std::endl;
|
||||
|
||||
raspiPng->writer.resize(width, height);
|
||||
}
|
||||
|
||||
void boblight_addpixelxy(void* vpboblight, int x, int y, int* rgb)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
|
||||
if (raspiPng->frameCnt%50 == 0)
|
||||
{
|
||||
// NB libpngwriter uses a one-based indexing scheme
|
||||
raspiPng->writer.plot(x+1,y+1, rgb[0]/255.0, rgb[1]/255.0, rgb[2]/255.0);
|
||||
}
|
||||
}
|
||||
|
||||
int boblight_sendrgb(void* vpboblight, int sync, int* outputused)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << "(" << sync << ", outputused) FRAME " << raspiPng->frameCnt++ << std::endl;
|
||||
|
||||
if (raspiPng->frameCnt%50 == 0)
|
||||
{
|
||||
// Write-out the current frame and prepare for the next
|
||||
raspiPng->writer.write_png();
|
||||
|
||||
++raspiPng->fileIndex;
|
||||
char filename[64];
|
||||
|
||||
sprintf(filename, "/home/pi/RASPI_%04ld.png", raspiPng->fileIndex);
|
||||
|
||||
raspiPng->writer.pngwriter_rename(filename);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int boblight_connect(void* vpboblight, const char* address, int port, int usectimeout)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int boblight_setpriority(void* vpboblight, int priority)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* boblight_geterror(void* vpboblight)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
return "ERROR";
|
||||
}
|
||||
|
||||
int boblight_getnrlights(void* vpboblight)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
return 50;
|
||||
}
|
||||
|
||||
const char* boblight_getlightname(void* vpboblight, int lightnr)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
return "LIGHT";
|
||||
}
|
||||
|
||||
int boblight_getnroptions(void* vpboblight)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* boblight_getoptiondescript(void* vpboblight, int option)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
int boblight_setoption(void* vpboblight, int lightnr, const char* option)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int boblight_getoption(void* vpboblight, int lightnr, const char* option, const char** output)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int boblight_addpixel(void* vpboblight, int lightnr, int* rgb)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int boblight_ping(void* vpboblight, int* outputused)
|
||||
{
|
||||
RaspiPng* raspiPng = reinterpret_cast<RaspiPng*>(vpboblight);
|
||||
raspiPng->logFile << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
@ -1,22 +1,57 @@
|
||||
|
||||
# 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/hyperion)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion)
|
||||
|
||||
add_library(hyperion
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(Hyperion_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/DispmanxWrapper.h
|
||||
)
|
||||
|
||||
SET(Hyperion_HEADERS
|
||||
${CURRENT_HEADER_DIR}/LedString.h
|
||||
${CURRENT_HEADER_DIR}/Hyperion.h
|
||||
${CURRENT_HEADER_DIR}/LedDevice.h
|
||||
${CURRENT_HEADER_DIR}/LedString.h
|
||||
${CURRENT_HEADER_DIR}/ImageToLedsMap.h
|
||||
${CURRENT_HEADER_DIR}/ImageProcessor.h
|
||||
${CURRENT_HEADER_DIR}/ImageProcessorFactory.h
|
||||
${CURRENT_HEADER_DIR}/PriorityMuxer.h
|
||||
|
||||
${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.h
|
||||
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageToLedsMap.h
|
||||
${CURRENT_SOURCE_DIR}/ColorTransform.h
|
||||
)
|
||||
|
||||
SET(Hyperion_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/LedString.cpp
|
||||
${CURRENT_SOURCE_DIR}/Hyperion.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
|
||||
${CURRENT_SOURCE_DIR}/ColorTransform.h
|
||||
${CURRENT_SOURCE_DIR}/ColorTransform.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageProcessor.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp
|
||||
${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp
|
||||
|
||||
${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp
|
||||
${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp
|
||||
|
||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp
|
||||
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
|
||||
${CURRENT_SOURCE_DIR}/ColorTransform.cpp
|
||||
)
|
||||
|
||||
QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
|
||||
|
||||
add_library(hyperion
|
||||
${Hyperion_HEADERS}
|
||||
${Hyperion_QT_HEADERS}
|
||||
${Hyperion_HEADERS_MOC}
|
||||
${Hyperion_SOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(hyperion
|
||||
hyperion-utils)
|
||||
hyperion-utils
|
||||
${QT_LIBRARIES}
|
||||
${BCM_LIBRARIES})
|
||||
|
@ -1,23 +1,26 @@
|
||||
// STL includes
|
||||
#include <cmath>
|
||||
|
||||
#include "ColorTransform.h"
|
||||
|
||||
using namespace hyperion;
|
||||
|
||||
ColorTransform::ColorTransform() :
|
||||
_threshold(0),
|
||||
_gamma(1.0),
|
||||
_blacklevel(0.0),
|
||||
_whitelevel(1.0)
|
||||
_threshold(0),
|
||||
_gamma(1.0),
|
||||
_blacklevel(0.0),
|
||||
_whitelevel(1.0)
|
||||
{
|
||||
initializeMapping();
|
||||
initializeMapping();
|
||||
}
|
||||
|
||||
ColorTransform::ColorTransform(double threshold, double gamma, double blacklevel, double whitelevel) :
|
||||
_threshold(threshold),
|
||||
_gamma(gamma),
|
||||
_blacklevel(blacklevel),
|
||||
_whitelevel(whitelevel)
|
||||
_threshold(threshold),
|
||||
_gamma(gamma),
|
||||
_blacklevel(blacklevel),
|
||||
_whitelevel(whitelevel)
|
||||
{
|
||||
initializeMapping();
|
||||
initializeMapping();
|
||||
}
|
||||
|
||||
ColorTransform::~ColorTransform()
|
||||
@ -26,77 +29,77 @@ ColorTransform::~ColorTransform()
|
||||
|
||||
double ColorTransform::getThreshold() const
|
||||
{
|
||||
return _threshold;
|
||||
return _threshold;
|
||||
}
|
||||
|
||||
void ColorTransform::setThreshold(double threshold)
|
||||
{
|
||||
_threshold = threshold;
|
||||
initializeMapping();
|
||||
_threshold = threshold;
|
||||
initializeMapping();
|
||||
}
|
||||
|
||||
double ColorTransform::getGamma() const
|
||||
{
|
||||
return _gamma;
|
||||
return _gamma;
|
||||
}
|
||||
|
||||
void ColorTransform::setGamma(double gamma)
|
||||
{
|
||||
_gamma = gamma;
|
||||
initializeMapping();
|
||||
_gamma = gamma;
|
||||
initializeMapping();
|
||||
}
|
||||
|
||||
double ColorTransform::getBlacklevel() const
|
||||
{
|
||||
return _blacklevel;
|
||||
return _blacklevel;
|
||||
}
|
||||
|
||||
void ColorTransform::setBlacklevel(double blacklevel)
|
||||
{
|
||||
_blacklevel = blacklevel;
|
||||
initializeMapping();
|
||||
_blacklevel = blacklevel;
|
||||
initializeMapping();
|
||||
}
|
||||
|
||||
double ColorTransform::getWhitelevel() const
|
||||
{
|
||||
return _whitelevel;
|
||||
return _whitelevel;
|
||||
}
|
||||
|
||||
void ColorTransform::setWhitelevel(double whitelevel)
|
||||
{
|
||||
_whitelevel = whitelevel;
|
||||
initializeMapping();
|
||||
_whitelevel = whitelevel;
|
||||
initializeMapping();
|
||||
}
|
||||
|
||||
void ColorTransform::initializeMapping()
|
||||
{
|
||||
// initialize the mapping as a linear array
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
double output = i / 255.0;
|
||||
// initialize the mapping as a linear array
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
double output = i / 255.0;
|
||||
|
||||
// apply linear transform
|
||||
if (output < _threshold)
|
||||
{
|
||||
output = 0.0;
|
||||
}
|
||||
// apply linear transform
|
||||
if (output < _threshold)
|
||||
{
|
||||
output = 0.0;
|
||||
}
|
||||
|
||||
// apply gamma correction
|
||||
output = std::pow(output, _gamma);
|
||||
// apply gamma correction
|
||||
output = std::pow(output, _gamma);
|
||||
|
||||
// apply blacklevel and whitelevel
|
||||
output = _blacklevel + (_whitelevel - _blacklevel) * output;
|
||||
// apply blacklevel and whitelevel
|
||||
output = _blacklevel + (_whitelevel - _blacklevel) * output;
|
||||
|
||||
// calc mapping
|
||||
int mappingValue = output * 255;
|
||||
if (mappingValue < 0)
|
||||
{
|
||||
mappingValue = 0;
|
||||
}
|
||||
else if (mappingValue > 255)
|
||||
{
|
||||
mappingValue = 255;
|
||||
}
|
||||
_mapping[i] = mappingValue;
|
||||
}
|
||||
// calc mapping
|
||||
int mappingValue = output * 255;
|
||||
if (mappingValue < 0)
|
||||
{
|
||||
mappingValue = 0;
|
||||
}
|
||||
else if (mappingValue > 255)
|
||||
{
|
||||
mappingValue = 255;
|
||||
}
|
||||
_mapping[i] = mappingValue;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdint.h"
|
||||
// STL includes
|
||||
#include <cstdint>
|
||||
|
||||
namespace hyperion
|
||||
{
|
||||
|
||||
/// Transform for a single color byte value
|
||||
///
|
||||
@ -14,36 +18,38 @@
|
||||
class ColorTransform
|
||||
{
|
||||
public:
|
||||
ColorTransform();
|
||||
ColorTransform(double threshold, double gamma, double whitelevel, double blacklevel);
|
||||
~ColorTransform();
|
||||
ColorTransform();
|
||||
ColorTransform(double threshold, double gamma, double blacklevel, double whitelevel);
|
||||
~ColorTransform();
|
||||
|
||||
double getThreshold() const;
|
||||
void setThreshold(double threshold);
|
||||
double getThreshold() const;
|
||||
void setThreshold(double threshold);
|
||||
|
||||
double getGamma() const;
|
||||
void setGamma(double gamma);
|
||||
double getGamma() const;
|
||||
void setGamma(double gamma);
|
||||
|
||||
double getBlacklevel() const;
|
||||
void setBlacklevel(double blacklevel);
|
||||
double getBlacklevel() const;
|
||||
void setBlacklevel(double blacklevel);
|
||||
|
||||
double getWhitelevel() const;
|
||||
void setWhitelevel(double whitelevel);
|
||||
double getWhitelevel() const;
|
||||
void setWhitelevel(double whitelevel);
|
||||
|
||||
/// get the transformed value for the given byte value
|
||||
uint8_t transform(uint8_t input) const
|
||||
{
|
||||
return _mapping[input];
|
||||
}
|
||||
/// get the transformed value for the given byte value
|
||||
uint8_t transform(uint8_t input) const
|
||||
{
|
||||
return _mapping[input];
|
||||
}
|
||||
|
||||
private:
|
||||
void initializeMapping();
|
||||
void initializeMapping();
|
||||
|
||||
private:
|
||||
double _threshold;
|
||||
double _gamma;
|
||||
double _blacklevel;
|
||||
double _whitelevel;
|
||||
double _threshold;
|
||||
double _gamma;
|
||||
double _blacklevel;
|
||||
double _whitelevel;
|
||||
|
||||
uint8_t _mapping[256];
|
||||
uint8_t _mapping[256];
|
||||
};
|
||||
|
||||
} // end namespace hyperion
|
||||
|
56
libsrc/hyperion/DispmanxFrameGrabber.cpp
Normal file
56
libsrc/hyperion/DispmanxFrameGrabber.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
#include "DispmanxFrameGrabber.h"
|
||||
|
||||
DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned height) :
|
||||
_display(0),
|
||||
_resource(0),
|
||||
_width(width),
|
||||
_height(height)
|
||||
{
|
||||
// Initiase BCM
|
||||
bcm_host_init();
|
||||
|
||||
// Open the connection to the displaydisplay
|
||||
_display = vc_dispmanx_display_open(0);
|
||||
int ret = vc_dispmanx_display_get_info(_display, &_info);
|
||||
// Make the compiler (in release mode) happy by 'using' ret
|
||||
(void)ret;
|
||||
assert(ret == 0);
|
||||
|
||||
// Create the resources for capturing image
|
||||
_resource = vc_dispmanx_resource_create(
|
||||
VC_IMAGE_RGB888,
|
||||
width,
|
||||
height,
|
||||
&_vc_image_ptr);
|
||||
assert(_resource);
|
||||
|
||||
// Define the capture rectangle with the same size
|
||||
vc_dispmanx_rect_set(&_rectangle, 0, 0, width, height);
|
||||
_pitch = width * 3;
|
||||
}
|
||||
|
||||
DispmanxFrameGrabber::~DispmanxFrameGrabber()
|
||||
{
|
||||
// Clean up resources
|
||||
vc_dispmanx_resource_delete(_resource);
|
||||
|
||||
// Close the displaye
|
||||
vc_dispmanx_display_close(_display);
|
||||
|
||||
// De-init BCM
|
||||
bcm_host_deinit();
|
||||
}
|
||||
|
||||
void DispmanxFrameGrabber::grabFrame(RgbImage& image)
|
||||
{
|
||||
// Sanity check of the given image size
|
||||
assert(image.width() == _width && image.height() == _height);
|
||||
|
||||
void* image_ptr = image.memptr();
|
||||
|
||||
// Create the snapshot
|
||||
vc_dispmanx_snapshot(_display, _resource, VC_IMAGE_ROT0);
|
||||
// Read the snapshot into the memory (incl down-scaling)
|
||||
vc_dispmanx_resource_read_data(_resource, &_rectangle, image_ptr, _pitch);
|
||||
}
|
36
libsrc/hyperion/DispmanxFrameGrabber.h
Normal file
36
libsrc/hyperion/DispmanxFrameGrabber.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
// BCM includes
|
||||
#pragma GCC system_header
|
||||
#include <bcm_host.h>
|
||||
|
||||
// STL includes
|
||||
#include <cstdint>
|
||||
|
||||
// Utils includes
|
||||
#include <utils/RgbImage.h>
|
||||
|
||||
///
|
||||
/// The DispmanxFrameGrabber grabs
|
||||
///
|
||||
class DispmanxFrameGrabber
|
||||
{
|
||||
public:
|
||||
DispmanxFrameGrabber(const unsigned width, const unsigned height);
|
||||
~DispmanxFrameGrabber();
|
||||
|
||||
void grabFrame(RgbImage& image);
|
||||
|
||||
private:
|
||||
DISPMANX_DISPLAY_HANDLE_T _display;
|
||||
DISPMANX_MODEINFO_T _info;
|
||||
|
||||
DISPMANX_RESOURCE_HANDLE_T _resource;
|
||||
|
||||
uint32_t _vc_image_ptr;
|
||||
|
||||
VC_RECT_T _rectangle;
|
||||
unsigned _width;
|
||||
unsigned _height;
|
||||
uint32_t _pitch;
|
||||
};
|
49
libsrc/hyperion/DispmanxWrapper.cpp
Normal file
49
libsrc/hyperion/DispmanxWrapper.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
// QT includes
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/DispmanxWrapper.h>
|
||||
#include <hyperion/ImageProcessorFactory.h>
|
||||
#include <hyperion/ImageProcessor.h>
|
||||
|
||||
|
||||
// Local-Hyperion includes
|
||||
#include "DispmanxFrameGrabber.h"
|
||||
|
||||
DispmanxWrapper::DispmanxWrapper() :
|
||||
_timer(),
|
||||
_frameGrabber(new DispmanxFrameGrabber(64, 64)),
|
||||
_processor(ImageProcessorFactory::getInstance().newImageProcessor())
|
||||
{
|
||||
_timer.setInterval(100);
|
||||
_timer.setSingleShot(false);
|
||||
|
||||
_processor->setSize(64, 64);
|
||||
|
||||
QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(action()));
|
||||
}
|
||||
|
||||
DispmanxWrapper::~DispmanxWrapper()
|
||||
{
|
||||
delete _processor;
|
||||
delete _frameGrabber;
|
||||
}
|
||||
|
||||
void DispmanxWrapper::start()
|
||||
{
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
void DispmanxWrapper::action()
|
||||
{
|
||||
qDebug() << "[" << QDateTime::currentDateTimeUtc() << "] Grabbing frame";
|
||||
RgbImage image(64, 64);
|
||||
_frameGrabber->grabFrame(image);
|
||||
|
||||
//_processor->
|
||||
}
|
||||
void DispmanxWrapper::stop()
|
||||
{
|
||||
_timer.stop();
|
||||
}
|
@ -10,6 +10,9 @@
|
||||
#include <hyperion/LedDevice.h>
|
||||
|
||||
#include "LedDeviceWs2801.h"
|
||||
#include "ColorTransform.h"
|
||||
|
||||
using namespace hyperion;
|
||||
|
||||
LedDevice* constructDevice(const Json::Value& deviceConfig)
|
||||
{
|
||||
@ -34,9 +37,41 @@ LedDevice* constructDevice(const Json::Value& deviceConfig)
|
||||
return device;
|
||||
}
|
||||
|
||||
ColorTransform* createColorTransform(const Json::Value& colorConfig)
|
||||
{
|
||||
const double threshold = colorConfig["threshold"].asDouble();
|
||||
const double gamma = colorConfig["gamma"].asDouble();
|
||||
const double blacklevel = colorConfig["blacklevel"].asDouble();
|
||||
const double whitelevel = colorConfig["whitelevel"].asDouble();
|
||||
|
||||
ColorTransform* transform = new ColorTransform(threshold, gamma, blacklevel, whitelevel);
|
||||
return transform;
|
||||
}
|
||||
LedString createLedString(const Json::Value& ledsConfig)
|
||||
{
|
||||
LedString ledString;
|
||||
|
||||
for (const Json::Value& ledConfig : ledsConfig)
|
||||
{
|
||||
Led led;
|
||||
led.index = ledConfig["index"].asInt();
|
||||
const Json::Value& hscanConfig = ledConfig["hscan"];
|
||||
const Json::Value& vscanConfig = ledConfig["vscan"];
|
||||
led.minX_frac = std::max(0.0, std::min(100.0, hscanConfig["minimum"].asDouble()))/100.0;
|
||||
led.maxX_frac = std::max(0.0, std::min(100.0, hscanConfig["maximum"].asDouble()))/100.0;
|
||||
led.minY_frac = 1.0 - std::max(0.0, std::min(100.0, vscanConfig["maximum"].asDouble()))/100.0;
|
||||
led.maxY_frac = 1.0 - std::max(0.0, std::min(100.0, vscanConfig["minimum"].asDouble()))/100.0;
|
||||
|
||||
ledString.leds().push_back(led);
|
||||
}
|
||||
return ledString;
|
||||
}
|
||||
|
||||
Hyperion::Hyperion(const Json::Value &jsonConfig) :
|
||||
mLedString(LedString::construct(jsonConfig["leds"], jsonConfig["color"])),
|
||||
mImage(nullptr),
|
||||
mLedString(createLedString(jsonConfig["leds"])),
|
||||
mRedTransform( createColorTransform(jsonConfig["color"]["red"])),
|
||||
mGreenTransform(createColorTransform(jsonConfig["color"]["green"])),
|
||||
mBlueTransform( createColorTransform(jsonConfig["color"]["blue"])),
|
||||
mDevice(constructDevice(jsonConfig["device"]))
|
||||
{
|
||||
// empty
|
||||
@ -45,58 +80,29 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) :
|
||||
|
||||
Hyperion::~Hyperion()
|
||||
{
|
||||
// Delete the existing image (or delete nullptr)
|
||||
delete mImage;
|
||||
|
||||
// Delete the Led-String
|
||||
delete mDevice;
|
||||
|
||||
// Delete the color-transform
|
||||
delete mBlueTransform;
|
||||
delete mGreenTransform;
|
||||
delete mRedTransform;
|
||||
}
|
||||
|
||||
void Hyperion::setInputSize(const unsigned width, const unsigned height)
|
||||
void Hyperion::setValue(int priority, std::vector<RgbColor>& ledColors)
|
||||
{
|
||||
// Delete the existing image (or delete nullptr)
|
||||
delete mImage;
|
||||
|
||||
// Create the new image with the mapping to the leds
|
||||
mImage = new RgbImage(width, height);
|
||||
mLedsMap.createMapping(*mImage, mLedString.leds());
|
||||
}
|
||||
|
||||
void Hyperion::commit()
|
||||
{
|
||||
// Derive the color per led
|
||||
std::vector<RgbColor> ledColors = mLedsMap.getMeanLedColor();
|
||||
// const std::vector<RgbColor> ledColors = mLedsMap.getMedianLedColor();
|
||||
|
||||
// Write the Led colors to the led-string
|
||||
mDevice->write(ledColors);
|
||||
}
|
||||
|
||||
void Hyperion::operator() (const RgbImage& inputImage)
|
||||
{
|
||||
// Copy the input-image into the buffer
|
||||
mImage->copy(inputImage);
|
||||
|
||||
// Derive the color per led
|
||||
std::vector<RgbColor> ledColors = mLedsMap.getMeanLedColor();
|
||||
// std::vector<RgbColor> ledColors = mLedsMap.getMedianLedColor();
|
||||
applyTransform(ledColors);
|
||||
|
||||
// Write the Led colors to the led-string
|
||||
mDevice->write(ledColors);
|
||||
}
|
||||
|
||||
void Hyperion::setColor(const RgbColor& color)
|
||||
{
|
||||
mDevice->write(std::vector<RgbColor>(mLedString.leds().size(), color));
|
||||
}
|
||||
|
||||
void Hyperion::applyTransform(std::vector<RgbColor>& colors) const
|
||||
{
|
||||
for (RgbColor& color : colors)
|
||||
// Apply the transform to each led and color-channel
|
||||
for (RgbColor& color : ledColors)
|
||||
{
|
||||
color.red = (color.red < mLedString.red.blacklevel)? 0 : mLedString.red.adjust + mLedString.red.gamma * color.red;
|
||||
color.green = (color.green < mLedString.green.blacklevel)? 0 : mLedString.green.adjust + mLedString.green.gamma * color.green;
|
||||
color.blue = (color.blue < mLedString.blue.blacklevel)? 0 : mLedString.blue.adjust + mLedString.blue.gamma * color.blue;
|
||||
color.red = mRedTransform->transform(color.red);
|
||||
color.green = mGreenTransform->transform(color.green);
|
||||
color.blue = mBlueTransform->transform(color.blue);
|
||||
}
|
||||
|
||||
mMuxer.setInput(priority, ledColors);
|
||||
|
||||
if (priority == mMuxer.getCurrentPriority())
|
||||
{
|
||||
mDevice->write(ledColors);
|
||||
}
|
||||
}
|
||||
|
65
libsrc/hyperion/ImageProcessor.cpp
Normal file
65
libsrc/hyperion/ImageProcessor.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#include <hyperion/ImageProcessor.h>
|
||||
|
||||
|
||||
#include "ImageToLedsMap.h"
|
||||
#include "ColorTransform.h"
|
||||
|
||||
using namespace hyperion;
|
||||
|
||||
ImageProcessor::ImageProcessor(const LedString& ledString) :
|
||||
mLedString(ledString),
|
||||
mBuffer(nullptr),
|
||||
mImageToLeds(nullptr)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
ImageProcessor::~ImageProcessor()
|
||||
{
|
||||
delete mImageToLeds;
|
||||
delete mBuffer;
|
||||
}
|
||||
|
||||
std::vector<RgbColor> ImageProcessor::process(const RgbImage& image)
|
||||
{
|
||||
// Ensure that the buffer-image is the proper size
|
||||
setSize(image.width(), image.height());
|
||||
|
||||
// Copy the data of the given image into the mapped-image
|
||||
mBuffer->copy(image);
|
||||
|
||||
// Create a result vector and call the 'in place' functionl
|
||||
std::vector<RgbColor> colors(mLedString.leds().size(), RgbColor::BLACK);
|
||||
inplace_process(colors);
|
||||
|
||||
// return the computed colors
|
||||
return colors;
|
||||
}
|
||||
|
||||
void ImageProcessor::setSize(const unsigned width, const unsigned height)
|
||||
{
|
||||
// Check if the existing buffer-image is already the correct dimensions
|
||||
if (mBuffer && mBuffer->width() == width && mBuffer->height() == height)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Clean up the old buffer and mapping
|
||||
delete mImageToLeds;
|
||||
delete mBuffer;
|
||||
|
||||
// Construct a new buffer and mapping
|
||||
mBuffer = new RgbImage(width, height);
|
||||
mImageToLeds = new ImageToLedsMap(*mBuffer, mLedString.leds());
|
||||
}
|
||||
|
||||
RgbImage& ImageProcessor::image()
|
||||
{
|
||||
return *mBuffer;
|
||||
}
|
||||
|
||||
void ImageProcessor::inplace_process(std::vector<RgbColor>& ledColors)
|
||||
{
|
||||
// Determine the mean-colors of each led (using the existing mapping)
|
||||
mImageToLeds->getMeanLedColor(ledColors);
|
||||
}
|
21
libsrc/hyperion/ImageProcessorFactory.cpp
Normal file
21
libsrc/hyperion/ImageProcessorFactory.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/ImageProcessorFactory.h>
|
||||
#include <hyperion/ImageProcessor.h>
|
||||
|
||||
ImageProcessorFactory& ImageProcessorFactory::getInstance()
|
||||
{
|
||||
static ImageProcessorFactory instance;
|
||||
// Return the singleton instance
|
||||
return instance;
|
||||
}
|
||||
|
||||
void ImageProcessorFactory::init(const LedString& ledString)
|
||||
{
|
||||
_ledString = ledString;
|
||||
}
|
||||
|
||||
ImageProcessor* ImageProcessorFactory::newImageProcessor() const
|
||||
{
|
||||
return new ImageProcessor(_ledString);
|
||||
}
|
@ -3,14 +3,11 @@
|
||||
#include <algorithm>
|
||||
|
||||
// hyperion includes
|
||||
#include <hyperion/ImageToLedsMap.h>
|
||||
#include "ImageToLedsMap.h"
|
||||
|
||||
ImageToLedsMap::ImageToLedsMap()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
using namespace hyperion;
|
||||
|
||||
void ImageToLedsMap::createMapping(const RgbImage& image, const std::vector<Led>& leds)
|
||||
ImageToLedsMap::ImageToLedsMap(const RgbImage& image, const std::vector<Led>& leds)
|
||||
{
|
||||
mColorsMap.resize(leds.size(), std::vector<const RgbColor*>());
|
||||
|
||||
@ -46,6 +43,19 @@ std::vector<RgbColor> ImageToLedsMap::getMeanLedColor()
|
||||
return colors;
|
||||
}
|
||||
|
||||
void ImageToLedsMap::getMeanLedColor(std::vector<RgbColor>& ledColors)
|
||||
{
|
||||
// Sanity check for the number of leds
|
||||
assert(mColorsMap.size() == ledColors.size());
|
||||
|
||||
auto led = ledColors.begin();
|
||||
for (auto ledColors = mColorsMap.begin(); ledColors != mColorsMap.end(); ++ledColors, ++led)
|
||||
{
|
||||
const RgbColor color = findMeanColor(*ledColors);
|
||||
*led = color;
|
||||
}
|
||||
}
|
||||
|
||||
RgbColor ImageToLedsMap::findMeanColor(const std::vector<const RgbColor*>& colors)
|
||||
{
|
||||
uint_fast16_t cummRed = 0;
|
||||
@ -64,27 +74,3 @@ RgbColor ImageToLedsMap::findMeanColor(const std::vector<const RgbColor*>& color
|
||||
|
||||
return {avgRed, avgGreen, avgBlue};
|
||||
}
|
||||
|
||||
std::vector<RgbColor> ImageToLedsMap::getMedianLedColor()
|
||||
{
|
||||
std::vector<RgbColor> ledColors;
|
||||
for (std::vector<const RgbColor*>& colors : mColorsMap)
|
||||
{
|
||||
const RgbColor color = findMedianColor(colors);
|
||||
ledColors.push_back(color);
|
||||
}
|
||||
|
||||
return ledColors;
|
||||
}
|
||||
|
||||
RgbColor ImageToLedsMap::findMedianColor(std::vector<const RgbColor*>& colors)
|
||||
{
|
||||
std::sort(colors.begin(), colors.end(), [](const RgbColor* lhs, const RgbColor* rhs){ return lhs->red < rhs->red; });
|
||||
const uint8_t red = colors.at(colors.size()/2)->red;
|
||||
std::sort(colors.begin(), colors.end(), [](const RgbColor* lhs, const RgbColor* rhs){ return lhs->green < rhs->green; });
|
||||
const uint8_t green = colors.at(colors.size()/2)->green;
|
||||
std::sort(colors.begin(), colors.end(), [](const RgbColor* lhs, const RgbColor* rhs){ return lhs->blue < rhs->blue; });
|
||||
const uint8_t blue = colors.at(colors.size()/2)->blue;
|
||||
|
||||
return {red, green, blue};
|
||||
}
|
||||
|
57
libsrc/hyperion/ImageToLedsMap.h
Normal file
57
libsrc/hyperion/ImageToLedsMap.h
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// hyperion-utils includes
|
||||
#include <utils/RgbImage.h>
|
||||
|
||||
// hyperion includes
|
||||
#include <hyperion/LedString.h>
|
||||
|
||||
namespace hyperion
|
||||
{
|
||||
|
||||
class ImageToLedsMap
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs an mapping from the colors in the image to each led based on the border
|
||||
* definition given in the list of leds. The map holds pointers to the given image and its
|
||||
* lifetime should never exceed that of the given image
|
||||
*
|
||||
* @param[in] image The RGB image
|
||||
* @param[in] leds The list with led specifications
|
||||
*/
|
||||
ImageToLedsMap(const RgbImage& image, const std::vector<Led>& leds);
|
||||
|
||||
/**
|
||||
* Determines the mean-color for each led using the mapping the image given
|
||||
* at construction.
|
||||
*
|
||||
* @return ledColors The vector containing the output
|
||||
*/
|
||||
std::vector<RgbColor> getMeanLedColor();
|
||||
|
||||
/**
|
||||
* Determines the mean-color for each led using the mapping the image given
|
||||
* at construction.
|
||||
*
|
||||
* @param[out] ledColors The vector containing the output
|
||||
*/
|
||||
void getMeanLedColor(std::vector<RgbColor>& ledColors);
|
||||
|
||||
private:
|
||||
std::vector<std::vector<const RgbColor*> > mColorsMap;
|
||||
|
||||
/**
|
||||
* Finds the 'mean color' of the given list. This is the mean over each color-channel (red,
|
||||
* green, blue)
|
||||
*
|
||||
* @param colors The list with colors
|
||||
*
|
||||
* @return The mean of the given list of colors (or black when empty)
|
||||
*/
|
||||
RgbColor findMeanColor(const std::vector<const RgbColor*>& colors);
|
||||
};
|
||||
|
||||
} // end namespace hyperion
|
@ -9,41 +9,6 @@
|
||||
// hyperion includes
|
||||
#include <hyperion/LedString.h>
|
||||
|
||||
LedString LedString::construct(const Json::Value& ledsConfig, const Json::Value& colorConfig)
|
||||
{
|
||||
LedString ledString;
|
||||
|
||||
const Json::Value& redConfig = colorConfig["red"];
|
||||
const Json::Value& greenConfig = colorConfig["greem"];
|
||||
const Json::Value& blueConfig = colorConfig["blue"];
|
||||
|
||||
ledString.red.gamma = redConfig["gamma"].asDouble();
|
||||
ledString.red.adjust = redConfig["adjust"].asDouble();
|
||||
ledString.red.blacklevel = redConfig["blacklevel"].asDouble();
|
||||
|
||||
ledString.green.gamma = greenConfig["gamma"].asDouble();
|
||||
ledString.green.adjust = colorConfig["adjust"].asDouble();
|
||||
ledString.green.blacklevel = colorConfig["blacklevel"].asDouble();
|
||||
|
||||
ledString.blue.gamma = blueConfig["gamma"].asDouble();
|
||||
ledString.blue.adjust = blueConfig["adjust"].asDouble();
|
||||
ledString.blue.blacklevel = blueConfig["blacklevel"].asDouble();
|
||||
|
||||
for (const Json::Value& ledConfig : ledsConfig)
|
||||
{
|
||||
Led led;
|
||||
led.index = ledConfig["index"].asInt();
|
||||
const Json::Value& hscanConfig = ledConfig["hscan"];
|
||||
const Json::Value& vscanConfig = ledConfig["vscan"];
|
||||
led.minX_frac = std::max(0.0, std::min(100.0, hscanConfig["minimum"].asDouble()))/100.0;
|
||||
led.maxX_frac = std::max(0.0, std::min(100.0, hscanConfig["maximum"].asDouble()))/100.0;
|
||||
led.minY_frac = 1.0 - std::max(0.0, std::min(100.0, vscanConfig["maximum"].asDouble()))/100.0;
|
||||
led.maxY_frac = 1.0 - std::max(0.0, std::min(100.0, vscanConfig["minimum"].asDouble()))/100.0;
|
||||
|
||||
ledString.mLeds.push_back(led);
|
||||
}
|
||||
return ledString;
|
||||
}
|
||||
|
||||
LedString::LedString()
|
||||
{
|
||||
@ -54,6 +19,11 @@ LedString::~LedString()
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<Led>& LedString::leds()
|
||||
{
|
||||
return mLeds;
|
||||
}
|
||||
|
||||
const std::vector<Led>& LedString::leds() const
|
||||
{
|
||||
return mLeds;
|
||||
|
94
libsrc/hyperion/PriorityMuxer.cpp
Normal file
94
libsrc/hyperion/PriorityMuxer.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
|
||||
// STL includes
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/PriorityMuxer.h>
|
||||
|
||||
PriorityMuxer::PriorityMuxer() :
|
||||
mCurrentPriority(MAX_PRIORITY)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
PriorityMuxer::~PriorityMuxer()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
int PriorityMuxer::getCurrentPriority() const
|
||||
{
|
||||
return mCurrentPriority;
|
||||
}
|
||||
|
||||
QList<int> PriorityMuxer::getPriorities() const
|
||||
{
|
||||
return mActiveInputs.keys();
|
||||
}
|
||||
|
||||
bool PriorityMuxer::hasPriority(const int priority) const
|
||||
{
|
||||
return mActiveInputs.contains(priority);
|
||||
}
|
||||
|
||||
const PriorityMuxer::InputInfo& PriorityMuxer::getInputInfo(const int priority) const
|
||||
{
|
||||
auto elemIt = mActiveInputs.find(priority);
|
||||
if (elemIt == mActiveInputs.end())
|
||||
{
|
||||
throw std::runtime_error("no such priority");
|
||||
}
|
||||
return elemIt.value();
|
||||
}
|
||||
|
||||
void PriorityMuxer::setInput(const int priority, const std::vector<RgbColor>& ledColors, const int64_t timeoutTime_ms)
|
||||
{
|
||||
InputInfo& input = mActiveInputs[priority];
|
||||
input.priority = priority;
|
||||
input.timeoutTime_ms = timeoutTime_ms;
|
||||
input.ledColors = ledColors;
|
||||
|
||||
mCurrentPriority = std::min(mCurrentPriority, priority);
|
||||
}
|
||||
|
||||
void PriorityMuxer::clearInput(const int priority)
|
||||
{
|
||||
mActiveInputs.remove(priority);
|
||||
if (mCurrentPriority == priority)
|
||||
{
|
||||
if (mActiveInputs.empty())
|
||||
{
|
||||
mCurrentPriority = MAX_PRIORITY;
|
||||
}
|
||||
else
|
||||
{
|
||||
QList<int> keys = mActiveInputs.keys();
|
||||
mCurrentPriority = *std::min_element(keys.begin(), keys.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PriorityMuxer::clearAll()
|
||||
{
|
||||
mActiveInputs.clear();
|
||||
mCurrentPriority = MAX_PRIORITY;
|
||||
}
|
||||
|
||||
void PriorityMuxer::setCurrentTime(const int64_t& now)
|
||||
{
|
||||
mCurrentPriority = MAX_PRIORITY;
|
||||
|
||||
for (auto infoIt = mActiveInputs.begin(); infoIt != mActiveInputs.end();)
|
||||
{
|
||||
if (infoIt->timeoutTime_ms != -1 && infoIt->timeoutTime_ms <= now)
|
||||
{
|
||||
infoIt = mActiveInputs.erase(infoIt);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentPriority = std::min(mCurrentPriority, infoIt->priority);
|
||||
++infoIt;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -2,38 +2,11 @@
|
||||
add_executable(WriteConfig
|
||||
WriteConfig.cpp)
|
||||
|
||||
add_executable(boblight-dispmanx
|
||||
boblight-dispmanx.cpp
|
||||
flagmanager.h
|
||||
flagmanager.cpp
|
||||
flagmanager-dispmanx.h
|
||||
flagmanager-dispmanx.cpp
|
||||
grabber-dispmanx.h
|
||||
grabber-dispmanx.cpp
|
||||
misc.h
|
||||
misc.cpp
|
||||
timer.h
|
||||
timer.cpp
|
||||
timeutils.h
|
||||
timeutils.cpp)
|
||||
|
||||
# Find the BCM-package (VC control)
|
||||
find_package(BCM REQUIRED)
|
||||
|
||||
include_directories(${BCM_INCLUDE_DIRS})
|
||||
|
||||
target_link_libraries(boblight-dispmanx
|
||||
# hyperion-png
|
||||
bob2hyperion
|
||||
${BCM_LIBRARIES})
|
||||
|
||||
add_executable(HyperionDispmanX
|
||||
HyperionDispmanX.cpp)
|
||||
|
||||
target_link_libraries(HyperionDispmanX
|
||||
hyperion
|
||||
${BCM_LIBRARIES})
|
||||
add_executable(hyperiond
|
||||
hyperion-d.cpp)
|
||||
|
||||
target_link_libraries(hyperiond
|
||||
hyperion)
|
||||
|
||||
# Find the libPNG
|
||||
find_package(PNG QUIET)
|
||||
@ -47,10 +20,7 @@ if(PNG_FOUND)
|
||||
|
||||
target_link_libraries(ViewPng
|
||||
hyperion
|
||||
hyperion-utils
|
||||
${PNG_LIBRARIES})
|
||||
endif(PNG_FOUND)
|
||||
|
||||
add_subdirectory(dispmanx-png)
|
||||
add_subdirectory(hyperion-remote)
|
||||
|
||||
|
@ -1,49 +0,0 @@
|
||||
|
||||
// VC includes
|
||||
#include <bcm_host.h>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/Hyperion.h>
|
||||
|
||||
#include <json/json.h>
|
||||
#include <utils/jsonschema/JsonFactory.h>
|
||||
|
||||
|
||||
#include "dispmanx-helper.h"
|
||||
|
||||
static volatile bool sRunning = true;
|
||||
|
||||
void signal_handler(int signum)
|
||||
{
|
||||
std::cout << "RECEIVED SIGNAL: " << signum << std::endl;
|
||||
sRunning = false;
|
||||
}
|
||||
|
||||
int main(int /*argc*/, char** /*argv*/)
|
||||
{
|
||||
// Install signal-handlers to exit the processing loop
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGINT, signal_handler);
|
||||
|
||||
const char* homeDir = getenv("RASPILIGHT_HOME");
|
||||
if (!homeDir)
|
||||
{
|
||||
homeDir = "/etc";
|
||||
}
|
||||
std::cout << "RASPILIGHT HOME DIR: " << homeDir << std::endl;
|
||||
|
||||
const std::string schemaFile = std::string(homeDir) + "/hyperion.schema.json";
|
||||
const std::string configFile = std::string(homeDir) + "/hyperion.config.json";
|
||||
|
||||
Json::Value raspiConfig;
|
||||
if (JsonFactory::load(schemaFile, configFile, raspiConfig) < 0)
|
||||
{
|
||||
std::cerr << "UNABLE TO LOAD CONFIGURATION" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
Hyperion hyperion(raspiConfig);
|
||||
|
||||
dispmanx_process(hyperion, sRunning);
|
||||
|
||||
return 0;
|
||||
}
|
@ -144,10 +144,10 @@ int main(int argc, char** argv)
|
||||
FbWriter fbWriter;
|
||||
|
||||
Hyperion raspiLight(raspiConfig);
|
||||
raspiLight.setInputSize(image->width(), image->height());
|
||||
// raspiLight.setInputSize(image->width(), image->height());
|
||||
|
||||
fbWriter.writeImage(*image);
|
||||
raspiLight(*image);
|
||||
// raspiLight(*image);
|
||||
|
||||
sleep(5);
|
||||
|
||||
|
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#define BOBLIGHT_DLOPEN
|
||||
#include "boblight.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//#include "config.h"
|
||||
#include "misc.h"
|
||||
#include "flagmanager-dispmanx.h"
|
||||
#include "grabber-dispmanx.h"
|
||||
|
||||
//OpenMax includes
|
||||
#include "bcm_host.h"
|
||||
#include <assert.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define TEST_SAVE_IMAGE 0
|
||||
#define PRINT_RET_VAL(ret, func, ...) ret = func(__VA_ARGS__); printf(#func " returned %d\n", ret);
|
||||
|
||||
int Run();
|
||||
void SignalHandler(int signum);
|
||||
|
||||
volatile bool stop = false;
|
||||
|
||||
CFlagManagerDispmanX g_flagmanager;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
std::cout << "HACKED VERSION WITH TIMOLIGHT" << std::endl;
|
||||
//load the boblight lib, if it fails we get a char* from dlerror()
|
||||
// char* boblight_error = boblight_loadlibrary(NULL);
|
||||
// if (boblight_error)
|
||||
// {
|
||||
// PrintError(boblight_error);
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
//try to parse the flags and bitch to stderr if there's an error
|
||||
try
|
||||
{
|
||||
g_flagmanager.ParseFlags(argc, argv);
|
||||
}
|
||||
catch (string error)
|
||||
{
|
||||
PrintError(error);
|
||||
g_flagmanager.PrintHelpMessage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (g_flagmanager.m_printhelp) //print help message
|
||||
{
|
||||
g_flagmanager.PrintHelpMessage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (g_flagmanager.m_printboblightoptions) //print boblight options (-o [light:]option=value)
|
||||
{
|
||||
g_flagmanager.PrintBoblightOptions();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (g_flagmanager.m_fork)
|
||||
{
|
||||
if (fork())
|
||||
return 0;
|
||||
}
|
||||
|
||||
//set up signal handlers
|
||||
signal(SIGTERM, SignalHandler);
|
||||
signal(SIGINT, SignalHandler);
|
||||
|
||||
//keep running until we want to quit
|
||||
return Run();
|
||||
}
|
||||
|
||||
int Run()
|
||||
{
|
||||
while(!stop)
|
||||
{
|
||||
//init boblight
|
||||
void* boblight = boblight_init();
|
||||
|
||||
cout << "Connecting to boblightd\n";
|
||||
|
||||
//try to connect, if we can't then bitch to stderr and destroy boblight
|
||||
if (!boblight_connect(boblight, g_flagmanager.m_address, g_flagmanager.m_port, 5000000) ||
|
||||
!boblight_setpriority(boblight, g_flagmanager.m_priority))
|
||||
{
|
||||
PrintError(boblight_geterror(boblight));
|
||||
cout << "Waiting 10 seconds before trying again\n";
|
||||
boblight_destroy(boblight);
|
||||
sleep(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
cout << "Connection to boblightd opened\n";
|
||||
|
||||
//try to parse the boblight flags and bitch to stderr if we can't
|
||||
try
|
||||
{
|
||||
g_flagmanager.ParseBoblightOptions(boblight);
|
||||
}
|
||||
catch (string error)
|
||||
{
|
||||
PrintError(error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CGrabberDispmanX *grabber = new CGrabberDispmanX(boblight, stop, g_flagmanager.m_sync);
|
||||
|
||||
grabber->SetInterval(g_flagmanager.m_interval);
|
||||
grabber->SetSize(g_flagmanager.m_pixels);
|
||||
|
||||
if (!grabber->Setup()) //just exit if we can't set up the grabber
|
||||
{
|
||||
PrintError(grabber->GetError());
|
||||
delete grabber;
|
||||
boblight_destroy(boblight);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!grabber->Run()) //just exit if some unrecoverable error happens
|
||||
{
|
||||
PrintError(grabber->GetError());
|
||||
delete grabber;
|
||||
boblight_destroy(boblight);
|
||||
return 1;
|
||||
}
|
||||
else //boblightd probably timed out, so just try to reconnect
|
||||
{
|
||||
if (!grabber->GetError().empty())
|
||||
PrintError(grabber->GetError());
|
||||
}
|
||||
|
||||
delete grabber;
|
||||
|
||||
boblight_destroy(boblight);
|
||||
}
|
||||
|
||||
cout << "Exiting\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SignalHandler(int signum)
|
||||
{
|
||||
if (signum == SIGTERM)
|
||||
{
|
||||
cout << "caught SIGTERM\n";
|
||||
stop = true;
|
||||
}
|
||||
else if (signum == SIGINT)
|
||||
{
|
||||
cout << "caught SIGINT\n";
|
||||
stop = true;
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// VC includes
|
||||
#include <bcm_host.h>
|
||||
|
||||
template <typename Hyperion_T>
|
||||
int dispmanx_process(Hyperion_T& hyperion, volatile bool& running)
|
||||
{
|
||||
// Configure the used image size
|
||||
const unsigned width = 64;
|
||||
const unsigned height = 64;
|
||||
hyperion.setInputSize(width, height);
|
||||
|
||||
// Initiase BCM
|
||||
bcm_host_init();
|
||||
|
||||
// Open the connection to the displaydisplay
|
||||
DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(0);
|
||||
DISPMANX_MODEINFO_T info;
|
||||
int ret = vc_dispmanx_display_get_info(display, &info);
|
||||
assert(ret == 0);
|
||||
|
||||
// Create the resources for capturing image
|
||||
uint32_t vc_image_ptr;
|
||||
DISPMANX_RESOURCE_HANDLE_T resource = vc_dispmanx_resource_create(
|
||||
VC_IMAGE_RGB888,
|
||||
width,
|
||||
height,
|
||||
&vc_image_ptr);
|
||||
assert(resource);
|
||||
|
||||
VC_RECT_T rectangle;
|
||||
vc_dispmanx_rect_set(&rectangle, 0, 0, width, height);
|
||||
|
||||
void* image_ptr = hyperion.image().memptr();
|
||||
const uint32_t pitch = width * 3;
|
||||
|
||||
timespec updateInterval;
|
||||
updateInterval.tv_sec = 0;
|
||||
updateInterval.tv_nsec = 100000000;
|
||||
while(running)
|
||||
{
|
||||
vc_dispmanx_snapshot(display, resource, VC_IMAGE_ROT0);
|
||||
vc_dispmanx_resource_read_data(resource, &rectangle, image_ptr, pitch);
|
||||
|
||||
hyperion.commit();
|
||||
|
||||
nanosleep(&updateInterval, NULL);
|
||||
}
|
||||
|
||||
// Clean up resources
|
||||
vc_dispmanx_resource_delete(resource);
|
||||
vc_dispmanx_display_close(display);
|
||||
|
||||
// De-init BCM
|
||||
bcm_host_deinit();
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
|
||||
# Find the BCM-package (VC control)
|
||||
find_package(BCM REQUIRED)
|
||||
|
||||
# Add the include dirs to the search path
|
||||
include_directories(${BCM_INCLUDE_DIRS})
|
||||
|
||||
add_executable(dispmanx-png
|
||||
dispmanx-png.cpp)
|
||||
|
||||
target_link_libraries(dispmanx-png
|
||||
hyperion-png
|
||||
${BCM_LIBRARIES})
|
@ -1,28 +0,0 @@
|
||||
|
||||
// STL includes
|
||||
#include <csignal>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperionpng/HyperionPng.h>
|
||||
|
||||
#include "../dispmanx-helper.h"
|
||||
|
||||
static volatile bool sRunning = true;
|
||||
|
||||
void signal_handler(int signum)
|
||||
{
|
||||
std::cout << "RECEIVED SIGNAL: " << signum << std::endl;
|
||||
sRunning = false;
|
||||
}
|
||||
|
||||
|
||||
int main(int /*argc*/, char** /*argv*/)
|
||||
{
|
||||
// Install signal-handlers to exit the processing loop
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGINT, signal_handler);
|
||||
|
||||
// Construct and initialise the PNG creator with preset size
|
||||
HyperionPng hyperion;
|
||||
return dispmanx_process(hyperion, sRunning);
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "flagmanager-dispmanx.h"
|
||||
//#include "config.h"
|
||||
#include "misc.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
CFlagManagerDispmanX::CFlagManagerDispmanX()
|
||||
{
|
||||
//extend the base getopt flags
|
||||
//i = interval, u = pixels, x = xgetimage, d = debug
|
||||
m_flags += "i:u:d::";
|
||||
|
||||
m_interval = 0.1; //default interval is 100 milliseconds
|
||||
m_pixels = 64; //-1 says to the capture classes to use default
|
||||
m_debug = false; //no debugging by default
|
||||
m_debugdpy = NULL; //default debug dpy is system default
|
||||
m_sync = true; //sync mode enabled by default
|
||||
}
|
||||
|
||||
void CFlagManagerDispmanX::ParseFlagsExtended(int& argc, char**& argv, int& c, char*& optarg) //we load our own flags here
|
||||
{
|
||||
if (c == 'i') //interval
|
||||
{
|
||||
bool vblank = false;
|
||||
|
||||
if (optarg[0] == 'v') //starting interval with v means vblank interval
|
||||
{
|
||||
#ifdef HAVE_LIBGL
|
||||
optarg++;
|
||||
vblank = true;
|
||||
#else
|
||||
throw string("Compiled without opengl support");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!StrToFloat(optarg, m_interval) || m_interval <= 0.0)
|
||||
{
|
||||
throw string("Wrong value " + string(optarg) + " for interval");
|
||||
}
|
||||
|
||||
if (vblank)
|
||||
{
|
||||
if (m_interval < 1.0)
|
||||
{
|
||||
throw string("Wrong value " + string(optarg) + " for vblank interval");
|
||||
}
|
||||
m_interval *= -1.0; //negative interval means vblank
|
||||
optarg--;
|
||||
}
|
||||
}
|
||||
else if (c == 'u') //nr of pixels to use
|
||||
{
|
||||
if (!StrToInt(optarg, m_pixels) || m_pixels <= 0)
|
||||
{
|
||||
throw string("Wrong value " + string(optarg) + " for pixels");
|
||||
}
|
||||
}
|
||||
else if (c == 'd') //turn on debug mode
|
||||
{
|
||||
m_debug = true;
|
||||
if (optarg) //optional debug dpy
|
||||
{
|
||||
m_strdebugdpy = optarg;
|
||||
m_debugdpy = m_strdebugdpy.c_str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CFlagManagerDispmanX::PrintHelpMessage()
|
||||
{
|
||||
cout << "Usage: boblight-dispmanx [OPTION]\n";
|
||||
cout << "\n";
|
||||
cout << " options:\n";
|
||||
cout << "\n";
|
||||
cout << " -p priority, from 0 to 255, default is 128\n";
|
||||
cout << " -s address:[port], set the address and optional port to connect to\n";
|
||||
cout << " -o add libboblight option, syntax: [light:]option=value\n";
|
||||
cout << " -l list libboblight options\n";
|
||||
cout << " -i set the interval in seconds, default is 0.1\n";
|
||||
cout << " -u set the number of pixels/rows to use\n";
|
||||
cout << " default is 64 for xrender and 16 for xgetimage\n";
|
||||
cout << " -d debug mode\n";
|
||||
cout << " -f fork\n";
|
||||
cout << " -y set the sync mode, default is on, valid options are \"on\" and \"off\"\n";
|
||||
cout << "\n";
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FLAGMANAGERDISPMANX
|
||||
#define FLAGMANAGERDISPMANX
|
||||
|
||||
#include "flagmanager.h"
|
||||
|
||||
class CFlagManagerDispmanX : public CFlagManager
|
||||
{
|
||||
public:
|
||||
CFlagManagerDispmanX();
|
||||
|
||||
int m_color;
|
||||
|
||||
void ParseFlagsExtended(int& argc, char**& argv, int& c, char*& optarg); //we load our own flags here
|
||||
void PrintHelpMessage();
|
||||
|
||||
double m_interval; //grab interval in seconds, or vertical blanks when negative
|
||||
int m_pixels; //number of pixels on lines to capture
|
||||
bool m_debug; //if true we make a little window where we put our captured output on, looks pretty
|
||||
const char* m_debugdpy; //display to place the debug window on, default is NULL
|
||||
|
||||
private:
|
||||
|
||||
std::string m_strdebugdpy; //place to store the debug dpy, cause our copied argv is destroyed
|
||||
};
|
||||
|
||||
#endif //FLAGMANAGEROPENMAX
|
@ -1,257 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "flagmanager.h"
|
||||
#include "misc.h"
|
||||
|
||||
//#define BOBLIGHT_DLOPEN_EXTERN
|
||||
#include "boblight.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
//very simple, store a copy of argc and argv
|
||||
CArguments::CArguments(int argc, char** argv)
|
||||
{
|
||||
m_argc = argc;
|
||||
|
||||
if (m_argc == 0)
|
||||
{
|
||||
m_argv = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_argv = new char*[m_argc];
|
||||
for (int i = 0; i < m_argc; i++)
|
||||
{
|
||||
m_argv[i] = new char[strlen(argv[i]) + 1];
|
||||
strcpy(m_argv[i], argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//delete the copy of argv
|
||||
CArguments::~CArguments()
|
||||
{
|
||||
if (m_argv)
|
||||
{
|
||||
for (int i = 0; i < m_argc; i++)
|
||||
{
|
||||
delete[] m_argv[i];
|
||||
}
|
||||
delete[] m_argv;
|
||||
}
|
||||
}
|
||||
|
||||
CFlagManager::CFlagManager()
|
||||
{
|
||||
m_port = -1; //-1 tells libboblight to use default port
|
||||
m_address = NULL; //NULL tells libboblight to use default address
|
||||
m_priority = 128; //default priority
|
||||
m_printhelp = false; //don't print helpmessage unless asked to
|
||||
m_printboblightoptions = false; //same for libboblight options
|
||||
m_fork = false; //don't fork by default
|
||||
m_sync = false; //sync mode disabled by default
|
||||
|
||||
// default getopt flags, can be extended in derived classes
|
||||
// p = priority, s = address[:port], o = boblight option, l = list boblight options, h = print help message, f = fork
|
||||
m_flags = "p:s:o:lhfy:";
|
||||
}
|
||||
|
||||
void CFlagManager::ParseFlags(int tempargc, char** tempargv)
|
||||
{
|
||||
//that copy class sure comes in handy now!
|
||||
CArguments arguments(tempargc, tempargv);
|
||||
int argc = arguments.m_argc;
|
||||
char** argv = arguments.m_argv;
|
||||
|
||||
string option;
|
||||
int c;
|
||||
|
||||
opterr = 0; //we don't want to print error messages
|
||||
|
||||
while ((c = getopt(argc, argv, m_flags.c_str())) != -1)
|
||||
{
|
||||
if (c == 'p') //priority
|
||||
{
|
||||
option = optarg;
|
||||
if (!StrToInt(option, m_priority) || m_priority < 0 || m_priority > 255)
|
||||
{
|
||||
throw string("Wrong option " + string(optarg) + " for argument -p");
|
||||
}
|
||||
}
|
||||
else if (c == 's') //address[:port]
|
||||
{
|
||||
option = optarg;
|
||||
//store address in string and set the char* to it
|
||||
m_straddress = option.substr(0, option.find(':'));
|
||||
m_address = m_straddress.c_str();
|
||||
|
||||
if (option.find(':') != string::npos) //check if we have a port
|
||||
{
|
||||
option = option.substr(option.find(':') + 1);
|
||||
string word;
|
||||
if (!StrToInt(option, m_port) || m_port < 0 || m_port > 65535)
|
||||
{
|
||||
throw string("Wrong option " + string(optarg) + " for argument -s");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (c == 'o') //option for libboblight
|
||||
{
|
||||
m_options.push_back(optarg);
|
||||
}
|
||||
else if (c == 'l') //list libboblight options
|
||||
{
|
||||
m_printboblightoptions = true;
|
||||
return;
|
||||
}
|
||||
else if (c == 'h') //print help message
|
||||
{
|
||||
m_printhelp = true;
|
||||
return;
|
||||
}
|
||||
else if (c == 'f')
|
||||
{
|
||||
m_fork = true;
|
||||
}
|
||||
else if (c == 'y')
|
||||
{
|
||||
if (!StrToBool(optarg, m_sync))
|
||||
{
|
||||
throw string("Wrong value " + string(optarg) + " for sync mode");
|
||||
}
|
||||
}
|
||||
else if (c == '?') //unknown option
|
||||
{
|
||||
//check if we know this option, but expected an argument
|
||||
if (m_flags.find(ToString((char)optopt) + ":") != string::npos)
|
||||
{
|
||||
throw string("Option " + ToString((char)optopt) + "requires an argument");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw string("Unkown option " + ToString((char)optopt));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ParseFlagsExtended(argc, argv, c, optarg); //pass our argument to a derived class
|
||||
}
|
||||
}
|
||||
|
||||
PostGetopt(optind, argc, argv); //some postprocessing
|
||||
}
|
||||
|
||||
//go through all options and print the descriptions to stdout
|
||||
void CFlagManager::PrintBoblightOptions()
|
||||
{
|
||||
void* boblight = boblight_init();
|
||||
int nroptions = boblight_getnroptions(boblight);
|
||||
|
||||
for (int i = 0; i < nroptions; i++)
|
||||
{
|
||||
cout << boblight_getoptiondescript(boblight, i) << "\n";
|
||||
}
|
||||
|
||||
boblight_destroy(boblight);
|
||||
}
|
||||
|
||||
void CFlagManager::ParseBoblightOptions(void* boblight)
|
||||
{
|
||||
int nrlights = boblight_getnrlights(boblight);
|
||||
|
||||
for (int i = 0; i < m_options.size(); i++)
|
||||
{
|
||||
string option = m_options[i];
|
||||
string lightname;
|
||||
string optionname;
|
||||
string optionvalue;
|
||||
int lightnr = -1;
|
||||
|
||||
//check if we have a lightname, otherwise we use all lights
|
||||
if (option.find(':') != string::npos)
|
||||
{
|
||||
lightname = option.substr(0, option.find(':'));
|
||||
if (option.find(':') == option.size() - 1) //check if : isn't the last char in the string
|
||||
{
|
||||
throw string("wrong option \"" + option + "\", syntax is [light:]option=value");
|
||||
}
|
||||
option = option.substr(option.find(':') + 1); //shave off the lightname
|
||||
|
||||
//check which light this is
|
||||
bool lightfound = false;
|
||||
for (int j = 0; j < nrlights; j++)
|
||||
{
|
||||
if (lightname == boblight_getlightname(boblight, j))
|
||||
{
|
||||
lightfound = true;
|
||||
lightnr = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!lightfound)
|
||||
{
|
||||
throw string("light \"" + lightname + "\" used in option \"" + m_options[i] + "\" doesn't exist");
|
||||
}
|
||||
}
|
||||
|
||||
//check if '=' exists and it's not at the end of the string
|
||||
if (option.find('=') == string::npos || option.find('=') == option.size() - 1)
|
||||
{
|
||||
throw string("wrong option \"" + option + "\", syntax is [light:]option=value");
|
||||
}
|
||||
|
||||
optionname = option.substr(0, option.find('=')); //option name is everything before = (already shaved off the lightname here)
|
||||
optionvalue = option.substr(option.find('=') + 1); //value is everything after =
|
||||
|
||||
option = optionname + " " + optionvalue; //libboblight wants syntax without =
|
||||
|
||||
//bitch if we can't set this option
|
||||
if (!boblight_setoption(boblight, lightnr, option.c_str()))
|
||||
{
|
||||
throw string(boblight_geterror(boblight));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CFlagManager::SetVideoGamma()
|
||||
{
|
||||
for (int i = 0; i < m_options.size(); i++)
|
||||
{
|
||||
string option = m_options[i];
|
||||
if (option.find(':') != string::npos)
|
||||
option = option.substr(option.find(':') + 1); //shave off the lightname
|
||||
|
||||
if (option.find('=') != string::npos)
|
||||
{
|
||||
if (option.substr(0, option.find('=')) == "gamma")
|
||||
return false; //gamma set by user, don't override
|
||||
}
|
||||
}
|
||||
|
||||
m_options.push_back("gamma=" + ToString(VIDEOGAMMA));
|
||||
|
||||
cout << "Gamma not set, using " << VIDEOGAMMA << " since this is default for video\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FLAGMANAGER
|
||||
#define FLAGMANAGER
|
||||
|
||||
#define VIDEOGAMMA 2.2
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
//class for making a copy of argc and argv
|
||||
class CArguments
|
||||
{
|
||||
public:
|
||||
CArguments(int argc, char** argv);
|
||||
~CArguments();
|
||||
|
||||
int m_argc;
|
||||
char** m_argv;
|
||||
};
|
||||
|
||||
class CFlagManager
|
||||
{
|
||||
public:
|
||||
CFlagManager();
|
||||
|
||||
bool m_printhelp; //if we need to print the help message
|
||||
bool m_printboblightoptions; //if we need to print the boblight options
|
||||
|
||||
const char* m_address; //address to connect to, set to NULL if none given for default
|
||||
int m_port; //port to connect to, set to -1 if none given for default
|
||||
int m_priority; //priority, set to 128 if none given for default
|
||||
bool m_fork; //if we should fork
|
||||
bool m_sync; //if sync mode is enabled
|
||||
|
||||
void ParseFlags(int tempargc, char** tempargv); //parsing commandline flags
|
||||
virtual void PrintHelpMessage() {};
|
||||
|
||||
void PrintBoblightOptions(); //printing of boblight options (-o [light:]option=value)
|
||||
void ParseBoblightOptions(void* boblight); //parsing of boblight options
|
||||
bool SetVideoGamma(); //set gamma to 2.2 if not given, returns true if done
|
||||
|
||||
protected:
|
||||
|
||||
std::string m_flags; //string to pass to getopt, for example "c:r:a:p"
|
||||
std::string m_straddress; //place to store address to connect to, because CArguments deletes argv
|
||||
|
||||
std::vector<std::string> m_options; //place to store boblight options
|
||||
|
||||
//gets called from ParseFlags, for derived classes
|
||||
virtual void ParseFlagsExtended(int& argc, char**& argv, int& c, char*& optarg){};
|
||||
//gets called after getopt
|
||||
virtual void PostGetopt(int optind, int argc, char** argv) {};
|
||||
};
|
||||
|
||||
#endif //FLAGMANAGER
|
@ -1,165 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
#include "grabber-dispmanx.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
//#define BOBLIGHT_DLOPEN_EXTERN
|
||||
#include "boblight.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
CGrabberDispmanX::CGrabberDispmanX(void* boblight, volatile bool& stop, bool sync) : m_stop(stop), m_timer(&stop)
|
||||
{
|
||||
int ret;
|
||||
|
||||
bcm_host_init();
|
||||
|
||||
m_boblight = boblight;
|
||||
m_debug = false;
|
||||
m_sync = sync;
|
||||
|
||||
type = VC_IMAGE_RGB888;
|
||||
|
||||
display = vc_dispmanx_display_open(0);
|
||||
|
||||
ret = vc_dispmanx_display_get_info(display, &info);
|
||||
assert(ret == 0);
|
||||
}
|
||||
|
||||
CGrabberDispmanX::~CGrabberDispmanX()
|
||||
{
|
||||
int ret;
|
||||
|
||||
free(image);
|
||||
|
||||
ret = vc_dispmanx_resource_delete(resource);
|
||||
assert( ret == 0 );
|
||||
ret = vc_dispmanx_display_close(display);
|
||||
assert( ret == 0 );
|
||||
|
||||
bcm_host_deinit();
|
||||
}
|
||||
|
||||
bool CGrabberDispmanX::Setup()
|
||||
{
|
||||
if (m_interval > 0.0) //set up timer
|
||||
{
|
||||
m_timer.SetInterval(Round64(m_interval * 1000000.0));
|
||||
}
|
||||
|
||||
pitch = ALIGN_UP(m_size*3, 32);
|
||||
|
||||
image = new char[m_size * m_size * 3];
|
||||
|
||||
resource = vc_dispmanx_resource_create(type,
|
||||
m_size,
|
||||
m_size,
|
||||
&vc_image_ptr );
|
||||
assert(resource);
|
||||
|
||||
m_error.clear();
|
||||
|
||||
return ExtendedSetup(); //run stuff from derived classes
|
||||
}
|
||||
|
||||
bool CGrabberDispmanX::ExtendedSetup()
|
||||
{
|
||||
if (!CheckExtensions())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGrabberDispmanX::CheckExtensions()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGrabberDispmanX::Run()
|
||||
{
|
||||
int rgb[3];
|
||||
VC_RECT_T rectangle;
|
||||
char* image_ptr;
|
||||
|
||||
boblight_setscanrange(m_boblight, m_size, m_size);
|
||||
|
||||
while(!m_stop)
|
||||
{
|
||||
vc_dispmanx_snapshot(display,resource, VC_IMAGE_ROT0);
|
||||
|
||||
vc_dispmanx_rect_set(&rectangle, 0, 0, m_size, m_size);
|
||||
|
||||
vc_dispmanx_resource_read_data(resource, &rectangle, image, m_size*3);
|
||||
|
||||
image_ptr = (char *)image;
|
||||
//read out the pixels
|
||||
for (int y = 0; y < m_size && !m_stop; y++)
|
||||
{
|
||||
// image_ptr += y*m_size*3;
|
||||
for (int x = 0; x < m_size && !m_stop; x++)
|
||||
{
|
||||
rgb[0] = image_ptr[y*m_size*3+x*3];
|
||||
rgb[1] = image_ptr[y*m_size*3+x*3 + 1];
|
||||
rgb[2] = image_ptr[y*m_size*3+x*3 + 2];
|
||||
|
||||
boblight_addpixelxy(m_boblight, x, y, rgb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//send pixeldata to boblight
|
||||
if (!boblight_sendrgb(m_boblight, m_sync, NULL))
|
||||
{
|
||||
m_error = boblight_geterror(m_boblight);
|
||||
return true; //recoverable error
|
||||
}
|
||||
|
||||
//when in debug mode, put the captured image on the debug window
|
||||
if (m_debug)
|
||||
{
|
||||
printf("Debug not supproted!\n");
|
||||
m_debug = false;
|
||||
}
|
||||
|
||||
if (!Wait())
|
||||
{
|
||||
return false; //unrecoverable error
|
||||
}
|
||||
}
|
||||
|
||||
m_error.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGrabberDispmanX::Wait()
|
||||
{
|
||||
if (m_interval > 0.0) //wait for timer
|
||||
{
|
||||
m_timer.Wait();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRABBERDISPMANX
|
||||
#define GRABBERDISPMANX
|
||||
|
||||
#include "bcm_host.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
//#include "config.h"
|
||||
#include "timer.h"
|
||||
|
||||
#ifndef ALIGN_UP
|
||||
#define ALIGN_UP(x,y) ((x + (y)-1) & ~((y)-1))
|
||||
#endif
|
||||
|
||||
//class for grabbing with DispmanX
|
||||
class CGrabberDispmanX
|
||||
{
|
||||
public:
|
||||
CGrabberDispmanX(void* boblight, volatile bool& stop, bool sync);
|
||||
~CGrabberDispmanX();
|
||||
|
||||
bool ExtendedSetup();
|
||||
bool Run();
|
||||
|
||||
std::string& GetError() { return m_error; } //retrieves the latest error
|
||||
|
||||
void SetInterval(double interval) { m_interval = interval; } //sets interval, negative means vblanks
|
||||
void SetSize(int size) { m_size = size; } //sets how many pixels we want to grab
|
||||
|
||||
bool Setup(); //base setup function
|
||||
|
||||
void SetDebug(const char* display); //turn on debug window
|
||||
|
||||
protected:
|
||||
|
||||
bool Wait(); //wait for the timer or on the vblank
|
||||
volatile bool& m_stop;
|
||||
|
||||
std::string m_error; //latest error
|
||||
|
||||
void* m_boblight; //our handle from libboblight
|
||||
|
||||
int m_size; //nr of pixels on lines to grab
|
||||
|
||||
bool m_debug; //if we have debug mode on
|
||||
|
||||
long double m_lastupdate;
|
||||
long double m_lastmeasurement;
|
||||
long double m_measurements;
|
||||
int m_nrmeasurements;
|
||||
|
||||
double m_interval; //interval in seconds, or negative for vblanks
|
||||
CTimer m_timer; //our timer
|
||||
bool m_sync; //sync mode for libboblight
|
||||
|
||||
|
||||
private:
|
||||
|
||||
bool CheckExtensions();
|
||||
|
||||
DISPMANX_DISPLAY_HANDLE_T display;
|
||||
DISPMANX_MODEINFO_T info;
|
||||
void *image;
|
||||
DISPMANX_UPDATE_HANDLE_T update;
|
||||
DISPMANX_RESOURCE_HANDLE_T resource;
|
||||
DISPMANX_ELEMENT_HANDLE_T element;
|
||||
uint32_t vc_image_ptr;
|
||||
VC_IMAGE_TYPE_T type;
|
||||
int pitch;
|
||||
};
|
||||
|
||||
#endif //GRABBEROPENMAX
|
17
src/hyperion-d.cpp
Normal file
17
src/hyperion-d.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
// QT includes
|
||||
#include <QCoreApplication>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/DispmanxWrapper.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
|
||||
DispmanxWrapper dispmanx;
|
||||
dispmanx.start();
|
||||
|
||||
app.exec();
|
||||
}
|
@ -12,7 +12,8 @@ include_directories(${QT_INCLUDES})
|
||||
|
||||
set(hyperion-remote_HEADERS
|
||||
specialoptions.h
|
||||
connection.h)
|
||||
connection.h
|
||||
colortransform.h)
|
||||
|
||||
set(hyperion-remote_SOURCES
|
||||
hyperion-remote.cpp
|
||||
|
8
src/hyperion-remote/colortransform.h
Normal file
8
src/hyperion-remote/colortransform.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
struct ColorTransform
|
||||
{
|
||||
double valueRed;
|
||||
double valueGreen;
|
||||
double valueBlue;
|
||||
};
|
@ -1,16 +1,41 @@
|
||||
#include <stdexcept>
|
||||
|
||||
#include "connection.h"
|
||||
|
||||
Connection::Connection(const std::string &address, bool printJson)
|
||||
Connection::Connection(const std::string & a, bool printJson) :
|
||||
_printJson(printJson),
|
||||
_socket()
|
||||
{
|
||||
QString address(a.c_str());
|
||||
QStringList parts = address.split(":");
|
||||
if (parts.size() != 2)
|
||||
{
|
||||
throw std::runtime_error(QString("Wrong address: unable to parse address (%1)").arg(address).toStdString());
|
||||
}
|
||||
|
||||
bool ok;
|
||||
uint16_t port = parts[1].toUShort(&ok);
|
||||
if (!ok)
|
||||
{
|
||||
throw std::runtime_error(QString("Wrong address: Unable to parse the port number (%1)").arg(parts[1]).toStdString());
|
||||
}
|
||||
|
||||
_socket.connectToHost(parts[0], port);
|
||||
if (!_socket.waitForConnected())
|
||||
{
|
||||
throw std::runtime_error("Unable to connect to host");
|
||||
}
|
||||
}
|
||||
|
||||
Connection::~Connection()
|
||||
{
|
||||
_socket.close();
|
||||
}
|
||||
|
||||
bool Connection::setColor(QColor color, int priority, int duration)
|
||||
{
|
||||
std::cout << "Set color to " << color.red() << " " << color.green() << " " << color.blue() << std::endl;
|
||||
sendMessage("Set color message");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -38,32 +63,49 @@ bool Connection::clearAll()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Connection::setThreshold(double red, double green, double blue)
|
||||
bool Connection::setTransform(ColorTransform *threshold, ColorTransform *gamma, ColorTransform *blacklevel, ColorTransform *whitelevel)
|
||||
{
|
||||
std::cout << "Set color transforms" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Connection::setGamma(double red, double green, double blue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Connection::setBlacklevel(double red, double green, double blue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Connection::setWhitelevel(double red, double green, double blue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Connection::sendMessage(const Json::Value &message)
|
||||
bool Connection::sendMessage(const Json::Value & message)
|
||||
{
|
||||
// rpint if requested
|
||||
if (_printJson)
|
||||
{
|
||||
std::cout << "Command:" << std::endl;
|
||||
std::cout << message << std::endl;
|
||||
std::cout << "Command: " << message << std::endl;
|
||||
}
|
||||
|
||||
// serialize message
|
||||
Json::FastWriter jsonWriter;
|
||||
std::string serializedMessage = jsonWriter.write(message);
|
||||
|
||||
// write message
|
||||
_socket.write(serializedMessage.c_str());
|
||||
if (!_socket.waitForBytesWritten())
|
||||
{
|
||||
throw std::runtime_error("Error while writing data to host");
|
||||
}
|
||||
|
||||
// receive reply
|
||||
if (!_socket.waitForReadyRead())
|
||||
{
|
||||
throw std::runtime_error("Error while reading data from host");
|
||||
}
|
||||
char data[1024 * 100];
|
||||
uint64_t count = _socket.read(data, sizeof(data));
|
||||
std::string serializedReply(data, count);
|
||||
Json::Reader jsonReader;
|
||||
Json::Value reply;
|
||||
if (!jsonReader.parse(serializedReply, reply))
|
||||
{
|
||||
throw std::runtime_error("Error while parsing reply:" + serializedReply);
|
||||
}
|
||||
|
||||
if (_printJson)
|
||||
{
|
||||
std::cout << "Reply:" << reply << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -4,9 +4,12 @@
|
||||
|
||||
#include <QColor>
|
||||
#include <QImage>
|
||||
#include <QTcpSocket>
|
||||
|
||||
#include <json/json.h>
|
||||
|
||||
#include "colortransform.h"
|
||||
|
||||
class Connection
|
||||
{
|
||||
public:
|
||||
@ -18,14 +21,13 @@ public:
|
||||
bool listPriorities();
|
||||
bool clear(int priority);
|
||||
bool clearAll();
|
||||
bool setThreshold(double red, double green, double blue);
|
||||
bool setGamma(double red, double green, double blue);
|
||||
bool setBlacklevel(double red, double green, double blue);
|
||||
bool setWhitelevel(double red, double green, double blue);
|
||||
bool setTransform(ColorTransform * threshold, ColorTransform * gamma, ColorTransform * blacklevel, ColorTransform * whitelevel);
|
||||
|
||||
private:
|
||||
bool sendMessage(const Json::Value & message);
|
||||
|
||||
private:
|
||||
bool _printJson;
|
||||
|
||||
QTcpSocket _socket;
|
||||
};
|
||||
|
@ -20,36 +20,112 @@ int count(std::initializer_list<bool> values)
|
||||
return count;
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
// some settings
|
||||
QString defaultServerAddress = "localhost:19444";
|
||||
int defaultPriority = 100;
|
||||
|
||||
OptionsParser optionParser("Simple application to send a command to hyperion using the Json interface");
|
||||
ParameterSet & parameters = optionParser.getParameters();
|
||||
StringParameter & argAddress = parameters.add<StringParameter> ('a', "address" , QString("Set the address of the hyperion server [default: %1]").arg(defaultServerAddress).toAscii().constData());
|
||||
IntParameter & argPriority = parameters.add<IntParameter> ('p', "priority" , QString("Use to the provided priority channel (the lower the number, the higher the priority) [default: %1]").arg(defaultPriority).toAscii().constData());
|
||||
IntParameter & argDuration = parameters.add<IntParameter> ('d', "duration" , "Specify how long the leds should be switched on in millseconds [default: infinity]");
|
||||
ColorParameter & argColor = parameters.add<ColorParameter> ('c', "color" , "Set all leds to a constant color (either RRGGBB hex value or a color name)");
|
||||
ImageParameter & argImage = parameters.add<ImageParameter> ('i', "image" , "Set the leds to the colors according to the given image file");
|
||||
SwitchParameter<> & argList = parameters.add<SwitchParameter<> >('l', "list" , "List all priority channels which are in use");
|
||||
SwitchParameter<> & argClear = parameters.add<SwitchParameter<> >('x', "clear" , "Clear data for the priority channel provided by the -p option");
|
||||
SwitchParameter<> & argClearAll = parameters.add<SwitchParameter<> >(0x0, "clear-all" , "Clear data for all priority channels");
|
||||
TransformParameter & argGamma = parameters.add<TransformParameter>('g', "gamma" , "Set the gamma of the leds (requires 3 values)");
|
||||
TransformParameter & argThreshold = parameters.add<TransformParameter>('t', "threshold" , "Set the threshold of the leds (requires 3 space seperated values between 0.0 and 1.0)");
|
||||
TransformParameter & argBlacklevel = parameters.add<TransformParameter>('b', "blacklevel", "Set the blacklevel of the leds (requires 3 space seperated values which are normally between 0.0 and 1.0)");
|
||||
TransformParameter & argWhitelevel = parameters.add<TransformParameter>('w', "whitelevel", "Set the whitelevel of the leds (requires 3 space seperated values which are normally between 0.0 and 1.0)");
|
||||
SwitchParameter<> & argPrint = parameters.add<SwitchParameter<> >(0x0, "print" , "Print the json input and output messages on stdout");
|
||||
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<> >('h', "help" , "Show this help message and exit");
|
||||
|
||||
argAddress.setDefault(defaultServerAddress.toStdString());
|
||||
argPriority.setDefault(defaultPriority);
|
||||
argDuration.setDefault(-1);
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
try
|
||||
{
|
||||
optionParser.parse(argc, argv);
|
||||
// some settings
|
||||
QString defaultServerAddress = "localhost:19444";
|
||||
int defaultPriority = 100;
|
||||
|
||||
OptionsParser optionParser("Simple application to send a command to hyperion using the Json interface");
|
||||
ParameterSet & parameters = optionParser.getParameters();
|
||||
StringParameter & argAddress = parameters.add<StringParameter> ('a', "address" , QString("Set the address of the hyperion server [default: %1]").arg(defaultServerAddress).toAscii().constData());
|
||||
IntParameter & argPriority = parameters.add<IntParameter> ('p', "priority" , QString("Use to the provided priority channel (the lower the number, the higher the priority) [default: %1]").arg(defaultPriority).toAscii().constData());
|
||||
IntParameter & argDuration = parameters.add<IntParameter> ('d', "duration" , "Specify how long the leds should be switched on in millseconds [default: infinity]");
|
||||
ColorParameter & argColor = parameters.add<ColorParameter> ('c', "color" , "Set all leds to a constant color (either RRGGBB hex value or a color name)");
|
||||
ImageParameter & argImage = parameters.add<ImageParameter> ('i', "image" , "Set the leds to the colors according to the given image file");
|
||||
SwitchParameter<> & argList = parameters.add<SwitchParameter<> >('l', "list" , "List all priority channels which are in use");
|
||||
SwitchParameter<> & argClear = parameters.add<SwitchParameter<> >('x', "clear" , "Clear data for the priority channel provided by the -p option");
|
||||
SwitchParameter<> & argClearAll = parameters.add<SwitchParameter<> >(0x0, "clear-all" , "Clear data for all priority channels");
|
||||
TransformParameter & argGamma = parameters.add<TransformParameter>('g', "gamma" , "Set the gamma of the leds (requires 3 values)");
|
||||
TransformParameter & argThreshold = parameters.add<TransformParameter>('t', "threshold" , "Set the threshold of the leds (requires 3 space seperated values between 0.0 and 1.0)");
|
||||
TransformParameter & argBlacklevel = parameters.add<TransformParameter>('b', "blacklevel", "Set the blacklevel of the leds (requires 3 space seperated values which are normally between 0.0 and 1.0)");
|
||||
TransformParameter & argWhitelevel = parameters.add<TransformParameter>('w', "whitelevel", "Set the whitelevel of the leds (requires 3 space seperated values which are normally between 0.0 and 1.0)");
|
||||
SwitchParameter<> & argPrint = parameters.add<SwitchParameter<> >(0x0, "print" , "Print the json input and output messages on stdout");
|
||||
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<> >('h', "help" , "Show this help message and exit");
|
||||
|
||||
argAddress.setDefault(defaultServerAddress.toStdString());
|
||||
argPriority.setDefault(defaultPriority);
|
||||
argDuration.setDefault(-1);
|
||||
|
||||
// parse the options
|
||||
optionParser.parse(argc, const_cast<const char **>(argv));
|
||||
|
||||
// check if we need to display the usage
|
||||
if (argHelp.isSet())
|
||||
{
|
||||
optionParser.usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check if a color transform is set
|
||||
bool colorTransform = argThreshold.isSet() || argGamma.isSet() || argBlacklevel.isSet() || argWhitelevel.isSet();
|
||||
|
||||
// check if exactly one command was given
|
||||
int commandCount = count({argColor.isSet(), argImage.isSet(), argList.isSet(), argClear.isSet(), argClearAll.isSet(), colorTransform});
|
||||
if (commandCount != 1)
|
||||
{
|
||||
if (commandCount == 0)
|
||||
{
|
||||
std::cerr << "No command found. Provide one of the following options:" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Multiple commands found. Provide one of the following options:" << std::endl;
|
||||
}
|
||||
std::cerr << " " << argColor.usageLine() << std::endl;
|
||||
std::cerr << " " << argImage.usageLine() << std::endl;
|
||||
std::cerr << " " << argList.usageLine() << std::endl;
|
||||
std::cerr << " " << argClear.usageLine() << std::endl;
|
||||
std::cerr << " " << argClearAll.usageLine() << std::endl;
|
||||
std::cerr << "or one or more of the color transformations:" << std::endl;
|
||||
std::cerr << " " << argThreshold.usageLine() << std::endl;
|
||||
std::cerr << " " << argGamma.usageLine() << std::endl;
|
||||
std::cerr << " " << argBlacklevel.usageLine() << std::endl;
|
||||
std::cerr << " " << argWhitelevel.usageLine() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// create the connection
|
||||
Connection connection(argAddress.getValue(), argPrint.isSet());
|
||||
|
||||
// now execute the given command
|
||||
if (argColor.isSet())
|
||||
{
|
||||
connection.setColor(argColor.getValue(), argPriority.getValue(), argDuration.getValue());
|
||||
}
|
||||
else if (argImage.isSet())
|
||||
{
|
||||
connection.setImage(argImage.getValue(), argPriority.getValue(), argDuration.getValue());
|
||||
}
|
||||
else if (argList.isSet())
|
||||
{
|
||||
connection.listPriorities();
|
||||
}
|
||||
else if (argClear.isSet())
|
||||
{
|
||||
connection.clear(argPriority.getValue());
|
||||
}
|
||||
else if (argClearAll.isSet())
|
||||
{
|
||||
connection.clearAll();
|
||||
}
|
||||
else if (colorTransform)
|
||||
{
|
||||
ColorTransform threshold = argThreshold.getValue();
|
||||
ColorTransform gamma = argGamma.getValue();
|
||||
ColorTransform blacklevel = argBlacklevel.getValue();
|
||||
ColorTransform whitelevel = argWhitelevel.getValue();
|
||||
|
||||
connection.setTransform(
|
||||
argThreshold.isSet() ? &threshold : nullptr,
|
||||
argGamma.isSet() ? &gamma : nullptr,
|
||||
argBlacklevel.isSet() ? &blacklevel : nullptr,
|
||||
argWhitelevel.isSet() ? &whitelevel : nullptr);
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error & e)
|
||||
{
|
||||
@ -57,67 +133,5 @@ int main(int argc, const char * argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check if we need to display the usage
|
||||
if (argHelp.isSet())
|
||||
{
|
||||
optionParser.usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check if a color transform is set
|
||||
bool colorTransform = argThreshold.isSet() || argGamma.isSet() || argBlacklevel.isSet() || argWhitelevel.isSet();
|
||||
|
||||
// check if exactly one command was given
|
||||
int commandCount = count({argColor.isSet(), argImage.isSet(), argList.isSet(), argClear.isSet(), argClearAll.isSet(), colorTransform});
|
||||
if (commandCount != 1)
|
||||
{
|
||||
if (commandCount == 0)
|
||||
{
|
||||
std::cerr << "No command found. Provide one of the following options:" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Multiple commands found. Provide one of the following options:" << std::endl;
|
||||
}
|
||||
std::cerr << " " << argColor.usageLine() << std::endl;
|
||||
std::cerr << " " << argImage.usageLine() << std::endl;
|
||||
std::cerr << " " << argList.usageLine() << std::endl;
|
||||
std::cerr << " " << argClear.usageLine() << std::endl;
|
||||
std::cerr << " " << argClearAll.usageLine() << std::endl;
|
||||
std::cerr << "or one or more of the color transformations:" << std::endl;
|
||||
std::cerr << " " << argThreshold.usageLine() << std::endl;
|
||||
std::cerr << " " << argGamma.usageLine() << std::endl;
|
||||
std::cerr << " " << argBlacklevel.usageLine() << std::endl;
|
||||
std::cerr << " " << argWhitelevel.usageLine() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Connection connection(argAddress.getValue(), argPrint.isSet());
|
||||
|
||||
// now execute the given command
|
||||
if (argColor.isSet())
|
||||
{
|
||||
connection.setColor(argColor.getValue(), argPriority.getValue(), argDuration.getValue());
|
||||
}
|
||||
else if (argImage.isSet())
|
||||
{
|
||||
connection.setImage(argImage.getValue(), argPriority.getValue(), argDuration.getValue());
|
||||
}
|
||||
else if (argList.isSet())
|
||||
{
|
||||
connection.listPriorities();
|
||||
}
|
||||
else if (argClear.isSet())
|
||||
{
|
||||
connection.clear(argPriority.getValue());
|
||||
}
|
||||
else if (argClearAll.isSet())
|
||||
{
|
||||
connection.clearAll();
|
||||
}
|
||||
else if (colorTransform)
|
||||
{
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -5,12 +5,7 @@
|
||||
|
||||
#include <getoptPlusPlus/getoptpp.h>
|
||||
|
||||
struct ColorTransform
|
||||
{
|
||||
double valueRed;
|
||||
double valueGreen;
|
||||
double valueBlue;
|
||||
};
|
||||
#include "colortransform.h"
|
||||
|
||||
typedef vlofgren::PODParameter<QColor> ColorParameter;
|
||||
typedef vlofgren::PODParameter<QImage> ImageParameter;
|
||||
|
81
src/misc.cpp
81
src/misc.cpp
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <locale.h>
|
||||
#include "misc.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void PrintError(const std::string& error)
|
||||
{
|
||||
std::cerr << "ERROR: " << error << "\n";
|
||||
}
|
||||
|
||||
//get the first word (separated by whitespace) from string data and place that in word
|
||||
//then remove that word from string data
|
||||
bool GetWord(string& data, string& word)
|
||||
{
|
||||
stringstream datastream(data);
|
||||
string end;
|
||||
|
||||
datastream >> word;
|
||||
if (datastream.fail())
|
||||
{
|
||||
data.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t pos = data.find(word) + word.length();
|
||||
|
||||
if (pos >= data.length())
|
||||
{
|
||||
data.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
data = data.substr(pos);
|
||||
|
||||
datastream.clear();
|
||||
datastream.str(data);
|
||||
|
||||
datastream >> end;
|
||||
if (datastream.fail())
|
||||
data.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//convert . or , to the current locale for correct conversion of ascii float
|
||||
void ConvertFloatLocale(std::string& strfloat)
|
||||
{
|
||||
static struct lconv* locale = localeconv();
|
||||
|
||||
size_t pos = strfloat.find_first_of(",.");
|
||||
|
||||
while (pos != string::npos)
|
||||
{
|
||||
strfloat.replace(pos, 1, 1, *locale->decimal_point);
|
||||
pos++;
|
||||
|
||||
if (pos >= strfloat.size())
|
||||
break;
|
||||
|
||||
pos = strfloat.find_first_of(",.", pos);
|
||||
}
|
||||
}
|
191
src/misc.h
191
src/misc.h
@ -1,191 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MISCUTIL
|
||||
#define MISCUTIL
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
void PrintError(const std::string& error);
|
||||
bool GetWord(std::string& data, std::string& word);
|
||||
void ConvertFloatLocale(std::string& strfloat);
|
||||
|
||||
template <class Value>
|
||||
inline std::string ToString(Value value)
|
||||
{
|
||||
std::string data;
|
||||
std::stringstream valuestream;
|
||||
valuestream << value;
|
||||
valuestream >> data;
|
||||
return data;
|
||||
}
|
||||
|
||||
inline std::string GetErrno()
|
||||
{
|
||||
return strerror(errno);
|
||||
}
|
||||
|
||||
inline std::string GetErrno(int err)
|
||||
{
|
||||
return strerror(err);
|
||||
}
|
||||
|
||||
template <class A, class B, class C>
|
||||
inline A Clamp(A value, B min, C max)
|
||||
{
|
||||
return value < max ? (value > min ? value : min) : max;
|
||||
}
|
||||
|
||||
template <class A, class B>
|
||||
inline A Max(A value1, B value2)
|
||||
{
|
||||
return value1 > value2 ? value1 : value2;
|
||||
}
|
||||
|
||||
template <class A, class B, class C>
|
||||
inline A Max(A value1, B value2, C value3)
|
||||
{
|
||||
return (value1 > value2) ? (value1 > value3 ? value1 : value3) : (value2 > value3 ? value2 : value3);
|
||||
}
|
||||
|
||||
template <class A, class B>
|
||||
inline A Min(A value1, B value2)
|
||||
{
|
||||
return value1 < value2 ? value1 : value2;
|
||||
}
|
||||
|
||||
template <class A, class B, class C>
|
||||
inline A Min(A value1, B value2, C value3)
|
||||
{
|
||||
return (value1 < value2) ? (value1 < value3 ? value1 : value3) : (value2 < value3 ? value2 : value3);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T Abs(T value)
|
||||
{
|
||||
return value > 0 ? value : -value;
|
||||
}
|
||||
|
||||
template <class A, class B>
|
||||
inline A Round(B value)
|
||||
{
|
||||
if (value == 0.0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (value > 0.0)
|
||||
{
|
||||
return (A)(value + 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (A)(value - 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
inline int32_t Round32(float value)
|
||||
{
|
||||
return lroundf(value);
|
||||
}
|
||||
|
||||
inline int32_t Round32(double value)
|
||||
{
|
||||
return lround(value);
|
||||
}
|
||||
|
||||
inline int64_t Round64(float value)
|
||||
{
|
||||
return llroundf(value);
|
||||
}
|
||||
|
||||
inline int64_t Round64(double value)
|
||||
{
|
||||
return llround(value);
|
||||
}
|
||||
|
||||
inline bool StrToInt(const std::string& data, int& value)
|
||||
{
|
||||
return sscanf(data.c_str(), "%i", &value) == 1;
|
||||
}
|
||||
|
||||
inline bool StrToInt(const std::string& data, int64_t& value)
|
||||
{
|
||||
return sscanf(data.c_str(), "%ld", &value) == 1;
|
||||
}
|
||||
|
||||
inline bool HexStrToInt(const std::string& data, int& value)
|
||||
{
|
||||
return sscanf(data.c_str(), "%x", &value) == 1;
|
||||
}
|
||||
|
||||
inline bool HexStrToInt(const std::string& data, int64_t& value)
|
||||
{
|
||||
return sscanf(data.c_str(), "%x", &value) == 1;
|
||||
}
|
||||
|
||||
inline bool StrToFloat(const std::string& data, float& value)
|
||||
{
|
||||
return sscanf(data.c_str(), "%f", &value) == 1;
|
||||
}
|
||||
|
||||
inline bool StrToFloat(const std::string& data, double& value)
|
||||
{
|
||||
return sscanf(data.c_str(), "%lf", &value) == 1;
|
||||
}
|
||||
|
||||
inline bool StrToBool(const std::string& data, bool& value)
|
||||
{
|
||||
std::string data2 = data;
|
||||
std::string word;
|
||||
if (!GetWord(data2, word))
|
||||
return false;
|
||||
|
||||
if (word == "1" || word == "true" || word == "on" || word == "yes")
|
||||
{
|
||||
value = true;
|
||||
return true;
|
||||
}
|
||||
else if (word == "0" || word == "false" || word == "off" || word == "no")
|
||||
{
|
||||
value = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int ivalue;
|
||||
if (StrToInt(word, ivalue))
|
||||
{
|
||||
value = ivalue != 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif //MISCUTIL
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "timer.h"
|
||||
#include "misc.h"
|
||||
#include "timeutils.h"
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
CTimer::CTimer(volatile bool* stop /*=NULL*/)
|
||||
{
|
||||
m_interval = -1;
|
||||
m_timerstop = stop;
|
||||
}
|
||||
|
||||
void CTimer::SetInterval(int64_t usecs)
|
||||
{
|
||||
m_interval = usecs;
|
||||
Reset();
|
||||
}
|
||||
|
||||
int64_t CTimer::GetInterval()
|
||||
{
|
||||
return m_interval;
|
||||
}
|
||||
|
||||
void CTimer::Reset()
|
||||
{
|
||||
m_time = GetTimeUs();
|
||||
}
|
||||
|
||||
void CTimer::Wait()
|
||||
{
|
||||
int64_t sleeptime;
|
||||
|
||||
//keep looping until we have a timestamp that's not too old
|
||||
int64_t now = GetTimeUs();
|
||||
do
|
||||
{
|
||||
m_time += m_interval;
|
||||
sleeptime = m_time - now;
|
||||
}
|
||||
while(sleeptime <= m_interval * -2LL);
|
||||
|
||||
if (sleeptime > m_interval * 2LL) //failsafe, m_time must be bork if we get here
|
||||
{
|
||||
sleeptime = m_interval * 2LL;
|
||||
Reset();
|
||||
}
|
||||
|
||||
USleep(sleeptime, m_timerstop);
|
||||
}
|
||||
|
42
src/timer.h
42
src/timer.h
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CTIMER
|
||||
#define CTIMER
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
class CTimer
|
||||
{
|
||||
public:
|
||||
CTimer(volatile bool* stop = NULL);
|
||||
void SetInterval(int64_t usecs);
|
||||
virtual void Wait();
|
||||
void Reset();
|
||||
|
||||
int64_t GetInterval();
|
||||
|
||||
protected:
|
||||
int64_t m_time;
|
||||
int64_t m_interval;
|
||||
volatile bool* m_timerstop;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "timeutils.h"
|
||||
|
||||
void USleep(int64_t usecs, volatile bool* stop /*= NULL*/)
|
||||
{
|
||||
if (usecs <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (stop && usecs > 1000000) //when a pointer to a bool is passed, check it every second and stop when it's true
|
||||
{
|
||||
int64_t now = GetTimeUs();
|
||||
int64_t end = now + usecs;
|
||||
|
||||
while (now < end)
|
||||
{
|
||||
struct timespec sleeptime = {};
|
||||
|
||||
if (*stop)
|
||||
return;
|
||||
else if (end - now >= 1000000)
|
||||
sleeptime.tv_sec = 1;
|
||||
else
|
||||
sleeptime.tv_nsec = ((end - now) % 1000000) * 1000;
|
||||
|
||||
nanosleep(&sleeptime, NULL);
|
||||
now = GetTimeUs();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct timespec sleeptime;
|
||||
sleeptime.tv_sec = usecs / 1000000;
|
||||
sleeptime.tv_nsec = (usecs % 1000000) * 1000;
|
||||
|
||||
nanosleep(&sleeptime, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* boblight
|
||||
* Copyright (C) Bob 2009
|
||||
*
|
||||
* boblight is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* boblight is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TIMEUTILS
|
||||
#define TIMEUTILS
|
||||
|
||||
#include "stdint.h"
|
||||
//#include "config.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
inline int64_t GetTimeUs()
|
||||
{
|
||||
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
struct timespec time;
|
||||
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||
return ((int64_t)time.tv_sec * 1000000LL) + (int64_t)(time.tv_nsec + 500) / 1000LL;
|
||||
#else
|
||||
struct timeval time;
|
||||
gettimeofday(&time, NULL);
|
||||
return ((int64_t)time.tv_sec * 1000000LL) + (int64_t)time.tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T GetTimeSec()
|
||||
{
|
||||
return (T)GetTimeUs() / (T)1000000.0;
|
||||
}
|
||||
|
||||
void USleep(int64_t usecs, volatile bool* stop = NULL);
|
||||
|
||||
#endif //TIMEUTILS
|
@ -4,44 +4,33 @@ include_directories(../libsrc)
|
||||
# Add the simple test executable 'TestSpi'
|
||||
add_executable(TestSpi
|
||||
TestSpi.cpp)
|
||||
|
||||
target_link_libraries(TestSpi
|
||||
hyperion
|
||||
hyperion-utils)
|
||||
hyperion)
|
||||
|
||||
|
||||
add_executable(TestConfigFile
|
||||
TestConfigFile.cpp)
|
||||
|
||||
target_link_libraries(TestConfigFile
|
||||
hyperion-utils
|
||||
hyperion)
|
||||
|
||||
add_executable(Test2BobLight
|
||||
Test2BobLight.cpp)
|
||||
|
||||
target_link_libraries(Test2BobLight
|
||||
bob2hyperion)
|
||||
|
||||
add_executable(TestRgbImage
|
||||
TestRgbImage.cpp)
|
||||
target_link_libraries(TestRgbImage
|
||||
hyperion-utils)
|
||||
|
||||
add_executable(TestColorTransform
|
||||
TestColorTransform.cpp)
|
||||
TestColorTransform.cpp)
|
||||
target_link_libraries(TestColorTransform
|
||||
hyperion)
|
||||
hyperion)
|
||||
|
||||
# Find the libPNG
|
||||
find_package(PNG REQUIRED QUIET)
|
||||
|
||||
#if(PNG_FOUND)
|
||||
# Add additional includes dirs
|
||||
include_directories(${PNG_INCLUDE_DIR})
|
||||
# Add additional includes dirs
|
||||
include_directories(${PNG_INCLUDE_DIR})
|
||||
|
||||
add_executable(TestHyperionPng
|
||||
TestHyperionPng.cpp)
|
||||
add_executable(TestHyperionPng
|
||||
TestHyperionPng.cpp)
|
||||
|
||||
target_link_libraries(TestHyperionPng
|
||||
hyperion-png)
|
||||
#endif(PNG_FOUND)
|
||||
target_link_libraries(TestHyperionPng
|
||||
hyperion-png)
|
||||
|
@ -1,39 +0,0 @@
|
||||
// STL includes
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
// Boblight includes
|
||||
#include <boblight.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
void* boblight_ptr = boblight_init();
|
||||
if (!boblight_ptr)
|
||||
{
|
||||
std::cerr << "Failed to initialise bob-light" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const unsigned width = 112;
|
||||
const unsigned height = 63;
|
||||
|
||||
boblight_setscanrange(boblight_ptr, width, height);
|
||||
|
||||
std::vector<int> rgbColor = { 255, 255, 0 };
|
||||
for (unsigned iY=0; iY<height; ++iY)
|
||||
{
|
||||
for (unsigned iX=0; iX<width; ++iX)
|
||||
{
|
||||
boblight_addpixelxy(boblight_ptr, iX, iY, rgbColor.data());
|
||||
}
|
||||
}
|
||||
boblight_sendrgb(boblight_ptr, 0, nullptr);
|
||||
|
||||
//sleep(5);
|
||||
|
||||
boblight_destroy(boblight_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
|
||||
// STL includes
|
||||
#include <iostream>
|
||||
|
||||
// Boblight includes
|
||||
#include <boblight.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "TestBoblightOrig started" << std::endl;
|
||||
|
||||
std::cout << "TestBoblightOrig finished" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,93 +1,96 @@
|
||||
// STL includes
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
#include <hyperion/ColorTransform.h>
|
||||
#include <../../libsrc/hyperion/ColorTransform.h>
|
||||
|
||||
using namespace hyperion;
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
std::cout << "Testing linear transform" << std::endl;
|
||||
ColorTransform t;
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
uint8_t input = i;
|
||||
uint8_t output = t.transform(input);
|
||||
uint8_t expected = input;
|
||||
{
|
||||
std::cout << "Testing linear transform" << std::endl;
|
||||
ColorTransform t;
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
uint8_t input = i;
|
||||
uint8_t output = t.transform(input);
|
||||
uint8_t expected = input;
|
||||
|
||||
if (output != expected)
|
||||
{
|
||||
std::cerr << "ERROR: input (" << (int)input << ") => output (" << (int)output << ") : expected (" << (int) expected << ")" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "OK: input (" << (int)input << ") => output (" << (int)output << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (output != expected)
|
||||
{
|
||||
std::cerr << "ERROR: input (" << (int)input << ") => output (" << (int)output << ") : expected (" << (int) expected << ")" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "OK: input (" << (int)input << ") => output (" << (int)output << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << "Testing threshold" << std::endl;
|
||||
ColorTransform t(.10, 1.0, 0.0, 1.0);
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
uint8_t input = i;
|
||||
uint8_t output = t.transform(input);
|
||||
uint8_t expected = ((i/255.0) < t.getThreshold() ? 0 : output);
|
||||
{
|
||||
std::cout << "Testing threshold" << std::endl;
|
||||
ColorTransform t(.10, 1.0, 0.0, 1.0);
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
uint8_t input = i;
|
||||
uint8_t output = t.transform(input);
|
||||
uint8_t expected = ((i/255.0) < t.getThreshold() ? 0 : output);
|
||||
|
||||
if (output != expected)
|
||||
{
|
||||
std::cerr << "ERROR: input (" << (int)input << ") => output (" << (int)output << ") : expected (" << (int) expected << ")" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "OK: input (" << (int)input << ") => output (" << (int)output << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (output != expected)
|
||||
{
|
||||
std::cerr << "ERROR: input (" << (int)input << ") => output (" << (int)output << ") : expected (" << (int) expected << ")" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "OK: input (" << (int)input << ") => output (" << (int)output << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << "Testing blacklevel and whitelevel" << std::endl;
|
||||
ColorTransform t(0, 1.0, 0.2, 0.8);
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
uint8_t input = i;
|
||||
uint8_t output = t.transform(input);
|
||||
uint8_t expected = (uint8_t)(input * (t.getWhitelevel()-t.getBlacklevel()) + 255 * t.getBlacklevel());
|
||||
{
|
||||
std::cout << "Testing blacklevel and whitelevel" << std::endl;
|
||||
ColorTransform t(0, 1.0, 0.2, 0.8);
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
uint8_t input = i;
|
||||
uint8_t output = t.transform(input);
|
||||
uint8_t expected = (uint8_t)(input * (t.getWhitelevel()-t.getBlacklevel()) + 255 * t.getBlacklevel());
|
||||
|
||||
if (output != expected)
|
||||
{
|
||||
std::cerr << "ERROR: input (" << (int)input << ") => output (" << (int)output << ") : expected (" << (int) expected << ")" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "OK: input (" << (int)input << ") => output (" << (int)output << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (output != expected)
|
||||
{
|
||||
std::cerr << "ERROR: input (" << (int)input << ") => output (" << (int)output << ") : expected (" << (int) expected << ")" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "OK: input (" << (int)input << ") => output (" << (int)output << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << "Testing gamma" << std::endl;
|
||||
ColorTransform t(0, 2.0, 0.0, 1.0);
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
uint8_t input = i;
|
||||
uint8_t output = t.transform(input);
|
||||
uint8_t expected = (uint8_t)(255 * std::pow(i / 255.0, 2));
|
||||
{
|
||||
std::cout << "Testing gamma" << std::endl;
|
||||
ColorTransform t(0, 2.0, 0.0, 1.0);
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
uint8_t input = i;
|
||||
uint8_t output = t.transform(input);
|
||||
uint8_t expected = (uint8_t)(255 * std::pow(i / 255.0, 2));
|
||||
|
||||
if (output != expected)
|
||||
{
|
||||
std::cerr << "ERROR: input (" << (int)input << ") => output (" << (int)output << ") : expected (" << (int) expected << ")" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "OK: input (" << (int)input << ") => output (" << (int)output << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (output != expected)
|
||||
{
|
||||
std::cerr << "ERROR: input (" << (int)input << ") => output (" << (int)output << ") : expected (" << (int) expected << ")" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "OK: input (" << (int)input << ") => output (" << (int)output << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -23,16 +23,30 @@ int main()
|
||||
}
|
||||
|
||||
const Json::Value& deviceConfig = config["device"];
|
||||
if (deviceConfig.empty())
|
||||
{
|
||||
std::cout << "Missing DEVICE configuration 'device'" << std::endl;
|
||||
}
|
||||
const Json::Value& ledConfig = config["leds"];
|
||||
if (ledConfig.empty())
|
||||
{
|
||||
std::cout << "Missing LEDS configuration 'leds'" << std::endl;
|
||||
}
|
||||
|
||||
const Json::Value& colorConfig = config["color"];
|
||||
if (colorConfig.empty())
|
||||
{
|
||||
std::cout << "Missing COLORS configuration 'colors'" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "COLOR CONFIGURATION: " << colorConfig.toStyledString() << std::endl;
|
||||
|
||||
std::cout << "COLOR CONFIGURATION: " << colorConfig.toStyledString() << std::endl;
|
||||
|
||||
const Json::Value& redConfig = colorConfig["red"];
|
||||
double redGamma = redConfig["gamma"].asDouble();
|
||||
std::cout << "RED GAMMA = " << redGamma << std::endl;
|
||||
std::cout << "RED GAMMA = " << colorConfig["red.gamma"].asDouble() << std::endl;
|
||||
LedString ledString = LedString::construct(ledConfig, colorConfig);
|
||||
const Json::Value& redConfig = colorConfig["red"];
|
||||
double redGamma = redConfig["gamma"].asDouble();
|
||||
std::cout << "RED GAMMA = " << redGamma << std::endl;
|
||||
std::cout << "RED GAMMA = " << colorConfig["red.gamma"].asDouble() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user