2008-12-07 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 /**
44  * dbind_method_call_reentrant:
45  *
46  * @cnx:       A D-Bus Connection used to make the method call.
47  * @bus_name:  The D-Bus bus name of the program where the method call should
48  *             be made.
49  * @path:      The D-Bus object path that should handle the method.
50  * @interface: The D-Bus interface used to scope the method name.
51  * @method:    Method to be invoked.
52  * @opt_error: D-Bus error.
53  * @arg_types: Variable length arguments interleaving D-Bus argument types
54  *             and pointers to argument data.
55  *
56  * Makes a D-Bus method call using the supplied location data, method name and
57  * argument data.This function is re-entrant. It continuously reads from the D-Bus
58  * bus and dispatches messages until a reply has been recieved.
59  **/
60 dbus_bool_t
61 dbind_method_call_reentrant (DBusConnection *cnx,
62                              const char     *bus_name,
63                              const char     *path,
64                              const char     *interface,
65                              const char     *method,
66                              DBusError      *opt_error,
67                              const char     *arg_types,
68                              ...)
69 {
70     dbus_bool_t success = FALSE;
71     DBusMessage *msg = NULL, *reply = NULL;
72     DBusMessageIter iter;
73     DBusError *err, real_err;
74     char *p;
75     va_list args;
76
77     va_start (args, arg_types);
78
79     if (opt_error)
80         err = opt_error;
81     else {
82         dbus_error_init (&real_err);
83         err = &real_err;
84     }
85
86     msg = dbus_message_new_method_call (bus_name, path, interface, method);
87     if (!msg)
88         goto out;
89
90     dbus_message_iter_init (msg, &iter);
91     dbind_any_marshal_va (&iter, &p, args);
92
93     reply = send_and_allow_reentry (cnx, msg, err);
94     if (!reply)
95         goto out;
96
97     if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
98     {
99       const char *name = dbus_message_get_error_name (reply);
100       dbus_set_error (err, name, g_strdup (""));
101       goto out;
102     }
103     /* demarshal */
104     if (p[0] == '=' && p[1] == '>')
105     {
106         DBusMessageIter iter;
107         p += 2;
108         dbus_message_iter_init (reply, &iter);
109         dbind_any_demarshal_va (&iter, &p, args);
110     }
111
112     success = TRUE;
113 out:
114     va_end (args);
115
116     if (msg)
117         dbus_message_unref (msg);
118
119     if (reply)
120         dbus_message_unref (reply);
121
122     if (err == &real_err)
123         dbus_error_free (err);
124
125     return success;
126 }
127
128 /*---------------------------------------------------------------------------*/
129
130 /**
131  * dbind_emit_signal:
132  *
133  * @cnx:       A D-Bus Connection used to make the method call.
134  * @path:      The D-Bus object path that this signal is emitted from.
135  * @interface: The D-Bus interface used to scope the method name.
136  * @signal:    Name of signal to emit.
137  * @opt_error: D-Bus error.
138  * @arg_types: Variable length arguments interleaving D-Bus argument types
139  *             and pointers to argument data.
140  *
141  * Emits a D-Bus signal  using the supplied signal name and argument data.
142  **/
143 dbus_bool_t
144 dbind_emit_signal (DBusConnection *cnx,
145                    const char     *path,
146                    const char     *interface,
147                    const char     *signal,
148                    DBusError      *opt_error,
149                    const char     *arg_types,
150                    ...)
151 {
152     dbus_bool_t success = FALSE;
153     DBusMessage *msg = NULL;
154     DBusMessageIter iter;
155     DBusError *err, real_err;
156     char *p;
157     va_list args;
158
159     va_start (args, arg_types);
160
161     if (opt_error)
162         err = opt_error;
163     else {
164         dbus_error_init (&real_err);
165         err = &real_err;
166     }
167
168     msg = dbus_message_new_signal (path, interface, signal);
169     if (!msg)
170         goto out;
171
172     dbus_message_iter_init (msg, &iter);
173     dbind_any_marshal_va (&iter, &p, args);
174
175     if (!dbus_connection_send (cnx, msg, NULL))
176        goto out;
177
178     success = TRUE;
179 out:
180     va_end (args);
181
182     if (msg)
183         dbus_message_unref (msg);
184
185     if (err == &real_err)
186         dbus_error_free (err);
187
188     return success;
189 }
190
191 /*END------------------------------------------------------------------------*/