Manual input source select via json (#143)

* implement manual source select via json interface
fix schema error

* refactoring

* add visible value to all listed prios
This commit is contained in:
redPanther 2016-07-31 22:21:35 +02:00 committed by GitHub
parent 04ab2f05f7
commit 722d4eb357
14 changed files with 208 additions and 47 deletions

View File

@ -128,7 +128,22 @@ public:
/// @param name uniq name of input source
void unRegisterPriority(const std::string name);
/// gets current priority register
/// @return the priority register
const PriorityRegister& getPriorityRegister() { return _priorityRegister; }
/// enable/disable automatic/priorized source selection
/// @param enable the state
void setSourceAutoSelectEnabled(bool enabled);
/// set current input source to visible
/// @param priority the priority channel which should be vidible
/// @return true if success, false on error
bool setCurrentSourcePriority(int priority );
/// gets current state of automatic/priorized source selection
/// @return the state
bool sourceAutoSelectEnabled() { return _sourceAutoSelectEnabled; };
public slots:
///
/// Writes a single color to all the leds for the given time and priority
@ -326,7 +341,18 @@ private:
/// register of input sources and it's prio channel
PriorityRegister _priorityRegister;
/// flag for color transform enable
bool _transformEnabled;
/// flag for color adjustment enable
bool _adjustmentEnabled;
/// flag for color temperature enable
bool _temperatureEnabled;
/// flag indicates state for autoselection of input source
bool _sourceAutoSelectEnabled;
/// holds the current priority channel that is manualy selected
int _currentSourcePriority;
};

View File

@ -49,14 +49,12 @@ private slots:
void closedConnection(JsonClientConnection * connection);
private:
/// Hyperion instance
Hyperion * _hyperion;
/// The TCP server object
QTcpServer _server;
/// List with open connections
QSet<JsonClientConnection *> _openConnections;
/// the logger instance
Logger * _log;
};

View File

@ -555,6 +555,7 @@ Hyperion::Hyperion(const Json::Value &jsonConfig, const std::string configFile)
, _timer()
, _log(Logger::getInstance("Core"))
, _hwLedCount(_ledString.leds().size())
, _sourceAutoSelectEnabled(true)
{
if (!_raw2ledAdjustment->verifyAdjustments())
{
@ -643,6 +644,31 @@ void Hyperion::unRegisterPriority(const std::string name)
_priorityRegister.erase(name);
}
void Hyperion::setSourceAutoSelectEnabled(bool enabled)
{
_sourceAutoSelectEnabled = enabled;
if (! _sourceAutoSelectEnabled)
{
setCurrentSourcePriority(_muxer.getCurrentPriority());
}
DebugIf( !_sourceAutoSelectEnabled, _log, "source auto select is disabled");
InfoIf(_sourceAutoSelectEnabled, _log, "set current input source to auto select");
}
bool Hyperion::setCurrentSourcePriority(int priority )
{
bool priorityValid = _muxer.hasPriority(priority);
if (priorityValid)
{
DebugIf(_sourceAutoSelectEnabled, _log, "source auto select is disabled");
_sourceAutoSelectEnabled = false;
_currentSourcePriority = priority;
Info(_log, "set current input source to priority channel %d", _currentSourcePriority);
}
return priorityValid;
}
void Hyperion::setColor(int priority, const ColorRgb &color, const int timeout_ms, bool clearEffects)
{
@ -758,7 +784,8 @@ void Hyperion::clearall()
int Hyperion::getCurrentPriority() const
{
return _muxer.getCurrentPriority();
return _sourceAutoSelectEnabled || !_muxer.hasPriority(_currentSourcePriority) ? _muxer.getCurrentPriority() : _currentSourcePriority;
}
QList<int> Hyperion::getActivePriorities() const
@ -797,8 +824,8 @@ void Hyperion::update()
_muxer.setCurrentTime(QDateTime::currentMSecsSinceEpoch());
// Obtain the current priority channel
int priority = _muxer.getCurrentPriority();
const PriorityMuxer::InputInfo & priorityInfo = _muxer.getInputInfo(priority);
int priority = _sourceAutoSelectEnabled || !_muxer.hasPriority(_currentSourcePriority) ? _muxer.getCurrentPriority() : _currentSourcePriority;
const PriorityMuxer::InputInfo & priorityInfo = _muxer.getInputInfo(priority);
// copy ledcolors to local buffer
_ledBuffer.reserve(_hwLedCount);

View File

@ -6,10 +6,10 @@
// Hyperion includes
#include <hyperion/PriorityMuxer.h>
PriorityMuxer::PriorityMuxer(int ledCount) :
_currentPriority(LOWEST_PRIORITY),
_activeInputs(),
_lowestPriorityInfo()
PriorityMuxer::PriorityMuxer(int ledCount)
: _currentPriority(LOWEST_PRIORITY)
, _activeInputs()
, _lowestPriorityInfo()
{
_lowestPriorityInfo.priority = LOWEST_PRIORITY;
_lowestPriorityInfo.timeoutTime_ms = -1;
@ -46,6 +46,7 @@ const PriorityMuxer::InputInfo& PriorityMuxer::getInputInfo(const int priority)
auto elemIt = _activeInputs.find(priority);
if (elemIt == _activeInputs.end())
{
std::cout << "error " << priority << std::endl;
throw std::runtime_error("HYPERION (prioritymux) ERROR: no such priority");
}
return elemIt.value();

View File

@ -58,7 +58,10 @@
"required" : true,
"properties":
{
"channelAdjustment_enable" : "boolean",
"channelAdjustment_enable" :
{
"type" : "boolean"
},
"channelAdjustment" :
{
"type" : "array",
@ -173,7 +176,10 @@
"additionalProperties" : false
}
},
"temperature_enable" : "boolean",
"temperature_enable" :
{
"type" : "boolean"
},
"temperature" :
{
"type" : "array",
@ -228,7 +234,10 @@
"additionalProperties" : false
}
},
"transform_enable" : "boolean",
"transform_enable" :
{
"type" : "boolean"
},
"transform" :
{
"type" : "array",

View File

@ -27,14 +27,14 @@
// project includes
#include "JsonClientConnection.h"
JsonClientConnection::JsonClientConnection(QTcpSocket *socket, Hyperion * hyperion) :
QObject(),
_socket(socket),
_imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()),
_hyperion(hyperion),
_receiveBuffer(),
_webSocketHandshakeDone(false),
_log(Logger::getInstance("JSONCLIENTCONNECTION"))
JsonClientConnection::JsonClientConnection(QTcpSocket *socket)
: QObject()
, _socket(socket)
, _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor())
, _hyperion(Hyperion::getInstance())
, _receiveBuffer()
, _webSocketHandshakeDone(false)
, _log(Logger::getInstance("JSONCLIENTCONNECTION"))
{
// connect internal signals and slots
connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
@ -256,6 +256,8 @@ void JsonClientConnection::handleMessage(const std::string &messageString)
handleTemperatureCommand(message);
else if (command == "adjustment")
handleAdjustmentCommand(message);
else if (command == "sourceselect")
handleSourceSelectCommand(message);
else
handleNotImplemented();
}
@ -388,7 +390,7 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &)
uint64_t now = QDateTime::currentMSecsSinceEpoch();
QList<int> activePriorities = _hyperion->getActivePriorities();
Hyperion::PriorityRegister priorityRegister = _hyperion->getPriorityRegister();
int currentPriority = _hyperion->getCurrentPriority();
foreach (int priority, activePriorities) {
const Hyperion::InputInfo & priorityInfo = _hyperion->getPriorityInfo(priority);
Json::Value & item = priorities[priorities.size()];
@ -399,7 +401,8 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &)
}
item["owner"] = "unknown";
item["active"] = "true";
item["active"] = true;
item["visible"] = (priority == currentPriority);
foreach(auto const &entry, priorityRegister)
{
if (entry.second == priority)
@ -414,7 +417,8 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &)
{
Json::Value & item = priorities[priorities.size()];
item["priority"] = entry.second;
item["active"] = "false";
item["active"] = false;
item["visible"] = false;
item["owner"] = entry.first;
}
@ -773,7 +777,30 @@ void JsonClientConnection::handleAdjustmentCommand(const Json::Value &message)
sendSuccessReply();
}
void JsonClientConnection::handleSourceSelectCommand(const Json::Value & message)
{
bool success = false;
if (message.get("auto",false).asBool())
{
_hyperion->setSourceAutoSelectEnabled(true);
success = true;
}
else if (message.isMember("priority"))
{
success = _hyperion->setCurrentSourcePriority(message["priority"].asInt());
}
if (success)
{
sendSuccessReply();
}
else
{
sendErrorReply("setting current priority failed");
}
}
void JsonClientConnection::handleNotImplemented()
{
sendErrorReply("Command not implemented");

View File

@ -32,7 +32,7 @@ public:
/// @param socket The Socket object for this connection
/// @param hyperion The Hyperion server
///
JsonClientConnection(QTcpSocket * socket, Hyperion * hyperion);
JsonClientConnection(QTcpSocket * socket);
///
/// Destructor
@ -128,6 +128,13 @@ private:
///
void handleAdjustmentCommand(const Json::Value & message);
///
/// Handle an incoming JSON SourceSelect message
///
/// @param message the incoming message
///
void handleSourceSelectCommand(const Json::Value & message);
///
/// Handle an incoming JSON message of unknown type
///
@ -195,6 +202,7 @@ private:
/// used for WebSocket detection and connection handling
bool _webSocketHandshakeDone;
/// the logger instance
Logger * _log;
};

View File

@ -11,5 +11,6 @@
<file alias="schema-temperature">schema/schema-temperature.json</file>
<file alias="schema-adjustment">schema/schema-adjustment.json</file>
<file alias="schema-effect">schema/schema-effect.json</file>
<file alias="schema-sourceselect">schema/schema-sourceselect.json</file>
</qresource>
</RCC>

View File

@ -5,19 +5,18 @@
#include <jsonserver/JsonServer.h>
#include "JsonClientConnection.h"
JsonServer::JsonServer(uint16_t port) :
QObject(),
_hyperion(Hyperion::getInstance()),
_server(),
_openConnections(),
_log(Logger::getInstance("JSONSERVER"))
JsonServer::JsonServer(uint16_t port)
: QObject()
, _server()
, _openConnections()
, _log(Logger::getInstance("JSONSERVER"))
{
if (!_server.listen(QHostAddress::Any, port))
{
throw std::runtime_error("JSONSERVER ERROR: could not bind to port");
}
QList<MessageForwarder::JsonSlaveAddress> list = _hyperion->getForwarder()->getJsonSlaves();
QList<MessageForwarder::JsonSlaveAddress> list = Hyperion::getInstance()->getForwarder()->getJsonSlaves();
for ( int i=0; i<list.size(); i++ )
{
if ( list.at(i).addr == QHostAddress::LocalHost && list.at(i).port == port ) {
@ -52,7 +51,7 @@ void JsonServer::newConnection()
if (socket != nullptr)
{
Debug(_log, "New connection");
JsonClientConnection * connection = new JsonClientConnection(socket, _hyperion);
JsonClientConnection * connection = new JsonClientConnection(socket);
_openConnections.insert(connection);
// register slot for cleaning up after the connection closed

View File

@ -0,0 +1,18 @@
{
"type":"object",
"required":false,
"properties":{
"command": {
"type" : "string",
"required" : true,
"enum" : ["sourceselect"]
},
"priority": {
"type": "integer"
},
"auto": {
"type": "boolean"
}
},
"additionalProperties": false
}

View File

@ -5,7 +5,7 @@
"command": {
"type" : "string",
"required" : true,
"enum" : ["color", "image", "effect", "serverinfo", "clear", "clearall", "transform", "correction", "temperature", "adjustment"]
"enum" : ["color", "image", "effect", "serverinfo", "clear", "clearall", "transform", "correction", "temperature", "adjustment", "sourceselect"]
}
}
}

View File

@ -7,9 +7,9 @@
// hyperion-remote includes
#include "JsonConnection.h"
JsonConnection::JsonConnection(const std::string & a, bool printJson) :
_printJson(printJson),
_socket()
JsonConnection::JsonConnection(const std::string & a, bool printJson)
: _printJson(printJson)
, _socket()
{
QString address(a.c_str());
QStringList parts = address.split(":");
@ -192,6 +192,34 @@ void JsonConnection::clearAll()
parseReply(reply);
}
void JsonConnection::setSource(int priority)
{
// create command
Json::Value command;
command["command"] = "sourceselect";
command["priority"] = priority;
// send command message
Json::Value reply = sendMessage(command);
// parse reply message
parseReply(reply);
}
void JsonConnection::setSourceAutoSelect()
{
// create command
Json::Value command;
command["command"] = "sourceselect";
command["auto"] = true;
// send command message
Json::Value reply = sendMessage(command);
// parse reply message
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)
{
std::cout << "Set color transforms" << std::endl;

View File

@ -83,6 +83,15 @@ public:
///
void clearAll();
///
/// Clear the given priority channel
///
/// @param priority The priority
///
void setSource(int priority);
void setSourceAutoSelect();
///
/// Set the color transform of the leds
///

View File

@ -56,7 +56,7 @@ int main(int argc, char * argv[])
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 & 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");
@ -65,8 +65,8 @@ int main(int argc, char * argv[])
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)");
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)");
@ -74,13 +74,15 @@ int main(int argc, char * argv[])
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)");
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");
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");
// set the default values
argAddress.setDefault(defaultServerAddress.toStdString());
@ -104,7 +106,7 @@ int main(int argc, char * argv[])
bool colorModding = colorTransform || colorAdjust || argCorrection.isSet() || argTemperature.isSet();
// check that exactly one command was given
int commandCount = count({argColor.isSet(), argImage.isSet(), argEffect.isSet(), argServerInfo.isSet(), argClear.isSet(), argClearAll.isSet(), colorModding});
int commandCount = count({argColor.isSet(), argImage.isSet(), argEffect.isSet(), argServerInfo.isSet(), argClear.isSet(), argClearAll.isSet(), colorModding, argSource.isSet(), argSourceAuto.isSet()});
if (commandCount != 1)
{
std::cerr << (commandCount == 0 ? "No command found." : "Multiple commands found.") << " Provide exactly one of the following options:" << std::endl;
@ -165,6 +167,14 @@ int main(int argc, char * argv[])
{
connection.clearAll();
}
else if (argSource.isSet())
{
connection.setSource(argSource.getValue());
}
else if (argSourceAuto.isSet())
{
connection.setSourceAutoSelect();
}
else if (colorModding)
{
if (argCorrection.isSet())