mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	Refactor event handling incl.CEC
This commit is contained in:
		@@ -192,8 +192,8 @@
 | 
			
		||||
    "conf_network_tok_intro": "Here you can create and delete tokens for API authentication. Created tokens will only be displayed once.",
 | 
			
		||||
    "conf_network_tok_lastuse": "Last use",
 | 
			
		||||
    "conf_network_tok_title": "Token Management",
 | 
			
		||||
    "conf_system_events_heading_title": "System Events",
 | 
			
		||||
    "conf_system_events_intro": "Settings related to diffent Operating System events Hyperion can handle",
 | 
			
		||||
    "conf_os_events_heading_title": "Operating System Events",
 | 
			
		||||
    "conf_os_events_intro": "Settings related to diffent Operating System events Hyperion can handle",
 | 
			
		||||
    "conf_webconfig_label_intro": "Webconfiguration settings. Edit wisely.",
 | 
			
		||||
    "dashboard_active_instance": "Selected instance",
 | 
			
		||||
    "dashboard_alert_message_confedit": "Your Hyperion configuration has been modified. To apply it, restart Hyperion.",
 | 
			
		||||
@@ -457,6 +457,12 @@
 | 
			
		||||
    "edt_conf_net_localApiAuth_title": "Local API Authentication",
 | 
			
		||||
    "edt_conf_net_restirctedInternetAccessAPI_expl": "You can restrict the access to the API through the internet to certain IP's.",
 | 
			
		||||
    "edt_conf_net_restirctedInternetAccessAPI_title": "Restrict to IP's",
 | 
			
		||||
    "edt_conf_os_events_lockEnable_title": "Listen to lock events",
 | 
			
		||||
    "edt_conf_os_events_lockEnable_expl": "Listen to screen lock/unlock events",
 | 
			
		||||
    "edt_conf_os_events_suspendEnable_title": "Listen to suspend events",
 | 
			
		||||
    "edt_conf_os_events_suspendEnable_expl": "Listen to operating system suspend/resume events",
 | 
			
		||||
    "edt_conf_os_events_suspendOnLockEnable_title": "Suspend when locked",
 | 
			
		||||
    "edt_conf_os_events_suspendOnLockEnable_expl": "Suspend when the screen is locked, otherwise go into idle mode",
 | 
			
		||||
    "edt_conf_pbs_heading_title": "Protocol Buffers Server",
 | 
			
		||||
    "edt_conf_pbs_timeout_expl": "If no data are received for the given period, the component will be (soft) disabled.",
 | 
			
		||||
    "edt_conf_pbs_timeout_title": "Timeout",
 | 
			
		||||
@@ -477,12 +483,6 @@
 | 
			
		||||
    "edt_conf_smooth_updateDelay_title": "Output delay",
 | 
			
		||||
    "edt_conf_smooth_updateFrequency_expl": "The output speed to your LED controller.",
 | 
			
		||||
    "edt_conf_smooth_updateFrequency_title": "Update frequency",
 | 
			
		||||
    "edt_conf_system_events_lockEnable_title": "Listen to lock events",
 | 
			
		||||
    "edt_conf_system_events_lockEnable_expl": "Listen to screen lock/unlock events",
 | 
			
		||||
    "edt_conf_system_events_suspendEnable_title": "Listen to suspend events",
 | 
			
		||||
    "edt_conf_system_events_suspendEnable_expl": "Listen to system suspend/resume events",
 | 
			
		||||
    "edt_conf_system_events_suspendOnLockEnable_title": "Suspend when locked",
 | 
			
		||||
    "edt_conf_system_events_suspendOnLockEnable_expl": "Suspend when the screen is locked, otherwise go into idle mode",
 | 
			
		||||
    "edt_conf_v4l2_blueSignalThreshold_expl": "Darkens low blue values (recognized as black)",
 | 
			
		||||
    "edt_conf_v4l2_blueSignalThreshold_title": "Blue signal threshold",
 | 
			
		||||
    "edt_conf_v4l2_cecDetection_expl": "If enabled, USB capture will be temporarily disabled when CEC standby event received from HDMI bus.",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,35 +1,75 @@
 | 
			
		||||
$(document).ready(function () {
 | 
			
		||||
  performTranslation();
 | 
			
		||||
 | 
			
		||||
  var conf_editor_systemEvents = null;
 | 
			
		||||
  var CEC_ENABLED = (jQuery.inArray("cec", window.serverInfo.services) !== -1);
 | 
			
		||||
 | 
			
		||||
  var conf_editor_osEvents = null;
 | 
			
		||||
  var conf_editor_cecEvents = null;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  if (window.showOptHelp) {
 | 
			
		||||
    //System Events
 | 
			
		||||
    $('#conf_cont').append(createRow('conf_cont_system_events'));
 | 
			
		||||
    $('#conf_cont_system_events').append(createOptPanel('fa-laptop', $.i18n("conf_system_events_heading_title"), 'editor_container_system_events', 'btn_submit_system_events', 'panel-system'));
 | 
			
		||||
    $('#conf_cont_system_events').append(createHelpTable(window.schema.systemEvents.properties, $.i18n("conf_system_events_heading_title")));
 | 
			
		||||
    //Operating System Events
 | 
			
		||||
    $('#conf_cont').append(createRow('conf_cont_os_events'));
 | 
			
		||||
    $('#conf_cont_os_events').append(createOptPanel('fa-laptop', $.i18n("conf_os_events_heading_title"), 'editor_container_os_events', 'btn_submit_os_events', 'panel-system'));
 | 
			
		||||
    $('#conf_cont_os_events').append(createHelpTable(window.schema.osEvents.properties, $.i18n("conf_os_events_heading_title")));
 | 
			
		||||
 | 
			
		||||
    //CEC Events
 | 
			
		||||
    if (CEC_ENABLED) {
 | 
			
		||||
      $('#conf_cont').append(createRow('conf_cont_event_cec'));
 | 
			
		||||
      $('#conf_cont_event_cec').append(createOptPanel('fa-tv', $.i18n("conf_cec_events_heading_title"), 'editor_container_cec_events', 'btn_submit_cec_events', 'panel-system'));
 | 
			
		||||
      $('#conf_cont_event_cec').append(createHelpTable(window.schema.cecEvents.properties, $.i18n("conf_cec_events_heading_title"), "cecEventsHelpPanelId"));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    $('#conf_cont').addClass('row');
 | 
			
		||||
    $('#conf_cont').append(createOptPanel('fa-laptop', $.i18n("conf_system_events_heading_title"), 'editor_container_system_events', 'btn_submit_system_events'));
 | 
			
		||||
    $('#conf_cont').append(createOptPanel('fa-laptop', $.i18n("conf_os_events_heading_title"), 'editor_container_os_events', 'btn_submit_os_events'));
 | 
			
		||||
    if (CEC_ENABLED) {
 | 
			
		||||
      $('#conf_cont').append(createOptPanel('fa-tv', $.i18n("conf_cec_events_heading_title"), 'editor_container_cec_events', 'btn_submit_cec_events'));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //System Events
 | 
			
		||||
  conf_editor_systemEvents = createJsonEditor('editor_container_system_events', {
 | 
			
		||||
    systemEvents: window.schema.systemEvents
 | 
			
		||||
  //Operating System Events
 | 
			
		||||
  conf_editor_osEvents = createJsonEditor('editor_container_os_events', {
 | 
			
		||||
    osEvents: window.schema.osEvents
 | 
			
		||||
  }, true, true);
 | 
			
		||||
 | 
			
		||||
  conf_editor_systemEvents.on('change', function () {
 | 
			
		||||
    conf_editor_systemEvents.validate().length || window.readOnlyMode ? $('#btn_submit_system_events').prop('disabled', true) : $('#btn_submit_system_events').prop('disabled', false);
 | 
			
		||||
  conf_editor_osEvents.on('change', function () {
 | 
			
		||||
    conf_editor_osEvents.validate().length || window.readOnlyMode ? $('#btn_submit_os_events').prop('disabled', true) : $('#btn_submit_os_events').prop('disabled', false);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  $('#btn_submit_system_events').off().on('click', function () {
 | 
			
		||||
    requestWriteConfig(conf_editor_systemEvents.getValue());
 | 
			
		||||
  $('#btn_submit_os_events').off().on('click', function () {
 | 
			
		||||
    requestWriteConfig(conf_editor_osEvents.getValue());
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  //CEC Events
 | 
			
		||||
  if (CEC_ENABLED) {
 | 
			
		||||
    conf_editor_cecEvents = createJsonEditor('editor_container_cec_events', {
 | 
			
		||||
      cecEvents: window.schema.cecEvents
 | 
			
		||||
    }, true, true);
 | 
			
		||||
 | 
			
		||||
    conf_editor_cecEvents.on('change', function () {
 | 
			
		||||
      var cecEventsEnable = conf_editor_cecEvents.getEditor("root.cecEvents.enable").getValue();
 | 
			
		||||
      if (cecEventsEnable) {
 | 
			
		||||
        showInputOptionsForKey(conf_editor_cecEvents, "cecEvents", "enable", true);
 | 
			
		||||
        $('#cecEventsHelpPanelId').show();
 | 
			
		||||
      } else {
 | 
			
		||||
        showInputOptionsForKey(conf_editor_cecEvents, "cecEvents", "enable", false);
 | 
			
		||||
        $('#cecEventsHelpPanelId').hide();
 | 
			
		||||
      }
 | 
			
		||||
      conf_editor_cecEvents.validate().length || window.readOnlyMode ? $('#btn_submit_cec_events').prop('disabled', true) : $('#btn_submit_cec_events').prop('disabled', false);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('#btn_submit_cec_events').off().on('click', function () {
 | 
			
		||||
      requestWriteConfig(conf_editor_cecEvents.getValue());
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //create introduction
 | 
			
		||||
  if (window.showOptHelp) {
 | 
			
		||||
    createHint("intro", $.i18n('conf_system_events_intro'), "editor_container_system_events");
 | 
			
		||||
    createHint("intro", $.i18n('conf_os_events_intro'), "editor_container_os_events");
 | 
			
		||||
    if (CEC_ENABLED) {
 | 
			
		||||
      createHint("intro", $.i18n('conf_cec_events_intro'), "editor_container_cec_events");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  removeOverlay();
 | 
			
		||||
 
 | 
			
		||||
@@ -231,26 +231,34 @@ macro(DeployLinux TARGET)
 | 
			
		||||
				if (EXISTS ${QT_PLUGINS_DIR}/${PLUGIN})
 | 
			
		||||
					file(GLOB files "${QT_PLUGINS_DIR}/${PLUGIN}/*.so")
 | 
			
		||||
					foreach(file ${files})
 | 
			
		||||
						get_prerequisites(${file} PLUGINS 0 1 "" "")
 | 
			
		||||
						foreach(DEPENDENCY ${PLUGINS})
 | 
			
		||||
							get_filename_component(resolved ${DEPENDENCY} NAME_WE)
 | 
			
		||||
							list(FIND SYSTEM_LIBS_SKIP ${resolved} _index)
 | 
			
		||||
							if (${_index} GREATER -1)
 | 
			
		||||
								continue() # Skip system libraries
 | 
			
		||||
							else()
 | 
			
		||||
								gp_resolve_item("${file}" "${DEPENDENCY}" "" "" resolved_file)
 | 
			
		||||
								get_filename_component(resolved_file ${resolved_file} ABSOLUTE)
 | 
			
		||||
								gp_append_unique(PREREQUISITE_LIBS ${resolved_file})
 | 
			
		||||
								get_filename_component(file_canonical ${resolved_file} REALPATH)
 | 
			
		||||
								gp_append_unique(PREREQUISITE_LIBS ${file_canonical})
 | 
			
		||||
							endif()
 | 
			
		||||
						endforeach()
 | 
			
		||||
 | 
			
		||||
						install(
 | 
			
		||||
							FILES ${file}
 | 
			
		||||
							DESTINATION "share/hyperion/lib/${PLUGIN}"
 | 
			
		||||
							COMPONENT "Hyperion"
 | 
			
		||||
						)
 | 
			
		||||
						if ("${file}" STREQUAL "libqsqlmimer.so")
 | 
			
		||||
							continue()
 | 
			
		||||
						else()
 | 
			
		||||
							get_prerequisites(${file} PLUGINS 0 1 "" "")
 | 
			
		||||
							foreach(DEPENDENCY ${PLUGINS})
 | 
			
		||||
								get_filename_component(resolved ${DEPENDENCY} NAME_WE)
 | 
			
		||||
								list(FIND SYSTEM_LIBS_SKIP ${resolved} _index)
 | 
			
		||||
								if (${_index} GREATER -1)
 | 
			
		||||
									continue() # Skip system libraries
 | 
			
		||||
								else()
 | 
			
		||||
									gp_resolve_item("${file}" "${DEPENDENCY}" "" "" resolved_file)
 | 
			
		||||
									get_filename_component(resolved_file ${resolved_file} ABSOLUTE)
 | 
			
		||||
									gp_append_unique(PREREQUISITE_LIBS ${resolved_file})
 | 
			
		||||
									get_filename_component(file_canonical ${resolved_file} REALPATH)
 | 
			
		||||
									gp_append_unique(PREREQUISITE_LIBS ${file_canonical})
 | 
			
		||||
								endif()
 | 
			
		||||
							endforeach()
 | 
			
		||||
						endif()	
 | 
			
		||||
						if ("${file}" STREQUAL "libqsqlmimer.so")
 | 
			
		||||
							continue()
 | 
			
		||||
						else()
 | 
			
		||||
							install(
 | 
			
		||||
								FILES ${file}
 | 
			
		||||
								DESTINATION "share/hyperion/lib/${PLUGIN}"
 | 
			
		||||
								COMPONENT "Hyperion"
 | 
			
		||||
							)
 | 
			
		||||
						endif()
 | 
			
		||||
						
 | 
			
		||||
					endforeach()
 | 
			
		||||
				endif()
 | 
			
		||||
			endforeach()
 | 
			
		||||
 
 | 
			
		||||
@@ -250,8 +250,12 @@
 | 
			
		||||
		}
 | 
			
		||||
	],
 | 
			
		||||
	
 | 
			
		||||
	"systemEvents": {
 | 
			
		||||
	"osEvents": {
 | 
			
		||||
		"suspendEnable": true,
 | 
			
		||||
		"lockEnable": true
 | 
			
		||||
	}
 | 
			
		||||
	},
 | 
			
		||||
	
 | 
			
		||||
	"cecEvents": {
 | 
			
		||||
		"enable": false
 | 
			
		||||
	}	
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								help/db/hyperion.db
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								help/db/hyperion.db
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
// parent class
 | 
			
		||||
#include <api/API.h>
 | 
			
		||||
#include <events/Event.h>
 | 
			
		||||
 | 
			
		||||
// hyperion includes
 | 
			
		||||
#include <utils/Components.h>
 | 
			
		||||
@@ -105,24 +106,9 @@ signals:
 | 
			
		||||
	void forwardJsonMessage(QJsonObject);
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// Signal emits whenever a suspend/resume request for all instances should be forwarded
 | 
			
		||||
	/// Signal emits whenever a hyperion event request for all instances should be forwarded
 | 
			
		||||
	///
 | 
			
		||||
	void suspendAll(bool isSuspend);
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// Signal emits whenever a toggle suspend/resume request for all instances should be forwarded
 | 
			
		||||
	///
 | 
			
		||||
	void toggleSuspendAll();
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// Signal emits whenever a idle mode request for all instances should be forwarded
 | 
			
		||||
	///
 | 
			
		||||
	void idleAll(bool isIdle);
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// Signal emits whenever a toggle idle/working mode request for all instances should be forwarded
 | 
			
		||||
	///
 | 
			
		||||
	void toggleIdleAll();
 | 
			
		||||
	void signalEvent(Event event);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	// true if further callbacks are forbidden (http)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
enum class CECEvent
 | 
			
		||||
{
 | 
			
		||||
        On,
 | 
			
		||||
        Off
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -7,7 +7,10 @@
 | 
			
		||||
 | 
			
		||||
#include <libcec/cec.h>
 | 
			
		||||
 | 
			
		||||
#include <cec/CECEvent.h>
 | 
			
		||||
#include <utils/settings.h>
 | 
			
		||||
 | 
			
		||||
//#include <cec/CECEvent.h>
 | 
			
		||||
#include <events/Event.h>
 | 
			
		||||
 | 
			
		||||
using CECCallbacks         = CEC::ICECCallbacks;
 | 
			
		||||
using CECAdapter           = CEC::ICECAdapter;
 | 
			
		||||
@@ -39,8 +42,12 @@ public slots:
 | 
			
		||||
	bool start();
 | 
			
		||||
	void stop();
 | 
			
		||||
 | 
			
		||||
	virtual void handleSettingsUpdate(settings::type type, const QJsonDocument& config);
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
	void cecEvent(CECEvent event);
 | 
			
		||||
	//void cecEvent(CECEvent event);
 | 
			
		||||
 | 
			
		||||
	void signalEvent(Event event);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	/* CEC Callbacks */
 | 
			
		||||
@@ -65,5 +72,7 @@ private:
 | 
			
		||||
	CECCallbacks _cecCallbacks {};
 | 
			
		||||
	CECConfig    _cecConfig    {};
 | 
			
		||||
 | 
			
		||||
	bool _isEnabled;
 | 
			
		||||
 | 
			
		||||
	Logger * _logger {};
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -113,7 +113,7 @@ public:
 | 
			
		||||
		// capture
 | 
			
		||||
		<< "framegrabber" << "grabberV4L2" << "grabberAudio"
 | 
			
		||||
		//Events
 | 
			
		||||
		<< "systemEvents"
 | 
			
		||||
		 << "osEvents" << "cecEvents"
 | 
			
		||||
		// other
 | 
			
		||||
		<< "logger" << "general";
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								include/events/Event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								include/events/Event.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
#ifndef EVENT_H
 | 
			
		||||
#define EVENT_H
 | 
			
		||||
 | 
			
		||||
enum class Event
 | 
			
		||||
{
 | 
			
		||||
	Suspend,
 | 
			
		||||
	Resume,
 | 
			
		||||
	ToggleSuspend,
 | 
			
		||||
	Idle,
 | 
			
		||||
	ResumeIdle,
 | 
			
		||||
	ToggleIdle,
 | 
			
		||||
	Reload,
 | 
			
		||||
	Restart
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline const char* eventToString(Event event)
 | 
			
		||||
{
 | 
			
		||||
	switch (event)
 | 
			
		||||
	{
 | 
			
		||||
	case Event::Suspend:       return "Suspend";
 | 
			
		||||
	case Event::Resume:        return "Resume";
 | 
			
		||||
	case Event::ToggleSuspend: return "ToggleSuspend detector";
 | 
			
		||||
	case Event::Idle:          return "Idle";
 | 
			
		||||
	case Event::ResumeIdle:    return "ResumeIdle";
 | 
			
		||||
	case Event::ToggleIdle:    return "ToggleIdle";
 | 
			
		||||
	case Event::Reload:        return "Reload";
 | 
			
		||||
	case Event::Restart:       return "Restart";
 | 
			
		||||
	default:                   return "Unknown";
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // EVENT_H
 | 
			
		||||
							
								
								
									
										54
									
								
								include/events/EventHandler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								include/events/EventHandler.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
#ifndef EVENTHANDLER_H
 | 
			
		||||
#define EVENTHANDLER_H
 | 
			
		||||
 | 
			
		||||
#include <utils/settings.h>
 | 
			
		||||
#include <events/Event.h>
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
 | 
			
		||||
class Logger;
 | 
			
		||||
 | 
			
		||||
class EventHandler : public QObject {
 | 
			
		||||
	Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
	EventHandler();
 | 
			
		||||
	~EventHandler() override;
 | 
			
		||||
 | 
			
		||||
	static EventHandler* getInstance();
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
 | 
			
		||||
	virtual void handleSettingsUpdate(settings::type type, const QJsonDocument& config);
 | 
			
		||||
 | 
			
		||||
	void suspend(bool sleep);
 | 
			
		||||
 | 
			
		||||
	void suspend();
 | 
			
		||||
	void resume();
 | 
			
		||||
	void toggleSuspend();
 | 
			
		||||
 | 
			
		||||
	void idle(bool isIdle);
 | 
			
		||||
	void idle();
 | 
			
		||||
	void resumeIdle();
 | 
			
		||||
	void toggleIdle();
 | 
			
		||||
 | 
			
		||||
	void handleEvent(Event event);
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
 | 
			
		||||
	void signalEvent(Event event);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
	Logger * _log {};
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
	bool _isSuspended;
 | 
			
		||||
	bool _isIdle;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // EVENTHANDLER_H
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										116
									
								
								include/events/OsEventHandler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								include/events/OsEventHandler.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
#ifndef OsEventHandler_H
 | 
			
		||||
#define OsEventHandler_H
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QJsonDocument>
 | 
			
		||||
 | 
			
		||||
#include <events/Event.h>
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
#include <QAbstractNativeEventFilter>
 | 
			
		||||
#include <QAbstractEventDispatcher>
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <utils/settings.h>
 | 
			
		||||
 | 
			
		||||
class Logger;
 | 
			
		||||
 | 
			
		||||
class OsEventHandlerBase : public QObject {
 | 
			
		||||
	Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	OsEventHandlerBase();
 | 
			
		||||
	~OsEventHandlerBase() override;
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
 | 
			
		||||
	void suspend(bool sleep);
 | 
			
		||||
	void lock(bool isLocked);
 | 
			
		||||
 | 
			
		||||
	virtual void handleSettingsUpdate(settings::type type, const QJsonDocument& config);
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
 | 
			
		||||
	void signalEvent(Event event);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
	virtual bool registerOsEventHandler() { return true; }
 | 
			
		||||
	virtual void unregisterOsEventHandler() {}
 | 
			
		||||
	virtual bool registerLockHandler() { return true; }
 | 
			
		||||
	virtual void unregisterLockHandler() {}
 | 
			
		||||
 | 
			
		||||
	bool _isSuspendEnabled;
 | 
			
		||||
	bool _isLockEnabled;
 | 
			
		||||
	bool _isSuspendOnLock;
 | 
			
		||||
 | 
			
		||||
	bool _isSuspendRegistered;
 | 
			
		||||
	bool _isLockRegistered;
 | 
			
		||||
 | 
			
		||||
	Logger * _log {};
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
 | 
			
		||||
class OsEventHandlerWindows : public OsEventHandlerBase, public QAbstractNativeEventFilter {
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	OsEventHandlerWindows();
 | 
			
		||||
	~OsEventHandlerWindows() override;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
 | 
			
		||||
	bool nativeEventFilter(const QByteArray& eventType, void* message, qintptr* result) override;
 | 
			
		||||
#else
 | 
			
		||||
	bool nativeEventFilter(const QByteArray& eventType, void* message, long int* result) override;
 | 
			
		||||
#endif
 | 
			
		||||
^
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
	bool registerOsEventHandler() override;
 | 
			
		||||
	void unregisterOsEventHandler() override;
 | 
			
		||||
	bool registerLockHandler() override;
 | 
			
		||||
	void unregisterLockHandler() override;
 | 
			
		||||
 | 
			
		||||
	QWidget			_widget;
 | 
			
		||||
	HPOWERNOTIFY	_notifyHandle;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using OsEventHandler = OsEventHandlerWindows;
 | 
			
		||||
 | 
			
		||||
#elif defined(__linux__)
 | 
			
		||||
class OsEventHandlerLinux : public OsEventHandlerBase {
 | 
			
		||||
	Q_OBJECT
 | 
			
		||||
 | 
			
		||||
	static void static_signaleHandler(int signum)
 | 
			
		||||
	{
 | 
			
		||||
		OsEventHandlerLinux::getInstance()->handleSignal(signum);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	OsEventHandlerLinux();
 | 
			
		||||
 | 
			
		||||
	void handleSignal (int signum);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	static OsEventHandlerLinux* getInstance();
 | 
			
		||||
 | 
			
		||||
#if defined(HYPERION_HAS_DBUS)
 | 
			
		||||
	bool registerOsEventHandler() override;
 | 
			
		||||
	void unregisterOsEventHandler() override;
 | 
			
		||||
	bool registerLockHandler() override;
 | 
			
		||||
	void unregisterLockHandler() override;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using OsEventHandler = OsEventHandlerLinux;
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
using OsEventHandler = OsEventHandlerBase;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // OsEventHandler_H
 | 
			
		||||
@@ -24,9 +24,7 @@
 | 
			
		||||
// Determine the cmake options
 | 
			
		||||
#include <HyperionConfig.h>
 | 
			
		||||
 | 
			
		||||
#if defined(ENABLE_CEC)
 | 
			
		||||
	#include <cec/CECEvent.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <events/Event.h>
 | 
			
		||||
 | 
			
		||||
///
 | 
			
		||||
/// Capture class for V4L2 devices
 | 
			
		||||
@@ -77,13 +75,10 @@ public:
 | 
			
		||||
	void setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold = 50);
 | 
			
		||||
	void setSignalDetectionOffset( double verticalMin, double horizontalMin, double verticalMax, double horizontalMax);
 | 
			
		||||
	void setSignalDetectionEnable(bool enable);
 | 
			
		||||
	void setCecDetectionEnable(bool enable);
 | 
			
		||||
	bool reload(bool force = false);
 | 
			
		||||
 | 
			
		||||
	QRectF getSignalDetectionOffset() const { return QRectF(_x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max); } //used from hyperion-v4l2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief Discover available V4L2 USB devices (for configuration).
 | 
			
		||||
	/// @param[in] params Parameters used to overwrite discovery default behaviour
 | 
			
		||||
@@ -97,9 +92,7 @@ public slots:
 | 
			
		||||
	void stop();
 | 
			
		||||
	void newThreadFrame(Image<ColorRgb> image);
 | 
			
		||||
 | 
			
		||||
#if defined(ENABLE_CEC)
 | 
			
		||||
	void handleCecEvent(CECEvent event);
 | 
			
		||||
#endif
 | 
			
		||||
	void handleEvent(Event event);
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
	void newFrame(const Image<ColorRgb> & image);
 | 
			
		||||
@@ -167,7 +160,7 @@ private:
 | 
			
		||||
	// signal detection
 | 
			
		||||
	int      _noSignalCounterThreshold;
 | 
			
		||||
	ColorRgb _noSignalThresholdColor;
 | 
			
		||||
	bool     _cecDetectionEnabled, _cecStandbyActivated, _signalDetectionEnabled, _noSignalDetected;
 | 
			
		||||
	bool     _standbyActivated, _signalDetectionEnabled, _noSignalDetected;
 | 
			
		||||
	int      _noSignalCounter;
 | 
			
		||||
	int		_brightness, _contrast, _saturation, _hue;
 | 
			
		||||
	double   _x_frac_min;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,9 +9,7 @@
 | 
			
		||||
	#include <grabber/V4L2Grabber.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(ENABLE_CEC)
 | 
			
		||||
	#include <cec/CECEvent.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <events/Event.h>
 | 
			
		||||
 | 
			
		||||
class VideoWrapper : public GrabberWrapper
 | 
			
		||||
{
 | 
			
		||||
@@ -25,9 +23,7 @@ public slots:
 | 
			
		||||
	bool start() override;
 | 
			
		||||
	void stop() override;
 | 
			
		||||
 | 
			
		||||
#if defined(ENABLE_CEC)
 | 
			
		||||
	void handleCecEvent(CECEvent event);
 | 
			
		||||
#endif
 | 
			
		||||
	void handleEvent(Event event);
 | 
			
		||||
 | 
			
		||||
	void handleSettingsUpdate(settings::type type, const QJsonDocument& config) override;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
#include <utils/VideoMode.h>
 | 
			
		||||
#include <utils/settings.h>
 | 
			
		||||
#include <utils/Components.h>
 | 
			
		||||
#include <events/Event.h>
 | 
			
		||||
 | 
			
		||||
// qt
 | 
			
		||||
#include <QMap>
 | 
			
		||||
@@ -74,26 +75,10 @@ public slots:
 | 
			
		||||
	bool stopInstance(quint8 inst);
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief Suspend (disable) all Hyperion instances
 | 
			
		||||
	/// @brief Handle an Hyperion Event
 | 
			
		||||
	/// @param event Event to be processed
 | 
			
		||||
	///
 | 
			
		||||
	void suspend();
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief Resume (resume) all Hyperion instances
 | 
			
		||||
	///
 | 
			
		||||
	void resume();
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief Toggle the state of all Hyperion instances for a suspend sceanrio (user is not interacting with the system)
 | 
			
		||||
	/// @param isSuspend, If true all instances toggle to suspend, else to resume
 | 
			
		||||
	///
 | 
			
		||||
	void toggleSuspend(bool isSuspend);
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief Toggle the state of all Hyperion instances for an idle sceanrio
 | 
			
		||||
	/// @param isIdle, If true all instances toggle to idle, else to resume
 | 
			
		||||
	///
 | 
			
		||||
	void toggleIdle(bool isIdle);
 | 
			
		||||
	void handleEvent(Event event);
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief Toggle the state of all Hyperion instances
 | 
			
		||||
@@ -147,10 +132,6 @@ signals:
 | 
			
		||||
	///
 | 
			
		||||
	void startInstanceResponse(QObject *caller, const int &tan);
 | 
			
		||||
 | 
			
		||||
	void triggerSuspend(bool isSuspend);
 | 
			
		||||
	void triggerToggleSuspend();
 | 
			
		||||
	void triggerIdle(bool isIdle);
 | 
			
		||||
	void triggerToggleIdle();
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
	///////////////////////////////////////
 | 
			
		||||
@@ -192,6 +173,18 @@ private slots:
 | 
			
		||||
	///
 | 
			
		||||
	void handleFinished();
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief Toggle the state of all Hyperion instances for a suspend sceanrio (user is not interacting with the system)
 | 
			
		||||
	/// @param isSuspend, If true all instances toggle to suspend, else to resume
 | 
			
		||||
	///
 | 
			
		||||
	void toggleSuspend(bool isSuspend);
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief Toggle the state of all Hyperion instances for an idle sceanrio
 | 
			
		||||
	/// @param isIdle, If true all instances toggle to idle, else to resume
 | 
			
		||||
	///
 | 
			
		||||
	void toggleIdle(bool isIdle);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class HyperionDaemon;
 | 
			
		||||
	///
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,8 @@ namespace settings {
 | 
			
		||||
		NETWORK,
 | 
			
		||||
		FLATBUFSERVER,
 | 
			
		||||
		PROTOSERVER,
 | 
			
		||||
		SYSTEMEVENTS,
 | 
			
		||||
		OSEVENTS,
 | 
			
		||||
		CECEVENTS,
 | 
			
		||||
		INVALID
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
@@ -65,7 +66,8 @@ namespace settings {
 | 
			
		||||
		case NETWORK:       return "network";
 | 
			
		||||
		case FLATBUFSERVER: return "flatbufServer";
 | 
			
		||||
		case PROTOSERVER:   return "protoServer";
 | 
			
		||||
		case SYSTEMEVENTS:  return "systemEvents";
 | 
			
		||||
		case OSEVENTS:      return "osEvents";
 | 
			
		||||
		case CECEVENTS:     return "cecEvents";
 | 
			
		||||
		default:            return "invalid";
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -99,7 +101,8 @@ namespace settings {
 | 
			
		||||
		else if (type == "network")              return NETWORK;
 | 
			
		||||
		else if (type == "flatbufServer")        return FLATBUFSERVER;
 | 
			
		||||
		else if (type == "protoServer")          return PROTOSERVER;
 | 
			
		||||
		else if (type == "systemEvents")         return SYSTEMEVENTS;
 | 
			
		||||
		else if (type == "osEvents")             return OSEVENTS;
 | 
			
		||||
		else if (type == "cecEvents")            return CECEVENTS;
 | 
			
		||||
		else                                     return INVALID;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,12 @@ add_subdirectory(db)
 | 
			
		||||
add_subdirectory(api)
 | 
			
		||||
add_subdirectory(ssdp)
 | 
			
		||||
 | 
			
		||||
if(ENABLE_CEC)
 | 
			
		||||
	add_subdirectory(cec)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
add_subdirectory(events)
 | 
			
		||||
 | 
			
		||||
if(ENABLE_MDNS)
 | 
			
		||||
	add_subdirectory(mdns)
 | 
			
		||||
endif()	
 | 
			
		||||
@@ -41,10 +47,6 @@ if(ENABLE_EFFECTENGINE)
 | 
			
		||||
	add_subdirectory(python)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if(ENABLE_CEC)
 | 
			
		||||
	add_subdirectory(cec)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if(ENABLE_EXPERIMENTAL)
 | 
			
		||||
	add_subdirectory(experimental)
 | 
			
		||||
endif()
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@
 | 
			
		||||
#include <grabber/QtGrabber.h>
 | 
			
		||||
 | 
			
		||||
#include <utils/WeakConnect.h>
 | 
			
		||||
#include <events/Event.h>
 | 
			
		||||
 | 
			
		||||
#if defined(ENABLE_MF)
 | 
			
		||||
	#include <grabber/MFGrabber.h>
 | 
			
		||||
@@ -82,6 +83,7 @@
 | 
			
		||||
 | 
			
		||||
// api includes
 | 
			
		||||
#include <api/JsonCB.h>
 | 
			
		||||
#include <events/EventHandler.h>
 | 
			
		||||
 | 
			
		||||
// auth manager
 | 
			
		||||
#include <hyperion/AuthManager.h>
 | 
			
		||||
@@ -110,6 +112,8 @@ JsonAPI::JsonAPI(QString peerAddress, Logger *log, bool localConnection, QObject
 | 
			
		||||
	_ledStreamTimer = new QTimer(this);
 | 
			
		||||
 | 
			
		||||
	Q_INIT_RESOURCE(JSONRPC_schemas);
 | 
			
		||||
 | 
			
		||||
		qRegisterMetaType<Event>("Event");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void JsonAPI::initialize()
 | 
			
		||||
@@ -135,16 +139,13 @@ void JsonAPI::initialize()
 | 
			
		||||
		connect(this, &JsonAPI::forwardJsonMessage, _hyperion, &Hyperion::forwardJsonMessage);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//notify instance manager on suspend/resume/idle requests
 | 
			
		||||
	connect(this, &JsonAPI::suspendAll, _instanceManager, &HyperionIManager::triggerSuspend);
 | 
			
		||||
	connect(this, &JsonAPI::toggleSuspendAll, _instanceManager, &HyperionIManager::triggerToggleSuspend);
 | 
			
		||||
	connect(this, &JsonAPI::idleAll, _instanceManager, &HyperionIManager::triggerIdle);
 | 
			
		||||
	connect(this, &JsonAPI::toggleIdleAll, _instanceManager, &HyperionIManager::triggerToggleIdle);
 | 
			
		||||
	//notify eventhadler on suspend/resume/idle requests
 | 
			
		||||
	connect(this, &JsonAPI::signalEvent, EventHandler::getInstance(), &EventHandler::handleEvent);
 | 
			
		||||
 | 
			
		||||
	connect(_ledStreamTimer, &QTimer::timeout, this, &JsonAPI::streamLedColorsUpdate, Qt::UniqueConnection);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool JsonAPI::handleInstanceSwitch(quint8 inst, bool forced)
 | 
			
		||||
bool JsonAPI::handleInstanceSwitch(quint8 inst, bool /*forced*/)
 | 
			
		||||
{
 | 
			
		||||
	if (API::setHyperionInstance(inst))
 | 
			
		||||
	{
 | 
			
		||||
@@ -1014,8 +1015,7 @@ void JsonAPI::handleConfigCommand(const QJsonObject &message, const QString &com
 | 
			
		||||
		if (_adminAuthorized)
 | 
			
		||||
		{
 | 
			
		||||
			Debug(_log, "Restarting due to RPC command");
 | 
			
		||||
 | 
			
		||||
			Process::restartHyperion(10);
 | 
			
		||||
			emit signalEvent(Event::Reload);
 | 
			
		||||
 | 
			
		||||
			sendSuccessReply(command + "-" + subcommand, tan);
 | 
			
		||||
		}
 | 
			
		||||
@@ -1852,32 +1852,37 @@ void JsonAPI::handleSystemCommand(const QJsonObject &message, const QString &com
 | 
			
		||||
 | 
			
		||||
	if (subc == "suspend")
 | 
			
		||||
	{
 | 
			
		||||
		emit suspendAll(true);
 | 
			
		||||
		emit signalEvent(Event::Suspend);
 | 
			
		||||
		sendSuccessReply(command + "-" + subc, tan);
 | 
			
		||||
	}
 | 
			
		||||
	else if (subc == "resume")
 | 
			
		||||
	{
 | 
			
		||||
		emit suspendAll(false);
 | 
			
		||||
		emit signalEvent(Event::Resume);
 | 
			
		||||
		sendSuccessReply(command + "-" + subc, tan);
 | 
			
		||||
	}
 | 
			
		||||
	else if (subc == "restart")
 | 
			
		||||
	{
 | 
			
		||||
		Process::restartHyperion(11);
 | 
			
		||||
		emit signalEvent(Event::Restart);
 | 
			
		||||
		sendSuccessReply(command + "-" + subc, tan);
 | 
			
		||||
	}
 | 
			
		||||
	else if (subc == "toggleSuspend")
 | 
			
		||||
	{
 | 
			
		||||
		emit toggleSuspendAll();
 | 
			
		||||
		emit signalEvent(Event::ToggleSuspend);
 | 
			
		||||
		sendSuccessReply(command + "-" + subc, tan);
 | 
			
		||||
	}
 | 
			
		||||
	else if (subc == "idle")
 | 
			
		||||
	{
 | 
			
		||||
		emit idleAll(true);
 | 
			
		||||
		emit signalEvent(Event::Idle);
 | 
			
		||||
		sendSuccessReply(command + "-" + subc, tan);
 | 
			
		||||
	}
 | 
			
		||||
	else if (subc == "resumeIdle")
 | 
			
		||||
	{
 | 
			
		||||
		emit signalEvent(Event::ResumeIdle);
 | 
			
		||||
		sendSuccessReply(command + "-" + subc, tan);
 | 
			
		||||
	}
 | 
			
		||||
	else if (subc == "toggleIdle")
 | 
			
		||||
	{
 | 
			
		||||
		emit toggleIdleAll();
 | 
			
		||||
		emit signalEvent(Event::ToggleIdle);
 | 
			
		||||
		sendSuccessReply(command + "-" + subc, tan);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
#include <libcec/cecloader.h>
 | 
			
		||||
#include <events/EventHandler.h>
 | 
			
		||||
 | 
			
		||||
#include <QJsonArray>
 | 
			
		||||
#include <QJsonDocument>
 | 
			
		||||
@@ -12,13 +13,14 @@
 | 
			
		||||
#include <QFile>
 | 
			
		||||
 | 
			
		||||
/* Enable to turn on detailed CEC logs */
 | 
			
		||||
#define NO_VERBOSE_CEC
 | 
			
		||||
#define VERBOSE_CEC
 | 
			
		||||
 | 
			
		||||
CECHandler::CECHandler()
 | 
			
		||||
	: _isEnabled(false)
 | 
			
		||||
{
 | 
			
		||||
	qRegisterMetaType<CECEvent>("CECEvent");
 | 
			
		||||
	qRegisterMetaType<Event>("Event");
 | 
			
		||||
 | 
			
		||||
	 _logger = Logger::getInstance("CEC");
 | 
			
		||||
	_logger = Logger::getInstance("CEC");
 | 
			
		||||
 | 
			
		||||
	_cecCallbacks            = getCallbacks();
 | 
			
		||||
	_cecConfig               = getConfig();
 | 
			
		||||
@@ -31,25 +33,41 @@ CECHandler::~CECHandler()
 | 
			
		||||
	stop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CECHandler::handleSettingsUpdate(settings::type type, const QJsonDocument& config)
 | 
			
		||||
{
 | 
			
		||||
	if(type == settings::CECEVENTS)
 | 
			
		||||
	{
 | 
			
		||||
		const QJsonObject& obj = config.object();
 | 
			
		||||
 | 
			
		||||
		_isEnabled = obj["Enable"].toBool(false);
 | 
			
		||||
 | 
			
		||||
		Debug(_logger, "_isEnabled: [%d]", _isEnabled);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CECHandler::start()
 | 
			
		||||
{
 | 
			
		||||
	if (_cecAdapter)
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	std::string library = std::string("" CEC_LIBRARY);
 | 
			
		||||
	_cecAdapter = LibCecInitialise(&_cecConfig, QFile::exists(QString::fromStdString(library)) ? library.c_str() : nullptr);
 | 
			
		||||
	if(!_cecAdapter)
 | 
			
		||||
	{
 | 
			
		||||
		Error(_logger, "Failed to loading libcec.so");
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//	std::string library = std::string("" CEC_LIBRARY);
 | 
			
		||||
	//	_cecAdapter = LibCecInitialise(&_cecConfig, QFile::exists(QString::fromStdString(library)) ? library.c_str() :CEC_DEVICE_TYPE_PLAYBACK_DEVICE nullptr);
 | 
			
		||||
 | 
			
		||||
	_cecAdapter = LibCecInitialise(&_cecConfig);
 | 
			
		||||
	if(_cecAdapter == nullptr)
 | 
			
		||||
	{
 | 
			
		||||
		Error(_logger, "Failed loading libCEC library. CEC is not supported.");
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Info(_logger, "CEC handler started");
 | 
			
		||||
 | 
			
		||||
	auto adapters = getAdapters();
 | 
			
		||||
	const auto adapters = getAdapters();
 | 
			
		||||
	if (adapters.isEmpty())
 | 
			
		||||
	{
 | 
			
		||||
		Error(_logger, "Failed to find CEC adapter");
 | 
			
		||||
		Error(_logger, "Failed to find any CEC adapter.");
 | 
			
		||||
		UnloadLibCec(_cecAdapter);
 | 
			
		||||
		_cecAdapter = nullptr;
 | 
			
		||||
 | 
			
		||||
@@ -64,14 +82,19 @@ bool CECHandler::start()
 | 
			
		||||
 | 
			
		||||
		if (!opened && openAdapter(adapter))
 | 
			
		||||
		{
 | 
			
		||||
			Info(_logger, "CEC Handler initialized with adapter : %s", adapter.strComName);
 | 
			
		||||
			QObject::connect(this, &CECHandler::signalEvent, EventHandler::getInstance(), &EventHandler::handleEvent);
 | 
			
		||||
 | 
			
		||||
			Info(_logger, "CEC adapter '%s', type: %s initialized." , adapter.strComName, _cecAdapter->ToString(adapter.adapterType));
 | 
			
		||||
			opened = true;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scan();
 | 
			
		||||
 | 
			
		||||
	if (!opened)
 | 
			
		||||
	{
 | 
			
		||||
		Error(_logger, "Could not initialize any CEC adapter.");
 | 
			
		||||
		UnloadLibCec(_cecAdapter);
 | 
			
		||||
		_cecAdapter = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
@@ -81,10 +104,12 @@ bool CECHandler::start()
 | 
			
		||||
 | 
			
		||||
void CECHandler::stop()
 | 
			
		||||
{
 | 
			
		||||
	if (_cecAdapter)
 | 
			
		||||
	if (_cecAdapter != nullptr)
 | 
			
		||||
	{
 | 
			
		||||
		Info(_logger, "Stopping CEC handler");
 | 
			
		||||
 | 
			
		||||
		QObject::disconnect(this, &CECHandler::signalEvent, EventHandler::getInstance(), &EventHandler::handleEvent);
 | 
			
		||||
 | 
			
		||||
		_cecAdapter->Close();
 | 
			
		||||
		UnloadLibCec(_cecAdapter);
 | 
			
		||||
		_cecAdapter = nullptr;
 | 
			
		||||
@@ -97,9 +122,9 @@ CECConfig CECHandler::getConfig() const
 | 
			
		||||
 | 
			
		||||
	const std::string name("HyperionCEC");
 | 
			
		||||
	name.copy(configuration.strDeviceName, std::min(name.size(), sizeof(configuration.strDeviceName)));
 | 
			
		||||
 | 
			
		||||
	configuration.deviceTypes.Add(CEC::CEC_DEVICE_TYPE_RECORDING_DEVICE);
 | 
			
		||||
	configuration.clientVersion = CEC::LIBCEC_VERSION_CURRENT;
 | 
			
		||||
	configuration.bActivateSource = 0;
 | 
			
		||||
 | 
			
		||||
	return configuration;
 | 
			
		||||
}
 | 
			
		||||
@@ -125,7 +150,8 @@ QVector<CECAdapterDescriptor> CECHandler::getAdapters() const
 | 
			
		||||
		return {};
 | 
			
		||||
 | 
			
		||||
	QVector<CECAdapterDescriptor> descriptors(16);
 | 
			
		||||
	int8_t size = _cecAdapter->DetectAdapters(descriptors.data(), descriptors.size(), nullptr, true /*quickscan*/);
 | 
			
		||||
	//int8_t size = _cecAdapter->DetectAdapters(descriptors.data(), static_cast<uint8_t>(descriptors.size()), nullptr, true /*quickscan*/);
 | 
			
		||||
	int8_t size = _cecAdapter->DetectAdapters(descriptors.data(), static_cast<uint8_t>(descriptors.size()), nullptr, false /*NO quickscan*/);
 | 
			
		||||
	descriptors.resize(size);
 | 
			
		||||
 | 
			
		||||
	return descriptors;
 | 
			
		||||
@@ -138,10 +164,7 @@ bool CECHandler::openAdapter(const CECAdapterDescriptor & descriptor)
 | 
			
		||||
 | 
			
		||||
	if(!_cecAdapter->Open(descriptor.strComName))
 | 
			
		||||
	{
 | 
			
		||||
		Error(_logger, "%s", QSTRING_CSTR(QString("Failed to open the CEC adaper on port %1")
 | 
			
		||||
										  .arg(descriptor.strComName))
 | 
			
		||||
			  );
 | 
			
		||||
 | 
			
		||||
		Error(_logger, "CEC adapter '%s', type: %s failed to open.", descriptor.strComName, _cecAdapter->ToString(descriptor.adapterType));
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
@@ -149,9 +172,16 @@ bool CECHandler::openAdapter(const CECAdapterDescriptor & descriptor)
 | 
			
		||||
 | 
			
		||||
void CECHandler::printAdapter(const CECAdapterDescriptor & descriptor) const
 | 
			
		||||
{
 | 
			
		||||
	Info(_logger, "%s", QSTRING_CSTR(QString("CEC Adapter:")));
 | 
			
		||||
	Info(_logger, "%s", QSTRING_CSTR(QString("\tName   : %1").arg(descriptor.strComName)));
 | 
			
		||||
	Info(_logger, "%s", QSTRING_CSTR(QString("\tPath   : %1").arg(descriptor.strComPath)));
 | 
			
		||||
	Info(_logger, "CEC Adapter:");
 | 
			
		||||
	Info(_logger, "\tName       : %s", descriptor.strComName);
 | 
			
		||||
	Info(_logger, "\tPath       : %s", descriptor.strComPath);
 | 
			
		||||
	Info(_logger, "\tVendor   id: %04x", descriptor.iVendorId);
 | 
			
		||||
	Info(_logger, "\tProduct  id: %04x", descriptor.iProductId);
 | 
			
		||||
	Info(_logger, "\tFirmware id: %d", descriptor.iFirmwareVersion);
 | 
			
		||||
	if (descriptor.adapterType != CEC::ADAPTERTYPE_UNKNOWN)
 | 
			
		||||
	{
 | 
			
		||||
		Info(_logger, "\tType   : %s", _cecAdapter->ToString(descriptor.adapterType));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString CECHandler::scan() const
 | 
			
		||||
@@ -163,14 +193,14 @@ QString CECHandler::scan() const
 | 
			
		||||
 | 
			
		||||
	QJsonArray devices;
 | 
			
		||||
	CECLogicalAddresses addresses = _cecAdapter->GetActiveDevices();
 | 
			
		||||
	for (int address = CEC::CECDEVICE_TV; address <= CEC::CECDEVICE_BROADCAST; ++address)
 | 
			
		||||
	for (uint8_t address = CEC::CECDEVICE_TV; address <= CEC::CECDEVICE_BROADCAST; ++address)
 | 
			
		||||
	{
 | 
			
		||||
		if (addresses[address])
 | 
			
		||||
		if (addresses[address] != 0)
 | 
			
		||||
		{
 | 
			
		||||
			CECLogicalAddress logicalAddress = (CECLogicalAddress)address;
 | 
			
		||||
			CECLogicalAddress logicalAddress = static_cast<CECLogicalAddress>(address);
 | 
			
		||||
 | 
			
		||||
			QJsonObject device;
 | 
			
		||||
			CECVendorId vendor = (CECVendorId)_cecAdapter->GetDeviceVendorId(logicalAddress);
 | 
			
		||||
			CECVendorId vendor = static_cast<CECVendorId>(_cecAdapter->GetDeviceVendorId(logicalAddress));
 | 
			
		||||
			CECPowerStatus power = _cecAdapter->GetDevicePowerStatus(logicalAddress);
 | 
			
		||||
 | 
			
		||||
			device["name"    ] = _cecAdapter->GetDeviceOSDName(logicalAddress).c_str();
 | 
			
		||||
@@ -181,14 +211,17 @@ QString CECHandler::scan() const
 | 
			
		||||
			devices << device;
 | 
			
		||||
 | 
			
		||||
			Info(_logger, "%s", QSTRING_CSTR(QString("\tCECDevice: %1 / %2 / %3 / %4")
 | 
			
		||||
				.arg(device["name"].toString(),
 | 
			
		||||
				device["vendor"].toString(),
 | 
			
		||||
				device["address"].toString(),
 | 
			
		||||
				device["power"].toString()))
 | 
			
		||||
											 .arg(device["name"].toString(),
 | 
			
		||||
											 device["vendor"].toString(),
 | 
			
		||||
											 device["address"].toString(),
 | 
			
		||||
											 device["power"].toString())
 | 
			
		||||
					)
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::cout << "Devices: " <<  QJsonDocument(devices).toJson().toStdString() << std::endl;
 | 
			
		||||
 | 
			
		||||
	return QJsonDocument(devices).toJson(QJsonDocument::Compact);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -202,25 +235,17 @@ void CECHandler::onCecLogMessage(void * context, const CECLogMessage * message)
 | 
			
		||||
	switch (message->level)
 | 
			
		||||
	{
 | 
			
		||||
	case CEC::CEC_LOG_ERROR:
 | 
			
		||||
		Error(handler->_logger, QString("%1")
 | 
			
		||||
			.arg(message->message)
 | 
			
		||||
				.toLocal8Bit());
 | 
			
		||||
		Error(handler->_logger, "%s", message->message);
 | 
			
		||||
		break;
 | 
			
		||||
	case CEC::CEC_LOG_WARNING:
 | 
			
		||||
		Warning(handler->_logger, QString("%1")
 | 
			
		||||
			.arg(message->message)
 | 
			
		||||
				.toLocal8Bit());
 | 
			
		||||
		Warning(handler->_logger, "%s", message->message);
 | 
			
		||||
		break;
 | 
			
		||||
	case CEC::CEC_LOG_TRAFFIC:
 | 
			
		||||
	case CEC::CEC_LOG_NOTICE:
 | 
			
		||||
		Info(handler->_logger, QString("%1")
 | 
			
		||||
			.arg(message->message)
 | 
			
		||||
				.toLocal8Bit());
 | 
			
		||||
		Info(handler->_logger, "%s", message->message);
 | 
			
		||||
		break;
 | 
			
		||||
	case CEC::CEC_LOG_DEBUG:
 | 
			
		||||
		Debug(handler->_logger, QString("%1")
 | 
			
		||||
			.arg(message->message)
 | 
			
		||||
				.toLocal8Bit());
 | 
			
		||||
		Debug(handler->_logger, "%s", message->message);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
@@ -230,29 +255,44 @@ void CECHandler::onCecLogMessage(void * context, const CECLogMessage * message)
 | 
			
		||||
 | 
			
		||||
void CECHandler::onCecKeyPress(void * context, const CECKeyPress * key)
 | 
			
		||||
{
 | 
			
		||||
#ifdef VERBOSE_CEC
 | 
			
		||||
	CECHandler * handler = qobject_cast<CECHandler*>(static_cast<QObject*>(context));
 | 
			
		||||
	if (!handler)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	CECAdapter * adapter = handler->_cecAdapter;
 | 
			
		||||
 | 
			
		||||
	Debug(handler->_logger, QString("CECHandler::onCecKeyPress: %1")
 | 
			
		||||
		.arg(adapter->ToString(key->keycode))
 | 
			
		||||
			.toLocal8Bit());
 | 
			
		||||
#ifdef VERBOSE_CEC
 | 
			
		||||
	Debug(handler->_logger, "CECHandler::onCecKeyPress: %s", adapter->ToString(key->keycode));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	switch (key->keycode) {
 | 
			
		||||
	case CEC::CEC_USER_CONTROL_CODE_F1_BLUE:
 | 
			
		||||
			emit handler->signalEvent(Event::ToggleIdle);
 | 
			
		||||
		break;
 | 
			
		||||
	case CEC::CEC_USER_CONTROL_CODE_F2_RED:
 | 
			
		||||
			emit handler->signalEvent(Event::Suspend);
 | 
			
		||||
		break;
 | 
			
		||||
	case CEC::CEC_USER_CONTROL_CODE_F3_GREEN:
 | 
			
		||||
			emit handler->signalEvent(Event::Resume);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CEC::CEC_USER_CONTROL_CODE_F4_YELLOW:
 | 
			
		||||
			emit handler->signalEvent(Event::ToggleSuspend);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CECHandler::onCecAlert(void * context, const CECAlert alert, const CECParameter data)
 | 
			
		||||
void CECHandler::onCecAlert(void * context, const CECAlert alert, const CECParameter /* data */)
 | 
			
		||||
{
 | 
			
		||||
#ifdef VERBOSE_CEC
 | 
			
		||||
	CECHandler * handler = qobject_cast<CECHandler*>(static_cast<QObject*>(context));
 | 
			
		||||
	if (!handler)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	Error(handler->_logger, QString("CECHandler::onCecAlert: %1")
 | 
			
		||||
		.arg(alert)
 | 
			
		||||
			.toLocal8Bit());
 | 
			
		||||
	Error(handler->_logger, QSTRING_CSTR(QString("CECHandler::onCecAlert: %1")
 | 
			
		||||
										 .arg(alert)));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -263,9 +303,7 @@ void CECHandler::onCecConfigurationChanged(void * context, const CECConfig * con
 | 
			
		||||
	if (!handler)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	Debug(handler->_logger, QString("CECHandler::onCecConfigurationChanged: %1")
 | 
			
		||||
		.arg(configuration->strDeviceName)
 | 
			
		||||
			.toLocal8Bit());
 | 
			
		||||
	Debug(handler->_logger, "CECHandler::onCecConfigurationChanged: %s", configuration->strDeviceName);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -278,9 +316,7 @@ int CECHandler::onCecMenuStateChanged(void * context, const CECMenuState state)
 | 
			
		||||
 | 
			
		||||
	CECAdapter * adapter = handler->_cecAdapter;
 | 
			
		||||
 | 
			
		||||
	Debug(handler->_logger, QString("CECHandler::onCecMenuStateChanged: %1")
 | 
			
		||||
		.arg(adapter->ToString(state))
 | 
			
		||||
			.toLocal8Bit());
 | 
			
		||||
	Debug(handler->_logger, "CECHandler::onCecMenuStateChanged: %s", adapter->ToString(state));
 | 
			
		||||
#endif
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -294,28 +330,28 @@ void CECHandler::onCecCommandReceived(void * context, const CECCommand * command
 | 
			
		||||
	CECAdapter * adapter = handler->_cecAdapter;
 | 
			
		||||
 | 
			
		||||
#ifdef VERBOSE_CEC
 | 
			
		||||
	Debug(handler->_logger, QString("CECHandler::onCecCommandReceived: %1 (%2 > %3)")
 | 
			
		||||
		.arg(adapter->ToString(command->opcode))
 | 
			
		||||
		.arg(adapter->ToString(command->initiator))
 | 
			
		||||
		.arg(adapter->ToString(command->destination))
 | 
			
		||||
			.toLocal8Bit());
 | 
			
		||||
	Debug(handler->_logger, "CECHandler::onCecCommandReceived: %s %s > %s)",
 | 
			
		||||
		  adapter->ToString(command->opcode),
 | 
			
		||||
		  adapter->ToString(command->initiator),
 | 
			
		||||
		  adapter->ToString(command->destination)
 | 
			
		||||
		  );
 | 
			
		||||
#endif
 | 
			
		||||
	/* We do NOT check sender */
 | 
			
		||||
	// if (address == CEC::CECDEVICE_TV)
 | 
			
		||||
	//if (address == CEC::CECDEVICE_TV)
 | 
			
		||||
	{
 | 
			
		||||
		if (command->opcode == CEC::CEC_OPCODE_SET_STREAM_PATH)
 | 
			
		||||
		{
 | 
			
		||||
			Info(handler->_logger, "%s", QSTRING_CSTR(QString("CEC source activated: %1")
 | 
			
		||||
				.arg(adapter->ToString(command->initiator)))
 | 
			
		||||
			);
 | 
			
		||||
			emit handler->cecEvent(CECEvent::On);
 | 
			
		||||
		}
 | 
			
		||||
		if (command->opcode == CEC::CEC_OPCODE_STANDBY)
 | 
			
		||||
		{
 | 
			
		||||
			Info(handler->_logger, "%s", QSTRING_CSTR(QString("CEC source deactivated: %1")
 | 
			
		||||
				.arg(adapter->ToString(command->initiator)))
 | 
			
		||||
			);
 | 
			
		||||
			emit handler->cecEvent(CECEvent::Off);
 | 
			
		||||
		switch (command->opcode) {
 | 
			
		||||
		case  CEC::CEC_OPCODE_STANDBY:
 | 
			
		||||
			Info(handler->_logger, "CEC source deactivated: %s", adapter->ToString(command->initiator));
 | 
			
		||||
			emit handler->signalEvent(Event::Suspend);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case  CEC::CEC_OPCODE_SET_STREAM_PATH:
 | 
			
		||||
			Info(handler->_logger, "'CEC source activated: %s", adapter->ToString(command->initiator));
 | 
			
		||||
			emit handler->signalEvent(Event::Resume);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -328,14 +364,15 @@ void CECHandler::onCecSourceActivated(void * context, const CECLogicalAddress ad
 | 
			
		||||
#ifdef VERBOSE_CEC
 | 
			
		||||
	CECHandler * handler = qobject_cast<CECHandler*>(static_cast<QObject*>(context));
 | 
			
		||||
	if (!handler)
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CECAdapter * adapter = handler->_cecAdapter;
 | 
			
		||||
 | 
			
		||||
	Debug(handler->_logger, QString("CEC source %1 : %2")
 | 
			
		||||
		.arg(activated ? "activated" : "deactivated")
 | 
			
		||||
		.arg(adapter->ToString(address))
 | 
			
		||||
			.toLocal8Bit());
 | 
			
		||||
	Debug(handler->_logger, QSTRING_CSTR(QString("CEC source %1 : %2")
 | 
			
		||||
										 .arg(activated ? "activated" : "deactivated",
 | 
			
		||||
											  adapter->ToString(address))
 | 
			
		||||
										 ));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,9 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/cec)
 | 
			
		||||
FILE (GLOB CEC_SOURCES "${CURRENT_HEADER_DIR}/*.h"  "${CURRENT_SOURCE_DIR}/*.h"  "${CURRENT_SOURCE_DIR}/*.cpp")
 | 
			
		||||
 | 
			
		||||
add_library(cechandler ${CEC_SOURCES})
 | 
			
		||||
 | 
			
		||||
message(STATUS "CEC_LIBRARIES = ${CEC_LIBRARIES}")
 | 
			
		||||
 | 
			
		||||
list(GET CEC_LIBRARIES 0 CEC_LIBRARIES)
 | 
			
		||||
add_definitions(-DCEC_LIBRARY="${CEC_LIBRARIES}")
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								libsrc/events/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								libsrc/events/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
# Define the current source/header locations
 | 
			
		||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/events)
 | 
			
		||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/events)
 | 
			
		||||
 | 
			
		||||
add_library(events
 | 
			
		||||
	${CURRENT_HEADER_DIR}/Event.h
 | 
			
		||||
	${CURRENT_HEADER_DIR}/EventHandler.h
 | 
			
		||||
	${CURRENT_SOURCE_DIR}/EventHandler.cpp
 | 
			
		||||
	${CURRENT_HEADER_DIR}/OsEventHandler.h
 | 
			
		||||
	${CURRENT_SOURCE_DIR}/OsEventHandler.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if (UNIX)
 | 
			
		||||
	find_package(Qt${QT_VERSION_MAJOR} COMPONENTS DBus QUIET )
 | 
			
		||||
	if (Qt${QT_VERSION_MAJOR}DBus_FOUND)
 | 
			
		||||
		target_link_libraries(events Qt${QT_VERSION_MAJOR}::DBus)
 | 
			
		||||
		if (NOT APPLE)
 | 
			
		||||
			target_compile_definitions(events PUBLIC HYPERION_HAS_DBUS)
 | 
			
		||||
		endif()
 | 
			
		||||
	endif()
 | 
			
		||||
endif(UNIX)
 | 
			
		||||
 | 
			
		||||
target_include_directories(events PUBLIC
 | 
			
		||||
	${CURRENT_HEADER_DIR}
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										186
									
								
								libsrc/events/EventHandler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								libsrc/events/EventHandler.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,186 @@
 | 
			
		||||
#include <events/EventHandler.h>
 | 
			
		||||
 | 
			
		||||
#include <QJsonDocument>
 | 
			
		||||
#include <QJsonObject>
 | 
			
		||||
 | 
			
		||||
#include <events/Event.h>
 | 
			
		||||
 | 
			
		||||
#include <utils/Logger.h>
 | 
			
		||||
#include <utils/Process.h>
 | 
			
		||||
#include <hyperion/HyperionIManager.h>
 | 
			
		||||
 | 
			
		||||
EventHandler::EventHandler()
 | 
			
		||||
	: _isSuspended(false)
 | 
			
		||||
	, _isIdle(false)
 | 
			
		||||
{
 | 
			
		||||
	qRegisterMetaType<Event>("Event");
 | 
			
		||||
	_log = Logger::getInstance("EVENTS");
 | 
			
		||||
 | 
			
		||||
	QObject::connect(this, &EventHandler::signalEvent, HyperionIManager::getInstance(), &HyperionIManager::handleEvent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EventHandler::~EventHandler()
 | 
			
		||||
{
 | 
			
		||||
	QObject::disconnect(this, &EventHandler::signalEvent, HyperionIManager::getInstance(), &HyperionIManager::handleEvent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EventHandler* EventHandler::getInstance()
 | 
			
		||||
{
 | 
			
		||||
	static EventHandler instance;
 | 
			
		||||
	return &instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EventHandler::handleSettingsUpdate(settings::type type, const QJsonDocument& config)
 | 
			
		||||
{
 | 
			
		||||
    if(type == settings::OSEVENTS)
 | 
			
		||||
	{
 | 
			
		||||
		const QJsonObject& obj = config.object();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EventHandler::suspend()
 | 
			
		||||
{
 | 
			
		||||
	suspend(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EventHandler::suspend(bool sleep)
 | 
			
		||||
{
 | 
			
		||||
	if (sleep)
 | 
			
		||||
	{
 | 
			
		||||
		if (!_isSuspended)
 | 
			
		||||
		{
 | 
			
		||||
			_isSuspended = true;
 | 
			
		||||
			Info(_log, "Suspend event received - Hyperion is going to sleep");
 | 
			
		||||
			emit signalEvent(Event::Suspend);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			Debug(_log, "Suspend event ignored - already suspended");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		if (_isSuspended || _isIdle)
 | 
			
		||||
		{
 | 
			
		||||
			Info(_log, "Resume event received - Hyperion is going into working mode");
 | 
			
		||||
			emit signalEvent(Event::Resume);
 | 
			
		||||
			_isSuspended = false;
 | 
			
		||||
			_isIdle = false;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			Debug(_log, "Resume event ignored - not in suspend nor idle mode");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EventHandler::resume()
 | 
			
		||||
{
 | 
			
		||||
	suspend(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EventHandler::toggleSuspend()
 | 
			
		||||
{
 | 
			
		||||
	Debug(_log, "Toggle suspend event received");
 | 
			
		||||
	if (!_isSuspended)
 | 
			
		||||
	{
 | 
			
		||||
		suspend(true);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		suspend(false);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EventHandler::idle()
 | 
			
		||||
{
 | 
			
		||||
	idle(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EventHandler::idle(bool isIdle)
 | 
			
		||||
{
 | 
			
		||||
	if (!_isSuspended)
 | 
			
		||||
	{
 | 
			
		||||
		if (isIdle)
 | 
			
		||||
		{
 | 
			
		||||
			if (!_isIdle)
 | 
			
		||||
			{
 | 
			
		||||
				_isIdle = true;
 | 
			
		||||
				Info(_log, "Idle event received");
 | 
			
		||||
				emit signalEvent(Event::Idle);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			if (_isIdle)
 | 
			
		||||
			{
 | 
			
		||||
				Info(_log, "Resume from idle event recevied");
 | 
			
		||||
				emit signalEvent(Event::ResumeIdle);
 | 
			
		||||
				_isIdle = false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		Debug(_log, "Idle event ignored - Hyperion is suspended");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
void EventHandler::resumeIdle()
 | 
			
		||||
{
 | 
			
		||||
	idle(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EventHandler::toggleIdle()
 | 
			
		||||
{
 | 
			
		||||
	Debug(_log, "Toggle idle event received");
 | 
			
		||||
	if (!_isIdle)
 | 
			
		||||
	{
 | 
			
		||||
		idle(true);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		idle(false);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EventHandler::handleEvent(Event event)
 | 
			
		||||
{
 | 
			
		||||
	Debug(_log,"%s Event [%d] received", eventToString(event), event);
 | 
			
		||||
	switch (event) {
 | 
			
		||||
	case Event::Suspend:
 | 
			
		||||
		suspend();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case Event::Resume:
 | 
			
		||||
		resume();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case Event::ToggleSuspend:
 | 
			
		||||
		suspend();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case Event::Idle:
 | 
			
		||||
		idle(true);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case Event::ResumeIdle:
 | 
			
		||||
		idle(false);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case Event::ToggleIdle:
 | 
			
		||||
		toggleIdle();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case Event::Reload:
 | 
			
		||||
		Process::restartHyperion(10);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case Event::Restart:
 | 
			
		||||
		Process::restartHyperion(11);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		Error(_log,"Unkonwn Event '%d' received", event);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										448
									
								
								libsrc/events/OsEventHandler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										448
									
								
								libsrc/events/OsEventHandler.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,448 @@
 | 
			
		||||
#include "OsEventHandler.h"
 | 
			
		||||
 | 
			
		||||
#include <QtGlobal>
 | 
			
		||||
#include <QJsonDocument>
 | 
			
		||||
#include <QJsonObject>
 | 
			
		||||
 | 
			
		||||
#include <events/EventHandler.h>
 | 
			
		||||
#include <utils/Logger.h>
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
#include <wtsapi32.h>
 | 
			
		||||
 | 
			
		||||
#pragma comment( lib, "wtsapi32.lib" )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
OsEventHandlerBase::OsEventHandlerBase()
 | 
			
		||||
	: _isSuspendEnabled(false)
 | 
			
		||||
	, _isLockEnabled(false)
 | 
			
		||||
	, _isSuspendOnLock(false)
 | 
			
		||||
	, _isSuspendRegistered(false)
 | 
			
		||||
	, _isLockRegistered(false)
 | 
			
		||||
{
 | 
			
		||||
	qRegisterMetaType<Event>("Event");
 | 
			
		||||
	_log = Logger::getInstance("EVENTS");
 | 
			
		||||
 | 
			
		||||
	QObject::connect(this, &OsEventHandlerBase::signalEvent, EventHandler::getInstance(), &EventHandler::handleEvent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OsEventHandlerBase::~OsEventHandlerBase()
 | 
			
		||||
{
 | 
			
		||||
	QObject::disconnect(this, &OsEventHandlerBase::signalEvent, EventHandler::getInstance(), &EventHandler::handleEvent);
 | 
			
		||||
 | 
			
		||||
	unregisterLockHandler();
 | 
			
		||||
	unregisterOsEventHandler();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OsEventHandlerBase::handleSettingsUpdate(settings::type type, const QJsonDocument& config)
 | 
			
		||||
{
 | 
			
		||||
	if(type == settings::OSEVENTS)
 | 
			
		||||
	{
 | 
			
		||||
		const QJsonObject& obj = config.object();
 | 
			
		||||
 | 
			
		||||
		//Suspend on lock or go into idle mode
 | 
			
		||||
		bool prevIsSuspendOnLock = _isSuspendOnLock;
 | 
			
		||||
		_isSuspendOnLock = obj["suspendOnLockEnable"].toBool(false);
 | 
			
		||||
 | 
			
		||||
		//Handle OS event related configurations
 | 
			
		||||
		_isSuspendEnabled = obj["suspendEnable"].toBool(true);
 | 
			
		||||
		if (_isSuspendEnabled)
 | 
			
		||||
		{
 | 
			
		||||
			// Listen to suspend/resume/idle events received by the OS
 | 
			
		||||
			registerOsEventHandler();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			unregisterOsEventHandler();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		_isLockEnabled = obj["lockEnable"].toBool(true);
 | 
			
		||||
		if (_isLockEnabled || _isSuspendOnLock != prevIsSuspendOnLock)
 | 
			
		||||
		{
 | 
			
		||||
			// Listen to lock/screensaver events received by the OS
 | 
			
		||||
			registerLockHandler();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			unregisterLockHandler();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OsEventHandlerBase::suspend(bool sleep)
 | 
			
		||||
{
 | 
			
		||||
	if (sleep)
 | 
			
		||||
	{
 | 
			
		||||
		emit signalEvent(Event::Suspend);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		emit signalEvent(Event::Resume);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OsEventHandlerBase::lock(bool isLocked)
 | 
			
		||||
{
 | 
			
		||||
	if (isLocked)
 | 
			
		||||
	{
 | 
			
		||||
		if (_isSuspendOnLock)
 | 
			
		||||
		{
 | 
			
		||||
			emit signalEvent(Event::Suspend);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			emit signalEvent(Event::Idle);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		if (_isSuspendOnLock)
 | 
			
		||||
		{
 | 
			
		||||
			emit signalEvent(Event::Resume);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			emit signalEvent(Event::ResumeIdle);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
 | 
			
		||||
OsEventHandlerWindows::OsEventHandlerWindows()
 | 
			
		||||
	: _notifyHandle(NULL)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OsEventHandlerWindows::~OsEventHandlerWindows()
 | 
			
		||||
{
 | 
			
		||||
	unregisterLockHandler();
 | 
			
		||||
	unregisterOsEventHandler();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
 | 
			
		||||
bool OsEventHandlerWindows::nativeEventFilter(const QByteArray& eventType, void* message, qintptr* /*result*/)
 | 
			
		||||
#else
 | 
			
		||||
bool OsEventHandlerWindows::nativeEventFilter(const QByteArray& eventType, void* message, long int* /*result*/)
 | 
			
		||||
#endif
 | 
			
		||||
{
 | 
			
		||||
	MSG* msg = static_cast<MSG*>(message);
 | 
			
		||||
 | 
			
		||||
	switch (msg->message)
 | 
			
		||||
	{
 | 
			
		||||
	case WM_WTSSESSION_CHANGE:
 | 
			
		||||
		switch (msg->wParam)
 | 
			
		||||
		{
 | 
			
		||||
		case WTS_SESSION_LOCK:
 | 
			
		||||
			emit lock(true);
 | 
			
		||||
			return true;
 | 
			
		||||
			break;
 | 
			
		||||
		case WTS_SESSION_UNLOCK:
 | 
			
		||||
			emit lock(false);
 | 
			
		||||
			return true;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case WM_POWERBROADCAST:
 | 
			
		||||
		switch (msg->wParam)
 | 
			
		||||
		{
 | 
			
		||||
		case PBT_APMRESUMESUSPEND:
 | 
			
		||||
			emit suspend(false);
 | 
			
		||||
			return true;
 | 
			
		||||
			break;
 | 
			
		||||
		case PBT_APMSUSPEND:
 | 
			
		||||
			emit suspend(true);
 | 
			
		||||
			return true;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool OsEventHandlerWindows::registerOsEventHandler()
 | 
			
		||||
{
 | 
			
		||||
	bool isRegistered{ _isSuspendRegistered };
 | 
			
		||||
	if (!_isSuspendRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		auto handle = reinterpret_cast<HWND> (_widget.winId());
 | 
			
		||||
		_notifyHandle = RegisterSuspendResumeNotification(handle, DEVICE_NOTIFY_WINDOW_HANDLE);
 | 
			
		||||
		if (_notifyHandle != NULL)
 | 
			
		||||
		{
 | 
			
		||||
			QCoreApplication::instance()->installNativeEventFilter(this);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			Error(_log, "Could not register for suspend/resume events!");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (isRegistered)
 | 
			
		||||
		{
 | 
			
		||||
			_isSuspendRegistered = true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return isRegistered;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OsEventHandlerWindows::unregisterOsEventHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (_isSuspendRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		if (_notifyHandle != NULL)
 | 
			
		||||
		{
 | 
			
		||||
			QCoreApplication::instance()->removeNativeEventFilter(this);
 | 
			
		||||
			UnregisterSuspendResumeNotification(_notifyHandle);
 | 
			
		||||
		}
 | 
			
		||||
		_notifyHandle = NULL;
 | 
			
		||||
		_isSuspendRegistered = false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool OsEventHandlerWindows::registerLockHandler()
 | 
			
		||||
{
 | 
			
		||||
	bool isRegistered{ _isLockRegistered };
 | 
			
		||||
	if (!_isLockRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		auto handle = reinterpret_cast<HWND> (_widget.winId());
 | 
			
		||||
		if (WTSRegisterSessionNotification(handle, NOTIFY_FOR_THIS_SESSION))
 | 
			
		||||
		{
 | 
			
		||||
			isRegistered = true;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			Error(_log, "Could not register for lock/unlock events!");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (isRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		_isLockRegistered = true;
 | 
			
		||||
	}
 | 
			
		||||
	return isRegistered;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OsEventHandlerWindows::unregisterLockHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (_isLockRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		auto handle = reinterpret_cast<HWND> (_widget.winId());
 | 
			
		||||
		WTSUnRegisterSessionNotification(handle);
 | 
			
		||||
		_isLockRegistered = false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__linux__)
 | 
			
		||||
 | 
			
		||||
#include <csignal>
 | 
			
		||||
 | 
			
		||||
OsEventHandlerLinux* OsEventHandlerLinux::getInstance()
 | 
			
		||||
{
 | 
			
		||||
	static OsEventHandlerLinux instance;
 | 
			
		||||
	return &instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OsEventHandlerLinux::OsEventHandlerLinux()
 | 
			
		||||
{
 | 
			
		||||
	signal(SIGUSR1, static_signaleHandler);
 | 
			
		||||
	signal(SIGUSR2, static_signaleHandler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OsEventHandlerLinux::handleSignal (int signum)
 | 
			
		||||
{
 | 
			
		||||
	if (signum == SIGUSR1)
 | 
			
		||||
	{
 | 
			
		||||
		suspend(true);
 | 
			
		||||
	}
 | 
			
		||||
	else if (signum == SIGUSR2)
 | 
			
		||||
	{
 | 
			
		||||
		suspend(false);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(HYPERION_HAS_DBUS)
 | 
			
		||||
#include <QDBusConnection>
 | 
			
		||||
 | 
			
		||||
struct dBusSignals
 | 
			
		||||
{
 | 
			
		||||
	QString service;
 | 
			
		||||
	QString path;
 | 
			
		||||
	QString interface;
 | 
			
		||||
	QString name;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef QMultiMap<QString, dBusSignals> DbusSignalsMap;
 | 
			
		||||
 | 
			
		||||
// Constants
 | 
			
		||||
namespace {
 | 
			
		||||
const DbusSignalsMap dbusSignals = {
 | 
			
		||||
	//system signals
 | 
			
		||||
	{"Suspend", {"org.freedesktop.login1","/org/freedesktop/login1","org.freedesktop.login1.Manager","PrepareForSleep"}},
 | 
			
		||||
 | 
			
		||||
	//Session signals
 | 
			
		||||
	{"ScreenSaver", {"org.freedesktop.ScreenSaver","/org/freedesktop/ScreenSaver","org.freedesktop.ScreenSaver","ActiveChanged"}},
 | 
			
		||||
	{"ScreenSaver", {"org.gnome.ScreenSaver","/org/gnome/ScreenSaver","org.gnome.ScreenSaver","ActiveChanged"}},
 | 
			
		||||
};
 | 
			
		||||
} //End of constants
 | 
			
		||||
 | 
			
		||||
bool OsEventHandlerLinux::registerOsEventHandler()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	bool isRegistered {_isSuspendRegistered};
 | 
			
		||||
	if (!_isSuspendRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QDBusConnection systemBus = QDBusConnection::systemBus();
 | 
			
		||||
		if (!systemBus.isConnected())
 | 
			
		||||
		{
 | 
			
		||||
			Info(_log, "The suspend/resume feature is not supported by your system configuration");
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			QString service = dbusSignals.find("Suspend").value().service;
 | 
			
		||||
			if (systemBus.connect(service,
 | 
			
		||||
								  dbusSignals.find("Suspend").value().path,
 | 
			
		||||
								  dbusSignals.find("Suspend").value().interface,
 | 
			
		||||
								  dbusSignals.find("Suspend").value().name,
 | 
			
		||||
								  this, SLOT(suspend(bool))))
 | 
			
		||||
			{
 | 
			
		||||
				Debug(_log, "Registered for suspend/resume events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
				isRegistered = true;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				Error(_log, "Could not register for suspend/resume events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (isRegistered)
 | 
			
		||||
		{
 | 
			
		||||
			_isSuspendRegistered = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return isRegistered;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OsEventHandlerLinux::unregisterOsEventHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (_isSuspendRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QDBusConnection systemBus = QDBusConnection::systemBus();
 | 
			
		||||
		if (!systemBus.isConnected())
 | 
			
		||||
		{
 | 
			
		||||
			Info(_log, "The suspend/resume feature is not supported by your system configuration");
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			QString service = dbusSignals.find("Suspend").value().service;
 | 
			
		||||
			if (systemBus.disconnect(service,
 | 
			
		||||
								  dbusSignals.find("Suspend").value().path,
 | 
			
		||||
								  dbusSignals.find("Suspend").value().interface,
 | 
			
		||||
								  dbusSignals.find("Suspend").value().name,
 | 
			
		||||
								  this, SLOT(suspend(bool))))
 | 
			
		||||
			{
 | 
			
		||||
				Debug(_log, "Unregistered for suspend/resume events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
				_isSuspendRegistered = false;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				Error(_log, "Could not unregister for suspend/resume events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool OsEventHandlerLinux::registerLockHandler()
 | 
			
		||||
{
 | 
			
		||||
	bool isRegistered {_isLockRegistered};
 | 
			
		||||
 | 
			
		||||
	if (!_isLockRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QDBusConnection sessionBus = QDBusConnection::sessionBus();
 | 
			
		||||
		if (!sessionBus.isConnected())
 | 
			
		||||
		{
 | 
			
		||||
			Info(_log, "The lock/unlock feature is not supported by your system configuration");
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			DbusSignalsMap::const_iterator iter = dbusSignals.find("ScreenSaver");
 | 
			
		||||
			while (iter != dbusSignals.end() && iter.key() == "ScreenSaver") {
 | 
			
		||||
				QString service = iter.value().service;
 | 
			
		||||
				if (sessionBus.connect(service,
 | 
			
		||||
									   iter.value().path,
 | 
			
		||||
									   iter.value().interface,
 | 
			
		||||
									   iter.value().name,
 | 
			
		||||
									   this, SLOT(lock(bool))))
 | 
			
		||||
				{
 | 
			
		||||
					Debug(_log, "Registered for lock/unlock events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
					isRegistered = true;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					Error(_log, "Could not register for lock/unlock events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
				++iter;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (isRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		_isLockRegistered = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return isRegistered;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OsEventHandlerLinux::unregisterLockHandler()
 | 
			
		||||
{
 | 
			
		||||
	bool isUnregistered {false};
 | 
			
		||||
 | 
			
		||||
	if (_isLockRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QDBusConnection sessionBus = QDBusConnection::sessionBus();
 | 
			
		||||
		if (!sessionBus.isConnected())
 | 
			
		||||
		{
 | 
			
		||||
			Info(_log, "The lock/unlock feature is not supported by your system configuration");
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			DbusSignalsMap::const_iterator iter = dbusSignals.find("ScreenSaver");
 | 
			
		||||
			while (iter != dbusSignals.end() && iter.key() == "ScreenSaver") {
 | 
			
		||||
				QString service = iter.value().service;
 | 
			
		||||
				if (sessionBus.disconnect(service,
 | 
			
		||||
									   iter.value().path,
 | 
			
		||||
									   iter.value().interface,
 | 
			
		||||
									   iter.value().name,
 | 
			
		||||
									   this, SLOT(lock(bool))))
 | 
			
		||||
				{
 | 
			
		||||
					Debug(_log, "Unregistered for lock/unlock events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
					isUnregistered = true;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					Error(_log, "Could not unregister for lock/unlock events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
				++iter;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (isUnregistered)
 | 
			
		||||
			{
 | 
			
		||||
				_isLockRegistered = false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif // HYPERION_HAS_DBUS
 | 
			
		||||
 | 
			
		||||
#endif // __linux__
 | 
			
		||||
@@ -2,6 +2,8 @@
 | 
			
		||||
 | 
			
		||||
#include <grabber/VideoWrapper.h>
 | 
			
		||||
 | 
			
		||||
#include <events/EventHandler.h>
 | 
			
		||||
 | 
			
		||||
// qt includes
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
 | 
			
		||||
@@ -15,10 +17,15 @@ VideoWrapper::VideoWrapper()
 | 
			
		||||
{
 | 
			
		||||
	// register the image type
 | 
			
		||||
	qRegisterMetaType<Image<ColorRgb>>("Image<ColorRgb>");
 | 
			
		||||
	qRegisterMetaType<Event>("Event");
 | 
			
		||||
 | 
			
		||||
	// Handle the image in the captured thread (Media Foundation/V4L2) using a direct connection
 | 
			
		||||
	connect(&_grabber, SIGNAL(newFrame(const Image<ColorRgb>&)), this, SLOT(newFrame(const Image<ColorRgb>&)), Qt::DirectConnection);
 | 
			
		||||
	connect(&_grabber, SIGNAL(readError(const char*)), this, SLOT(readError(const char*)), Qt::DirectConnection);
 | 
			
		||||
 | 
			
		||||
	connect(&_grabber, SIGNAL(readError(const char*)), this, SLOT(readError(const char*)), Qt::DirectConnection);
 | 
			
		||||
 | 
			
		||||
	QObject::connect(EventHandler::getInstance(), &EventHandler::signalEvent, this, &VideoWrapper::handleEvent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VideoWrapper::~VideoWrapper()
 | 
			
		||||
@@ -37,15 +44,11 @@ void VideoWrapper::stop()
 | 
			
		||||
	GrabberWrapper::stop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(ENABLE_CEC) && !defined(ENABLE_MF)
 | 
			
		||||
 | 
			
		||||
void VideoWrapper::handleCecEvent(CECEvent event)
 | 
			
		||||
void VideoWrapper::handleEvent(Event event)
 | 
			
		||||
{
 | 
			
		||||
	_grabber.handleCecEvent(event);
 | 
			
		||||
	_grabber.handleEvent(event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void VideoWrapper::handleSettingsUpdate(settings::type type, const QJsonDocument& config)
 | 
			
		||||
{
 | 
			
		||||
	if(type == settings::V4L2 && _grabberName.startsWith("V4L2"))
 | 
			
		||||
@@ -100,11 +103,6 @@ void VideoWrapper::handleSettingsUpdate(settings::type type, const QJsonDocument
 | 
			
		||||
				obj["hardware_saturation"].toInt(0),
 | 
			
		||||
				obj["hardware_hue"].toInt(0));
 | 
			
		||||
 | 
			
		||||
#if defined(ENABLE_CEC) && defined(ENABLE_V4L2)
 | 
			
		||||
			// CEC Standby
 | 
			
		||||
			_grabber.setCecDetectionEnable(obj["cecDetection"].toBool(true));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			// Software frame skipping
 | 
			
		||||
			_grabber.setFpsSoftwareDecimation(obj["fpsSoftwareDecimation"].toInt(1));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -79,8 +79,7 @@ V4L2Grabber::V4L2Grabber()
 | 
			
		||||
	, _currentFrame(0)
 | 
			
		||||
	, _noSignalCounterThreshold(40)
 | 
			
		||||
	, _noSignalThresholdColor(ColorRgb{0,0,0})
 | 
			
		||||
	, _cecDetectionEnabled(true)
 | 
			
		||||
	, _cecStandbyActivated(false)
 | 
			
		||||
	, _standbyActivated(false)
 | 
			
		||||
	, _signalDetectionEnabled(true)
 | 
			
		||||
	, _noSignalDetected(false)
 | 
			
		||||
	, _noSignalCounter(0)
 | 
			
		||||
@@ -1035,7 +1034,7 @@ bool V4L2Grabber::process_image(const void *p, int size)
 | 
			
		||||
 | 
			
		||||
void V4L2Grabber::newThreadFrame(Image<ColorRgb> image)
 | 
			
		||||
{
 | 
			
		||||
	if (_cecDetectionEnabled && _cecStandbyActivated)
 | 
			
		||||
	if (_standbyActivated)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (_signalDetectionEnabled)
 | 
			
		||||
@@ -1203,16 +1202,6 @@ void V4L2Grabber::setSignalDetectionEnable(bool enable)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void V4L2Grabber::setCecDetectionEnable(bool enable)
 | 
			
		||||
{
 | 
			
		||||
	if (_cecDetectionEnabled != enable)
 | 
			
		||||
	{
 | 
			
		||||
		_cecDetectionEnabled = enable;
 | 
			
		||||
		if(_initialized)
 | 
			
		||||
			Info(_log, "%s", QSTRING_CSTR(QString("CEC detection is now %1").arg(enable ? "enabled" : "disabled")));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool V4L2Grabber::reload(bool force)
 | 
			
		||||
{
 | 
			
		||||
	if (_reload || force)
 | 
			
		||||
@@ -1231,26 +1220,24 @@ bool V4L2Grabber::reload(bool force)
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(ENABLE_CEC)
 | 
			
		||||
 | 
			
		||||
void V4L2Grabber::handleCecEvent(CECEvent event)
 | 
			
		||||
void V4L2Grabber::handleEvent(Event event)
 | 
			
		||||
{
 | 
			
		||||
	switch (event)
 | 
			
		||||
	{
 | 
			
		||||
		case CECEvent::On  :
 | 
			
		||||
			Debug(_log,"CEC on event received");
 | 
			
		||||
			_cecStandbyActivated = false;
 | 
			
		||||
			return;
 | 
			
		||||
		case CECEvent::Off :
 | 
			
		||||
			Debug(_log,"CEC off event received");
 | 
			
		||||
			_cecStandbyActivated = true;
 | 
			
		||||
			return;
 | 
			
		||||
		default: break;
 | 
			
		||||
	case Event::Suspend:
 | 
			
		||||
	case Event::Idle:
 | 
			
		||||
		Debug(_log,"Suspend/Idle event received");
 | 
			
		||||
		_standbyActivated = true;
 | 
			
		||||
		return;
 | 
			
		||||
	case Event::Resume:
 | 
			
		||||
	case Event::ResumeIdle:
 | 
			
		||||
		Debug(_log,"Resume event received");
 | 
			
		||||
		_standbyActivated = false;
 | 
			
		||||
		return;
 | 
			
		||||
	default: break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
QJsonArray V4L2Grabber::discover(const QJsonObject& params)
 | 
			
		||||
{
 | 
			
		||||
	DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData());
 | 
			
		||||
 
 | 
			
		||||
@@ -63,23 +63,28 @@ void HyperionIManager::stopAll()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HyperionIManager::suspend()
 | 
			
		||||
void HyperionIManager::handleEvent(Event event)
 | 
			
		||||
{
 | 
			
		||||
	Info(_log,"Suspend all instances and enabled components");
 | 
			
		||||
	QMap<quint8, Hyperion*> instCopy = _runningInstances;
 | 
			
		||||
	for(const auto instance : instCopy)
 | 
			
		||||
	{
 | 
			
		||||
		emit instance->suspendRequest(true);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
	Debug(_log,"%s Event [%d] received", eventToString(event), event);
 | 
			
		||||
	switch (event) {
 | 
			
		||||
	case Event::Suspend:
 | 
			
		||||
		toggleSuspend(true);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
void HyperionIManager::resume()
 | 
			
		||||
{
 | 
			
		||||
	Info(_log,"Resume all instances and enabled components");
 | 
			
		||||
	QMap<quint8, Hyperion*> instCopy = _runningInstances;
 | 
			
		||||
	for(const auto instance : instCopy)
 | 
			
		||||
	{
 | 
			
		||||
		emit instance->suspendRequest(false);
 | 
			
		||||
	case Event::Resume:
 | 
			
		||||
		toggleSuspend(false);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case Event::Idle:
 | 
			
		||||
		toggleIdle(true);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case Event::ResumeIdle:
 | 
			
		||||
		toggleIdle(false);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -91,10 +91,14 @@
 | 
			
		||||
		{
 | 
			
		||||
			"$ref": "schema-leds.json"
 | 
			
		||||
		},
 | 
			
		||||
		"systemEvents":
 | 
			
		||||
		"osEvents":
 | 
			
		||||
		{
 | 
			
		||||
			"$ref": "schema-systemEvents.json"
 | 
			
		||||
		}
 | 
			
		||||
			"$ref": "schema-osEvents.json"
 | 
			
		||||
		},
 | 
			
		||||
		"cecEvents":
 | 
			
		||||
		{
 | 
			
		||||
			"$ref": "schema-cecEvents.json"
 | 
			
		||||
		}				
 | 
			
		||||
	},
 | 
			
		||||
	"additionalProperties" : false
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
		<file alias="schema-leds.json">schema/schema-leds.json</file>
 | 
			
		||||
		<file alias="schema-instCapture.json">schema/schema-instCapture.json</file>
 | 
			
		||||
		<file alias="schema-network.json">schema/schema-network.json</file>
 | 
			
		||||
		<file alias="schema-systemEvents.json">schema/schema-systemEvents.json</file>
 | 
			
		||||
		<file alias="schema-osEvents.json">schema/schema-osEvents.json</file>
 | 
			
		||||
		<file alias="schema-cecEvents.json">schema/schema-cecEvents.json</file>
 | 
			
		||||
	</qresource>
 | 
			
		||||
</RCC>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								libsrc/hyperion/schema/schema-cecEvents.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								libsrc/hyperion/schema/schema-cecEvents.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
{
 | 
			
		||||
	"type" : "object",
 | 
			
		||||
	"required" : true,
 | 
			
		||||
	"title" : "edt_conf_cec_events_heading_title",
 | 
			
		||||
	"properties" :
 | 
			
		||||
	{
 | 
			
		||||
		"enable" :
 | 
			
		||||
		{
 | 
			
		||||
			"type" : "boolean",
 | 
			
		||||
			"required" : true,
 | 
			
		||||
			"title" : "edt_conf_general_enable_title",
 | 
			
		||||
			"default" : false,
 | 
			
		||||
			"propertyOrder" : 1
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	"additionalProperties" : false
 | 
			
		||||
}
 | 
			
		||||
@@ -1,26 +1,26 @@
 | 
			
		||||
{
 | 
			
		||||
	"type" : "object",
 | 
			
		||||
	"required" : true,
 | 
			
		||||
	"title" : "edt_conf_system_events_heading_title",
 | 
			
		||||
	"title" : "edt_conf_os_events_heading_title",
 | 
			
		||||
	"properties": {
 | 
			
		||||
		"suspendEnable": {
 | 
			
		||||
			"type": "boolean",
 | 
			
		||||
			"required": true,
 | 
			
		||||
			"title": "edt_conf_system_events_suspendEnable_title",
 | 
			
		||||
			"title": "edt_conf_os_events_suspendEnable_title",
 | 
			
		||||
			"default": true,
 | 
			
		||||
			"propertyOrder": 1
 | 
			
		||||
		},
 | 
			
		||||
		"lockEnable": {
 | 
			
		||||
			"type": "boolean",
 | 
			
		||||
			"required": true,
 | 
			
		||||
			"title": "edt_conf_system_events_lockEnable_title",
 | 
			
		||||
			"title": "edt_conf_os_events_lockEnable_title",
 | 
			
		||||
			"default": true,
 | 
			
		||||
			"propertyOrder": 2
 | 
			
		||||
		},
 | 
			
		||||
		"suspendOnLockEnable": {
 | 
			
		||||
			"type": "boolean",
 | 
			
		||||
			"required": false,
 | 
			
		||||
			"title": "edt_conf_system_events_suspendOnLockEnable_title",
 | 
			
		||||
			"title": "edt_conf_os_events_suspendOnLockEnable_title",
 | 
			
		||||
			"default": false,
 | 
			
		||||
			  "options": {
 | 
			
		||||
				"dependencies": {
 | 
			
		||||
@@ -36,6 +36,8 @@ void JsonClientConnection::readRequest()
 | 
			
		||||
		// remove message data from buffer
 | 
			
		||||
		_receiveBuffer = _receiveBuffer.mid(bytes);
 | 
			
		||||
 | 
			
		||||
		std::cout << "JsonClientConnection::readRequest | [" << _socket->peerAddress().toString().toStdString() << "] Received: [" << message.toStdString() << "]" << std::endl;
 | 
			
		||||
 | 
			
		||||
		// handle message
 | 
			
		||||
		_jsonAPI->handleMessage(message);
 | 
			
		||||
 | 
			
		||||
@@ -49,6 +51,8 @@ qint64 JsonClientConnection::sendMessage(QJsonObject message)
 | 
			
		||||
	QJsonDocument writer(message);
 | 
			
		||||
	QByteArray data = writer.toJson(QJsonDocument::Compact) + "\n";
 | 
			
		||||
 | 
			
		||||
	std::cout << "JsonClientConnection::sendMessage | [" << _socket->peerAddress().toString().toStdString() << "] Send: [" << data.constData() << "]" << std::endl;
 | 
			
		||||
 | 
			
		||||
	if (!_socket || (_socket->state() != QAbstractSocket::ConnectedState)) return 0;
 | 
			
		||||
	return _socket->write(data.data(), data.size());
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,29 +30,17 @@ if (APPLE)
 | 
			
		||||
	set_source_files_properties(${BUNDLE_RESOURCE_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
 | 
			
		||||
endif(APPLE)
 | 
			
		||||
 | 
			
		||||
if (UNIX)
 | 
			
		||||
	find_package(Qt${QT_VERSION_MAJOR} COMPONENTS DBus QUIET )
 | 
			
		||||
	if (Qt${QT_VERSION_MAJOR}DBus_FOUND)
 | 
			
		||||
		set(hyperiond_POWER_MNG_DBUS "Qt${QT_VERSION_MAJOR}::DBus")
 | 
			
		||||
	endif()
 | 
			
		||||
endif(UNIX)
 | 
			
		||||
 | 
			
		||||
add_executable(${PROJECT_NAME}
 | 
			
		||||
	console.h
 | 
			
		||||
	hyperiond.h
 | 
			
		||||
	systray.h
 | 
			
		||||
	hyperiond.cpp
 | 
			
		||||
	systray.cpp
 | 
			
		||||
	SuspendHandler.cpp
 | 
			
		||||
	main.cpp
 | 
			
		||||
	${hyperiond_WIN_RC_PATH}
 | 
			
		||||
	${BUNDLE_RESOURCE_FILES}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if (UNIX AND NOT APPLE AND Qt${QT_VERSION_MAJOR}DBus_FOUND)
 | 
			
		||||
	target_compile_definitions(${PROJECT_NAME} PUBLIC HYPERION_HAS_DBUS)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
# promote hyperiond as GUI app
 | 
			
		||||
if (WIN32)
 | 
			
		||||
	target_link_options(${PROJECT_NAME} PUBLIC /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup)
 | 
			
		||||
@@ -66,11 +54,11 @@ target_link_libraries(${PROJECT_NAME}
 | 
			
		||||
	ssdp
 | 
			
		||||
	database
 | 
			
		||||
	resources
 | 
			
		||||
	events
 | 
			
		||||
	Qt${QT_VERSION_MAJOR}::Core
 | 
			
		||||
	Qt${QT_VERSION_MAJOR}::Gui
 | 
			
		||||
	Qt${QT_VERSION_MAJOR}::Network
 | 
			
		||||
	Qt${QT_VERSION_MAJOR}::Widgets
 | 
			
		||||
	${hyperiond_POWER_MNG_DBUS}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if(ENABLE_EFFECTENGINE)
 | 
			
		||||
@@ -119,7 +107,7 @@ if (ENABLE_MF)
 | 
			
		||||
endif (ENABLE_MF)
 | 
			
		||||
 | 
			
		||||
if (ENABLE_AUDIO)
 | 
			
		||||
	target_link_libraries(hyperiond audio-grabber)
 | 
			
		||||
	target_link_libraries(${PROJECT_NAME} audio-grabber)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if (ENABLE_AMLOGIC)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,637 +0,0 @@
 | 
			
		||||
#include "SuspendHandler.h"
 | 
			
		||||
 | 
			
		||||
#include <QtGlobal>
 | 
			
		||||
#include <QJsonDocument>
 | 
			
		||||
#include <QJsonObject>
 | 
			
		||||
 | 
			
		||||
#include <hyperion/HyperionIManager.h>
 | 
			
		||||
#include <utils/Logger.h>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
#include <wtsapi32.h>
 | 
			
		||||
 | 
			
		||||
#pragma comment( lib, "wtsapi32.lib" )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
SuspendHandlerBase::SuspendHandlerBase()
 | 
			
		||||
	: _isSuspendEnabled(false)
 | 
			
		||||
	, _isLockEnabled(false)
 | 
			
		||||
	, _isSuspendApiEnabled(false)
 | 
			
		||||
	, _isIdleApiEnabled(false)
 | 
			
		||||
	, _isSuspendOnLock(false)
 | 
			
		||||
	, _isSuspendRegistered(false)
 | 
			
		||||
	, _isLockRegistered(false)
 | 
			
		||||
	, _isSuspendApiRegistered(false)
 | 
			
		||||
	, _isIdleApiRegistered(false)
 | 
			
		||||
	, _isSuspended(false)
 | 
			
		||||
	, _isIdle(false)
 | 
			
		||||
	, _isLocked (false)
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
	_log = Logger::getInstance("EVENTS");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SuspendHandlerBase::~SuspendHandlerBase()
 | 
			
		||||
{
 | 
			
		||||
	unregisterLockHandler();
 | 
			
		||||
	unregisterSuspendHandler();
 | 
			
		||||
 | 
			
		||||
	unregisterIdleApiHandler();
 | 
			
		||||
	unregisterSuspendApiHandler();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerBase::handleSettingsUpdate(settings::type type, const QJsonDocument& config)
 | 
			
		||||
{
 | 
			
		||||
	if(type == settings::SYSTEMEVENTS)
 | 
			
		||||
	{
 | 
			
		||||
		const QJsonObject& obj = config.object();
 | 
			
		||||
 | 
			
		||||
		//Suspend on lock or go into idle mode
 | 
			
		||||
		bool prevIsSuspendOnLock = _isSuspendOnLock;
 | 
			
		||||
		_isSuspendOnLock = obj["suspendOnLockEnable"].toBool(false);
 | 
			
		||||
 | 
			
		||||
		//Handle OS event related configurations
 | 
			
		||||
		_isSuspendEnabled = obj["suspendEnable"].toBool(true);
 | 
			
		||||
		if (_isSuspendEnabled)
 | 
			
		||||
		{
 | 
			
		||||
			// Listen to suspend/resume/idle events received by the OS
 | 
			
		||||
			registerSuspendHandler();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			unregisterSuspendHandler();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		_isLockEnabled = obj["lockEnable"].toBool(true);
 | 
			
		||||
		if (_isLockEnabled || _isSuspendOnLock != prevIsSuspendOnLock)
 | 
			
		||||
		{
 | 
			
		||||
			// Listen to lock/screensaver events received by the OS
 | 
			
		||||
			registerLockHandler();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			unregisterLockHandler();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//Handle API event related configurations
 | 
			
		||||
		_isSuspendApiEnabled = obj["suspendApiEnable"].toBool(true);
 | 
			
		||||
		if (_isSuspendApiEnabled)
 | 
			
		||||
		{
 | 
			
		||||
			// Listen to suspend/resume/idle events received by the OS
 | 
			
		||||
			registerSuspendApiHandler();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			unregisterSuspendApiHandler();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		_isIdleApiEnabled = obj["idleApiEnable"].toBool(true);
 | 
			
		||||
		if (_isIdleApiEnabled)
 | 
			
		||||
		{
 | 
			
		||||
			// Listen to lock/screensaver events received by the OS
 | 
			
		||||
			registerIdleApiHandler();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			unregisterIdleApiHandler();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SuspendHandlerBase::registerSuspendHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (!_isSuspendRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QObject::connect(this, &SuspendHandlerBase::suspendEvent, HyperionIManager::getInstance(), &HyperionIManager::suspend);
 | 
			
		||||
		QObject::connect(this, &SuspendHandlerBase::resumeEvent, HyperionIManager::getInstance(), &HyperionIManager::resume);
 | 
			
		||||
		Info(_log, "Registered for suspend/resume events.");
 | 
			
		||||
		_isSuspendRegistered = true;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerBase::unregisterSuspendHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (_isSuspendRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QObject::disconnect(this, &SuspendHandlerBase::suspendEvent, HyperionIManager::getInstance(), &HyperionIManager::suspend);
 | 
			
		||||
		QObject::disconnect(this, &SuspendHandlerBase::resumeEvent, HyperionIManager::getInstance(), &HyperionIManager::resume);
 | 
			
		||||
		Info(_log, "Unregistered for suspend/resume events.");
 | 
			
		||||
		_isSuspendRegistered = false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SuspendHandlerBase::registerLockHandler()
 | 
			
		||||
{
 | 
			
		||||
	QObject::disconnect(this, &SuspendHandlerBase::lockedEvent,nullptr, nullptr);
 | 
			
		||||
	if (_isSuspendOnLock)
 | 
			
		||||
	{
 | 
			
		||||
		QObject::connect(this, &SuspendHandlerBase::lockedEvent, HyperionIManager::getInstance(), &HyperionIManager::toggleSuspend);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		QObject::connect(this, &SuspendHandlerBase::lockedEvent, HyperionIManager::getInstance(), &HyperionIManager::toggleIdle);
 | 
			
		||||
	}
 | 
			
		||||
	QObject::connect(this, &SuspendHandlerBase::idleEvent, HyperionIManager::getInstance(), &HyperionIManager::toggleIdle);
 | 
			
		||||
	Info(_log, "Registered for lock/unlock events. %s on lock event.", _isSuspendOnLock ? "Suspend" : "Idle");
 | 
			
		||||
	_isLockRegistered = true;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerBase::unregisterLockHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (_isLockRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QObject::disconnect(this, &SuspendHandlerBase::lockedEvent, HyperionIManager::getInstance(), &HyperionIManager::toggleSuspend);
 | 
			
		||||
		QObject::disconnect(this, &SuspendHandlerBase::lockedEvent, HyperionIManager::getInstance(), &HyperionIManager::toggleIdle);
 | 
			
		||||
		QObject::disconnect(this, &SuspendHandlerBase::idleEvent, HyperionIManager::getInstance(), &HyperionIManager::toggleIdle);
 | 
			
		||||
		Info(_log, "Unregistered for lock/unlock events.");
 | 
			
		||||
		_isLockRegistered = false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool SuspendHandlerBase::registerSuspendApiHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (!_isSuspendApiRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QObject::connect(HyperionIManager::getInstance(), &HyperionIManager::triggerSuspend, this, QOverload<bool>::of(&SuspendHandler::suspend));
 | 
			
		||||
		QObject::connect(HyperionIManager::getInstance(), &HyperionIManager::triggerToggleSuspend, this, &SuspendHandler::toggleSuspend);
 | 
			
		||||
		Info(_log, "Registered for suspend/resume API events.");
 | 
			
		||||
		_isSuspendApiRegistered = true;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerBase::unregisterSuspendApiHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (_isSuspendApiRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QObject::disconnect(HyperionIManager::getInstance(), &HyperionIManager::triggerSuspend, this, QOverload<bool>::of(&SuspendHandler::suspend));
 | 
			
		||||
		QObject::disconnect(HyperionIManager::getInstance(), &HyperionIManager::triggerToggleSuspend, this, &SuspendHandler::toggleSuspend);
 | 
			
		||||
		Info(_log, "Unregistered for suspend/resume API events.");
 | 
			
		||||
		_isSuspendApiRegistered = false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SuspendHandlerBase::registerIdleApiHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (!_isIdleApiRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QObject::connect(HyperionIManager::getInstance(), &HyperionIManager::triggerIdle, this, &SuspendHandler::idle);
 | 
			
		||||
		QObject::connect(HyperionIManager::getInstance(), &HyperionIManager::triggerToggleIdle, this, &SuspendHandler::toggleIdle);
 | 
			
		||||
		Info(_log, "Registered for idle API events.");
 | 
			
		||||
		_isIdleApiRegistered = true;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerBase::unregisterIdleApiHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (_isIdleApiRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QObject::disconnect(HyperionIManager::getInstance(), &HyperionIManager::triggerIdle, this, &SuspendHandler::idle);
 | 
			
		||||
		QObject::disconnect(HyperionIManager::getInstance(), &HyperionIManager::triggerToggleIdle, this, &SuspendHandler::toggleIdle);
 | 
			
		||||
		Info(_log, "Unregistered for idle API events.");
 | 
			
		||||
		_isIdleApiRegistered = false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerBase::suspend()
 | 
			
		||||
{
 | 
			
		||||
	suspend(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerBase::suspend(bool sleep)
 | 
			
		||||
{
 | 
			
		||||
	if (sleep)
 | 
			
		||||
	{
 | 
			
		||||
		if (!_isSuspended)
 | 
			
		||||
		{
 | 
			
		||||
			_isSuspended = true;
 | 
			
		||||
			Info(_log, "Suspend event received - Hyperion is going to sleep");
 | 
			
		||||
			emit suspendEvent();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			Debug(_log, "Suspend event ignored - already suspended");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		if (_isSuspended || _isIdle)
 | 
			
		||||
		{
 | 
			
		||||
			Info(_log, "Resume event received - Hyperion is going into working mode");
 | 
			
		||||
			emit resumeEvent();
 | 
			
		||||
			_isSuspended = false;
 | 
			
		||||
			_isIdle = false;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			Debug(_log, "Resume event ignored - not in suspend nor idle mode");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerBase::resume()
 | 
			
		||||
{
 | 
			
		||||
	suspend(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerBase::toggleSuspend()
 | 
			
		||||
{
 | 
			
		||||
	Debug(_log, "Toggle suspend event received");
 | 
			
		||||
	if (!_isSuspended)
 | 
			
		||||
	{
 | 
			
		||||
		suspend(true);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		suspend(false);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerBase::idle(bool isIdle)
 | 
			
		||||
{
 | 
			
		||||
	if (!_isSuspended)
 | 
			
		||||
	{
 | 
			
		||||
		if (isIdle)
 | 
			
		||||
		{
 | 
			
		||||
			if (!_isIdle)
 | 
			
		||||
			{
 | 
			
		||||
				_isIdle = true;
 | 
			
		||||
				Info(_log, "Idle event received");
 | 
			
		||||
				emit idleEvent(isIdle);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			if (_isIdle)
 | 
			
		||||
			{
 | 
			
		||||
				Info(_log, "Resume from idle event recevied");
 | 
			
		||||
				emit idleEvent(isIdle);
 | 
			
		||||
				_isIdle = false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		Debug(_log, "Idle event ignored - Hyperion is suspended");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerBase::toggleIdle()
 | 
			
		||||
{
 | 
			
		||||
	Debug(_log, "Toggle idle event received");
 | 
			
		||||
	if (!_isIdle)
 | 
			
		||||
	{
 | 
			
		||||
		idle(true);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		idle(false);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerBase::lock(bool isLocked)
 | 
			
		||||
{
 | 
			
		||||
	if (!_isSuspended)
 | 
			
		||||
	{
 | 
			
		||||
		if (isLocked)
 | 
			
		||||
		{
 | 
			
		||||
			if (!_isLocked)
 | 
			
		||||
			{
 | 
			
		||||
				_isLocked = true;
 | 
			
		||||
				Info(_log, "Screen lock event received");
 | 
			
		||||
				emit lockedEvent(isLocked);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			if (_isLocked)
 | 
			
		||||
			{
 | 
			
		||||
				Info(_log, "Screen unlock event received");
 | 
			
		||||
				emit lockedEvent(isLocked);
 | 
			
		||||
				_isLocked = false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		Debug(_log, "Screen lock event ignored - Hyperion is suspended");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
 | 
			
		||||
SuspendHandlerWindows::SuspendHandlerWindows()
 | 
			
		||||
	: _notifyHandle(NULL)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SuspendHandlerWindows::~SuspendHandlerWindows()
 | 
			
		||||
{
 | 
			
		||||
	unregisterLockHandler();
 | 
			
		||||
	unregisterSuspendHandler();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
 | 
			
		||||
bool SuspendHandlerWindows::nativeEventFilter(const QByteArray& eventType, void* message, qintptr* /*result*/)
 | 
			
		||||
#else
 | 
			
		||||
bool SuspendHandlerWindows::nativeEventFilter(const QByteArray& eventType, void* message, long int* /*result*/)
 | 
			
		||||
#endif
 | 
			
		||||
{
 | 
			
		||||
	MSG* msg = static_cast<MSG*>(message);
 | 
			
		||||
 | 
			
		||||
	switch (msg->message)
 | 
			
		||||
	{
 | 
			
		||||
	case WM_WTSSESSION_CHANGE:
 | 
			
		||||
		switch (msg->wParam)
 | 
			
		||||
		{
 | 
			
		||||
		case WTS_SESSION_LOCK:
 | 
			
		||||
			emit lock(true);
 | 
			
		||||
			return true;
 | 
			
		||||
			break;
 | 
			
		||||
		case WTS_SESSION_UNLOCK:
 | 
			
		||||
			emit lock(false);
 | 
			
		||||
			return true;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case WM_POWERBROADCAST:
 | 
			
		||||
		switch (msg->wParam)
 | 
			
		||||
		{
 | 
			
		||||
		case PBT_APMRESUMESUSPEND:
 | 
			
		||||
			emit suspend(false);
 | 
			
		||||
			return true;
 | 
			
		||||
			break;
 | 
			
		||||
		case PBT_APMSUSPEND:
 | 
			
		||||
			emit suspend(true);
 | 
			
		||||
			return true;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SuspendHandlerWindows::registerSuspendHandler()
 | 
			
		||||
{
 | 
			
		||||
	bool isRegistered{ _isSuspendRegistered };
 | 
			
		||||
	if (!_isSuspendRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		auto handle = reinterpret_cast<HWND> (_widget.winId());
 | 
			
		||||
		_notifyHandle = RegisterSuspendResumeNotification(handle, DEVICE_NOTIFY_WINDOW_HANDLE);
 | 
			
		||||
		if (_notifyHandle != NULL)
 | 
			
		||||
		{
 | 
			
		||||
			QCoreApplication::instance()->installNativeEventFilter(this);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			Error(_log, "Could not register for suspend/resume events!");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (isRegistered)
 | 
			
		||||
		{
 | 
			
		||||
			isRegistered = SuspendHandlerBase::registerSuspendHandler();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return isRegistered;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerWindows::unregisterSuspendHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (_isSuspendRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		if (_notifyHandle != NULL)
 | 
			
		||||
		{
 | 
			
		||||
			QCoreApplication::instance()->removeNativeEventFilter(this);
 | 
			
		||||
			UnregisterSuspendResumeNotification(_notifyHandle);
 | 
			
		||||
		}
 | 
			
		||||
		_notifyHandle = NULL;
 | 
			
		||||
		SuspendHandlerBase::unregisterSuspendHandler();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SuspendHandlerWindows::registerLockHandler()
 | 
			
		||||
{
 | 
			
		||||
	bool isRegistered{ _isLockRegistered };
 | 
			
		||||
	if (!_isLockRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		auto handle = reinterpret_cast<HWND> (_widget.winId());
 | 
			
		||||
		if (WTSRegisterSessionNotification(handle, NOTIFY_FOR_THIS_SESSION))
 | 
			
		||||
		{
 | 
			
		||||
			isRegistered = true;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			Error(_log, "Could not register for lock/unlock events!");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (isRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		isRegistered = SuspendHandlerBase::registerLockHandler();
 | 
			
		||||
	}
 | 
			
		||||
	return isRegistered;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerWindows::unregisterLockHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (_isLockRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		auto handle = reinterpret_cast<HWND> (_widget.winId());
 | 
			
		||||
		WTSUnRegisterSessionNotification(handle);
 | 
			
		||||
		SuspendHandlerBase::unregisterLockHandler();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__linux__) && defined(HYPERION_HAS_DBUS)
 | 
			
		||||
#include <QDBusConnection>
 | 
			
		||||
 | 
			
		||||
struct dBusSignals
 | 
			
		||||
{
 | 
			
		||||
	QString service;
 | 
			
		||||
	QString path;
 | 
			
		||||
	QString interface;
 | 
			
		||||
	QString name;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef QMultiMap<QString, dBusSignals> DbusSignalsMap;
 | 
			
		||||
 | 
			
		||||
// Constants
 | 
			
		||||
namespace {
 | 
			
		||||
const DbusSignalsMap dbusSignals = {
 | 
			
		||||
	//system signals
 | 
			
		||||
	{"Suspend", {"org.freedesktop.login1","/org/freedesktop/login1","org.freedesktop.login1.Manager","PrepareForSleep"}},
 | 
			
		||||
 | 
			
		||||
	//Session signals
 | 
			
		||||
	{"ScreenSaver", {"org.freedesktop.ScreenSaver","/org/freedesktop/ScreenSaver","org.freedesktop.ScreenSaver","ActiveChanged"}},
 | 
			
		||||
	{"ScreenSaver", {"org.gnome.ScreenSaver","/org/gnome/ScreenSaver","org.gnome.ScreenSaver","ActiveChanged"}},
 | 
			
		||||
};
 | 
			
		||||
} //End of constants
 | 
			
		||||
 | 
			
		||||
SuspendHandlerLinux::SuspendHandlerLinux()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SuspendHandlerLinux::registerSuspendHandler()
 | 
			
		||||
{
 | 
			
		||||
	bool isRegistered {_isSuspendRegistered};
 | 
			
		||||
	if (!_isSuspendRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QDBusConnection systemBus = QDBusConnection::systemBus();
 | 
			
		||||
		if (!systemBus.isConnected())
 | 
			
		||||
		{
 | 
			
		||||
			Info(_log, "The suspend/resume feature is not supported by your system configuration");
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			QString service = dbusSignals.find("Suspend").value().service;
 | 
			
		||||
			if (systemBus.connect(service,
 | 
			
		||||
								  dbusSignals.find("Suspend").value().path,
 | 
			
		||||
								  dbusSignals.find("Suspend").value().interface,
 | 
			
		||||
								  dbusSignals.find("Suspend").value().name,
 | 
			
		||||
								  this, SLOT(suspend(bool))))
 | 
			
		||||
			{
 | 
			
		||||
				Debug(_log, "Registered for suspend/resume events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
				isRegistered = true;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				Error(_log, "Could not register for suspend/resume events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (isRegistered)
 | 
			
		||||
		{
 | 
			
		||||
			isRegistered = SuspendHandlerBase::registerSuspendHandler();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return isRegistered;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerLinux::unregisterSuspendHandler()
 | 
			
		||||
{
 | 
			
		||||
	if (_isSuspendRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QDBusConnection systemBus = QDBusConnection::systemBus();
 | 
			
		||||
		if (!systemBus.isConnected())
 | 
			
		||||
		{
 | 
			
		||||
			Info(_log, "The suspend/resume feature is not supported by your system configuration");
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			QString service = dbusSignals.find("Suspend").value().service;
 | 
			
		||||
			if (systemBus.disconnect(service,
 | 
			
		||||
								  dbusSignals.find("Suspend").value().path,
 | 
			
		||||
								  dbusSignals.find("Suspend").value().interface,
 | 
			
		||||
								  dbusSignals.find("Suspend").value().name,
 | 
			
		||||
								  this, SLOT(suspend(bool))))
 | 
			
		||||
			{
 | 
			
		||||
				Debug(_log, "Unregistered for suspend/resume events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
				SuspendHandlerBase::unregisterSuspendHandler();
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				Error(_log, "Could not unregister for suspend/resume events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SuspendHandlerLinux::registerLockHandler()
 | 
			
		||||
{
 | 
			
		||||
	bool isRegistered {_isLockRegistered};
 | 
			
		||||
 | 
			
		||||
	if (!_isLockRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QDBusConnection sessionBus = QDBusConnection::sessionBus();
 | 
			
		||||
		if (!sessionBus.isConnected())
 | 
			
		||||
		{
 | 
			
		||||
			Info(_log, "The lock/unlock feature is not supported by your system configuration");
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			DbusSignalsMap::const_iterator iter = dbusSignals.find("ScreenSaver");
 | 
			
		||||
			while (iter != dbusSignals.end() && iter.key() == "ScreenSaver") {
 | 
			
		||||
				QString service = iter.value().service;
 | 
			
		||||
				if (sessionBus.connect(service,
 | 
			
		||||
									   iter.value().path,
 | 
			
		||||
									   iter.value().interface,
 | 
			
		||||
									   iter.value().name,
 | 
			
		||||
									   this, SLOT(lock(bool))))
 | 
			
		||||
				{
 | 
			
		||||
					Debug(_log, "Registered for lock/unlock events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
					isRegistered = true;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					Error(_log, "Could not register for lock/unlock events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
				++iter;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (isRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		isRegistered = SuspendHandlerBase::registerLockHandler();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return isRegistered;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SuspendHandlerLinux::unregisterLockHandler()
 | 
			
		||||
{
 | 
			
		||||
	bool isUnregistered {false};
 | 
			
		||||
 | 
			
		||||
	if (_isLockRegistered)
 | 
			
		||||
	{
 | 
			
		||||
		QDBusConnection sessionBus = QDBusConnection::sessionBus();
 | 
			
		||||
		if (!sessionBus.isConnected())
 | 
			
		||||
		{
 | 
			
		||||
			Info(_log, "The lock/unlock feature is not supported by your system configuration");
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			DbusSignalsMap::const_iterator iter = dbusSignals.find("ScreenSaver");
 | 
			
		||||
			while (iter != dbusSignals.end() && iter.key() == "ScreenSaver") {
 | 
			
		||||
				QString service = iter.value().service;
 | 
			
		||||
				if (sessionBus.disconnect(service,
 | 
			
		||||
									   iter.value().path,
 | 
			
		||||
									   iter.value().interface,
 | 
			
		||||
									   iter.value().name,
 | 
			
		||||
									   this, SLOT(lock(bool))))
 | 
			
		||||
				{
 | 
			
		||||
					Debug(_log, "Unregistered for lock/unlock events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
					isUnregistered = true;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					Error(_log, "Could not unregister for lock/unlock events via service: %s", QSTRING_CSTR(service));
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
				++iter;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (isUnregistered)
 | 
			
		||||
			{
 | 
			
		||||
				SuspendHandlerBase::unregisterLockHandler();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,127 +0,0 @@
 | 
			
		||||
#ifndef SUSPENDHANDLER_H
 | 
			
		||||
#define SUSPENDHANDLER_H
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QJsonDocument>
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
#include <QAbstractNativeEventFilter>
 | 
			
		||||
#include <QAbstractEventDispatcher>
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <utils/settings.h>
 | 
			
		||||
 | 
			
		||||
class Logger;
 | 
			
		||||
 | 
			
		||||
class SuspendHandlerBase : public QObject {
 | 
			
		||||
	Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	SuspendHandlerBase();
 | 
			
		||||
	~SuspendHandlerBase() override;
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
 | 
			
		||||
	void suspend(bool sleep);
 | 
			
		||||
 | 
			
		||||
	void suspend();
 | 
			
		||||
	void resume();
 | 
			
		||||
	void toggleSuspend();
 | 
			
		||||
 | 
			
		||||
	void idle(bool isIdle);
 | 
			
		||||
	void toggleIdle();
 | 
			
		||||
 | 
			
		||||
	void lock(bool isLocked);
 | 
			
		||||
 | 
			
		||||
	virtual void handleSettingsUpdate(settings::type type, const QJsonDocument& config);
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
 | 
			
		||||
	void suspendEvent();
 | 
			
		||||
	void resumeEvent();
 | 
			
		||||
	void lockedEvent(bool);
 | 
			
		||||
	void idleEvent(bool);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
	virtual bool registerSuspendHandler();
 | 
			
		||||
	virtual void unregisterSuspendHandler();
 | 
			
		||||
	virtual bool registerLockHandler();
 | 
			
		||||
	virtual void unregisterLockHandler();
 | 
			
		||||
 | 
			
		||||
	virtual bool registerSuspendApiHandler();
 | 
			
		||||
	virtual void unregisterSuspendApiHandler();
 | 
			
		||||
	virtual bool registerIdleApiHandler();
 | 
			
		||||
	virtual void unregisterIdleApiHandler();
 | 
			
		||||
 | 
			
		||||
	bool _isSuspendEnabled;
 | 
			
		||||
	bool _isLockEnabled;
 | 
			
		||||
	bool _isSuspendApiEnabled;
 | 
			
		||||
	bool _isIdleApiEnabled;
 | 
			
		||||
	bool _isSuspendOnLock;
 | 
			
		||||
 | 
			
		||||
	bool _isSuspendRegistered;
 | 
			
		||||
	bool _isLockRegistered;
 | 
			
		||||
	bool _isSuspendApiRegistered;
 | 
			
		||||
	bool _isIdleApiRegistered;
 | 
			
		||||
 | 
			
		||||
	Logger * _log {};
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
	bool _isSuspended;
 | 
			
		||||
	bool _isIdle;
 | 
			
		||||
	bool _isLocked;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
 | 
			
		||||
class SuspendHandlerWindows : public SuspendHandlerBase, public QAbstractNativeEventFilter {
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	SuspendHandlerWindows();
 | 
			
		||||
	~SuspendHandlerWindows() override;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
 | 
			
		||||
	bool nativeEventFilter(const QByteArray& eventType, void* message, qintptr* result) override;
 | 
			
		||||
#else
 | 
			
		||||
	bool nativeEventFilter(const QByteArray& eventType, void* message, long int* result) override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
	bool registerSuspendHandler() override;
 | 
			
		||||
	void unregisterSuspendHandler() override;
 | 
			
		||||
	bool registerLockHandler() override;
 | 
			
		||||
	void unregisterLockHandler() override;
 | 
			
		||||
 | 
			
		||||
	QWidget			_widget;
 | 
			
		||||
	HPOWERNOTIFY	_notifyHandle;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using SuspendHandler = SuspendHandlerWindows;
 | 
			
		||||
 | 
			
		||||
#elif defined(__linux__) && defined(HYPERION_HAS_DBUS)
 | 
			
		||||
 | 
			
		||||
class SuspendHandlerLinux : public SuspendHandlerBase {
 | 
			
		||||
	Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	SuspendHandlerLinux();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	bool registerSuspendHandler() override;
 | 
			
		||||
	void unregisterSuspendHandler() override;
 | 
			
		||||
	bool registerLockHandler() override;
 | 
			
		||||
	void unregisterLockHandler() override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using SuspendHandler = SuspendHandlerLinux;
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
using SuspendHandler = SuspendHandlerBase;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // SUSPENDHANDLER_H
 | 
			
		||||
@@ -97,7 +97,8 @@ HyperionDaemon::HyperionDaemon(const QString& rootPath, QObject* parent, bool lo
 | 
			
		||||
#ifdef ENABLE_CEC
 | 
			
		||||
	, _cecHandler(nullptr)
 | 
			
		||||
#endif
 | 
			
		||||
	, _suspendHandler(nullptr)
 | 
			
		||||
	, _eventHandler(nullptr)
 | 
			
		||||
	, _osEventHandler(nullptr)
 | 
			
		||||
	, _currVideoMode(VideoMode::VIDEO_2D)
 | 
			
		||||
{
 | 
			
		||||
	HyperionDaemon::daemon = this;
 | 
			
		||||
@@ -119,8 +120,6 @@ HyperionDaemon::HyperionDaemon(const QString& rootPath, QObject* parent, bool lo
 | 
			
		||||
		handleSettingsUpdate(settings::LOGGER, getSetting(settings::LOGGER));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	createCecHandler();
 | 
			
		||||
 | 
			
		||||
	//Create MdnsBrowser singleton in main tread to ensure thread affinity during destruction
 | 
			
		||||
#ifdef ENABLE_MDNS
 | 
			
		||||
	MdnsBrowser::getInstance();
 | 
			
		||||
@@ -178,7 +177,7 @@ HyperionDaemon::HyperionDaemon(const QString& rootPath, QObject* parent, bool lo
 | 
			
		||||
	startNetworkServices();
 | 
			
		||||
 | 
			
		||||
	// init events services
 | 
			
		||||
	handleSettingsUpdate(settings::SYSTEMEVENTS, getSetting(settings::SYSTEMEVENTS));
 | 
			
		||||
	handleSettingsUpdate(settings::OSEVENTS, getSetting(settings::OSEVENTS));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HyperionDaemon::~HyperionDaemon()
 | 
			
		||||
@@ -234,7 +233,10 @@ void HyperionDaemon::handleInstanceStateChange(InstanceState state, quint8 insta
 | 
			
		||||
			connect(_sslWebserver, &WebServer::publishService, _mDNSProvider, &MdnsProvider::publishService);
 | 
			
		||||
#endif
 | 
			
		||||
			sslWsThread->start();
 | 
			
		||||
 | 
			
		||||
			//startCecHandler();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case InstanceState::H_STOPPED:
 | 
			
		||||
@@ -263,6 +265,8 @@ void HyperionDaemon::freeObjects()
 | 
			
		||||
{
 | 
			
		||||
	Debug(_log, "Cleaning up Hyperion before quit.");
 | 
			
		||||
 | 
			
		||||
	stopCecHandler();
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_MDNS
 | 
			
		||||
	if (_mDNSProvider != nullptr)
 | 
			
		||||
	{
 | 
			
		||||
@@ -333,19 +337,7 @@ void HyperionDaemon::freeObjects()
 | 
			
		||||
		_sslWebserver = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_CEC
 | 
			
		||||
	if (_cecHandler != nullptr)
 | 
			
		||||
	{
 | 
			
		||||
		auto cecHandlerThread = _cecHandler->thread();
 | 
			
		||||
		cecHandlerThread->quit();
 | 
			
		||||
		cecHandlerThread->wait();
 | 
			
		||||
		delete cecHandlerThread;
 | 
			
		||||
		delete _cecHandler;
 | 
			
		||||
		_cecHandler = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	delete _suspendHandler;
 | 
			
		||||
	delete _osEventHandler;
 | 
			
		||||
 | 
			
		||||
	// stop Hyperions (non blocking)
 | 
			
		||||
	_instanceManager->stopAll();
 | 
			
		||||
@@ -693,19 +685,6 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
 | 
			
		||||
	}
 | 
			
		||||
	else if (settingsType == settings::V4L2)
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_CEC
 | 
			
		||||
		const QJsonObject& grabberConfig = config.object();
 | 
			
		||||
		if (_cecHandler != nullptr && grabberConfig["cecDetection"].toBool(false))
 | 
			
		||||
		{
 | 
			
		||||
			QMetaObject::invokeMethod(_cecHandler, "start", Qt::QueuedConnection);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			QMetaObject::invokeMethod(_cecHandler, "stop", Qt::QueuedConnection);
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(ENABLE_V4L2) || defined(ENABLE_MF)
 | 
			
		||||
		if (_videoGrabber == nullptr)
 | 
			
		||||
		{
 | 
			
		||||
@@ -743,18 +722,28 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
 | 
			
		||||
		Debug(_log, "Audio capture not supported on this platform");
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
	else if (settingsType == settings::SYSTEMEVENTS)
 | 
			
		||||
	else if (settingsType == settings::OSEVENTS)
 | 
			
		||||
	{
 | 
			
		||||
		// Create suspend handler
 | 
			
		||||
		if (_suspendHandler == nullptr)
 | 
			
		||||
		if (_eventHandler == nullptr)
 | 
			
		||||
		{
 | 
			
		||||
			_suspendHandler = new SuspendHandler();
 | 
			
		||||
			_suspendHandler->handleSettingsUpdate(settings::SYSTEMEVENTS, getSetting(settings::SYSTEMEVENTS));
 | 
			
		||||
 | 
			
		||||
			connect(this, &HyperionDaemon::settingsChanged, _suspendHandler, &SuspendHandler::handleSettingsUpdate);
 | 
			
		||||
 | 
			
		||||
			Debug(_log, "SuspendHandler created");
 | 
			
		||||
			_eventHandler = EventHandler::getInstance();
 | 
			
		||||
			Debug(_log, "Hyperion event handler created");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Create suspend handler
 | 
			
		||||
		if (_osEventHandler == nullptr)
 | 
			
		||||
		{
 | 
			
		||||
			_osEventHandler = new OsEventHandler();
 | 
			
		||||
			_osEventHandler->handleSettingsUpdate(settings::OSEVENTS, getSetting(settings::OSEVENTS));
 | 
			
		||||
 | 
			
		||||
			connect(this, &HyperionDaemon::settingsChanged, _osEventHandler, &OsEventHandler::handleSettingsUpdate);
 | 
			
		||||
 | 
			
		||||
			Debug(_log, "Operating System event handler created");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else if (settingsType == settings::CECEVENTS)
 | 
			
		||||
	{
 | 
			
		||||
		startCecHandler();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -929,26 +918,47 @@ void HyperionDaemon::createGrabberOsx(const QJsonObject& grabberConfig)
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HyperionDaemon::createCecHandler()
 | 
			
		||||
void HyperionDaemon::startCecHandler()
 | 
			
		||||
{
 | 
			
		||||
#if defined(ENABLE_V4L2) && defined(ENABLE_CEC)
 | 
			
		||||
	_cecHandler = new CECHandler;
 | 
			
		||||
#if defined(ENABLE_CEC)
 | 
			
		||||
	if (_cecHandler == nullptr)
 | 
			
		||||
	{
 | 
			
		||||
		_cecHandler = new CECHandler;
 | 
			
		||||
 | 
			
		||||
	QThread* thread = new QThread(this);
 | 
			
		||||
	thread->setObjectName("CECThread");
 | 
			
		||||
	_cecHandler->moveToThread(thread);
 | 
			
		||||
	thread->start();
 | 
			
		||||
		QThread* cecHandlerThread = new QThread(this);
 | 
			
		||||
		cecHandlerThread->setObjectName("CECThread");
 | 
			
		||||
		_cecHandler->moveToThread(cecHandlerThread);
 | 
			
		||||
 | 
			
		||||
	connect(_cecHandler, &CECHandler::cecEvent, [&](CECEvent event) {
 | 
			
		||||
		if (_videoGrabber != nullptr)
 | 
			
		||||
		{
 | 
			
		||||
			_videoGrabber->handleCecEvent(event);
 | 
			
		||||
		}
 | 
			
		||||
		});
 | 
			
		||||
		connect(cecHandlerThread, &QThread::started, _cecHandler, &CECHandler::start);
 | 
			
		||||
		connect(cecHandlerThread, &QThread::finished, _cecHandler, &CECHandler::stop);
 | 
			
		||||
 | 
			
		||||
	Info(_log, "CEC handler created");
 | 
			
		||||
		cecHandlerThread->start();
 | 
			
		||||
 | 
			
		||||
		_cecHandler->handleSettingsUpdate(settings::CECEVENTS, getSetting(settings::CECEVENTS));
 | 
			
		||||
		connect(this, &HyperionDaemon::settingsChanged, _cecHandler, &CECHandler::handleSettingsUpdate);
 | 
			
		||||
 | 
			
		||||
		Info(_log, "CEC event handler created");
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
	Debug(_log, "The CEC handler is not supported on this platform");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HyperionDaemon::stopCecHandler()
 | 
			
		||||
{
 | 
			
		||||
#if defined(ENABLE_CEC)
 | 
			
		||||
	if (_cecHandler != nullptr)
 | 
			
		||||
	{
 | 
			
		||||
		disconnect(_cecHandler, &CECHandler::signalEvent, _eventHandler, &EventHandler::handleEvent);
 | 
			
		||||
 | 
			
		||||
		auto cecHandlerThread = _cecHandler->thread();
 | 
			
		||||
		cecHandlerThread->quit();
 | 
			
		||||
		cecHandlerThread->wait();
 | 
			
		||||
		delete cecHandlerThread;
 | 
			
		||||
		delete _cecHandler;
 | 
			
		||||
		_cecHandler = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
	Info(_log, "CEC handler stopped");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -75,7 +75,8 @@
 | 
			
		||||
#include <utils/settings.h>
 | 
			
		||||
#include <utils/Components.h>
 | 
			
		||||
 | 
			
		||||
#include "SuspendHandler.h"
 | 
			
		||||
#include <events/EventHandler.h>
 | 
			
		||||
#include <events/OsEventHandler.h>
 | 
			
		||||
 | 
			
		||||
class HyperionIManager;
 | 
			
		||||
class SysTray;
 | 
			
		||||
@@ -103,18 +104,13 @@ class HyperionDaemon : public QObject
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	HyperionDaemon(const QString& rootPath, QObject *parent, bool logLvlOverwrite, bool readonlyMode = false);
 | 
			
		||||
	~HyperionDaemon();
 | 
			
		||||
	~HyperionDaemon() override;
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief Get webserver pointer (systray)
 | 
			
		||||
	///
 | 
			
		||||
	WebServer *getWebServerInstance() { return _webserver; }
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief Get suspense handler pointer
 | 
			
		||||
	///
 | 
			
		||||
	SuspendHandler* getSuspendHandlerInstance() { return _suspendHandler; }
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief Get the current videoMode
 | 
			
		||||
	///
 | 
			
		||||
@@ -185,10 +181,12 @@ private:
 | 
			
		||||
	void createGrabberX11(const QJsonObject & grabberConfig);
 | 
			
		||||
	void createGrabberXcb(const QJsonObject & grabberConfig);
 | 
			
		||||
	void createGrabberQt(const QJsonObject & grabberConfig);
 | 
			
		||||
	void createCecHandler();
 | 
			
		||||
	void createGrabberDx(const QJsonObject & grabberConfig);
 | 
			
		||||
	void createGrabberAudio(const QJsonObject & grabberConfig);
 | 
			
		||||
 | 
			
		||||
	void startCecHandler();
 | 
			
		||||
	void stopCecHandler();
 | 
			
		||||
 | 
			
		||||
	Logger*                    _log;
 | 
			
		||||
	HyperionIManager*          _instanceManager;
 | 
			
		||||
	AuthManager*               _authManager;
 | 
			
		||||
@@ -216,7 +214,8 @@ private:
 | 
			
		||||
	#ifdef ENABLE_CEC
 | 
			
		||||
	CECHandler*                _cecHandler;
 | 
			
		||||
	#endif
 | 
			
		||||
	SuspendHandler*            _suspendHandler;
 | 
			
		||||
	EventHandler*              _eventHandler;
 | 
			
		||||
	OsEventHandler*            _osEventHandler;
 | 
			
		||||
 | 
			
		||||
	#if defined(ENABLE_FLATBUF_SERVER)
 | 
			
		||||
	FlatBufferServer*          _flatBufferServer;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <csignal>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
@@ -46,40 +45,12 @@
 | 
			
		||||
 | 
			
		||||
#include "hyperiond.h"
 | 
			
		||||
#include "systray.h"
 | 
			
		||||
#include "SuspendHandler.h"
 | 
			
		||||
#include <events/EventHandler.h>
 | 
			
		||||
 | 
			
		||||
using namespace commandline;
 | 
			
		||||
 | 
			
		||||
#define PERM0664 (QFileDevice::ReadOwner | QFileDevice::ReadGroup | QFileDevice::ReadOther | QFileDevice::WriteOwner | QFileDevice::WriteGroup)
 | 
			
		||||
 | 
			
		||||
#ifndef _WIN32
 | 
			
		||||
void signal_handler(int signum)
 | 
			
		||||
{
 | 
			
		||||
	HyperionDaemon* hyperiond = HyperionDaemon::getInstance();
 | 
			
		||||
	SuspendHandler* suspendHandler = hyperiond->getSuspendHandlerInstance();
 | 
			
		||||
 | 
			
		||||
	if (signum == SIGCHLD)
 | 
			
		||||
	{
 | 
			
		||||
		// only quit when a registered child process is gone
 | 
			
		||||
		// currently this feature is not active ...
 | 
			
		||||
	}
 | 
			
		||||
	else if (signum == SIGUSR1)
 | 
			
		||||
	{
 | 
			
		||||
		if (suspendHandler != nullptr)
 | 
			
		||||
		{
 | 
			
		||||
			suspendHandler->suspend();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else if (signum == SIGUSR2)
 | 
			
		||||
	{
 | 
			
		||||
		if (suspendHandler != nullptr)
 | 
			
		||||
		{
 | 
			
		||||
			suspendHandler->resume();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
QCoreApplication* createApplication(int &argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	bool isGuiApp = false;
 | 
			
		||||
@@ -150,11 +121,6 @@ int main(int argc, char** argv)
 | 
			
		||||
 | 
			
		||||
	DefaultSignalHandler::install();
 | 
			
		||||
 | 
			
		||||
#ifndef _WIN32
 | 
			
		||||
	signal(SIGCHLD, signal_handler);
 | 
			
		||||
	signal(SIGUSR1, signal_handler);
 | 
			
		||||
	signal(SIGUSR2, signal_handler);
 | 
			
		||||
#endif
 | 
			
		||||
	// force the locale
 | 
			
		||||
	setlocale(LC_ALL, "C");
 | 
			
		||||
	QLocale::setDefault(QLocale::c());
 | 
			
		||||
 
 | 
			
		||||
@@ -22,10 +22,11 @@
 | 
			
		||||
#endif
 | 
			
		||||
#include <webserver/WebServer.h>
 | 
			
		||||
#include <hyperion/PriorityMuxer.h>
 | 
			
		||||
#include <events/EventHandler.h>
 | 
			
		||||
 | 
			
		||||
#include "hyperiond.h"
 | 
			
		||||
#include "systray.h"
 | 
			
		||||
#include "SuspendHandler.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SysTray::SysTray(HyperionDaemon *hyperiond)
 | 
			
		||||
	: QWidget()
 | 
			
		||||
@@ -33,7 +34,6 @@ SysTray::SysTray(HyperionDaemon *hyperiond)
 | 
			
		||||
	, _hyperiond(hyperiond)
 | 
			
		||||
	, _hyperion(nullptr)
 | 
			
		||||
	, _instanceManager(HyperionIManager::getInstance())
 | 
			
		||||
	, _suspendHandler (hyperiond->getSuspendHandlerInstance())
 | 
			
		||||
	, _webPort(8090)
 | 
			
		||||
{
 | 
			
		||||
	Q_INIT_RESOURCE(resources);
 | 
			
		||||
@@ -84,13 +84,16 @@ void SysTray::createTrayIcon()
 | 
			
		||||
	restartAction->setIcon(QPixmap(":/restart.svg"));
 | 
			
		||||
	connect(restartAction, &QAction::triggered, this , [=](){ Process::restartHyperion(12); });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// TODO: Check if can be done with SystemEvents
 | 
			
		||||
	suspendAction = new QAction(tr("&Suspend"), this);
 | 
			
		||||
	suspendAction->setIcon(QPixmap(":/suspend.svg"));
 | 
			
		||||
	connect(suspendAction, &QAction::triggered, _suspendHandler, QOverload<>::of(&SuspendHandler::suspend));
 | 
			
		||||
	connect(suspendAction, &QAction::triggered, EventHandler::getInstance(), QOverload<>::of(&EventHandler::suspend));
 | 
			
		||||
 | 
			
		||||
	resumeAction = new QAction(tr("&Resume"), this);
 | 
			
		||||
	resumeAction->setIcon(QPixmap(":/resume.svg"));
 | 
			
		||||
	connect(resumeAction, &QAction::triggered, _suspendHandler, &SuspendHandler::resume);
 | 
			
		||||
 | 
			
		||||
	connect(resumeAction, &QAction::triggered, EventHandler::getInstance(), &EventHandler::resume);
 | 
			
		||||
 | 
			
		||||
	colorAction = new QAction(tr("&Color"), this);
 | 
			
		||||
	colorAction->setIcon(QPixmap(":/color.svg"));
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
 | 
			
		||||
#include <hyperion/Hyperion.h>
 | 
			
		||||
#include <hyperion/HyperionIManager.h>
 | 
			
		||||
#include "SuspendHandler.h"
 | 
			
		||||
#include <events/EventHandler.h>
 | 
			
		||||
 | 
			
		||||
class HyperionDaemon;
 | 
			
		||||
 | 
			
		||||
@@ -22,13 +22,13 @@ class SysTray : public QWidget
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	SysTray(HyperionDaemon *hyperiond);
 | 
			
		||||
	~SysTray();
 | 
			
		||||
	~SysTray() override;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
	void showColorDialog();
 | 
			
		||||
	void setColor(const QColor & color);
 | 
			
		||||
	void closeEvent(QCloseEvent *event);
 | 
			
		||||
	void closeEvent(QCloseEvent *event) override;
 | 
			
		||||
	void settings() const;
 | 
			
		||||
#if defined(ENABLE_EFFECTENGINE)
 | 
			
		||||
	void setEffect();
 | 
			
		||||
@@ -42,7 +42,7 @@ private slots:
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief is called whenever the webserver changes the port
 | 
			
		||||
	///
 | 
			
		||||
	void webserverPortChanged(quint16 port) { _webPort = port; };
 | 
			
		||||
	void webserverPortChanged(quint16 port) { _webPort = port; }
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	/// @brief is called whenever a hyperion instance state changes
 | 
			
		||||
@@ -84,6 +84,4 @@ private:
 | 
			
		||||
	Hyperion         *_hyperion;
 | 
			
		||||
	HyperionIManager *_instanceManager;
 | 
			
		||||
	quint16           _webPort;
 | 
			
		||||
 | 
			
		||||
	SuspendHandler   *_suspendHandler;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user