diff --git a/src/map-file-glib b/src/map-file-glib index ef0a31f3b907f04ae3ac0630997c70e097198bad..e06ff2c1e4bd3e8dfd3b74fdc49ba290c17e3c40 100644 --- a/src/map-file-glib +++ b/src/map-file-glib @@ -42,6 +42,11 @@ spice_file_transfer_task_get_type; spice_get_option_group; spice_gl_scanout_free; spice_gl_scanout_get_type; +spice_glib_get_debug; +spice_glib_get_version_string; +spice_glib_set_debug; +spice_glib_signal_connect_object; +spice_glib_uuid_to_string; spice_g_signal_connect_object; spice_inputs_button_press; spice_inputs_button_release; diff --git a/src/meson.build b/src/meson.build index c1f240fec4441092808c91a5516a053ea4c7c3ee..d26e173b0d5ad537510e3f17a696f9034cdc9e3d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -43,7 +43,7 @@ foreach version : versions endforeach versions = '''2 3 4 5 6 7 8 9 10 11 13 14 15 17 19 - 20 24 27 30 31 32 33 34 35 36 38 39 40'''.split() + 20 24 27 30 31 32 33 34 35 36 38 39 40 43'''.split() foreach version: versions script = '''@2@ #if SPICE_GTK_VERSION_MAX_ALLOWED < SPICE_GTK_VERSION_@0@_@1@ @@ -131,6 +131,7 @@ spice_client_glib_introspection_sources = [ 'spice-option.c', 'spice-session.c', 'spice-util.c', + 'spice-util-glib.c', 'usb-device-manager.c', ] diff --git a/src/spice-util-glib.c b/src/spice-util-glib.c new file mode 100644 index 0000000000000000000000000000000000000000..561171b46fcea0794c6f203f662d2057018b1d7f --- /dev/null +++ b/src/spice-util-glib.c @@ -0,0 +1,233 @@ +/* + Copyright (C) 2010 Red Hat, Inc. + Copyright © 2006-2010 Collabora Ltd. <http://www.collabora.co.uk/> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#include "config.h" + +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <glib.h> +#include <glib-object.h> +#include "spice-common.h" +#include "spice-util-priv.h" +#include "spice-util.h" +#include "spice-util-priv.h" + +static GOnce debug_once = G_ONCE_INIT; + +static void spice_util_enable_debug_messages(void) +{ + const gchar *doms = g_getenv("G_MESSAGES_DEBUG"); + if (!doms) { + g_setenv("G_MESSAGES_DEBUG", G_LOG_DOMAIN, 1); + } else if (g_str_equal(doms, "all")) { + return; + } else if (!strstr(doms, G_LOG_DOMAIN)) { + gchar *newdoms = g_strdup_printf("%s %s", doms, G_LOG_DOMAIN); + g_setenv("G_MESSAGES_DEBUG", newdoms, 1); + g_free(newdoms); + } +} + +/** + * spice_glib_set_debug: + * @enabled: %TRUE or %FALSE + * + * Enable or disable Spice-GTK debugging messages. + **/ +void spice_glib_set_debug(gboolean enabled) +{ + /* Make sure debug_once has been initialised + * with the value of SPICE_DEBUG already, otherwise + * spice_util_get_debug() may overwrite the value + * that was just set using spice_util_set_debug() + */ + spice_glib_get_debug(); + + if (enabled) { + spice_util_enable_debug_messages(); + } + + debug_once.retval = GINT_TO_POINTER(enabled); +} + +static gpointer getenv_debug(gpointer data) +{ + gboolean debug; + + debug = (g_getenv("SPICE_DEBUG") != NULL); + if (debug) + spice_util_enable_debug_messages(); + + return GINT_TO_POINTER(debug); +} + +gboolean spice_glib_get_debug(void) +{ + g_once(&debug_once, getenv_debug, NULL); + + return GPOINTER_TO_INT(debug_once.retval); +} + +/** + * spice_glib_get_version_string: + * + * Gets the version string + * + * Returns: Spice-GTK version as a const string. + **/ +const gchar *spice_glib_get_version_string(void) +{ + return VERSION; +} + +/** + * spice_glib_uuid_to_string: + * @uuid: (array fixed-size=16): UUID byte array + * + * Creates a string representation of @uuid, of the form + * "06e023d5-86d8-420e-8103-383e4566087a" + * + * Returns: A string that should be freed with g_free(). + * Since: 0.43 + **/ +gchar* spice_glib_uuid_to_string(const guint8 uuid[16]) +{ + return g_strdup_printf(UUID_FMT, uuid[0], uuid[1], + uuid[2], uuid[3], uuid[4], uuid[5], + uuid[6], uuid[7], uuid[8], uuid[9], + uuid[10], uuid[11], uuid[12], uuid[13], + uuid[14], uuid[15]); +} + +typedef struct { + GObject *instance; + GObject *observer; + GClosure *closure; + gulong handler_id; +} WeakHandlerCtx; + +static WeakHandlerCtx * +whc_new (GObject *instance, + GObject *observer) +{ + WeakHandlerCtx *ctx = g_new0 (WeakHandlerCtx, 1); + + ctx->instance = instance; + ctx->observer = observer; + + return ctx; +} + +static void +whc_free (WeakHandlerCtx *ctx) +{ + g_free (ctx); +} + +static void observer_destroyed_cb (gpointer, GObject *); +static void closure_invalidated_cb (gpointer, GClosure *); + +/* + * If signal handlers are removed before the object is destroyed, this + * callback will never get triggered. + */ +static void +instance_destroyed_cb (gpointer ctx_, + GObject *where_the_instance_was) +{ + WeakHandlerCtx *ctx = ctx_; + + /* No need to disconnect the signal here, the instance has gone away. */ + g_object_weak_unref (ctx->observer, observer_destroyed_cb, ctx); + g_closure_remove_invalidate_notifier (ctx->closure, ctx, + closure_invalidated_cb); + whc_free (ctx); +} + +/* Triggered when the observer is destroyed. */ +static void +observer_destroyed_cb (gpointer ctx_, + GObject *where_the_observer_was) +{ + WeakHandlerCtx *ctx = ctx_; + + g_closure_remove_invalidate_notifier (ctx->closure, ctx, + closure_invalidated_cb); + g_signal_handler_disconnect (ctx->instance, ctx->handler_id); + g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx); + whc_free (ctx); +} + +/* Triggered when either object is destroyed or the handler is disconnected. */ +static void +closure_invalidated_cb (gpointer ctx_, + GClosure *where_the_closure_was) +{ + WeakHandlerCtx *ctx = ctx_; + + g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx); + g_object_weak_unref (ctx->observer, observer_destroyed_cb, ctx); + whc_free (ctx); +} + +/* Copied from tp_g_signal_connect_object. See documentation. */ +/** + * spice_glib_signal_connect_object: (skip) + * @instance: the instance to connect to. + * @detailed_signal: a string of the form "signal-name::detail". + * @c_handler: the #GCallback to connect. + * @gobject: the object to pass as data to @c_handler. + * @connect_flags: a combination of #GConnectFlags. + * + * Similar to g_signal_connect_object() but will delete connection + * when any of the objects is destroyed. + * + * Returns: the handler id. + * Since: 0.43 + */ +gulong spice_glib_signal_connect_object (gpointer instance, + const gchar *detailed_signal, + GCallback c_handler, + gpointer gobject, + GConnectFlags connect_flags) +{ + GObject *instance_obj = G_OBJECT (instance); + + g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); + g_return_val_if_fail (detailed_signal != NULL, 0); + g_return_val_if_fail (c_handler != NULL, 0); + g_return_val_if_fail (G_IS_OBJECT (gobject), 0); + g_return_val_if_fail ( + (connect_flags & ~(G_CONNECT_AFTER|G_CONNECT_SWAPPED)) == 0, 0); + + WeakHandlerCtx *ctx = whc_new (instance_obj, gobject); + if (connect_flags & G_CONNECT_SWAPPED) + ctx->closure = g_cclosure_new_object_swap (c_handler, gobject); + else + ctx->closure = g_cclosure_new_object (c_handler, gobject); + + ctx->handler_id = g_signal_connect_closure (instance, detailed_signal, + ctx->closure, (connect_flags & G_CONNECT_AFTER) ? TRUE : FALSE); + + g_object_weak_ref (instance_obj, instance_destroyed_cb, ctx); + g_object_weak_ref (gobject, observer_destroyed_cb, ctx); + g_closure_add_invalidate_notifier (ctx->closure, ctx, + closure_invalidated_cb); + + return ctx->handler_id; +} diff --git a/src/spice-util.c b/src/spice-util.c index aefe128483ef370b00e047f4c3152b9915724e05..a92e696b9121a3bfee0998f177b5b07ae5989921 100644 --- a/src/spice-util.c +++ b/src/spice-util.c @@ -37,60 +37,23 @@ * Various functions for debugging and informational purposes. */ -static GOnce debug_once = G_ONCE_INIT; - -static void spice_util_enable_debug_messages(void) -{ - const gchar *doms = g_getenv("G_MESSAGES_DEBUG"); - if (!doms) { - g_setenv("G_MESSAGES_DEBUG", G_LOG_DOMAIN, 1); - } else if (g_str_equal(doms, "all")) { - return; - } else if (!strstr(doms, G_LOG_DOMAIN)) { - gchar *newdoms = g_strdup_printf("%s %s", doms, G_LOG_DOMAIN); - g_setenv("G_MESSAGES_DEBUG", newdoms, 1); - g_free(newdoms); - } -} - /** * spice_util_set_debug: * @enabled: %TRUE or %FALSE * * Enable or disable Spice-GTK debugging messages. + * Kept for ABI compatibility. + * + * Deprecated: 0.43: Use spice_glib_set_debug() instead **/ void spice_util_set_debug(gboolean enabled) { - /* Make sure debug_once has been initialised - * with the value of SPICE_DEBUG already, otherwise - * spice_util_get_debug() may overwrite the value - * that was just set using spice_util_set_debug() - */ - spice_util_get_debug(); - - if (enabled) { - spice_util_enable_debug_messages(); - } - - debug_once.retval = GINT_TO_POINTER(enabled); -} - -static gpointer getenv_debug(gpointer data) -{ - gboolean debug; - - debug = (g_getenv("SPICE_DEBUG") != NULL); - if (debug) - spice_util_enable_debug_messages(); - - return GINT_TO_POINTER(debug); + spice_glib_set_debug(enabled); } gboolean spice_util_get_debug(void) { - g_once(&debug_once, getenv_debug, NULL); - - return GPOINTER_TO_INT(debug_once.retval); + return spice_glib_get_debug(); } /** @@ -99,10 +62,12 @@ gboolean spice_util_get_debug(void) * Gets the version string * * Returns: Spice-GTK version as a const string. + * + * Deprecated: 0.43: Use spice_glib_get_version_string() instead **/ const gchar *spice_util_get_version_string(void) { - return VERSION; + return spice_glib_get_version_string(); } G_GNUC_INTERNAL @@ -129,88 +94,14 @@ gboolean spice_strv_contains(const GStrv strv, const gchar *str) * * Returns: A string that should be freed with g_free(). * Since: 0.22 + * + * Deprecated: 0.43: Use spice_glib_uuid_to_string() instead **/ gchar* spice_uuid_to_string(const guint8 uuid[16]) { - return g_strdup_printf(UUID_FMT, uuid[0], uuid[1], - uuid[2], uuid[3], uuid[4], uuid[5], - uuid[6], uuid[7], uuid[8], uuid[9], - uuid[10], uuid[11], uuid[12], uuid[13], - uuid[14], uuid[15]); + return spice_glib_uuid_to_string(uuid); } -typedef struct { - GObject *instance; - GObject *observer; - GClosure *closure; - gulong handler_id; -} WeakHandlerCtx; - -static WeakHandlerCtx * -whc_new (GObject *instance, - GObject *observer) -{ - WeakHandlerCtx *ctx = g_new0 (WeakHandlerCtx, 1); - - ctx->instance = instance; - ctx->observer = observer; - - return ctx; -} - -static void -whc_free (WeakHandlerCtx *ctx) -{ - g_free (ctx); -} - -static void observer_destroyed_cb (gpointer, GObject *); -static void closure_invalidated_cb (gpointer, GClosure *); - -/* - * If signal handlers are removed before the object is destroyed, this - * callback will never get triggered. - */ -static void -instance_destroyed_cb (gpointer ctx_, - GObject *where_the_instance_was) -{ - WeakHandlerCtx *ctx = ctx_; - - /* No need to disconnect the signal here, the instance has gone away. */ - g_object_weak_unref (ctx->observer, observer_destroyed_cb, ctx); - g_closure_remove_invalidate_notifier (ctx->closure, ctx, - closure_invalidated_cb); - whc_free (ctx); -} - -/* Triggered when the observer is destroyed. */ -static void -observer_destroyed_cb (gpointer ctx_, - GObject *where_the_observer_was) -{ - WeakHandlerCtx *ctx = ctx_; - - g_closure_remove_invalidate_notifier (ctx->closure, ctx, - closure_invalidated_cb); - g_signal_handler_disconnect (ctx->instance, ctx->handler_id); - g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx); - whc_free (ctx); -} - -/* Triggered when either object is destroyed or the handler is disconnected. */ -static void -closure_invalidated_cb (gpointer ctx_, - GClosure *where_the_closure_was) -{ - WeakHandlerCtx *ctx = ctx_; - - g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx); - g_object_weak_unref (ctx->observer, observer_destroyed_cb, ctx); - whc_free (ctx); -} - -/* Copied from tp_g_signal_connect_object. See documentation. */ /** * spice_g_signal_connect_object: (skip) * @instance: the instance to connect to. @@ -223,6 +114,8 @@ closure_invalidated_cb (gpointer ctx_, * when any of the objects is destroyed. * * Returns: the handler id. + * + * Deprecated: 0.43: Use spice_glib_signal_connect_object() instead */ gulong spice_g_signal_connect_object (gpointer instance, const gchar *detailed_signal, @@ -230,30 +123,8 @@ gulong spice_g_signal_connect_object (gpointer instance, gpointer gobject, GConnectFlags connect_flags) { - GObject *instance_obj = G_OBJECT (instance); - - g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); - g_return_val_if_fail (detailed_signal != NULL, 0); - g_return_val_if_fail (c_handler != NULL, 0); - g_return_val_if_fail (G_IS_OBJECT (gobject), 0); - g_return_val_if_fail ( - (connect_flags & ~(G_CONNECT_AFTER|G_CONNECT_SWAPPED)) == 0, 0); - - WeakHandlerCtx *ctx = whc_new (instance_obj, gobject); - if (connect_flags & G_CONNECT_SWAPPED) - ctx->closure = g_cclosure_new_object_swap (c_handler, gobject); - else - ctx->closure = g_cclosure_new_object (c_handler, gobject); - - ctx->handler_id = g_signal_connect_closure (instance, detailed_signal, - ctx->closure, (connect_flags & G_CONNECT_AFTER) ? TRUE : FALSE); - - g_object_weak_ref (instance_obj, instance_destroyed_cb, ctx); - g_object_weak_ref (gobject, observer_destroyed_cb, ctx); - g_closure_add_invalidate_notifier (ctx->closure, ctx, - closure_invalidated_cb); - - return ctx->handler_id; + return spice_glib_signal_connect_object(instance, detailed_signal, c_handler, + gobject, connect_flags); } G_GNUC_INTERNAL diff --git a/src/spice-util.h b/src/spice-util.h index c283b07eeb471203d57ad0a3a96a3ec0fa4751cb..07a6836660fd628e20ee84cb073d1238b3abdcf6 100644 --- a/src/spice-util.h +++ b/src/spice-util.h @@ -21,21 +21,38 @@ G_BEGIN_DECLS -SPICE_GTK_AVAILABLE_IN_ALL +SPICE_GTK_DEPRECATED_IN_0_43_FOR(spice_glib_set_debug) void spice_util_set_debug(gboolean enabled); -SPICE_GTK_AVAILABLE_IN_ALL +SPICE_GTK_DEPRECATED_IN_0_43_FOR(spice_glib_get_debug) gboolean spice_util_get_debug(void); -SPICE_GTK_AVAILABLE_IN_ALL +SPICE_GTK_DEPRECATED_IN_0_43_FOR(spice_glib_get_version_string) const gchar *spice_util_get_version_string(void); -SPICE_GTK_AVAILABLE_IN_0_8 + +SPICE_GTK_AVAILABLE_IN_0_43 +void spice_glib_set_debug(gboolean enabled); +SPICE_GTK_AVAILABLE_IN_0_43 +gboolean spice_glib_get_debug(void); +SPICE_GTK_AVAILABLE_IN_0_43 +const gchar *spice_glib_get_version_string(void); + +SPICE_GTK_DEPRECATED_IN_0_43_FOR(spice_glib_signal_connect_object) gulong spice_g_signal_connect_object(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer gobject, GConnectFlags connect_flags); -SPICE_GTK_AVAILABLE_IN_0_11 +SPICE_GTK_DEPRECATED_IN_0_43_FOR(spice_glib_uuid_to_string) gchar* spice_uuid_to_string(const guint8 uuid[16]); +SPICE_GTK_AVAILABLE_IN_0_43 +gulong spice_glib_signal_connect_object(gpointer instance, + const gchar *detailed_signal, + GCallback c_handler, + gpointer gobject, + GConnectFlags connect_flags); +SPICE_GTK_AVAILABLE_IN_0_43 +gchar* spice_glib_uuid_to_string(const guint8 uuid[16]); + #define SPICE_DEBUG(fmt, ...) \ do { \ if (G_UNLIKELY(spice_util_get_debug())) \