mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	Merge remote-tracking branch 'remotes/origin/add_effect_engine' into add_effect_engine
Former-commit-id: c7f7fe4307f7dfaddaef23b71c6ead3491d0e669
This commit is contained in:
		| @@ -133,7 +133,8 @@ void BoblightClientConnection::handleMessage(const QString & message) | ||||
| 					if (messageParts[3] == "rgb" && messageParts.size() == 7) | ||||
| 					{ | ||||
| 						bool rc1, rc2, rc3; | ||||
| 						uint8_t red = 255 * messageParts[4].toFloat(&rc1); | ||||
| 						uint8_t red = qMax(0, qMin(255, int(255 * messageParts[4].toFloat(&rc1)))); | ||||
|  | ||||
| 						if (!rc1) | ||||
| 						{ | ||||
| 							// maybe a locale issue. switch to a locale with a comma instead of a dot as decimal seperator (or vice versa) | ||||
| @@ -141,11 +142,11 @@ void BoblightClientConnection::handleMessage(const QString & message) | ||||
| 							_locale.setNumberOptions(QLocale::OmitGroupSeparator | QLocale::RejectGroupSeparator); | ||||
|  | ||||
| 							// try again | ||||
| 							red = 255 * messageParts[4].toFloat(&rc1); | ||||
| 							red = qMax(0, qMin(255, int(255 * messageParts[4].toFloat(&rc1)))); | ||||
| 						} | ||||
|  | ||||
| 						uint8_t green = 255 * messageParts[5].toFloat(&rc2); | ||||
| 						uint8_t blue  = 255 * messageParts[6].toFloat(&rc3); | ||||
| 						uint8_t green = qMax(0, qMin(255, 255 * int(messageParts[5].toFloat(&rc2)))); | ||||
| 						uint8_t blue  = qMax(0, qMin(255, 255 * int(messageParts[6].toFloat(&rc3)))); | ||||
|  | ||||
| 						if (rc1 && rc2 && rc3) | ||||
| 						{ | ||||
| @@ -153,6 +154,13 @@ void BoblightClientConnection::handleMessage(const QString & message) | ||||
| 							rgb.red = red; | ||||
| 							rgb.green = green; | ||||
| 							rgb.blue = blue; | ||||
|  | ||||
| 							// send current color values to hyperion if this is the last led assuming leds values are send in order of id | ||||
| 							if ((ledIndex == _ledColors.size() -1) && _priority < 255) | ||||
| 							{ | ||||
| 								_hyperion->setColors(_priority, _ledColors, -1); | ||||
| 							} | ||||
|  | ||||
| 							return; | ||||
| 						} | ||||
| 					} | ||||
|   | ||||
| @@ -40,6 +40,7 @@ SET(Hyperion_HEADERS | ||||
| 		${CURRENT_SOURCE_DIR}/device/LedDeviceLpd6803.h | ||||
| 		${CURRENT_SOURCE_DIR}/device/LedDeviceLpd8806.h | ||||
| 		${CURRENT_SOURCE_DIR}/device/LedDeviceLightpack.h | ||||
| 		${CURRENT_SOURCE_DIR}/device/LedDevicePaintpack.h | ||||
| 		${CURRENT_SOURCE_DIR}/device/LedDeviceMultiLightpack.h | ||||
| ) | ||||
|  | ||||
| @@ -65,6 +66,7 @@ SET(Hyperion_SOURCES | ||||
| 		${CURRENT_SOURCE_DIR}/device/LedDeviceLpd8806.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/device/LedDeviceAdalight.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/device/LedDeviceLightpack.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/device/LedDevicePaintpack.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/device/LedDeviceMultiLightpack.cpp | ||||
| ) | ||||
|  | ||||
| @@ -87,6 +89,7 @@ add_library(hyperion | ||||
| target_link_libraries(hyperion | ||||
| 		hyperion-utils | ||||
| 		effectengine | ||||
| 		hidapi-libusb | ||||
| 		serialport | ||||
| 		${LIBUSB_1_LIBRARIES} #apt-get install libusb-1.0-0-dev | ||||
| 		${CMAKE_THREAD_LIBS_INIT} | ||||
|   | ||||
| @@ -23,6 +23,7 @@ | ||||
| #include "device/LedDeviceTest.h" | ||||
| #include "device/LedDeviceWs2801.h" | ||||
| #include "device/LedDeviceAdalight.h" | ||||
| #include "device/LedDevicePaintpack.h" | ||||
| #include "device/LedDeviceLightpack.h" | ||||
| #include "device/LedDeviceMultiLightpack.h" | ||||
|  | ||||
| @@ -40,7 +41,7 @@ LedDevice* Hyperion::createDevice(const Json::Value& deviceConfig) | ||||
| 	std::transform(type.begin(), type.end(), type.begin(), ::tolower); | ||||
|  | ||||
| 	LedDevice* device = nullptr; | ||||
| 	if (type == "ws2801") | ||||
| 	if (type == "ws2801" || type == "lightberry") | ||||
| 	{ | ||||
| 		const std::string output = deviceConfig["output"].asString(); | ||||
| 		const unsigned rate      = deviceConfig["rate"].asInt(); | ||||
| @@ -99,6 +100,13 @@ LedDevice* Hyperion::createDevice(const Json::Value& deviceConfig) | ||||
|  | ||||
| 		device = deviceLightpack; | ||||
| 	} | ||||
| 	else if (type == "paintpack") | ||||
| 	{ | ||||
| 		LedDevicePaintpack * devicePainLightpack = new LedDevicePaintpack(); | ||||
| 		devicePainLightpack->open(); | ||||
|  | ||||
| 		device = devicePainLightpack; | ||||
| 	} | ||||
| 	else if (type == "multi-lightpack") | ||||
| 	{ | ||||
| 		LedDeviceMultiLightpack* deviceLightpack = new LedDeviceMultiLightpack(); | ||||
|   | ||||
							
								
								
									
										77
									
								
								libsrc/hyperion/device/LedDevicePaintpack.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								libsrc/hyperion/device/LedDevicePaintpack.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
|  | ||||
| // Hyperion includes | ||||
| #include "LedDevicePaintpack.h" | ||||
|  | ||||
| LedDevicePaintpack::LedDevicePaintpack() : | ||||
| 	LedDevice(), | ||||
| 	_deviceHandle(nullptr) | ||||
| { | ||||
| 	// empty | ||||
| } | ||||
|  | ||||
| int LedDevicePaintpack::open() | ||||
| { | ||||
| 	// initialize the usb context | ||||
| 	int error = hid_init(); | ||||
| 	if (error != 0) | ||||
| 	{ | ||||
| 		std::cerr << "Error while initializing the hidapi context" << std::endl; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	std::cout << "Hidapi initialized" << std::endl; | ||||
|  | ||||
| 	// Initialise the paintpack device | ||||
| 	const unsigned short Paintpack_VendorId  = 0x0ebf; | ||||
| 	const unsigned short Paintpack_ProductId = 0x0025; | ||||
| 	_deviceHandle = hid_open(Paintpack_VendorId, Paintpack_ProductId, nullptr); | ||||
| 	if (_deviceHandle == nullptr) | ||||
| 	{ | ||||
| 		// Failed to open the device | ||||
| 		std::cerr << "Failed to open HID Paintpakc device " << std::endl; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| LedDevicePaintpack::~LedDevicePaintpack() | ||||
| { | ||||
| 	if (_deviceHandle != nullptr) | ||||
| 	{ | ||||
| 		hid_close(_deviceHandle); | ||||
| 		_deviceHandle = nullptr; | ||||
| 	} | ||||
|  | ||||
| 	hid_exit(); | ||||
| } | ||||
|  | ||||
| int LedDevicePaintpack::write(const std::vector<ColorRgb>& ledValues) | ||||
| { | ||||
| 	if (_ledBuffer.size() < 3 + ledValues.size()*3) | ||||
| 	{ | ||||
| 		_ledBuffer.resize(3 + ledValues.size()*3, uint8_t(0)); | ||||
|  | ||||
| 		_ledBuffer[0] = 0; | ||||
| 		_ledBuffer[1] = 3; | ||||
| 		_ledBuffer[2] = 0; | ||||
| 	} | ||||
|  | ||||
| 	auto bufIt = _ledBuffer.begin()+3; | ||||
| 	for (const ColorRgb & ledValue : ledValues) | ||||
| 	{ | ||||
| 		*bufIt = ledValue.red; | ||||
| 		++bufIt; | ||||
| 		*bufIt = ledValue.green; | ||||
| 		++bufIt; | ||||
| 		*bufIt = ledValue.blue; | ||||
| 		++bufIt; | ||||
| 	} | ||||
|  | ||||
| 	return hid_write(_deviceHandle, _ledBuffer.data(), _ledBuffer.size()); | ||||
| } | ||||
|  | ||||
| int LedDevicePaintpack::switchOff() | ||||
| { | ||||
| 	std::fill(_ledBuffer.begin()+3, _ledBuffer.end(), uint8_t(0)); | ||||
| 	return hid_write(_deviceHandle, _ledBuffer.data(), _ledBuffer.size()); | ||||
| } | ||||
							
								
								
									
										59
									
								
								libsrc/hyperion/device/LedDevicePaintpack.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								libsrc/hyperion/device/LedDevicePaintpack.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| #pragma once | ||||
|  | ||||
| // STL includes | ||||
| #include <vector> | ||||
|  | ||||
| // libusb include | ||||
| #include <hidapi/hidapi.h> | ||||
|  | ||||
| // Hyperion includes | ||||
| #include <hyperion/LedDevice.h> | ||||
|  | ||||
| /// | ||||
| /// LedDevice implementation for a paintpack device () | ||||
| /// | ||||
| class LedDevicePaintpack : public LedDevice | ||||
| { | ||||
| public: | ||||
| 	/** | ||||
| 	 * Constructs the paintpack device | ||||
| 	 */ | ||||
| 	LedDevicePaintpack(); | ||||
|  | ||||
| 	/** | ||||
| 	 * Destructs the paintpack device, closes USB connection if open | ||||
| 	 */ | ||||
| 	virtual ~LedDevicePaintpack(); | ||||
|  | ||||
| 	/** | ||||
| 	 * Opens the Paintpack device | ||||
| 	 * | ||||
| 	 * @return Zero on succes else negative | ||||
| 	 */ | ||||
| 	int open(); | ||||
|  | ||||
| 	/// | ||||
| 	/// Writes the RGB-Color values to the leds. | ||||
| 	/// | ||||
| 	/// @param[in] ledValues  The RGB-color per led | ||||
| 	/// | ||||
| 	/// @return Zero on success else negative | ||||
| 	/// | ||||
| 	virtual int write(const std::vector<ColorRgb>& ledValues); | ||||
|  | ||||
| 	/// | ||||
| 	/// Switch the leds off | ||||
| 	/// | ||||
| 	/// @return Zero on success else negative | ||||
| 	/// | ||||
| 	virtual int switchOff(); | ||||
|  | ||||
| private: | ||||
| 	/// libusb device handle | ||||
| 	hid_device * _deviceHandle; | ||||
|  | ||||
| 	/// buffer for led data | ||||
| 	std::vector<uint8_t> _ledBuffer; | ||||
|  | ||||
|  | ||||
| }; | ||||
| @@ -114,10 +114,33 @@ void JsonClientConnection::handleColorCommand(const Json::Value &message) | ||||
| 	// extract parameters | ||||
| 	int priority = message["priority"].asInt(); | ||||
| 	int duration = message.get("duration", -1).asInt(); | ||||
| 	ColorRgb color = {uint8_t(message["color"][0u].asInt()), uint8_t(message["color"][1u].asInt()), uint8_t(message["color"][2u].asInt())}; | ||||
|  | ||||
| 	std::vector<ColorRgb> colorData(_hyperion->getLedCount()); | ||||
| 	const Json::Value & jsonColor = message["color"]; | ||||
| 	Json::UInt i = 0; | ||||
| 	for (; i < jsonColor.size()/3 && i < _hyperion->getLedCount(); ++i) | ||||
| 	{ | ||||
| 		colorData[i].red = uint8_t(message["color"][3u*i].asInt()); | ||||
| 		colorData[i].green = uint8_t(message["color"][3u*i+1u].asInt()); | ||||
| 		colorData[i].blue = uint8_t(message["color"][3u*i+2u].asInt()); | ||||
| 	} | ||||
|  | ||||
| 	// copy full blocks of led colors | ||||
| 	unsigned size = i; | ||||
| 	while (i + size < _hyperion->getLedCount()) | ||||
| 	{ | ||||
| 		memcpy(&(colorData[i]), colorData.data(), size * sizeof(ColorRgb)); | ||||
| 		i += size; | ||||
| 	} | ||||
|  | ||||
| 	// copy remaining block of led colors | ||||
| 	if (i < _hyperion->getLedCount()) | ||||
| 	{ | ||||
| 		memcpy(&(colorData[i]), colorData.data(), (_hyperion->getLedCount()-i) * sizeof(ColorRgb)); | ||||
| 	} | ||||
|  | ||||
| 	// set output | ||||
| 	_hyperion->setColor(priority, color, duration); | ||||
| 	_hyperion->setColors(priority, colorData, duration); | ||||
|  | ||||
| 	// send reply | ||||
| 	sendSuccessReply(); | ||||
|   | ||||
| @@ -21,8 +21,7 @@ | ||||
|             "items" :{ | ||||
|                 "type" : "integer" | ||||
|             }, | ||||
|             "minItems": 3, | ||||
|             "maxItems": 3 | ||||
|             "minItems": 3 | ||||
|         } | ||||
|     }, | ||||
|     "additionalProperties": false | ||||
|   | ||||
| @@ -11,7 +11,7 @@ | ||||
| #include "ColorTransformValues.h" | ||||
|  | ||||
| /// Data parameter for a color | ||||
| typedef vlofgren::PODParameter<QColor> ColorParameter; | ||||
| typedef vlofgren::PODParameter<std::vector<QColor>> ColorParameter; | ||||
|  | ||||
| /// Data parameter for an image | ||||
| typedef vlofgren::PODParameter<QImage> ImageParameter; | ||||
| @@ -21,40 +21,54 @@ typedef vlofgren::PODParameter<ColorTransformValues> TransformParameter; | ||||
|  | ||||
| namespace vlofgren { | ||||
| 	/// | ||||
| 	/// Translates a string (as passed on the commandline) to a color | ||||
| 	/// 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 color | ||||
| 	/// @return The translated colors | ||||
| 	/// | ||||
| 	/// @throws Parameter::ParameterRejected If the string did not result in a color | ||||
| 	/// | ||||
| 	template<> | ||||
| 	QColor ColorParameter::validate(const std::string& s) throw (Parameter::ParameterRejected) | ||||
| 	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 color; | ||||
| 			return std::vector<QColor>{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])) | ||||
| 		if (s.length() >= 6u && (s.length()%6) == 0u && std::count_if(s.begin(), s.end(), isxdigit) == s.length()) | ||||
| 		{ | ||||
| 			bool ok = true; | ||||
| 			int rgb[3]; | ||||
| 			for (int i = 0; i < 3 && ok; ++i) | ||||
| 			std::vector<QColor> colors; | ||||
|  | ||||
| 			for (size_t j = 0; j < s.length()/6; ++j) | ||||
| 			{ | ||||
| 				QString colorComponent(s.substr(2*i, 2).c_str()); | ||||
| 				rgb[i] = colorComponent.toInt(&ok, 16); | ||||
| 				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) | ||||
| 			{ | ||||
| 				color.setRgb(rgb[0], rgb[1], rgb[2]); | ||||
| 				return color; | ||||
| 				return colors; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @@ -65,7 +79,7 @@ namespace vlofgren { | ||||
| 		} | ||||
| 		throw Parameter::ParameterRejected(errorMessage.str()); | ||||
|  | ||||
| 		return color; | ||||
| 		return std::vector<QColor>{color}; | ||||
| 	} | ||||
|  | ||||
| 	template<> | ||||
|   | ||||
| @@ -39,18 +39,21 @@ JsonConnection::~JsonConnection() | ||||
| 	_socket.close(); | ||||
| } | ||||
|  | ||||
| void JsonConnection::setColor(QColor color, int priority, int duration) | ||||
| void JsonConnection::setColor(std::vector<QColor> colors, int priority, int duration) | ||||
| { | ||||
| 	std::cout << "Set color to " << color.red() << " " << color.green() << " " << color.blue() << std::endl; | ||||
| 	std::cout << "Set color to " << colors[0].red() << " " << colors[0].green() << " " << colors[0].blue() << (colors.size() > 1 ? " + ..." : "") << std::endl; | ||||
|  | ||||
| 	// create command | ||||
| 	Json::Value command; | ||||
| 	command["command"] = "color"; | ||||
| 	command["priority"] = priority; | ||||
| 	Json::Value & rgbValue = command["color"]; | ||||
| 	rgbValue[0] = color.red(); | ||||
| 	rgbValue[1] = color.green(); | ||||
| 	rgbValue[2] = color.blue(); | ||||
| 	for (const QColor & color : colors) | ||||
| 	{ | ||||
| 		rgbValue.append(color.red()); | ||||
| 		rgbValue.append(color.green()); | ||||
| 		rgbValue.append(color.blue()); | ||||
| 	} | ||||
| 	if (duration > 0) | ||||
| 	{ | ||||
| 		command["duration"] = duration; | ||||
|   | ||||
| @@ -41,7 +41,7 @@ public: | ||||
| 	/// @param priority The priority | ||||
| 	/// @param duration The duration in milliseconds | ||||
| 	/// | ||||
| 	void setColor(QColor color, int priority, int duration); | ||||
| 	void setColor(std::vector<QColor> color, int priority, int duration); | ||||
|  | ||||
| 	/// | ||||
| 	/// Set the leds according to the given image (assume the image is stretched to the display size) | ||||
|   | ||||
| @@ -40,7 +40,7 @@ int main(int argc, char * argv[]) | ||||
| 		StringParameter    & argAddress    = parameters.add<StringParameter>   ('a', "address"   , QString("Set the address of the hyperion server [default: %1]").arg(defaultServerAddress).toAscii().constData()); | ||||
| 		IntParameter       & argPriority   = parameters.add<IntParameter>      ('p', "priority"  , QString("Use to the provided priority channel (the lower the number, the higher the priority) [default: %1]").arg(defaultPriority).toAscii().constData()); | ||||
| 		IntParameter       & argDuration   = parameters.add<IntParameter>      ('d', "duration"  , "Specify how long the leds should be switched on in millseconds [default: infinity]"); | ||||
| 		ColorParameter     & argColor      = parameters.add<ColorParameter>    ('c', "color"     , "Set all leds to a constant color (either RRGGBB hex value or a color name)"); | ||||
| 		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."); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user