mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	Added the possibility to set effect arguments over json
Former-commit-id: 4bc2920c04853e549c712ec70492371b14d20877
This commit is contained in:
		
							
								
								
									
										14
									
								
								include/effectengine/EffectDefinition.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								include/effectengine/EffectDefinition.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// stl include
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
// json include
 | 
			
		||||
#include <json/value.h>
 | 
			
		||||
 | 
			
		||||
struct EffectDefinition
 | 
			
		||||
{
 | 
			
		||||
	std::string name;
 | 
			
		||||
	std::string script;
 | 
			
		||||
	Json::Value args;
 | 
			
		||||
};
 | 
			
		||||
@@ -1,11 +1,17 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// Qt includes
 | 
			
		||||
#include <QObject>
 | 
			
		||||
 | 
			
		||||
// Json includes
 | 
			
		||||
#include <json/value.h>
 | 
			
		||||
 | 
			
		||||
// Hyperion includes
 | 
			
		||||
#include <hyperion/Hyperion.h>
 | 
			
		||||
 | 
			
		||||
// Effect engine includes
 | 
			
		||||
#include <effectengine/EffectDefinition.h>
 | 
			
		||||
 | 
			
		||||
// pre-declarioation
 | 
			
		||||
class Effect;
 | 
			
		||||
typedef struct _ts PyThreadState;
 | 
			
		||||
@@ -18,32 +24,28 @@ public:
 | 
			
		||||
	EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectConfig);
 | 
			
		||||
	virtual ~EffectEngine();
 | 
			
		||||
 | 
			
		||||
	std::list<std::string> getEffects() const;
 | 
			
		||||
	const std::list<EffectDefinition> & getEffects() const;
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
	/// Run the specified effect on the given priority channel and optionally specify a timeout
 | 
			
		||||
	int runEffect(const std::string &effectName, int priority, int timeout = -1);
 | 
			
		||||
 | 
			
		||||
	/// Run the specified effect on the given priority channel and optionally specify a timeout
 | 
			
		||||
	int runEffect(const std::string &effectName, const Json::Value & args, int priority, int timeout = -1);
 | 
			
		||||
 | 
			
		||||
	/// Clear any effect running on the provided channel
 | 
			
		||||
	void channelCleared(int priority);
 | 
			
		||||
 | 
			
		||||
	/// Clear all effects
 | 
			
		||||
	void allChannelsCleared();
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	struct EffectDefinition
 | 
			
		||||
	{
 | 
			
		||||
		std::string script;
 | 
			
		||||
		Json::Value args;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
	void effectFinished(Effect * effect);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	Hyperion * _hyperion;
 | 
			
		||||
 | 
			
		||||
	std::map<std::string, EffectDefinition> _availableEffects;
 | 
			
		||||
	std::list<EffectDefinition> _availableEffects;
 | 
			
		||||
 | 
			
		||||
	std::list<Effect *> _activeEffects;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,9 @@
 | 
			
		||||
#include <hyperion/LedDevice.h>
 | 
			
		||||
#include <hyperion/PriorityMuxer.h>
 | 
			
		||||
 | 
			
		||||
// Effect engine includes
 | 
			
		||||
#include <effectengine/EffectDefinition.h>
 | 
			
		||||
 | 
			
		||||
// Forward class declaration
 | 
			
		||||
class HsvTransform;
 | 
			
		||||
class ColorTransform;
 | 
			
		||||
@@ -102,7 +105,7 @@ public:
 | 
			
		||||
 | 
			
		||||
	/// Get the list of available effects
 | 
			
		||||
	/// @return The list of available effects
 | 
			
		||||
	std::list<std::string> getEffects() const;
 | 
			
		||||
	const std::list<EffectDefinition> &getEffects() const;
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
	///
 | 
			
		||||
@@ -153,6 +156,12 @@ public slots:
 | 
			
		||||
	/// @param timout The timeout of the effect (after the timout, the effect will be cleared)
 | 
			
		||||
	int setEffect(const std::string & effectName, int priority, int timeout = -1);
 | 
			
		||||
 | 
			
		||||
	/// Run the specified effect on the given priority channel and optionally specify a timeout
 | 
			
		||||
	/// @param effectName Name of the effec to run
 | 
			
		||||
	///	@param priority The priority channel of the effect
 | 
			
		||||
	/// @param timout The timeout of the effect (after the timout, the effect will be cleared)
 | 
			
		||||
	int setEffect(const std::string & effectName, const Json::Value & args, int priority, int timeout = -1);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	static LedDevice * createDevice(const Json::Value & deviceConfig);
 | 
			
		||||
	static ColorOrder createColorOrder(const Json::Value & deviceConfig);
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ SET(EffectEngineQT_HEADERS
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
SET(EffectEngineHEADERS
 | 
			
		||||
	${CURRENT_HEADER_DIR}/EffectDefinition.h
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
SET(EffectEngineSOURCES
 | 
			
		||||
 
 | 
			
		||||
@@ -49,9 +49,9 @@ private:
 | 
			
		||||
 | 
			
		||||
	const int _timeout;
 | 
			
		||||
 | 
			
		||||
	const std::string & _script;
 | 
			
		||||
	const std::string _script;
 | 
			
		||||
 | 
			
		||||
	const Json::Value & _args;
 | 
			
		||||
	const Json::Value _args;
 | 
			
		||||
 | 
			
		||||
	int64_t _endTime;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectCo
 | 
			
		||||
	for (const std::string & name : effectNames)
 | 
			
		||||
	{
 | 
			
		||||
		const Json::Value & info = jsonEffectConfig[name];
 | 
			
		||||
		_availableEffects[name] = {info["script"].asString(), info["args"]};
 | 
			
		||||
		_availableEffects.push_back({name, info["script"].asString(), info["args"]});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// initialize the python interpreter
 | 
			
		||||
@@ -43,22 +43,33 @@ EffectEngine::~EffectEngine()
 | 
			
		||||
	Py_Finalize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::list<std::string> EffectEngine::getEffects() const
 | 
			
		||||
const std::list<EffectDefinition> &EffectEngine::getEffects() const
 | 
			
		||||
{
 | 
			
		||||
	std::list<std::string> effectNames;
 | 
			
		||||
	foreach (auto entry, _availableEffects) {
 | 
			
		||||
		effectNames.push_back(entry.first);
 | 
			
		||||
	}
 | 
			
		||||
	return effectNames;
 | 
			
		||||
	return _availableEffects;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int EffectEngine::runEffect(const std::string &effectName, int priority, int timeout)
 | 
			
		||||
{
 | 
			
		||||
	return runEffect(effectName, Json::Value(Json::nullValue), priority, timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int EffectEngine::runEffect(const std::string &effectName, const Json::Value &args, int priority, int timeout)
 | 
			
		||||
{
 | 
			
		||||
	std::cout << "run effect " << effectName << " on channel " << priority << std::endl;
 | 
			
		||||
 | 
			
		||||
	if (_availableEffects.find(effectName) == _availableEffects.end())
 | 
			
		||||
	const EffectDefinition * effectDefinition = nullptr;
 | 
			
		||||
	for (const EffectDefinition & e : _availableEffects)
 | 
			
		||||
	{
 | 
			
		||||
		if (e.name == effectName)
 | 
			
		||||
		{
 | 
			
		||||
			effectDefinition = &e;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (effectDefinition == nullptr)
 | 
			
		||||
	{
 | 
			
		||||
		// no such effect
 | 
			
		||||
		std::cerr << "effect " << effectName << " not found" << std::endl;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -66,8 +77,7 @@ int EffectEngine::runEffect(const std::string &effectName, int priority, int tim
 | 
			
		||||
	channelCleared(priority);
 | 
			
		||||
 | 
			
		||||
	// create the effect
 | 
			
		||||
	const EffectDefinition & effectDefinition = _availableEffects[effectName];
 | 
			
		||||
	Effect * effect = new Effect(priority, timeout, effectDefinition.script, effectDefinition.args);
 | 
			
		||||
	Effect * effect = new Effect(priority, timeout, effectDefinition->script, args.isNull() ? effectDefinition->args : args);
 | 
			
		||||
	connect(effect, SIGNAL(setColors(int,std::vector<ColorRgb>,int)), _hyperion, SLOT(setColors(int,std::vector<ColorRgb>,int)), Qt::QueuedConnection);
 | 
			
		||||
	connect(effect, SIGNAL(effectFinished(Effect*)), this, SLOT(effectFinished(Effect*)));
 | 
			
		||||
	_activeEffects.push_back(effect);
 | 
			
		||||
 
 | 
			
		||||
@@ -466,7 +466,7 @@ const Hyperion::InputInfo &Hyperion::getPriorityInfo(const int priority) const
 | 
			
		||||
	return _muxer.getInputInfo(priority);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::list<std::string> Hyperion::getEffects() const
 | 
			
		||||
const std::list<EffectDefinition> & Hyperion::getEffects() const
 | 
			
		||||
{
 | 
			
		||||
	return _effectEngine->getEffects();
 | 
			
		||||
}
 | 
			
		||||
@@ -476,6 +476,11 @@ int Hyperion::setEffect(const std::string &effectName, int priority, int timeout
 | 
			
		||||
	return _effectEngine->runEffect(effectName, priority, timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Hyperion::setEffect(const std::string &effectName, const Json::Value &args, int priority, int timeout)
 | 
			
		||||
{
 | 
			
		||||
	return _effectEngine->runEffect(effectName, args, priority, timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hyperion::update()
 | 
			
		||||
{
 | 
			
		||||
	// Update the muxer, cleaning obsolete priorities
 | 
			
		||||
 
 | 
			
		||||
@@ -162,7 +162,14 @@ void JsonClientConnection::handleEffectCommand(const Json::Value &message)
 | 
			
		||||
	const std::string & effectName = effect["name"].asString();
 | 
			
		||||
 | 
			
		||||
	// set output
 | 
			
		||||
	_hyperion->setEffect(effectName, priority, duration);
 | 
			
		||||
	if (effect.isMember("args"))
 | 
			
		||||
	{
 | 
			
		||||
		_hyperion->setEffect(effectName, effect["args"], priority, duration);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		_hyperion->setEffect(effectName, priority, duration);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// send reply
 | 
			
		||||
	sendSuccessReply();
 | 
			
		||||
@@ -212,11 +219,13 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &)
 | 
			
		||||
 | 
			
		||||
	// collect effect info
 | 
			
		||||
	Json::Value & effects = info["effects"] = Json::Value(Json::arrayValue);
 | 
			
		||||
	std::list<std::string> effectNames = _hyperion->getEffects();
 | 
			
		||||
	for (const std::string & name : effectNames)
 | 
			
		||||
	const std::list<EffectDefinition> & effectsDefinitions = _hyperion->getEffects();
 | 
			
		||||
	for (const EffectDefinition & effectDefinition : effectsDefinitions)
 | 
			
		||||
	{
 | 
			
		||||
		Json::Value effect;
 | 
			
		||||
		effect["name"] = name;
 | 
			
		||||
		effect["name"] = effectDefinition.name;
 | 
			
		||||
		effect["script"] = effectDefinition.script;
 | 
			
		||||
		effect["args"] = effectDefinition.args;
 | 
			
		||||
 | 
			
		||||
		effects.append(effect);
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,10 @@
 | 
			
		||||
                "name" : {
 | 
			
		||||
                    "type" : "string",
 | 
			
		||||
                    "required" : true
 | 
			
		||||
                },
 | 
			
		||||
                "args" : {
 | 
			
		||||
                    "type" : "object",
 | 
			
		||||
                    "required" : false
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "additionalProperties": false
 | 
			
		||||
 
 | 
			
		||||
@@ -102,7 +102,7 @@ void JsonConnection::setImage(QImage image, int priority, int duration)
 | 
			
		||||
	parseReply(reply);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void JsonConnection::setEffect(const std::string &effectName, int priority, int duration)
 | 
			
		||||
void JsonConnection::setEffect(const std::string &effectName, const std::string & effectArgs, int priority, int duration)
 | 
			
		||||
{
 | 
			
		||||
	std::cout << "Start effect " << effectName << std::endl;
 | 
			
		||||
 | 
			
		||||
@@ -112,6 +112,14 @@ void JsonConnection::setEffect(const std::string &effectName, int priority, int
 | 
			
		||||
	command["priority"] = priority;
 | 
			
		||||
	Json::Value & effect = command["effect"];
 | 
			
		||||
	effect["name"] = effectName;
 | 
			
		||||
	if (effectArgs.size() > 0)
 | 
			
		||||
	{
 | 
			
		||||
		Json::Reader reader;
 | 
			
		||||
		if (!reader.parse(effectArgs, effect["args"], false))
 | 
			
		||||
		{
 | 
			
		||||
			throw std::runtime_error("Error in effect arguments: " + reader.getFormattedErrorMessages());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (duration > 0)
 | 
			
		||||
	{
 | 
			
		||||
		command["duration"] = duration;
 | 
			
		||||
 
 | 
			
		||||
@@ -56,10 +56,11 @@ public:
 | 
			
		||||
	/// Start the given effect
 | 
			
		||||
	///
 | 
			
		||||
	/// @param effect The name of the effect
 | 
			
		||||
	/// @param effectArgs The arguments to use instead of the default ones
 | 
			
		||||
	/// @param priority The priority
 | 
			
		||||
	/// @param duration The duration in milliseconds
 | 
			
		||||
	///
 | 
			
		||||
	void setEffect(const std::string & effectName, int priority, int duration);
 | 
			
		||||
	void setEffect(const std::string & effectName, const std::string &effectArgs, int priority, int duration);
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// Retrieve a list of all occupied priority channels
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,7 @@ int main(int argc, char * argv[])
 | 
			
		||||
		ColorParameter     & argColor      = parameters.add<ColorParameter>    ('c', "color"     , "Set all leds to a constant color (either RRGGBB hex value or a color name)");
 | 
			
		||||
		ImageParameter     & argImage      = parameters.add<ImageParameter>    ('i', "image"     , "Set the leds to the colors according to the given image file");
 | 
			
		||||
		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");
 | 
			
		||||
		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");
 | 
			
		||||
@@ -59,6 +60,7 @@ int main(int argc, char * argv[])
 | 
			
		||||
		argAddress.setDefault(defaultServerAddress.toStdString());
 | 
			
		||||
		argPriority.setDefault(defaultPriority);
 | 
			
		||||
		argDuration.setDefault(-1);
 | 
			
		||||
		argEffectArgs.setDefault("");
 | 
			
		||||
 | 
			
		||||
		// parse all options
 | 
			
		||||
		optionParser.parse(argc, const_cast<const char **>(argv));
 | 
			
		||||
@@ -108,7 +110,7 @@ int main(int argc, char * argv[])
 | 
			
		||||
		}
 | 
			
		||||
		else if (argEffect.isSet())
 | 
			
		||||
		{
 | 
			
		||||
			connection.setEffect(argEffect.getValue(), argPriority.getValue(), argDuration.getValue());
 | 
			
		||||
			connection.setEffect(argEffect.getValue(), argEffectArgs.getValue(), argPriority.getValue(), argDuration.getValue());
 | 
			
		||||
		}
 | 
			
		||||
		else if (argServerInfo.isSet())
 | 
			
		||||
		{
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user