From 8d0a0083631aff40ea386a688ca892dfeff7d58d Mon Sep 17 00:00:00 2001 From: Mike Gorse Date: Mon, 21 Apr 2008 08:09:41 -0400 Subject: [PATCH] Add droute.c, droute.h, dbus.c, dbus.h, bitarray.h --- libspi/bitarray.h | 35 ++++ libspi/dbus.c | 215 ++++++++++++++++++++++++ libspi/dbus.h | 44 +++++ libspi/droute.c | 479 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ libspi/droute.h | 90 ++++++++++ 5 files changed, 863 insertions(+) create mode 100644 libspi/bitarray.h create mode 100644 libspi/dbus.c create mode 100644 libspi/dbus.h create mode 100644 libspi/droute.c create mode 100644 libspi/droute.h diff --git a/libspi/bitarray.h b/libspi/bitarray.h new file mode 100644 index 0000000..e93dbef --- /dev/null +++ b/libspi/bitarray.h @@ -0,0 +1,35 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2008 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _BITARRAY_H +#define _BITARRAY_H + +#include "dbus/dbus.h" +#include "glib.h" + +#define BITARRAY_SEQ_TERM 0xffffffff + +#define BITARRAY_SET(p, n) ((p)[n/32] |= (1<<(n))) + +gint bitarray_to_seq(dbus_uint32_t *array, gint array_size, gint **out); +dbus_uint32_t bitarray_from_seq(gint *seq, dbus_uint32_t **out); +#endif /* _BITARRAY_H */ diff --git a/libspi/dbus.c b/libspi/dbus.c new file mode 100644 index 0000000..090a721 --- /dev/null +++ b/libspi/dbus.c @@ -0,0 +1,215 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2008 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "accessible.h" +#include +#include +#include "dbus.h" + +static GHashTable *path2ptr; +static guint objindex; + +static void +deregister_object (gpointer obj) +{ + g_hash_table_remove (path2ptr, obj); +} + +static guint +register_object (AtkObject * obj) +{ + if (!path2ptr) + { + path2ptr = g_hash_table_new (g_int_hash, g_int_equal); + if (!path2ptr) + return ++objindex; + } + while (g_hash_table_lookup (path2ptr, (gpointer)++ objindex)) + { + /* g_object_get_data returning 0 means no data, so handle wrap-around */ + if (objindex == 0) + objindex++; + } + g_hash_table_insert (path2ptr, (gpointer) objindex, obj); + g_object_set_data_full (G_OBJECT (obj), "dbus-id", (gpointer) objindex, + deregister_object); + return objindex; +} + +AtkObject * +spi_dbus_get_object (const char *path) +{ + guint index; + void *data; + + g_assert (path); + index = atoi (path); + data = g_hash_table_lookup (path2ptr, (gpointer) index); + if (data) + return ATK_OBJECT (data); + return NULL; +} + +char * +spi_dbus_get_path (AtkObject * obj) +{ + guint index = (guint) g_object_get_data (G_OBJECT (obj), "dbus-id"); + if (!index) + index = register_object (obj); + return g_strdup_printf ("/org/freedesktop/atspi/accessible/%d", index); +} + +DBusMessage * +spi_dbus_general_error (DBusMessage * message) +{ + return dbus_message_new_error (message, + "org.freedesktop.accessibility.GeneralError", + "General error"); +} + +/* Reply with the given object and dereference it if unref is TRUE */ +DBusMessage * +spi_dbus_return_object (DBusMessage * message, AtkObject * obj, int unref) +{ + DBusMessage *reply; + const char *path = spi_dbus_get_path (obj); + if (unref) + g_object_unref (obj); + if (!path) + { + /* Should we have a more specific error for this? */ + return spi_dbus_general_error (message); + } + reply = dbus_message_new_method_return (message); + if (reply) + { + dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, path, + DBUS_TYPE_INVALID); + } + return reply; +} + +DBusMessage * +spi_dbus_return_rect (DBusMessage * message, gint ix, gint iy, gint iwidth, + gint iheight) +{ + DBusMessage *reply; + dbus_uint32_t x, y, width, height; + + x = ix; + y = iy; + width = iwidth; + height = iheight; + reply = dbus_message_new_method_return (message); + if (reply) + { + DBusMessageIter iter, sub; + dbus_message_iter_init_append (reply, &iter); + if (!dbus_message_iter_open_container + (&iter, DBUS_TYPE_STRUCT, NULL, &sub)) + goto oom; + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &x); + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &y); + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &width); + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &height); + if (!dbus_message_iter_close_container (&iter, &sub)) + goto oom; + } + return reply; +oom: + /* todo: return an error */ + return reply; +} + +dbus_bool_t +spi_dbus_return_v_object (DBusMessageIter * iter, AtkObject * obj, int unref) +{ + const char *path = spi_dbus_get_path (obj); + if (unref) + g_object_unref (obj); + if (!path) + return FALSE; + return droute_return_v_object (iter, path); +} + + +void +spi_dbus_initialize (DRouteData * data) +{ + spi_initialize_accessible (data); + spi_initialize_action(data); + spi_initialize_component (data); + spi_initialize_document (data); + spi_initialize_editabletext (data); + spi_initialize_hyperlink (data); + spi_initialize_hypertext (data); + spi_initialize_image (data); + spi_initialize_selection (data); + spi_initialize_table (data); + spi_initialize_text (data); + spi_initialize_value (data); +} + +static GString * +spi_get_tree (AtkObject * obj, GString * str, DRouteData * data) +{ + int role; + const char *name; + gchar *path; + GSList *l; + gint childcount; + gint i; + + if (!obj) + return NULL; + role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));; + name = atk_object_get_name (obj); + if (!name) + name = ""; + path = spi_dbus_get_path (obj); + g_string_append_printf (str, + "\n", + path, name, role); + for (l = data->interfaces; l; l = g_slist_next (l)) + { + DRouteInterface *iface_def = (DRouteInterface *) l->data; + void *datum = NULL; + if (iface_def->get_datum) + datum = (*iface_def->get_datum) (path, data->user_data); + if (datum) + { + g_string_append_printf (str, "\n", + iface_def->name); + if (iface_def->free_datum) + (*iface_def->free_datum) (datum); + } + } + childcount = atk_object_get_n_accessible_children (obj); + for (i = 0; i < childcount; i++) + { + AtkObject *child = atk_object_ref_accessible_child (obj, i); + str = spi_get_tree (child, str, data); + g_object_unref (child); + } + str = g_string_append (str, "\n"); + return str; +} diff --git a/libspi/dbus.h b/libspi/dbus.h new file mode 100644 index 0000000..135fcb2 --- /dev/null +++ b/libspi/dbus.h @@ -0,0 +1,44 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2008 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSPI_DBUS_H +#define _ATSPI_DBUS_H + +#include +#include +#include + +#include "droute.h" + +AtkObject *spi_dbus_get_object(const char *path); + +char *spi_dbus_get_path(AtkObject *obj); +DBusMessage *spi_dbus_general_error(DBusMessage *message); +DBusMessage *spi_dbus_return_rect(DBusMessage *message, gint ix, gint iy, gint iwidth, gint iheight); +DBusMessage *spi_dbus_return_object(DBusMessage *message, AtkObject *obj, int unref); +dbus_bool_t spi_dbus_return_v_object(DBusMessageIter *iter, AtkObject *obj, int unref); + +#define SPI_DBUS_RETURN_ERROR(m, e) dbus_message_new_error(m, (e)->name, (e)->message) + +void spi_dbus_initialize(DRouteData *data); + +#endif /* _ATSPI_DBUS_H */ diff --git a/libspi/droute.c b/libspi/droute.c new file mode 100644 index 0000000..514bfa6 --- /dev/null +++ b/libspi/droute.c @@ -0,0 +1,479 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2008 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "droute.h" +#include +#include + +static DRouteInterface * +find_iface (DRouteData * data, const char *name) +{ + GSList *l; + + for (l = data->interfaces; l; l = g_slist_next (l)) + { + DRouteInterface *iface = (DRouteInterface *) l->data; + if (iface && iface->name && !strcmp (iface->name, name)) + return iface; + } + return NULL; +} + +static DBusHandlerResult +prop_get_all (DBusConnection * bus, DBusMessage * message, DRouteData * data) +{ + DRouteInterface *iface_def; + DRouteProperty *prop; + DBusError error; + const char *iface; + const char *path = dbus_message_get_path (message); + DBusMessage *reply; + DBusMessageIter iter, iter_dict, iter_dict_entry; + + dbus_error_init (&error); + if (!dbus_message_get_args + (message, &error, DBUS_TYPE_STRING, &iface, DBUS_TYPE_INVALID)) + { + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + reply = dbus_message_new_method_return (message); + /* tbd: replace tbd with todo? */ + if (!reply) + goto oom; + dbus_message_iter_init_append (reply, &iter); + if (!dbus_message_iter_open_container + (&iter, DBUS_TYPE_ARRAY, "{sv}", &iter_dict)) + goto oom; + iface_def = find_iface (data, iface); + if (!iface_def) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (iface_def->properties) + for (prop = iface_def->properties; prop->name; prop++) + { + if (!prop->get) + continue; + if (!dbus_message_iter_open_container + (&iter_dict, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict_entry)) + goto oom; + dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, + &prop->name); + (*prop->get) (path, &iter_dict_entry, data->user_data); + if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry)) + goto oom; + } + if (!dbus_message_iter_close_container (&iter, &iter_dict)) + goto oom; + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); + return DBUS_HANDLER_RESULT_HANDLED; +oom: + /* tbd: return a standard out-of-memory error */ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult +prop (DBusConnection * bus, DBusMessage * message, DRouteData * data) +{ + const char *mode = dbus_message_get_member (message); + const char *iface, *member; + const char *path = dbus_message_get_path (message); + int set; + DBusMessage *reply; + DBusMessageIter iter; + DRouteInterface *iface_def; + DRouteProperty *prop = NULL; + + if (!strcmp (mode, "Set")) + set = 1; + else if (!strcmp (mode, "Get")) + set = 0; + else + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + reply = dbus_message_new_method_return (message); + dbus_message_iter_init ((set ? reply : message), &iter); + dbus_message_iter_get_basic (&iter, &iface); + dbus_message_iter_next (&iter); + dbus_message_iter_get_basic (&iter, &member); + iface_def = find_iface (data, iface); + if (!iface_def) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (iface_def->properties) + for (prop = iface_def->properties; + prop->name && strcmp (prop->name, member); prop++) + if (!prop || !prop->name) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (set) + { + if (!prop->set) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + (*prop->set) (path, &iter, data->user_data); + } + else + { + if (!prop->get) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + (*prop->get) (path, &iter, data->user_data); + } + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (message); + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult +introspect (DBusConnection * bus, DBusMessage * message, DRouteData * data) +{ + const char *path = dbus_message_get_path (message); + GString *xml; + DRouteInterface *iface_def; + DRouteMethod *method; + DRouteProperty *property; + char *str; + DBusMessage *reply; + GSList *l; + + if (strcmp (dbus_message_get_member (message), "Introspect")) + { + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + xml = g_string_new (NULL); + /* below code stolen from dbus-glib */ + g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE); + + /* We are introspectable, though I guess that was pretty obvious */ + g_string_append_printf (xml, " \n", + DBUS_INTERFACE_INTROSPECTABLE); + g_string_append (xml, " \n"); + g_string_append_printf (xml, + " \n", + DBUS_TYPE_STRING_AS_STRING); + g_string_append (xml, " \n"); + g_string_append (xml, " \n"); + + /* We support get/set/getall properties */ + g_string_append_printf (xml, " \n", + DBUS_INTERFACE_PROPERTIES); + g_string_append (xml, " \n"); + g_string_append_printf (xml, + " \n", + DBUS_TYPE_STRING_AS_STRING); + g_string_append_printf (xml, + " \n", + DBUS_TYPE_STRING_AS_STRING); + g_string_append_printf (xml, + " \n", + DBUS_TYPE_VARIANT_AS_STRING); + g_string_append (xml, " \n"); + g_string_append (xml, " \n"); + g_string_append_printf (xml, + " \n", + DBUS_TYPE_STRING_AS_STRING); + g_string_append_printf (xml, + " \n", + DBUS_TYPE_STRING_AS_STRING); + g_string_append_printf (xml, + " \n", + DBUS_TYPE_VARIANT_AS_STRING); + g_string_append (xml, " \n"); + g_string_append (xml, " \n"); + g_string_append_printf (xml, + " \n", + DBUS_TYPE_STRING_AS_STRING); + g_string_append_printf (xml, + " \n", + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING); + + g_string_append (xml, " \n"); + g_string_append (xml, " \n"); + g_string_append_printf (xml, "\n", path); + /* end of stolen code */ + + for (l = data->interfaces; l; l = g_slist_next (l)) + { + iface_def = (DRouteInterface *) l->data; + if (!(*iface_def->get_datum) (path, data->user_data)) + continue; + g_string_append_printf (xml, "\n", + iface_def->name); + if (iface_def->methods) + for (method = iface_def->methods; method->name; method++) + { + const char *p = method->arg_desc; + g_string_append_printf (xml, "<%s name=\"%s\">\n", + (method->type == + DROUTE_METHOD ? "method" : "signal"), + method->name); + g_string_append (xml, "\n", + (*p == 'o' ? "out" : "in")); + p += strcspn (p, ":"); + if (*p == ':') + p++; + } + if (iface_def->properties) + for (property = iface_def->properties; property->name; property++) + { + if (!property->get && !property->set) + continue; + g_string_append_printf (xml, + "\n", + property->name, property->type, + (property->get ? "read" : ""), + (property->set ? "write" : "")); + } + } + (*data->introspect_children) (path, xml, data->user_data); + str = g_string_free (xml, FALSE); + reply = dbus_message_new_method_return (message); + if (reply) + { + dbus_message_append_args (reply, DBUS_TYPE_STRING, &str, + DBUS_TYPE_INVALID); + } + g_free (str); + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult +droute_message (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + DRouteData *data = (DRouteData *) user_data; + DRouteInterface *iface_def; + DRouteMethod *method; + const char *iface = dbus_message_get_interface (message); + const char *member = dbus_message_get_member (message); + int type; + DBusError error; + DBusMessage *reply; + + dbus_error_init (&error); + if (!member) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (iface && !strcmp (iface, "org.freedesktop.dbus.Properties")) + { + if (!strcmp (member, "GetAll")) + return prop_get_all (bus, message, data); + return prop (bus, message, data); + } + else if (iface && !strcmp (iface, "org.freedesktop.dbus.Introspectable")) + { + return introspect (bus, message, data); + } + else + { + int message_type = dbus_message_get_type (message); + switch (message_type) + { + case DBUS_MESSAGE_TYPE_METHOD_CALL: + type = DROUTE_METHOD; + break; + case DBUS_MESSAGE_TYPE_SIGNAL: + type = DROUTE_SIGNAL; + break; + default: + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + } + if (iface) + { + iface_def = find_iface (data, iface); + if (!iface_def) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (iface_def->methods) + for (method = iface_def->methods; method->func; method++) + { + if (method->type == type && !strcmp (method->name, member)) + { + reply = + (*method->func) (bus, message, + (method->wants_droute_data ? data : data-> + user_data)); + if (reply) + { + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); + } + return DBUS_HANDLER_RESULT_HANDLED; + } + } + } + else + { + GSList *l; + if (type == DBUS_MESSAGE_TYPE_SIGNAL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + for (l = data->interfaces; l; l = g_slist_next (l)) + { + iface_def = (DRouteInterface *) l->data; + if (iface_def->methods) + for (method = iface_def->methods; method->func; method++) + { + if (method->type == type && !strcmp (method->name, member)) + { + reply = (*method->func) (bus, message, data->user_data); + if (reply) + { + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); + } + return DBUS_HANDLER_RESULT_HANDLED; + } + } + } + } + return DBUS_HANDLER_RESULT_HANDLED; +} + +dbus_bool_t +droute_return_v_int32 (DBusMessageIter * iter, dbus_int32_t val) +{ + DBusMessageIter sub; + + if (!dbus_message_iter_open_container + (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &sub)) + { + return FALSE; + } + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &val); + dbus_message_iter_close_container (iter, &sub); + return TRUE; +} + +dbus_bool_t +droute_return_v_double (DBusMessageIter * iter, double val) +{ + DBusMessageIter sub; + + if (!dbus_message_iter_open_container + (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &sub)) + { + return FALSE; + } + dbus_message_iter_append_basic (&sub, DBUS_TYPE_DOUBLE, &val); + dbus_message_iter_close_container (iter, &sub); + return TRUE; +} + +/* Return a string in a variant + * will return an empty string if passed a NULL value */ +dbus_bool_t +droute_return_v_string (DBusMessageIter * iter, const char *val) +{ + DBusMessageIter sub; + + if (!val) + val = ""; + if (!dbus_message_iter_open_container + (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &sub)) + { + return FALSE; + } + dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING, &val); + dbus_message_iter_close_container (iter, &sub); + return TRUE; +} + +dbus_int32_t +droute_get_v_int32 (DBusMessageIter * iter) +{ + DBusMessageIter sub; + dbus_int32_t rv; + + // TODO- ensure we have the correct type + dbus_message_iter_recurse (iter, &sub); + dbus_message_iter_get_basic (&sub, &rv); + return rv; +} + +const char * +droute_get_v_string (DBusMessageIter * iter) +{ + DBusMessageIter sub; + char *rv; + + // TODO- ensure we have the correct type + dbus_message_iter_recurse (iter, &sub); + dbus_message_iter_get_basic (&sub, &rv); + return rv; +} + +dbus_bool_t +droute_return_v_object (DBusMessageIter * iter, const char *path) +{ + DBusMessageIter sub; + + if (!dbus_message_iter_open_container + (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_OBJECT_PATH_AS_STRING, &sub)) + { + return FALSE; + } + dbus_message_iter_append_basic (&sub, DBUS_TYPE_OBJECT_PATH, &path); + dbus_message_iter_close_container (iter, &sub); + return TRUE; +} + +dbus_bool_t +droute_add_interface (DRouteData * data, const char *name, + DRouteMethod * methods, DRouteProperty * properties, + DRouteGetDatumFunction get_datum, + DRouteFreeDatumFunction free_datum) +{ + DRouteInterface *iface = + (DRouteInterface *) malloc (sizeof (DRouteInterface)); + GSList *new_list; + + if (!iface) + return FALSE; + iface->name = strdup (name); + if (!iface->name) + { + free (iface); + return FALSE; + } + iface->methods = methods; + iface->properties = properties; + iface->get_datum = get_datum; + iface->free_datum = free_datum; + new_list = g_slist_append (data->interfaces, iface); + if (!new_list) + { + free (iface->name); + free (iface); + return FALSE; + } + data->interfaces = new_list; + return TRUE; +} diff --git a/libspi/droute.h b/libspi/droute.h new file mode 100644 index 0000000..0cdfe96 --- /dev/null +++ b/libspi/droute.h @@ -0,0 +1,90 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2008 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _DROUTE_H +#define _DROUTE_H + +#include +#include "glib.h" /* needed for GString */ + +#define DROUTE_METHOD 0 +#define DROUTE_SIGNAL 1 + +typedef DBusMessage *(*DRouteFunction)(DBusConnection *, DBusMessage *, void *); +typedef dbus_bool_t (*DRoutePropertyFunction)(const char *, DBusMessageIter *, void *); +typedef char *(*DRoutePropertyStrFunction)(void *); + +typedef struct _DRouteMethod DRouteMethod; +struct _DRouteMethod +{ + /* DROUTE_(METHOD|SIGNAL) */ + int type; + DRouteFunction func; + const char *name; + /* arg_desc contains argument information used for introspection. + * It is a colon-delimited string of type,name,dir values */ + const char *arg_desc; + dbus_bool_t wants_droute_data; +}; + +typedef struct _DRouteProperty DRouteProperty; +struct _DRouteProperty +{ + DRoutePropertyFunction get; + DRoutePropertyStrFunction get_str; + DRoutePropertyFunction set; + DRoutePropertyStrFunction set_str; + const char *name; + const char *type; +}; + + typedef void *(*DRouteGetDatumFunction)(const char *, void *); + typedef void (*DRouteFreeDatumFunction)(void *); + +typedef struct _DRouteInterface DRouteInterface; +struct _DRouteInterface +{ + DRouteMethod *methods; + DRouteProperty *properties; + DRouteGetDatumFunction get_datum; + DRouteFreeDatumFunction free_datum; + char *name; +}; + +typedef struct _DRouteData DRouteData; +struct _DRouteData +{ + GSList *interfaces; + char (*introspect_children)(const char *, GString *, void *); + void *user_data; +}; + +DBusHandlerResult droute_message(DBusConnection *bus, DBusMessage *message, void *user_data); + +dbus_bool_t droute_return_v_int32(DBusMessageIter *iter, dbus_int32_t val); +dbus_bool_t droute_return_v_double(DBusMessageIter *iter, double val); +dbus_bool_t droute_return_v_string(DBusMessageIter *iter, const char *val); +dbus_int32_t droute_get_v_int32(DBusMessageIter *iter); +const char *droute_get_v_string(DBusMessageIter *iter); +dbus_bool_t droute_return_v_object(DBusMessageIter *iter, const char *path); + +dbus_bool_t droute_add_interface(DRouteData *data, const char *name, DRouteMethod *methods, DRouteProperty *properties, DRouteGetDatumFunction get_datum, DRouteFreeDatumFunction free_datum); +#endif /* _DROUTE_H */ -- 2.7.4