2008-12-17 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     p = arg_types;
91     dbus_message_iter_init (msg, &iter);
92     dbind_any_marshal_va (&iter, &p, args);
93
94     reply = send_and_allow_reentry (cnx, msg, err);
95     if (!reply)
96         goto out;
97
98     if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
99     {
100       const char *name = dbus_message_get_error_name (reply);
101       dbus_set_error (err, name, g_strdup (""));
102       goto out;
103     }
104     /* demarshal */
105     if (p[0] == '=' && p[1] == '>')
106     {
107         DBusMessageIter iter;
108         p += 2;
109         dbus_message_iter_init (reply, &iter);
110         dbind_any_demarshal_va (&iter, &p, args);
111     }
112
113     success = TRUE;
114 out:
115     va_end (args);
116
117     if (msg)
118         dbus_message_unref (msg);
119
120     if (reply)
121         dbus_message_unref (reply);
122
123     if (err == &real_err)
124         dbus_error_free (err);
125
126     return success;
127 }
128
129 /*---------------------------------------------------------------------------*/
130
131 /**
132  * dbind_emit_signal:
133  *
134  * @cnx:       A D-Bus Connection used to make the method call.
135  * @path:      The D-Bus object path that this signal is emitted from.
136  * @interface: The D-Bus interface used to scope the method name.
137  * @signal:    Name of signal to emit.
138  * @opt_error: D-Bus error.
139  * @arg_types: Variable length arguments interleaving D-Bus argument types
140  *             and pointers to argument data.
141  *
142  * Emits a D-Bus signal  using the supplied signal name and argument data.
143  **/
144 dbus_bool_t
145 dbind_emit_signal (DBusConnection *cnx,
146                    const char     *path,
147                    const char     *interface,
148                    const char     *signal,
149                    DBusError      *opt_error,
150                    const char     *arg_types,
151                    ...)
152 {
153     dbus_bool_t success = FALSE;
154     DBusMessage *msg = NULL;
155     DBusMessageIter iter;
156     DBusError *err, real_err;
157     char *p;
158     va_list args;
159
160     va_start (args, arg_types);
161
162     if (opt_error)
163         err = opt_error;
164     else {
165         dbus_error_init (&real_err);
166         err = &real_err;
167     }
168
169     msg = dbus_message_new_signal (path, interface, signal);
170     if (!msg)
171         goto out;
172
173     dbus_message_iter_init (msg, &iter);
174     dbind_any_marshal_va (&iter, &p, args);
175
176     if (!dbus_connection_send (cnx, msg, NULL))
177        goto out;
178
179     success = TRUE;
180 out:
181     va_end (args);
182
183     if (msg)
184         dbus_message_unref (msg);
185
186     if (err == &real_err)
187         dbus_error_free (err);
188
189     return success;
190 }
191
192 /*END------------------------------------------------------------------------*/