2008-12-18 Mark Doffman <mark.doffman@codethink.co.uk>
[platform/core/uifw/at-spi2-atk.git] / dbind / dbind.c
1
2
3 #include <stdio.h>
4 #include <stdarg.h>
5 #include <glib.h>
6
7 #include "config.h"
8 #include "dbind/dbind.h"
9
10 /*
11  * FIXME: compare types - to ensure they match &
12  *        do dynamic padding of structures etc.
13  */
14
15 /*---------------------------------------------------------------------------*/
16
17 static void
18 set_reply (DBusPendingCall *pending, void *user_data)
19 {
20     void **replyptr = (void **)user_data;
21
22     *replyptr = dbus_pending_call_steal_reply (pending);
23 }
24
25 static DBusMessage *
26 send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, DBusError *error)
27 {
28     DBusPendingCall *pending;
29     DBusMessage *reply = NULL;
30
31     if (!dbus_connection_send_with_reply (bus, message, &pending, -1))
32     {
33         return NULL;
34     }
35     dbus_pending_call_set_notify (pending, set_reply, (void *)&reply, NULL);
36     while (!reply)
37     {
38       if (!dbus_connection_read_write_dispatch (bus, -1)) return NULL;
39     }
40     return reply;
41 }
42
43 dbus_bool_t
44 dbind_method_call_reentrant_va (DBusConnection *cnx,
45                                 const char     *bus_name,
46                                 const char     *path,
47                                 const char     *interface,
48                                 const char     *method,
49                                 DBusError      *opt_error,
50                                 const char     *arg_types,
51                                 va_list         args)
52 {
53     dbus_bool_t success = FALSE;
54     DBusMessage *msg = NULL, *reply = NULL;
55     DBusMessageIter iter;
56     DBusError *err, real_err;
57     char *p;
58
59     if (opt_error)
60         err = opt_error;
61     else {
62         dbus_error_init (&real_err);
63         err = &real_err;
64     }
65
66     msg = dbus_message_new_method_call (bus_name, path, interface, method);
67     if (!msg)
68         goto out;
69
70     p = arg_types;
71     dbus_message_iter_init (msg, &iter);
72     dbind_any_marshal_va (&iter, &p, args);
73
74     reply = send_and_allow_reentry (cnx, msg, err);
75     if (!reply)
76         goto out;
77
78     if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
79     {
80       const char *name = dbus_message_get_error_name (reply);
81       dbus_set_error (err, name, g_strdup (""));
82       goto out;
83     }
84     /* demarshal */
85     if (p[0] == '=' && p[1] == '>')
86     {
87         DBusMessageIter iter;
88         p += 2;
89         dbus_message_iter_init (reply, &iter);
90         dbind_any_demarshal_va (&iter, &p, args);
91     }
92
93     success = TRUE;
94 out:
95     if (msg)
96         dbus_message_unref (msg);
97
98     if (reply)
99         dbus_message_unref (reply);
100
101     if (err == &real_err)
102         dbus_error_free (err);
103
104     return success;
105 }
106
107 /**
108  * dbind_method_call_reentrant:
109  *
110  * @cnx:       A D-Bus Connection used to make the method call.
111  * @bus_name:  The D-Bus bus name of the program where the method call should
112  *             be made.
113  * @path:      The D-Bus object path that should handle the method.
114  * @interface: The D-Bus interface used to scope the method name.
115  * @method:    Method to be invoked.
116  * @opt_error: D-Bus error.
117  * @arg_types: Variable length arguments interleaving D-Bus argument types
118  *             and pointers to argument data.
119  *
120  * Makes a D-Bus method call using the supplied location data, method name and
121  * argument data.This function is re-entrant. It continuously reads from the D-Bus
122  * bus and dispatches messages until a reply has been recieved.
123  **/
124 dbus_bool_t
125 dbind_method_call_reentrant (DBusConnection *cnx,
126                              const char     *bus_name,
127                              const char     *path,
128                              const char     *interface,
129                              const char     *method,
130                              DBusError      *opt_error,
131                              const char     *arg_types,
132                              ...)
133 {
134     dbus_bool_t success = FALSE;
135     va_list args;
136
137     va_start (args, arg_types);
138     success = dbind_method_call_reentrant_va (cnx,
139                                               bus_name,
140                                               path,
141                                               interface,
142                                               method,
143                                               opt_error,
144                                               arg_types,
145                                               args);
146     va_end (args);
147
148     return success;
149 }
150
151 /*---------------------------------------------------------------------------*/
152
153 /**
154  * dbind_emit_signal:
155  *
156  * @cnx:       A D-Bus Connection used to make the method call.
157  * @path:      The D-Bus object path that this signal is emitted from.
158  * @interface: The D-Bus interface used to scope the method name.
159  * @signal:    Name of signal to emit.
160  * @opt_error: D-Bus error.
161  * @arg_types: Variable length arguments interleaving D-Bus argument types
162  *             and pointers to argument data.
163  *
164  * Emits a D-Bus signal  using the supplied signal name and argument data.
165  **/
166 dbus_bool_t
167 dbind_emit_signal (DBusConnection *cnx,
168                    const char     *path,
169                    const char     *interface,
170                    const char     *signal,
171                    DBusError      *opt_error,
172                    const char     *arg_types,
173                    ...)
174 {
175     dbus_bool_t success = FALSE;
176     DBusMessage *msg = NULL;
177     DBusMessageIter iter;
178     DBusError *err, real_err;
179     char *p;
180     va_list args;
181
182     va_start (args, arg_types);
183
184     if (opt_error)
185         err = opt_error;
186     else {
187         dbus_error_init (&real_err);
188         err = &real_err;
189     }
190
191     msg = dbus_message_new_signal (path, interface, signal);
192     if (!msg)
193         goto out;
194
195     dbus_message_iter_init (msg, &iter);
196     dbind_any_marshal_va (&iter, &p, args);
197
198     if (!dbus_connection_send (cnx, msg, NULL))
199        goto out;
200
201     success = TRUE;
202 out:
203     va_end (args);
204
205     if (msg)
206         dbus_message_unref (msg);
207
208     if (err == &real_err)
209         dbus_error_free (err);
210
211     return success;
212 }
213
214 /*END------------------------------------------------------------------------*/