summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2010-06-17 14:47:31 -0400
committerDavid Zeuthen <davidz@redhat.com>2010-06-17 14:47:31 -0400
commit427d3c5ea1f4af5d1f26f70ffae5606eb0a70618 (patch)
treee92b7bfaebfa7b10ceefb2c2a047cac67b8b7eac
parent5700b0c08cd5c37097af442d784c489e88e24cb5 (diff)
Handle signals
-rw-r--r--src/gdbusgi.c411
-rw-r--r--src/myfrobnicator.c69
-rw-r--r--src/myfrobnicator.h7
-rw-r--r--src/test.c118
4 files changed, 544 insertions, 61 deletions
diff --git a/src/gdbusgi.c b/src/gdbusgi.c
index f34270a..04a1512 100644
--- a/src/gdbusgi.c
+++ b/src/gdbusgi.c
@@ -1024,19 +1024,26 @@ convert_gvariant_to_gi (GVariant *variant,
typedef struct
{
GObject *object;
+ gchar *object_path;
+ GDBusConnection *connection;
GDBusInterfaceInfo *info;
gpointer user_data;
GDestroyNotify user_data_free_func;
GHashTable *dbus_method_name_to_method_data;
+ GHashTable *g_signal_name_to_signal_data;
} ExportData;
static void
export_data_free (ExportData *data)
{
g_hash_table_unref (data->dbus_method_name_to_method_data);
+ g_hash_table_unref (data->g_signal_name_to_signal_data);
if (data->object != NULL)
g_object_unref (data->object);
+ g_free (data->object_path);
+ if (data->connection != NULL)
+ g_object_unref (data->connection);
if (data->info != NULL)
g_dbus_interface_info_unref (data->info);
if (data->user_data_free_func != NULL)
@@ -1047,19 +1054,6 @@ export_data_free (ExportData *data)
/* ---------------------------------------------------------------------------------------------------- */
typedef struct _ArgData ArgData;
-
-typedef struct
-{
- GIFunctionInfo *method;
- GDBusMethodInfo *dbus_method;
-
- guint num_in_args; /* number of GIArgInfo where direction is IN or IN_OUT */
- guint num_out_args; /* number of GIArgInfo where direction is OUT or IN_OUT */
-
- GPtrArray *args;
- ArgData *return_value;
-} MethodData;
-
struct _ArgData
{
GIDirection direction;
@@ -1101,20 +1095,6 @@ arg_data_free (ArgData *data)
g_free (data);
}
-static void
-method_data_free (MethodData *data)
-{
- g_base_info_unref (data->method);
- if (data->dbus_method != NULL)
- g_dbus_method_info_unref (data->dbus_method);
- g_ptr_array_unref (data->args);
- if (data->return_value != NULL)
- arg_data_free (data->return_value);
- g_free (data);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
static gchar *
arg_data_print (ArgData *data)
{
@@ -1145,6 +1125,32 @@ arg_data_print (ArgData *data)
return g_string_free (str, FALSE);
}
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+ GIFunctionInfo *method;
+ GDBusMethodInfo *dbus_method;
+
+ guint num_in_args; /* number of GIArgInfo where direction is IN or IN_OUT */
+ guint num_out_args; /* number of GIArgInfo where direction is OUT or IN_OUT */
+
+ GPtrArray *args;
+ ArgData *return_value;
+} MethodData;
+
+static void
+method_data_free (MethodData *data)
+{
+ g_base_info_unref (data->method);
+ if (data->dbus_method != NULL)
+ g_dbus_method_info_unref (data->dbus_method);
+ g_ptr_array_unref (data->args);
+ if (data->return_value != NULL)
+ arg_data_free (data->return_value);
+ g_free (data);
+}
+
static gchar *
method_data_print (MethodData *data,
guint indent)
@@ -1206,6 +1212,69 @@ method_data_dump (MethodData *data,
gchar *s;
s = method_data_print (data, indent);
g_print ("------------------------------------------------------------------------\n"
+ "METHOD:\n"
+ "%s"
+ "------------------------------------------------------------------------\n",
+ s);
+ g_free (s);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+ GISignalInfo *signal;
+ GDBusSignalInfo *dbus_signal;
+
+ /* all args in the in direction and return values are not supported */
+ GPtrArray *args;
+} SignalData;
+
+static void
+signal_data_free (SignalData *data)
+{
+ g_base_info_unref (data->signal);
+ if (data->dbus_signal != NULL)
+ g_dbus_signal_info_unref (data->dbus_signal);
+ g_ptr_array_unref (data->args);
+ g_free (data);
+}
+
+static gchar *
+signal_data_print (SignalData *data,
+ guint indent)
+{
+ GString *str;
+ guint n;
+ gchar *s;
+
+ str = g_string_new (NULL);
+ g_string_append_printf (str,
+ "%*sName: %s\n"
+ "%*sD-Bus name: %s\n",
+ indent, "", g_base_info_get_name ((GIBaseInfo *) data->signal),
+ indent, "", data->dbus_signal->name);
+ for (n = 0; n < data->args->len; n++)
+ {
+ ArgData *ad = data->args->pdata[n];
+ s = arg_data_print (ad);
+ g_string_append_printf (str,
+ "%*s arg[%2d]: %s\n",
+ indent, "", n, s);
+ g_free (s);
+ }
+
+ return g_string_free (str, FALSE);
+}
+
+static void
+signal_data_dump (SignalData *data,
+ guint indent)
+{
+ gchar *s;
+ s = signal_data_print (data, indent);
+ g_print ("------------------------------------------------------------------------\n"
+ "SIGNAL:\n"
"%s"
"------------------------------------------------------------------------\n",
s);
@@ -1893,16 +1962,138 @@ get_method_data (GIFunctionInfo *method,
return ret;
}
+/* ---------------------------------------------------------------------------------------------------- */
+
+static SignalData *
+get_signal_data (GISignalInfo *signal,
+ const gchar *dbus_name,
+ GError **error)
+{
+ SignalData *ret;
+ GICallableInfo *callable;
+ GPtrArray *dbus_args;
+ ArgData *ad;
+ guint n;
+
+ dbus_args = g_ptr_array_new ();
+
+ ret = g_new0 (SignalData, 1);
+ ret->signal = g_base_info_ref ((GIBaseInfo *) signal);
+ ret->args = g_ptr_array_new_with_free_func ((GDestroyNotify) arg_data_free);
+
+ /* this/self */
+ ad = arg_data_new ();
+ ad->direction = GI_DIRECTION_IN;
+ g_ptr_array_add (ret->args, ad);
+
+ callable = (GICallableInfo *) signal;
+
+ g_print ("Using dbus name `%s' for signal `%s'\n", dbus_name, g_base_info_get_name ((GIBaseInfo *) signal));
+
+ /* TODO: reject if it has a return value */
+
+ /* Go through all parameters */
+ for (n = 0; n < (guint) g_callable_info_get_n_args (callable); n++)
+ {
+ GIArgInfo *arg;
+ GITypeInfo *type;
+ GDBusArgInfo *arg_info;
+ gboolean not_on_dbus;
+ guint m;
+
+ /* TODO: reject out and inout params */
+
+ /* Don't export arg on D-Bus if it's used for another arg (e.g. a length parameter for an array) */
+ not_on_dbus = FALSE;
+
+ arg = g_callable_info_get_arg (callable, n);
+ type = g_arg_info_get_type (arg);
+
+ ad = arg_data_new ();
+ ad->direction = g_arg_info_get_direction (arg);
+ ad->arg_info = g_base_info_ref ((GIBaseInfo *) arg);
+ ad->type_info = g_arg_info_get_type (arg);
+ ad->transfer = g_arg_info_get_ownership_transfer (arg);
+
+ /* Now figure out if this arg is a length param for an array */
+ for (m = 0; m < (guint) g_callable_info_get_n_args (callable) && !not_on_dbus; m++)
+ {
+ /* TODO: also check return value! */
+ GIArgInfo *other_arg;
+ GITypeInfo *other_type;
+ other_arg = g_callable_info_get_arg (callable, m);
+ other_type = g_arg_info_get_type (other_arg);
+ /* get_array_length() assumes first arg is this/self */
+ if (g_type_info_get_array_length (other_type) == (gint) n + 1)
+ {
+ not_on_dbus = TRUE;
+ ad->is_array_len_for_position = n;
+ }
+ g_base_info_unref ((GIBaseInfo *) other_type);
+ g_base_info_unref ((GIBaseInfo *) other_arg);
+ }
+
+ /* Set if this is an array using another arg as a length parameter */
+ ad->array_len_position = g_type_info_get_array_length (type);
+
+ arg_info = NULL;
+ if (!not_on_dbus)
+ {
+ arg_info = get_arg_info (callable, arg, error);
+ if (arg_info == NULL)
+ {
+ g_prefix_error (error,
+ "Error processing argument `%s' of signal `%s': ",
+ g_base_info_get_name ((GIBaseInfo *) arg),
+ g_base_info_get_name ((GIBaseInfo *) signal));
+ g_base_info_unref ((GIBaseInfo *) arg);
+ g_base_info_unref ((GIBaseInfo *) type);
+ signal_data_free (ret);
+ ret = NULL;
+ goto out;
+ }
+ }
+
+ ad->dbus_arg_info = arg_info != NULL ? g_dbus_arg_info_ref (arg_info) : NULL;
+
+ if (arg_info != NULL)
+ g_ptr_array_add (dbus_args, arg_info);
+ g_ptr_array_add (ret->args, ad);
+
+ if (arg_info != NULL)
+ g_dbus_arg_info_unref (arg_info);
+ g_base_info_unref ((GIBaseInfo *) arg);
+ g_base_info_unref ((GIBaseInfo *) type);
+ }
+ g_ptr_array_add (dbus_args, NULL);
+
+ ret->dbus_signal = g_new0 (GDBusSignalInfo, 1);
+ ret->dbus_signal->ref_count = 1;
+ ret->dbus_signal->name = g_strdup (dbus_name);
+ g_ptr_array_ref (dbus_args);
+ ret->dbus_signal->args = (GDBusArgInfo **) g_ptr_array_free (dbus_args, FALSE);
+
+ out:
+ g_ptr_array_foreach (dbus_args, (GFunc) g_dbus_arg_info_unref, NULL);
+ g_ptr_array_unref (dbus_args);
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static GDBusInterfaceInfo *
compute_introspection_data (GObject *object,
ExportData *data,
GError **error)
{
+ GPtrArray *signal_infos;
GPtrArray *method_infos;
GDBusInterfaceInfo *ret;
GIRepository *repo;
GIBaseInfo *info;
guint n;
+ guint n_methods;
+ guint n_signals;
ret = NULL;
info = NULL;
@@ -1937,7 +2128,8 @@ compute_introspection_data (GObject *object,
g_assert (GI_IS_OBJECT_INFO (info));
method_infos = g_ptr_array_new ();
- for (n = 0; n < (guint) g_object_info_get_n_methods ((GIObjectInfo *) info); n++)
+ n_methods = g_object_info_get_n_methods ((GIObjectInfo *) info);
+ for (n = 0; n < n_methods; n++)
{
GIFunctionInfo *method;
const gchar *dbus_name;
@@ -1967,10 +2159,48 @@ compute_introspection_data (GObject *object,
g_strdup (dbus_name),
method_data);
}
+ g_base_info_unref ((GIBaseInfo *) method);
}
g_ptr_array_add (method_infos, NULL);
ret->methods = (GDBusMethodInfo **) g_ptr_array_free (method_infos, FALSE);
+ signal_infos = g_ptr_array_new ();
+ n_signals = g_object_info_get_n_signals ((GIObjectInfo *) info);
+ for (n = 0; n < n_signals; n++)
+ {
+ GISignalInfo *signal;
+ const gchar *dbus_name;
+
+ signal = g_object_info_get_signal ((GIObjectInfo *) info, n);
+ dbus_name = g_base_info_get_attribute ((GIBaseInfo *) signal, "gdbus.signal");
+ if (dbus_name != NULL)
+ {
+ SignalData *signal_data;
+
+ signal_data = get_signal_data (signal,
+ dbus_name,
+ error);
+ if (signal_data == NULL)
+ {
+ g_ptr_array_foreach (signal_infos, (GFunc) g_dbus_signal_info_unref, NULL);
+ g_ptr_array_unref (signal_infos);
+ g_dbus_interface_info_unref (ret);
+ ret = NULL;
+ goto out;
+ }
+ g_ptr_array_add (signal_infos, signal_data->dbus_signal);
+
+ signal_data_dump (signal_data, 0);
+
+ g_hash_table_insert (data->g_signal_name_to_signal_data,
+ g_strdup (g_base_info_get_name ((GIBaseInfo *) signal_data->signal)),
+ signal_data);
+ }
+ g_base_info_unref ((GIBaseInfo *) signal);
+ }
+ g_ptr_array_add (signal_infos, NULL);
+ ret->signals = (GDBusSignalInfo **) g_ptr_array_free (signal_infos, FALSE);
+
out:
if (info != NULL)
g_base_info_unref (info);
@@ -1979,6 +2209,104 @@ compute_introspection_data (GObject *object,
/* ---------------------------------------------------------------------------------------------------- */
+typedef struct
+{
+ GClosure parent_instance;
+
+ gulong signal_handler_id;
+ SignalData *signal_data;
+ ExportData *export_data;
+} GDBusClosure;
+
+static GVariant *
+process_signal_args (guint n_param_values,
+ const GValue *param_values,
+ SignalData *data)
+{
+ guint n;
+ ArgData *ad;
+ GVariant *value;
+ GVariantType *gvariant_type;
+ GVariantBuilder builder;
+ GArgument *array_len_arg;
+ GITypeInfo *array_len_arg_type;
+ GArgument **args;
+
+ g_assert_cmpint (n_param_values, ==, data->args->len);
+
+ /* Convert GValue to GArgument
+ *
+ * TODO: verify that the conversion really is that simple...
+ */
+ args = g_new0 (GArgument *, n_param_values);
+ for (n = 0; n < n_param_values; n++)
+ args[n] = (GArgument *) &(param_values[n].data[0]);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
+ for (n = 0; n < data->args->len; n++)
+ {
+ ad = data->args->pdata[n];
+
+ if (ad->dbus_arg_info == NULL)
+ continue;
+
+ array_len_arg = NULL;
+ array_len_arg_type = NULL;
+ if (ad->array_len_position != -1)
+ {
+ array_len_arg = args[ad->array_len_position];
+ array_len_arg_type = ((ArgData *) data->args->pdata[ad->array_len_position])->type_info;
+ }
+
+ gvariant_type = g_variant_type_new (ad->dbus_arg_info->signature);
+ value = convert_gi_to_gvariant (args[n],
+ ad->type_info,
+ gvariant_type,
+ array_len_arg,
+ array_len_arg_type);
+ g_variant_ref_sink (value);
+ g_variant_builder_add_value (&builder, value);
+ g_variant_unref (value);
+ g_variant_type_free (gvariant_type);
+ }
+
+ g_free (args);
+
+ return g_variant_builder_end (&builder);
+}
+
+static void
+marshal_signal_onto_dbus (GClosure *_closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ GDBusClosure *closure = (GDBusClosure *) _closure;
+ GVariant *variant;
+ GError *error;
+
+ variant = process_signal_args (n_param_values,
+ param_values,
+ closure->signal_data);
+ error = NULL;
+ if (!g_dbus_connection_emit_signal (closure->export_data->connection,
+ NULL,
+ closure->export_data->object_path,
+ closure->export_data->info->name,
+ closure->signal_data->dbus_signal->name,
+ variant,
+ &error))
+ {
+ g_warning ("Error emitting D-Bus signal `%s' in response to G signal: %s",
+ closure->signal_data->dbus_signal->name,
+ error->message);
+ g_error_free (error);
+ }
+ g_variant_unref (variant);
+}
+
guint
g_dbus_connection_register_gobject (GDBusConnection *connection,
GObject *object,
@@ -1996,6 +2324,8 @@ g_dbus_connection_register_gobject (GDBusConnection *connection,
data = g_new0 (ExportData, 1);
data->object = g_object_ref (object);
+ data->object_path = g_strdup (object_path);
+ data->connection = g_object_ref (connection);
data->user_data = user_data;
data->user_data_free_func = user_data_free_func;
@@ -2003,6 +2333,10 @@ g_dbus_connection_register_gobject (GDBusConnection *connection,
g_str_equal,
g_free,
(GDestroyNotify) method_data_free);
+ data->g_signal_name_to_signal_data = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) signal_data_free);
data->info = compute_introspection_data (object,
data,
@@ -2010,6 +2344,27 @@ g_dbus_connection_register_gobject (GDBusConnection *connection,
if (data->info == NULL)
goto fail;
+ /* Set up signal handlers for all exported signals */
+ GHashTableIter iter;
+ const gchar *g_signal_name;
+ SignalData *signal_data;
+ g_hash_table_iter_init (&iter, data->g_signal_name_to_signal_data);
+ while (g_hash_table_iter_next (&iter, (gpointer*) &g_signal_name, (gpointer*) &signal_data))
+ {
+ GDBusClosure *closure;
+
+ closure = (GDBusClosure *) g_closure_new_simple (sizeof (GDBusClosure), NULL);
+ g_closure_set_marshal ((GClosure *) closure, marshal_signal_onto_dbus);
+
+ closure->signal_data = signal_data;
+ closure->signal_handler_id = g_signal_connect_closure (object,
+ g_signal_name,
+ (GClosure *) closure,
+ TRUE);
+ closure->export_data = data;
+ /* TODO: we need to unregister these handlers in export_data_free() */
+ }
+
return g_dbus_connection_register_object (connection,
object_path,
data->info,
diff --git a/src/myfrobnicator.c b/src/myfrobnicator.c
index 49c0cfd..9936e62 100644
--- a/src/myfrobnicator.c
+++ b/src/myfrobnicator.c
@@ -32,6 +32,14 @@ struct _MyFrobnicatorPrivate
guint foo;
};
+enum
+{
+ LASER_FIRED_SIGNAL,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
G_DEFINE_TYPE (MyFrobnicator, my_frobnicator, G_TYPE_OBJECT);
static void
@@ -42,6 +50,31 @@ my_frobnicator_init (MyFrobnicator *frobnicator)
static void
my_frobnicator_class_init (MyFrobnicatorClass *klass)
{
+ /**
+ * MyFrobnicator::laser-fired:
+ * @frobnicator: A #MyFrobnicator.
+ * @str: A string.
+ * @carray_as: (array) (element-type utf8):
+ * @garray_ai: (array zero-terminated="0") (element-type gint):
+ *
+ * Check that signal parameters are marshalled correctly onto the
+ * bus. Btw, Hmm, apparently (array length=carray_ai_len) doesn't
+ * work yet. TODO: file bug
+ *
+ * Attributes: (gdbus.signal LaserFired)
+ */
+ signals[LASER_FIRED_SIGNAL] = g_signal_new ("laser-fired",
+ MY_TYPE_FROBNICATOR,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MyFrobnicatorClass, laser_fired),
+ NULL, /* accumulator */
+ NULL, /* accu_data */
+ NULL, /* we don't need a C marshaller if we're only using D-Bus */
+ G_TYPE_NONE,
+ 3,
+ G_TYPE_STRING,
+ G_TYPE_STRV,
+ G_TYPE_ARRAY);
}
MyFrobnicator *
@@ -406,3 +439,39 @@ my_frobnicator_return_arrays (MyFrobnicator *frobnicator,
as[2] = g_strdup ("0.03");
*out_carray_as = as;
}
+
+/**
+ * my_frobnicator_fire_laser:
+ * @frobnicator:
+ *
+ * Emits the laser-fired signal.
+ *
+ * Attributes: (gdbus.method FireLaser)
+ */
+void
+my_frobnicator_fire_laser (MyFrobnicator *frobnicator)
+{
+ const gchar *strv[4];
+ GArray *garray_ai;
+
+ strv[0] = "zero";
+ strv[1] = "two";
+ strv[2] = "three";
+ strv[3] = NULL;
+
+ garray_ai = g_array_new (FALSE, FALSE, sizeof (gint));
+ g_array_set_size (garray_ai, 3);
+ ((gint *) (garray_ai)->data)[0] = 10;
+ ((gint *) (garray_ai)->data)[1] = 20;
+ ((gint *) (garray_ai)->data)[2] = 30;
+
+ g_signal_emit (frobnicator,
+ signals[LASER_FIRED_SIGNAL],
+ 0,
+ "woot",
+ strv,
+ garray_ai);
+
+ g_array_unref (garray_ai);
+}
+
diff --git a/src/myfrobnicator.h b/src/myfrobnicator.h
index ea9ab42..b299b69 100644
--- a/src/myfrobnicator.h
+++ b/src/myfrobnicator.h
@@ -62,6 +62,11 @@ struct _MyFrobnicatorClass
{
/*< private >*/
GObjectClass parent_class;
+
+ void (*laser_fired) (MyFrobnicator *frobnicator,
+ const gchar *str,
+ const gchar *const *carray_as,
+ GArray *garray_ai);
};
GType my_frobnicator_get_type (void) G_GNUC_CONST;
@@ -128,6 +133,8 @@ void my_frobnicator_return_arrays (MyFrobnicator *frobnicator,
gchar ***out_carray_as_nzt,
gchar ***out_carray_as);
+void my_frobnicator_fire_laser (MyFrobnicator *frobnicator);
+
G_END_DECLS
#endif /* __MY_FROBNICATOR_H__ */
diff --git a/src/test.c b/src/test.c
index 5e0f80a..191597f 100644
--- a/src/test.c
+++ b/src/test.c
@@ -31,6 +31,7 @@
#include "myfrobnicator.h"
static GMainLoop *loop;
+static GMainLoop *thread_loop;
static MyFrobnicator *obj;
static gboolean just_serve = FALSE;
@@ -53,6 +54,20 @@ on_bus_acquired (GDBusConnection *connection,
}
static void
+run_tests_on_signal_received (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ GVariant **signal_params = user_data;
+ *signal_params = g_variant_ref (parameters);
+ g_main_loop_quit (thread_loop);
+}
+
+static void
run_test (GDBusConnection *connection)
{
GError *error;
@@ -209,45 +224,41 @@ run_test (GDBusConnection *connection)
"org.MyProject.Frobnicator",
"SimpleTypes",
g_variant_new ("(bnqiuxtiudsog)",
- TRUE, 10, 11, 12, 13, G_GINT64_CONSTANT (14), G_GUINT64_CONSTANT (15), 16, 17, 18.5,
- "a string", "/the/path", "assgit"),
+ TRUE,
+ 10,
+ 11,
+ 12,
+ 13,
+ G_GINT64_CONSTANT (14),
+ G_GUINT64_CONSTANT (15),
+ 16,
+ 17,
+ 18.5,
+ "a string",
+ "/the/path",
+ "assgit"),
G_VARIANT_TYPE ("(bnqiuxtiudsog)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL, /* GCancellable */
&error);
g_assert_no_error (error);
- {
- gboolean v_boolean;
- gint16 v_int16;
- guint16 v_uint16;
- gint32 v_int32;
- guint32 v_uint32;
- gint64 v_int64;
- guint64 v_uint64;
- gint v_int;
- guint v_uint;
- gdouble v_double;
- const gchar *v_string;
- const gchar *v_object_path;
- const gchar *v_signature;
- g_variant_get (ret,
- "(bnqiuxtiud&s&o&g)",
- &v_boolean, &v_int16, &v_uint16, &v_int32, &v_uint32,
- &v_int64, &v_uint64, &v_int, &v_uint, &v_double,
- &v_string, &v_object_path, &v_signature);
- g_assert (!!v_boolean == !TRUE);
- g_assert_cmpint (v_int16, ==, 10 + 100);
- g_assert_cmpint (v_uint16, ==, 11 + 101);
- g_assert_cmpint (v_int32, ==, 12 + 102);
- g_assert_cmpint (v_uint32, ==, 13 + 103);
- g_assert_cmpint (v_int64, ==, 14 + 104);
- g_assert_cmpint (v_uint64, ==, 15 + 105);
- g_assert_cmpint (v_int, ==, 16 + 106);
- g_assert_cmpint (v_uint, ==, 17 + 107);
- g_assert_cmpint (v_double, ==, 18.5 + 108);
- }
+ other = g_variant_new_parsed ("(false, "
+ "int16 110, "
+ "uint16 112, "
+ "114, "
+ "uint32 116, "
+ "int64 118, "
+ "uint64 120, "
+ "122, "
+ "uint32 124, "
+ "126.5, "
+ "\"You passed `a string'\", "
+ "objectpath '/you/passed/the/path', "
+ "signature 'assgitassgit')");
+ g_assert (g_variant_equal (ret, other));
g_variant_unref (ret);
+ g_variant_unref (other);
error = NULL;
ret = g_dbus_connection_call_sync (connection,
@@ -295,6 +306,48 @@ run_test (GDBusConnection *connection)
g_assert (g_variant_equal (ret, other));
g_variant_unref (ret);
g_variant_unref (other);
+
+ guint signal_sub_id;
+ GVariant *signal_params;
+ signal_sub_id = g_dbus_connection_signal_subscribe (connection,
+ NULL, /* sender */
+ "org.MyProject.Frobnicator",
+ "LaserFired",
+ "/org/My/Frobnicator",
+ NULL, /* arg0 */
+ run_tests_on_signal_received,
+ &signal_params,
+ NULL); /* user_data_free_func */
+ g_assert (signal_sub_id > 0);
+
+ error = NULL;
+ signal_params = NULL;
+ ret = g_dbus_connection_call_sync (connection,
+ "org.My.Service",
+ "/org/My/Frobnicator",
+ "org.MyProject.Frobnicator",
+ "FireLaser",
+ NULL,
+ G_VARIANT_TYPE ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL, /* GCancellable */
+ &error);
+ g_assert_no_error (error);
+ g_variant_unref (ret);
+ g_assert (signal_params == NULL);
+
+ g_main_loop_run (thread_loop);
+ g_assert (signal_params != NULL);
+
+ other = g_variant_new_parsed ("('woot', "
+ "['zero', 'two', 'three'], "
+ "[10, 20, 30])");
+ g_assert (g_variant_equal (signal_params, other));
+ g_variant_unref (signal_params);
+ g_variant_unref (other);
+
+ g_dbus_connection_signal_unsubscribe (connection, signal_sub_id);
}
static gpointer
@@ -302,7 +355,6 @@ run_test_thread_func (gpointer user_data)
{
GDBusConnection *connection = G_DBUS_CONNECTION (user_data);
GMainContext *thread_context;
- GMainLoop *thread_loop;
thread_context = g_main_context_new ();
thread_loop = g_main_loop_new (thread_context, FALSE);