Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package ddcutil-service for openSUSE:Factory checked in at 2024-04-29 17:57:49 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ddcutil-service (Old) and /work/SRC/openSUSE:Factory/.ddcutil-service.new.1880 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ddcutil-service" Mon Apr 29 17:57:49 2024 rev:5 rq:1170644 version:1.0.6 Changes: -------- --- /work/SRC/openSUSE:Factory/ddcutil-service/ddcutil-service.changes 2024-04-14 12:24:47.481937126 +0200 +++ /work/SRC/openSUSE:Factory/.ddcutil-service.new.1880/ddcutil-service.changes 2024-04-29 17:57:53.770388912 +0200 @@ -1,0 +2,12 @@ +Mon Apr 29 03:52:43 UTC 2024 - Michael Hamilton <mich...@actrix.gen.nz> + +- 1.0.6 + - Add SetVcp/SetVcpWithContext NO_VERIFY (no retry) flag option. + - Match the behaviour of the ddcutil command, default to verify-and-retry for all set-vcp method calls. + - Default to verify-and-retry for all libddcutil versions. + - Replace the stateful DdcutilVerifySetVcp property with the stateless NO_VERIFY flag. + - Fix the ServiceFlagOptions property so that it lists all flag options. + - Check the status returned by libddcutil ddca_init() and exit on error to prevent any inconsistent behaviour. + - Cleanup the --prefer-polling and --prefer-drm options to make them consistent with each other. + +------------------------------------------------------------------- Old: ---- ddcutil-service-1.0.4.tar.gz New: ---- ddcutil-service-1.0.6.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ddcutil-service.spec ++++++ --- /var/tmp/diff_new_pack.CMaW5W/_old 2024-04-29 17:57:54.606419319 +0200 +++ /var/tmp/diff_new_pack.CMaW5W/_new 2024-04-29 17:57:54.606419319 +0200 @@ -18,7 +18,7 @@ Name: ddcutil-service -Version: 1.0.4 +Version: 1.0.6 Release: 0 Summary: D-Bus service for libddcutil VESA DDC Monitor Virtual Control Panel License: GPL-2.0-or-later ++++++ ddcutil-service-1.0.4.tar.gz -> ddcutil-service-1.0.6.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ddcutil-service-1.0.4/Makefile new/ddcutil-service-1.0.6/Makefile --- old/ddcutil-service-1.0.4/Makefile 2024-04-11 02:58:06.000000000 +0200 +++ new/ddcutil-service-1.0.6/Makefile 2024-04-29 06:17:32.000000000 +0200 @@ -5,6 +5,7 @@ CFLAGS_DDCUTIL = $(shell pkg-config --cflags --libs ddcutil) # Uncomment to compile against a developer local libddcutil #CFLAGS_DDCUTIL = -isystem $(HOME)/Downloads/ddcutil-2.1.5-dev/src/public -L $(HOME)/Downloads/ddcutil-2.1.5-dev/src/.libs -lddcutil +#CFLAGS_DDCUTIL = -isystem $(HOME)/Downloads/ddcutil-2.1.5-dev-clion/build/src/public -isystem $(HOME)/Downloads/ddcutil-2.1.5-dev-clion/src/public -L $(HOME)/Downloads/ddcutil-2.1.5-dev-clion/build/src/.libs -lddcutil #CFLAGS_DDCUTIL = -isystem $(HOME)/Downloads/ddcutil-2.1.4-dev/src/public -L $(HOME)/Downloads/ddcutil-2.1.4-dev/src/.libs -lddcutil #CFLAGS_DDCUTIL = -isystem $(HOME)/Downloads/ddcutil-2.0.0/src/public -L $(HOME)/Downloads/ddcutil-2.0.0/src/.libs -lddcutil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ddcutil-service-1.0.4/README.md new/ddcutil-service-1.0.6/README.md --- old/ddcutil-service-1.0.4/README.md 2024-04-11 02:58:06.000000000 +0200 +++ new/ddcutil-service-1.0.6/README.md 2024-04-29 06:17:32.000000000 +0200 @@ -98,7 +98,18 @@ Johan Grande ([nahoj](https://github.com/nahoj)) for the Ubuntu patches; and Mark Wagie ([yochananmarqos](https://github.com/yochananmarqos)) for AUR packaging. +The development IDE is **[JetBrains CLion-Nova/CLion](https://www.jetbrains.com/help/clion/clion-nova-introduction.html)**. Thanks go out to JetBrains for +granting the [Open Source development license]( https://jb.gg/OpenSourceSupport). + ### Version History +- 1.0.6 + - Add SetVcp/SetVcpWithContext NO_VERIFY (no retry) flag option. + - Match the behaviour of the ddcutil command, default to verify-and-retry for all set-vcp method calls. + - Default to verify-and-retry for all libddcutil versions. + - Replace the stateful DdcutilVerifySetVcp property with the stateless NO_VERIFY flag. + - Fix the ServiceFlagOptions property so that it lists all flag options. + - Check the status returned by libddcutil ddca_init() and exit on error to prevent any inconsistent behaviour. + - Cleanup the --prefer-polling and --prefer-drm options to make them consistent with each other. - 1.0.4 - Provide an API flag RETURN_RAW_VALUES which disables GetVcp high-byte masking of Simple Non-Continuous features. - Provide the --return-raw-values command line option for the same purpose. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ddcutil-service-1.0.4/ddcutil-service.1 new/ddcutil-service-1.0.6/ddcutil-service.1 --- old/ddcutil-service-1.0.4/ddcutil-service.1 2024-04-11 02:58:06.000000000 +0200 +++ new/ddcutil-service-1.0.6/ddcutil-service.1 2024-04-29 06:17:32.000000000 +0200 @@ -224,6 +224,8 @@ .B SetVcp Set a display setting, specified by VCP code, to a new value. If the method succeeds, it will also emit a D-Bus \fBVcpValueChanged\fP signal. +Set the method's \fBflags\fP to \fB4\fP (\fBNO_VERIFY\fP) to disable libddcutil +verification and retry. .TP .B SetVcpWithContext @@ -392,9 +394,8 @@ .TP .B DdcutilVerifySetVcp -Enable/disable -.B libddcutil -extra DDC calls to check whether VCP settings were actually applied by the monitor. +Obsolete as of version 1.0.5+, +replaced by the \fBSetVcp\fP method's \fBNO_VERIFY\fP flag. .TP .B DdcutilVersion diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ddcutil-service-1.0.4/ddcutil-service.7 new/ddcutil-service-1.0.6/ddcutil-service.7 --- old/ddcutil-service-1.0.4/ddcutil-service.7 2024-04-11 02:58:06.000000000 +0200 +++ new/ddcutil-service-1.0.6/ddcutil-service.7 2024-04-29 06:17:32.000000000 +0200 @@ -2,12 +2,12 @@ .\" Title: com.ddcutil.DdcutilInterface .\" Author: Michael Hamilton .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 04/09/2024 +.\" Date: 04/25/2024 .\" Manual: Miscellaneous .\" Source: ddcutil-service .\" Language: English .\" -.TH "COM\&.DDCUTIL\&.DDCU" "7" "04/09/2024" "ddcutil\-service" "Miscellaneous" +.TH "COM\&.DDCUTIL\&.DDCU" "7" "04/25/2024" "ddcutil\-service" "Miscellaneous" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -150,7 +150,6 @@ AttributesReturnedByDetect readable as StatusValues readable a{is} DdcutilVersion readable s -DdcutilVerifySetVcp readwrite b DdcutilDynamicSleep readwrite b DdcutilOutputLevel readwrite u DisplayEventTypes readable a{is} @@ -438,6 +437,10 @@ \fIvcp_new_value\fR is always passed as a 16 bit integer (most VCP values are single byte 8\-bit intergers, very few are two\-byte 16\-bit)\&. .PP +The method\*(Aqs +\fIflags\fR +parameter can be set to 4 (NO_VERIFY) to disable libddcutil verify and retry\&. Verification and retry is the default\&. +.PP IN i \fIdisplay_number\fR: .RS 4 the libddcutil/ddcutil display number to alter @@ -499,6 +502,10 @@ \fIvcp_new_value\fR is always passed as a 16 bit integer (most VCP values are single byte 8\-bit intergers, very few are two\-byte 16\-bit)\&. .PP +The method\*(Aqs +\fIflags\fR +parameter can be set to 4 (NO_VERIFY) to disable libddcutil verify and retry\&. Verification and retry is the default\&. +.PP IN i \fIdisplay_number\fR: .RS 4 the libddcutil/ddcutil display number to alter @@ -1068,21 +1075,6 @@ .\} .PP The ddcutil version number for the linked libddcutil\&. -.SS "The "DdcutilVerifySetVcp" property" -.sp -.if n \{\ -.RS 4 -.\} -.nf -DdcutilVerifySetVcp readwrite b -.fi -.if n \{\ -.RE -.\} -.PP -Within libddcutil each setvcp is verified by internal check using a getvcp\&. This verfication step can be enabled or disabled by altering this property\&. -.PP -Attempting to set this property when the service is configuration\-locked will result in an com\&.ddcutil\&.DdcutilService\&.Error\&.ConfigurationLocked error being raised\&. .SS "The "DdcutilDynamicSleep" property" .sp .if n \{\ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ddcutil-service-1.0.4/ddcutil-service.c new/ddcutil-service-1.0.6/ddcutil-service.c --- old/ddcutil-service-1.0.4/ddcutil-service.c 2024-04-11 02:58:06.000000000 +0200 +++ new/ddcutil-service-1.0.6/ddcutil-service.c 2024-04-29 06:17:32.000000000 +0200 @@ -58,7 +58,7 @@ #include <ddcutil_status_codes.h> #include <ddcutil_macros.h> -#define DDCUTIL_DBUS_INTERFACE_VERSION_STRING "1.0.4" +#define DDCUTIL_DBUS_INTERFACE_VERSION_STRING "1.0.6" #define DDCUTIL_DBUS_DOMAIN "com.ddcutil.DdcutilService" #if DDCUTIL_VMAJOR == 2 && DDCUTIL_VMINOR == 0 && DDCUTIL_VMICRO < 2 @@ -73,14 +73,25 @@ #define LIBDDCUTIL_HAS_DDCA_GET_DEFAULT_SLEEP_MULTIPLIER #endif +#define MACRO_EXISTS(name) (#name [0] != G_STRINGIFY(name) [0]) + #undef XML_FROM_INTROSPECTED_DATA +/** + * Define the service's connectivity monitoring options + */ +typedef enum { + MONITOR_BY_INTERNAL_POLLING, + MONITOR_BY_LIBDDCUTIL_EVENTS, +} Monitoring_Preference_Type; + static gboolean display_status_detection_enabled = FALSE; static gboolean enable_connectivity_signals = FALSE; -static gboolean prefer_polling = TRUE; static gboolean return_raw_values = FALSE; static gboolean lock_configuration = FALSE; +static Monitoring_Preference_Type monitoring_preference = MONITOR_BY_INTERNAL_POLLING; + #define VERIFY_I2C static int service_broken_error = -1; @@ -179,15 +190,18 @@ * Boolean flags that can be passed in the service method flags argument. */ typedef enum { - EDID_PREFIX = 1, // Indicates the EDID passed to the service is a unique prefix (substring) of the actual EDID. - RETURN_RAW_VALUES = 2, + EDID_PREFIX = 1, // Indicates the EDID passed to the service is a unique prefix (substr) of the actual EDID. + RETURN_RAW_VALUES = 2, // GetVcp GetMultipleVcp + NO_VERIFY = 4, // SetVcp } Flags_Enum_Type; /** * Iterable definitions of Flags_Enum_Type values/names (for return from a service property). */ -const int flag_options[] = {EDID_PREFIX,}; -const char* flag_options_names[] = {G_STRINGIFY(EDID_PREFIX),}; +const int flag_options[] = {EDID_PREFIX,RETURN_RAW_VALUES, NO_VERIFY,}; +const char* flag_options_names[] = {G_STRINGIFY(EDID_PREFIX), + G_STRINGIFY(RETURN_RAW_VALUES), + G_STRINGIFY(NO_VERIFY),}; /* ---------------------------------------------------------------------------------------------------- * D-Bus interface definition in XML @@ -230,7 +244,7 @@ @text_options: Text options to be passed to libddcutil ddca_init(). @syslog_level: The libddcutil syslog level. @flags: For furture use. - @error_status: A libddcutil DDCRC error status. DDCA_OK (zero) if no errors have occured. + @error_status: A libddcutil DDCRC error status. DDCRC_OK (zero) if no errors have occured. @error_message: Text message for error_status. Restarts the service with the supplied parameters. @@ -251,7 +265,7 @@ @flags: If set to 1, any invalid VDUs will be included in the results. @number_of_displays: The number of VDUs detected (the length of @detected_displays). @detected_displays: An array of structures describing the VDUs. - @error_status: A libddcutil DDCRC error status. DDCA_OK (zero) if no errors have occured. + @error_status: A libddcutil DDCRC error status. DDCRC_OK (zero) if no errors have occured. @error_message: Text message for error_status. Issues a detect and returns the VDUs detected. @@ -279,7 +293,7 @@ @vcp_current_value: The current numeric value as a unified 16 bit integer. @vcp_max_value: The maximum possible value, to allow for easy calculation of current/max. @vcp_formatted_value: A formatted version of the value including related info such as the max-value. - @error_status: A libddcutil DDCRC error status. DDCA_OK (zero) if no errors have occured. + @error_status: A libddcutil DDCRC error status. DDCRC_OK (zero) if no errors have occured. @error_message: Text message for error_status. Retrieve the value for a VCP-code for the specified VDU. @@ -312,7 +326,7 @@ @vcp_code: the VPC-code to query. @flags: If 1, the @edid_txt is matched as a unique prefex of the EDID. @vcp_current_value: An array of VCP-codes and values. - @error_status: A libddcutil DDCRC error status. DDCA_OK (zero) if no errors have occured. + @error_status: A libddcutil DDCRC error status. DDCRC_OK (zero) if no errors have occured. @error_message: Text message for error_status. Retrieves several different VCP values for the specified VDU. This is a convienience @@ -341,13 +355,16 @@ @vcp_code: the VPC-code to query. @vcp_new_value: the numeric value as a 16 bit integer. @flags: If 1, the @edid_txt is matched as a unique prefex of the EDID. - @error_status: A libddcutil DDCRC error status. DDCA_OK (zero) if no errors have occured. + @error_status: A libddcutil DDCRC error status. DDCRC_OK (zero) if no errors have occured. @error_message: Text message for error_status. Set the value for a VCP-code for the specified VDU. For simplicity the @vcp_new_value is always passed as a 16 bit integer (most VCP values are single byte 8-bit intergers, very few are two-byte 16-bit). + + The method's @flags parameter can be set to 4 (NO_VERIFY) to disable + libddcutil verify and retry. Verification and retry is the default. --> <method name='SetVcp'> <arg name='display_number' type='i' direction='in'/> @@ -367,13 +384,16 @@ @vcp_new_value: the numeric value as a 16 bit integer. @client_context: a client-context string that will be returned with the VcpValueChanged signal. @flags: If 1, the @edid_txt is matched as a unique prefex of the EDID. - @error_status: A libddcutil DDCRC error status. DDCA_OK (zero) if no errors have occured. + @error_status: A libddcutil DDCRC error status. DDCRC_OK (zero) if no errors have occured. @error_message: Text message for error_status. Set the value for a VCP-code for the specified VDU. For simplicity the @vcp_new_value is always passed as a 16 bit integer (most VCP values are single byte 8-bit intergers, very few are two-byte 16-bit). + + The method's @flags parameter can be set to 4 (NO_VERIFY) to disable + libddcutil verify and retry. Verification and retry is the default. --> <method name='SetVcpWithContext'> <arg name='display_number' type='i' direction='in'/> @@ -399,7 +419,7 @@ @is_rw: True if the feature is readable and writable. @is_complex: True if the feature is complex (multi-byte). @is_continuous: True in the feature is a continuous value (it is not an enumeration). - @error_status: A libddcutil DDCRC error status. DDCA_OK (zero) if no errors have occured. + @error_status: A libddcutil DDCRC error status. DDCRC_OK (zero) if no errors have occured. @error_message: Text message for error_status. Retrieve the metadata for a VCP-code for the specified VDU. @@ -426,7 +446,7 @@ @edid_txt: the base-64 encoded EDID of the display @flags: If 1, the @edid_txt is matched as a unique prefex of the EDID. @capabilities_text: the capability string for the VDU. - @error_status: A libddcutil DDCRC error status. DDCA_OK (zero) if no errors have occured. + @error_status: A libddcutil DDCRC error status. DDCRC_OK (zero) if no errors have occured. @error_message: Text message for error_status. Retrieve the capabilities metadata for a VDU in a format similar to that output by @@ -451,7 +471,7 @@ @mccs_minor: MCCS minor version number byte. @commands: supported commands as a dictionary indexed by command number. @capabilities: supported VCP features as a dictionary indexed by VCP-code. - @error_status: A libddcutil DDCRC error status. DDCA_OK (zero) if no errors have occured. + @error_status: A libddcutil DDCRC error status. DDCRC_OK (zero) if no errors have occured. @error_message: Text message for error_status. Retrieve the capabilities metadata for a VDU in a parsed dictionary structure @@ -509,7 +529,7 @@ @vcp_code: the VPC-code to query, for example, 16 (0x10) is brightness. @flags: If 1, the @edid_txt is matched as a unique prefex of the EDID. @current_multiplier: the sleep multiplier. - @error_status: A libddcutil DDCRC error status. DDCA_OK (zero) if no errors have occured. + @error_status: A libddcutil DDCRC error status. DDCRC_OK (zero) if no errors have occured. @error_message: Text message for error_status. Get the current libddcutil sleep multiplier for the specified VDU. @@ -532,7 +552,7 @@ @vcp_code: The VPC-code to query, for example, 16 (0x10) is brightness. @flags: If 1, the @edid_txt is matched as a unique prefex of the EDID. @new_multiplier: The sleep multiplier. - @error_status: A libddcutil DDCRC error status. DDCA_OK (zero) if no errors have occured. + @error_status: A libddcutil DDCRC error status. DDCRC_OK (zero) if no errors have occured. @error_message: Text message for error_status. Set the libddcutil sleep multiplier for the specified VDU. @@ -631,18 +651,6 @@ <property type='s' name='DdcutilVersion' access='read'/> <!-- - DdcutilVerifySetVcp: - - Within libddcutil each setvcp is verified by internal check using a getvcp. - This verfication step can be enabled or disabled by altering this property. - - Attempting to set this property when the service is configuration-locked - will result in an com.ddcutil.DdcutilService.Error.ConfigurationLocked error - being raised. - --> - <property type='b' name='DdcutilVerifySetVcp' access='readwrite'/> - - <!-- DdcutilDynamicSleep: Enables/disables automatic adjustment of the sleep-multiplier. Before @@ -1182,6 +1190,8 @@ GVariantBuilder* value_array_builder = &value_array_builder_instance; g_variant_builder_init(value_array_builder, G_VARIANT_TYPE("a(yqqs)")); + ddca_enable_verify(TRUE); + DDCA_Display_Info_List* info_list = NULL; DDCA_Display_Info* vdu_info = NULL; // pointer into info_list DDCA_Status status = get_display_info(display_number, edid_encoded, &info_list, &vdu_info, flags & EDID_PREFIX); @@ -1262,8 +1272,8 @@ client_context = g_strdup(""); } - g_info("%s vcp_code=%d value=%d display_num=%d edid=%.30s...", - call_name, vcp_code, new_value, display_number, edid_encoded); + // Always explicitly default to verify - ensures all libddcutil versions behave the same way + ddca_enable_verify(flags & NO_VERIFY ? FALSE : TRUE); DDCA_Display_Info_List* info_list = NULL; DDCA_Display_Info* vdu_info = NULL; // pointer into info_list @@ -1278,7 +1288,7 @@ ddca_close_display(disp_handle); } } - if (status == 0) { + if (status == DDCRC_OK) { GError* local_error = NULL; const gchar* client_name = g_dbus_method_invocation_get_sender(invocation); if (!g_dbus_connection_emit_signal(dbus_connection, @@ -1745,6 +1755,107 @@ } /** + * @brief validate and update the poll_interval_millis + * @param secs + * @return TRUE if valid and succeeded + */ +static bool update_poll_interval(const uint secs) { + if (secs > 0 && secs < MIN_POLL_SECONDS) { + g_warning ("Invalid polling interval %u, interval must be at least %d seconds", secs, MIN_POLL_SECONDS); + return FALSE; + } + else if (secs == 0) { + g_message("ServicePollInterval changed to zero, polling is now disabled."); + poll_interval_micros = 0; + } + else { + g_message("ServicePollInterval changed to %u seconds", secs); + poll_interval_micros = secs * 1000000; + } + return TRUE; +} + +/** + * @brief validate and update the poll_cascade_interval_millis + * @param secs + * @return TRUE if valid and succeeded + */ +static bool update_poll_cascade_interval(const double secs) { + if (secs < MIN_POLL_CASCADE_INTERVAL_SECONDS || secs > poll_interval_micros / 1000000) { + g_warning("Invalid poll cascade interval %5.3f, valid range is %5.3f to %5.3f", + secs, MIN_POLL_CASCADE_INTERVAL_SECONDS, poll_interval_micros / 1000000.0); + return FALSE; + } + g_message("ServicePollCascadeInterval changed to %f seconds", secs); + poll_cascade_interval_micros = (long) (secs * 1000000); + return TRUE; +} + +/** + * @brief stop ddc watch displays if not already stopped + * @return DDCRC_OK if already stopped or stop succeeds, otherwise returns the stop error status + */ +static DDCA_Status disable_ddca_watch_displays() { +#if defined(LIBDDCUTIL_HAS_CHANGES_CALLBACK) + DDCA_Display_Event_Class classes_loc; + const bool running = ddca_get_active_watch_classes(&classes_loc) == DDCRC_OK; + if (!running) { + g_message("stop libddcutil watch_displays - already stopped, nothing to do."); + return DDCRC_OK; + } + const int status = ddca_stop_watch_displays(true); + if (status != DDCRC_OK) { + char *message_text = get_status_message(status); + g_warning("stop libddcutil watch_displays failed %d %s", status, message_text); + free(message_text); + } + return status; +#else + g_warning("ServiceEmitConnectivitySignals using libddcutil not supported by libddcutil %s", + ddca_ddcutil_extended_version_string()); + return DDCRC_UNIMPLEMENTED; +#endif +} + +/** + * @brief start ddc watch displays + * @return DDCRC_OK if start/restart succeeds, otherwise returns the error status + */ +static DDCA_Status enable_ddca_watch_displays(void) { +#if defined(LIBDDCUTIL_HAS_CHANGES_CALLBACK) + g_message("ServiceEmitConnectivitySignals using libddcutil change detection"); + int status = DDCRC_OK; + DDCA_Display_Event_Class classes_loc; + const bool running = ddca_get_active_watch_classes(&classes_loc) == DDCRC_OK; + if (running) { + g_message("start libddcutil watch_displays - already running - stopping first."); + status = ddca_stop_watch_displays(true); + } + if (status == DDCRC_OK) { + g_message("start libddcutil watch_displays - starting."); + status = ddca_start_watch_displays(DDCA_EVENT_CLASS_ALL); + if (status == DDCRC_OK) { + g_message("registering libddcutil display status callback"); + poll_interval_micros = 0; // Disable internal polling + const int status = ddca_register_display_status_callback(display_status_event_callback); + if (status == DDCRC_OK) { + return status; + } + } + } + char *message_text = get_status_message(status); + g_warning("enabling libddcutil watch displays failed (status=%d - %s)", status, message_text); + free(message_text); + g_warning("libddcutil change detection unavailable for this GPU"); + return status; +#else + g_warning("ServiceEmitConnectivitySignals using libddcutil not supported by libddcutil %s", + ddca_ddcutil_extended_version_string()); + return DDCRC_UNIMPLEMENTED; +#endif +} + +/** * @brief Handles DdcutilService D-Bus method-calls by passing them to implementating functions. * * This handler is registered with glib's D-Bus main loop to handle DdcutilService @@ -1855,9 +1966,6 @@ else if (g_strcmp0(property_name, "ServiceInterfaceVersion") == 0) { ret = g_variant_new_string(DDCUTIL_DBUS_INTERFACE_VERSION_STRING); } - else if (g_strcmp0(property_name, "DdcutilVerifySetVcp") == 0) { - ret = g_variant_new_boolean(ddca_is_verify_enabled()); - } else if (g_strcmp0(property_name, "DdcutilDynamicSleep") == 0) { #if defined(LIBDDCUTIL_HAS_DYNAMIC_SLEEP_BOOLEAN) ret = g_variant_new_boolean(ddca_is_dynamic_sleep_enabled()); @@ -1959,14 +2067,13 @@ g_warning("%s", (*error)->message); return FALSE; } - if (g_strcmp0(property_name, "DdcutilVerifySetVcp") == 0) { - ddca_enable_verify(g_variant_get_boolean(value)); - } - else if (g_strcmp0(property_name, "DdcutilDynamicSleep") == 0) { + + if (g_strcmp0(property_name, "DdcutilDynamicSleep") == 0) { #if defined(LIBDDCUTIL_HAS_DYNAMIC_SLEEP_BOOLEAN) ddca_enable_dynamic_sleep(g_variant_get_boolean(value)); #else - g_warning("Dynamic sleep boolean not supported by this version of libddcutil"); + g_warning("Dynamic sleep boolean not supported by this version of libddcutil %s", + ddca_ddcutil_extended_version_string()); #endif } else if (g_strcmp0(property_name, "DdcutilOutputLevel") == 0) { @@ -1984,74 +2091,54 @@ } enable_connectivity_signals = g_variant_get_boolean(value); g_message("ServiceEmitConnectivitySignals set property to %s", - enable_connectivity_signals ? "enabled" : "disabled"); - if (prefer_polling) { - if (enable_connectivity_signals) { - if (poll_interval_micros == 0) { // If not already set - poll_interval_micros = DEFAULT_POLL_SECONDS * 1000000; - } - g_message("ServiceEmitConnectivitySignals ddcutil-service polling every %ld seconds", - poll_interval_micros/1000000); - } - } - else { - g_message("Detect changes using libddcutil callbacks."); - poll_interval_micros = 0; -#if defined(LIBDDCUTIL_HAS_CHANGES_CALLBACK) - if (enable_connectivity_signals) { - g_message("ServiceEmitConnectivitySignals using libddcutil change detection"); - const int status = ddca_start_watch_displays(DDCA_EVENT_CLASS_ALL); - if (status != DDCRC_OK) { - char* message_text = get_status_message(status); - g_message("ServiceEmitConnectivitySignals ddca_start_watch_displays %d %s", status, message_text); - free(message_text); + enable_connectivity_signals ? "enabled" : "disabled"); + switch (monitoring_preference) { + case MONITOR_BY_LIBDDCUTIL_EVENTS: + g_message("Detect changes using libddcutil callbacks."); + poll_interval_micros = 0; + if (enable_connectivity_signals) { + if (enable_ddca_watch_displays() == DDCRC_OK) { + break; // Success, exit the switch + } + // Failed, fall through to polling + } else { + disable_ddca_watch_displays(); + break; } - } - else { - const int status = ddca_stop_watch_displays(DDCA_EVENT_CLASS_ALL); - if (status != DDCRC_OK) { - char* message_text = get_status_message(status); - g_message("ServiceEmitConnectivitySignals ddca_stop_watch_displays %d %s", status, message_text); - free(message_text); + case MONITOR_BY_INTERNAL_POLLING: + default: + if (enable_connectivity_signals) { + if (poll_interval_micros == 0) { // If not already set + poll_interval_micros = DEFAULT_POLL_SECONDS * 1000000; + } + g_message("ServiceEmitConnectivitySignals ddcutil-service polling every %ld seconds", + poll_interval_micros / 1000000); + } else { + poll_interval_micros = 0; } - } -#endif + break; } } else if (g_strcmp0(property_name, "ServicePollInterval") == 0) { const uint secs = g_variant_get_uint32(value); - if (secs == 0) { - poll_interval_micros = 0; - g_message("ServicePollInterval changed to zero, polling is now disabled."); - } - else if (secs < MIN_POLL_SECONDS) { + if (!update_poll_interval(secs)) { g_set_error (error, - service_error_quark, - DDCUTIL_SERVICE_INVALID_POLL_SECONDS, - "Invalid polling interval %u, interval must be at least %d seconds", secs, MIN_POLL_SECONDS); - g_warning("%s", (*error)->message); + service_error_quark, + DDCUTIL_SERVICE_INVALID_POLL_SECONDS, + "Invalid polling interval %u, interval must be at least %d seconds", secs, MIN_POLL_SECONDS); return FALSE; } - else { - g_message("ServicePollInterval changed to %u seconds", secs); - poll_interval_micros = secs * 1000000; - } } else if (g_strcmp0(property_name, "ServicePollCascadeInterval") == 0) { const double secs = g_variant_get_double(value); - if (secs < MIN_POLL_CASCADE_INTERVAL_SECONDS || secs < poll_interval_micros / 1000000) { + if (!update_poll_cascade_interval(secs)) { g_set_error (error, service_error_quark, DDCUTIL_SERVICE_INVALID_POLL_CASCADE_SECONDS, "Invalid poll cascade interval %5.3f, valid range is %5.3f to %5.3f", secs, MIN_POLL_CASCADE_INTERVAL_SECONDS, poll_interval_micros / 1000000.0); - g_warning("%s", (*error)->message); return FALSE; } - else { - g_message("ServicePollCascadeInterval changed to %f seconds", secs); - poll_cascade_interval_micros = (long) (secs * 1000000); - } } return *error == NULL; } @@ -2191,7 +2278,7 @@ } /* - * GDBUS service handler table - passed on registraction of the service + * GDBUS service handler table - passed on registration of the service */ static const GDBusInterfaceVTable interface_vtable = {handle_method_call, handle_get_property, handle_set_property}; @@ -2445,6 +2532,7 @@ gboolean introspect_request = FALSE; // g_option_context_parse will overrun gboolean log_info = FALSE; // TODO should all bool be changed to gboolean for safety? + gboolean prefer_polling = TRUE; gboolean prefer_drm = FALSE; int poll_seconds = -1; // -1 flags no argument supplied @@ -2541,6 +2629,11 @@ g_message("All properties and sleep-multipliers are read only (--lock passed)"); } + g_info("LIBDDCUTIL_HAS_CHANGES_CALLBACK %d", MACRO_EXISTS(LIBDDCUTIL_HAS_CHANGES_CALLBACK)); + g_info("LIBDDCUTIL_HAS_OPTION_ARGUMENTS %d", MACRO_EXISTS(LIBDDCUTIL_HAS_OPTION_ARGUMENTS)); + g_info("LIBDDCUTIL_HAS_INDIVIDUAL_SLEEP_MULTIPLIER %d", MACRO_EXISTS(LIBDDCUTIL_HAS_INDIVIDUAL_SLEEP_MULTIPLIER)); + g_info("LIBDDCUTIL_HAS_DYNAMIC_SLEEP_BOOLEAN %d", MACRO_EXISTS(LIBDDCUTIL_HAS_DYNAMIC_SLEEP_BOOLEAN)); + /* Build introspection data structures from XML. */ introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL); @@ -2568,7 +2661,12 @@ #if defined(LIBDDCUTIL_HAS_OPTION_ARGUMENTS) ddca_init_options |= DDCA_INIT_OPTIONS_CLIENT_OPENED_SYSLOG; g_message("Calling ddca_init %d %d '%s'", ddca_syslog_level, ddca_init_options, arg_string); - ddca_init(arg_string, ddca_syslog_level, ddca_init_options); + const int status = ddca_init(arg_string, ddca_syslog_level, ddca_init_options); + if (status != DDCRC_OK) { + char* message_text = get_status_message(status); + g_critical("Fail to initialised libddcutil cannot continue: %s", message_text); + exit(1); + } #else if (argc > 0) { g_warning("libddcutil %s does not support calling ddca_init %d %d '%s'", @@ -2593,82 +2691,42 @@ GMainLoop* main_loop = g_main_loop_new(NULL, FALSE); - if (!enable_connectivity_signals) { - g_message("ConnectedDisplaysChanged signals disabled" - "(add --emit_connectivity_signals to enable them)."); - poll_interval_micros = 0; // Disable internal polling - } - else { + prefer_polling = !prefer_drm; + monitoring_preference = prefer_polling ? MONITOR_BY_INTERNAL_POLLING : MONITOR_BY_LIBDDCUTIL_EVENTS; -#if defined(LIBDDCUTIL_HAS_CHANGES_CALLBACK) - prefer_polling = !prefer_drm; - if (prefer_polling) { - g_message("ConnectedDisplaysChanged signal - prefering polling for change detection"); - } - else { - const int rstatus = ddca_register_display_status_callback(display_status_event_callback); - if (rstatus != DDCRC_OK) { - char* message_text = get_status_message(rstatus); - g_message("libddcutil ddca_register_display_status_callback failed (status=%d - %s)", rstatus, - message_text); - free(message_text); - g_warning("libddcutil change detection unavailable for this GPU"); - } - else { - const int status = ddca_start_watch_displays(DDCA_EVENT_CLASS_ALL); + if (enable_connectivity_signals) { + switch (monitoring_preference) { + case MONITOR_BY_LIBDDCUTIL_EVENTS: { + const int status = enable_ddca_watch_displays(); if (status == DDCRC_OK) { - g_message("Enabled ConnectedDisplaysChanged signal - using libddcutil change detection"); - poll_interval_micros = 0; // Disable internal polling - } - else { - char* message_text = get_status_message(status); - g_message("libddcutil ddca_start_watch_displays failed - non-DRM GPU? (status=%d - %s)", status, - message_text); - free(message_text); - g_warning("libddcutil change detection unavailable for this GPU"); - } - } - } -#else - if (prefer_drm) { - g_warning("ConnectedDisplaysChanged signal - using polling, DRM not supported by libddcutil %s", - ddca_ddcutil_extended_version_string()); - } -#endif - - if (poll_interval_micros > 0) { // Means polling hasn't been disabled by other options - if (poll_seconds != -1) { - // Command line override of polling interval - if (poll_seconds == 0) { - poll_interval_micros = 0; // Disable - g_message("ConnectedDisplaysChanged - polling disabled by --poll-interval 0"); - } - else if (poll_seconds < MIN_POLL_SECONDS) { - g_print("Polling interval parameter must be at least %d seconds.", MIN_POLL_SECONDS); - exit(1); - } - else { - poll_interval_micros = poll_seconds * 1000000; + poll_interval_micros = 0; + break; } + g_warning("Falling back to service internal polling for change detection"); } - g_message("Enabled ConnectedDisplaysChanged signal - using internal polling every %ld seconds", - poll_interval_micros / 1000000); - - if (poll_cascade_interval_seconds > 0) { - // Command line override of polling interval - if (poll_cascade_interval_seconds < MIN_POLL_CASCADE_INTERVAL_SECONDS) { - g_print("Polling cascade interval parameter must be at least %5.3f seconds.", - MIN_POLL_CASCADE_INTERVAL_SECONDS); - exit(1); - } - else { - poll_cascade_interval_micros = (long) (poll_cascade_interval_seconds * 1000000); + case MONITOR_BY_INTERNAL_POLLING: + default: + g_message("ConnectedDisplaysChanged signal - using service internal polling for change detection"); + if (poll_seconds >= 0 && !update_poll_interval(poll_seconds)) { + g_print("Polling interval parameter must be at least %d seconds.", MIN_POLL_SECONDS); + exit(1); + } + if (poll_cascade_interval_seconds > 0.0 && !update_poll_cascade_interval(poll_cascade_interval_seconds)) { + g_print("Polling cascade interval parameter must be at least %5.3f seconds.", + MIN_POLL_CASCADE_INTERVAL_SECONDS); + exit(1); } - } - g_message("Set ConnectedDisplaysChanged event cascade interval to %5.3f seconds", - poll_cascade_interval_micros / 1000000.0); + g_message("ConnectedDisplaysChanged signal - poll-interval=%ld poll-cascade-interval=%5.3f", + poll_interval_micros / 1000000, poll_cascade_interval_micros / 100000.0); + break; } } + else { + g_message("ConnectedDisplaysChanged signals disabled" + "(add --emit_connectivity_signals to enable them)."); + poll_interval_micros = 0; // Disable internal polling + } + enable_custom_source(main_loop); // May do nothing - but a client may enable events or polling later g_main_loop_run(main_loop); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ddcutil-service-1.0.4/ddcutil-service.spec new/ddcutil-service-1.0.6/ddcutil-service.spec --- old/ddcutil-service-1.0.4/ddcutil-service.spec 2024-04-11 02:58:06.000000000 +0200 +++ new/ddcutil-service-1.0.6/ddcutil-service.spec 2024-04-29 06:17:32.000000000 +0200 @@ -18,7 +18,7 @@ Name: ddcutil-service -Version: 1.0.4 +Version: 1.0.6 Release: 0 Summary: D-Bus service for libddcutil VESA DDC Monitor Virtual Control Panel License: GPL-2.0-or-later diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ddcutil-service-1.0.4/docs/html/ddcutil-service.1.html new/ddcutil-service-1.0.6/docs/html/ddcutil-service.1.html --- old/ddcutil-service-1.0.4/docs/html/ddcutil-service.1.html 2024-04-11 02:58:06.000000000 +0200 +++ new/ddcutil-service-1.0.6/docs/html/ddcutil-service.1.html 2024-04-29 06:17:32.000000000 +0200 @@ -1,5 +1,5 @@ <!-- Creator : groff version 1.23.0 --> -<!-- CreationDate: Tue Apr 9 16:30:23 2024 --> +<!-- CreationDate: Thu Apr 25 08:20:05 2024 --> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> @@ -305,7 +305,9 @@ <p>Set a display setting, specified by VCP code, to a new value. If the method succeeds, it will also emit a D-Bus -<b>VcpValueChanged</b> signal.</p></td></tr> +<b>VcpValueChanged</b> signal. Set the method’s +<b>flags</b> to <b>4</b> (<b>NO_VERIFY</b>) to disable +libddcutil verification and retry.</p></td></tr> </table> <p style="margin-left:9%;"><b>SetVcpWithContext</b></p> @@ -480,9 +482,9 @@ <p style="margin-left:9%;"><b>DdcutilVerifySetVcp</b></p> -<p style="margin-left:18%;">Enable/disable -<b>libddcutil</b> extra DDC calls to check whether VCP -settings were actually applied by the monitor.</p> +<p style="margin-left:18%;">Obsolete as of version 1.0.5+, +replaced by the <b>SetVcp</b> method’s +<b>NO_VERIFY</b> flag.</p> <p style="margin-left:9%;"><b>DdcutilVersion</b></p> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ddcutil-service-1.0.4/docs/html/ddcutil-service.7.html new/ddcutil-service-1.0.6/docs/html/ddcutil-service.7.html --- old/ddcutil-service-1.0.4/docs/html/ddcutil-service.7.html 2024-04-11 02:58:06.000000000 +0200 +++ new/ddcutil-service-1.0.6/docs/html/ddcutil-service.7.html 2024-04-29 06:17:32.000000000 +0200 @@ -1,5 +1,5 @@ <!-- Creator : groff version 1.23.0 --> -<!-- CreationDate: Tue Apr 9 16:30:23 2024 --> +<!-- CreationDate: Thu Apr 25 08:20:05 2024 --> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> @@ -46,7 +46,6 @@ <a href="#The AttributesReturnedByDetect" property"">The AttributesReturnedByDetect" property"</a><br> <a href="#The StatusValues" property"">The StatusValues" property"</a><br> <a href="#The DdcutilVersion" property"">The DdcutilVersion" property"</a><br> -<a href="#The DdcutilVerifySetVcp" property"">The DdcutilVerifySetVcp" property"</a><br> <a href="#The DdcutilDynamicSleep" property"">The DdcutilDynamicSleep" property"</a><br> <a href="#The DdcutilOutputLevel" property"">The DdcutilOutputLevel" property"</a><br> <a href="#The DisplayEventTypes" property"">The DisplayEventTypes" property"</a><br> @@ -197,7 +196,6 @@ readable as <br> StatusValues readable a{is} <br> DdcutilVersion readable s <br> -DdcutilVerifySetVcp readwrite b <br> DdcutilDynamicSleep readwrite b <br> DdcutilOutputLevel readwrite u <br> DisplayEventTypes readable a{is} <br> @@ -529,6 +527,11 @@ integer (most VCP values are single byte 8−bit intergers, very few are two−byte 16−bit).</p> +<p style="margin-left:9%; margin-top: 1em">The method's +<i>flags</i> parameter can be set to 4 (NO_VERIFY) to +disable libddcutil verify and retry. Verification and retry +is the default.</p> + <p style="margin-left:9%; margin-top: 1em">IN i <i>display_number</i>:</p> @@ -595,6 +598,11 @@ integer (most VCP values are single byte 8−bit intergers, very few are two−byte 16−bit).</p> +<p style="margin-left:9%; margin-top: 1em">The method's +<i>flags</i> parameter can be set to 4 (NO_VERIFY) to +disable libddcutil verify and retry. Verification and retry +is the default.</p> + <p style="margin-left:9%; margin-top: 1em">IN i <i>display_number</i>:</p> @@ -1231,26 +1239,6 @@ <p style="margin-left:9%; margin-top: 1em">The ddcutil version number for the linked libddcutil.</p> -<h3>The DdcutilVerifySetVcp" property" -<a name="The DdcutilVerifySetVcp" property""></a> -</h3> - - - -<p style="margin-left:14%; margin-top: 1em">DdcutilVerifySetVcp -readwrite b</p> - -<p style="margin-left:9%; margin-top: 1em">Within -libddcutil each setvcp is verified by internal check using a -getvcp. This verfication step can be enabled or disabled by -altering this property.</p> - -<p style="margin-left:9%; margin-top: 1em">Attempting to -set this property when the service is -configuration−locked will result in an -com.ddcutil.DdcutilService.Error.ConfigurationLocked error -being raised.</p> - <h3>The DdcutilDynamicSleep" property" <a name="The DdcutilDynamicSleep" property""></a> </h3>