mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	Threading and more
- webui remove restarts - threading for LedDevice
This commit is contained in:
		| @@ -1,5 +1,4 @@ | ||||
| $(document).ready( function() { | ||||
| 	var uiLock = false; | ||||
|  | ||||
| 	loadContentTo("#container_connection_lost","connection_lost"); | ||||
| 	loadContentTo("#container_restart","restart"); | ||||
| @@ -7,42 +6,26 @@ $(document).ready( function() { | ||||
|  | ||||
| 	$(hyperion).on("cmd-serverinfo",function(event){ | ||||
| 		serverInfo = event.response.info; | ||||
| 		// protect components from serverinfo updates | ||||
| 		if(!compsInited) | ||||
| 		{ | ||||
| 			comps = event.response.info.components | ||||
| 			compsInited = true; | ||||
| 		} | ||||
| 		// comps | ||||
| 		comps = event.response.info.components | ||||
|  | ||||
| 		if(!priosInited) | ||||
| 		{ | ||||
| 			priosInited = true; | ||||
| 		} | ||||
| 		$(hyperion).trigger("ready"); | ||||
|  | ||||
| 		if (serverInfo.hyperion.config_modified) | ||||
| 			$("#hyperion_reload_notify").fadeIn("fast"); | ||||
| 		else | ||||
| 			$("#hyperion_reload_notify").fadeOut("fast"); | ||||
| 		comps.forEach( function(obj) { | ||||
| 			if (obj.name == "ALL") | ||||
| 			{ | ||||
| 				if(obj.enabled) | ||||
| 					$("#hyperion_disabled_notify").fadeOut("fast"); | ||||
| 				else | ||||
| 					$("#hyperion_disabled_notify").fadeIn("fast"); | ||||
| 			} | ||||
| 		}); | ||||
|  | ||||
| 		if (serverInfo.hyperion.enabled) | ||||
| 			$("#hyperion_disabled_notify").fadeOut("fast"); | ||||
| 		else | ||||
| 			$("#hyperion_disabled_notify").fadeIn("fast"); | ||||
|  | ||||
| 		if (!serverInfo.hyperion.config_writeable) | ||||
| 		{ | ||||
| 			showInfoDialog('uilock',$.i18n('InfoDialog_nowrite_title'),$.i18n('InfoDialog_nowrite_text')); | ||||
| 			$('#wrapper').toggle(false); | ||||
| 			uiLock = true; | ||||
| 		} | ||||
| 		else if (uiLock) | ||||
| 		{ | ||||
| 			$("#modal_dialog").modal('hide'); | ||||
| 			$('#wrapper').toggle(true); | ||||
| 			uiLock = false; | ||||
| 		} | ||||
|  | ||||
| 		updateSessions(); | ||||
| 	}); // end cmd-serverinfo | ||||
|  | ||||
| @@ -51,21 +34,21 @@ $(document).ready( function() { | ||||
| 		updateSessions(); | ||||
| 	}); | ||||
|  | ||||
| 	$(hyperion).one("cmd-sysinfo", function(event) { | ||||
| 	$(hyperion).on("cmd-sysinfo", function(event) { | ||||
| 		requestServerInfo(); | ||||
| 		sysInfo = event.response.info; | ||||
|  | ||||
| 		currentVersion = sysInfo.hyperion.version; | ||||
| 	}); | ||||
|  | ||||
| 	$(hyperion).one("cmd-config-getschema", function(event) { | ||||
| 	$(hyperion).on("cmd-config-getschema", function(event) { | ||||
| 		serverSchema = event.response.info; | ||||
| 		requestServerConfig(); | ||||
|  | ||||
| 		schema = serverSchema.properties; | ||||
| 	}); | ||||
|  | ||||
| 	$(hyperion).one("cmd-config-getconfig", function(event) { | ||||
| 	$(hyperion).on("cmd-config-getconfig", function(event) { | ||||
| 		serverConfig = event.response.info; | ||||
| 		requestSysInfo(); | ||||
|  | ||||
| @@ -80,7 +63,7 @@ $(document).ready( function() { | ||||
| 		requestServerConfigSchema(); | ||||
| 	}); | ||||
|  | ||||
| 	$(hyperion).one("ready", function(event) { | ||||
| 	$(hyperion).on("ready", function(event) { | ||||
| 		loadContent(); | ||||
| 	}); | ||||
|  | ||||
| @@ -98,7 +81,7 @@ $(document).ready( function() { | ||||
| 		// notfication in index | ||||
| 		if (obj.name == "ALL") | ||||
| 		{ | ||||
| 			if(obj.enable) | ||||
| 			if(obj.enabled) | ||||
| 				$("#hyperion_disabled_notify").fadeOut("fast"); | ||||
| 			else | ||||
| 				$("#hyperion_disabled_notify").fadeIn("fast"); | ||||
| @@ -117,10 +100,6 @@ $(document).ready( function() { | ||||
| 		serverInfo.effects = event.response.data.effects | ||||
| 	}); | ||||
|  | ||||
| 	$("#btn_hyperion_reload").on("click", function(){ | ||||
| 		initRestart(); | ||||
| 	}); | ||||
|  | ||||
| 	$(".mnava").bind('click.menu', function(e){ | ||||
| 		loadContent(e); | ||||
| 		window.scrollTo(0, 0); | ||||
|   | ||||
| @@ -203,6 +203,14 @@ $(document).ready(function() { | ||||
| 	function updateComponents() | ||||
| 	{ | ||||
| 		components = comps; | ||||
| 		var hyperionEnabled = true; | ||||
| 		components.forEach( function(obj) { | ||||
| 			if (obj.name == "ALL") | ||||
| 			{ | ||||
| 				hyperionEnabled = obj.enabled | ||||
| 			} | ||||
| 		}); | ||||
|  | ||||
| 		// create buttons | ||||
| 		$('#componentsbutton').html(""); | ||||
| 		for ( idx=0; idx<components.length;idx++) | ||||
| @@ -214,7 +222,7 @@ $(document).ready(function() { | ||||
| 			enable_icon  = (components[idx].enabled? "fa-play" : "fa-stop"); | ||||
| 			comp_name    = components[idx].name; | ||||
| 			comp_btn_id  = "comp_btn_"+comp_name; | ||||
| 			comp_goff	 = serverInfo.hyperion.enabled? "enabled" : "disabled"; | ||||
| 			comp_goff	 = hyperionEnabled? "enabled" : "disabled"; | ||||
|  | ||||
| 			// create btn if not there | ||||
| 			if ($("#"+comp_btn_id).length == 0) | ||||
|   | ||||
| @@ -25,14 +25,8 @@ var wSess = []; | ||||
| var plugins_installed = {}; | ||||
| var plugins_available = {}; | ||||
|  | ||||
| //comps serverinfo lock | ||||
| //comps serverinfo | ||||
| comps = []; | ||||
| compsInited = false; | ||||
|  | ||||
| // prios serverinfo lock | ||||
| priosInited = false; | ||||
| // token list | ||||
| tokenList = {} | ||||
|  | ||||
| function initRestart() | ||||
| { | ||||
|   | ||||
| @@ -91,7 +91,7 @@ function getHashtag() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function loadContent(event) | ||||
| function loadContent(event, forceRefresh) | ||||
| { | ||||
| 	var tag; | ||||
|  | ||||
| @@ -104,7 +104,7 @@ function loadContent(event) | ||||
| 	else | ||||
| 		tag = getHashtag(); | ||||
|  | ||||
| 	if(prevTag != tag) | ||||
| 	if(forceRefresh || prevTag != tag) | ||||
| 	{ | ||||
| 		prevTag = tag; | ||||
| 		$("#page-content").off(); | ||||
|   | ||||
| @@ -58,7 +58,7 @@ | ||||
| 		$('#wizp2_body').append('<div class="form-group"><label>'+$.i18n('wiz_rgb_switchevery')+'</label><div class="input-group" style="width:100px"><select id="wiz_switchtime_select" class="form-control"></select><div class="input-group-addon">'+$.i18n('edt_append_s')+'</div></div></div>'); | ||||
| 		$('#wizp2_body').append('<canvas id="wiz_canv_color" width="100" height="100" style="border-radius:60px;background-color:red; display:block; margin: 10px 0;border:4px solid grey;"></canvas><label>'+$.i18n('wiz_rgb_q')+'</label>'); | ||||
| 		$('#wizp2_body').append('<table class="table borderless" style="width:200px"><tbody><tr><td class="ltd"><label>'+$.i18n('wiz_rgb_qrend')+'</label></td><td class="itd"><select id="wiz_r_select" class="form-control wselect"></select></td></tr><tr><td class="ltd"><label>'+$.i18n('wiz_rgb_qgend')+'</label></td><td class="itd"><select id="wiz_g_select" class="form-control wselect"></select></td></tr></tbody></table>'); | ||||
| 		$('#wizp2_footer').html('<button type="button" class="btn btn-primary" id="btn_wiz_save"><i class="fa fa-fw fa-save"></i>'+$.i18n('general_btn_saverestart')+'</button><button type="button" class="btn btn-primary" id="btn_wiz_checkok" style="display:none" data-dismiss="modal"><i class="fa fa-fw fa-check"></i>'+$.i18n('general_btn_ok')+'</button><button type="button" class="btn btn-danger" id="btn_wiz_abort"><i class="fa fa-fw fa-close"></i>'+$.i18n('general_btn_cancel')+'</button>') | ||||
| 		$('#wizp2_footer').html('<button type="button" class="btn btn-primary" id="btn_wiz_save"><i class="fa fa-fw fa-save"></i>'+$.i18n('general_btn_save')+'</button><button type="button" class="btn btn-primary" id="btn_wiz_checkok" style="display:none" data-dismiss="modal"><i class="fa fa-fw fa-check"></i>'+$.i18n('general_btn_ok')+'</button><button type="button" class="btn btn-danger" id="btn_wiz_abort"><i class="fa fa-fw fa-close"></i>'+$.i18n('general_btn_cancel')+'</button>') | ||||
|  | ||||
| 		//open modal | ||||
| 		$("#wizard_modal").modal({ | ||||
| @@ -155,7 +155,6 @@ | ||||
| 			resetWizard(); | ||||
| 			serverConfig.device.colorOrder = new_rgb_order; | ||||
| 			requestWriteConfig({"device" : serverConfig.device}); | ||||
| 			setTimeout(initRestart, 100); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| @@ -416,7 +415,7 @@ | ||||
| 		$('#wizp1_body').html('<h4 style="font-weight:bold;text-transform:uppercase;">'+$.i18n('wiz_cc_title')+'</h4><p>'+$.i18n('wiz_cc_intro1')+'</p><label>'+$.i18n('wiz_cc_kwebs')+'</label><input class="form-control" style="width:170px;margin:auto" id="wiz_cc_kodiip" type="text" placeholder="'+kodiAddress+'" value="'+kodiAddress+'" /><span id="kodi_status"></span><span id="multi_cali"></span>'); | ||||
| 		$('#wizp1_footer').html('<button type="button" class="btn btn-primary" id="btn_wiz_cont" disabled="disabled"><i class="fa fa-fw fa-check"></i>'+$.i18n('general_btn_continue')+'</button><button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-fw fa-close"></i>'+$.i18n('general_btn_cancel')+'</button>'); | ||||
| 		$('#wizp2_body').html('<div id="wiz_cc_desc" style="font-weight:bold"></div><div id="editor_container_wiz"></div>'); | ||||
| 		$('#wizp2_footer').html('<button type="button" class="btn btn-primary" id="btn_wiz_back"><i class="fa fa-fw fa-chevron-left"></i>'+$.i18n('general_btn_back')+'</button><button type="button" class="btn btn-primary" id="btn_wiz_next">'+$.i18n('general_btn_next')+'<i style="margin-left:4px;"class="fa fa-fw fa-chevron-right"></i></button><button type="button" class="btn btn-warning" id="btn_wiz_save" style="display:none"><i class="fa fa-fw fa-save"></i>'+$.i18n('general_btn_saverestart')+'</button><button type="button" class="btn btn-danger" id="btn_wiz_abort"><i class="fa fa-fw fa-close"></i>'+$.i18n('general_btn_cancel')+'</button>') | ||||
| 		$('#wizp2_footer').html('<button type="button" class="btn btn-primary" id="btn_wiz_back"><i class="fa fa-fw fa-chevron-left"></i>'+$.i18n('general_btn_back')+'</button><button type="button" class="btn btn-primary" id="btn_wiz_next">'+$.i18n('general_btn_next')+'<i style="margin-left:4px;"class="fa fa-fw fa-chevron-right"></i></button><button type="button" class="btn btn-warning" id="btn_wiz_save" style="display:none"><i class="fa fa-fw fa-save"></i>'+$.i18n('general_btn_save')+'</button><button type="button" class="btn btn-danger" id="btn_wiz_abort"><i class="fa fa-fw fa-close"></i>'+$.i18n('general_btn_cancel')+'</button>') | ||||
|  | ||||
| 		//open modal | ||||
| 		$("#wizard_modal").modal({ | ||||
| @@ -500,7 +499,6 @@ | ||||
| 		$('#btn_wiz_save').off().on('click',function() { | ||||
| 			requestWriteConfig(wiz_editor.getValue()); | ||||
| 			resetWizard(); | ||||
| 			setTimeout(initRestart, 200); | ||||
| 		}); | ||||
|  | ||||
| 		wiz_editor.on("change", function(e){ | ||||
| @@ -538,7 +536,7 @@ | ||||
| 		$('#wizp2_body').append('<div id="hue_ids_t" style="display:none"><p style="font-weight:bold">'+$.i18n('wiz_hue_desc2')+'</p></div>'); | ||||
| 		createTable("lidsh", "lidsb", "hue_ids_t"); | ||||
| 		$('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lightid_title'),$.i18n('wiz_hue_pos'),$.i18n('wiz_hue_ident')], true)); | ||||
| 		$('#wizp2_footer').html('<button type="button" class="btn btn-primary" id="btn_wiz_save" style="display:none"><i class="fa fa-fw fa-save"></i>'+$.i18n('general_btn_saverestart')+'</button><button type="button" class="btn btn-danger" id="btn_wiz_abort"><i class="fa fa-fw fa-close"></i>'+$.i18n('general_btn_cancel')+'</button>'); | ||||
| 		$('#wizp2_footer').html('<button type="button" class="btn btn-primary" id="btn_wiz_save" style="display:none"><i class="fa fa-fw fa-save"></i>'+$.i18n('general_btn_save')+'</button><button type="button" class="btn btn-danger" id="btn_wiz_abort"><i class="fa fa-fw fa-close"></i>'+$.i18n('general_btn_cancel')+'</button>'); | ||||
| 		$('#wizp3_body').html('<span>'+$.i18n('wiz_hue_press_link')+'</span> <br /><br /><center><span id="connectionTime"></span><br /><i class="fa fa-cog fa-spin" style="font-size:100px"></i></center>'); | ||||
|  | ||||
| 		//open modal | ||||
| @@ -751,7 +749,7 @@ | ||||
| 			serverConfig.smoothing.enable = false; | ||||
|  | ||||
| 			requestWriteConfig(serverConfig, true); | ||||
| 			setTimeout(initRestart,200); | ||||
| 			resetWizard(); | ||||
| 		}); | ||||
|  | ||||
| 		$('#btn_wiz_abort').off().on('click', resetWizard); | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
| #include <utils/settings.h> | ||||
|  | ||||
| class Grabber; | ||||
| class DispmanxFrameGrabber; | ||||
| class GlobalSignals; | ||||
| class QTimer; | ||||
|  | ||||
| /// | ||||
| @@ -60,7 +60,6 @@ public: | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| public slots: | ||||
| 	/// | ||||
| 	/// virtual method, should perform single frame grab and computes the led-colors | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| #include <QMap> | ||||
|  | ||||
| // QT includes | ||||
| #include <QObject> | ||||
| //#include <QObject> | ||||
| #include <QString> | ||||
| #include <QStringList> | ||||
| #include <QSize> | ||||
| @@ -37,11 +37,9 @@ | ||||
|  | ||||
| // Forward class declaration | ||||
| class QTimer; | ||||
|  | ||||
| class HyperionDaemon; | ||||
| class ImageProcessor; | ||||
| class MessageForwarder; | ||||
| class LedDevice; | ||||
| class LinearColorSmoothing; | ||||
| class EffectEngine; | ||||
| class MultiColorAdjustment; | ||||
| @@ -50,6 +48,7 @@ class SettingsManager; | ||||
| class BGEffectHandler; | ||||
| class CaptureCont; | ||||
| class BoblightServer; | ||||
| class LedDeviceWrapper; | ||||
|  | ||||
| /// | ||||
| /// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through | ||||
| @@ -228,6 +227,13 @@ public: | ||||
| 	/// @return the state | ||||
| 	bool sourceAutoSelectEnabled(); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief Called from components to update their current state. DO NOT CALL FROM USERS | ||||
| 	/// @param[in] component The component from enum | ||||
| 	/// @param[in] state The state of the component [true | false] | ||||
| 	/// | ||||
| 	void setNewComponentState(const hyperion::Components& component, const bool& state); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief Enable/Disable components during runtime, called from external API (requests) | ||||
| 	/// | ||||
| @@ -432,13 +438,9 @@ signals: | ||||
| 	void effectListUpdated(); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief systemImage from the parent HyperionDaemon SystemCapture | ||||
| 	/// @brief Emits whenever new data should be pushed to the LedDeviceWrapper which forwards it to the threaded LedDevice | ||||
| 	/// | ||||
| 	void systemImage(const Image<ColorRgb>& image); | ||||
| 	/// | ||||
| 	/// @brief v4lImage from the parent HyperionDaemon V4lCapture | ||||
| 	/// | ||||
| 	void v4lImage(const Image<ColorRgb> & image); | ||||
| 	void ledDeviceData(const std::vector<ColorRgb>& ledValues); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief Emits whenever new untransformed ledColos data is available, reflects the current visible device | ||||
| @@ -504,8 +506,8 @@ private: | ||||
| 	/// The adjustment from raw colors to led colors | ||||
| 	MultiColorAdjustment * _raw2ledAdjustment; | ||||
|  | ||||
| 	/// The actual LedDevice | ||||
| 	LedDevice * _device; | ||||
| 	/// The actual LedDeviceWrapper | ||||
| 	LedDeviceWrapper* _ledDeviceWrapper; | ||||
|  | ||||
| 	/// The smoothing LedDevice | ||||
| 	LinearColorSmoothing * _deviceSmooth; | ||||
| @@ -513,7 +515,7 @@ private: | ||||
| 	/// Effect engine | ||||
| 	EffectEngine * _effectEngine; | ||||
|  | ||||
| 	// proto and json Message forwarder | ||||
| 	// Message forwarder | ||||
| 	MessageForwarder * _messageForwarder; | ||||
|  | ||||
| 	/// the name of config file | ||||
|   | ||||
| @@ -34,11 +34,8 @@ class LedDevice : public QObject | ||||
| 	Q_OBJECT | ||||
|  | ||||
| public: | ||||
| 	LedDevice(); | ||||
| 	/// | ||||
| 	/// Empty virtual destructor for pure virtual base class | ||||
| 	/// | ||||
| 	virtual ~LedDevice() {} | ||||
| 	LedDevice(const QJsonObject& config = QJsonObject(), QObject* parent = nullptr); | ||||
| 	virtual ~LedDevice(); | ||||
|  | ||||
| 	/// Switch the leds off (led hardware disable) | ||||
| 	virtual int switchOff(); | ||||
| @@ -48,33 +45,38 @@ public: | ||||
|  | ||||
| 	virtual int setLedValues(const std::vector<ColorRgb>& ledValues); | ||||
|  | ||||
| 	/// | ||||
| 	/// Opens and configures the output device | ||||
| 	/// | ||||
| 	/// @return Zero on succes else negative | ||||
| 	/// | ||||
| 	virtual int open(); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief Get color order of device | ||||
| 	/// @return The color order | ||||
| 	/// | ||||
| 	const QString & getColorOrder() { return _colorOrder; }; | ||||
|  | ||||
| 	static int addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr); | ||||
| 	static const LedDeviceRegistry& getDeviceMap(); | ||||
| 	void setActiveDevice(QString dev); | ||||
| 	const QString & getActiveDevice() { return _activeDevice; }; | ||||
| 	static QJsonObject getLedDeviceSchemas(); | ||||
| 	void setLedCount(int ledCount); | ||||
| 	int  getLedCount() { return _ledCount; } | ||||
|  | ||||
| 	void setEnable(bool enable); | ||||
| 	bool enabled() { return _enabled; }; | ||||
| 	int getLatchTime() { return _latchTime_ms; }; | ||||
| 	const int getLatchTime() { return _latchTime_ms; }; | ||||
|  | ||||
| 	inline bool componentState() { return enabled(); }; | ||||
|  | ||||
| public slots: | ||||
| 	/// | ||||
| 	/// Is called on thread start, all construction tasks and init should run here | ||||
| 	/// | ||||
| 	virtual void start() { _deviceReady = 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) = 0; | ||||
|  | ||||
| signals: | ||||
| 	/// | ||||
| 	/// Emits whenever the led device switches between on/off | ||||
| @@ -83,16 +85,18 @@ signals: | ||||
| 	void enableStateChanged(bool newState); | ||||
|  | ||||
| protected: | ||||
| 	/// | ||||
| 	/// 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) = 0; | ||||
| 	virtual bool init(const QJsonObject &deviceConfig); | ||||
|  | ||||
| 	/// | ||||
| 	/// Opens and configures the output device | ||||
| 	/// | ||||
| 	/// @return Zero on succes else negative | ||||
| 	/// | ||||
| 	virtual int open(); | ||||
|  | ||||
| 	// Helper to pipe device config from constructor to start() | ||||
| 	QJsonObject _devConfig; | ||||
|  | ||||
| 	/// The common Logger instance for all LedDevices | ||||
| 	Logger * _log; | ||||
|  | ||||
| @@ -102,7 +106,6 @@ protected: | ||||
| 	bool _deviceReady; | ||||
|  | ||||
| 	QString _activeDevice; | ||||
| 	static LedDeviceRegistry _ledDeviceMap; | ||||
|  | ||||
| 	int _ledCount; | ||||
| 	int _ledRGBCount; | ||||
|   | ||||
							
								
								
									
										111
									
								
								include/leddevice/LedDeviceWrapper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								include/leddevice/LedDeviceWrapper.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| #pragma once | ||||
|  | ||||
| // util | ||||
| #include <utils/Logger.h> | ||||
| #include <utils/ColorRgb.h> | ||||
| #include <utils/Components.h> | ||||
|  | ||||
| class LedDevice; | ||||
| class Hyperion; | ||||
|  | ||||
| typedef LedDevice* ( *LedDeviceCreateFuncType ) ( const QJsonObject& ); | ||||
| typedef std::map<QString,LedDeviceCreateFuncType> LedDeviceRegistry; | ||||
|  | ||||
| /// | ||||
| /// @brief Creates and destroys LedDevice instances with LedDeviceFactory and moves the device to a thread. Pipes all signal/slots and methods to LedDevice instance | ||||
| /// | ||||
| class LedDeviceWrapper : public QObject | ||||
| { | ||||
| 	Q_OBJECT | ||||
| public: | ||||
| 	LedDeviceWrapper(Hyperion* hyperion); | ||||
| 	~LedDeviceWrapper(); | ||||
| 	/// | ||||
| 	/// @brief Contructs a new LedDevice, moves to thread and starts | ||||
| 	/// @param config  With the given config | ||||
| 	/// | ||||
| 	void createLedDevice(const QJsonObject& config); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief Get all available device schemas | ||||
| 	/// @return device schemas | ||||
| 	/// | ||||
| 	static const QJsonObject getLedDeviceSchemas(); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief add all device constrcutors to the map | ||||
| 	/// | ||||
| 	static int addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief Return all available device contructors | ||||
| 	/// @return device constrcutors | ||||
| 	/// | ||||
| 	static const LedDeviceRegistry& getDeviceMap(); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief Get the current latchtime of the ledDevice | ||||
| 	/// @ return latchtime in ms | ||||
| 	/// | ||||
| 	int getLatchTime(); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief Get the current active ledDevice | ||||
| 	/// | ||||
| 	const QString & getActiveDevice(); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief Return the last enable state | ||||
| 	/// | ||||
| 	const bool & enabled() { return _enabled; }; | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief Get the current colorOrder from device | ||||
| 	/// | ||||
| 	const QString & getColorOrder(); | ||||
|  | ||||
| public slots: | ||||
| 	/// | ||||
| 	/// @brief Handle new component state request | ||||
| 	/// @apram component  The comp from enum | ||||
| 	/// @param state      The new state | ||||
| 	/// | ||||
| 	void handleComponentState(const hyperion::Components component, const bool state); | ||||
|  | ||||
| signals: | ||||
| 	/// | ||||
| 	/// PIPER signal for Hyperion -> LedDevice | ||||
| 	/// | ||||
| 	/// @param[in] ledValues  The RGB-color per led | ||||
| 	/// | ||||
| 	/// @return Zero on success else negative | ||||
| 	/// | ||||
| 	int write(const std::vector<ColorRgb>& ledValues); | ||||
|  | ||||
| private slots: | ||||
| 	/// | ||||
| 	/// @brief Is called whenever the led device switches between on/off. The led device can disable it's component state | ||||
| 	/// The signal comes from the LedDevice | ||||
| 	/// @param newState The new state of the device | ||||
| 	/// | ||||
| 	void handleInternalEnableState(bool newState); | ||||
|  | ||||
|  | ||||
| protected: | ||||
| 	/// contains all available led device constrcutors | ||||
| 	static LedDeviceRegistry _ledDeviceMap; | ||||
|  | ||||
| private: | ||||
| 	/// | ||||
| 	/// @brief switchOff() the device and Stops the device thread | ||||
| 	///  | ||||
| 	void stopDeviceThread(); | ||||
|  | ||||
| private: | ||||
| 	// parent Hyperion | ||||
| 	Hyperion* _hyperion; | ||||
| 	// Pointer of current led device | ||||
| 	LedDevice* _ledDevice; | ||||
| 	// the enable state | ||||
| 	bool _enabled; | ||||
| }; | ||||
							
								
								
									
										41
									
								
								include/utils/GlobalSignals.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								include/utils/GlobalSignals.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| #pragma once | ||||
|  | ||||
| // util | ||||
| #include <utils/Image.h> | ||||
| #include <utils/ColorRgb.h> | ||||
|  | ||||
| // qt | ||||
| #include <QObject> | ||||
|  | ||||
| /// | ||||
| /// Singleton instance for simple signal sharing across threads, should be never used with Qt:DirectConnection! | ||||
| /// | ||||
| class GlobalSignals : public QObject | ||||
| { | ||||
| 	Q_OBJECT | ||||
| public: | ||||
|     static GlobalSignals* getInstance() | ||||
|     { | ||||
|         static GlobalSignals instance; | ||||
|         return & instance; | ||||
|     } | ||||
| private: | ||||
|     GlobalSignals() {} | ||||
|  | ||||
| public: | ||||
|     GlobalSignals(GlobalSignals const&)   = delete; | ||||
|     void operator=(GlobalSignals const&)  = delete; | ||||
|  | ||||
| signals: | ||||
| 	/// | ||||
| 	/// @brief PIPE SystemCapture images from GrabberWrapper to Hyperion class | ||||
| 	/// @param image  The prepared image | ||||
| 	/// | ||||
| 	void setSystemImage(const Image<ColorRgb>&  image); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief PIPE v4lCapture images from v4lCapture over HyperionDaemon to Hyperion class | ||||
| 	/// @param image  The prepared image | ||||
| 	/// | ||||
| 	void setV4lImage(const Image<ColorRgb> & image); | ||||
| }; | ||||
| @@ -22,7 +22,7 @@ | ||||
| #include <utils/SysInfo.h> | ||||
| #include <HyperionConfig.h> | ||||
| #include <utils/ColorSys.h> | ||||
| #include <leddevice/LedDevice.h> | ||||
| #include <leddevice/LedDeviceWrapper.h> | ||||
| #include <hyperion/GrabberWrapper.h> | ||||
| #include <utils/Process.h> | ||||
| #include <utils/JsonUtils.h> | ||||
| @@ -50,6 +50,8 @@ JsonAPI::JsonAPI(QString peerAddress, Logger* log, QObject* parent, bool noListe | ||||
| 	, _image_stream_timeout(0) | ||||
| 	, _led_stream_timeout(0) | ||||
| { | ||||
| 	Q_INIT_RESOURCE(JSONRPC_schemas); | ||||
|  | ||||
| 	// the JsonCB creates json messages you can subscribe to e.g. data change events; forward them to the parent client | ||||
| 	connect(_jsonCB, &JsonCB::newCallback, this, &JsonAPI::callbackMessage); | ||||
|  | ||||
| @@ -63,7 +65,6 @@ JsonAPI::JsonAPI(QString peerAddress, Logger* log, QObject* parent, bool noListe | ||||
| void JsonAPI::handleMessage(const QString& messageString) | ||||
| { | ||||
| 	const QString ident = "JsonRpc@"+_peerAddress; | ||||
| 	Q_INIT_RESOURCE(JSONRPC_schemas); | ||||
| 	QJsonObject message; | ||||
| 	// parse the message | ||||
| 	if(!JsonUtils::parse(ident, messageString, message, _log)) | ||||
| @@ -408,7 +409,7 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject& message, const QString& | ||||
| 	QJsonObject ledDevices; | ||||
| 	ledDevices["active"] = _hyperion->getActiveDevice(); | ||||
| 	QJsonArray availableLedDevices; | ||||
| 	for (auto dev: LedDevice::getDeviceMap()) | ||||
| 	for (auto dev: LedDeviceWrapper::getDeviceMap()) | ||||
| 	{ | ||||
| 		availableLedDevices.append(dev.first); | ||||
| 	} | ||||
| @@ -696,7 +697,7 @@ void JsonAPI::handleSchemaGetCommand(const QJsonObject& message, const QString& | ||||
|  | ||||
| 	// collect all LED Devices | ||||
| 	properties = schemaJson["properties"].toObject(); | ||||
| 	alldevices = LedDevice::getLedDeviceSchemas(); | ||||
| 	alldevices = LedDeviceWrapper::getLedDeviceSchemas(); | ||||
| 	properties.insert("alldevices", alldevices); | ||||
|  | ||||
| 	// collect all available effect schemas | ||||
|   | ||||
| @@ -1,6 +1,12 @@ | ||||
| #include <hyperion/CaptureCont.h> | ||||
|  | ||||
| // hyperion includes | ||||
| #include <hyperion/Hyperion.h> | ||||
|  | ||||
| // utils includes | ||||
| #include <utils/GlobalSignals.h> | ||||
|  | ||||
| // qt includes | ||||
| #include <QTimer> | ||||
|  | ||||
| CaptureCont::CaptureCont(Hyperion* hyperion) | ||||
| @@ -56,11 +62,11 @@ void CaptureCont::setSystemCaptureEnable(const bool& enable) | ||||
| 		if(enable) | ||||
| 		{ | ||||
| 			_hyperion->registerInput(_systemCaptPrio, hyperion::COMP_GRABBER); | ||||
| 			connect(_hyperion, &Hyperion::systemImage, this, &CaptureCont::handleSystemImage); | ||||
| 			connect(GlobalSignals::getInstance(), &GlobalSignals::setSystemImage, this, &CaptureCont::handleSystemImage); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			disconnect(_hyperion, &Hyperion::systemImage, this, &CaptureCont::handleSystemImage); | ||||
| 			disconnect(GlobalSignals::getInstance(), &GlobalSignals::setSystemImage, 0, 0); | ||||
| 			_hyperion->clear(_systemCaptPrio); | ||||
| 		} | ||||
| 		_systemCaptEnabled = enable; | ||||
| @@ -75,11 +81,11 @@ void CaptureCont::setV4LCaptureEnable(const bool& enable) | ||||
| 		if(enable) | ||||
| 		{ | ||||
| 			_hyperion->registerInput(_v4lCaptPrio, hyperion::COMP_V4L); | ||||
| 			connect(_hyperion, &Hyperion::v4lImage, this, &CaptureCont::handleV4lImage); | ||||
| 			connect(GlobalSignals::getInstance(), &GlobalSignals::setV4lImage, this, &CaptureCont::handleV4lImage); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			disconnect(_hyperion, &Hyperion::v4lImage, this, &CaptureCont::handleV4lImage); | ||||
| 			disconnect(GlobalSignals::getInstance(), &GlobalSignals::setV4lImage, 0, 0); | ||||
| 			_hyperion->clear(_v4lCaptPrio); | ||||
| 			_v4lInactiveTimer->stop(); | ||||
| 		} | ||||
|   | ||||
| @@ -3,6 +3,9 @@ | ||||
| #include <hyperion/Grabber.h> | ||||
| #include <HyperionConfig.h> | ||||
|  | ||||
| // utils includes | ||||
| #include <utils/GlobalSignals.h> | ||||
|  | ||||
| // qt | ||||
| #include <QTimer> | ||||
|  | ||||
| @@ -20,6 +23,11 @@ GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned | ||||
| 	_image.resize(width, height); | ||||
|  | ||||
| 	connect(_timer, &QTimer::timeout, this, &GrabberWrapper::action); | ||||
|  | ||||
| 	// connect the image forwarding | ||||
| 	_grabberName.startsWith("V4L") | ||||
| 		? connect(this, &GrabberWrapper::systemImage, GlobalSignals::getInstance(), &GlobalSignals::setV4lImage) | ||||
| 		: connect(this, &GrabberWrapper::systemImage, GlobalSignals::getInstance(), &GlobalSignals::setSystemImage); | ||||
| } | ||||
|  | ||||
| GrabberWrapper::~GrabberWrapper() | ||||
|   | ||||
| @@ -26,8 +26,7 @@ | ||||
| #include <utils/hyperion.h> | ||||
|  | ||||
| // Leddevice includes | ||||
| #include <leddevice/LedDevice.h> | ||||
| #include <leddevice/LedDeviceFactory.h> | ||||
| #include <leddevice/LedDeviceWrapper.h> | ||||
|  | ||||
| #include <hyperion/MultiColorAdjustment.h> | ||||
| #include "LinearColorSmoothing.h" | ||||
| @@ -127,22 +126,23 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString | ||||
| 	QJsonObject ledDevice = getSetting(settings::DEVICE).object(); | ||||
| 	ledDevice["currentLedCount"] = int(_hwLedCount); // Inject led count info | ||||
|  | ||||
| 	_device       = LedDeviceFactory::construct(ledDevice); | ||||
| 	_deviceSmooth = new LinearColorSmoothing(_device, getSetting(settings::SMOOTHING), this); | ||||
| 	_ledDeviceWrapper = new LedDeviceWrapper(this); | ||||
| 	connect(this, &Hyperion::componentStateChanged, _ledDeviceWrapper, &LedDeviceWrapper::handleComponentState); | ||||
| 	connect(this, &Hyperion::ledDeviceData, _ledDeviceWrapper, &LedDeviceWrapper::write); | ||||
| 	_ledDeviceWrapper->createLedDevice(ledDevice); | ||||
|  | ||||
| 	// smoothing | ||||
| 	_deviceSmooth = new LinearColorSmoothing(getSetting(settings::SMOOTHING), this); | ||||
| 	connect(this, &Hyperion::settingsChanged, _deviceSmooth, &LinearColorSmoothing::handleSettingsUpdate); | ||||
|  | ||||
| 	getComponentRegister().componentStateChanged(hyperion::COMP_LEDDEVICE, _device->componentState()); | ||||
|  | ||||
| 	// create the effect engine and pipe the updateEmit; must be initialized after smoothing! | ||||
| 	// create the effect engine; needs to be initialized after smoothing! | ||||
| 	_effectEngine = new EffectEngine(this); | ||||
| 	connect(_effectEngine, &EffectEngine::effectListUpdated, this, &Hyperion::effectListUpdated); | ||||
|  | ||||
| 	// setup config state checks and initial shot | ||||
| 	checkConfigState(); | ||||
| 	if(_fsWatcher.addPath(_configFile)) | ||||
| 	{ | ||||
| 		QObject::connect(&_fsWatcher, &QFileSystemWatcher::fileChanged, this, &Hyperion::checkConfigState); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		_cTimer = new QTimer(this); | ||||
| @@ -153,6 +153,7 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString | ||||
|  | ||||
| 	// initial startup effect | ||||
| 	hyperion::handleInitialEffect(this, getSetting(settings::FGEFFECT).object()); | ||||
|  | ||||
| 	// handle background effect | ||||
| 	_BGEffectHandler = new BGEffectHandler(this); | ||||
|  | ||||
| @@ -163,7 +164,6 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString | ||||
| 	update(); | ||||
|  | ||||
| 	// boblight, can't live in global scope as it depends on layout | ||||
|  | ||||
| 	_boblightServer = new BoblightServer(this, getSetting(settings::BOBLSERVER)); | ||||
| 	connect(this, &Hyperion::settingsChanged, _boblightServer, &BoblightServer::handleSettingsUpdate); | ||||
| } | ||||
| @@ -188,10 +188,10 @@ void Hyperion::freeObjects(bool emitCloseSignal) | ||||
| 	delete _captureCont; | ||||
| 	delete _effectEngine; | ||||
| 	//delete _deviceSmooth; | ||||
| 	delete _device; | ||||
| 	delete _raw2ledAdjustment; | ||||
| 	delete _messageForwarder; | ||||
| 	delete _settingsManager; | ||||
| 	delete _ledDeviceWrapper; | ||||
| } | ||||
|  | ||||
| void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config) | ||||
| @@ -241,7 +241,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum | ||||
| 		_hwLedCount = qMax(unsigned(getSetting(settings::DEVICE).object()["hardwareLedCount"].toInt(getLedCount())), getLedCount()); | ||||
|  | ||||
| 		// update led count in device | ||||
| 		_device->setLedCount(_hwLedCount); | ||||
| 		//_ledDeviceWrapper->setLedCount(_hwLedCount); | ||||
|  | ||||
| 		// change in leds are also reflected in adjustment | ||||
| 		delete _raw2ledAdjustment; | ||||
| @@ -262,7 +262,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum | ||||
| 		_hwLedCount = qMax(unsigned(dev["hardwareLedCount"].toInt(getLedCount())), getLedCount()); | ||||
|  | ||||
| 		// force ledString update, if device ByteOrder changed | ||||
| 		if(_device->getColorOrder() != dev["colorOrder"].toString("rgb")) | ||||
| 		if(_ledDeviceWrapper->getColorOrder() != dev["colorOrder"].toString("rgb")) | ||||
| 		{ | ||||
| 			_ledString = hyperion::createLedString(getSetting(settings::LEDS).array(), hyperion::createColorOrder(dev)); | ||||
| 			_ledStringClone = hyperion::createLedStringClone(getSetting(settings::LEDS).array(), hyperion::createColorOrder(dev)); | ||||
| @@ -276,16 +276,9 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum | ||||
| 		// update led count | ||||
| 		_device->setLedCount(_hwLedCount); | ||||
| 	*/ | ||||
| 		// do always reinit | ||||
| 		// TODO segfaulting in LinearColorSmoothing::queueColor triggert from QTimer because of device->setLEdValues (results from gdb debugging and testing) | ||||
| 		bool wasEnabled = _deviceSmooth->enabled(); | ||||
| 		_deviceSmooth->stopTimer(); | ||||
| 		delete _device; | ||||
| 		// do always reinit until the led devices can handle dynamic changes | ||||
| 		dev["currentLedCount"] = int(_hwLedCount); // Inject led count info | ||||
| 		_device = LedDeviceFactory::construct(dev); | ||||
| 		getComponentRegister().componentStateChanged(hyperion::COMP_LEDDEVICE, _device->componentState()); | ||||
| 		if(wasEnabled) | ||||
| 			_deviceSmooth->startTimerDelayed(); | ||||
| 		_ledDeviceWrapper->createLedDevice(dev); | ||||
| 		_lockUpdate = false; | ||||
| 	} | ||||
| 	// update once to push single color sets / adjustments/ ledlayout resizes and update ledBuffer color | ||||
| @@ -310,7 +303,7 @@ QString Hyperion::getConfigFileName() const | ||||
|  | ||||
| int Hyperion::getLatchTime() const | ||||
| { | ||||
|   return _device->getLatchTime(); | ||||
|   return _ledDeviceWrapper->getLatchTime(); | ||||
| } | ||||
|  | ||||
| unsigned Hyperion::addSmoothingConfig(int settlingTime_ms, double ledUpdateFrequency_hz, unsigned updateDelay) | ||||
| @@ -373,18 +366,14 @@ bool Hyperion::sourceAutoSelectEnabled() | ||||
| 	return _muxer.isSourceAutoSelectEnabled(); | ||||
| } | ||||
|  | ||||
| void Hyperion::setNewComponentState(const hyperion::Components& component, const bool& state) | ||||
| { | ||||
| 	_componentRegister.componentStateChanged(component, state); | ||||
| } | ||||
|  | ||||
| void Hyperion::setComponentState(const hyperion::Components component, const bool state) | ||||
| { | ||||
| 	switch (component) | ||||
| 	{ | ||||
| 		case hyperion::COMP_LEDDEVICE: | ||||
| 			_device->setEnable(state); | ||||
| 			getComponentRegister().componentStateChanged(hyperion::COMP_LEDDEVICE, _device->componentState()); | ||||
| 			break; | ||||
|  | ||||
| 		default: | ||||
| 			emit componentStateChanged(component, state); | ||||
| 	} | ||||
| 	emit componentStateChanged(component, state); | ||||
| } | ||||
|  | ||||
| void Hyperion::registerInput(const int priority, const hyperion::Components& component, const QString& origin, const QString& owner, unsigned smooth_cfg) | ||||
| @@ -571,7 +560,7 @@ const VideoMode & Hyperion::getCurrentVideoMode() | ||||
|  | ||||
| const QString & Hyperion::getActiveDevice() | ||||
| { | ||||
| 	return _device->getActiveDevice(); | ||||
| 	return _ledDeviceWrapper->getActiveDevice(); | ||||
| } | ||||
|  | ||||
| void Hyperion::updatedComponentState(const hyperion::Components comp, const bool state) | ||||
| @@ -681,7 +670,7 @@ void Hyperion::update() | ||||
| 	} | ||||
|  | ||||
| 	// Write the data to the device | ||||
| 	if (_device->enabled()) | ||||
| 	if (_ledDeviceWrapper->enabled()) | ||||
| 	{ | ||||
| 		_deviceSmooth->selectConfig(priorityInfo.smooth_cfg); | ||||
|  | ||||
| @@ -690,6 +679,6 @@ void Hyperion::update() | ||||
| 			_deviceSmooth->setLedValues(_ledBuffer); | ||||
|  | ||||
| 		if  (! _deviceSmooth->enabled()) | ||||
| 			_device->setLedValues(_ledBuffer); | ||||
| 			emit ledDeviceData(_ledBuffer); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -9,9 +9,8 @@ | ||||
|  | ||||
| using namespace hyperion; | ||||
|  | ||||
| LinearColorSmoothing::LinearColorSmoothing( LedDevice * ledDevice, const QJsonDocument& config, Hyperion* hyperion) | ||||
| 	: LedDevice() | ||||
| 	, _ledDevice(ledDevice) | ||||
| LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument& config, Hyperion* hyperion) | ||||
| 	: LedDevice(QJsonObject(), hyperion) | ||||
| 	, _log(Logger::getInstance("SMOOTHING")) | ||||
| 	, _hyperion(hyperion) | ||||
| 	, _updateInterval(1000) | ||||
| @@ -42,8 +41,7 @@ LinearColorSmoothing::LinearColorSmoothing( LedDevice * ledDevice, const QJsonDo | ||||
|  | ||||
| LinearColorSmoothing::~LinearColorSmoothing() | ||||
| { | ||||
| 	// Make sure to switch off the underlying led-device (because switchOff is no longer forwarded) | ||||
| 	_ledDevice->switchOff(); | ||||
|  | ||||
| } | ||||
|  | ||||
| void LinearColorSmoothing::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config) | ||||
| @@ -148,7 +146,8 @@ void LinearColorSmoothing::queueColors(const std::vector<ColorRgb> & ledColors) | ||||
| 	{ | ||||
| 		// No output delay => immediate write | ||||
| 		if ( _writeToLedsEnable && !_pause) | ||||
| 			_ledDevice->setLedValues(ledColors); | ||||
| 			emit _hyperion->ledDeviceData(ledColors); | ||||
|  | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| @@ -163,7 +162,7 @@ void LinearColorSmoothing::queueColors(const std::vector<ColorRgb> & ledColors) | ||||
| 			{ | ||||
| 				if (!_pause) | ||||
| 				{ | ||||
| 					_ledDevice->setLedValues(_outputQueue.front()); | ||||
| 					emit _hyperion->ledDeviceData(_outputQueue.front()); | ||||
| 				} | ||||
| 				_outputQueue.pop_front(); | ||||
| 			} | ||||
| @@ -235,18 +234,3 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, const bool& force) | ||||
| 	_currentConfigId = 0; | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| void LinearColorSmoothing::startTimerDelayed() | ||||
| { | ||||
| 	QTimer::singleShot(500, this, SLOT(delayStartTimer())); | ||||
| } | ||||
|  | ||||
| void LinearColorSmoothing::stopTimer() | ||||
| { | ||||
| 	_timer->stop(); | ||||
| } | ||||
|  | ||||
| void LinearColorSmoothing::delayStartTimer() | ||||
| { | ||||
| 	_timer->start(); | ||||
| } | ||||
|   | ||||
| @@ -28,11 +28,10 @@ class LinearColorSmoothing : public LedDevice | ||||
|  | ||||
| public: | ||||
| 	/// Constructor | ||||
| 	/// @param LedDevice the led device | ||||
| 	/// @param config    The configuration document smoothing | ||||
| 	/// @param hyperion  The hyperion parent instance | ||||
| 	/// | ||||
| 	LinearColorSmoothing(LedDevice *ledDevice, const QJsonDocument& config, Hyperion* hyperion); | ||||
| 	LinearColorSmoothing(const QJsonDocument& config, Hyperion* hyperion); | ||||
|  | ||||
| 	/// Destructor | ||||
| 	virtual ~LinearColorSmoothing(); | ||||
| @@ -71,12 +70,6 @@ public: | ||||
| 	/// | ||||
| 	bool selectConfig(unsigned cfg, const bool& force = false); | ||||
|  | ||||
| 	/// | ||||
| 	/// @ Helper methods to start the timer with delay (see delayStartSmooth()) | ||||
| 	/// | ||||
| 	void startTimerDelayed(); | ||||
| 	void stopTimer(); | ||||
|  | ||||
| public slots: | ||||
| 	/// | ||||
| 	/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor | ||||
| @@ -89,9 +82,6 @@ private slots: | ||||
| 	/// Timer callback which writes updated led values to the led device | ||||
| 	void updateLeds(); | ||||
|  | ||||
| 	/// Delay timer slot to workaround the leddevice reconstruction segfault (dangling pointer) | ||||
| 	void delayStartTimer(); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief Handle component state changes | ||||
| 	/// @param component   The component | ||||
| @@ -107,9 +97,6 @@ private: | ||||
| 	 */ | ||||
| 	void queueColors(const std::vector<ColorRgb> & ledColors); | ||||
|  | ||||
| 	/// The led device | ||||
| 	LedDevice * _ledDevice; | ||||
|  | ||||
| 	/// Logger instance | ||||
| 	Logger* _log; | ||||
|  | ||||
|   | ||||
| @@ -10,10 +10,9 @@ | ||||
| #include "hyperion/Hyperion.h" | ||||
| #include <utils/JsonUtils.h> | ||||
|  | ||||
| LedDeviceRegistry LedDevice::_ledDeviceMap = LedDeviceRegistry(); | ||||
|  | ||||
| LedDevice::LedDevice() | ||||
| 	: QObject() | ||||
| LedDevice::LedDevice(const QJsonObject& config, QObject* parent) | ||||
| 	: QObject(parent) | ||||
| 	, _devConfig(config) | ||||
| 	, _log(Logger::getInstance("LEDDEVICE")) | ||||
| 	, _ledBuffer(0) | ||||
| 	, _deviceReady(true) | ||||
| @@ -24,15 +23,16 @@ LedDevice::LedDevice() | ||||
| 	, _componentRegistered(false) | ||||
| 	, _enabled(true) | ||||
| { | ||||
| 	LedDevice::getLedDeviceSchemas(); | ||||
| 	qRegisterMetaType<hyperion::Components>("hyperion::Components"); | ||||
|  | ||||
| 	// setup timer | ||||
| 	_refresh_timer.setSingleShot(false); | ||||
| 	_refresh_timer.setInterval(0); | ||||
| 	connect(&_refresh_timer, SIGNAL(timeout()), this, SLOT(rewriteLeds())); | ||||
| } | ||||
|  | ||||
| LedDevice::~LedDevice() | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| // dummy implemention | ||||
| int LedDevice::open() | ||||
| { | ||||
| @@ -55,17 +55,6 @@ void LedDevice::setEnable(bool enable) | ||||
| 	_enabled = enable; | ||||
| } | ||||
|  | ||||
| int LedDevice::addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr) | ||||
| { | ||||
| 	_ledDeviceMap.emplace(name,funcPtr); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| const LedDeviceRegistry& LedDevice::getDeviceMap() | ||||
| { | ||||
| 	return _ledDeviceMap; | ||||
| } | ||||
|  | ||||
| void LedDevice::setActiveDevice(QString dev) | ||||
| { | ||||
| 	_activeDevice = dev; | ||||
| @@ -88,42 +77,6 @@ bool LedDevice::init(const QJsonObject &deviceConfig) | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| QJsonObject LedDevice::getLedDeviceSchemas() | ||||
| { | ||||
| 	// make sure the resources are loaded (they may be left out after static linking) | ||||
| 	Q_INIT_RESOURCE(LedDeviceSchemas); | ||||
|  | ||||
| 	// read the json schema from the resource | ||||
| 	QDir d(":/leddevices/"); | ||||
| 	QStringList l = d.entryList(); | ||||
| 	QJsonObject result, schemaJson; | ||||
|  | ||||
| 	for(QString &item : l) | ||||
| 	{ | ||||
| 		QString schemaPath(QString(":/leddevices/")+item); | ||||
| 		QString devName = item.remove("schema-"); | ||||
|  | ||||
| 		QString data; | ||||
| 		if(!FileUtils::readFile(schemaPath, data, Logger::getInstance("LedDevice"))) | ||||
| 		{ | ||||
| 			throw std::runtime_error("ERROR: Schema not found: " + item.toStdString()); | ||||
| 		} | ||||
|  | ||||
| 		QJsonObject schema; | ||||
| 		if(!JsonUtils::parse(schemaPath, data, schema, Logger::getInstance("LedDevice"))) | ||||
| 		{ | ||||
| 			throw std::runtime_error("ERROR: Json schema wrong of file: " + item.toStdString()); | ||||
| 		} | ||||
|  | ||||
| 		schemaJson = schema; | ||||
| 		schemaJson["title"] = QString("edt_dev_spec_header_title"); | ||||
|  | ||||
| 		result[devName] = schemaJson; | ||||
| 	} | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| int LedDevice::setLedValues(const std::vector<ColorRgb>& ledValues) | ||||
| { | ||||
| 	int retval = 0; | ||||
|   | ||||
| @@ -7,10 +7,11 @@ | ||||
|  | ||||
| // Leddevice includes | ||||
| #include <leddevice/LedDeviceFactory.h> | ||||
| #include <leddevice/LedDeviceWrapper.h> | ||||
| #include <utils/Logger.h> | ||||
| #include <leddevice/LedDevice.h> | ||||
|  | ||||
| // following file is auto generated by cmake! it contains all available leddevice headers | ||||
| // autogen | ||||
| #include "LedDevice_headers.h" | ||||
|  | ||||
| LedDevice * LedDeviceFactory::construct(const QJsonObject & deviceConfig) | ||||
| @@ -21,14 +22,7 @@ LedDevice * LedDeviceFactory::construct(const QJsonObject & deviceConfig) | ||||
|  | ||||
| 	QString type = deviceConfig["type"].toString("UNSPECIFIED").toLower(); | ||||
|  | ||||
| 	#define REGISTER(className) LedDevice::addToDeviceMap(QString(#className).toLower(), LedDevice##className::construct); | ||||
|  | ||||
| 	// the REGISTER() calls are autogenerated by cmake. | ||||
| 	#include "LedDevice_register.cpp" | ||||
|  | ||||
| 	#undef REGISTER | ||||
|  | ||||
| 	const LedDeviceRegistry& devList = LedDevice::getDeviceMap(); | ||||
| 	const LedDeviceRegistry& devList = LedDeviceWrapper::getDeviceMap(); | ||||
| 	LedDevice* device = nullptr; | ||||
| 	try | ||||
| 	{ | ||||
| @@ -56,7 +50,5 @@ LedDevice * LedDeviceFactory::construct(const QJsonObject & deviceConfig) | ||||
| 		device = LedDeviceFile::construct(QJsonObject()); | ||||
| 	} | ||||
|  | ||||
| 	device->open(); | ||||
|  | ||||
| 	return device; | ||||
| } | ||||
|   | ||||
							
								
								
									
										148
									
								
								libsrc/leddevice/LedDeviceWrapper.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								libsrc/leddevice/LedDeviceWrapper.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| #include <leddevice/LedDeviceWrapper.h> | ||||
|  | ||||
| #include <leddevice/LedDevice.h> | ||||
| #include <leddevice/LedDeviceFactory.h> | ||||
|  | ||||
| // following file is auto generated by cmake! it contains all available leddevice headers | ||||
| #include "LedDevice_headers.h" | ||||
|  | ||||
| // util | ||||
| #include <hyperion/Hyperion.h> | ||||
| #include <utils/JsonUtils.h> | ||||
|  | ||||
| // qt | ||||
| #include <QThread> | ||||
| #include <QDir> | ||||
|  | ||||
| LedDeviceRegistry LedDeviceWrapper::_ledDeviceMap = LedDeviceRegistry(); | ||||
|  | ||||
| LedDeviceWrapper::LedDeviceWrapper(Hyperion* hyperion) | ||||
| 	: QObject(hyperion) | ||||
| 	, _hyperion(hyperion) | ||||
| 	, _ledDevice(nullptr) | ||||
| { | ||||
| 	// prepare the device constrcutor map | ||||
| 	#define REGISTER(className) LedDeviceWrapper::addToDeviceMap(QString(#className).toLower(), LedDevice##className::construct); | ||||
|  | ||||
| 	// the REGISTER() calls are autogenerated by cmake. | ||||
| 	#include "LedDevice_register.cpp" | ||||
|  | ||||
| 	#undef REGISTER | ||||
|  | ||||
| 	_hyperion->setNewComponentState(hyperion::COMP_LEDDEVICE, true); | ||||
| } | ||||
|  | ||||
| LedDeviceWrapper::~LedDeviceWrapper() | ||||
| { | ||||
| 	stopDeviceThread(); | ||||
| } | ||||
|  | ||||
| void LedDeviceWrapper::createLedDevice(const QJsonObject& config) | ||||
| { | ||||
| 	if(_ledDevice != nullptr) | ||||
| 	 { | ||||
| 		 stopDeviceThread(); | ||||
| 	 } | ||||
|  | ||||
| 	 // create thread and device | ||||
| 	 QThread* thread = new QThread(this); | ||||
| 	 _ledDevice = LedDeviceFactory::construct(config); | ||||
| 	 _ledDevice->moveToThread(thread); | ||||
| 	 // setup thread management | ||||
| 	 connect(thread, &QThread::started, _ledDevice, &LedDevice::start); | ||||
| 	 connect(thread, &QThread::finished, thread, &QObject::deleteLater); | ||||
| 	 connect(thread, &QThread::finished, _ledDevice, &QObject::deleteLater); | ||||
|  | ||||
| 	 // further signals | ||||
| 	 connect(this, &LedDeviceWrapper::write, _ledDevice, &LedDevice::write); | ||||
| 	 connect(_ledDevice, &LedDevice::enableStateChanged, this, &LedDeviceWrapper::handleInternalEnableState); | ||||
|  | ||||
| 	 // start the thread | ||||
| 	 thread->start(); | ||||
| } | ||||
|  | ||||
| const QJsonObject LedDeviceWrapper::getLedDeviceSchemas() | ||||
| { | ||||
| 	// make sure the resources are loaded (they may be left out after static linking) | ||||
| 	Q_INIT_RESOURCE(LedDeviceSchemas); | ||||
|  | ||||
| 	// read the json schema from the resource | ||||
| 	QDir d(":/leddevices/"); | ||||
| 	QStringList l = d.entryList(); | ||||
| 	QJsonObject result, schemaJson; | ||||
|  | ||||
| 	for(QString &item : l) | ||||
| 	{ | ||||
| 		QString schemaPath(QString(":/leddevices/")+item); | ||||
| 		QString devName = item.remove("schema-"); | ||||
|  | ||||
| 		QString data; | ||||
| 		if(!FileUtils::readFile(schemaPath, data, Logger::getInstance("LedDevice"))) | ||||
| 		{ | ||||
| 			throw std::runtime_error("ERROR: Schema not found: " + item.toStdString()); | ||||
| 		} | ||||
|  | ||||
| 		QJsonObject schema; | ||||
| 		if(!JsonUtils::parse(schemaPath, data, schema, Logger::getInstance("LedDevice"))) | ||||
| 		{ | ||||
| 			throw std::runtime_error("ERROR: Json schema wrong of file: " + item.toStdString()); | ||||
| 		} | ||||
|  | ||||
| 		schemaJson = schema; | ||||
| 		schemaJson["title"] = QString("edt_dev_spec_header_title"); | ||||
|  | ||||
| 		result[devName] = schemaJson; | ||||
| 	} | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| int LedDeviceWrapper::addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr) | ||||
| { | ||||
| 	_ledDeviceMap.emplace(name,funcPtr); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| const LedDeviceRegistry& LedDeviceWrapper::getDeviceMap() | ||||
| { | ||||
| 	return _ledDeviceMap; | ||||
| } | ||||
|  | ||||
| int LedDeviceWrapper::getLatchTime() | ||||
| { | ||||
| 	return _ledDevice->getLatchTime(); | ||||
| } | ||||
|  | ||||
| const QString & LedDeviceWrapper::getActiveDevice() | ||||
| { | ||||
| 	return _ledDevice->getActiveDevice(); | ||||
| } | ||||
|  | ||||
| const QString & LedDeviceWrapper::getColorOrder() | ||||
| { | ||||
| 	return _ledDevice->getColorOrder(); | ||||
| } | ||||
|  | ||||
| void LedDeviceWrapper::handleComponentState(const hyperion::Components component, const bool state) | ||||
| { | ||||
| 	if(component == hyperion::COMP_LEDDEVICE) | ||||
| 	{ | ||||
| 		_ledDevice->setEnable(state); | ||||
| 		_hyperion->setNewComponentState(hyperion::COMP_LEDDEVICE, _ledDevice->componentState()); | ||||
| 		_enabled = state; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void LedDeviceWrapper::handleInternalEnableState(bool newState) | ||||
| { | ||||
| 	_hyperion->setNewComponentState(hyperion::COMP_LEDDEVICE, newState); | ||||
| 	_enabled = newState; | ||||
| } | ||||
|  | ||||
| void LedDeviceWrapper::stopDeviceThread() | ||||
| { | ||||
| 	_ledDevice->switchOff(); | ||||
| 	QThread* oldThread = _ledDevice->thread(); | ||||
| 	delete _ledDevice; // fast desctruction | ||||
| 	oldThread->quit(); // non blocking | ||||
| } | ||||
| @@ -201,7 +201,7 @@ void PhilipsHueBridge::resolveReply(QNetworkReply* reply) | ||||
|  | ||||
| void PhilipsHueBridge::post(QString route, QString content) | ||||
| { | ||||
| 	Debug(log, "Post %s: %s", QSTRING_CSTR(QString("http://IP/api/USR/%1").arg(route)), QSTRING_CSTR(content)); | ||||
| 	//Debug(log, "Post %s: %s", QSTRING_CSTR(QString("http://IP/api/USR/%1").arg(route)), QSTRING_CSTR(content)); | ||||
|  | ||||
| 	QNetworkRequest request(QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route)); | ||||
| 	manager.put(request, content.toLatin1()); | ||||
| @@ -214,7 +214,7 @@ const std::set<QString> PhilipsHueLight::GAMUT_B_MODEL_IDS = | ||||
| const std::set<QString> PhilipsHueLight::GAMUT_C_MODEL_IDS = | ||||
| { "LLC020", "LST002", "LCT011", "LCT012", "LCT010", "LCT014" }; | ||||
|  | ||||
| PhilipsHueLight::PhilipsHueLight(Logger* log, PhilipsHueBridge& bridge, unsigned int id, QJsonObject values) | ||||
| PhilipsHueLight::PhilipsHueLight(Logger* log, PhilipsHueBridge* bridge, unsigned int id, QJsonObject values) | ||||
| 	: log(log) | ||||
| 	, bridge(bridge) | ||||
| 	, id(id) | ||||
| @@ -297,7 +297,7 @@ PhilipsHueLight::~PhilipsHueLight() | ||||
|  | ||||
| void PhilipsHueLight::set(QString state) | ||||
| { | ||||
| 	bridge.post(QString("lights/%1/state").arg(id), state); | ||||
| 	bridge->post(QString("lights/%1/state").arg(id), state); | ||||
| } | ||||
|  | ||||
| void PhilipsHueLight::setOn(bool on) | ||||
| @@ -345,18 +345,25 @@ LedDevice* LedDevicePhilipsHue::construct(const QJsonObject &deviceConfig) | ||||
| } | ||||
|  | ||||
| LedDevicePhilipsHue::LedDevicePhilipsHue(const QJsonObject& deviceConfig) | ||||
| 	: LedDevice() | ||||
| 	, bridge(_log, deviceConfig["output"].toString(), deviceConfig["username"].toString()) | ||||
| 	: LedDevice(deviceConfig) | ||||
| 	, _bridge(nullptr) | ||||
| { | ||||
| 	_deviceReady = init(deviceConfig); | ||||
|  | ||||
| 	connect(&bridge, &PhilipsHueBridge::newLights, this, &LedDevicePhilipsHue::newLights); | ||||
| 	connect(this, &LedDevice::enableStateChanged, this, &LedDevicePhilipsHue::stateChanged); | ||||
| } | ||||
|  | ||||
| LedDevicePhilipsHue::~LedDevicePhilipsHue() | ||||
| { | ||||
| 	switchOff(); | ||||
| 	delete _bridge; | ||||
| } | ||||
|  | ||||
| void LedDevicePhilipsHue::start() | ||||
| { | ||||
| 	_bridge = new PhilipsHueBridge(_log, _devConfig["output"].toString(), _devConfig["username"].toString()); | ||||
| 	_deviceReady = init(_devConfig); | ||||
|  | ||||
| 	connect(_bridge, &PhilipsHueBridge::newLights, this, &LedDevicePhilipsHue::newLights); | ||||
| 	connect(this, &LedDevice::enableStateChanged, this, &LedDevicePhilipsHue::stateChanged); | ||||
| } | ||||
|  | ||||
| bool LedDevicePhilipsHue::init(const QJsonObject &deviceConfig) | ||||
| @@ -374,7 +381,7 @@ bool LedDevicePhilipsHue::init(const QJsonObject &deviceConfig) | ||||
| 			lightIds.push_back(i.toInt()); | ||||
| 		} | ||||
| 		// get light info from bridge | ||||
| 		bridge.bConnect(); | ||||
| 		_bridge->bConnect(); | ||||
|  | ||||
| 		// adapt latchTime to count of user lightIds (bridge 10Hz max overall) | ||||
| 		newDC.insert("latchTime",QJsonValue(100*(int)lightIds.size())); | ||||
| @@ -399,7 +406,7 @@ void LedDevicePhilipsHue::newLights(QMap<quint16, QJsonObject> map) | ||||
| 		{ | ||||
| 			if (map.contains(id)) | ||||
| 			{ | ||||
| 				lights.push_back(PhilipsHueLight(_log, bridge, id, map.value(id))); | ||||
| 				lights.push_back(PhilipsHueLight(_log, _bridge, id, map.value(id))); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| @@ -427,7 +434,6 @@ int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues) | ||||
| 	{ | ||||
| 		// Get color. | ||||
| 		ColorRgb color = ledValues.at(idx); | ||||
|  | ||||
| 		// Scale colors from [0, 255] to [0, 1] and convert to xy space. | ||||
| 		CiColor xy = CiColor::rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, | ||||
| 				light.getColorSpace()); | ||||
| @@ -453,7 +459,7 @@ int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues) | ||||
| void LedDevicePhilipsHue::stateChanged(bool newState) | ||||
| { | ||||
| 	if(newState) | ||||
| 		bridge.bConnect(); | ||||
| 		_bridge->bConnect(); | ||||
| 	else | ||||
| 		lights.clear(); | ||||
| } | ||||
|   | ||||
| @@ -139,7 +139,7 @@ class PhilipsHueLight | ||||
| { | ||||
| private: | ||||
| 	Logger* log; | ||||
| 	PhilipsHueBridge& bridge; | ||||
| 	PhilipsHueBridge* bridge; | ||||
| 	/// light id | ||||
| 	unsigned int id; | ||||
| 	bool on; | ||||
| @@ -172,7 +172,7 @@ public: | ||||
| 	/// @param bridge the bridge | ||||
| 	/// @param id the light id | ||||
| 	/// | ||||
| 	PhilipsHueLight(Logger* log, PhilipsHueBridge& bridge, unsigned int id, QJsonObject values); | ||||
| 	PhilipsHueLight(Logger* log, PhilipsHueBridge* bridge, unsigned int id, QJsonObject values); | ||||
| 	~PhilipsHueLight(); | ||||
|  | ||||
| 	/// | ||||
| @@ -227,6 +227,10 @@ public: | ||||
| 	/// constructs leddevice | ||||
| 	static LedDevice* construct(const QJsonObject &deviceConfig); | ||||
|  | ||||
| public slots: | ||||
| 	/// thread start | ||||
| 	virtual void start(); | ||||
|  | ||||
| private slots: | ||||
| 	/// creates new PhilipsHueLight(s) based on user lightid with bridge feedback | ||||
| 	/// | ||||
| @@ -249,7 +253,7 @@ protected: | ||||
|  | ||||
| private: | ||||
| 	/// bridge class | ||||
| 	PhilipsHueBridge bridge; | ||||
| 	PhilipsHueBridge* _bridge; | ||||
|  | ||||
| 	/// | ||||
| 	bool switchOffOnBlack; | ||||
|   | ||||
| @@ -40,7 +40,7 @@ bool LedDeviceTinkerforge::init(const QJsonObject &deviceConfig) | ||||
| 	_uid      = deviceConfig["uid"].toString(); | ||||
| 	_interval = deviceConfig["rate"].toInt(); | ||||
|  | ||||
| 	if ((unsigned)_ledCount > MAX_NUM_LEDS)  | ||||
| 	if ((unsigned)_ledCount > MAX_NUM_LEDS) | ||||
| 	{ | ||||
| 		Error(_log,"Invalid attempt to write led values. Not more than %d leds are allowed.", MAX_NUM_LEDS); | ||||
| 		return -1; | ||||
| @@ -68,7 +68,7 @@ int LedDeviceTinkerforge::open() | ||||
| 	if (_ipConnection != nullptr) | ||||
| 	{ | ||||
| 		Error(_log, "Attempt to open existing connection; close before opening"); | ||||
| 		return -1; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	// Initialise a new connection | ||||
| @@ -76,10 +76,10 @@ int LedDeviceTinkerforge::open() | ||||
| 	ipcon_create(_ipConnection); | ||||
|  | ||||
| 	int connectionStatus = ipcon_connect(_ipConnection, QSTRING_CSTR(_host), _port); | ||||
| 	if (connectionStatus < 0)  | ||||
| 	if (connectionStatus < 0) | ||||
| 	{ | ||||
| 		Warning(_log, "Attempt to connect to master brick (%s:%d) failed with status %d", QSTRING_CSTR(_host), _port, connectionStatus); | ||||
| 		return -1; | ||||
| 		Error(_log, "Attempt to connect to master brick (%s:%d) failed with status %d", QSTRING_CSTR(_host), _port, connectionStatus); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	// Create the 'LedStrip' | ||||
| @@ -87,17 +87,20 @@ int LedDeviceTinkerforge::open() | ||||
| 	led_strip_create(_ledStrip, QSTRING_CSTR(_uid), _ipConnection); | ||||
|  | ||||
| 	int frameStatus = led_strip_set_frame_duration(_ledStrip, _interval); | ||||
| 	if (frameStatus < 0)  | ||||
| 	if (frameStatus < 0) | ||||
| 	{ | ||||
| 		Error(_log,"Attempt to connect to led strip bricklet (led_strip_set_frame_duration()) failed with status %d", frameStatus); | ||||
| 		return -1; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| int LedDeviceTinkerforge::write(const std::vector<ColorRgb> &ledValues) | ||||
| { | ||||
| 	if(!_deviceReady) | ||||
| 		return 0; | ||||
|  | ||||
| 	auto redIt   = _redChannel.begin(); | ||||
| 	auto greenIt = _greenChannel.begin(); | ||||
| 	auto blueIt  = _blueChannel.begin(); | ||||
| @@ -115,7 +118,7 @@ int LedDeviceTinkerforge::write(const std::vector<ColorRgb> &ledValues) | ||||
| 	return transferLedData(_ledStrip, 0, _colorChannelSize, _redChannel.data(), _greenChannel.data(), _blueChannel.data()); | ||||
| } | ||||
|  | ||||
| int LedDeviceTinkerforge::transferLedData(LEDStrip *ledStrip, unsigned index, unsigned length, uint8_t *redChannel, uint8_t *greenChannel, uint8_t *blueChannel)  | ||||
| int LedDeviceTinkerforge::transferLedData(LEDStrip *ledStrip, unsigned index, unsigned length, uint8_t *redChannel, uint8_t *greenChannel, uint8_t *blueChannel) | ||||
| { | ||||
| 	if (length == 0 || index >= length || length > MAX_NUM_LEDS) | ||||
| 	{ | ||||
|   | ||||
| @@ -90,14 +90,13 @@ HyperionDaemon::HyperionDaemon(QString configFile, const QString rootPath, QObje | ||||
|  | ||||
| 	Info(_log, "Hyperion initialized"); | ||||
|  | ||||
| 	connect(_hyperion,SIGNAL(closing()),this,SLOT(freeObjects())); | ||||
| 	//connect(_hyperion,SIGNAL(closing()),this,SLOT(freeObjects())); for app restart refactor required | ||||
|  | ||||
| 	// listen for setting changes | ||||
| 	connect(_hyperion, &Hyperion::settingsChanged, this, &HyperionDaemon::settingsChanged); | ||||
| 	// listen for setting changes of framegrabber and v4l2 | ||||
| 	connect(this, &HyperionDaemon::settingsChanged, this, &HyperionDaemon::handleSettingsUpdate); | ||||
| 	// forward system and v4l images to Hyperion | ||||
| 	connect(this, &HyperionDaemon::systemImage, _hyperion, &Hyperion::systemImage); | ||||
| 	connect(this, &HyperionDaemon::v4lImage, _hyperion, &Hyperion::v4lImage); | ||||
|  | ||||
| 	// forward videoModes from Hyperion to Daemon evaluation | ||||
| 	connect(_hyperion, &Hyperion::videoMode, this, &HyperionDaemon::setVideoMode); | ||||
| 	// forward videoMode changes from Daemon to Hyperion | ||||
| @@ -107,6 +106,7 @@ HyperionDaemon::HyperionDaemon(QString configFile, const QString rootPath, QObje | ||||
| 	#if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX) && !defined(ENABLE_FB) && !defined(ENABLE_X11) && !defined(ENABLE_AMLOGIC) | ||||
| 		Warning(_log, "No platform capture can be instantiated, because all grabbers have been left out from the build"); | ||||
| 	#endif | ||||
|  | ||||
| 	// init system capture (framegrabber) | ||||
| 	handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE)); | ||||
| 	// init v4l2 capture | ||||
| @@ -379,7 +379,6 @@ void HyperionDaemon::handleSettingsUpdate(const settings::type& type, const QJso | ||||
| 			Debug(_log, "V4L2 grabber created"); | ||||
|  | ||||
| 			// connect to HyperionDaemon signal | ||||
| 			connect(grabber, &V4L2Wrapper::systemImage, this, &HyperionDaemon::v4lImage); | ||||
| 			connect(this, &HyperionDaemon::videoMode, grabber, &V4L2Wrapper::setVideoMode); | ||||
| 			connect(this, &HyperionDaemon::settingsChanged, grabber, &V4L2Wrapper::handleSettingsUpdate); | ||||
|  | ||||
| @@ -399,7 +398,6 @@ void HyperionDaemon::createGrabberDispmanx() | ||||
|  | ||||
| 	// connect to HyperionDaemon signal | ||||
| 	connect(this, &HyperionDaemon::videoMode, _dispmanx, &DispmanxWrapper::setVideoMode); | ||||
| 	connect(_dispmanx, &DispmanxWrapper::systemImage, this, &HyperionDaemon::systemImage); | ||||
| 	connect(this, &HyperionDaemon::settingsChanged, _dispmanx, &DispmanxWrapper::handleSettingsUpdate); | ||||
|  | ||||
| 	_dispmanx->start(); | ||||
| @@ -419,7 +417,6 @@ void HyperionDaemon::createGrabberAmlogic() | ||||
|  | ||||
| 	// connect to HyperionDaemon signal | ||||
| 	connect(this, &HyperionDaemon::videoMode, _amlGrabber, &AmlogicWrapper::setVideoMode); | ||||
| 	connect(_amlGrabber, &AmlogicWrapper::systemImage, this, &HyperionDaemon::systemImage); | ||||
| 	connect(this, &HyperionDaemon::settingsChanged, _amlGrabber, &AmlogicWrapper::handleSettingsUpdate); | ||||
|  | ||||
| 	_amlGrabber->start(); | ||||
| @@ -440,7 +437,6 @@ void HyperionDaemon::createGrabberX11(const QJsonObject & grabberConfig) | ||||
|  | ||||
| 	// connect to HyperionDaemon signal | ||||
| 	connect(this, &HyperionDaemon::videoMode, _x11Grabber, &X11Wrapper::setVideoMode); | ||||
| 	connect(_x11Grabber, &X11Wrapper::systemImage, this, &HyperionDaemon::systemImage); | ||||
| 	connect(this, &HyperionDaemon::settingsChanged, _x11Grabber, &X11Wrapper::handleSettingsUpdate); | ||||
|  | ||||
| 	_x11Grabber->start(); | ||||
| @@ -461,7 +457,6 @@ void HyperionDaemon::createGrabberFramebuffer(const QJsonObject & grabberConfig) | ||||
| 	_fbGrabber->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom); | ||||
| 	// connect to HyperionDaemon signal | ||||
| 	connect(this, &HyperionDaemon::videoMode, _fbGrabber, &FramebufferWrapper::setVideoMode); | ||||
| 	connect(_fbGrabber, &FramebufferWrapper::systemImage, this, &HyperionDaemon::systemImage); | ||||
| 	connect(this, &HyperionDaemon::settingsChanged, _fbGrabber, &FramebufferWrapper::handleSettingsUpdate); | ||||
|  | ||||
| 	_fbGrabber->start(); | ||||
| @@ -482,7 +477,6 @@ void HyperionDaemon::createGrabberOsx(const QJsonObject & grabberConfig) | ||||
|  | ||||
| 	// connect to HyperionDaemon signal | ||||
| 	connect(this, &HyperionDaemon::videoMode, _osxGrabber, &OsxWrapper::setVideoMode); | ||||
| 	connect(_osxGrabber, &OsxWrapper::systemImage, this, &HyperionDaemon::systemImage); | ||||
| 	connect(this, &HyperionDaemon::settingsChanged, _osxGrabber, &OsxWrapper::handleSettingsUpdate); | ||||
|  | ||||
| 	_osxGrabber->start(); | ||||
|   | ||||
| @@ -97,16 +97,6 @@ signals: | ||||
| 	/// | ||||
| 	void settingsChanged(const settings::type& type, const QJsonDocument& data); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief PIPE SystemCapture images from SystemCapture over HyperionDaemon to Hyperion class | ||||
| 	/// | ||||
| 	void systemImage(const Image<ColorRgb>&  image); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief PIPE v4lCapture images from v4lCapture over HyperionDaemon to Hyperion class | ||||
| 	/// | ||||
| 	void v4lImage(const Image<ColorRgb> & image); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief After eval of setVideoMode this signal emits with a new one on change | ||||
| 	/// | ||||
|   | ||||
		Reference in New Issue
	
	Block a user