diff options
-rw-r--r-- | telepathy-glib/channel.c | 42 | ||||
-rw-r--r-- | tools/glib-client-gen.py | 106 | ||||
-rw-r--r-- | tools/libglibcodegen.py | 28 |
3 files changed, 155 insertions, 21 deletions
diff --git a/telepathy-glib/channel.c b/telepathy-glib/channel.c index a943e588e..63943ec5b 100644 --- a/telepathy-glib/channel.c +++ b/telepathy-glib/channel.c @@ -1889,21 +1889,20 @@ tp_channel_join_finish (TpChannel *self, _tp_implement_finish_void (self, tp_channel_join_async); } -/* tp_cli callbacks can potentially be called in a re-entrant way, - * so we can't necessarily complete @result without using an idle. */ static void -channel_close_cb (TpChannel *channel, - const GError *error, - gpointer user_data, - GObject *weak_object) +channel_close_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) { GSimpleAsyncResult *result = user_data; + TpChannel *self = TP_CHANNEL (g_async_result_get_source_object (user_data)); + GError *error = NULL; - if (error != NULL) + if (!tp_cli_channel_close_finish (self, res, &error)) { DEBUG ("Close() failed: %s", error->message); - if (tp_proxy_get_invalidated (channel) == NULL) + if (tp_proxy_get_invalidated (self) == NULL) { g_simple_async_result_set_from_error (result, error); } @@ -1911,9 +1910,11 @@ channel_close_cb (TpChannel *channel, { DEBUG ("... but channel was already invalidated, so never mind"); } + + g_error_free (error); } - g_simple_async_result_complete_in_idle (result); + g_simple_async_result_complete (result); g_object_unref (result); } @@ -1934,8 +1935,8 @@ channel_remove_self_cb (TpChannel *channel, DEBUG ("RemoveMembersWithDetails() with self handle failed; call Close()" " %s", error->message); - tp_cli_channel_call_close (channel, -1, channel_close_cb, result, - NULL, NULL); + tp_cli_channel_close_async (channel, NULL, NULL, channel_close_cb, + result); return; } @@ -2015,8 +2016,8 @@ group_prepared_cb (GObject *source, return; call_close: - tp_cli_channel_call_close (self, -1, channel_close_cb, - g_object_ref (ctx->result), NULL, NULL); + tp_cli_channel_close_async (self, NULL, NULL, channel_close_cb, + g_object_ref (ctx->result)); leave_ctx_free (ctx); } @@ -2065,8 +2066,8 @@ tp_channel_leave_async (TpChannel *self, { DEBUG ("Channel doesn't implement Group; fallback to Close()"); - tp_cli_channel_call_close (self, -1, channel_close_cb, result, - NULL, NULL); + tp_cli_channel_close_async (self, NULL, NULL, channel_close_cb, + result); return; } @@ -2130,8 +2131,7 @@ tp_channel_close_async (TpChannel *self, result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, tp_channel_close_async); - tp_cli_channel_call_close (self, -1, channel_close_cb, result, - NULL, NULL); + tp_cli_channel_close_async (self, NULL, NULL, channel_close_cb, result); } /** @@ -2167,8 +2167,8 @@ channel_destroy_cb (TpChannel *channel, { DEBUG ("Destroy() failed; call Close(): %s", error->message); - tp_cli_channel_call_close (channel, -1, channel_close_cb, result, - NULL, NULL); + tp_cli_channel_close_async (channel, NULL, NULL, channel_close_cb, + result); return; } @@ -2210,8 +2210,8 @@ tp_channel_destroy_async (TpChannel *self, { DEBUG ("Channel doesn't implement Destroy; fallback to Close()"); - tp_cli_channel_call_close (self, -1, channel_close_cb, result, - NULL, NULL); + tp_cli_channel_close_async (self, NULL, NULL, channel_close_cb, + result); return; } diff --git a/tools/glib-client-gen.py b/tools/glib-client-gen.py index e2ea3fc7b..94886cbca 100644 --- a/tools/glib-client-gen.py +++ b/tools/glib-client-gen.py @@ -414,6 +414,8 @@ class Generator(object): ret_count = 0 in_args = [] out_args = [] + in_signature = '' + out_signature = '' for arg in method.getElementsByTagName('arg'): name = arg.getAttribute('name') @@ -437,8 +439,10 @@ class Generator(object): info = type_to_gtype(type) if direction != 'out': in_args.append((name, info, tp_type, arg)) + in_signature = in_signature + type else: out_args.append((name, info, tp_type, arg)) + out_signature = out_signature + type # Async reply callback type @@ -871,6 +875,108 @@ class Generator(object): self.do_method_reentrant(method, iface_lc, member, member_lc, in_args, out_args, collect_callback) + # Async stub (GVariant-style) + + # Example: + # void tp_cli_dbus_properties_get_properties_async + # (gpointer proxy, + # GVariant *parameters, + # GCancellable *cancellable, + # GAsyncReadyCallback callback, + # gpointer user_data); + # GVariant *tp_cli_dbus_properties_get_properties_finish + # (gpointer proxy, + + async_name = '%s_%s_%s_async' % (self.prefix_lc, iface_lc, member_lc) + finish_name = '%s_%s_%s_finish' % (self.prefix_lc, iface_lc, member_lc) + + self.d('/**') + self.d(' * %s:' % async_name) + self.d(' * @proxy: %s' % self.proxy_doc) + self.d(' * @parameters: a #GVariant of type "(%s)"' % in_signature) + self.d(' * @cancellable: %NULL or a cancellation object') + self.d(' * @callback: a #GAsyncReadyCallback to call when the method') + self.d(' * returns, times out or is cancelled, or %NULL') + self.d(' * @user_data: user data for @callback') + self.d(' *') + self.d(' * Call the D-Bus method "%s.%s".' % (self.iface_dbus, member)) + self.d(' *') + self.d(' * If @parameters is a floating #GVariant reference, it is') + self.d(' * consumed, allowing for convenient "inline" use of') + self.d(' * g_variant_new() (as for g_dbus_connection_call()).') + self.d(' */') + + self.d('/**') + self.d(' * %s:' % finish_name) + self.d(' * @proxy: %s' % self.proxy_doc) + self.d(' * @result: a result from the #GAsyncReadyCallback') + self.d(' * @error: return location for error or %NULL') + self.d(' *') + self.d(' * Examine the result of the D-Bus method "%s.%s".' + % (self.iface_dbus, member)) + self.d(' *') + self.d(' * If a faulty implementation of the method returns an') + self.d(' * unexpected signature, it is turned into a #GError') + self.d(' * and %NULL is returned instead.') + self.d(' *') + self.d(' * Returns: (transfer full): a #GVariant of type "(%s)"' + % out_signature) + self.d(' * or %NULL on error') + self.d(' */') + + self.h('#ifndef __GTK_DOC_IGNORE__') + self.h('static inline') + self.h('#endif /* __GTK_DOC_IGNORE__ */') + self.h('void %s (%s proxy,' % (async_name, self.proxy_arg)) + self.h(' GVariant *parameters,') + self.h(' GCancellable *cancellable,') + self.h(' GAsyncReadyCallback callback,') + self.h(' gpointer user_data);') + + self.h('#ifndef __GTK_DOC_IGNORE__') + self.h('static inline') + self.h('#endif /* __GTK_DOC_IGNORE__ */') + self.h('GVariant *%s (%s proxy,' % (finish_name, self.proxy_arg)) + self.h(' GAsyncResult *result,') + self.h(' GError **error);') + + self.h('#ifndef __GTK_DOC_IGNORE__') + self.h('static inline void') + self.h('%s (%s proxy,' % (async_name, self.proxy_arg)) + self.h(' GVariant *parameters,') + self.h(' GCancellable *cancellable,') + self.h(' GAsyncReadyCallback callback,') + self.h(' gpointer user_data)') + self.h('{') + self.h(' TpProxy *cast_to_proxy = (TpProxy *) proxy;') + self.h('') + self.h(' g_return_if_fail (%s (proxy));' % self.proxy_assert) + self.h(' g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));') + self.h(' g_return_if_fail (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(%s)")));' % in_signature) + self.h(' dbus_g_connection_call_async (cast_to_proxy->dbus_connection,') + self.h(' cast_to_proxy->bus_name,') + self.h(' cast_to_proxy->object_path,') + self.h(' "%s",' % self.iface_dbus) + self.h(' "%s",' % member) + self.h(' parameters,') + self.h(' G_VARIANT_TYPE ("(%s)"),' % out_signature) + self.h(' G_DBUS_CALL_FLAGS_NONE,') + self.h(' -1,') + self.h(' cancellable,') + self.h(' callback,') + self.h(' user_data);') + self.h(' g_variant_ref_sink (parameters);') + self.h(' g_variant_unref (parameters);') + self.h('}') + self.h('static inline GVariant *') + self.h('%s (%s proxy,' % (finish_name, self.proxy_arg)) + self.h(' GAsyncResult *result,') + self.h(' GError **error)') + self.h('{') + self.h(' return dbus_g_connection_call_finish (result, error);') + self.h('}') + self.h('#endif /* __GTK_DOC_IGNORE__ */') + # leave a gap for the end of the method self.d('') self.b('') diff --git a/tools/libglibcodegen.py b/tools/libglibcodegen.py index 6a9d21485..3bd9ee3db 100644 --- a/tools/libglibcodegen.py +++ b/tools/libglibcodegen.py @@ -170,3 +170,31 @@ def type_to_gtype(s): # we just don't know .. raise Exception, "don't know the GType for " + s + +def type_to_gdbus_info(s): + if s == 'y': #byte + return dict(ctype='guchar ') + elif s == 'b': #boolean + return dict(ctype='gboolean ') + elif s == 'n': #int16 + return dict(ctype='gint16 ') + elif s == 'q': #uint16 + return dict(ctype='guint16 ') + elif s == 'i': #int32 + return dict(ctype='gint32 ') + elif s == 'u': #uint32 + return dict(ctype='guint32 ') + elif s == 'x': #int64 + return dict(ctype='gint64 ') + elif s == 't': #uint64 + return dict(ctype='guint64 ') + elif s == 'd': #double + return dict(ctype='gdouble ') + elif s == 's': #string + return dict(ctype='gchar *', pointer=True) + elif s == 'g': #signature - FIXME + return dict(ctype='gchar *', pointer=True) + elif s == 'o': #object path + return dict(ctype='gchar *', pointer=True) + else: + return dict(ctype='GVariant *', pointer=True, variant=True) |