mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-02-05 12:20:32 +01:00
2005-01-30 Havoc Pennington <hp@redhat.com>
* tools/dbus-names-model.c: dynamically watch NameOwnerChanged * autogen.sh: change to autotools 1.9 * glib/dbus-gproxy.c: completely change how signals work (dbus_g_proxy_add_signal): new function to specify signature of a signal (dbus_g_proxy_emit_received): marshal the dbus message to GValues, and g_warning if the incoming message has the wrong signature.
This commit is contained in:
parent
d5b7d7a78c
commit
d2c1a633d1
11 changed files with 510 additions and 88 deletions
12
ChangeLog
12
ChangeLog
|
|
@ -1,3 +1,15 @@
|
|||
2005-01-30 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* tools/dbus-names-model.c: dynamically watch NameOwnerChanged
|
||||
|
||||
* autogen.sh: change to autotools 1.9
|
||||
|
||||
* glib/dbus-gproxy.c: completely change how signals work
|
||||
(dbus_g_proxy_add_signal): new function to specify signature of a
|
||||
signal
|
||||
(dbus_g_proxy_emit_received): marshal the dbus message to GValues,
|
||||
and g_warning if the incoming message has the wrong signature.
|
||||
|
||||
2005-01-30 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* tools/dbus-names-model.c (have_names_notify): fix this
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ DIE=0
|
|||
DIE=1
|
||||
}
|
||||
|
||||
AUTOMAKE=automake-1.7
|
||||
ACLOCAL=aclocal-1.7
|
||||
AUTOMAKE=automake-1.9
|
||||
ACLOCAL=aclocal-1.9
|
||||
|
||||
($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
|
||||
AUTOMAKE=automake
|
||||
|
|
|
|||
|
|
@ -819,6 +819,13 @@ fi
|
|||
AM_CONDITIONAL(HAVE_GLIB, test x$have_glib = xyes)
|
||||
AM_CONDITIONAL(HAVE_GLIB_THREADS, test x$have_glib_threads = xyes)
|
||||
|
||||
if test x$have_glib = xyes; then
|
||||
GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`
|
||||
else
|
||||
GLIB_GENMARSHAL=glib-not-enabled-so-there-is-no-genmarshal
|
||||
fi
|
||||
AC_SUBST(GLIB_GENMARSHAL)
|
||||
|
||||
dnl GLib flags
|
||||
AC_SUBST(DBUS_GLIB_CFLAGS)
|
||||
AC_SUBST(DBUS_GLIB_LIBS)
|
||||
|
|
|
|||
|
|
@ -149,6 +149,9 @@ DBusGProxy* dbus_g_proxy_new_for_name_owner (DBusGConnection *connect
|
|||
DBusGProxy* dbus_g_proxy_new_for_peer (DBusGConnection *connection,
|
||||
const char *path_name,
|
||||
const char *interface_name);
|
||||
void dbus_g_proxy_add_signal (DBusGProxy *proxy,
|
||||
const char *signal_name,
|
||||
const char *signature);
|
||||
void dbus_g_proxy_connect_signal (DBusGProxy *proxy,
|
||||
const char *signal_name,
|
||||
GCallback handler,
|
||||
|
|
|
|||
6
doc/TODO
6
doc/TODO
|
|
@ -55,9 +55,9 @@ Important for 1.0 GLib Bindings
|
|||
dbus_malloc() memory, only g_malloc().
|
||||
dbus_g_proxy_end_call() is the major offender.
|
||||
|
||||
- dbus_gproxy_connect_signal() has to take a signature for the signal
|
||||
so it can figure out how to invoke the callback, or we have to rely
|
||||
on having introspection data.
|
||||
- DBusGProxy signals feature is a complete fiasco;
|
||||
right now the problem is that it dynamically creates
|
||||
signals on the global DBusGProxy class and never frees them
|
||||
|
||||
- DBusGProxy doesn't emit "destroy" when it should
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ lib_LTLIBRARIES=libdbus-glib-1.la
|
|||
libdbus_glib_1_la_SOURCES = \
|
||||
dbus-glib.c \
|
||||
dbus-gmain.c \
|
||||
dbus-gmarshal.c \
|
||||
dbus-gmarshal.h \
|
||||
dbus-gobject.c \
|
||||
dbus-gproxy.c \
|
||||
dbus-gtest.c \
|
||||
|
|
@ -41,6 +43,15 @@ dbus_binding_tool_SOURCES = \
|
|||
|
||||
dbus_binding_tool_LDADD= -lexpat libdbus-gtool.la
|
||||
|
||||
## we just rebuilt these manually and check them into cvs; easier than
|
||||
## convincing automake/make to do this properly
|
||||
regenerate-built-sources:
|
||||
@GLIB_GENMARSHAL@ --prefix=_dbus_g_marshal dbus-gmarshal.list --header > dbus-gmarshal.h && \
|
||||
echo '#include "dbus-gmarshal.h"' > dbus-gmarshal.c && \
|
||||
@GLIB_GENMARSHAL@ --prefix=_dbus_g_marshal dbus-gmarshal.list --body >> dbus-gmarshal.c
|
||||
|
||||
EXTRA_DIST=dbus-gmarshal.list
|
||||
|
||||
if DBUS_BUILD_TESTS
|
||||
|
||||
## we use noinst_PROGRAMS not check_PROGRAMS for TESTS so that we
|
||||
|
|
|
|||
89
glib/dbus-gmarshal.c
Normal file
89
glib/dbus-gmarshal.c
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#include "dbus-gmarshal.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
|
||||
#define g_marshal_value_peek_char(v) g_value_get_char (v)
|
||||
#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
|
||||
#define g_marshal_value_peek_int(v) g_value_get_int (v)
|
||||
#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
|
||||
#define g_marshal_value_peek_long(v) g_value_get_long (v)
|
||||
#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
|
||||
#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
|
||||
#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
|
||||
#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
|
||||
#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
|
||||
#define g_marshal_value_peek_float(v) g_value_get_float (v)
|
||||
#define g_marshal_value_peek_double(v) g_value_get_double (v)
|
||||
#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
|
||||
#define g_marshal_value_peek_param(v) g_value_get_param (v)
|
||||
#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
|
||||
#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
|
||||
#define g_marshal_value_peek_object(v) g_value_get_object (v)
|
||||
#else /* !G_ENABLE_DEBUG */
|
||||
/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
|
||||
* Do not access GValues directly in your code. Instead, use the
|
||||
* g_value_get_*() functions
|
||||
*/
|
||||
#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
|
||||
#define g_marshal_value_peek_char(v) (v)->data[0].v_int
|
||||
#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
|
||||
#define g_marshal_value_peek_int(v) (v)->data[0].v_int
|
||||
#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
|
||||
#define g_marshal_value_peek_long(v) (v)->data[0].v_long
|
||||
#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
|
||||
#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
|
||||
#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
|
||||
#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
|
||||
#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
|
||||
#define g_marshal_value_peek_float(v) (v)->data[0].v_float
|
||||
#define g_marshal_value_peek_double(v) (v)->data[0].v_double
|
||||
#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
|
||||
#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
|
||||
#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
|
||||
#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
|
||||
#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
|
||||
#endif /* !G_ENABLE_DEBUG */
|
||||
|
||||
|
||||
/* NONE:STRING,STRING,STRING (dbus-gmarshal.list:1) */
|
||||
void
|
||||
_dbus_g_marshal_VOID__STRING_STRING_STRING (GClosure *closure,
|
||||
GValue *return_value,
|
||||
guint n_param_values,
|
||||
const GValue *param_values,
|
||||
gpointer invocation_hint,
|
||||
gpointer marshal_data)
|
||||
{
|
||||
typedef void (*GMarshalFunc_VOID__STRING_STRING_STRING) (gpointer data1,
|
||||
gpointer arg_1,
|
||||
gpointer arg_2,
|
||||
gpointer arg_3,
|
||||
gpointer data2);
|
||||
register GMarshalFunc_VOID__STRING_STRING_STRING callback;
|
||||
register GCClosure *cc = (GCClosure*) closure;
|
||||
register gpointer data1, data2;
|
||||
|
||||
g_return_if_fail (n_param_values == 4);
|
||||
|
||||
if (G_CCLOSURE_SWAP_DATA (closure))
|
||||
{
|
||||
data1 = closure->data;
|
||||
data2 = g_value_peek_pointer (param_values + 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
data1 = g_value_peek_pointer (param_values + 0);
|
||||
data2 = closure->data;
|
||||
}
|
||||
callback = (GMarshalFunc_VOID__STRING_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
|
||||
|
||||
callback (data1,
|
||||
g_marshal_value_peek_string (param_values + 1),
|
||||
g_marshal_value_peek_string (param_values + 2),
|
||||
g_marshal_value_peek_string (param_values + 3),
|
||||
data2);
|
||||
}
|
||||
|
||||
21
glib/dbus-gmarshal.h
Normal file
21
glib/dbus-gmarshal.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
#ifndef ___dbus_g_marshal_MARSHAL_H__
|
||||
#define ___dbus_g_marshal_MARSHAL_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* NONE:STRING,STRING,STRING (dbus-gmarshal.list:1) */
|
||||
extern void _dbus_g_marshal_VOID__STRING_STRING_STRING (GClosure *closure,
|
||||
GValue *return_value,
|
||||
guint n_param_values,
|
||||
const GValue *param_values,
|
||||
gpointer invocation_hint,
|
||||
gpointer marshal_data);
|
||||
#define _dbus_g_marshal_NONE__STRING_STRING_STRING _dbus_g_marshal_VOID__STRING_STRING_STRING
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* ___dbus_g_marshal_MARSHAL_H__ */
|
||||
|
||||
1
glib/dbus-gmarshal.list
Normal file
1
glib/dbus-gmarshal.list
Normal file
|
|
@ -0,0 +1 @@
|
|||
NONE:STRING,STRING,STRING
|
||||
|
|
@ -23,6 +23,8 @@
|
|||
#include <dbus/dbus-glib.h>
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
#include "dbus-gutils.h"
|
||||
#include "dbus-gmarshal.h"
|
||||
#include "dbus-gvalue.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
|
|
@ -48,6 +50,8 @@ struct DBusGProxy
|
|||
char *name; /**< Name messages go to or NULL */
|
||||
char *path; /**< Path messages go to or NULL */
|
||||
char *interface; /**< Interface messages go to or NULL */
|
||||
|
||||
GData *signal_signatures; /**< D-BUS signatures for each signal */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -58,14 +62,13 @@ struct DBusGProxyClass
|
|||
GObjectClass parent_class; /**< Parent class */
|
||||
};
|
||||
|
||||
static void dbus_g_proxy_init (DBusGProxy *proxy);
|
||||
static void dbus_g_proxy_class_init (DBusGProxyClass *klass);
|
||||
static void dbus_g_proxy_finalize (GObject *object);
|
||||
static void dbus_g_proxy_dispose (GObject *object);
|
||||
static void dbus_g_proxy_destroy (DBusGProxy *proxy);
|
||||
static void dbus_g_proxy_emit_received (DBusGProxy *proxy,
|
||||
DBusMessage *message);
|
||||
|
||||
static void dbus_g_proxy_init (DBusGProxy *proxy);
|
||||
static void dbus_g_proxy_class_init (DBusGProxyClass *klass);
|
||||
static void dbus_g_proxy_finalize (GObject *object);
|
||||
static void dbus_g_proxy_dispose (GObject *object);
|
||||
static void dbus_g_proxy_destroy (DBusGProxy *proxy);
|
||||
static void dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy,
|
||||
DBusMessage *message);
|
||||
|
||||
/**
|
||||
* A list of proxies with a given name+path+interface, used to
|
||||
|
|
@ -641,7 +644,7 @@ dbus_g_proxy_manager_filter (DBusConnection *connection,
|
|||
proxy = DBUS_G_PROXY (tmp->data);
|
||||
|
||||
UNLOCK_MANAGER (manager);
|
||||
dbus_g_proxy_emit_received (proxy, message);
|
||||
dbus_g_proxy_emit_remote_signal (proxy, message);
|
||||
g_object_unref (G_OBJECT (proxy));
|
||||
LOCK_MANAGER (manager);
|
||||
|
||||
|
|
@ -670,7 +673,6 @@ dbus_g_proxy_manager_filter (DBusConnection *connection,
|
|||
enum
|
||||
{
|
||||
DESTROY,
|
||||
RECEIVED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
|
@ -680,7 +682,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
|
|||
static void
|
||||
dbus_g_proxy_init (DBusGProxy *proxy)
|
||||
{
|
||||
/* Nothing */
|
||||
g_datalist_init (&proxy->signal_signatures);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -701,16 +703,6 @@ dbus_g_proxy_class_init (DBusGProxyClass *klass)
|
|||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[RECEIVED] =
|
||||
g_signal_new ("received",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__BOXED,
|
||||
G_TYPE_NONE, 1,
|
||||
DBUS_TYPE_MESSAGE);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -721,6 +713,8 @@ dbus_g_proxy_dispose (GObject *object)
|
|||
|
||||
proxy = DBUS_G_PROXY (object);
|
||||
|
||||
g_datalist_clear (&proxy->signal_signatures);
|
||||
|
||||
g_signal_emit (object, signals[DESTROY], 0);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
|
|
@ -755,28 +749,102 @@ dbus_g_proxy_destroy (DBusGProxy *proxy)
|
|||
g_object_run_dispose (G_OBJECT (proxy));
|
||||
}
|
||||
|
||||
/* this is to avoid people using g_signal_connect() directly,
|
||||
* to avoid confusion with local signal names, and because
|
||||
* of the horribly broken current setup (signals are added
|
||||
* globally to all proxies)
|
||||
*/
|
||||
static char*
|
||||
create_signal_detail (const char *interface,
|
||||
const char *signal)
|
||||
create_signal_name (const char *interface,
|
||||
const char *signal)
|
||||
{
|
||||
GString *str;
|
||||
char *p;
|
||||
|
||||
str = g_string_new (interface);
|
||||
|
||||
g_string_append (str, ".");
|
||||
|
||||
g_string_append (str, "-");
|
||||
|
||||
g_string_append (str, signal);
|
||||
|
||||
/* GLib will silently barf on '.' in signal names */
|
||||
p = str->str;
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '.')
|
||||
*p = '-';
|
||||
++p;
|
||||
}
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_g_proxy_emit_received (DBusGProxy *proxy,
|
||||
DBusMessage *message)
|
||||
emit_remote_internal (DBusGProxy *proxy,
|
||||
DBusMessage *message,
|
||||
guint signal_id,
|
||||
gboolean marshal_args)
|
||||
{
|
||||
#define MAX_SIGNATURE_ARGS 20
|
||||
GValue values[MAX_SIGNATURE_ARGS];
|
||||
int arg;
|
||||
int i;
|
||||
|
||||
memset (&values[0], 0, sizeof (values));
|
||||
|
||||
arg = 0;
|
||||
|
||||
g_value_init (&values[arg], G_TYPE_FROM_INSTANCE (proxy));
|
||||
g_value_set_instance (&values[arg], proxy);
|
||||
++arg;
|
||||
|
||||
if (marshal_args)
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
int dtype;
|
||||
|
||||
dbus_message_iter_init (message, &iter);
|
||||
|
||||
while ((dtype = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
|
||||
{
|
||||
if (arg == MAX_SIGNATURE_ARGS)
|
||||
{
|
||||
g_warning ("Don't support more than %d signal args\n", MAX_SIGNATURE_ARGS);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!dbus_gvalue_demarshal (&iter, &values[arg]))
|
||||
{
|
||||
g_warning ("Unable to convert arg type %d to GValue to emit DBusGProxy signal", dtype);
|
||||
goto out;
|
||||
}
|
||||
|
||||
++arg;
|
||||
dbus_message_iter_next (&iter);
|
||||
}
|
||||
}
|
||||
|
||||
g_signal_emitv (&values[0],
|
||||
signal_id,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
out:
|
||||
i = 0;
|
||||
while (i < arg)
|
||||
{
|
||||
g_value_unset (&values[i]);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy,
|
||||
DBusMessage *message)
|
||||
{
|
||||
const char *interface;
|
||||
const char *signal;
|
||||
char *detail;
|
||||
char *name;
|
||||
GQuark q;
|
||||
|
||||
interface = dbus_message_get_interface (message);
|
||||
|
|
@ -785,21 +853,43 @@ dbus_g_proxy_emit_received (DBusGProxy *proxy,
|
|||
g_assert (interface != NULL);
|
||||
g_assert (signal != NULL);
|
||||
|
||||
detail = create_signal_detail (interface, signal);
|
||||
name = create_signal_name (interface, signal);
|
||||
|
||||
/* If the quark isn't preexisting, there's no way there
|
||||
* are any handlers connected. We don't want to create
|
||||
* extra quarks for every possible signal.
|
||||
*/
|
||||
q = g_quark_try_string (detail);
|
||||
q = g_quark_try_string (name);
|
||||
|
||||
if (q != 0)
|
||||
g_signal_emit (G_OBJECT (proxy),
|
||||
signals[RECEIVED],
|
||||
q,
|
||||
message);
|
||||
{
|
||||
const char *signature;
|
||||
|
||||
g_free (detail);
|
||||
signature = g_datalist_id_get_data (&proxy->signal_signatures, q);
|
||||
if (signature == NULL)
|
||||
{
|
||||
g_warning ("Signal '%s' has not been added to this proxy object\n",
|
||||
name);
|
||||
}
|
||||
else if (!dbus_message_has_signature (message, signature))
|
||||
{
|
||||
g_warning ("Signature '%s' expected for signal '%s', actual signature '%s'\n",
|
||||
signature,
|
||||
name,
|
||||
dbus_message_get_signature (message));
|
||||
}
|
||||
else
|
||||
{
|
||||
guint signal_id;
|
||||
|
||||
signal_id = g_signal_lookup (name, G_OBJECT_TYPE (proxy));
|
||||
g_assert (signal_id != 0); /* because we have the signature */
|
||||
|
||||
emit_remote_internal (proxy, message, signal_id, signature != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
/** @} End of DBusGLibInternals */
|
||||
|
|
@ -1264,8 +1354,8 @@ dbus_g_proxy_call_no_reply (DBusGProxy *proxy,
|
|||
* @param client_serial return location for message's serial, or #NULL */
|
||||
void
|
||||
dbus_g_proxy_send (DBusGProxy *proxy,
|
||||
DBusMessage *message,
|
||||
dbus_uint32_t *client_serial)
|
||||
DBusMessage *message,
|
||||
dbus_uint32_t *client_serial)
|
||||
{
|
||||
g_return_if_fail (DBUS_IS_G_PROXY (proxy));
|
||||
|
||||
|
|
@ -1289,15 +1379,103 @@ dbus_g_proxy_send (DBusGProxy *proxy,
|
|||
g_error ("Out of memory\n");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
siginfo_from_signature (const char *signature,
|
||||
GSignalCMarshaller *c_marshaller,
|
||||
GType *return_type,
|
||||
guint *n_params,
|
||||
GType **param_types)
|
||||
{
|
||||
/* FIXME (which marshalers should we include?
|
||||
* probably need public API to add your own
|
||||
*/
|
||||
|
||||
if (strcmp (signature, "sss") == 0)
|
||||
{
|
||||
*c_marshaller = _dbus_g_marshal_NONE__STRING_STRING_STRING;
|
||||
*return_type = G_TYPE_NONE;
|
||||
*n_params = 3;
|
||||
*param_types = g_new0 (GType, *n_params);
|
||||
(*param_types)[0] = G_TYPE_STRING;
|
||||
(*param_types)[1] = G_TYPE_STRING;
|
||||
(*param_types)[2] = G_TYPE_STRING;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the signature of a signal, such that it's possible to
|
||||
* connect to the signal on this proxy.
|
||||
*
|
||||
* @param proxy the proxy for a remote interface
|
||||
* @param signal_name the name of the signal
|
||||
* @param signature D-BUS signature of the signal
|
||||
*/
|
||||
void
|
||||
dbus_g_proxy_add_signal (DBusGProxy *proxy,
|
||||
const char *signal_name,
|
||||
const char *signature)
|
||||
{
|
||||
GSignalCMarshaller c_marshaller;
|
||||
GType return_type;
|
||||
int n_params;
|
||||
GType *params;
|
||||
|
||||
g_return_if_fail (DBUS_IS_G_PROXY (proxy));
|
||||
g_return_if_fail (signal_name != NULL);
|
||||
g_return_if_fail (signature != NULL);
|
||||
|
||||
if (siginfo_from_signature (signature,
|
||||
&c_marshaller,
|
||||
&return_type,
|
||||
&n_params,
|
||||
¶ms))
|
||||
{
|
||||
GQuark q;
|
||||
char *name;
|
||||
|
||||
name = create_signal_name (proxy->interface, signal_name);
|
||||
|
||||
q = g_quark_from_string (name);
|
||||
|
||||
g_return_if_fail (g_datalist_id_get_data (&proxy->signal_signatures, q) == NULL);
|
||||
|
||||
g_datalist_id_set_data_full (&proxy->signal_signatures,
|
||||
q, g_strdup (signature),
|
||||
g_free);
|
||||
|
||||
/* hackaround global nature of g_signal_newv()... this whole thing needs unhosing */
|
||||
|
||||
if (g_signal_lookup (name,
|
||||
G_OBJECT_TYPE (proxy)) == 0)
|
||||
{
|
||||
g_signal_newv (name,
|
||||
G_OBJECT_TYPE (proxy),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
c_marshaller,
|
||||
return_type, n_params, params);
|
||||
}
|
||||
|
||||
g_free (params);
|
||||
g_free (name);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("DBusGProxy doesn't know how to create a signal with signature '%s'\n",
|
||||
signature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect a signal handler to a proxy for a remote interface. When
|
||||
* the remote interface emits the specified signal, the proxy will
|
||||
* emit a corresponding GLib signal.
|
||||
*
|
||||
* @todo Right now there's no way to specify the signature to use
|
||||
* for invoking the GCallback. Need to either rely on introspection,
|
||||
* or require signature here.
|
||||
*
|
||||
* @param proxy a proxy for a remote interface
|
||||
* @param signal_name the DBus signal name to listen for
|
||||
* @param handler the handler to connect
|
||||
|
|
@ -1306,27 +1484,40 @@ dbus_g_proxy_send (DBusGProxy *proxy,
|
|||
*/
|
||||
void
|
||||
dbus_g_proxy_connect_signal (DBusGProxy *proxy,
|
||||
const char *signal_name,
|
||||
GCallback handler,
|
||||
void *data,
|
||||
GClosureNotify free_data_func)
|
||||
const char *signal_name,
|
||||
GCallback handler,
|
||||
void *data,
|
||||
GClosureNotify free_data_func)
|
||||
{
|
||||
GClosure *closure;
|
||||
char *detail;
|
||||
char *name;
|
||||
guint signal_id;
|
||||
|
||||
g_return_if_fail (DBUS_IS_G_PROXY (proxy));
|
||||
g_return_if_fail (signal_name != NULL);
|
||||
g_return_if_fail (handler != NULL);
|
||||
|
||||
detail = create_signal_detail (proxy->interface, signal_name);
|
||||
|
||||
closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func);
|
||||
g_signal_connect_closure_by_id (G_OBJECT (proxy),
|
||||
signals[RECEIVED],
|
||||
g_quark_from_string (detail),
|
||||
closure, FALSE);
|
||||
name = create_signal_name (proxy->interface, signal_name);
|
||||
|
||||
g_free (detail);
|
||||
g_printerr ("Looking up signal '%s'\n", name);
|
||||
signal_id = g_signal_lookup (name,
|
||||
G_OBJECT_TYPE (proxy));
|
||||
if (signal_id != 0)
|
||||
{
|
||||
GClosure *closure;
|
||||
|
||||
closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func);
|
||||
g_signal_connect_closure_by_id (G_OBJECT (proxy),
|
||||
signal_id,
|
||||
0,
|
||||
closure, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("You have to add signal '%s' with dbus_g_proxy_add_signal() before you can connect to it\n",
|
||||
name);
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1340,38 +1531,38 @@ dbus_g_proxy_connect_signal (DBusGProxy *proxy,
|
|||
*/
|
||||
void
|
||||
dbus_g_proxy_disconnect_signal (DBusGProxy *proxy,
|
||||
const char *signal_name,
|
||||
GCallback handler,
|
||||
void *data)
|
||||
const char *signal_name,
|
||||
GCallback handler,
|
||||
void *data)
|
||||
{
|
||||
char *detail;
|
||||
GQuark q;
|
||||
char *name;
|
||||
guint signal_id;
|
||||
|
||||
g_return_if_fail (DBUS_IS_G_PROXY (proxy));
|
||||
g_return_if_fail (signal_name != NULL);
|
||||
g_return_if_fail (handler != NULL);
|
||||
|
||||
detail = create_signal_detail (proxy->interface, signal_name);
|
||||
q = g_quark_try_string (detail);
|
||||
g_free (detail);
|
||||
name = create_signal_name (proxy->interface, signal_name);
|
||||
|
||||
#ifndef G_DISABLE_CHECKS
|
||||
if (q == 0)
|
||||
signal_id = g_signal_lookup (name, G_OBJECT_TYPE (proxy));
|
||||
if (signal_id != 0)
|
||||
{
|
||||
g_warning ("%s: No signal handlers for %s found on this DBusGProxy",
|
||||
G_GNUC_FUNCTION, signal_name);
|
||||
return;
|
||||
g_signal_handlers_disconnect_matched (G_OBJECT (proxy),
|
||||
G_SIGNAL_MATCH_DETAIL |
|
||||
G_SIGNAL_MATCH_FUNC |
|
||||
G_SIGNAL_MATCH_DATA,
|
||||
signal_id,
|
||||
0,
|
||||
NULL,
|
||||
G_CALLBACK (handler), data);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Attempt to disconnect from signal '%s' which is not registered\n",
|
||||
name);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_signal_handlers_disconnect_matched (G_OBJECT (proxy),
|
||||
G_SIGNAL_MATCH_DETAIL |
|
||||
G_SIGNAL_MATCH_FUNC |
|
||||
G_SIGNAL_MATCH_DATA,
|
||||
signals[RECEIVED],
|
||||
q,
|
||||
NULL,
|
||||
G_CALLBACK (handler), data);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
/** @} End of DBusGLib public */
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
*/
|
||||
#include "dbus-names-model.h"
|
||||
#include <glib/gi18n.h>
|
||||
#include <string.h>
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
@ -112,6 +113,81 @@ have_names_notify (DBusGPendingCall *call,
|
|||
g_strfreev (names);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
names_model_find_name (NamesModel *names_model,
|
||||
const char *name,
|
||||
GtkTreeIter *iter_p)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (names_model),
|
||||
&iter))
|
||||
return FALSE;
|
||||
|
||||
do
|
||||
{
|
||||
char *s;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (names_model),
|
||||
&iter,
|
||||
MODEL_COLUMN_NAME, &s,
|
||||
-1);
|
||||
if (s && strcmp (s, name) == 0)
|
||||
{
|
||||
*iter_p = iter;
|
||||
g_free (s);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_free (s);
|
||||
}
|
||||
while (gtk_tree_model_iter_next (GTK_TREE_MODEL (names_model),
|
||||
&iter));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
name_owner_changed (DBusGProxy *driver_proxy,
|
||||
const char *name,
|
||||
const char *old_owner,
|
||||
const char *new_owner,
|
||||
void *data)
|
||||
{
|
||||
NamesModel *names_model = NAMES_MODEL (data);
|
||||
|
||||
#if 0
|
||||
g_printerr ("Name '%s' changed owner '%s' -> '%s'\n",
|
||||
name, old_owner, new_owner);
|
||||
#endif
|
||||
|
||||
if (*new_owner == '\0')
|
||||
{
|
||||
/* this name has vanished */
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (names_model_find_name (names_model, name, &iter))
|
||||
gtk_tree_store_remove (GTK_TREE_STORE (names_model),
|
||||
&iter);
|
||||
}
|
||||
else if (*old_owner == '\0')
|
||||
{
|
||||
/* this name has been added */
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (!names_model_find_name (names_model, name, &iter))
|
||||
{
|
||||
gtk_tree_store_append (GTK_TREE_STORE (names_model),
|
||||
&iter, NULL);
|
||||
|
||||
gtk_tree_store_set (GTK_TREE_STORE (names_model),
|
||||
&iter,
|
||||
MODEL_COLUMN_NAME, name,
|
||||
-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
names_model_reload (NamesModel *names_model)
|
||||
{
|
||||
|
|
@ -144,8 +220,6 @@ static void
|
|||
names_model_set_connection (NamesModel *names_model,
|
||||
DBusGConnection *connection)
|
||||
{
|
||||
const char *match_rule = "type='signal',member='NameOwnerChanged'";
|
||||
|
||||
g_return_if_fail (IS_NAMES_MODEL (names_model));
|
||||
|
||||
if (connection == names_model->connection)
|
||||
|
|
@ -153,10 +227,11 @@ names_model_set_connection (NamesModel *names_model,
|
|||
|
||||
if (names_model->connection)
|
||||
{
|
||||
dbus_g_proxy_call_no_reply (names_model->driver_proxy,
|
||||
"RemoveMatch",
|
||||
DBUS_TYPE_STRING, &match_rule,
|
||||
DBUS_TYPE_INVALID);
|
||||
dbus_g_proxy_disconnect_signal (names_model->driver_proxy,
|
||||
"NameOwnerChanged",
|
||||
G_CALLBACK (name_owner_changed),
|
||||
names_model);
|
||||
|
||||
g_object_unref (names_model->driver_proxy);
|
||||
names_model->driver_proxy = NULL;
|
||||
dbus_g_connection_unref (names_model->connection);
|
||||
|
|
@ -174,6 +249,18 @@ names_model_set_connection (NamesModel *names_model,
|
|||
DBUS_PATH_ORG_FREEDESKTOP_DBUS,
|
||||
DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS);
|
||||
g_assert (names_model->driver_proxy);
|
||||
|
||||
dbus_g_proxy_add_signal (names_model->driver_proxy,
|
||||
"NameOwnerChanged",
|
||||
DBUS_TYPE_STRING_AS_STRING
|
||||
DBUS_TYPE_STRING_AS_STRING
|
||||
DBUS_TYPE_STRING_AS_STRING);
|
||||
|
||||
dbus_g_proxy_connect_signal (names_model->driver_proxy,
|
||||
"NameOwnerChanged",
|
||||
G_CALLBACK (name_owner_changed),
|
||||
names_model,
|
||||
NULL);
|
||||
}
|
||||
|
||||
names_model_reload (names_model);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue