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 ((set ? reply : message), &iter);
113 dbus_message_iter_get_basic (&iter, &iface);
114 dbus_message_iter_next (&iter);
115 dbus_message_iter_get_basic (&iter, &member);
116 iface_def = find_iface (data, iface);
118 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
119 if (iface_def->properties)
120 for (prop = iface_def->properties;
121 prop->name && strcmp (prop->name, member); prop++)
122 if (!prop || !prop->name)
123 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
127 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
128 (*prop->set) (path, &iter, data->user_data);
133 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
134 (*prop->get) (path, &iter, data->user_data);
136 dbus_connection_send (bus, reply, NULL);
137 dbus_message_unref (message);
138 return DBUS_HANDLER_RESULT_HANDLED;
141 static DBusHandlerResult
142 introspect (DBusConnection * bus, DBusMessage * message, DRouteData * data)
144 const char *path = dbus_message_get_path (message);
146 DRouteInterface *iface_def;
147 DRouteMethod *method;
148 DRouteProperty *property;
154 if (strcmp (dbus_message_get_member (message), "Introspect"))
156 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
158 xml = g_string_new (NULL);
159 /* below code stolen from dbus-glib */
160 g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
161 g_string_append_printf (xml, "<node name=\"%s\">\n", path);
163 /* We are introspectable, though I guess that was pretty obvious */
164 g_string_append_printf (xml, " <interface name=\"%s\">\n",
165 DBUS_INTERFACE_INTROSPECTABLE);
166 g_string_append (xml, " <method name=\"Introspect\">\n");
167 g_string_append_printf (xml,
168 " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n",
169 DBUS_TYPE_STRING_AS_STRING);
170 g_string_append (xml, " </method>\n");
171 g_string_append (xml, " </interface>\n");
173 /* We support get/set/getall properties */
174 g_string_append_printf (xml, " <interface name=\"%s\">\n",
175 DBUS_INTERFACE_PROPERTIES);
176 g_string_append (xml, " <method name=\"Get\">\n");
177 g_string_append_printf (xml,
178 " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n",
179 DBUS_TYPE_STRING_AS_STRING);
180 g_string_append_printf (xml,
181 " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n",
182 DBUS_TYPE_STRING_AS_STRING);
183 g_string_append_printf (xml,
184 " <arg name=\"value\" direction=\"out\" type=\"%s\"/>\n",
185 DBUS_TYPE_VARIANT_AS_STRING);
186 g_string_append (xml, " </method>\n");
187 g_string_append (xml, " <method name=\"Set\">\n");
188 g_string_append_printf (xml,
189 " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n",
190 DBUS_TYPE_STRING_AS_STRING);
191 g_string_append_printf (xml,
192 " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n",
193 DBUS_TYPE_STRING_AS_STRING);
194 g_string_append_printf (xml,
195 " <arg name=\"value\" direction=\"in\" type=\"%s\"/>\n",
196 DBUS_TYPE_VARIANT_AS_STRING);
197 g_string_append (xml, " </method>\n");
198 g_string_append (xml, " <method name=\"GetAll\">\n");
199 g_string_append_printf (xml,
200 " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n",
201 DBUS_TYPE_STRING_AS_STRING);
202 g_string_append_printf (xml,
203 " <arg name=\"props\" direction=\"out\" type=\"%s\"/>\n",
204 DBUS_TYPE_ARRAY_AS_STRING
205 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
206 DBUS_TYPE_STRING_AS_STRING
207 DBUS_TYPE_VARIANT_AS_STRING
208 DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
210 g_string_append (xml, " </method>\n");
211 g_string_append (xml, " </interface>\n");
212 /* end of stolen code */
214 for (l = data->interfaces; l; l = g_slist_next (l))
216 iface_def = (DRouteInterface *) l->data;
217 datum = (*iface_def->get_datum) (path, data->user_data);
220 g_string_append_printf (xml, "<interface name=\"%s\">\n",
222 if (iface_def->methods)
223 for (method = iface_def->methods; method->name; method++)
225 const char *p = method->arg_desc;
226 g_string_append_printf (xml, "<%s name=\"%s\">\n",
228 DROUTE_METHOD ? "method" : "signal"),
232 g_string_append (xml, "<arg type=\"");
233 g_string_append_len (xml, p, strcspn (p, ",:"));
234 p += strcspn (p, ",");
237 if (strcspn (p, ",:") > 0)
239 g_string_append (xml, "\" name=\"");
240 g_string_append_len (xml, p, strcspn (p, ",:"));
241 p += strcspn (p, ",");
245 g_string_append_printf (xml, "\" direction=\"%s\"/>\n",
246 (*p == 'o' ? "out" : "in"));
247 p += strcspn (p, ":");
251 g_string_append_printf (xml, "</%s>\n",
253 DROUTE_METHOD ? "method" : "signal"));
255 if (iface_def->properties)
256 for (property = iface_def->properties; property->name; property++)
258 if (!property->get && !property->set)
260 g_string_append_printf (xml,
261 "<property name=\"%s\" type=\"%s\" access=\"%s%s\"/>\n",
262 property->name, property->type,
263 (property->get ? "read" : ""),
264 (property->set ? "write" : ""));
266 if (iface_def->free_datum)
267 (*iface_def->free_datum) (datum);
268 g_string_append (xml, "</interface>\n");
270 if (data->introspect_children)
272 (*data->introspect_children) (path, xml, data->user_data);
274 g_string_append (xml, "</node>\n");
275 str = g_string_free (xml, FALSE);
276 reply = dbus_message_new_method_return (message);
279 dbus_message_append_args (reply, DBUS_TYPE_STRING, &str,
283 dbus_connection_send (bus, reply, NULL);
284 dbus_message_unref (reply);
285 return DBUS_HANDLER_RESULT_HANDLED;
289 droute_message (DBusConnection * bus, DBusMessage * message, void *user_data)
291 DRouteData *data = (DRouteData *) user_data;
292 DRouteInterface *iface_def;
293 DRouteMethod *method;
294 const char *iface = dbus_message_get_interface (message);
295 const char *member = dbus_message_get_member (message);
300 dbus_error_init (&error);
302 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
303 if (iface && !strcmp (iface, "org.freedesktop.DBus.Properties"))
305 if (!strcmp (member, "GetAll"))
306 return prop_get_all (bus, message, data);
307 return prop (bus, message, data);
309 else if (iface && !strcmp (iface, "org.freedesktop.DBus.Introspectable"))
311 return introspect (bus, message, data);
315 int message_type = dbus_message_get_type (message);
316 switch (message_type)
318 case DBUS_MESSAGE_TYPE_METHOD_CALL:
319 type = DROUTE_METHOD;
321 case DBUS_MESSAGE_TYPE_SIGNAL:
322 type = DROUTE_SIGNAL;
325 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
330 iface_def = find_iface (data, iface);
332 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
333 if (iface_def->methods)
334 for (method = iface_def->methods; method->func; method++)
336 if (method->type == type && !strcmp (method->name, member))
339 (*method->func) (bus, message,
340 (method->wants_droute_data ? data : data->
344 dbus_connection_send (bus, reply, NULL);
345 dbus_message_unref (reply);
347 return DBUS_HANDLER_RESULT_HANDLED;
354 if (type == DBUS_MESSAGE_TYPE_SIGNAL)
355 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
356 for (l = data->interfaces; l; l = g_slist_next (l))
358 iface_def = (DRouteInterface *) l->data;
359 if (iface_def->methods)
360 for (method = iface_def->methods; method->func; method++)
362 if (method->type == type && !strcmp (method->name, member))
364 reply = (*method->func) (bus, message, data->user_data);
367 dbus_connection_send (bus, reply, NULL);
368 dbus_message_unref (reply);
370 return DBUS_HANDLER_RESULT_HANDLED;
375 return DBUS_HANDLER_RESULT_HANDLED;
379 droute_return_v_int32 (DBusMessageIter * iter, dbus_int32_t val)
383 if (!dbus_message_iter_open_container
384 (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &sub))
388 dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &val);
389 dbus_message_iter_close_container (iter, &sub);
394 droute_return_v_double (DBusMessageIter * iter, double val)
398 if (!dbus_message_iter_open_container
399 (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &sub))
403 dbus_message_iter_append_basic (&sub, DBUS_TYPE_DOUBLE, &val);
404 dbus_message_iter_close_container (iter, &sub);
408 /* Return a string in a variant
409 * will return an empty string if passed a NULL value */
411 droute_return_v_string (DBusMessageIter * iter, const char *val)
417 if (!dbus_message_iter_open_container
418 (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &sub))
422 dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING, &val);
423 dbus_message_iter_close_container (iter, &sub);
428 droute_get_v_int32 (DBusMessageIter * iter)
433 // TODO- ensure we have the correct type
434 dbus_message_iter_recurse (iter, &sub);
435 dbus_message_iter_get_basic (&sub, &rv);
440 droute_get_v_string (DBusMessageIter * iter)
445 // TODO- ensure we have the correct type
446 dbus_message_iter_recurse (iter, &sub);
447 dbus_message_iter_get_basic (&sub, &rv);
452 droute_return_v_object (DBusMessageIter * iter, const char *path)
456 if (!dbus_message_iter_open_container
457 (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_OBJECT_PATH_AS_STRING, &sub))
461 dbus_message_iter_append_basic (&sub, DBUS_TYPE_OBJECT_PATH, &path);
462 dbus_message_iter_close_container (iter, &sub);
467 droute_add_interface (DRouteData * data, const char *name,
468 DRouteMethod * methods, DRouteProperty * properties,
469 DRouteGetDatumFunction get_datum,
470 DRouteFreeDatumFunction free_datum)
472 DRouteInterface *iface =
473 (DRouteInterface *) malloc (sizeof (DRouteInterface));
478 iface->name = strdup (name);
484 iface->methods = methods;
485 iface->properties = properties;
486 iface->get_datum = get_datum;
487 iface->free_datum = free_datum;
488 new_list = g_slist_append (data->interfaces, iface);
495 data->interfaces = new_list;