Qcommandlineparser (#199)

* Replaced getoptplusplus with QCommandLineParser. Fixes #39

* enabling C++11 if possible

* enabling C++11 if possible

* fixed gcc compilation issues

* fixed linux builds and improved os x build

* trying to fix dispmanx

* trying to fix dispmanx

* simplified travis build script

* fixed argumentparser default values

* rewrote validator system and made sure default arguments are processed correctly

* rewrote validator system and made sure default arguments are processed correctly

* fixed bool vs. regular options

* oops... removing debug code

* reverted screenshot api change
This commit is contained in:
Rick van Hattem
2016-08-28 15:10:43 +02:00
committed by redPanther
parent c13f2e20ec
commit 61db9f43b8
74 changed files with 1490 additions and 3911 deletions

View File

@@ -15,9 +15,7 @@ ENDIF()
include_directories(${QT_INCLUDES})
set(hyperion-remote_HEADERS
CustomParameter.h
JsonConnection.h
ColorTransformValues.h)
JsonConnection.h)
set(hyperion-remote_SOURCES
hyperion-remote.cpp
@@ -28,8 +26,8 @@ add_executable(${PROJECT_NAME}
${hyperion-remote_SOURCES})
target_link_libraries(${PROJECT_NAME}
commandline
jsoncpp
getoptPlusPlus
${QT_LIBRARIES})
qt5_use_modules(${PROJECT_NAME} Gui Core Network)

View File

@@ -1,12 +0,0 @@
#pragma once
/// Simple structure to contain the values of a color transformation
struct ColorAdjustmentValues
{
/// The value for the red color-channel
int valueRed;
/// The value for the green color-channel
int valueGreen;
/// The value for the blue color-channel
int valueBlue;
};

View File

@@ -1,12 +0,0 @@
#pragma once
/// Simple structure to contain the values of a color transformation
struct ColorCorrectionValues
{
/// The value for the red color-channel
int valueRed;
/// The value for the green color-channel
int valueGreen;
/// The value for the blue color-channel
int valueBlue;
};

View File

@@ -1,12 +0,0 @@
#pragma once
/// Simple structure to contain the values of a color transformation
struct ColorTransformValues
{
/// The value for the red color-channel
double valueRed;
/// The value for the green color-channel
double valueGreen;
/// The value for the blue color-channel
double valueBlue;
};

View File

@@ -1,197 +0,0 @@
#pragma once
// STL includes
#include <algorithm>
// Qt includes
#include <QColor>
#include <QImage>
// getoptPlusPLus includes
#include <getoptPlusPlus/getoptpp.h>
// hyperion-remote includes
#include "ColorTransformValues.h"
#include "ColorCorrectionValues.h"
#include "ColorAdjustmentValues.h"
/// Data parameter for a color
typedef vlofgren::PODParameter<std::vector<QColor>> ColorParameter;
/// Data parameter for an image
typedef vlofgren::PODParameter<QImage> ImageParameter;
/// Data parameter for color transform values (list of three values)
typedef vlofgren::PODParameter<ColorTransformValues> TransformParameter;
/// Data parameter for color correction values (list of three values)
typedef vlofgren::PODParameter<ColorCorrectionValues> CorrectionParameter;
/// Data parameter for color correction values (list of three values)
typedef vlofgren::PODParameter<ColorAdjustmentValues> AdjustmentParameter;
namespace vlofgren {
///
/// Translates a string (as passed on the commandline) to a vector of colors
///
/// @param[in] s The string (as passed on the commandline)
///
/// @return The translated colors
///
/// @throws Parameter::ParameterRejected If the string did not result in a color
///
template<>
std::vector<QColor> ColorParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
{
// Check if we can create the color by name
QColor color(s.c_str());
if (color.isValid())
{
return std::vector<QColor>{color};
}
// check if we can create the color by hex RRGGBB value
if (s.length() >= 6u && (s.length()%6u) == 0u && std::count_if(s.begin(), s.end(), isxdigit) == int(s.length()))
{
bool ok = true;
std::vector<QColor> colors;
for (size_t j = 0; j < s.length()/6; ++j)
{
int rgb[3];
for (int i = 0; i < 3 && ok; ++i)
{
QString colorComponent(s.substr(6*j+2*i, 2).c_str());
rgb[i] = colorComponent.toInt(&ok, 16);
}
if (ok)
{
color.setRgb(rgb[0], rgb[1], rgb[2]);
colors.push_back(color);
}
else
{
break;
}
}
// check if all components parsed succesfully
if (ok)
{
return colors;
}
}
std::stringstream errorMessage;
errorMessage << "Invalid color. A color is specified by a six lettered RRGGBB hex value or one of the following names:";
foreach (const QString & colorname, QColor::colorNames()) {
errorMessage << "\n " << colorname.toStdString();
}
throw Parameter::ParameterRejected(errorMessage.str());
return std::vector<QColor>{color};
}
template<>
QImage ImageParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
{
QImage image(s.c_str());
if (image.isNull())
{
std::stringstream errorMessage;
errorMessage << "File " << s << " could not be opened as an image";
throw Parameter::ParameterRejected(errorMessage.str());
}
return image;
}
template<>
ColorTransformValues TransformParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
{
ColorTransformValues transform;
// s should be split in 3 parts
// seperators are either a ',' or a space
QStringList components = QString(s.c_str()).split(" ", QString::SkipEmptyParts);
if (components.size() == 3)
{
bool ok1, ok2, ok3;
transform.valueRed = components[0].toDouble(&ok1);
transform.valueGreen = components[1].toDouble(&ok2);
transform.valueBlue = components[2].toDouble(&ok3);
if (ok1 && ok2 && ok3)
{
return transform;
}
}
std::stringstream errorMessage;
errorMessage << "Argument " << s << " can not be parsed to 3 double values";
throw Parameter::ParameterRejected(errorMessage.str());
return transform;
}
template<>
ColorCorrectionValues CorrectionParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
{
ColorCorrectionValues correction;
// s should be split in 3 parts
// seperators are either a ',' or a space
QStringList components = QString(s.c_str()).split(" ", QString::SkipEmptyParts);
if (components.size() == 3)
{
bool ok1, ok2, ok3;
correction.valueRed = components[0].toInt(&ok1);
correction.valueGreen = components[1].toInt(&ok2);
correction.valueBlue = components[2].toInt(&ok3);
if (ok1 && ok2 && ok3)
{
return correction;
}
}
std::stringstream errorMessage;
errorMessage << "Argument " << s << " can not be parsed to 3 integer values";
throw Parameter::ParameterRejected(errorMessage.str());
return correction;
}
template<>
ColorAdjustmentValues AdjustmentParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
{
ColorAdjustmentValues adjustment;
// s should be split in 3 parts
// seperators are either a ',' or a space
QStringList components = QString(s.c_str()).split(" ", QString::SkipEmptyParts);
if (components.size() == 3)
{
bool ok1, ok2, ok3;
adjustment.valueRed = components[0].toInt(&ok1);
adjustment.valueGreen = components[1].toInt(&ok2);
adjustment.valueBlue = components[2].toInt(&ok3);
if (ok1 && ok2 && ok3)
{
return adjustment;
}
}
std::stringstream errorMessage;
errorMessage << "Argument " << s << " can not be parsed to 3 integer values";
throw Parameter::ParameterRejected(errorMessage.str());
return adjustment;
}
}

View File

@@ -8,11 +8,10 @@
// hyperion-remote includes
#include "JsonConnection.h"
JsonConnection::JsonConnection(const std::string & a, bool printJson)
JsonConnection::JsonConnection(const QString & address, bool printJson)
: _printJson(printJson)
, _socket()
{
QString address(a.c_str());
QStringList parts = address.split(":");
if (parts.size() != 2)
{
@@ -32,7 +31,7 @@ JsonConnection::JsonConnection(const std::string & a, bool printJson)
throw std::runtime_error("Unable to connect to host");
}
std::cout << "Connected to " << a << std::endl;
qDebug() << "Connected to:" << address;
}
JsonConnection::~JsonConnection()
@@ -67,7 +66,7 @@ void JsonConnection::setColor(std::vector<QColor> colors, int priority, int dura
parseReply(reply);
}
void JsonConnection::setImage(QImage image, int priority, int duration)
void JsonConnection::setImage(QImage &image, int priority, int duration)
{
std::cout << "Set image has size: " << image.width() << "x" << image.height() << std::endl;
@@ -93,7 +92,7 @@ void JsonConnection::setImage(QImage image, int priority, int duration)
command["priority"] = priority;
command["imagewidth"] = image.width();
command["imageheight"] = image.height();
command["imagedata"] = std::string(base64Image.data(), base64Image.size());
command["imagedata"] = base64Image.data();
if (duration > 0)
{
command["duration"] = duration;
@@ -106,20 +105,20 @@ void JsonConnection::setImage(QImage image, int priority, int duration)
parseReply(reply);
}
void JsonConnection::setEffect(const std::string &effectName, const std::string & effectArgs, int priority, int duration)
void JsonConnection::setEffect(const QString &effectName, const QString & effectArgs, int priority, int duration)
{
std::cout << "Start effect " << effectName << std::endl;
qDebug() << "Start effect " << effectName;
// create command
Json::Value command;
command["command"] = "effect";
command["priority"] = priority;
Json::Value & effect = command["effect"];
effect["name"] = effectName;
effect["name"] = effectName.toStdString();
if (effectArgs.size() > 0)
{
Json::Reader reader;
if (!reader.parse(effectArgs, effect["args"], false))
if (!reader.parse(effectArgs.toStdString(), effect["args"], false))
{
throw std::runtime_error("Error in effect arguments: " + reader.getFormattedErrorMessages());
}
@@ -193,16 +192,15 @@ void JsonConnection::clearAll()
parseReply(reply);
}
void JsonConnection::setComponentState(const std::string& component, const bool state)
void JsonConnection::setComponentState(const QString & component, const bool state)
{
state ? std::cout << "Enable Component " : std::cout << "Disable Component ";
std::cout << component << std::endl;
qDebug() << (state ? "Enable" : "Disable") << "Component" << component;
// create command
Json::Value command;
command["command"] = "componentstate";
Json::Value & parameter = command["componentstate"];
parameter["component"] = component;
parameter["component"] = component.toStdString();
parameter["state"] = state;
// send command message
@@ -268,7 +266,7 @@ QString JsonConnection::getConfig(std::string type)
return QString();
}
void JsonConnection::setConfig(const std::string &jsonString, bool create, bool overwrite)
void JsonConnection::setConfig(const QString &jsonString, bool create, bool overwrite)
{
// create command
Json::Value command;
@@ -281,7 +279,7 @@ void JsonConnection::setConfig(const std::string &jsonString, bool create, bool
if (jsonString.size() > 0)
{
Json::Reader reader;
if (!reader.parse(jsonString, config, false))
if (!reader.parse(jsonString.toStdString(), config, false))
{
throw std::runtime_error("Error in configset arguments: " + reader.getFormattedErrorMessages());
}
@@ -294,7 +292,16 @@ void JsonConnection::setConfig(const std::string &jsonString, bool create, bool
parseReply(reply);
}
void JsonConnection::setTransform(std::string * transformId, double * saturation, double * value, double * saturationL, double * luminance, double * luminanceMin, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel)
void JsonConnection::setTransform(const QString &transformId,
double *saturation,
double *value,
double *saturationL,
double *luminance,
double *luminanceMin,
QColor threshold,
QColor gamma,
QColor blacklevel,
QColor whitelevel)
{
std::cout << "Set color transforms" << std::endl;
@@ -303,9 +310,9 @@ void JsonConnection::setTransform(std::string * transformId, double * saturation
command["command"] = "transform";
Json::Value & transform = command["transform"];
if (transformId != nullptr)
if (!transformId.isNull())
{
transform["id"] = *transformId;
transform["id"] = transformId.toStdString();
}
if (saturation != nullptr)
@@ -333,36 +340,36 @@ void JsonConnection::setTransform(std::string * transformId, double * saturation
transform["luminanceMinimum"] = *luminanceMin;
}
if (threshold != nullptr)
if (threshold.isValid())
{
Json::Value & v = transform["threshold"];
v.append(threshold->valueRed);
v.append(threshold->valueGreen);
v.append(threshold->valueBlue);
v.append(threshold.red());
v.append(threshold.green());
v.append(threshold.blue());
}
if (gamma != nullptr)
if (gamma.isValid())
{
Json::Value & v = transform["gamma"];
v.append(gamma->valueRed);
v.append(gamma->valueGreen);
v.append(gamma->valueBlue);
v.append(gamma.red());
v.append(gamma.green());
v.append(gamma.blue());
}
if (blacklevel != nullptr)
if (blacklevel.isValid())
{
Json::Value & v = transform["blacklevel"];
v.append(blacklevel->valueRed);
v.append(blacklevel->valueGreen);
v.append(blacklevel->valueBlue);
v.append(blacklevel.red());
v.append(blacklevel.green());
v.append(blacklevel.blue());
}
if (whitelevel != nullptr)
if (whitelevel.isValid())
{
Json::Value & v = transform["whitelevel"];
v.append(whitelevel->valueRed);
v.append(whitelevel->valueGreen);
v.append(whitelevel->valueBlue);
v.append(whitelevel.red());
v.append(whitelevel.green());
v.append(whitelevel.blue());
}
// send command message
@@ -372,7 +379,7 @@ void JsonConnection::setTransform(std::string * transformId, double * saturation
parseReply(reply);
}
void JsonConnection::setCorrection(std::string * correctionId, ColorCorrectionValues *correction)
void JsonConnection::setCorrection(QString &correctionId, const QColor & correction)
{
std::cout << "Set color corrections" << std::endl;
@@ -381,17 +388,17 @@ void JsonConnection::setCorrection(std::string * correctionId, ColorCorrectionVa
command["command"] = "correction";
Json::Value & correct = command["correction"];
if (correctionId != nullptr)
if (!correctionId.isNull())
{
correct["id"] = *correctionId;
correct["id"] = correctionId.toStdString();
}
if (correction != nullptr)
if (correction.isValid())
{
Json::Value & v = correct["correctionValues"];
v.append(correction->valueRed);
v.append(correction->valueGreen);
v.append(correction->valueBlue);
v.append(correction.red());
v.append(correction.green());
v.append(correction.blue());
}
// send command message
@@ -401,7 +408,7 @@ void JsonConnection::setCorrection(std::string * correctionId, ColorCorrectionVa
parseReply(reply);
}
void JsonConnection::setTemperature(std::string * temperatureId, ColorCorrectionValues *temperature)
void JsonConnection::setTemperature(const QString &temperatureId, const QColor & temperature)
{
std::cout << "Set color temperature corrections" << std::endl;
@@ -410,17 +417,17 @@ void JsonConnection::setTemperature(std::string * temperatureId, ColorCorrection
command["command"] = "temperature";
Json::Value & temp = command["temperature"];
if (temperatureId != nullptr)
if (!temperatureId.isNull())
{
temp["id"] = *temperatureId;
temp["id"] = temperatureId.toStdString();
}
if (temperature != nullptr)
if (temperature.isValid())
{
Json::Value & v = temp["correctionValues"];
v.append(temperature->valueRed);
v.append(temperature->valueGreen);
v.append(temperature->valueBlue);
v.append(temperature.red());
v.append(temperature.green());
v.append(temperature.blue());
}
// send command message
@@ -430,7 +437,10 @@ void JsonConnection::setTemperature(std::string * temperatureId, ColorCorrection
parseReply(reply);
}
void JsonConnection::setAdjustment(std::string * adjustmentId, ColorAdjustmentValues * redAdjustment, ColorAdjustmentValues * greenAdjustment, ColorAdjustmentValues * blueAdjustment)
void JsonConnection::setAdjustment(const QString &adjustmentId,
const QColor & redAdjustment,
const QColor & greenAdjustment,
const QColor & blueAdjustment)
{
std::cout << "Set color adjustments" << std::endl;
@@ -439,33 +449,33 @@ void JsonConnection::setAdjustment(std::string * adjustmentId, ColorAdjustmentVa
command["command"] = "adjustment";
Json::Value & adjust = command["adjustment"];
if (adjustmentId != nullptr)
if (!adjustmentId.isNull())
{
adjust["id"] = *adjustmentId;
adjust["id"] = adjustmentId.toStdString();
}
if (redAdjustment != nullptr)
if (redAdjustment.isValid())
{
Json::Value & v = adjust["redAdjust"];
v.append(redAdjustment->valueRed);
v.append(redAdjustment->valueGreen);
v.append(redAdjustment->valueBlue);
v.append(redAdjustment.red());
v.append(redAdjustment.green());
v.append(redAdjustment.blue());
}
if (greenAdjustment != nullptr)
if (greenAdjustment.isValid())
{
Json::Value & v = adjust["greenAdjust"];
v.append(greenAdjustment->valueRed);
v.append(greenAdjustment->valueGreen);
v.append(greenAdjustment->valueBlue);
v.append(greenAdjustment.red());
v.append(greenAdjustment.green());
v.append(greenAdjustment.blue());
}
if (blueAdjustment != nullptr)
if (blueAdjustment.isValid())
{
Json::Value & v = adjust["blueAdjust"];
v.append(blueAdjustment->valueRed);
v.append(blueAdjustment->valueGreen);
v.append(blueAdjustment->valueBlue);
v.append(blueAdjustment.red());
v.append(blueAdjustment.green());
v.append(blueAdjustment.blue());
}
// send command message

View File

@@ -13,9 +13,6 @@
#include <json/json.h>
// hyperion-remote includes
#include "ColorTransformValues.h"
#include "ColorCorrectionValues.h"
#include "ColorAdjustmentValues.h"
///
/// Connection class to setup an connection to the hyperion server and execute commands
@@ -29,7 +26,7 @@ public:
/// @param address The address of the Hyperion server (for example "192.168.0.32:19444)
/// @param printJson Boolean indicating if the sent and received json is written to stdout
///
JsonConnection(const std::string & address, bool printJson);
JsonConnection(const QString & address, bool printJson);
///
/// Destructor
@@ -52,7 +49,7 @@ public:
/// @param priority The priority
/// @param duration The duration in milliseconds
///
void setImage(QImage image, int priority, int duration);
void setImage(QImage &image, int priority, int duration);
///
/// Start the given effect
@@ -62,7 +59,7 @@ public:
/// @param priority The priority
/// @param duration The duration in milliseconds
///
void setEffect(const std::string & effectName, const std::string &effectArgs, int priority, int duration);
void setEffect(const QString & effectName, const QString &effectArgs, int priority, int duration);
///
/// Retrieve a list of all occupied priority channels
@@ -89,7 +86,7 @@ public:
/// @param component The component [SMOOTHING, BLACKBORDER, KODICHECKER, FORWARDER, UDPLISTENER, BOBLIGHT_SERVER, GRABBER]
/// @param state The state of the component [true | false]
///
void setComponentState(const std::string & component, const bool state);
void setComponentState(const QString & component, const bool state);
///
/// Set current active priority channel and deactivate auto source switching
@@ -114,7 +111,7 @@ public:
/// @param jsonString The JSON String(s) to write
/// @param create Specifies whether the nonexistent json string to be created
///
void setConfig(const std::string & jsonString, bool create, bool overwrite);
void setConfig(const QString &jsonString, bool create, bool overwrite);
///
/// Set the color transform of the leds
@@ -133,16 +130,16 @@ public:
/// @param whitelevel The whitelevel
///
void setTransform(
std::string * transformId,
double * saturation,
double * value,
double * saturationL,
double * luminance,
double * luminanceMin,
ColorTransformValues * threshold,
ColorTransformValues * gamma,
ColorTransformValues * blacklevel,
ColorTransformValues * whitelevel);
const QString &transformId,
double *saturation,
double *value,
double *saturationL,
double *luminance,
double *luminanceMin,
QColor threshold,
QColor gamma,
QColor blacklevel,
QColor whitelevel);
///
/// Set the color correction of the leds
@@ -152,8 +149,8 @@ public:
/// @param correctionId The identifier of the correction to set
/// @param correction The correction values
void setCorrection(
std::string * correctionId,
ColorCorrectionValues * correction);
QString &correctionId,
const QColor & correction);
///
/// Set the color temperature of the leds
@@ -163,8 +160,8 @@ public:
/// @param temperatureId The identifier of the correction to set
/// @param temperature The temperature correction values
void setTemperature(
std::string * temperatureId,
ColorCorrectionValues * temperature);
const QString & temperatureId,
const QColor & temperature);
///
/// Set the color adjustment of the leds
@@ -176,10 +173,10 @@ public:
/// @param greenAdjustment The green channel adjustment values
/// @param blueAdjustment The blue channel adjustment values
void setAdjustment(
std::string * adjustmentId,
ColorAdjustmentValues * redAdjustment,
ColorAdjustmentValues * greenAdjustment,
ColorAdjustmentValues * blueAdjustment);
const QString & adjustmentId,
const QColor & redAdjustment,
const QColor & greenAdjustment,
const QColor & blueAdjustment);
private:
///

View File

@@ -7,17 +7,13 @@
#include <QCoreApplication>
#include <QLocale>
// getoptPlusPLus includes
#include <getoptPlusPlus/getoptpp.h>
// hyperion-remote include
#include "CustomParameter.h"
#include "JsonConnection.h"
#include "HyperionConfig.h"
#include <commandline/Parser.h>
using namespace vlofgren;
using namespace commandline;
/// Count the number of true values in a list of booleans
int count(std::initializer_list<bool> values)
@@ -30,6 +26,17 @@ int count(std::initializer_list<bool> values)
return count;
}
void showHelp(Option & option){
QString shortOption;
QString longOption = QString("-%1").arg(option.names().last());
if(option.names().size() == 2){
shortOption = QString("-%1").arg(option.names().first());
}
qWarning() << qPrintable(QString("\t%1\t%2\t%3").arg(shortOption, longOption, option.description()));
}
int main(int argc, char * argv[])
{
std::cout
@@ -45,256 +52,201 @@ int main(int argc, char * argv[])
try
{
// some default settings
QString defaultServerAddress = "localhost:19444";
int defaultPriority = 100;
// create the option parser and initialize all parameters
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).toLatin1().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).toLatin1().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. The color may be repeated multiple time like: RRGGBBRRGGBB)");
ImageParameter & argImage = parameters.add<ImageParameter> ('i', "image" , "Set the leds to the colors according to the given image file");
StringParameter & argEffect = parameters.add<StringParameter> ('e', "effect" , "Enable the effect with the given name");
StringParameter & argEffectArgs = parameters.add<StringParameter> (0x0, "effectArgs", "Arguments to use in combination with the specified effect. Should be a Json object string.");
SwitchParameter<> & argServerInfo = parameters.add<SwitchParameter<> >('l', "list" , "List server info and active effects with priority and duration");
SwitchParameter<> & argClear = parameters.add<SwitchParameter<> >('x', "clear" , "Clear data for the priority channel provided by the -p option");
SwitchParameter<> & argClearAll = parameters.add<SwitchParameter<> >(0x0, "clearall" , "Clear data for all active priority channels");
StringParameter & argEnableComponent = parameters.add<StringParameter> ('E', "enable" , "Enable the Component with the given name. Available Components are [SMOOTHING, BLACKBORDER, KODICHECKER, FORWARDER, UDPLISTENER, BOBLIGHT_SERVER, GRABBER]");
StringParameter & argDisableComponent = parameters.add<StringParameter> ('D', "disable" , "Disable the Component with the given name. Available Components are [SMOOTHING, BLACKBORDER, KODICHECKER, FORWARDER, UDPLISTENER, BOBLIGHT_SERVER, GRABBER]");
StringParameter & argId = parameters.add<StringParameter> ('q', "qualifier" , "Identifier(qualifier) of the transform to set");
DoubleParameter & argSaturation = parameters.add<DoubleParameter> ('s', "saturation", "!DEPRECATED! Will be removed soon! Set the HSV saturation gain of the leds");
DoubleParameter & argValue = parameters.add<DoubleParameter> ('v', "value" , "!DEPRECATED! Will be removed soon! Set the HSV value gain of the leds");
DoubleParameter & argSaturationL = parameters.add<DoubleParameter> ('u', "saturationL", "Set the HSL saturation gain of the leds");
DoubleParameter & argLuminance = parameters.add<DoubleParameter> ('m', "luminance" , "Set the HSL luminance gain of the leds");
DoubleParameter & argLuminanceMin= parameters.add<DoubleParameter> ('n', "luminanceMin" , "Set the HSL luminance minimum of the leds (backlight)");
TransformParameter & argGamma = parameters.add<TransformParameter>('g', "gamma" , "Set the gamma of the leds (requires 3 space seperated 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", "!DEPRECATED! Will be removed soon! 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", "!DEPRECATED! Will be removed soon! 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");
StringParameter & argIdC = parameters.add<StringParameter> ('y', "qualifier" , "!DEPRECATED! Will be removed soon! Identifier(qualifier) of the correction to set");
CorrectionParameter & argCorrection = parameters.add<CorrectionParameter>('Y', "correction" , "!DEPRECATED! Will be removed soon! Set the correction of the leds (requires 3 space seperated values between 0 and 255)");
StringParameter & argIdT = parameters.add<StringParameter> ('z', "qualifier" , "Identifier(qualifier) of the temperature correction to set");
CorrectionParameter & argTemperature= parameters.add<CorrectionParameter>('Z', "temperature" , "Set the temperature correction of the leds (requires 3 space seperated values between 0 and 255)");
StringParameter & argIdA = parameters.add<StringParameter> ('j', "qualifier" , "Identifier(qualifier) of the adjustment to set");
AdjustmentParameter & argRAdjust = parameters.add<AdjustmentParameter>('R', "redAdjustment" , "Set the adjustment of the red color (requires 3 space seperated values between 0 and 255)");
AdjustmentParameter & argGAdjust = parameters.add<AdjustmentParameter>('G', "greenAdjustment", "Set the adjustment of the green color (requires 3 space seperated values between 0 and 255)");
AdjustmentParameter & argBAdjust = parameters.add<AdjustmentParameter>('B', "blueAdjustment", "Set the adjustment of the blue color (requires 3 space seperated values between 0 and 255)");
IntParameter & argSource = parameters.add<IntParameter> (0x0, "sourceSelect" , "Set current active priority channel and deactivate auto source switching");
SwitchParameter<> & argSourceAuto = parameters.add<SwitchParameter<> >(0x0, "sourceAutoSelect", "Enables auto source, if disabled prio by manual selecting input source");
SwitchParameter<> & argSourceOff = parameters.add<SwitchParameter<> >(0x0, "sourceOff", "select no source, this results in leds activly set to black (=off)");
SwitchParameter<> & argConfigGet = parameters.add<SwitchParameter<> >(0x0, "configGet" , "Print the current loaded Hyperion configuration file");
SwitchParameter<> & argSchemaGet = parameters.add<SwitchParameter<> >(0x0, "schemaGet" , "Print the json schema for Hyperion configuration");
StringParameter & argConfigSet = parameters.add<StringParameter>('W', "configSet", "Write to the actual loaded configuration file. Should be a Json object string.");
SwitchParameter<> & argCreate = parameters.add<SwitchParameter<> >(0x0, "createkeys", "Create non exist Json Entry(s) in the actual loaded configuration file. Argument to use in combination with configSet.");
SwitchParameter<> & argOverwriteConfig = parameters.add<SwitchParameter<> >(0x0, "overwrite", "Overwrite the actual loaded configuration file with the Json object string from configSet. Argument to use in combination with configSet.");
Parser parser("Simple application to send a command to hyperion using the Json interface");
// set the default values
argAddress.setDefault(defaultServerAddress.toStdString());
argPriority.setDefault(defaultPriority);
argDuration.setDefault(-1);
argEffectArgs.setDefault("");
Option & argAddress = parser.add<Option> ('a', "address" , "Set the address of the hyperion server [default: %1]", "localhost:19444");
IntOption & argPriority = parser.add<IntOption> ('p', "priority" , "Use to the provided priority channel (the lower the number, the higher the priority) [default: %1]", "100");
IntOption & argDuration = parser.add<IntOption> ('d', "duration" , "Specify how long the leds should be switched on in milliseconds [default: infinity]");
ColorsOption & argColor = parser.add<ColorsOption> ('c', "color" , "Set all leds to a constant color (either RRGGBB hex getColors or a color name. The color may be repeated multiple time like: RRGGBBRRGGBB)");
ImageOption & argImage = parser.add<ImageOption> ('i', "image" , "Set the leds to the colors according to the given image file");
Option & argEffect = parser.add<Option> ('e', "effect" , "Enable the effect with the given name");
Option & argEffectArgs = parser.add<Option> (0x0, "effectArgs", "Arguments to use in combination with the specified effect. Should be a Json object string.", "");
BooleanOption & argServerInfo = parser.add<BooleanOption> ('l', "list" , "List server info and active effects with priority and duration");
BooleanOption & argClear = parser.add<BooleanOption> ('x', "clear" , "Clear data for the priority channel provided by the -p option");
BooleanOption & argClearAll = parser.add<BooleanOption> (0x0, "clearall" , "Clear data for all active priority channels");
Option & argEnableComponent = parser.add<Option> ('E', "enable" , "Enable the Component with the given name. Available Components are [SMOOTHING, BLACKBORDER, KODICHECKER, FORWARDER, UDPLISTENER, BOBLIGHT_SERVER, GRABBER]");
Option & argDisableComponent = parser.add<Option> ('D', "disable" , "Disable the Component with the given name. Available Components are [SMOOTHING, BLACKBORDER, KODICHECKER, FORWARDER, UDPLISTENER, BOBLIGHT_SERVER, GRABBER]");
Option & argId = parser.add<Option> ('q', "qualifier" , "Identifier(qualifier) of the transform to set");
DoubleOption & argSaturation = parser.add<DoubleOption> ('s', "saturation", "!DEPRECATED! Will be removed soon! Set the HSV saturation gain of the leds");
DoubleOption & argValue = parser.add<DoubleOption> ('v', "getColors" , "!DEPRECATED! Will be removed soon! Set the HSV getColors gain of the leds");
DoubleOption & argSaturationL = parser.add<DoubleOption> ('u', "saturationL", "Set the HSL saturation gain of the leds");
DoubleOption & argLuminance = parser.add<DoubleOption> ('m', "luminance" , "Set the HSL luminance gain of the leds");
DoubleOption & argLuminanceMin= parser.add<DoubleOption> ('n', "luminanceMin" , "Set the HSL luminance minimum of the leds (backlight)");
ColorOption & argGamma = parser.add<ColorOption>('g', "gamma" , "Set the gamma of the leds (requires colors in hex format as RRGGBB)");
ColorOption & argThreshold = parser.add<ColorOption>('t', "threshold" , "Set the threshold of the leds (requires colors in hex format as RRGGBB)");
ColorOption & argBlacklevel = parser.add<ColorOption>('b', "blacklevel", "!DEPRECATED! Will be removed soon! Set the blacklevel of the leds (requires colors in hex format as RRGGBB which are normally between 0.0 and 1.0)");
ColorOption & argWhitelevel = parser.add<ColorOption>('w', "whitelevel", "!DEPRECATED! Will be removed soon! Set the whitelevel of the leds (requires colors in hex format as RRGGBB which are normally between 0.0 and 1.0)");
BooleanOption & argPrint = parser.add<BooleanOption>(0x0, "print" , "Print the json input and output messages on stdout");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help" , "Show this help message and exit");
Option & argIdC = parser.add<Option> ('y', "qualifier-c" , "!DEPRECATED! Will be removed soon! Identifier(qualifier) of the correction to set");
ColorOption & argCorrection = parser.add<ColorOption>('Y', "correction" , "!DEPRECATED! Will be removed soon! Set the correction of the leds (requires colors in hex format as RRGGBB)");
Option & argIdT = parser.add<Option> ('z', "qualifier-t" , "Identifier(qualifier) of the temperature correction to set");
ColorOption & argTemperature= parser.add<ColorOption>('Z', "temperature" , "Set the temperature correction of the leds (requires colors in hex format as RRGGBB)");
Option & argIdA = parser.add<Option> ('j', "qualifier-a" , "Identifier(qualifier) of the adjustment to set");
ColorOption & argRAdjust = parser.add<ColorOption>('R', "redAdjustment" , "Set the adjustment of the red color (requires colors in hex format as RRGGBB)");
ColorOption & argGAdjust = parser.add<ColorOption>('G', "greenAdjustment", "Set the adjustment of the green color (requires colors in hex format as RRGGBB)");
ColorOption & argBAdjust = parser.add<ColorOption>('B', "blueAdjustment", "Set the adjustment of the blue color (requires colors in hex format as RRGGBB)");
IntOption & argSource = parser.add<IntOption> (0x0, "sourceSelect" , "Set current active priority channel and deactivate auto source switching");
BooleanOption & argSourceAuto = parser.add<BooleanOption>(0x0, "sourceAutoSelect", "Enables auto source, if disabled prio by manual selecting input source");
BooleanOption & argSourceOff = parser.add<BooleanOption>(0x0, "sourceOff", "select no source, this results in leds activly set to black (=off)");
BooleanOption & argConfigGet = parser.add<BooleanOption>(0x0, "configGet" , "Print the current loaded Hyperion configuration file");
Option & argSchemaGet = parser.add<Option>(0x0, "schemaGet" , "Print the json schema for Hyperion configuration");
Option & argConfigSet = parser.add<Option>('W', "configSet", "Write to the actual loaded configuration file. Should be a Json object string.");
Option & argCreate = parser.add<Option>(0x0, "createkeys", "Create non exist Json Entry(s) in the actual loaded configuration file. Argument to use in combination with configSet.");
Option & argOverwriteConfig = parser.add<Option>(0x0, "overwrite", "Overwrite the actual loaded configuration file with the Json object string from configSet. Argument to use in combination with configSet.");
// parse all options
optionParser.parse(argc, const_cast<const char **>(argv));
// parse all _options
parser.process(app);
// check if we need to display the usage. exit if we do.
if (argHelp.isSet())
if (parser.isSet(argHelp))
{
optionParser.usage();
return 0;
parser.showHelp(0);
}
// check if at least one of the available color transforms is set
bool colorTransform = argSaturation.isSet() || argValue.isSet() || argSaturationL.isSet() || argLuminance.isSet() || argLuminanceMin.isSet() || argThreshold.isSet() || argGamma.isSet() || argBlacklevel.isSet() || argWhitelevel.isSet();
bool colorAdjust = argRAdjust.isSet() || argGAdjust.isSet() || argBAdjust.isSet();
bool colorModding = colorTransform || colorAdjust || argCorrection.isSet() || argTemperature.isSet();
bool colorTransform = parser.isSet(argSaturation) || parser.isSet(argValue) || parser.isSet(argSaturationL) || parser.isSet(argLuminance) || parser.isSet(argLuminanceMin) || parser.isSet(argThreshold) || parser.isSet(argGamma) || parser.isSet(argBlacklevel) || parser.isSet(argWhitelevel);
bool colorAdjust = parser.isSet(argRAdjust) || parser.isSet(argGAdjust) || parser.isSet(argBAdjust);
bool colorModding = colorTransform || colorAdjust || parser.isSet(argCorrection) || parser.isSet(argTemperature);
// check that exactly one command was given
int commandCount = count({
argColor.isSet(), argImage.isSet(), argEffect.isSet(), argServerInfo.isSet(), argClear.isSet(), argClearAll.isSet(), argEnableComponent.isSet(),
argDisableComponent.isSet(), colorModding, argSource.isSet(), argSourceAuto.isSet(), argSourceOff.isSet(), argSchemaGet.isSet(), argConfigGet.isSet(),
argConfigSet.isSet()
});
int commandCount = count({parser.isSet(argColor), parser.isSet(argImage), parser.isSet(argEffect), parser.isSet(argServerInfo), parser.isSet(argClear), parser.isSet(argClearAll), parser.isSet(argEnableComponent), parser.isSet(argDisableComponent), colorModding, parser.isSet(argSource), parser.isSet(argSourceAuto), parser.isSet(argSourceOff), parser.isSet(argConfigGet)});
if (commandCount != 1)
{
std::cerr << (commandCount == 0 ? "No command found." : "Multiple commands found.") << " Provide exactly one of the following options:" << std::endl;
std::cerr << " " << argColor.usageLine() << std::endl;
std::cerr << " " << argImage.usageLine() << std::endl;
std::cerr << " " << argEffect.usageLine() << std::endl;
std::cerr << " " << argServerInfo.usageLine() << std::endl;
std::cerr << " " << argClear.usageLine() << std::endl;
std::cerr << " " << argClearAll.usageLine() << std::endl;
std::cerr << " " << argEnableComponent.usageLine() << std::endl;
std::cerr << " " << argDisableComponent.usageLine() << std::endl;
std::cerr << " " << argSource.usageLine() << std::endl;
std::cerr << " " << argSourceAuto.usageLine() << std::endl;
std::cerr << " " << argConfigGet.usageLine() << std::endl;
std::cerr << " " << argSchemaGet.usageLine() << std::endl;
std::cerr << " " << argConfigSet.usageLine() << std::endl;
std::cerr << "or one or more of the available color modding operations:" << std::endl;
std::cerr << " " << argId.usageLine() << std::endl;
std::cerr << " " << argSaturation.usageLine() << std::endl;
std::cerr << " " << argValue.usageLine() << std::endl;
std::cerr << " " << argSaturationL.usageLine() << std::endl;
std::cerr << " " << argLuminance.usageLine() << std::endl;
std::cerr << " " << argLuminanceMin.usageLine() << 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;
std::cerr << " " << argIdC.usageLine() << std::endl;
std::cerr << " " << argCorrection.usageLine() << std::endl;
std::cerr << " " << argIdT.usageLine() << std::endl;
std::cerr << " " << argTemperature.usageLine() << std::endl;
std::cerr << " " << argIdA.usageLine() << std::endl;
std::cerr << " " << argRAdjust.usageLine() << std::endl;
std::cerr << " " << argGAdjust.usageLine() << std::endl;
std::cerr << " " << argBAdjust.usageLine() << std::endl;
qWarning() << (commandCount == 0 ? "No command found." : "Multiple commands found.") << " Provide exactly one of the following options:";
showHelp(argColor);
showHelp(argImage);
showHelp(argEffect);
showHelp(argServerInfo);
showHelp(argClear);
showHelp(argClearAll);
showHelp(argEnableComponent);
showHelp(argDisableComponent);
showHelp(argSource);
showHelp(argSourceAuto);
showHelp(argConfigGet);
qWarning() << "or one or more of the available color modding operations:";
showHelp(argId);
showHelp(argSaturation);
showHelp(argValue);
showHelp(argSaturationL);
showHelp(argLuminance);
showHelp(argLuminanceMin);
showHelp(argThreshold);
showHelp(argGamma);
showHelp(argBlacklevel);
showHelp(argWhitelevel);
showHelp(argIdC);
showHelp(argCorrection);
showHelp(argIdT);
showHelp(argTemperature);
showHelp(argIdA);
showHelp(argRAdjust);
showHelp(argGAdjust);
showHelp(argBAdjust);
return 1;
}
// create the connection to the hyperion server
JsonConnection connection(argAddress.getValue(), argPrint.isSet());
JsonConnection connection(argAddress.value(parser), parser.isSet(argPrint));
// now execute the given command
if (argColor.isSet())
if (parser.isSet(argColor))
{
connection.setColor(argColor.getValue(), argPriority.getValue(), argDuration.getValue());
// TODO: make sure setColor accepts a QList<QColor>
connection.setColor(argColor.getColors(parser).toVector().toStdVector(), argPriority.getInt(parser), argDuration.getInt(parser));
}
else if (argImage.isSet())
else if (parser.isSet(argImage))
{
connection.setImage(argImage.getValue(), argPriority.getValue(), argDuration.getValue());
connection.setImage(argImage.getImage(parser), argPriority.getInt(parser), argDuration.getInt(parser));
}
else if (argEffect.isSet())
{
connection.setEffect(argEffect.getValue(), argEffectArgs.getValue(), argPriority.getValue(), argDuration.getValue());
}
else if (argServerInfo.isSet())
else if (parser.isSet(argEffect))
{
connection.setEffect(argEffect.value(parser), argEffectArgs.value(parser), argPriority.getInt(parser), argDuration.getInt(parser));
}
else if (parser.isSet(argServerInfo))
{
QString info = connection.getServerInfo();
std::cout << "Server info:\n" << info.toStdString() << std::endl;
}
else if (argClear.isSet())
else if (parser.isSet(argClear))
{
connection.clear(argPriority.getValue());
connection.clear(argPriority.getInt(parser));
}
else if (argClearAll.isSet())
else if (parser.isSet(argClearAll))
{
connection.clearAll();
}
else if (argEnableComponent.isSet())
else if (parser.isSet(argEnableComponent))
{
connection.setComponentState(argEnableComponent.getValue(), true);
connection.setComponentState(argEnableComponent.value(parser), true);
}
else if (argDisableComponent.isSet())
else if (parser.isSet(argDisableComponent))
{
connection.setComponentState(argDisableComponent.getValue(), false);
connection.setComponentState(argDisableComponent.value(parser), false);
}
else if (argSourceOff.isSet())
else if (parser.isSet(argSourceOff))
{
connection.setSource(std::numeric_limits<int>::max());
}
else if (argSource.isSet())
else if (parser.isSet(argSource))
{
connection.setSource(argSource.getValue());
connection.setSource(argSource.getInt(parser));
}
else if (argSourceAuto.isSet())
else if (parser.isSet(argSourceAuto))
{
connection.setSourceAutoSelect();
}
else if (argConfigGet.isSet())
else if (parser.isSet(argConfigGet))
{
QString info = connection.getConfig("config");
std::cout << "Configuration:\n" << info.toStdString() << std::endl;
}
else if (argSchemaGet.isSet())
else if (parser.isSet(argSchemaGet))
{
QString info = connection.getConfig("schema");
std::cout << "Configuration Schema\n" << info.toStdString() << std::endl;
}
else if (argConfigSet.isSet())
else if (parser.isSet(argConfigSet))
{
connection.setConfig(argConfigSet.getValue(), argCreate.isSet(), argOverwriteConfig.isSet());
connection.setConfig(argConfigSet.value(parser), parser.isSet(argCreate), parser.isSet(argOverwriteConfig));
}
else if (colorModding)
{
if (argCorrection.isSet())
if (parser.isSet(argCorrection))
{
std::string corrId;
ColorCorrectionValues correction;
if (argIdC.isSet()) corrId = argIdC.getValue();
if (argCorrection.isSet()) correction = argCorrection.getValue();
connection.setTemperature(
argIdC.isSet() ? &corrId : nullptr,
argCorrection.isSet() ? &correction : nullptr);
connection.setTemperature(argIdC.value(parser), argCorrection.getColor(parser));
}
if (argTemperature.isSet())
if (parser.isSet(argTemperature))
{
std::string tempId;
ColorCorrectionValues temperature;
if (argIdT.isSet()) tempId = argIdT.getValue();
if (argTemperature.isSet()) temperature = argTemperature.getValue();
connection.setTemperature(
argIdT.isSet() ? &tempId : nullptr,
argTemperature.isSet() ? &temperature : nullptr);
connection.setTemperature(argIdT.value(parser), argTemperature.getColor(parser));
}
if (colorAdjust)
{
std::string adjustId;
ColorAdjustmentValues redChannel, greenChannel, blueChannel;
if (argIdA.isSet()) adjustId = argIdA.getValue();
if (argRAdjust.isSet()) redChannel = argRAdjust.getValue();
if (argGAdjust.isSet()) greenChannel = argGAdjust.getValue();
if (argBAdjust.isSet()) blueChannel = argBAdjust.getValue();
connection.setAdjustment(
argIdA.isSet() ? &adjustId : nullptr,
argRAdjust.isSet() ? &redChannel : nullptr,
argGAdjust.isSet() ? &greenChannel : nullptr,
argBAdjust.isSet() ? &blueChannel : nullptr);
argIdA.value(parser),
argRAdjust.getColor(parser),
argGAdjust.getColor(parser),
argBAdjust.getColor(parser)
);
}
if (colorTransform)
{
std::string transId;
double saturation, value, saturationL, luminance, luminanceMin;
ColorTransformValues threshold, gamma, blacklevel, whitelevel;
if (argId.isSet()) transId = argId.getValue();
if (argSaturation.isSet()) saturation = argSaturation.getValue();
if (argValue.isSet()) value = argValue.getValue();
if (argSaturationL.isSet()) saturationL = argSaturationL.getValue();
if (argLuminance.isSet()) luminance = argLuminance.getValue();
if (argLuminanceMin.isSet()) luminanceMin = argLuminanceMin.getValue();
if (argThreshold.isSet()) threshold = argThreshold.getValue();
if (argGamma.isSet()) gamma = argGamma.getValue();
if (argBlacklevel.isSet()) blacklevel = argBlacklevel.getValue();
if (argWhitelevel.isSet()) whitelevel = argWhitelevel.getValue();
connection.setTransform(
argId.isSet() ? &transId : nullptr,
argSaturation.isSet() ? &saturation : nullptr,
argValue.isSet() ? &value : nullptr,
argSaturationL.isSet() ? &saturationL : nullptr,
argLuminance.isSet() ? &luminance : nullptr,
argLuminanceMin.isSet() ? &luminanceMin : nullptr,
argThreshold.isSet() ? &threshold : nullptr,
argGamma.isSet() ? &gamma : nullptr,
argBlacklevel.isSet() ? &blacklevel : nullptr,
argWhitelevel.isSet() ? &whitelevel : nullptr);
argId.value(parser),
argSaturation.getDoublePtr(parser),
argValue.getDoublePtr(parser),
argSaturationL.getDoublePtr(parser),
argLuminance.getDoublePtr(parser),
argLuminanceMin.getDoublePtr(parser),
argThreshold.getColor(parser),
argGamma.getColor(parser),
argBlacklevel.getColor(parser),
argWhitelevel.getColor(parser));
}
}
}