# HG changeset patch # User Piotr Zielinski # Date 1120962592 0 # Node ID f54740547c95f09e5894b465a71088d2b5df08e6 # Parent b2ace57224e280d2cac8c17fb4e071695c388b6b [gaim-migrate @ 13092] All gaim signals are automatically relayed to dbus. committer: Tailor Script diff -r b2ace57224e2 -r f54740547c95 src/dbus-server.c --- a/src/dbus-server.c Sat Jul 09 20:27:57 2005 +0000 +++ b/src/dbus-server.c Sun Jul 10 02:29:52 2005 +0000 @@ -29,6 +29,7 @@ #include #include #include +#include #include "account.h" #include "blist.h" @@ -39,46 +40,281 @@ #include "core.h" #include "value.h" -/**************************************************************************/ -/** @name Lots of GObject crap I don't understand */ +static gint gaim_dbus_pointer_to_id(gpointer node); +static gpointer gaim_dbus_id_to_pointer(gint id, GaimDBusPointerType type); + + /**************************************************************************/ - -typedef struct GaimObject GaimObject; -typedef struct GaimObjectClass GaimObjectClass; +/** @name Lots of GObject stuff I don't really understand */ +/**************************************************************************/ GType gaim_object_get_type(void); -struct GaimObject { +struct _GaimObject { GObject parent; + + int ping_signal_id; }; -struct GaimObjectClass { +typedef struct { GObjectClass parent; -}; +} GaimObjectClass; + + -#define GAIM_TYPE_OBJECT (gaim_object_get_type ()) -#define GAIM_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GAIM_TYPE_OBJECT, GaimObject)) -#define GAIM_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAIM_TYPE_OBJECT, GaimObjectClass)) -#define GAIM_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GAIM_TYPE_OBJECT)) -#define GAIM_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAIM_TYPE_OBJECT)) -#define GAIM_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAIM_TYPE_OBJECT, GaimObjectClass)) +#define GAIM_DBUS_TYPE_OBJECT (gaim_object_get_type ()) +#define GAIM_DBUS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GAIM_DBUS_TYPE_OBJECT, GaimObject)) +#define GAIM_DBUS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAIM_DBUS_TYPE_OBJECT, GaimObjectClass)) +#define GAIM_DBUS_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GAIM_DBUS_TYPE_OBJECT)) +#define GAIM_DBUS_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAIM_DBUS_TYPE_OBJECT)) +#define GAIM_DBUS_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAIM_DBUS_TYPE_OBJECT, GaimObjectClass)) G_DEFINE_TYPE(GaimObject, gaim_object, G_TYPE_OBJECT) +GaimObject *gaim_dbus_object; +static GQuark gaim_object_error_quark; -static void -gaim_object_init(GaimObject *obj) -{ +static const char* null_to_empty(const char *s) { + if (s) + return s; + else + return ""; } -static void -gaim_object_class_init(GaimObjectClass *mobject_class) + + +static void gaim_object_class_init(GaimObjectClass *klass) { } -static GObject *gaim_object; -static GQuark gaim_object_error_quark; + + +/**************************************************************************/ +/** @name Signals */ +/**************************************************************************/ + +/* used in #gaim_values_to_gvalues, undefined afterwards */ +#define my_arg(type) (ptr != NULL ? * ((type *)ptr) : va_arg(data, type)) + +/** + Converts from a list of data into an GValue array. + + @param gvalus Array of empty gvalues to be filled. + @param number The number of data items. + @param gaim_value Array of #number pointers to GaimValues. + The types of of these GaimValues determine the type + of data items. The values do not matter. + @param mainptr A pointer to a single data item. If this pointer is not #NULL, + then #number must be 1. + @param data A va_list containing data items. If + + Exactly one of #mainptr and #data must be not #NULL. If #mainptr + is not #NULL, then there is a single piece of data at the address + pointed at by #mainptr. If #data is not #NULL, then there are + #number data items in the #va_list #data. + */ +static void gaim_values_to_gvalues(GValue *gvalue, int number, + GaimValue **gaim_values, gpointer mainptr, va_list data) +{ + int i; + gpointer ptr; + + g_assert(mainptr == NULL || data == NULL); + g_assert(mainptr != NULL || data != NULL); + g_assert(number == 1 || data != NULL); + + for(i=0; itype) { + case GAIM_TYPE_CHAR: + g_value_init(gvalue, G_TYPE_CHAR); + g_value_set_char(gvalue, (char) my_arg(int)); + break; + case GAIM_TYPE_INT: + g_value_init(gvalue, G_TYPE_INT); + g_value_set_int(gvalue, my_arg(gint)); + break; + case GAIM_TYPE_UINT: + g_value_init(gvalue, G_TYPE_UINT); + g_value_set_uint(gvalue, my_arg(guint)); + break; + case GAIM_TYPE_BOOLEAN: + g_value_init(gvalue, G_TYPE_BOOLEAN); + g_value_set_boolean(gvalue, my_arg(gboolean)); + break; + case GAIM_TYPE_STRING: + g_value_init(gvalue, G_TYPE_STRING); + g_value_set_string(gvalue, null_to_empty(my_arg(char*))); + break; + case GAIM_TYPE_SUBTYPE: /* registered pointers only! */ + g_value_init(gvalue, G_TYPE_INT); + g_value_set_int(gvalue, + gaim_dbus_pointer_to_id(my_arg(gpointer))); + break; + case GAIM_TYPE_POINTER: + case GAIM_TYPE_OBJECT: + case GAIM_TYPE_BOXED: + my_arg(gpointer); /* cannot pass general pointers */ + g_value_init(gvalue, G_TYPE_INT); + g_value_set_int(gvalue, 0); + break; + + default: /* no conversion implemented */ + g_assert_not_reached(); + } + } + + if (data) + va_end(data); +} + +#undef my_arg /* my_arg was only used in gaim_values_to_gvalues */ + + + +/** + Converts from GaimTypes to GTypes. + @param type A GaimType to be converted. + @result The result of the conversion (GType). +*/ +static GType gaim_type_to_g_type(GaimType type) +{ + switch(type) { + case GAIM_TYPE_CHAR: + return G_TYPE_CHAR; + case GAIM_TYPE_INT: + return G_TYPE_INT; + case GAIM_TYPE_UINT: + return G_TYPE_UINT; + case GAIM_TYPE_BOOLEAN: + return G_TYPE_BOOLEAN; + case GAIM_TYPE_STRING: + return G_TYPE_STRING; + case GAIM_TYPE_SUBTYPE: /* registered pointers only! */ + return G_TYPE_INT; + case GAIM_TYPE_POINTER: + case GAIM_TYPE_BOXED: + case GAIM_TYPE_OBJECT: + return G_TYPE_INT; /* always 0 */ + default: /* no conversion implemented */ + g_assert_not_reached(); + } +} + + +static const char *gaim_dbus_convert_signal_name(const char *gaim_name) +{ + int gaim_index, g_index; + char *g_name = g_new(char, strlen(gaim_name)+1); + gboolean capitalize_next = TRUE; + + for(gaim_index = g_index = 0; gaim_name[gaim_index]; gaim_index++) + if (gaim_name[gaim_index] != '-' && gaim_name[gaim_index] != '_') { + if (capitalize_next) + g_name[g_index++] = g_ascii_toupper(gaim_name[gaim_index]); + else + g_name[g_index++] = gaim_name[gaim_index]; + capitalize_next = FALSE; + } else + capitalize_next = TRUE; + g_name[g_index] = 0; + + return g_name; +} + +/* Public signal-related functions */ + + +void gaim_dbus_invalid_marshaller(GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + g_assert_not_reached(); +} + +int gaim_dbus_signal_register(GaimObject *object, const char *name, + GSignalCMarshaller marshaller, + int num_values, ...) +{ + va_list args; + + va_start(args, num_values); + + return g_signal_new_valist(name, G_OBJECT_TYPE(object), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + NULL, NULL, NULL, marshaller, + G_TYPE_NONE, num_values, args); +} + +void gaim_dbus_signal_emit(GaimObject *object, int dbus_id, ...) { + va_list args; + + va_start(args, dbus_id); + + gaim_dbus_signal_emit_valist(object, dbus_id, args); +} + +void gaim_dbus_signal_emit_valist(GaimObject *object, int dbus_id, va_list args) { + g_signal_emit_valist(object, dbus_id, 0, args); +} + +int gaim_dbus_signal_register_gaim(GaimObject *object, const char *name, + GSignalCMarshaller marshaller, + int num_values, GaimValue **values) +{ + int i; + int dbus_id; + GType *types; + + types = g_new0(GType, num_values); + + for(i=0; itype); + + dbus_id = + g_signal_newv(gaim_dbus_convert_signal_name(name), + G_OBJECT_TYPE(object), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + NULL, NULL, NULL, marshaller, + G_TYPE_NONE, num_values, types); + + g_free(types); + + return dbus_id; +} + + +void gaim_dbus_signal_emit_gaim(GaimObject *object, int dbus_id, int num_values, + GaimValue **values, va_list vargs) +{ + GValue *args; + int i; + + g_return_if_fail(dbus_id); + + args = g_new0(GValue, num_values + 1); + + g_value_init(args + 0, G_OBJECT_TYPE(object)); + g_value_set_object(args + 0, object); + + gaim_values_to_gvalues(args + 1, num_values, values, NULL, vargs); + + g_signal_emitv(args, dbus_id, 0, NULL); + + for(i = 1; i <= num_values; i++) + g_value_unset(args + i); + + g_free(args); +} /**************************************************************************/ @@ -101,13 +337,6 @@ return FALSE; \ } -static const char* null_to_empty(const char *s) { - if (s) - return s; - else - return ""; -} - typedef gboolean (*GaimNodeFilter)(GaimBlistNode *node, gpointer *user_data); static gboolean @@ -152,8 +381,9 @@ /**************************************************************************/ static gboolean -gaim_object_ping(GaimObject *obj, GError **error) +gaim_object_ping(GaimObject *object, GError **error) { + gaim_dbus_signal_emit(object, object->ping_signal_id, "Ping Pong!"); return TRUE; } @@ -204,7 +434,7 @@ static gboolean -gaim_object_find_account(GaimObject *unused, +gaim_object_find_account(GaimObject *object, const char *account_name, const char *protocol_name, gint *account_id, GError **error) { @@ -218,7 +448,7 @@ } static gboolean -gaim_object_find_buddy(GaimObject *unused, gint account_id, const char *buddy_name, +gaim_object_find_buddy(GaimObject *object, gint account_id, const char *buddy_name, gint *buddy_id, GError **error) { GaimAccount *account; @@ -235,7 +465,7 @@ } static gboolean -gaim_object_start_im_conversation (GaimObject *obj, gint buddy_id, GError **error) +gaim_object_start_im_conversation (GaimObject *object, gint buddy_id, GError **error) { GaimBuddy *buddy = (GaimBuddy*) gaim_dbus_id_to_pointer(buddy_id, DBUS_POINTER_BUDDY); @@ -271,31 +501,16 @@ for(i=0; iping_signal_id = + gaim_dbus_signal_register(object, "PingSignal", + g_cclosure_marshal_VOID__STRING, + 1, G_TYPE_STRING); +} + + +gboolean gaim_dbus_init(void) +{ + gaim_dbus_init_ids(); + gaim_object_error_quark = + g_quark_from_static_string("org.gaim.GaimError"); + + gaim_dbus_object = GAIM_DBUS_OBJECT(g_object_new (GAIM_DBUS_TYPE_OBJECT, NULL)); + + return TRUE; +} diff -r b2ace57224e2 -r f54740547c95 src/dbus-server.h --- a/src/dbus-server.h Sat Jul 09 20:27:57 2005 +0000 +++ b/src/dbus-server.h Sun Jul 10 02:29:52 2005 +0000 @@ -27,6 +27,8 @@ #ifndef _GAIM_DBUS_SERVER_H_ #define _GAIM_DBUS_SERVER_H_ +#include +#include "value.h" G_BEGIN_DECLS @@ -48,6 +50,10 @@ DBUS_POINTER_ACCOUNT } GaimDBusPointerType; +typedef struct _GaimObject GaimObject; + +/** The main GaimObject */ +GaimObject * gaim_dbus_object; /** * Starts the gaim DBUS server. It is responsible for handling DBUS @@ -55,7 +61,9 @@ * * @return TRUE if successful, FALSE otherwise. */ -gboolean dbus_server_init(void); +gboolean gaim_dbus_init(void); + +gboolean gaim_dbus_connect(GaimObject *object); /** Initializes gaim dbus pointer registration engine. @@ -102,6 +110,94 @@ */ void gaim_dbus_unregister_pointer(gpointer node); +/** + Registers a gaim signal with a #GaimObject. + + @param object The #GaimObject (usually #gaim_dbus_object) + @param name Name of the signal + @param marshaller Marshaller for the signal. + @param num_values The number of parameters. + @param values Array of pointers to #GaimValue objects representing + the types of the parameters. + @result The dbus id of the registered signal. + + This function is intended to be used in signal.h, where it + automatically registers all gaim signals with dbus. For your own + dbus signals, use #gaim_dbus_register. + + The name of the signal, usually in the form "aaa-bbb-ccc", is + converted into DBus standard, "AaaBbbCcc", because "aaa-bbb-ccc" + doesn't work with DBus GObject binding version 0.34 (cvs version is ok). + + The #marshaller can be set to gaim_dbus_invalid_marshaller because + DBus signals are never passed to any local handler. + */ +int gaim_dbus_signal_register_gaim(GaimObject *object, const char *name, + GSignalCMarshaller marshaller, + int num_values, GaimValue **values); + +/** + Emits a dbus signal. + + @param object The #GaimObject (usually #gaim_dbus_object) + @param dbus_id Id of the signal. + @param num_values The number of parameters. + @param values Array of pointers to #GaimValue objects representing + the types of the parameters. + @param vargs A va_list containing the actual parameters. + + This function is intended to be used in signal.h, where it + automatically emits all gaim signals to dbus. For your own dbus + signals, use #gaim_dbus_emit. + */ +void gaim_dbus_signal_emit_gaim(GaimObject *object, int dbus_id, + int num_values, GaimValue **values, va_list vargs); + +/** + A marshaller that emits an "assertion failed" message if called. + + This marshaller is intended to use with signal that will never need to be marshalled. + */ +void gaim_dbus_invalid_marshaller(GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/** + Registers a gaim signal with a #GaimObject. + + @param object The #GaimObject (usually #gaim_dbus_object) + @param name Name of the signal + @param marshaller Marshaller for the signal. + @param num_values The number of parameters. + @param ... List of GType of the parameter types. + + @result The dbus id of the registered signal. + */ +int gaim_dbus_signal_register(GaimObject *object, const char *name, + GSignalCMarshaller marshaller, + int num_values, ...); + +/** + Emits a dbus signal. + + @param object The #GaimObject (usually #gaim_dbus_object) + @param dbus_id Id of the signal. + @param ... Actual parameters. + */ +void gaim_dbus_signal_emit(GaimObject *object, int dbus_id, ...); + +/** + Emits a dbus signal. + + @param object The #GaimObject (usually #gaim_dbus_object) + @param dbus_id Id of the signal. + @param vargs A va_list containing the actual parameters. + */ +void gaim_dbus_signal_emit_valist(GaimObject *object, int dbus_id, va_list args); + G_END_DECLS diff -r b2ace57224e2 -r f54740547c95 src/gtkmain.c --- a/src/gtkmain.c Sat Jul 09 20:27:57 2005 +0000 +++ b/src/gtkmain.c Sun Jul 10 02:29:52 2005 +0000 @@ -494,6 +494,7 @@ textdomain(PACKAGE); #endif + #if HAVE_SIGNAL_H /* Let's not violate any PLA's!!!! */ /* jseymour: whatever the fsck that means */ @@ -617,8 +618,7 @@ #endif #ifdef HAVE_DBUS - /* start dbus pointer registration system */ - gaim_dbus_init_ids(); + gaim_dbus_init(); #endif gaim_core_set_ui_ops(gaim_gtk_core_get_ui_ops()); @@ -727,8 +727,7 @@ gaim_debug_register_category("stringref"); #ifdef HAVE_DBUS - /* Starting DBUS */ - dbus_server_init(); + gaim_dbus_connect(gaim_dbus_object); #endif gtk_main(); diff -r b2ace57224e2 -r f54740547c95 src/signals.c --- a/src/signals.c Sat Jul 09 20:27:57 2005 +0000 +++ b/src/signals.c Sun Jul 10 02:29:52 2005 +0000 @@ -24,6 +24,7 @@ */ #include "internal.h" +#include "dbus-maybe.h" #include "debug.h" #include "signals.h" #include "value.h" @@ -57,6 +58,7 @@ gulong next_handler_id; + int dbus_id; } GaimSignalData; typedef struct @@ -167,6 +169,15 @@ instance_data->next_signal_id++; instance_data->signal_count++; +#ifdef HAVE_DBUS + /* DBus messages are sent directly to the bus so the + marshalling function is never called. */ + signal_data->dbus_id = + gaim_dbus_signal_register_gaim(gaim_dbus_object, signal, + gaim_dbus_invalid_marshaller, + num_values, signal_data->values); +#endif /* HAVE_DBUS */ + return signal_data->id; } @@ -487,6 +498,13 @@ va_end(tmp); } + +#ifdef HAVE_DBUS + gaim_dbus_signal_emit_gaim(gaim_dbus_object, signal_data->dbus_id, + signal_data->num_values, + signal_data->values, args); +#endif /* HAVE_DBUS */ + } void * @@ -533,6 +551,12 @@ return 0; } +#ifdef HAVE_DBUS + gaim_dbus_signal_emit_gaim(gaim_dbus_object, signal_data->dbus_id, + signal_data->num_values, + signal_data->values, args); +#endif /* HAVE_DBUS */ + for (l = signal_data->handlers; l != NULL; l = l_next) { void *ret_val = NULL;