diff --git a/dependencies/build/getoptPlusPlus/getoptpp.cc b/dependencies/build/getoptPlusPlus/getoptpp.cc
index aae499a9..eca180a7 100644
--- a/dependencies/build/getoptPlusPlus/getoptpp.cc
+++ b/dependencies/build/getoptPlusPlus/getoptpp.cc
@@ -1,18 +1,18 @@
- /* (C) 2011 Viktor Lofgren
- *
- * This program 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
- * any later version.
- *
- * This program 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 .
- */
+/* (C) 2011 Viktor Lofgren
+ *
+ * This program 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
+ * any later version.
+ *
+ * This program 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 .
+ */
#include "getoptpp.h"
#include
@@ -23,175 +23,207 @@ using namespace std;
namespace vlofgren {
/*
- *
- * Class OptionsParser
- *
- *
- */
+*
+* Class OptionsParser
+*
+*
+*/
OptionsParser::OptionsParser(const char* programDesc) : fprogramDesc(programDesc) {}
OptionsParser::~OptionsParser() {}
ParameterSet& OptionsParser::getParameters() {
- return parameters;
+ return parameters;
}
void OptionsParser::parse(int argc, const char* argv[]) throw(runtime_error)
{
- argv0 = argv[0];
+ argv0 = argv[0];
- if(argc == 1) return;
+ if(argc == 1) return;
- vector v(&argv[1], &argv[argc]);
+ vector v(&argv[1], &argv[argc]);
- ParserState state(*this, v);
+ ParserState state(*this, v);
- for(; !state.end(); state.advance()) {
+ for(; !state.end(); state.advance()) {
- std::list::iterator i;
+ std::list::iterator i;
- for(i = parameters.parameters.begin();
- i != parameters.parameters.end(); i++)
- {
- if((*i)->receive(state)) break;
- }
+ for(i = parameters.parameters.begin();
+ i != parameters.parameters.end(); i++)
+ {
+ int n = 0;
+ try
+ {
+ n = (*i)->receive(state);
+ }
+ catch(Parameter::ExpectedArgument &)
+ {
+ throw Parameter::ExpectedArgument(state.get() + ": expected an argument");
+ }
+ catch(Parameter::UnexpectedArgument &)
+ {
+ throw Parameter::UnexpectedArgument(state.get() + ": did not expect an argument");
+ }
+ catch(Switchable::SwitchingError &)
+ {
+ throw Parameter::ParameterRejected(state.get() + ": parameter already set");
+ }
+ catch(Parameter::ParameterRejected & pr) {
+ std::string what = pr.what();
+ if(what.length())
+ {
+ throw Parameter::ParameterRejected(state.get() + ": " + what);
+ }
+ throw Parameter::ParameterRejected(state.get() + " (unspecified error)");
+ }
- if(i == parameters.parameters.end()) {
- std::string file = state.get();
- if(file == "--") {
- state.advance();
- break;
- }
- else if(file.at(0) == '-')
- throw Parameter::ParameterRejected(string("Bad parameter: ") + file);
- else files.push_back(state.get());
- }
- }
+ for (int j = 1; j < n; ++j)
+ {
+ state.advance();
+ }
- if(!state.end()) for(; !state.end(); state.advance()) {
- files.push_back(state.get());
- }
+ if(n != 0)
+ {
+ break;
+ }
+ }
+
+ if(i == parameters.parameters.end()) {
+ std::string file = state.get();
+ if(file == "--") {
+ state.advance();
+ break;
+ }
+ else if(file.at(0) == '-')
+ throw Parameter::ParameterRejected(string("Bad parameter: ") + file);
+ else files.push_back(state.get());
+ }
+ }
+
+ if(!state.end()) for(; !state.end(); state.advance()) {
+ files.push_back(state.get());
+ }
}
void OptionsParser::usage() const {
- cerr << "Usage: " << programName() << " arguments" << endl;
+ cerr << fprogramDesc << endl;
+ cerr << "Usage: " << programName() << " [OPTIONS]" << endl << endl;
- cerr << fprogramDesc << endl << endl;
+ cerr << "Parameters: " << endl;
- cerr << "Parameters: " << endl;
+ std::list::const_iterator i;
+ for(i = parameters.parameters.begin();
+ i != parameters.parameters.end(); i++)
+ {
+ cerr.width(30);
+ cerr << std::left << " " + (*i)->usageLine();
- std::list::const_iterator i;
- for(i = parameters.parameters.begin();
- i != parameters.parameters.end(); i++)
- {
- cerr.width(30);
- cerr << std::left << " " + (*i)->usageLine();
-
- cerr.width(40);
- cerr << std::left << (*i)->description() << endl;
-
- }
+ cerr.width(40);
+ cerr << std::left << (*i)->description() << endl;
+ }
}
const vector& OptionsParser::getFiles() const {
- return files;
+ return files;
}
const string& OptionsParser::programName() const {
- return argv0;
+ return argv0;
}
/*
- * Parameter set
- *
- *
- */
+* Parameter set
+*
+*
+*/
ParameterSet::ParameterSet(const ParameterSet& ps) {
- throw new runtime_error("ParameterSet not copyable");
+ throw new runtime_error("ParameterSet not copyable");
}
ParameterSet::~ParameterSet() {
- for(std::list::iterator i = parameters.begin();
- i != parameters.end(); i++)
- {
- delete *i;
- }
+ for(std::list::iterator i = parameters.begin();
+ i != parameters.end(); i++)
+ {
+ delete *i;
+ }
}
/* The typical use case for command line arguments makes linear searching completely
- * acceptable here.
- */
+* acceptable here.
+*/
Parameter& ParameterSet::operator[](char c) const {
- for(std::list::const_iterator i = parameters.begin(); i!= parameters.end(); i++) {
- if((*i)->shortOption() == c) return *(*i);
- }
- throw out_of_range("ParameterSet["+c+string("]"));
+ for(std::list::const_iterator i = parameters.begin(); i!= parameters.end(); i++) {
+ if((*i)->shortOption() == c) return *(*i);
+ }
+ throw out_of_range("ParameterSet["+c+string("]"));
}
Parameter& ParameterSet::operator[](const string& param) const {
- for(std::list::const_iterator i = parameters.begin(); i!= parameters.end(); i++) {
- if((*i)->longOption() == param) return *(*i);
- }
- throw out_of_range("ParameterSet["+param+"]");
+ for(std::list::const_iterator i = parameters.begin(); i!= parameters.end(); i++) {
+ if((*i)->longOption() == param) return *(*i);
+ }
+ throw out_of_range("ParameterSet["+param+"]");
}
/*
- *
- * Class ParserState
- *
- *
- */
+*
+* Class ParserState
+*
+*
+*/
ParserState::ParserState(OptionsParser &opts, vector& args) :
- opts(opts), arguments(args), iterator(args.begin())
+ opts(opts), arguments(args), iterator(args.begin())
{
-
+
}
const string ParserState::peek() const {
- vector::const_iterator next = iterator+1;
- if(next != arguments.end()) return *next;
- else return "";
-
+ vector::const_iterator next = iterator+1;
+ if(next != arguments.end()) return *next;
+ else return "";
+
}
const string ParserState::get() const {
- if(!end()) return *iterator;
- else return "";
+ if(!end()) return *iterator;
+ else return "";
}
void ParserState::advance() {
- iterator++;
+ iterator++;
}
bool ParserState::end() const {
- return iterator == arguments.end();
+ return iterator == arguments.end();
}
/*
- *
- * Class Parameter
- *
- *
- */
+*
+* Class Parameter
+*
+*
+*/
Parameter::Parameter(char shortOption, const std::string & longOption, const std::string & description) :
- fshortOption(shortOption), flongOption(longOption), fdescription(description)
+ fshortOption(shortOption), flongOption(longOption), fdescription(description)
{
-
+
}
Parameter::~Parameter() {}
@@ -202,11 +234,11 @@ bool Parameter::hasShortOption() const { return fshortOption != 0x0; }
char Parameter::shortOption() const { assert(hasShortOption()); return fshortOption; }
/*
- *
- * Class Switchable
- *
- *
- */
+*
+* Class Switchable
+*
+*
+*/
bool Switchable::isSet() const { return fset; }
Switchable::~Switchable() {};
@@ -217,108 +249,88 @@ MultiSwitchable::~MultiSwitchable() {}
void UniquelySwitchable::set() throw (Switchable::SwitchingError) {
- if(UniquelySwitchable::isSet()) throw Switchable::SwitchingError();
- fset = true;
+ if(UniquelySwitchable::isSet()) throw Switchable::SwitchingError();
+ fset = true;
}
UniquelySwitchable::~UniquelySwitchable() {}
PresettableUniquelySwitchable::~PresettableUniquelySwitchable() {}
bool PresettableUniquelySwitchable::isSet() const {
- return UniquelySwitchable::isSet() || fpreset.isSet();
+ return UniquelySwitchable::isSet() || fpreset.isSet();
}
void PresettableUniquelySwitchable::set() throw (Switchable::SwitchingError)
{
- UniquelySwitchable::set();
+ UniquelySwitchable::set();
}
void PresettableUniquelySwitchable::preset() {
- fpreset.set();
+ fpreset.set();
}
/*
- *
- * Class SwitchParameter
- *
- *
- */
-
-
-SwitchParameter::SwitchParameter(char shortOption, const char *longOption,
- const char* description) : CommonParameter(shortOption, longOption, description) {}
-SwitchParameter::~SwitchParameter() {}
-
-void SwitchParameter::receiveSwitch() throw(Parameter::ParameterRejected) {
- set();
-}
-
-void SwitchParameter::receiveArgument(const string &arg) throw(Parameter::ParameterRejected) {
- throw UnexpectedArgument();
-}
-
-/*
- *
- * PODParameter specializations
- *
- *
- *
- */
+*
+* PODParameter specializations
+*
+*
+*
+*/
template<>
PODParameter::PODParameter(char shortOption, const char *longOption,
- const char* description) : CommonParameter(shortOption, longOption, description) {
- preset();
+ const char* description) : CommonParameter(shortOption, longOption, description) {
+ preset();
}
template<>
int PODParameter::validate(const string &s) throw(Parameter::ParameterRejected)
{
- // This is sadly necessary for strto*-functions to operate on
- // const char*. The function doesn't write to the memory, though,
- // so it's quite safe.
+ // This is sadly necessary for strto*-functions to operate on
+ // const char*. The function doesn't write to the memory, though,
+ // so it's quite safe.
- char* cstr = const_cast(s.c_str());
- if(*cstr == '\0') throw ParameterRejected("No argument given");
+ char* cstr = const_cast(s.c_str());
+ if(*cstr == '\0') throw ParameterRejected("No argument given");
- long l = strtol(cstr, &cstr, 10);
- if(*cstr != '\0') throw ParameterRejected("Expected int");
+ long l = strtol(cstr, &cstr, 10);
+ if(*cstr != '\0') throw ParameterRejected("Expected int");
- if(l > INT_MAX || l < INT_MIN) {
- throw ParameterRejected("Expected int");
- }
+ if(l > INT_MAX || l < INT_MIN) {
+ throw ParameterRejected("Expected int");
+ }
- return l;
+ return l;
}
template<>
long PODParameter::validate(const string &s) throw(Parameter::ParameterRejected)
{
- char* cstr = const_cast(s.c_str());
- if(*cstr == '\0') throw ParameterRejected("No argument given");
+ char* cstr = const_cast(s.c_str());
+ if(*cstr == '\0') throw ParameterRejected("No argument given");
- long l = strtol(cstr, &cstr, 10);
- if(*cstr != '\0') throw ParameterRejected("Expected long");
+ long l = strtol(cstr, &cstr, 10);
+ if(*cstr != '\0') throw ParameterRejected("Expected long");
- return l;
+ return l;
}
template<>
double PODParameter::validate(const string &s) throw(Parameter::ParameterRejected)
{
- char* cstr = const_cast(s.c_str());
- if(*cstr == '\0') throw ParameterRejected("No argument given");
+ char* cstr = const_cast(s.c_str());
+ if(*cstr == '\0') throw ParameterRejected("No argument given");
- double d = strtod(cstr, &cstr);
- if(*cstr != '\0') throw ParameterRejected("Expected double");
+ double d = strtod(cstr, &cstr);
+ if(*cstr != '\0') throw ParameterRejected("Expected double");
- return d;
+ return d;
}
template<>
string PODParameter::validate(const string &s) throw(Parameter::ParameterRejected)
{
- return s;
+ return s;
}
diff --git a/dependencies/include/getoptPlusPlus/getoptpp.h b/dependencies/include/getoptPlusPlus/getoptpp.h
index 23d0aeba..b0f825cf 100644
--- a/dependencies/include/getoptPlusPlus/getoptpp.h
+++ b/dependencies/include/getoptPlusPlus/getoptpp.h
@@ -203,7 +203,7 @@ protected:
* iterator that technically allows for more complex grammar than what is
* presently used.
*/
- virtual bool receive(ParserState& state) throw(ParameterRejected) = 0;
+ virtual int receive(ParserState& state) throw(ParameterRejected) = 0;
friend class OptionsParser;
@@ -250,20 +250,9 @@ protected:
* receiveSwitch() or receiveArgument() accordingly.
*
* @param state The current argument being parsed.
+ * @return The number of parameters taken from the input
*/
- virtual bool receive(ParserState& state) throw(ParameterRejected);
-
- /**
- * Called when a parameter does not have an argument, e.g.
- * either -f or --foo
- */
- virtual void receiveSwitch() throw (ParameterRejected) = 0;
-
- /**
- * Called when a parameter does have an argument, .e.g
- * -fbar or --foo=bar
- */
- virtual void receiveArgument(const std::string& argument) throw (ParameterRejected) = 0;
+ virtual int receive(ParserState& state) throw(ParameterRejected) = 0;
};
/** This class (used as a mixin) defines how a parameter
@@ -344,15 +333,15 @@ private:
/* Parameter that does not take an argument, and throws an exception
* if an argument is given */
-class SwitchParameter : public CommonParameter {
+template
+class SwitchParameter : public CommonParameter {
public:
SwitchParameter(char shortOption, const char *longOption,
const char* description);
virtual ~SwitchParameter();
protected:
- virtual void receiveSwitch() throw (Parameter::ParameterRejected);
- virtual void receiveArgument(const std::string& argument) throw (Parameter::ParameterRejected);
+ virtual int receive(ParserState& state) throw(Parameter::ParameterRejected);
};
/** Plain-Old-Data parameter. Performs input validation.
@@ -363,8 +352,8 @@ protected:
* Specifically, you need to specialize validate().
*/
-template
-class PODParameter : public CommonParameter {
+template
+class PODParameter : public CommonParameter {
public:
PODParameter(char shortOption, const char *longOption,
const char* description);
@@ -383,14 +372,14 @@ public:
std::string usageLine() const;
protected:
+ virtual int receive(ParserState& state) throw(Parameter::ParameterRejected);
+
/** Validation function for the data type.
*
* @throw ParameterRejected if the argument does not conform to this data type.
* @return the value corresponding to the argument.
*/
- virtual T validate(const std::string& s) throw (ParameterRejected);
- virtual void receiveArgument(const std::string &argument) throw(ParameterRejected);
- virtual void receiveSwitch() throw (Parameter::ParameterRejected);
+ virtual T validate(const std::string& s) throw (Parameter::ParameterRejected);
T value;
};
diff --git a/dependencies/include/getoptPlusPlus/parameter.include.cc b/dependencies/include/getoptPlusPlus/parameter.include.cc
index 4564d5ec..a1daf516 100644
--- a/dependencies/include/getoptPlusPlus/parameter.include.cc
+++ b/dependencies/include/getoptPlusPlus/parameter.include.cc
@@ -53,155 +53,125 @@ template
std::string CommonParameter::usageLine() const {
std::stringstream strstr;
- strstr.width(10);
if (hasShortOption())
{
- strstr << std::left<< std::string("-") + shortOption();
+ strstr << "-" << shortOption() << ", ";
}
else
{
- strstr << " ";
+ strstr << " ";
}
- strstr.width(20);
- strstr << std::left << "--" + longOption();
+ strstr.width(20);
+ strstr << std::left << "--" + longOption();
- return strstr.str();
+ return strstr.str();
}
-
+/*
+ *
+ * Class SwitchParameter
+ *
+ *
+ */
template
-bool CommonParameter::receive(ParserState& state) throw(Parameter::ParameterRejected) {
+SwitchParameter::SwitchParameter(char shortOption, const char *longOption,
+ const char* description) : CommonParameter(shortOption, longOption, description) {}
+template
+SwitchParameter::~SwitchParameter() {}
+
+template
+int SwitchParameter::receive(ParserState& state) throw(Parameter::ParameterRejected) {
const std::string arg = state.get();
- try {
- if(arg.at(0) != '-') return false;
+ if(arg.at(0) != '-') return false;
- if(arg.at(1) == '-') { /* Long form parameter */
- try {
- unsigned int eq = arg.find_first_of("=");
+ if ((arg.at(1) == '-' && arg.substr(2) == this->longOption()) ||
+ (this->hasShortOption() && arg.at(1) == this->shortOption() && arg.length() == 2))
+ {
+ this->set();
+ return 1;
+ }
- if(eq == std::string::npos) {
- if(arg.substr(2) != longOption())
- return false;
-
- this->receiveSwitch();
- } else {
- if(arg.substr(2, eq-2) != longOption())
- return false;
-
- this->receiveArgument(arg.substr(eq+1));
- }
- return true;
- } catch(Parameter::ExpectedArgument &ea) {
- throw ExpectedArgument("--" + longOption() + ": expected an argument");
- } catch(Parameter::UnexpectedArgument &ua) {
- throw UnexpectedArgument("--" + longOption() + ": did not expect an argument");
- } catch(Switchable::SwitchingError &e) {
- throw ParameterRejected("--" + longOption() + ": parameter already set");
- } catch(Parameter::ParameterRejected &pr) {
-
- std::string what = pr.what();
- if(what.length())
- throw Parameter::ParameterRejected("--" + longOption() + ": " + what);
- throw Parameter::ParameterRejected("--" + longOption() + " (unspecified error)");
- }
- }
- else if (hasShortOption())
- {
- try {
- if(arg.at(1) == shortOption()) {
- /* Matched argument on the form -f or -fsomething */
- if(arg.length() == 2) { /* -f */
- this->receiveSwitch();
-
- return true;
- } else { /* -fsomething */
- this->receiveArgument(arg.substr(2));
-
- return true;
- }
- }
- } catch(Parameter::ExpectedArgument &ea) {
- throw ExpectedArgument(std::string("-") + shortOption() + ": expected an argument");
- } catch(Parameter::UnexpectedArgument &ua) {
- throw UnexpectedArgument(std::string("-") + shortOption() + ": did not expect an argument");
- } catch(Switchable::SwitchingError &e) {
- throw ParameterRejected(std::string("-") + shortOption() + ": parameter already set");
- }
- }
- } catch(std::out_of_range& o) {
- return false;
- }
-
- return false;
+ return 0;
}
-
-
/*
* PODParameter stuff
*
*/
-template
-PODParameter::PODParameter(char shortOption, const char *longOption,
+template
+PODParameter::PODParameter(char shortOption, const char *longOption,
const char* description) : CommonParameter(shortOption, longOption, description) {}
-template
-PODParameter::~PODParameter() {}
+template
+PODParameter::~PODParameter() {}
-template
-PODParameter::operator T() const { return getValue(); }
+template
+PODParameter::operator T() const { return getValue(); }
-template
-void PODParameter::setDefault(T value) {
+template
+void PODParameter::setDefault(T value) {
PresettableUniquelySwitchable::preset();
this->value = value;
}
-template
-T PODParameter::getValue() const {
- if(!isSet()) {
- throw runtime_error(
- std::string("Attempting to retreive the argument of parameter") + longOption() + " but it hasn't been set!");
+template
+T PODParameter::getValue() const {
+ if(!this->isSet()) {
+ throw std::runtime_error(
+ std::string("Attempting to retreive the argument of parameter") + this->longOption() + " but it hasn't been set!");
}
return value;
}
-
-template
-std::string PODParameter::usageLine() const {
+template
+std::string PODParameter::usageLine() const {
std::stringstream strstr;
- strstr.width(10);
- if (hasShortOption())
+ if (this->hasShortOption())
{
- strstr << std::left << std::string("-") + shortOption() +"arg";
+ strstr << "-" << this->shortOption() << ", ";
}
else
{
- strstr << "";
+ strstr << " ";
}
strstr.width(20);
- strstr << std::left << "--" + longOption() + "=arg";
+ strstr << std::left << "--" + this->longOption() + " ";
return strstr.str();
}
-template
-void PODParameter::receiveSwitch() throw (Parameter::ParameterRejected) {
- throw Parameter::ExpectedArgument();
-}
+template
+int PODParameter::receive(ParserState& state) throw(Parameter::ParameterRejected) {
-template
-void PODParameter::receiveArgument(const std::string &argument) throw(Parameter::ParameterRejected) {
- set();
- value = this->validate(argument);
-}
+ const std::string arg = state.get();
+ if(arg.at(0) != '-') return false;
+
+ if((arg.at(1) == '-' && arg.substr(2) == this->longOption()) ||
+ (this->hasShortOption() && arg.at(1) == this->shortOption() && arg.length() == 2))
+ {
+ // retrieve the argument
+ std::string arg1 = state.peek();
+ if (arg1.length() == 0)
+ {
+ throw Parameter::ExpectedArgument(arg + ": expected an argument");
+ return 1;
+ }
+
+ this->set();
+ value = this->validate(arg1);
+
+ return 2;
+ }
+
+ return 0;
+}
#endif
diff --git a/src/hyperion-remote/CMakeLists.txt b/src/hyperion-remote/CMakeLists.txt
index a6eee382..8ed36533 100644
--- a/src/hyperion-remote/CMakeLists.txt
+++ b/src/hyperion-remote/CMakeLists.txt
@@ -1,19 +1,22 @@
cmake_minimum_required(VERSION 2.8)
project(hyperion-remote)
-find_package(Qt4 REQUIRED QtCore QtNetwork)
+find_package(Qt4 REQUIRED QtCore QtGui QtNetwork)
# The following I do not undrstand completely...
# libQtCore.so uses some hardcoded library path inside which are incorrect after copying the file RPi file system
# Therefor, an extra path is needed on which to find the required libraries
LINK_DIRECTORIES(${LINK_DIRECTORIES} ${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf)
-include_directories(${QT_INCLUDE_DIR})
+include_directories(${QT_INCLUDES})
-set(hyperion-remote_HEADERS)
+set(hyperion-remote_HEADERS
+ specialoptions.h
+ connection.h)
set(hyperion-remote_SOURCES
- hyperion-remote.cpp)
+ hyperion-remote.cpp
+ connection.cpp)
qt4_wrap_cpp(HYPERION_REMOTE_MOC_SOURCES
${hyperion-remote_HEADERS})
@@ -25,6 +28,7 @@ add_executable(hyperion-remote
qt4_use_modules(hyperion-remote
Core
+ Gui
Network)
target_link_libraries(hyperion-remote
diff --git a/src/hyperion-remote/connection.cpp b/src/hyperion-remote/connection.cpp
new file mode 100644
index 00000000..0b2d6970
--- /dev/null
+++ b/src/hyperion-remote/connection.cpp
@@ -0,0 +1,71 @@
+#include "connection.h"
+
+Connection::Connection(const std::string &address, bool printJson)
+{
+}
+
+Connection::~Connection()
+{
+}
+
+bool Connection::setColor(QColor color, int priority, int duration)
+{
+ std::cout << "Set color to " << color.red() << " " << color.green() << " " << color.blue() << std::endl;
+ return false;
+}
+
+bool Connection::setImage(QImage image, int priority, int duration)
+{
+ std::cout << "Set image has size: " << image.width() << "x" << image.height() << std::endl;
+ return false;
+}
+
+bool Connection::listPriorities()
+{
+ std::cout << "List priority channels" << std::endl;
+ return false;
+}
+
+bool Connection::clear(int priority)
+{
+ std::cout << "Clear priority channel " << priority << std::endl;
+ return false;
+}
+
+bool Connection::clearAll()
+{
+ std::cout << "Clear all priority channels" << std::endl;
+ return false;
+}
+
+bool Connection::setThreshold(double red, double green, double blue)
+{
+ 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)
+{
+ if (_printJson)
+ {
+ std::cout << "Command:" << std::endl;
+ std::cout << message << std::endl;
+ }
+
+ return true;
+}
+
diff --git a/src/hyperion-remote/connection.h b/src/hyperion-remote/connection.h
new file mode 100644
index 00000000..5035e630
--- /dev/null
+++ b/src/hyperion-remote/connection.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include
+
+#include
+#include
+
+#include
+
+class Connection
+{
+public:
+ Connection(const std::string & address, bool printJson);
+ ~Connection();
+
+ bool setColor(QColor color, int priority, int duration);
+ bool setImage(QImage image, int priority, int duration);
+ 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);
+
+private:
+ bool sendMessage(const Json::Value & message);
+
+private:
+ bool _printJson;
+};
diff --git a/src/hyperion-remote/hyperion-remote.cpp b/src/hyperion-remote/hyperion-remote.cpp
index 2311ffef..df6e57ba 100644
--- a/src/hyperion-remote/hyperion-remote.cpp
+++ b/src/hyperion-remote/hyperion-remote.cpp
@@ -1,10 +1,25 @@
-#include
+#include
+
#include
#include
+#include "specialoptions.h"
+#include "connection.h"
+
+
using namespace vlofgren;
+int count(std::initializer_list values)
+{
+ int count = 0;
+ for (auto& value : values) {
+ if (value)
+ count++;
+ }
+ return count;
+}
+
int main(int argc, const char * argv[])
{
// some settings
@@ -13,37 +28,96 @@ int main(int argc, const char * argv[])
OptionsParser optionParser("Simple application to send a command to hyperion using the Json interface");
ParameterSet & parameters = optionParser.getParameters();
- StringParameter & argAddress = parameters.add('a', "address" , QString("Set the address of the hyperion server [default: %1]").arg(defaultServerAddress).toAscii().constData());
- IntParameter & argPriority = parameters.add ('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 ('d', "duration" , "Specify how long the leds should be switched on in millseconds. Without this parameter, the leds will be switched on without end time.");
- StringParameter & argColor = parameters.add('c', "color" , "Set all leds to a constant color (either RRGGBB hex value or a color name)");
- StringParameter & argImage = parameters.add('i', "image" , "Set the leds to the colors according to the given image file");
- SwitchParameter & argList = parameters.add('l', "list" , "List all priority channels which are in use");
- SwitchParameter & argClear = parameters.add('x', "clear" , "Clear data for the priority channel provided by the -p option");
- SwitchParameter & argClearAll = parameters.add(0x0, "clear-all" , "Clear data for all priority channels");
- DoubleParameter & argGamma = parameters.add('g', "gamma" , "Set the gamma of the leds (requires 3 values)");
- DoubleParameter & argThreshold = parameters.add('t', "threshold" , "Set the threshold of the leds (requires 3 values between 0.0 and 1.0)");
- DoubleParameter & argBlacklevel = parameters.add('b', "blacklevel", "Set the blacklevel of the leds (requires 3 values which are normally between 0.0 and 1.0)");
- DoubleParameter & argWhitelevel = parameters.add('w', "whitelevel", "Set the whitelevel of the leds (requires 3 values which are normally between 0.0 and 1.0)");
- SwitchParameter & argPrint = parameters.add(0x0, "print" , "Print the json input and output messages on stdout");
- SwitchParameter & argHelp = parameters.add('h', "help" , "Show this help message and exit");
+ StringParameter & argAddress = parameters.add ('a', "address" , QString("Set the address of the hyperion server [default: %1]").arg(defaultServerAddress).toAscii().constData());
+ IntParameter & argPriority = parameters.add ('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 ('d', "duration" , "Specify how long the leds should be switched on in millseconds [default: infinity]");
+ ColorParameter & argColor = parameters.add ('c', "color" , "Set all leds to a constant color (either RRGGBB hex value or a color name)");
+ ImageParameter & argImage = parameters.add ('i', "image" , "Set the leds to the colors according to the given image file");
+ SwitchParameter<> & argList = parameters.add >('l', "list" , "List all priority channels which are in use");
+ SwitchParameter<> & argClear = parameters.add >('x', "clear" , "Clear data for the priority channel provided by the -p option");
+ SwitchParameter<> & argClearAll = parameters.add >(0x0, "clear-all" , "Clear data for all priority channels");
+ TransformParameter & argGamma = parameters.add('g', "gamma" , "Set the gamma of the leds (requires 3 values)");
+ TransformParameter & argThreshold = parameters.add('t', "threshold" , "Set the threshold of the leds (requires 3 space seperated values between 0.0 and 1.0)");
+ TransformParameter & argBlacklevel = parameters.add('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('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 >(0x0, "print" , "Print the json input and output messages on stdout");
+ SwitchParameter<> & argHelp = parameters.add >('h', "help" , "Show this help message and exit");
+
+ argAddress.setDefault(defaultServerAddress.toStdString());
+ argPriority.setDefault(defaultPriority);
+ argDuration.setDefault(-1);
+
try
{
optionParser.parse(argc, argv);
}
catch (const std::runtime_error & e)
{
- qWarning() << e.what();
- optionParser.usage();
+ std::cerr << e.what() << std::endl;
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;
}
diff --git a/src/hyperion-remote/specialoptions.h b/src/hyperion-remote/specialoptions.h
new file mode 100644
index 00000000..96f4b304
--- /dev/null
+++ b/src/hyperion-remote/specialoptions.h
@@ -0,0 +1,102 @@
+#pragma once
+
+#include
+#include
+
+#include
+
+struct ColorTransform
+{
+ double valueRed;
+ double valueGreen;
+ double valueBlue;
+};
+
+typedef vlofgren::PODParameter ColorParameter;
+typedef vlofgren::PODParameter ImageParameter;
+typedef vlofgren::PODParameter TransformParameter;
+
+namespace vlofgren {
+ template<>
+ 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 color;
+ }
+
+ // check if we can create the color by hex RRGGBB value
+ if (s.length() == 6 && isxdigit(s[0]) && isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]) && isxdigit(s[4]) && isxdigit(s[5]))
+ {
+ bool ok = true;
+ int rgb[3];
+ for (int i = 0; i < 3 && ok; ++i)
+ {
+ QString colorComponent(s.substr(2*i, 2).c_str());
+ rgb[i] = colorComponent.toInt(&ok, 16);
+ }
+
+ // check if all components parsed succesfully
+ if (ok)
+ {
+ color.setRgb(rgb[0], rgb[1], rgb[2]);
+ return color;
+ }
+ }
+
+ 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 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<>
+ ColorTransform TransformParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
+ {
+ ColorTransform 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;
+ }
+}