2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2008 Novell, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
27 static DRouteInterface *
28 find_iface (DRouteData * data, const char *name)
32 for (l = data->interfaces; l; l = g_slist_next (l))
34 DRouteInterface *iface = (DRouteInterface *) l->data;
35 if (iface && iface->name && !strcmp (iface->name, name))
41 static DBusHandlerResult
42 prop_get_all (DBusConnection * bus, DBusMessage * message, DRouteData * data)
44 DRouteInterface *iface_def;
48 const char *path = dbus_message_get_path (message);
50 DBusMessageIter iter, iter_dict, iter_dict_entry;
52 dbus_error_init (&error);
53 if (!dbus_message_get_args
54 (message, &error, DBUS_TYPE_STRING, &iface, DBUS_TYPE_INVALID))
56 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
58 reply = dbus_message_new_method_return (message);
59 /* tbd: replace tbd with todo? */
62 dbus_message_iter_init_append (reply, &iter);
63 if (!dbus_message_iter_open_container
64 (&iter, DBUS_TYPE_ARRAY, "{sv}", &iter_dict))
66 iface_def = find_iface (data, iface);
68 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
69 if (iface_def->properties)
70 for (prop = iface_def->properties; prop->name; prop++)
74 if (!dbus_message_iter_open_container
75 (&iter_dict, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict_entry))
77 dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING,
79 (*prop->get) (path, &iter_dict_entry, data->user_data);
80 if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry))
83 if (!dbus_message_iter_close_container (&iter, &iter_dict))
85 dbus_connection_send (bus, reply, NULL);
86 dbus_message_unref (reply);
87 return DBUS_HANDLER_RESULT_HANDLED;
89 /* tbd: return a standard out-of-memory error */
90 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
93 static DBusHandlerResult
94 prop (DBusConnection * bus, DBusMessage * message, DRouteData * data)
96 const char *mode = dbus_message_get_member (message);
97 const char *iface, *member;
98 const char *path = dbus_message_get_path (message);
101 DBusMessageIter iter;
102 DRouteInterface *iface_def;
103 DRouteProperty *prop = NULL;
105 if (!strcmp (mode, "Set"))
107 else if (!strcmp (mode, "Get"))
110 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
111 reply = dbus_message_new_method_return (message);
112 dbus_message_iter_init (message, &iter);
113 dbus_message_iter_get_basic (&iter, &iface);
114 dbus_message_iter_next (&iter);
115 dbus_message_iter_get_basic (&iter, &member);
117 dbus_message_iter_init_append (reply, &iter);
118 iface_def = find_iface (data, iface);
120 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
121 if (iface_def->properties)
122 for (prop = iface_def->properties;
123 prop->name && strcmp (prop->name, member); prop++)
124 if (!prop || !prop->name)
125 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
129 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
130 (*prop->set) (path, &iter, data->user_data);
135 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
136 (*prop->get) (path, &iter, data->user_data);
138 dbus_connection_send (bus, reply, NULL);
139 dbus_message_unref (reply);
140 return DBUS_HANDLER_RESULT_HANDLED;
143 static DBusHandlerResult
144 introspect (DBusConnection * bus, DBusMessage * message, DRouteData * data)
146 const char *path = dbus_message_get_path (message);
148 DRouteInterface *iface_def;
149 DRouteMethod *method;
150 DRouteProperty *property;
156 if (strcmp (dbus_message_get_member (message), "Introspect"))
158 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
160 xml = g_string_new (NULL);
161 /* below code stolen from dbus-glib */
162 g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
163 g_string_append_printf (xml, "<node name=\"%s\">\n", path);
165 /* We are introspectable, though I guess that was pretty obvious */
166 g_string_append_printf (xml, " <interface name=\"%s\">\n",
167 DBUS_INTERFACE_INTROSPECTABLE);
168 g_string_append (xml, " <method name=\"Introspect\">\n");
169 g_string_append_printf (xml,
170 " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n",
171 DBUS_TYPE_STRING_AS_STRING);
172 g_string_append (xml, " </method>\n");
173 g_string_append (xml, " </interface>\n");
175 /* We support get/set/getall properties */
176 g_string_append_printf (xml, " <interface name=\"%s\">\n",
177 DBUS_INTERFACE_PROPERTIES);
178 g_string_append (xml, " <method name=\"Get\">\n");
179 g_string_append_printf (xml,
180 " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n",
181 DBUS_TYPE_STRING_AS_STRING);
182 g_string_append_printf (xml,
183 " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n",
184 DBUS_TYPE_STRING_AS_STRING);
185 g_string_append_printf (xml,
186 " <arg name=\"value\" direction=\"out\" type=\"%s\"/>\n",
187 DBUS_TYPE_VARIANT_AS_STRING);
188 g_string_append (xml, " </method>\n");
189 g_string_append (xml, " <method name=\"Set\">\n");
190 g_string_append_printf (xml,
191 " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n",
192 DBUS_TYPE_STRING_AS_STRING);
193 g_string_append_printf (xml,
194 " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n",
195 DBUS_TYPE_STRING_AS_STRING);
196 g_string_append_printf (xml,
197 " <arg name=\"value\" direction=\"in\" type=\"%s\"/>\n",
198 DBUS_TYPE_VARIANT_AS_STRING);
199 g_string_append (xml, " </method>\n");
200 g_string_append (xml, " <method name=\"GetAll\">\n");
201 g_string_append_printf (xml,
202 " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n",
203 DBUS_TYPE_STRING_AS_STRING);
204 g_string_append_printf (xml,
205 " <arg name=\"props\" direction=\"out\" type=\"%s\"/>\n",
206 DBUS_TYPE_ARRAY_AS_STRING
207 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
208 DBUS_TYPE_STRING_AS_STRING
209 DBUS_TYPE_VARIANT_AS_STRING
210 DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
212 g_string_append (xml, " </method>\n");
213 g_string_append (xml, " </interface>\n");
214 /* end of stolen code */
216 for (l = data->interfaces; l; l = g_slist_next (l))
218 iface_def = (DRouteInterface *) l->data;
219 if (iface_def->get_datum)
221 datum = (*iface_def->get_datum) (path, data->user_data);
225 g_string_append_printf (xml, "<interface name=\"%s\">\n",
227 if (iface_def->methods)
228 for (method = iface_def->methods; method->name; method++)
230 const char *p = method->arg_desc;
231 g_string_append_printf (xml, "<%s name=\"%s\">\n",
233 DROUTE_METHOD ? "method" : "signal"),
237 g_string_append (xml, "<arg type=\"");
238 g_string_append_len (xml, p, strcspn (p, ",:"));
239 p += strcspn (p, ",");
242 if (strcspn (p, ",:") > 0)
244 g_string_append (xml, "\" name=\"");
245 g_string_append_len (xml, p, strcspn (p, ",:"));
246 p += strcspn (p, ",");
250 g_string_append_printf (xml, "\" direction=\"%s\"/>\n",
251 (*p == 'o' ? "out" : "in"));
252 p += strcspn (p, ":");
256 g_string_append_printf (xml, "</%s>\n",
258 DROUTE_METHOD ? "method" : "signal"));
260 if (iface_def->properties)
261 for (property = iface_def->properties; property->name; property++)
263 if (!property->get && !property->set)
265 g_string_append_printf (xml,
266 "<property name=\"%s\" type=\"%s\" access=\"%s%s\"/>\n",
267 property->name, property->type,
268 (property->get ? "read" : ""),
269 (property->set ? "write" : ""));
271 if (iface_def->free_datum)
272 (*iface_def->free_datum) (datum);
273 g_string_append (xml, "</interface>\n");
275 if (data->introspect_children)
277 (*data->introspect_children) (path, xml, data->user_data);
279 g_string_append (xml, "</node>\n");
280 str = g_string_free (xml, FALSE);
281 reply = dbus_message_new_method_return (message);
284 dbus_message_append_args (reply, DBUS_TYPE_STRING, &str,
288 dbus_connection_send (bus, reply, NULL);
289 dbus_message_unref (reply);
290 return DBUS_HANDLER_RESULT_HANDLED;
294 droute_message (DBusConnection * bus, DBusMessage * message, void *user_data)
296 DRouteData *data = (DRouteData *) user_data;
297 DRouteInterface *iface_def;
298 DRouteMethod *method;
299 const char *iface = dbus_message_get_interface (message);
300 const char *member = dbus_message_get_member (message);
305 dbus_error_init (&error);
307 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
308 if (iface && !strcmp (iface, "org.freedesktop.DBus.Properties"))
310 if (!strcmp (member, "GetAll"))
311 return prop_get_all (bus, message, data);
312 return prop (bus, message, data);
314 else if (iface && !strcmp (iface, "org.freedesktop.DBus.Introspectable"))
316 return introspect (bus, message, data);
320 int message_type = dbus_message_get_type (message);
321 switch (message_type)
323 case DBUS_MESSAGE_TYPE_METHOD_CALL:
324 type = DROUTE_METHOD;
326 case DBUS_MESSAGE_TYPE_SIGNAL:
327 type = DROUTE_SIGNAL;
330 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
335 iface_def = find_iface (data, iface);
337 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
338 if (iface_def->methods)
339 for (method = iface_def->methods; method->func; method++)
341 if (method->type == type && !strcmp (method->name, member))
344 (*method->func) (bus, message,
345 (method->wants_droute_data ? data : data->
349 dbus_connection_send (bus, reply, NULL);
350 dbus_message_unref (reply);
352 return DBUS_HANDLER_RESULT_HANDLED;
359 if (type == DBUS_MESSAGE_TYPE_SIGNAL)
360 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
361 for (l = data->interfaces; l; l = g_slist_next (l))
363 iface_def = (DRouteInterface *) l->data;
364 if (iface_def->methods)
365 for (method = iface_def->methods; method->func; method++)
367 if (method->type == type && !strcmp (method->name, member))
369 reply = (*method->func) (bus, message, data->user_data);
372 dbus_connection_send (bus, reply, NULL);
373 dbus_message_unref (reply);
375 return DBUS_HANDLER_RESULT_HANDLED;
380 return DBUS_HANDLER_RESULT_HANDLED;
384 droute_return_v_int32 (DBusMessageIter * iter, dbus_int32_t val)
388 if (!dbus_message_iter_open_container
389 (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &sub))
393 dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &val);
394 dbus_message_iter_close_container (iter, &sub);
399 droute_return_v_double (DBusMessageIter * iter, double val)
403 if (!dbus_message_iter_open_container
404 (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &sub))
408 dbus_message_iter_append_basic (&sub, DBUS_TYPE_DOUBLE, &val);
409 dbus_message_iter_close_container (iter, &sub);
413 /* Return a string in a variant
414 * will return an empty string if passed a NULL value */
416 droute_return_v_string (DBusMessageIter * iter, const char *val)
422 if (!dbus_message_iter_open_container
423 (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &sub))
427 dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING, &val);
428 dbus_message_iter_close_container (iter, &sub);
433 droute_get_v_int32 (DBusMessageIter * iter)
438 // TODO- ensure we have the correct type
439 dbus_message_iter_recurse (iter, &sub);
440 dbus_message_iter_get_basic (&sub, &rv);
445 droute_get_v_string (DBusMessageIter * iter)
450 // TODO- ensure we have the correct type
451 dbus_message_iter_recurse (iter, &sub);
452 dbus_message_iter_get_basic (&sub, &rv);
457 droute_return_v_object (DBusMessageIter * iter, const char *path)
461 if (!dbus_message_iter_open_container
462 (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_OBJECT_PATH_AS_STRING, &sub))
466 dbus_message_iter_append_basic (&sub, DBUS_TYPE_OBJECT_PATH, &path);
467 dbus_message_iter_close_container (iter, &sub);
472 droute_add_interface (DRouteData * data, const char *name,
473 DRouteMethod * methods, DRouteProperty * properties,
474 DRouteGetDatumFunction get_datum,
475 DRouteFreeDatumFunction free_datum)
477 DRouteInterface *iface =
478 (DRouteInterface *) malloc (sizeof (DRouteInterface));
483 iface->name = strdup (name);
489 iface->methods = methods;
490 iface->properties = properties;
491 iface->get_datum = get_datum;
492 iface->free_datum = free_datum;
493 new_list = g_slist_append (data->interfaces, iface);
500 data->interfaces = new_list;