2008-12-07 Mark Doffman <mark.doffman@codethink.co.uk>
authorMark Doffman <mdoff@silver-wind.(none)>
Sun, 7 Dec 2008 23:13:13 +0000 (23:13 +0000)
committerMark Doffman <mdoff@silver-wind.(none)>
Sun, 7 Dec 2008 23:13:13 +0000 (23:13 +0000)
        * dbind/*
          droute/*
          Complete refactoring droute to add api for
          creating single objects and object classes.
          Minor refactor of dbind, adding interface
          for marshalling signals.

14 files changed:
dbind/Makefile.am
dbind/dbind-any.c
dbind/dbind-any.h
dbind/dbind.c
dbind/dbind.h
dbind/dbtest.c
droute/Makefile.am
droute/droute-pairhash.c [new file with mode: 0644]
droute/droute-pairhash.h [moved from droute/introspect-loader.h with 69% similarity]
droute/droute-variant.c [new file with mode: 0644]
droute/droute-variant.h [new file with mode: 0644]
droute/droute.c
droute/droute.h
droute/introspect-loader.c [deleted file]

index 97365b8..cc2849e 100644 (file)
@@ -1,6 +1,6 @@
 lib_LTLIBRARIES = libdbind.la
 
-INCLUDES = \
+AM_CPPFLAGS = \
        -DG_LOG_DOMAIN=\"dbind\" \
        -I$(top_srcdir) \
        $(WARN_CFLAGS) \
@@ -21,4 +21,4 @@ TESTS = dbtest
 
 check_PROGRAMS = dbtest
 dbtest_SOURCES = dbtest.c
-dbtest_LDFLAGS = libdbind.la
\ No newline at end of file
+dbtest_LDFLAGS = libdbind.la
index 1f784e5..83a87ba 100644 (file)
@@ -1,9 +1,9 @@
 /* type driven marshalling */
-#include "config.h"
-#include "dbind-config.h"
-#define DBUS_API_SUBJECT_TO_CHANGE
 #include <stdio.h>
 #include <glib.h>
+
+#include "config.h"
+#include "dbind-config.h"
 #include "dbind-any.h"
 
 #undef DEBUG
   ((gpointer)ALIGN_VALUE(this, boundary))
 
 #define PTR_PLUS(ptr, offset) \
-       ((gpointer) (((guchar *)(ptr)) + (offset)))
+        ((gpointer) (((guchar *)(ptr)) + (offset)))
+
+#define DBIND_POD_CASES \
+         DBUS_TYPE_BYTE: \
+    case DBUS_TYPE_INT16: \
+    case DBUS_TYPE_UINT16: \
+    case DBUS_TYPE_INT32: \
+    case DBUS_TYPE_UINT32: \
+    case DBUS_TYPE_BOOLEAN: \
+    case DBUS_TYPE_INT64: \
+    case DBUS_TYPE_UINT64: \
+    case DBUS_TYPE_DOUBLE
 
-unsigned int dbind_find_c_alignment_r (char **type);
-unsigned int dbind_find_c_alignment   (char  *type);
+/*---------------------------------------------------------------------------*/
 
 static void
 warn_braces ()
@@ -36,26 +46,87 @@ warn_braces ()
              " an explicit type member of 'struct'\n");
 }
 
+/*---------------------------------------------------------------------------*/
+
+static unsigned int
+dbind_find_c_alignment_r (char **type)
+{
+        unsigned int retval = 1;
+
+    char t = **type;
+    (*type)++;
+
+#ifdef DEBUG
+    fprintf (stderr, "\tfind align for %c (0x%x)\n", t, t);
+#endif
+
+        switch (t) {
+    case DBUS_TYPE_BYTE:
+        return DBIND_ALIGNOF_CHAR;
+    case DBUS_TYPE_BOOLEAN:
+        return DBIND_ALIGNOF_DBUS_BOOL_T;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+        return DBIND_ALIGNOF_DBUS_INT16_T;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+        return DBIND_ALIGNOF_DBUS_INT32_T;
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+        return DBIND_ALIGNOF_DBUS_INT64_T;
+    case DBUS_TYPE_DOUBLE:
+        return DBIND_ALIGNOF_DOUBLE;
+    /* ptr types */
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_SIGNATURE:
+    case DBUS_TYPE_ARRAY:
+        return DBIND_ALIGNOF_DBIND_POINTER;
+        case DBUS_STRUCT_BEGIN_CHAR:
+#if DBIND_ALIGNOF_DBIND_STRUCT > 1
+                retval = MAX (retval, DBIND_ALIGNOF_DBIND_STRUCT);
+#endif
+        while (**type != DBUS_STRUCT_END_CHAR) {
+            int elem_align = dbind_find_c_alignment_r (type);
+                        retval = MAX (retval, elem_align);
+        }
+        (*type)++;
+                return retval;
+    case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_DICT_ENTRY:
+        warn_braces ();
+        return DBIND_ALIGNOF_DBIND_POINTER;
+    case '\0':
+        g_assert_not_reached();
+        break;
+        default:
+                return 1;
+        }
+}
+
+/*---------------------------------------------------------------------------*/
+
 /* gather immediate allocation information for this type */
-size_t dbind_gather_alloc_info_r (char **type)
+static size_t
+dbind_gather_alloc_info_r (char **type)
 {
     char t = **type;
     (*type)++;
     if (t == DBUS_TYPE_ARRAY) {
-       switch (**type) {
-           case DBUS_STRUCT_BEGIN_CHAR:
-               while (**type != DBUS_STRUCT_END_CHAR && **type != '\0') (*type)++;
-               if (**type != '\0') (*type)++;
-               break;
-           case '\0':
-               break;
-           default:
-               (*type)++;
-               break;
-           }
-       }
-
-       switch (t) {
+        switch (**type) {
+            case DBUS_STRUCT_BEGIN_CHAR:
+                while (**type != DBUS_STRUCT_END_CHAR && **type != '\0') (*type)++;
+                if (**type != '\0') (*type)++;
+                break;
+            case '\0':
+                break;
+            default:
+                (*type)++;
+                break;
+            }
+        }
+
+        switch (t) {
     case DBUS_TYPE_BYTE:
         return sizeof (char);
     case DBUS_TYPE_BOOLEAN:
@@ -78,106 +149,114 @@ size_t dbind_gather_alloc_info_r (char **type)
     case DBUS_TYPE_ARRAY:
         return sizeof (void *);
     case DBUS_STRUCT_BEGIN_CHAR: {
-               int sum = 0, stralign;
+                int sum = 0, stralign;
 
         stralign = dbind_find_c_alignment (*type - 1);
 
         while (**type != DBUS_STRUCT_END_CHAR) {
-                       sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type));
-                       sum += dbind_gather_alloc_info_r (type);
+                        sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type));
+                        sum += dbind_gather_alloc_info_r (type);
         }
-               sum = ALIGN_VALUE (sum, stralign);
+                sum = ALIGN_VALUE (sum, stralign);
 
         g_assert (**type == DBUS_STRUCT_END_CHAR);
         (*type)++;
 
-               return sum;
+                return sum;
     }
     case DBUS_TYPE_STRUCT:
     case DBUS_TYPE_DICT_ENTRY:
         warn_braces ();
-       default:
-               return 0;
-       }
+        default:
+                return 0;
+        }
 }
 
-size_t dbind_gather_alloc_info (char *type)
+static size_t
+dbind_gather_alloc_info (char *type)
 {
     return dbind_gather_alloc_info_r (&type);
 }
 
-unsigned int
-dbind_find_c_alignment_r (char **type)
-{
-       unsigned int retval = 1;
+/*---------------------------------------------------------------------------*/
 
-    char t = **type;
-    (*type)++;
+static void
+dbind_any_free_r (char **type, void **data)
+{
+    size_t len;
 
 #ifdef DEBUG
-    fprintf (stderr, "\tfind align for %c (0x%x)\n", t, t);
+    fprintf (stderr, "any free '%c' to %p\n", **type, *data);
 #endif
 
-       switch (t) {
-    case DBUS_TYPE_BYTE:
-        return DBIND_ALIGNOF_CHAR;
-    case DBUS_TYPE_BOOLEAN:
-        return DBIND_ALIGNOF_DBUS_BOOL_T;
-    case DBUS_TYPE_INT16:
-    case DBUS_TYPE_UINT16:
-        return DBIND_ALIGNOF_DBUS_INT16_T;
-    case DBUS_TYPE_INT32:
-    case DBUS_TYPE_UINT32:
-        return DBIND_ALIGNOF_DBUS_INT32_T;
-    case DBUS_TYPE_INT64:
-    case DBUS_TYPE_UINT64:
-        return DBIND_ALIGNOF_DBUS_INT64_T;
-    case DBUS_TYPE_DOUBLE:
-        return DBIND_ALIGNOF_DOUBLE;
-    /* ptr types */
+    switch (**type) {
+    case DBIND_POD_CASES:
+        *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
+        (*type)++;
+        break;
     case DBUS_TYPE_STRING:
     case DBUS_TYPE_OBJECT_PATH:
     case DBUS_TYPE_SIGNATURE:
-    case DBUS_TYPE_ARRAY:
-        return DBIND_ALIGNOF_DBIND_POINTER;
-       case DBUS_STRUCT_BEGIN_CHAR:
-#if DBIND_ALIGNOF_DBIND_STRUCT > 1
-               retval = MAX (retval, DBIND_ALIGNOF_DBIND_STRUCT);
+#ifdef DEBUG
+        fprintf (stderr, "string free %p\n", **(void ***)data);
 #endif
+        g_free (**(void ***)data);
+        *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
+        (*type)++;
+        break;
+    case DBUS_TYPE_ARRAY: {
+        int i;
+        GArray *vals = **(void ***)data;
+        size_t elem_size, elem_align;
+        char *saved_child_type, *child_type_string;
+
+        (*type)++;
+        saved_child_type = *type;
+
+        elem_size = dbind_gather_alloc_info (*type);
+        elem_align = dbind_find_c_alignment_r (type); 
+
+        for (i = 0; i < vals->len; i++) {
+            void *ptr = vals->data + elem_size * i;
+            *type = saved_child_type; /* rewind type info */
+            ptr = ALIGN_ADDRESS (ptr, elem_align);
+            dbind_any_free_r (type, &ptr);
+        }
+        g_array_free (vals, TRUE);
+        break;
+    }
+    case DBUS_STRUCT_BEGIN_CHAR: {
+                gconstpointer data0 = *data;
+                int offset = 0, stralign;
+
+        stralign = dbind_find_c_alignment (*type);
+        (*type)++;
+
+        offset = 0 ;
         while (**type != DBUS_STRUCT_END_CHAR) {
-            int elem_align = dbind_find_c_alignment_r (type);
-                       retval = MAX (retval, elem_align);
+            char *subt = *type;
+                        offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
+                        *data = PTR_PLUS (data0, offset);
+            dbind_any_free_r (type, data);
+            offset += dbind_gather_alloc_info (subt);
         }
+
+                offset = ALIGN_VALUE (offset, stralign);
+                *data = PTR_PLUS (data0, offset);
+
+        g_assert (**type == DBUS_STRUCT_END_CHAR);
         (*type)++;
-               return retval;
+
+        break;
+    }
     case DBUS_TYPE_STRUCT:
     case DBUS_TYPE_DICT_ENTRY:
         warn_braces ();
-        return DBIND_ALIGNOF_DBIND_POINTER;
-    case '\0':
-        g_assert_not_reached();
         break;
-       default:
-               return 1;
-       }
+    }
 }
 
-unsigned int
-dbind_find_c_alignment (char *type)
-{
-    return dbind_find_c_alignment_r (&type);
-}
-
-#define DBIND_POD_CASES \
-         DBUS_TYPE_BYTE: \
-    case DBUS_TYPE_INT16: \
-    case DBUS_TYPE_UINT16: \
-    case DBUS_TYPE_INT32: \
-    case DBUS_TYPE_UINT32: \
-    case DBUS_TYPE_BOOLEAN: \
-    case DBUS_TYPE_INT64: \
-    case DBUS_TYPE_UINT64: \
-    case DBUS_TYPE_DOUBLE
+/*---------------------------------------------------------------------------*/
 
 void
 dbind_any_marshal (DBusMessageIter *iter,
@@ -215,7 +294,7 @@ dbind_any_marshal (DBusMessageIter *iter,
 
         /* wow this part of the API sucks too ... */
         child_type_string = g_strndup (saved_child_type, *type - saved_child_type);
-/*        fprintf (stderr, "array child type '%s'\n", child_type_string); */
+        /* fprintf (stderr, "array child type '%s'\n", child_type_string); */
         dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY,
                                           child_type_string, &sub);
         for (i = 0; i < vals->len; i++) {
@@ -230,8 +309,8 @@ dbind_any_marshal (DBusMessageIter *iter,
         break;
     }
     case DBUS_STRUCT_BEGIN_CHAR: {
-               gconstpointer data0 = *data;
-               int offset = 0, stralign;
+                gconstpointer data0 = *data;
+                int offset = 0, stralign;
         DBusMessageIter sub;
 
         stralign = dbind_find_c_alignment (*type);
@@ -243,14 +322,14 @@ dbind_any_marshal (DBusMessageIter *iter,
         offset = 0 ;
         while (**type != DBUS_STRUCT_END_CHAR) {
             char *subt = *type;
-                       offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
-                       *data = PTR_PLUS (data0, offset);
+                        offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
+                        *data = PTR_PLUS (data0, offset);
             dbind_any_marshal (&sub, type, data);
             offset += dbind_gather_alloc_info (subt);
         }
 
-               offset = ALIGN_VALUE (offset, stralign);
-               *data = PTR_PLUS (data0, offset);
+                offset = ALIGN_VALUE (offset, stralign);
+                *data = PTR_PLUS (data0, offset);
 
         dbus_message_iter_close_container (iter, &sub);
 
@@ -266,6 +345,73 @@ dbind_any_marshal (DBusMessageIter *iter,
     }
 }
 
+/*---------------------------------------------------------------------------*/
+
+void
+dbind_any_marshal_va (DBusMessageIter *iter,
+                      char           **arg_types,
+                      va_list          args)
+{
+    char *p = *arg_types;
+    {
+        /* special case base-types since we need to walk the stack worse-luck */
+        for (;*p != '\0' && *p != '=';) {
+            int intarg;
+            void *ptrarg;
+            double doublearg;
+            dbus_int64_t int64arg;
+            void *arg = NULL;
+
+            switch (*p) {
+            case DBUS_TYPE_BYTE:
+            case DBUS_TYPE_BOOLEAN:
+            case DBUS_TYPE_INT16:
+            case DBUS_TYPE_UINT16:
+            case DBUS_TYPE_INT32:
+            case DBUS_TYPE_UINT32:
+                intarg = va_arg (args, int);
+                arg = &intarg;
+                break;
+            case DBUS_TYPE_INT64:
+            case DBUS_TYPE_UINT64:
+                int64arg = va_arg (args, dbus_int64_t);
+                arg = &int64arg;
+                break;
+            case DBUS_TYPE_DOUBLE:
+                doublearg = va_arg (args, double);
+                arg = &doublearg;
+                break;
+            /* ptr types */
+            case DBUS_TYPE_STRING:
+            case DBUS_TYPE_OBJECT_PATH:
+            case DBUS_TYPE_SIGNATURE:
+            case DBUS_TYPE_ARRAY:
+            case DBUS_TYPE_DICT_ENTRY:
+                ptrarg = va_arg (args, void *);
+                arg = &ptrarg;
+                break;
+            case DBUS_STRUCT_BEGIN_CHAR:
+                ptrarg = va_arg (args, void *);
+                arg = ptrarg;
+                break;
+
+            case DBUS_TYPE_VARIANT:
+                fprintf (stderr, "No variant support yet - very toolkit specific\n");
+                ptrarg = va_arg (args, void *);
+                arg = &ptrarg;
+                break;
+            default:
+                fprintf (stderr, "Unknown / invalid arg type %c\n", *p);
+                break;
+            }
+            if (arg != NULL)
+                dbind_any_marshal (iter, &p, &arg);
+            }
+    }
+}
+
+/*---------------------------------------------------------------------------*/
+
 void
 dbind_any_demarshal (DBusMessageIter *iter,
                      char           **type,
@@ -305,13 +451,13 @@ dbind_any_demarshal (DBusMessageIter *iter,
 
         (*type)++;
         stored_child_type = *type;
-        
+
         elem_size = dbind_gather_alloc_info (*type);
         elem_align = dbind_find_c_alignment_r (type);
         vals = g_array_new (FALSE, FALSE, elem_size);
         (**(void ***)data) = vals;
         *data = ((guchar *)*data) + sizeof (void *);
-        
+
         i = 0;
         dbus_message_iter_recurse (iter, &child);
         while (dbus_message_iter_get_arg_type (&child) != DBUS_TYPE_INVALID) {
@@ -326,8 +472,8 @@ dbind_any_demarshal (DBusMessageIter *iter,
         break;
     }
     case DBUS_STRUCT_BEGIN_CHAR: {
-               gconstpointer data0 = *data;
-               int offset = 0, stralign;
+                gconstpointer data0 = *data;
+                int offset = 0, stralign;
         DBusMessageIter child;
 
         stralign = dbind_find_c_alignment (*type);
@@ -338,14 +484,14 @@ dbind_any_demarshal (DBusMessageIter *iter,
 
         while (**type != DBUS_STRUCT_END_CHAR) {
             char *subt = *type;
-                       offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
-                       *data = PTR_PLUS (data0, offset);
+                        offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
+                        *data = PTR_PLUS (data0, offset);
             dbind_any_demarshal (&child, type, data);
             offset += dbind_gather_alloc_info (subt);
         }
 
-               offset = ALIGN_VALUE (offset, stralign);
-               *data = PTR_PLUS (data0, offset);
+                offset = ALIGN_VALUE (offset, stralign);
+                *data = PTR_PLUS (data0, offset);
 
         g_assert (**type == DBUS_STRUCT_END_CHAR);
         (*type)++;
@@ -360,82 +506,22 @@ dbind_any_demarshal (DBusMessageIter *iter,
     dbus_message_iter_next (iter);
 }
 
-static void
-dbind_any_free_r (char **type, void **data)
-{
-    size_t len;
-
-#ifdef DEBUG
-    fprintf (stderr, "any free '%c' to %p\n", **type, *data);
-#endif
-
-    switch (**type) {
-    case DBIND_POD_CASES:
-        *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
-        (*type)++;
-        break;
-    case DBUS_TYPE_STRING:
-    case DBUS_TYPE_OBJECT_PATH:
-    case DBUS_TYPE_SIGNATURE:
-#ifdef DEBUG
-        fprintf (stderr, "string free %p\n", **(void ***)data);
-#endif
-        g_free (**(void ***)data);
-        *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
-        (*type)++;
-        break;
-    case DBUS_TYPE_ARRAY: {
-        int i;
-        GArray *vals = **(void ***)data;
-        size_t elem_size, elem_align;
-        char *saved_child_type, *child_type_string;
-
-        (*type)++;
-        saved_child_type = *type;
-
-        elem_size = dbind_gather_alloc_info (*type);
-        elem_align = dbind_find_c_alignment_r (type); 
-
-        for (i = 0; i < vals->len; i++) {
-            void *ptr = vals->data + elem_size * i;
-            *type = saved_child_type; /* rewind type info */
-            ptr = ALIGN_ADDRESS (ptr, elem_align);
-            dbind_any_free_r (type, &ptr);
-        }
-        g_array_free (vals, TRUE);
-        break;
-    }
-    case DBUS_STRUCT_BEGIN_CHAR: {
-               gconstpointer data0 = *data;
-               int offset = 0, stralign;
+/*---------------------------------------------------------------------------*/
 
-        stralign = dbind_find_c_alignment (*type);
-        (*type)++;
-
-        offset = 0 ;
-        while (**type != DBUS_STRUCT_END_CHAR) {
-            char *subt = *type;
-                       offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
-                       *data = PTR_PLUS (data0, offset);
-            dbind_any_free_r (type, data);
-            offset += dbind_gather_alloc_info (subt);
-        }
-
-               offset = ALIGN_VALUE (offset, stralign);
-               *data = PTR_PLUS (data0, offset);
-
-        g_assert (**type == DBUS_STRUCT_END_CHAR);
-        (*type)++;
-
-        break;
-    }
-    case DBUS_TYPE_STRUCT:
-    case DBUS_TYPE_DICT_ENTRY:
-        warn_braces ();
-        break;
+void
+dbind_any_demarshal_va (DBusMessageIter *iter,
+                        char           **arg_types,
+                        va_list          args)
+{
+    char *p = *arg_types;
+    for (;*p != '\0';) {
+        void *arg = va_arg (args, void *);
+        dbind_any_demarshal (iter, &p, &arg);
     }
 }
 
+/*---------------------------------------------------------------------------*/
+
 /* nice deep free ... */
 void
 dbind_any_free (char *type,
@@ -450,3 +536,13 @@ dbind_any_free_ptr (char *type, void *ptr)
 {
     dbind_any_free (type, &ptr);
 }
+
+/*---------------------------------------------------------------------------*/
+
+unsigned int
+dbind_find_c_alignment (char *type)
+{
+    return dbind_find_c_alignment_r (&type);
+}
+
+/*END------------------------------------------------------------------------*/
index ce6482e..975b244 100644 (file)
@@ -1,17 +1,30 @@
 #ifndef _DBIND_ANY_H_
 #define _DBIND_ANY_H_
 
+#define DBUS_API_SUBJECT_TO_CHANGE
 #include <dbus/dbus.h>
 
-size_t dbind_gather_alloc_info (char            *type);
+unsigned int dbind_find_c_alignment (char *type);
+
 void   dbind_any_marshal       (DBusMessageIter *iter,
                                 char           **type,
                                 void           **val);
+
+void   dbind_any_marshal_va    (DBusMessageIter *iter,
+                                char           **arg_types,
+                                va_list          args);
+
 void   dbind_any_demarshal     (DBusMessageIter *iter,
                                 char           **type,
                                 void           **val);
+
+void   dbind_any_demarshal_va  (DBusMessageIter *iter,
+                                char           **arg_types,
+                                va_list          args);
+
 void   dbind_any_free          (char            *type,
                                 void            *ptr_to_ptr);
+
 void   dbind_any_free_ptr      (char            *type,
                                 void            *ptr);
 
index 1bbf0b0..f34bcc4 100644 (file)
-#include "config.h"
+
+
 #include <stdio.h>
-#define DBUS_API_SUBJECT_TO_CHANGE
-#include <dbind/dbind.h>
-#include <dbind/dbind-any.h>
-#include <glib.h>
 #include <stdarg.h>
+#include <glib.h>
+
+#include "config.h"
+#include "dbind/dbind.h"
 
 /*
  * FIXME: compare types - to ensure they match &
  *        do dynamic padding of structures etc.
  */
 
-struct _DBindContext {
-    DBusConnection *cnx;
-};
-
-DBindContext *
-dbind_create_context (DBusBusType type, DBusError *opt_error)
-{
-    DBindContext *ctx = NULL;
-    DBusConnection *cnx;
-    DBusError *err, real_err;
-    
-    if (opt_error)
-        err = opt_error;
-    else {
-        dbus_error_init (&real_err);
-        err = &real_err;
-    }
-   
-    cnx = dbus_bus_get (DBUS_BUS_SESSION, err);
-    if (!cnx)
-        goto out;
-
-    ctx = g_new0 (DBindContext, 1);
-    ctx->cnx = cnx;
-
-out:
-    if (err == &real_err)
-        dbus_error_free (err);
-
-    return ctx;
-}
-
-void
-dbind_context_free (DBindContext *ctx)
-{
-    if (!ctx)
-        return;
-    dbus_connection_unref (ctx->cnx);
-    g_free (ctx);
-}
-
-dbus_bool_t
-dbind_context_method_call (DBindContext *ctx,
-                           const char *bus_name,
-                           const char *path,
-                           const char *interface,
-                           const char *method,
-                           DBusError *opt_error,
-                           const char *arg_types,
-                           ...)
-{
-    dbus_bool_t success;
-    va_list args;
-
-    va_start (args, arg_types);
-
-    success = dbind_connection_method_call_va
-        (ctx->cnx, bus_name, path, interface, method, opt_error, arg_types, args);
-
-    va_end (args);
-
-    return success;
-}
-
-dbus_bool_t
-dbind_connection_method_call (DBusConnection *cnx,
-                              const char *bus_name,
-                              const char *path,
-                              const char *interface,
-                              const char *method,
-                              DBusError *opt_error,
-                              const char *arg_types,
-                              ...)
-{
-    dbus_bool_t success;
-    va_list args;
-
-    va_start (args, arg_types);
-
-    success = dbind_connection_method_call_va
-        (cnx, bus_name, path, interface, method, opt_error, arg_types, args);
+/*---------------------------------------------------------------------------*/
 
-    va_end (args);
-
-    return success;
-}
-
-static void set_reply (DBusPendingCall *pending, void *user_data)
+static void
+set_reply (DBusPendingCall *pending, void *user_data)
 {
-  void **replyptr = (void **)user_data;
+    void **replyptr = (void **)user_data;
 
-  *replyptr = dbus_pending_call_steal_reply (pending);
+    *replyptr = dbus_pending_call_steal_reply (pending);
 }
 
 static DBusMessage *
-send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, int timeout, DBusError *error)
+send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, DBusError *error)
 {
-  DBusPendingCall *pending;
-  DBusMessage *reply = NULL;
-
-  if (!dbus_connection_send_with_reply (bus, message, &pending, timeout))
-  {
-    return NULL;
-  }
-  dbus_pending_call_set_notify (pending, set_reply, (void *)&reply, NULL);
-  while (!reply)
-  {
-    if (!dbus_connection_read_write_dispatch (bus, timeout)) return NULL;
-  }
-  return reply;
+    DBusPendingCall *pending;
+    DBusMessage *reply = NULL;
+
+    if (!dbus_connection_send_with_reply (bus, message, &pending, -1))
+    {
+        return NULL;
+    }
+    dbus_pending_call_set_notify (pending, set_reply, (void *)&reply, NULL);
+    while (!reply)
+    {
+      if (!dbus_connection_read_write_dispatch (bus, -1)) return NULL;
+    }
+    return reply;
 }
 
+/**
+ * dbind_method_call_reentrant:
+ *
+ * @cnx:       A D-Bus Connection used to make the method call.
+ * @bus_name:  The D-Bus bus name of the program where the method call should
+ *             be made.
+ * @path:      The D-Bus object path that should handle the method.
+ * @interface: The D-Bus interface used to scope the method name.
+ * @method:    Method to be invoked.
+ * @opt_error: D-Bus error.
+ * @arg_types: Variable length arguments interleaving D-Bus argument types
+ *             and pointers to argument data.
+ *
+ * Makes a D-Bus method call using the supplied location data, method name and
+ * argument data.This function is re-entrant. It continuously reads from the D-Bus
+ * bus and dispatches messages until a reply has been recieved.
+ **/
 dbus_bool_t
-dbind_connection_method_call_va (DBusConnection *cnx,
-                                 const char *bus_name,
-                                 const char *path,
-                                 const char *interface,
-                                 const char *method,
-                                 DBusError *opt_error,
-                                 const char *arg_types,
-                                 va_list     args)
+dbind_method_call_reentrant (DBusConnection *cnx,
+                             const char     *bus_name,
+                             const char     *path,
+                             const char     *interface,
+                             const char     *method,
+                             DBusError      *opt_error,
+                             const char     *arg_types,
+                             ...)
 {
     dbus_bool_t success = FALSE;
     DBusMessage *msg = NULL, *reply = NULL;
+    DBusMessageIter iter;
     DBusError *err, real_err;
     char *p;
-    char *dest;
+    va_list args;
+
+    va_start (args, arg_types);
 
     if (opt_error)
         err = opt_error;
@@ -149,88 +86,17 @@ dbind_connection_method_call_va (DBusConnection *cnx,
     msg = dbus_message_new_method_call (bus_name, path, interface, method);
     if (!msg)
         goto out;
-    dbus_message_set_auto_start (msg, TRUE);
 
-    /* marshal */
-    p = (char *)arg_types;
-    {
-        DBusMessageIter iter;
-        
-        dbus_message_iter_init_append (msg, &iter);
-        /* special case base-types since we need to walk the stack worse-luck */
-        for (;*p != '\0' && *p != '=';) {
-            int intarg;
-            void *ptrarg;
-            double doublearg;
-            dbus_int64_t int64arg;
-            void *arg = NULL;
-
-            switch (*p) {
-            case DBUS_TYPE_BYTE:
-            case DBUS_TYPE_BOOLEAN:
-            case DBUS_TYPE_INT16:
-            case DBUS_TYPE_UINT16:
-            case DBUS_TYPE_INT32:
-            case DBUS_TYPE_UINT32:
-                intarg = va_arg (args, int);
-                arg = &intarg;
-                break;
-            case DBUS_TYPE_INT64:
-            case DBUS_TYPE_UINT64:
-                int64arg = va_arg (args, dbus_int64_t);
-                arg = &int64arg;
-                break;
-            case DBUS_TYPE_DOUBLE:
-                doublearg = va_arg (args, double);
-                arg = &doublearg;
-                break;
-            /* ptr types */
-            case DBUS_TYPE_STRING:
-            case DBUS_TYPE_OBJECT_PATH:
-            case DBUS_TYPE_SIGNATURE:
-            case DBUS_TYPE_ARRAY:
-            case DBUS_TYPE_DICT_ENTRY:
-                ptrarg = va_arg (args, void *);
-                arg = &ptrarg;
-                break;
-            case DBUS_STRUCT_BEGIN_CHAR:
-                ptrarg = va_arg (args, void *);
-                arg = ptrarg;
-                break;
-
-            case DBUS_TYPE_VARIANT:
-                fprintf (stderr, "No variant support yet - very toolkit specific\n");
-                ptrarg = va_arg (args, void *);
-                arg = &ptrarg;
-                break;
-            default:
-                fprintf (stderr, "Unknown / invalid arg type %c\n", *p);
-                break;
-            }
-            if (arg != NULL)
-                dbind_any_marshal (&iter, &p, &arg);
-            }
-    }
+    dbus_message_iter_init (msg, &iter);
+    dbind_any_marshal_va (&iter, &p, args);
 
-    dest = dbus_message_get_destination(msg);
-    if (!dest)
-        goto out;
-    if (!strcmp (dbus_bus_get_unique_name(cnx), dest))
-    {
-      /* Can't use dbus_message_send_with_reply_and_block because it will
-       * not pass messages on to the provider side, causing deadlock */
-      reply = send_and_allow_reentry (cnx, msg, -1, err);
-    }
-    else
-    {
-      reply = dbus_connection_send_with_reply_and_block (cnx, msg, -1, err);
-    }
+    reply = send_and_allow_reentry (cnx, msg, err);
     if (!reply)
         goto out;
 
     if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
     {
-      char *name = dbus_message_get_error_name (reply);
+      const char *name = dbus_message_get_error_name (reply);
       dbus_set_error (err, name, g_strdup (""));
       goto out;
     }
@@ -240,14 +106,13 @@ dbind_connection_method_call_va (DBusConnection *cnx,
         DBusMessageIter iter;
         p += 2;
         dbus_message_iter_init (reply, &iter);
-        for (;*p != '\0';) {
-            void *arg = va_arg (args, void *);
-            dbind_any_demarshal (&iter, &p, &arg);
-        }
+        dbind_any_demarshal_va (&iter, &p, args);
     }
 
     success = TRUE;
 out:
+    va_end (args);
+
     if (msg)
         dbus_message_unref (msg);
 
@@ -260,3 +125,67 @@ out:
     return success;
 }
 
+/*---------------------------------------------------------------------------*/
+
+/**
+ * dbind_emit_signal:
+ *
+ * @cnx:       A D-Bus Connection used to make the method call.
+ * @path:      The D-Bus object path that this signal is emitted from.
+ * @interface: The D-Bus interface used to scope the method name.
+ * @signal:    Name of signal to emit.
+ * @opt_error: D-Bus error.
+ * @arg_types: Variable length arguments interleaving D-Bus argument types
+ *             and pointers to argument data.
+ *
+ * Emits a D-Bus signal  using the supplied signal name and argument data.
+ **/
+dbus_bool_t
+dbind_emit_signal (DBusConnection *cnx,
+                   const char     *path,
+                   const char     *interface,
+                   const char     *signal,
+                   DBusError      *opt_error,
+                   const char     *arg_types,
+                   ...)
+{
+    dbus_bool_t success = FALSE;
+    DBusMessage *msg = NULL;
+    DBusMessageIter iter;
+    DBusError *err, real_err;
+    char *p;
+    va_list args;
+
+    va_start (args, arg_types);
+
+    if (opt_error)
+        err = opt_error;
+    else {
+        dbus_error_init (&real_err);
+        err = &real_err;
+    }
+
+    msg = dbus_message_new_signal (path, interface, signal);
+    if (!msg)
+        goto out;
+
+    dbus_message_iter_init (msg, &iter);
+    dbind_any_marshal_va (&iter, &p, args);
+
+    if (!dbus_connection_send (cnx, msg, NULL))
+       goto out;
+
+    success = TRUE;
+out:
+    va_end (args);
+
+    if (msg)
+        dbus_message_unref (msg);
+
+    if (err == &real_err)
+        dbus_error_free (err);
+
+    return success;
+}
+
+/*END------------------------------------------------------------------------*/
index 4e66359..0f6cec8 100644 (file)
@@ -1,39 +1,27 @@
 #ifndef _DBIND_H_
 #define _DBIND_H_
 
-
 #define DBUS_API_SUBJECT_TO_CHANGE
 #include <dbus/dbus.h>
+#include <dbind/dbind-any.h>
 
-typedef struct _DBindContext DBindContext;
-
-DBindContext *dbind_create_context         (DBusBusType type, DBusError *opt_error);
-void          dbind_context_free           (DBindContext *ctx);
-dbus_bool_t   dbind_context_method_call    (DBindContext *ctx,
-                                            const char *bus_name,
-                                            const char *path,
-                                            const char *interface,
-                                            const char *method,
-                                            DBusError *opt_error,
-                                            const char *arg_types,
-                                            ...);
+dbus_bool_t
+dbind_method_call_reentrant (DBusConnection *cnx,
+                             const char     *bus_name,
+                             const char     *path,
+                             const char     *interface,
+                             const char     *method,
+                             DBusError      *opt_error,
+                             const char     *arg_types,
+                             ...);
 
-/* dbus connection variants */
-dbus_bool_t   dbind_connection_method_call    (DBusConnection *cnx,
-                                               const char *bus_name,
-                                               const char *path,
-                                               const char *interface,
-                                               const char *method,
-                                               DBusError *opt_error,
-                                               const char *arg_types,
-                                               ...);
-dbus_bool_t   dbind_connection_method_call_va (DBusConnection *cnx,
-                                               const char *bus_name,
-                                               const char *path,
-                                               const char *interface,
-                                               const char *method,
-                                               DBusError *opt_error,
-                                               const char *arg_types,
-                                               va_list     args);
+dbus_bool_t
+dbind_emit_signal (DBusConnection *cnx,
+                   const char     *path,
+                   const char     *interface,
+                   const char     *signal,
+                   DBusError      *opt_error,
+                   const char     *arg_types,
+                   ...);
 
 #endif /* _DBIND_H_ */
index 9a3ae86..8203c27 100644 (file)
@@ -1,9 +1,7 @@
 #include <stdio.h>
 #include <glib.h>
 #include <string.h>
-#define DBUS_API_SUBJECT_TO_CHANGE
 #include <dbind/dbind.h>
-#include <dbind/dbind-any.h>
 
 /* Wow! dbus is unpleasant to use */
 
@@ -341,7 +339,7 @@ void test_marshalling ()
     fprintf (stderr, "Marshalling ok\n");
 }
 
-void test_teamspaces (DBindContext *ctx)
+void test_teamspaces (DBusConnection *bus)
 {
     GArray *spaces;
     DBusError error;
@@ -353,9 +351,14 @@ void test_teamspaces (DBindContext *ctx)
     } TeamSpace;
 
     dbus_error_init (&error);
-    if (!dbind_context_method_call (ctx, NULL, DESKICE_PATH, DESKICE_NAMESPACE,
-                                    "GetTeamList", &error,
-                                    "=>a(sss)", &spaces)) {
+    if (!dbind_method_call_reentrant (bus,
+                                      NULL,
+                                      DESKICE_PATH,
+                                      DESKICE_NAMESPACE,
+                                      "GetTeamList",
+                                      &error,
+                                      "=>a(sss)",
+                                      &spaces)) {
         fprintf (stderr, "Error getting team spaces %s: %s\n",
                  error.name, error.message);
         dbus_error_free (&error);
@@ -375,8 +378,6 @@ void test_teamspaces (DBindContext *ctx)
     dbind_any_free_ptr ("a(sss)", spaces);
 }
 
-extern dbind_find_c_alignment (char *type);
-
 void test_helpers ()
 {
     dbind_find_c_alignment ("(sss)");
@@ -387,17 +388,14 @@ void test_helpers ()
 
 int main (int argc, char **argv)
 {
-    DBindContext *ctx;
+    DBusConnection *bus;
+    DBusError err;
 
-    ctx = dbind_create_context (DBUS_BUS_SESSION, NULL);
-    if (!ctx)
-        return 1;
+    bus = dbus_bus_get (DBUS_BUS_SESSION, &err);
 
     test_helpers ();
     test_marshalling ();
-    test_teamspaces (ctx);
-
-    dbind_context_free (ctx);
+    test_teamspaces (bus);
 
     return 0;
 }
index 2071b8f..46207e4 100644 (file)
@@ -1,12 +1,19 @@
 noinst_LTLIBRARIES = libdroute.la
 
-libdroute_la_CFLAGS = $(DBUS_GLIB_CFLAGS) $(ATK_CFLAGS)\
-                    -DATSPI_INTROSPECTION_PATH=\"$(pkgdatadir)/$(DEFAULT_ATSPI_INTROSPECTION_PATH)\"\
-                    -I$(top_builddir)\
-                    -I$(top_srcdir)
+libdroute_la_CFLAGS = $(DBUS_GLIB_CFLAGS) \
+                      -DATSPI_INTROSPECTION_PATH=\"$(pkgdatadir)/$(DEFAULT_ATSPI_INTROSPECTION_PATH)\"\
+                      -I$(top_builddir)\
+                      -I$(top_srcdir)
 
-libdroute_la_SOURCES =         \
-       droute.c                \
-       droute.h                \
-       introspect-loader.c     \
-       introspect-loader.h
+libdrouteinclude_HEADERS = \
+               droute.h
+               droute-variant.h
+libdrouteincludedir=$(includedir)/dbind-0.1
+
+libdroute_la_SOURCES =\
+               droute.c\
+               droute.h\
+               droute-variant.c\
+               droute-variant.h\
+               droute-pairhash.c\
+               droute-pairhash.h
diff --git a/droute/droute-pairhash.c b/droute/droute-pairhash.c
new file mode 100644 (file)
index 0000000..20ff491
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2008 Codethink Ltd.
+ *
+ * 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-pairhash.h"
+
+/*---------------------------------------------------------------------------*/
+
+static guint
+str_hash (guint32 h, const signed char *p)
+{
+  for (p += 1; *p != '\0'; p++)
+      h = (h << 5) - h + *p;
+
+  return h;
+}
+
+/*---------------------------------------------------------------------------*/
+
+StrPair *
+str_pair_new (const gchar *one, const gchar *two)
+{
+    StrPair *pair;
+
+    pair = g_new (StrPair, 1);
+    pair->one = one;
+    pair->two = two;
+}
+
+gint
+str_pair_hash (gconstpointer key)
+{
+    StrPair *pair = (StrPair *) key;
+    guint hash = 0;
+
+    if (*(pair->two) != '\0')
+      {
+        hash = *(pair->two);
+        hash = str_hash (hash, ++(pair->two));
+        hash = str_hash (hash, pair->one);
+      }
+
+    return hash;
+}
+
+gboolean
+str_pair_equal (gconstpointer a, gconstpointer b)
+{
+    StrPair *ap = (StrPair *) a;
+    StrPair *bp = (StrPair *) b;
+
+    if (g_str_equal (ap->one, bp->one) &&
+        g_str_equal (ap->two, bp->two))
+      {
+        return TRUE;
+      }
+    else
+      {
+        return FALSE;
+      }
+}
+
+/*END------------------------------------------------------------------------*/
similarity index 69%
rename from droute/introspect-loader.h
rename to droute/droute-pairhash.h
index bfea0b7..50d4b34 100644 (file)
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-
-#ifndef SPI_INTROSPECT_LOADER_H_
-#define SPI_INTROSPECT_LOADER_H_
+#ifndef _DROUTE_PAIRHASH_H
+#define _DROUTE_PAIRHASH_H
 
 #include <glib.h>
 
-extern const char *spi_introspection_header;
-
-extern const char *spi_introspection_node_element;
+typedef struct _StrPair StrPair;
+struct _StrPair
+{
+    const gchar *one;
+    const gchar *two;
+};
 
-extern const char *spi_introspection_footer;
+StrPair *str_pair_new     (const gchar *one,
+                           const gchar *two);
 
-void
-spi_append_interface (GString *str, const char *interface);
+gint     str_pair_hash    (gconstpointer key);
+gboolean str_pair_equal   (gconstpointer a,
+                           gconstpointer b);
 
-#endif /* SPI_INTROSPECT_LOADER_H_ */
+#endif /* _DROUTE_PAIRHASH_H */
diff --git a/droute/droute-variant.c b/droute/droute-variant.c
new file mode 100644 (file)
index 0000000..d4b5ca6
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include "droute-variant.h"
+
+/*---------------------------------------------------------------------------*/
+
+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;
+}
+
+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_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_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;
+}
+
+/*END------------------------------------------------------------------------*/
diff --git a/droute/droute-variant.h b/droute/droute-variant.h
new file mode 100644 (file)
index 0000000..47feb96
--- /dev/null
@@ -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 _DROUTE_VARIANT_H
+#define _DROUTE_VARIANT_H
+
+#include <dbus/dbus.h>
+
+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_bool_t  droute_return_v_object (DBusMessageIter *iter, const char *path);
+
+dbus_int32_t droute_get_v_int32     (DBusMessageIter *iter);
+const char  *droute_get_v_string    (DBusMessageIter *iter);
+
+#endif /* _DROUTE_VARIANT_H */
index e4c1f91..5b1d9de 100644 (file)
@@ -3,6 +3,7 @@
  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
  *
  * Copyright 2008 Novell, Inc.
+ * Copyright 2008 Codethink Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #include <string.h>
 
 #include "droute.h"
+#include "droute-pairhash.h"
 
-static DRouteInterface *
-find_iface (DRouteData * data, const char *name)
+#define CHUNKS_DEFAULT (512)
+
+#define oom() g_error ("D-Bus out of memory, this message will fail anyway")
+
+struct _DRouteContext
 {
-  GSList *l;
+    DBusConnection       *bus;
+    GPtrArray            *registered_paths;
 
-  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;
-}
+    gchar                *introspect_dir;
+};
+
+struct _DRoutePath
+{
+    DRouteContext        *cnx;
+    GStringChunk         *chunks;
+    GPtrArray            *interfaces;
+    GHashTable           *methods;
+    GHashTable           *properties;
+
+    void                   *user_data;
+    DRouteGetDatumFunction  get_datum;
+};
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct PropertyPair
+{
+    DRoutePropertyFunction get;
+    DRoutePropertyFunction set;
+} PropertyPair;
+
+/*---------------------------------------------------------------------------*/
 
 static DBusHandlerResult
-prop_get_all (DBusConnection * bus, DBusMessage * message, DRouteData * data)
+handle_message (DBusConnection *bus, DBusMessage *message, void *user_data);
+
+/*---------------------------------------------------------------------------*/
+
+static DRoutePath *
+path_new (DRouteContext *cnx,
+          void    *user_data,
+          DRouteGetDatumFunction get_datum)
 {
-  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;
+    DRoutePath *new_path;
+
+    new_path = g_new0 (DRoutePath, 0);
+    new_path->cnx = cnx;
+    new_path->chunks = g_string_chunk_new (CHUNKS_DEFAULT);
+    new_path->interfaces = g_ptr_array_new ();
+
+    new_path->methods = g_hash_table_new_full ((GHashFunc)str_pair_hash,
+                                               str_pair_equal,
+                                               g_free,
+                                               NULL);
+
+    new_path->properties = g_hash_table_new_full ((GHashFunc)str_pair_hash,
+                                                  str_pair_equal,
+                                                  g_free,
+                                                  NULL);
+
+    new_path->user_data = user_data;
+    new_path->get_datum = get_datum;
+
+    return new_path;
 }
 
-static DBusHandlerResult
-prop (DBusConnection * bus, DBusMessage * message, DRouteData * data)
+static void
+path_free (DRoutePath *path, gpointer user_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 (message, &iter);
-  dbus_message_iter_get_basic (&iter, &iface);
-  dbus_message_iter_next (&iter);
-  dbus_message_iter_get_basic (&iter, &member);
-  if (!set)
-    dbus_message_iter_init_append (reply, &iter);
-  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 (reply);
-  return DBUS_HANDLER_RESULT_HANDLED;
+    g_string_chunk_free  (path->chunks);
+    g_ptr_array_free     (path->interfaces, TRUE);
+    g_hash_table_destroy (path->methods);
+    g_hash_table_destroy (path->properties);
 }
 
-DBusHandlerResult
-droute_message (DBusConnection * bus, DBusMessage * message, void *user_data)
+static void *
+path_get_datum (DRoutePath *path, const gchar *pathstr)
 {
-  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);
-    }
-  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 (!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 (!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;
+    if (path->get_datum != NULL)
+        return (path->get_datum) (pathstr, path->user_data);
+    else
+        return path->user_data;
 }
 
-dbus_bool_t
-droute_return_v_int32 (DBusMessageIter * iter, dbus_int32_t val)
+/*---------------------------------------------------------------------------*/
+
+DRouteContext *
+droute_new (DBusConnection *bus, const char *introspect_dir)
 {
-  DBusMessageIter sub;
+    DRouteContext *cnx;
 
-  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;
+    cnx = g_new0 (DRouteContext, 1);
+    cnx->bus = bus;
+    cnx->registered_paths = g_ptr_array_new ();
+    cnx->introspect_dir = g_strdup(introspect_dir);
 }
 
-dbus_bool_t
-droute_return_v_double (DBusMessageIter * iter, double val)
+void
+droute_free (DRouteContext *cnx)
 {
-  DBusMessageIter sub;
+    g_pointer_array_foreach ((GFunc) path_free, cnx->registered_paths, NULL);
+    g_free (cnx->introspect_dir);
+    g_free (cnx);
+}
 
-  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;
+/*---------------------------------------------------------------------------*/
+
+static DBusObjectPathVTable droute_vtable =
+{
+  NULL,
+  &handle_message,
+  NULL, NULL, NULL, NULL
+};
+
+DRoutePath *
+droute_add_one (DRouteContext *cnx,
+                const char    *path,
+                const void    *data)
+{
+    DRoutePath *new_path;
+
+    new_path = path_new (cnx, (void *) data, NULL);
+
+    if (!dbus_connection_register_object_path (cnx->bus, path, &droute_vtable, new_path))
+        oom();
+
+    g_ptr_array_add (cnx->registered_paths, new_path);
+    return new_path;
 }
 
-/* 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)
+DRoutePath *
+droute_add_many (DRouteContext *cnx,
+                 const char    *path,
+                 const void    *data,
+                 const DRouteGetDatumFunction get_datum)
 {
-  DBusMessageIter sub;
+    DRoutePath *new_path;
 
-  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;
+    new_path = path_new (cnx, (void *) data, get_datum);
+
+    if (!dbus_connection_register_fallback (cnx->bus, path, &droute_vtable, new_path))
+        oom();
+
+    g_ptr_array_add (cnx->registered_paths, new_path);
+    return new_path;
 }
 
-dbus_int32_t
-droute_get_v_int32 (DBusMessageIter * iter)
+/*---------------------------------------------------------------------------*/
+
+void
+droute_path_add_interface(DRoutePath *path,
+                          const char *name,
+                          const DRouteMethod   *methods,
+                          const DRouteProperty *properties)
 {
-  DBusMessageIter sub;
-  dbus_int32_t rv;
+    gchar *itf;
+
+    g_return_if_fail (name == NULL);
+
+    itf = g_string_chunk_insert (path->chunks, name);
+    g_ptr_array_add (path->interfaces, itf);
+
+    for (; methods->name != NULL; methods++)
+      {
+        gchar *meth;
+
+        meth = g_string_chunk_insert (path->chunks, methods->name);
+        g_hash_table_insert (path->methods, str_pair_new (itf, meth), methods->func);
+      }
 
-  // TODO- ensure we have the correct type
-  dbus_message_iter_recurse (iter, &sub);
-  dbus_message_iter_get_basic (&sub, &rv);
-  return rv;
+    for (; properties->name != NULL; properties++)
+      {
+        gchar *prop;
+        PropertyPair *pair;
+
+        prop = g_string_chunk_insert (path->chunks, properties->name);
+        pair = g_new (PropertyPair, 1);
+        pair->get = properties->get;
+        pair->set = properties->set;
+        g_hash_table_insert (path->properties, str_pair_new (itf, prop), pair);
+      }
 }
 
-const char *
-droute_get_v_string (DBusMessageIter * iter)
+/*---------------------------------------------------------------------------*/
+
+/* The data structures don't support an efficient implementation of GetAll
+ * and I don't really care.
+ */
+static DBusMessage *
+impl_prop_GetAll (DBusMessage *message,
+                  DRoutePath  *path,
+                  const char  *pathstr)
 {
-  DBusMessageIter sub;
-  char *rv;
+    DBusMessageIter iter, iter_dict, iter_dict_entry;
+    DBusMessage *reply;
+    DBusError error;
+    GHashTableIter prop_iter;
+
+    StrPair *key;
+    PropertyPair *value;
+    gchar *iface;
+
+    void  *datum = path_get_datum (path, pathstr);
+
+    dbus_error_init (&error);
 
-  // TODO- ensure we have the correct type
-  dbus_message_iter_recurse (iter, &sub);
-  dbus_message_iter_get_basic (&sub, &rv);
-  return rv;
+    if (!dbus_message_get_args
+                (message, &error, DBUS_TYPE_STRING, &iface, DBUS_TYPE_INVALID))
+        return dbus_message_new_error (message, DBUS_ERROR_FAILED, error.message);
+
+    reply = dbus_message_new_method_return (message);
+    if (!reply)
+        oom ();
+
+    dbus_message_iter_init_append (reply, &iter);
+    if (!dbus_message_iter_open_container
+                (&iter, DBUS_TYPE_ARRAY, "{sv}", &iter_dict))
+        oom ();
+
+    g_hash_table_iter_init (&prop_iter, path->properties);
+    while (g_hash_table_iter_next (&prop_iter, (gpointer*)&key, (gpointer*)&value))
+      {
+        if (!g_strcmp (key->one, iface))
+         {
+           if (!value->get)
+              continue;
+           if (!dbus_message_iter_open_container
+                        (&iter_dict, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict_entry))
+              oom ();
+           dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING,
+                                           key->two);
+           (value->get) (&iter_dict_entry, datum);
+           if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry))
+               oom ();
+         }
+      }
+
+    if (!dbus_message_iter_close_container (&iter, &iter_dict))
+        oom ();
+    return reply;
 }
 
-dbus_bool_t
-droute_return_v_object (DBusMessageIter * iter, const char *path)
+static DBusMessage *
+impl_prop_GetSet (DBusMessage *message,
+                  DRoutePath  *path,
+                  const char  *pathstr,
+                  gboolean     get)
 {
-  DBusMessageIter sub;
+    DBusMessage *reply = NULL;
+    DBusError error;
 
-  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;
+    StrPair pair;
+    PropertyPair *prop_funcs;
+
+    if (!dbus_message_get_args (message,
+                                &error,
+                                DBUS_TYPE_STRING,
+                                &(pair.one),
+                                DBUS_TYPE_STRING,
+                                &(pair.two),
+                                DBUS_TYPE_INVALID))
+        return dbus_message_new_error (message, DBUS_ERROR_FAILED, error.message);
+
+    prop_funcs = (PropertyPair *) g_hash_table_lookup (path->properties, &pair);
+    if (!prop_funcs)
+        return dbus_message_new_error (message, DBUS_ERROR_FAILED, "Property unavailable");
+
+    if (get && prop_funcs->get)
+      {
+        void *datum = path_get_datum (path, pathstr);
+        DBusMessageIter iter;
+
+        reply = dbus_message_new_method_return (message);
+        dbus_message_iter_init_append (reply, &iter);
+        (prop_funcs->get) (&iter, datum);
+      }
+    else if (!get && prop_funcs->set)
+      {
+        void *datum = path_get_datum (path, pathstr);
+        DBusMessageIter iter;
+
+        dbus_message_iter_init_append (message, &iter);
+        /* Skip the interface and property name */
+        dbus_message_iter_next(&iter);
+        dbus_message_iter_next(&iter);
+        (prop_funcs->get) (&iter, datum);
+      }
+    return reply;
 }
 
-dbus_bool_t
-droute_add_interface (DRouteData * data, const char *name,
-                     DRouteMethod * methods, DRouteProperty * properties,
-                     DRouteGetDatumFunction get_datum,
-                     DRouteFreeDatumFunction free_datum)
+static DBusHandlerResult
+handle_properties (DBusConnection *bus,
+                   DBusMessage    *message,
+                   DRoutePath     *path,
+                   const gchar    *iface,
+                   const gchar    *member,
+                   const gchar    *pathstr)
 {
-  DRouteInterface *iface =
-    (DRouteInterface *) malloc (sizeof (DRouteInterface));
-  GSList *new_list;
-
-  if (!iface)
-    return FALSE;
-  iface->name = strdup (name);
-  if (!iface->name)
+    DBusMessage *reply;
+    DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED;
+
+    if (!g_strcmp0(member, "GetAll"))
+       reply = impl_prop_GetAll (message, path, pathstr);
+    else if (!g_strcmp0 (member, "Get"))
+       reply = impl_prop_GetSet (message, path, pathstr, TRUE);
+    else if (!g_strcmp0 (member, "Set"))
+       reply = impl_prop_GetSet (message, path, pathstr, FALSE);
+    else
+       result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    return result;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static const char *introspection_header =
+"<?xml version=\"1.0\"?>\n";
+
+static const char *introspection_node_element =
+"<node name=\"%s\">\n";
+
+static const char *introspection_footer =
+"</node>";
+
+static void
+append_interface (GString     *str,
+                  const gchar *interface,
+                  const gchar *directory)
+{
+  gchar *filename;
+  gchar *contents;
+  gsize len;
+
+  GError *err = NULL;
+
+  filename = g_build_filename (directory, interface, NULL);
+
+  if (g_file_get_contents (filename, &contents, &len, &err))
     {
-      free (iface);
-      return FALSE;
+      g_string_append_len (str, contents, len);
     }
-  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)
+  else
     {
-      free (iface->name);
-      free (iface);
-      return FALSE;
+      g_warning ("AT-SPI: Cannot find introspection XML file %s - %s",
+                 filename, err->message);
+      g_error_free (err);
     }
-  data->interfaces = new_list;
-  return TRUE;
+
+  g_string_append (str, "\n");
+  g_free (filename);
+  g_free (contents);
 }
+
+static DBusHandlerResult
+handle_intropsection (DBusConnection *bus,
+                      DBusMessage    *message,
+                      DRoutePath     *path,
+                      const gchar    *iface,
+                      const gchar    *member,
+                      const gchar    *pathstr)
+{
+    GString *output;
+    gchar *final;
+    gint i;
+
+    DBusMessage *reply;
+
+    if (g_strcmp (member, "Introspect"))
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    output = g_string_new(introspection_header);
+
+    g_string_append_printf(output, introspection_node_element, pathstr);
+
+    for (i=0; i < path->interfaces->len; i++)
+      {
+        gchar *interface = (gchar *) g_ptr_array_index (path->interfaces, i);
+        append_interface(output, interface, path->cnx->introspect_dir);
+      }
+
+    g_string_append(output, introspection_footer);
+    final = g_string_free(output, FALSE);
+
+    reply = dbus_message_new_method_return (message);
+    if (!reply)
+        oom ();
+    dbus_message_append_args(reply, DBUS_TYPE_STRING, &final,
+                             DBUS_TYPE_INVALID);
+    dbus_connection_send (bus, reply, NULL);
+
+    dbus_message_unref (reply);
+    g_free(final);
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static DBusHandlerResult
+handle_other (DBusConnection *bus,
+              DBusMessage    *message,
+              DRoutePath     *path,
+              const gchar    *iface,
+              const gchar    *member,
+              const gchar    *pathstr)
+{
+    gint result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    StrPair pair;
+    DRouteFunction func;
+    DBusMessage *reply;
+
+    pair.one = iface;
+    pair.two = member;
+
+    func = (DRouteFunction) g_hash_table_lookup (path->methods, &pair);
+    if (func != NULL)
+      {
+        void *datum = path_get_datum (path, pathstr);
+
+        reply = (func) (bus, message, datum);
+
+        if (reply)
+          {
+            dbus_connection_send (bus, reply, NULL);
+            dbus_message_unref (reply);
+          }
+        result = DBUS_HANDLER_RESULT_HANDLED;
+      }
+    return result;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static DBusHandlerResult
+handle_message (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+    DRoutePath *path = (DRoutePath *) user_data;
+    const gchar *iface   = dbus_message_get_interface (message);
+    const gchar *member  = dbus_message_get_member (message);
+    const gint   type    = dbus_message_get_type (message);
+    const gchar *pathstr = dbus_message_get_path (message);
+
+    /* Check for basic reasons not to handle */
+    if (type   != DBUS_MESSAGE_TYPE_METHOD_CALL ||
+        member == NULL ||
+        iface  == NULL)
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    if (!strcmp (iface, "org.freedesktop.DBus.Properties"))
+        return handle_properties (bus, message, path, iface, member, pathstr);
+
+    if (!strcmp (iface, "org.freedesktop.DBus.Introspectable"))
+        return handle_introspection (bus, message, path, iface, member, pathstr);
+
+    return handle_other (bus, message, path, iface, member, pathstr);
+}
+
+/*END------------------------------------------------------------------------*/
index c3006cc..93de4f7 100644 (file)
@@ -3,6 +3,7 @@
  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
  *
  * Copyright 2008 Novell, Inc.
+ * Copyright 2008 Codethink Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #define _DROUTE_H
 
 #include <dbus/dbus.h>
-#include "glib.h"      /* needed for GString */
+#include <glib.h>
 
-#define DROUTE_METHOD   0
-#define DROUTE_SIGNAL   1
+#include <droute/droute-variant.h>
 
-typedef DBusMessage *(*DRouteFunction)(DBusConnection *, DBusMessage *, void *);
-typedef dbus_bool_t (*DRoutePropertyFunction)(const char *, DBusMessageIter *, void *);
+typedef DBusMessage *(*DRouteFunction)         (DBusConnection *, DBusMessage *, void *);
+typedef dbus_bool_t  (*DRoutePropertyFunction) (DBusMessageIter *, void *);
+
+typedef void        *(*DRouteGetDatumFunction) (const char *, void *);
 
 typedef struct _DRouteMethod DRouteMethod;
 struct _DRouteMethod
 {
-  DRouteFunction func;
-  const char *name;
-  dbus_bool_t wants_droute_data;
+    DRouteFunction func;
+    const char *name;
 };
 
 typedef struct _DRouteProperty DRouteProperty;
 struct _DRouteProperty
 {
-  DRoutePropertyFunction get;
-  DRoutePropertyFunction set;
-  const char *name;
+    DRoutePropertyFunction get;
+    DRoutePropertyFunction set;
+    const char *name;
 };
 
-  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 _DRouteContext DRouteContext;
 
-typedef struct _DRouteData DRouteData;
-struct _DRouteData
-{
-  DBusConnection *bus;
-  GSList *interfaces;
-  char (*introspect_children)(const char *, GString *, void *);
-  void *user_data;
-};
+typedef struct _DRoutePath    DRoutePath;
+
+/*---------------------------------------------------------------------------*/
+
+DRouteContext *
+droute_new      (DBusConnection *bus,
+                 const char *introspect_dir);
+void
+droute_free     (DRouteContext *cnx);
+
+DRoutePath *
+droute_add_one  (DRouteContext *cnx,
+                 const char    *path,
+                 const void    *data);
 
-DBusHandlerResult droute_message(DBusConnection *bus, DBusMessage *message, void *user_data);
+DRoutePath *
+droute_add_many (DRouteContext *cnx,
+                 const char    *path,
+                 const void    *data,
+                 const DRouteGetDatumFunction get_datum);
 
-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);
+void
+droute_path_add_interface (DRoutePath *path,
+                           const char *name,
+                           const DRouteMethod   *methods,
+                           const DRouteProperty *properties);
 
-dbus_bool_t droute_add_interface(DRouteData *data, const char *name, DRouteMethod *methods, DRouteProperty *properties, DRouteGetDatumFunction get_datum, DRouteFreeDatumFunction free_datum);
-#endif /* _DROUTE_H */
+#endif /* _DROUTE_H */
diff --git a/droute/introspect-loader.c b/droute/introspect-loader.c
deleted file mode 100644 (file)
index 723d3d6..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * AT-SPI - Assistive Technology Service Provider Interface
- * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
- *
- * Copyright 2008 Codethink Ltd.
- *
- * 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 <glib.h>
-
-/*
- * This file contains utilities for loading introspection XML
- * from the local file system.
- *
- * There is an installation directory with files containing introspection xml.
- * Each file is named after the interface it describes.
- */
-
-/*
- * Provides the path for the introspection directory.
- */
-#if !defined ATSPI_INTROSPECTION_PATH
-    #error "No introspection XML directory defined"
-#endif
-
-const char *spi_introspection_header =
-"<?xml version=\"1.0\"?>\n";
-
-const char *spi_introspection_node_element =
-"<node name=\"%s\">\n";
-
-const char *spi_introspection_footer =
-"</node>";
-
-void
-spi_append_interface (GString *str, const char *interface)
-{
-  char *filename;
-  char *contents;
-  char *introspection_directory;
-  gsize len;
-
-  GError *err = NULL;
-
-  introspection_directory = (char *) g_getenv("ATSPI_INTROSPECTION_PATH");
-  if (introspection_directory == NULL)
-      introspection_directory = ATSPI_INTROSPECTION_PATH;
-
-  filename = g_build_filename(introspection_directory, interface, NULL);
-
-  if (g_file_get_contents(filename, &contents, &len, &err))
-    {
-      g_string_append_len(str, contents, len);
-    }
-  else
-    {
-      g_warning("AT-SPI: Cannot find introspection XML file %s - %s",
-               filename, err->message);
-      g_error_free(err);
-    }
-
-  g_string_append(str, "\n");
-  g_free(filename);
-  g_free(contents);
-}