Backport changes from EFL
authorLucas De Marchi <lucas.demarchi@profusion.mobi>
Fri, 26 Apr 2013 16:05:06 +0000 (13:05 -0300)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Fri, 26 Apr 2013 16:05:06 +0000 (13:05 -0300)
There were lots of changes in eldbus inside EFL. This commit imports all
of them by simply copying the headers and source files over the old
ones. This is the lazy way to do but there were way too many missing
commits, including renames and cleanups.

Docs are probably broken - NOT TESTED. Use the EFL version if you are
interested in the documentation.

21 files changed:
configure.ac
src/lib/Eldbus.h
src/lib/eldbus_connection.h
src/lib/eldbus_core.c
src/lib/eldbus_freedesktop.c
src/lib/eldbus_freedesktop.h
src/lib/eldbus_message.c
src/lib/eldbus_message.h
src/lib/eldbus_message_to_eina_value.c
src/lib/eldbus_object.c
src/lib/eldbus_object.h
src/lib/eldbus_pending.c
src/lib/eldbus_pending.h
src/lib/eldbus_private.h
src/lib/eldbus_private_types.h
src/lib/eldbus_proxy.c
src/lib/eldbus_proxy.h
src/lib/eldbus_service.c
src/lib/eldbus_service.h
src/lib/eldbus_signal_handler.c
src/lib/eldbus_signal_handler.h

index 1cfaca9..c4fd1c7 100644 (file)
@@ -1,10 +1,12 @@
 EFL_VERSION([1], [7], [99], [dev])
 AC_INIT([eldbus], [efl_ver], [enlightenment-devel@lists.sourceforge.net])
+
 AC_PREREQ([2.60])
+AC_CONFIG_SRCDIR([configure.ac])
+AC_CONFIG_MACRO_DIR([m4])
 
+AC_CONFIG_HEADERS([config.h])
 AM_INIT_AUTOMAKE([foreign subdir-objects])
-AC_CONFIG_HEADER([config.h])
-AC_CONFIG_MACRO_DIR([m4])
 
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 
@@ -44,8 +46,6 @@ AC_LANG_C
 AC_PROG_CC
 AC_PROG_MKDIR_P
 AM_PROG_CC_C_O
-AC_C___ATTRIBUTE__
-AC_C_VA_LIST_AS_ARRAY
 
 AC_DISABLE_STATIC
 define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl
index 1e5ce65..e49061d 100644 (file)
@@ -1,14 +1,23 @@
 /**
- * @mainpage Eldbus
+ * @page eldbus_main Eldbus
  *
- * @section eldbus_intro_sec Introduction
+ * @date 2012 (created)
+ *
+ * @section toc Table of Contents
+ *
+ * @li @ref eldbus_main_intro
+ * @li @ref eldbus_main_compiling
+ * @li @ref eldbus_main_next_steps
+ * @li @ref eldbus_main_intro_example
+ *
+ * @section eldbus_main_intro Introduction
  *
  * Eldbus is a wrapper around the
  * <a href="http://www.freedesktop.org/wiki/Software/dbus">dbus</a>
  * library, which is a message bus system. It also implements a set of
  * specifications using dbus as interprocess communication.
  *
- * @section eldbus_modules_sec Modules
+ * @subsection eldbus_modules_sec Modules
  *
  * <ul>
  * <li> @ref Eldbus_Core
  * <li> @ref Eldbus_Basic
  * </ul>
  *
- * @section eldbus_examples_sec Examples
+ * @section eldbus_main_compiling How to compile
+ *
+ * Eldbus is a library your application links to. The procedure for this is
+ * very simple. You simply have to compile your application with the
+ * appropriate compiler flags that the @c pkg-config script outputs. For
+ * example:
+ *
+ * Compiling C or C++ files into object files:
+ *
+ * @verbatim
+   gcc -c -o main.o main.c `pkg-config --cflags eldbus`
+   @endverbatim
+ *
+ * Linking object files into a binary executable:
+ *
+ * @verbatim
+   gcc -o my_application main.o `pkg-config --libs eldbus`
+   @endverbatim
+ *
+ * See @ref pkgconfig
+ *
+ * @section eldbus_main_next_steps Next Steps
+ *
+ * After you understood what Eldbus is and installed it in your system
+ * you should proceed understanding the programming interface.
+ *
+ * Recommended reading:
+ * @li @ref Eldbus_Core for library init, shutdown and getting a connection.
+ * @li @ref Eldbus_Proxy to easily bind a client object to an interface.
+ * @li @ref Eldbus_Object_Mapper to monitor server objects and properties.
  *
- * Here some Eldbus examples:
+ * @section eldbus_main_intro_example Introductory Example
  *
- * @li @ref banshee
- * @li @ref simple_dbus_client
- * @li @ref simple_dbus_server
- * @li @ref complex_types
- * @li @ref complex_types_server
- * @li @ref eina_value
- * @li @ref signal_emmiter
- * @li @ref connman
- * @li @ref ofono
+ * @include ofono-dial.c
  *
- * @author Gustavo Sverzut Barbieri <barbieri@profusion.mobi>
- * @author José Roberto de Souza <zehortigoza@profusion.mobi>
- * @author Leandro Pereira <leandro@profusion.mobi>
- * @author Lucas De Marchi <lucas.demarchi@profusion.mobi>
+ * More examples can be found at @ref eldbus_examples.
  */
 #ifndef ELDBUS_H
 #define ELDBUS_H
@@ -84,11 +111,12 @@ extern "C" {
 
 /**
  * @defgroup Eldbus_Core Core
+ * @ingroup Eldbus
  *
  * @{
  */
 #define ELDBUS_VERSION_MAJOR 1
-#define ELDBUS_VERSION_MINOR 6
+#define ELDBUS_VERSION_MINOR 8
 
 #define ELDBUS_FDO_BUS "org.freedesktop.DBus"
 #define ELDBUS_FDO_PATH "/org/freedesktop/DBus"
@@ -97,6 +125,7 @@ extern "C" {
 #define ELDBUS_FDO_INTERFACE_OBJECT_MANAGER "org.freedesktop.DBus.ObjectManager"
 #define ELDBUS_FDO_INTERFACE_INTROSPECTABLE "org.freedesktop.DBus.Introspectable"
 #define ELDBUS_FDO_INTEFACE_PEER "org.freedesktop.DBus.Peer"
+#define ELDBUS_ERROR_PENDING_CANCELED "org.enlightenment.DBus.Canceled"
 
 typedef struct _Eldbus_Version
 {
index 93d8243..8fd8136 100644 (file)
@@ -3,6 +3,7 @@
 
 /**
  * @defgroup Eldbus_Conneciton Connection
+ * @ingroup Eldbus
  *
  * @{
  */
index b6b726a..c2b3b57 100644 (file)
@@ -1,8 +1,9 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include "eldbus_private.h"
 #include "eldbus_private_types.h"
-#include <dbus/dbus.h>
-
-#include <Ecore.h>
 
 #define ELDBUS_CONNECTION_CHECK(conn)                        \
   do                                                        \
@@ -73,7 +74,9 @@ EAPI const Eldbus_Version * eldbus_version = &_version;
 static int _eldbus_init_count = 0;
 int _eldbus_log_dom = -1;
 
-static Eldbus_Connection *shared_connections[3];
+/* We don't save ELDBUS_CONNECTION_TYPE_UNKNOWN in here so we need room for 
+ * last - 1 elements */
+static Eldbus_Connection *shared_connections[ELDBUS_CONNECTION_TYPE_LAST - 1];
 
 static void _eldbus_connection_event_callback_call(Eldbus_Connection *conn, Eldbus_Connection_Event_Type type, const void *event_info);
 static void _eldbus_connection_context_event_cb_del(Eldbus_Connection_Context_Event *ce, Eldbus_Connection_Context_Event_Cb *ctx);
@@ -381,14 +384,14 @@ eldbus_connection_name_gc(Eldbus_Connection *conn, Eldbus_Connection_Name *cn)
 
    eina_hash_del(conn->names, cn->name, cn);
    if (cn->name_owner_changed)
-     {
-        cn->name_owner_changed->bus = NULL;
-        eldbus_signal_handler_del(cn->name_owner_changed);
-     }
+     eldbus_signal_handler_del(cn->name_owner_changed);
    if (cn->objects)
      eina_hash_free(cn->objects);
    eina_stringshare_del(cn->name);
-   eina_stringshare_del(cn->unique_id);
+   if (cn->name_owner_get)
+     eldbus_pending_cancel(cn->name_owner_get);
+   if (cn->unique_id)
+     eina_stringshare_del(cn->unique_id);
    eina_list_free(cn->event_handlers.to_delete);
    free(cn);
 }
@@ -433,13 +436,19 @@ on_name_owner_changed(void *data, const Eldbus_Message *msg)
 }
 
 static void
-on_get_name_owner(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
+on_get_name_owner(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
 {
-   const char *unique_id = "";
+   const char *unique_id = "", *error_name;
    Eldbus_Connection_Name *cn = data;
 
-   if (eldbus_message_error_get(msg, NULL, NULL))
-     DBG("GetNameOwner returned an error");
+   cn->name_owner_get = NULL;
+
+   if (eldbus_message_error_get(msg, &error_name, NULL))
+     {
+        if (!strcmp(error_name, ELDBUS_ERROR_PENDING_CANCELED))
+          return;
+        DBG("GetNameOwner of bus = %s returned an error", cn->name);
+     }
    else if (!eldbus_message_arguments_get(msg, "s", &unique_id))
      ERR("Error getting arguments from GetNameOwner");
 
@@ -487,7 +496,7 @@ eldbus_connection_name_get(Eldbus_Connection *conn, const char *name)
    if (name[0] == ':')
      cn->unique_id = eina_stringshare_add(name);
    else
-     eldbus_name_owner_get(conn, cn->name, on_get_name_owner, cn);
+     cn->name_owner_get = eldbus_name_owner_get(conn, cn->name, on_get_name_owner, cn);
 
    cn->name_owner_changed = _eldbus_signal_handler_add(conn, ELDBUS_FDO_BUS,
                                                       ELDBUS_FDO_PATH,
@@ -608,7 +617,7 @@ cb_watch_add(DBusWatch *watch, void *data)
 }
 
 static void
-cb_watch_del(DBusWatch *watch, void *data)
+cb_watch_del(DBusWatch *watch, void *data EINA_UNUSED)
 {
    DBG("cb_watch_del");
    /* will trigger eldbus_handler_data_free() */
@@ -616,7 +625,7 @@ cb_watch_del(DBusWatch *watch, void *data)
 }
 
 static void
-cb_watch_toggle(DBusWatch *watch, void *data)
+cb_watch_toggle(DBusWatch *watch, void *data EINA_UNUSED)
 {
    Eldbus_Handler_Data *hd;
    hd = dbus_watch_get_data(watch);
@@ -683,7 +692,7 @@ cb_timeout_add(DBusTimeout *timeout, void *data)
 }
 
 static void
-cb_timeout_del(DBusTimeout *timeout, void *data)
+cb_timeout_del(DBusTimeout *timeout, void *data EINA_UNUSED)
 {
    DBG("timeout del!");
    /* will trigger eldbus_timeout_data_free() */
@@ -691,7 +700,7 @@ cb_timeout_del(DBusTimeout *timeout, void *data)
 }
 
 static void
-cb_timeout_toggle(DBusTimeout *timeout, void *data)
+cb_timeout_toggle(DBusTimeout *timeout, void *data EINA_UNUSED)
 {
    Eldbus_Timeout_Data *td;
 
@@ -740,7 +749,7 @@ eldbus_idler(void *data)
 }
 
 static void
-cb_dispatch_status(DBusConnection *dbus_conn, DBusDispatchStatus new_status, void *data)
+cb_dispatch_status(DBusConnection *dbus_conn EINA_UNUSED, DBusDispatchStatus new_status, void *data)
 {
    Eldbus_Connection *conn = data;
 
@@ -762,16 +771,41 @@ cb_dispatch_status(DBusConnection *dbus_conn, DBusDispatchStatus new_status, voi
      }
 }
 
+static inline Eina_Bool
+extra_arguments_check(DBusMessage *msg, Eldbus_Signal_Handler *sh)
+{
+   DBusMessageIter iter;
+   Signal_Argument *arg;
+   unsigned int arg_index = 0;
+
+   dbus_message_iter_init(msg, &iter);
+   EINA_INLIST_FOREACH(sh->args, arg)
+     {
+        const char *arg_msg;
+        int type = 0;
+
+        while((arg->index > arg_index) && dbus_message_iter_next(&iter))
+          arg_index++;
+
+        if (arg_index != arg->index)
+          return EINA_FALSE;
+
+        type = dbus_message_iter_get_arg_type(&iter);
+        if (!(type == 's' || type == 'o'))
+          return EINA_FALSE;
+
+        dbus_message_iter_get_basic(&iter, &arg_msg);
+        if (strcmp(arg_msg, arg->value))
+          return EINA_FALSE;
+     }
+   return EINA_TRUE;
+}
+
 static void
 cb_signal_dispatcher(Eldbus_Connection *conn, DBusMessage *msg)
 {
-   Eldbus_Signal_Handler *sh;
-   DBusMessageIter iter;
-   int type, counter;
-   char *arg_msg;
    Eldbus_Message *eldbus_msg;
-   Signal_Argument *arg;
-   Eina_Inlist *safe_list;
+   Eina_Inlist *next;
 
    eldbus_msg = eldbus_message_new(EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN(eldbus_msg);
@@ -781,9 +815,20 @@ cb_signal_dispatcher(Eldbus_Connection *conn, DBusMessage *msg)
                           &eldbus_msg->iterator->dbus_iterator);
 
    eldbus_connection_ref(conn);
-   EINA_INLIST_FOREACH(conn->signal_handlers, sh)
+   eldbus_init();
+   /*
+    * Do the walking open-coded so we don't crash if a callback
+    * removes other signal handlers from the list and we don't own
+    * yet a reference to them.
+    */
+   next = conn->signal_handlers;
+   while (next != NULL)
      {
-        sh->refcount++;
+        Eldbus_Signal_Handler *sh;
+
+        sh = EINA_INLIST_CONTAINER_GET(next, Eldbus_Signal_Handler);
+        next = next->next;
+
         if (sh->dangling) continue;
         if (sh->sender)
           {
@@ -795,47 +840,33 @@ cb_signal_dispatcher(Eldbus_Connection *conn, DBusMessage *msg)
                     continue;
                }
              else
-                if (!dbus_message_has_sender(msg, sh->sender)) continue;
+               if (!dbus_message_has_sender(msg, sh->sender)) continue;
           }
         if (sh->path && !dbus_message_has_path(msg, sh->path)) continue;
         if (sh->member && !dbus_message_has_member(msg, sh->member)) continue;
+        if (!extra_arguments_check(msg, sh)) continue;
 
-        dbus_message_iter_init(msg, &iter);
-        counter = 0;
-        EINA_INLIST_FOREACH(sh->args, arg)
-          {
-             type = dbus_message_iter_get_arg_type(&iter);
-             if (counter != arg->index || !(type == 's' || type == 'o'))
-               goto next_sh;
-
-             dbus_message_iter_get_basic(&iter, &arg_msg);
-             if (strcmp(arg_msg, arg->value))
-               goto next_sh;
-
-             dbus_message_iter_next(&iter);
-             counter++;
-          }
+        eldbus_signal_handler_ref(sh);
         sh->cb((void *)sh->cb_data, eldbus_msg);
+        /* update next signal handler because the list may have changed */
+        next = EINA_INLIST_GET(sh)->next;
+        eldbus_signal_handler_unref(sh);
+
         /*
          * Rewind iterator so another signal handler matching the same signal
          * can iterate over it.
          */
         dbus_message_iter_init(eldbus_msg->dbus_msg,
                                &eldbus_msg->iterator->dbus_iterator);
-
-next_sh:
-        type = 0;
      }
 
-   EINA_INLIST_FOREACH_SAFE(conn->signal_handlers, safe_list, sh)
-     eldbus_signal_handler_unref(sh);
-
    eldbus_message_unref(eldbus_msg);
    eldbus_connection_unref(conn);
+   eldbus_shutdown();
 }
 
 static DBusHandlerResult
-eldbus_filter(DBusConnection *conn_dbus, DBusMessage *message, void *user_data)
+eldbus_filter(DBusConnection *conn_dbus EINA_UNUSED, DBusMessage *message, void *user_data)
 {
    Eldbus_Connection *conn = user_data;
 
@@ -901,7 +932,7 @@ eldbus_connection_setup(Eldbus_Connection *conn)
 }
 
 static void
-_disconnected(void *data, const Eldbus_Message *msg)
+_disconnected(void *data, const Eldbus_Message *msg EINA_UNUSED)
 {
    Eldbus_Connection *conn = data;
    _eldbus_connection_event_callback_call(
@@ -957,6 +988,10 @@ eldbus_connection_get(Eldbus_Connection_Type type)
    Eldbus_Connection *conn;
 
    DBG("Getting connection with type %d", type);
+
+   if (!type)
+     return NULL;
+
    conn = shared_connections[type - 1];
    if (conn)
      {
@@ -993,6 +1028,7 @@ _eldbus_connection_unref(Eldbus_Connection *conn)
    Eina_Iterator *iter;
    Eldbus_Connection_Name *cn;
    Eina_Array *cns;
+   const char *name;
 
    DBG("Connection %p: unref (currently at %d refs)",
        conn, conn->refcount);
@@ -1023,12 +1059,16 @@ _eldbus_connection_unref(Eldbus_Connection *conn)
                                                           cn->event_handlers.list);
              free(ctx);
           }
-        eina_array_push(cns, cn);
+        eina_array_push(cns, eina_stringshare_add(cn->name));
      }
    eina_iterator_free(iter);
 
-   while ((cn = eina_array_pop(cns)))
-     eldbus_connection_name_gc(conn, cn);
+   while ((name = eina_array_pop(cns)))
+     {
+        cn = eina_hash_find(conn->names, name);
+        if (cn) eldbus_connection_name_gc(conn, cn);
+        eina_stringshare_del(name);
+     }
 
    eina_hash_free(conn->names);
    eina_array_free(cns);
@@ -1085,7 +1125,7 @@ _eldbus_connection_unref(Eldbus_Connection *conn)
    eldbus_data_del_all(&conn->data);
 
    if (conn->idler) ecore_idler_del(conn->idler);
-   if (shared_connections[conn->type - 1] == conn)
+   if (conn->type && (shared_connections[conn->type - 1] == conn))
      shared_connections[conn->type - 1] = NULL;
 
    free(conn);
@@ -1154,6 +1194,13 @@ eldbus_dispatch_name_owner_change(Eldbus_Connection_Name *cn, const char *old_id
         ctx->cb((void *)ctx->cb_data, cn->name, previous_id, cn->unique_id);
      }
    cn->event_handlers.walking--;
+   EINA_LIST_FREE(cn->event_handlers.to_delete, ctx)
+     {
+        cn->event_handlers.list = eina_inlist_remove(cn->event_handlers.list,
+                                                     EINA_INLIST_GET(ctx));
+        free(ctx);
+     }
+   eldbus_connection_name_gc(cn->name_owner_changed->conn, cn);
 }
 
 typedef struct _dispach_name_owner_data
@@ -1250,6 +1297,7 @@ eldbus_name_owner_changed_callback_del(Eldbus_Connection *conn, const char *bus,
         free(data);
      }
    free(found);
+   eldbus_connection_name_gc(conn, cn);
 }
 
 EAPI void
index 294573c..e9b4dfd 100644 (file)
@@ -74,7 +74,9 @@ EAPI Eldbus_Pending *
 eldbus_object_managed_objects_get(Eldbus_Object *obj, Eldbus_Message_Cb cb, const void *data)
 {
    Eldbus_Message *msg;
+   Eldbus_Pending *p;
    msg = eldbus_object_method_call_new(obj, ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
                                       "GetManagedObjects");
-   return eldbus_object_send(obj, msg, cb, data, -1);
+   p = eldbus_object_send(obj, msg, cb, data, -1);
+   return p;
 }
index b43dc80..e3903ef 100644 (file)
@@ -2,7 +2,8 @@
 #define ELDBUS_FREEDESKTOP_H 1
 
 /**
- * @defgroup Eldbus_Basic Basic Methods
+ * @defgroup Eldbus_Basic Basic FreeDesktop.Org Methods
+ * @ingroup Eldbus
  *
  * @{
  */
index b1d1a55..85fbe56 100644 (file)
@@ -273,8 +273,8 @@ eldbus_message_arguments_vget(const Eldbus_Message *msg, const char *signature,
    return _eldbus_message_arguments_vget((Eldbus_Message *)msg, signature, ap);
 }
 
-EAPI Eina_Bool
-eldbus_message_iter_arguments_vappend(Eldbus_Message_Iter *iter, const char *signature, va_list ap)
+static Eina_Bool
+_eldbus_message_iter_arguments_vappend(Eldbus_Message_Iter *iter, const char *signature, va_list *aq)
 {
    DBusSignatureIter signature_iter;
    Eina_Bool r = EINA_TRUE;
@@ -288,14 +288,13 @@ eldbus_message_iter_arguments_vappend(Eldbus_Message_Iter *iter, const char *sig
    while ((type = dbus_signature_iter_get_signature(&signature_iter)))
      {
         if (type[0] != DBUS_TYPE_VARIANT && !type[1])
-          r = append_basic(type[0], MAKE_PTR_FROM_VA_LIST(ap),
-                           &iter->dbus_iterator);
+          r = append_basic(type[0], aq, &iter->dbus_iterator);
         else
           {
              Eldbus_Message_Iter **user_itr;
              Eldbus_Message_Iter *sub;
 
-             user_itr = va_arg(ap, Eldbus_Message_Iter **);
+             user_itr = va_arg(*aq, Eldbus_Message_Iter **);
              sub = _message_iterator_new(EINA_TRUE);
              if (!sub)
                {
@@ -340,6 +339,20 @@ next:
      }
 
    return r;
+
+}
+
+EAPI Eina_Bool
+eldbus_message_iter_arguments_vappend(Eldbus_Message_Iter *iter, const char *signature, va_list ap)
+{
+   va_list aq;
+   Eina_Bool ret;
+
+   va_copy(aq, ap);
+   ret = _eldbus_message_iter_arguments_vappend(iter, signature, &aq);
+   va_end(aq);
+
+   return ret;
 }
 
 EAPI Eina_Bool
@@ -422,7 +435,7 @@ append_basic(char type, va_list *vl, DBusMessageIter *iter)
 }
 
 static Eina_Bool
-_eldbus_message_arguments_vappend(Eldbus_Message *msg, const char *signature, va_list ap)
+_eldbus_message_arguments_vappend(Eldbus_Message *msg, const char *signature, va_list *aq)
 {
    DBusSignatureIter signature_iter;
    Eldbus_Message_Iter *iter;
@@ -440,8 +453,7 @@ _eldbus_message_arguments_vappend(Eldbus_Message *msg, const char *signature, va
    while ((type = dbus_signature_iter_get_current_type(&signature_iter)))
      {
         if (dbus_type_is_basic(type))
-          r = append_basic(type, MAKE_PTR_FROM_VA_LIST(ap),
-                           &iter->dbus_iterator);
+          r = append_basic(type, aq, &iter->dbus_iterator);
         else
           {
              ERR("sig = %s | eldbus_message_arguments_append() and \
@@ -468,7 +480,7 @@ eldbus_message_arguments_append(Eldbus_Message *msg, const char *signature, ...)
    EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EINA_FALSE);
 
    va_start(ap, signature);
-   ret = _eldbus_message_arguments_vappend(msg, signature, ap);
+   ret = _eldbus_message_arguments_vappend(msg, signature, &ap);
    va_end(ap);
    return ret;
 }
@@ -476,9 +488,17 @@ eldbus_message_arguments_append(Eldbus_Message *msg, const char *signature, ...)
 EAPI Eina_Bool
 eldbus_message_arguments_vappend(Eldbus_Message *msg, const char *signature, va_list ap)
 {
+   va_list aq;
+   Eina_Bool ret;
+
    ELDBUS_MESSAGE_CHECK_RETVAL(msg, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EINA_FALSE);
-   return _eldbus_message_arguments_vappend(msg, signature, ap);
+
+   va_copy(aq, ap);
+   ret = _eldbus_message_arguments_vappend(msg, signature, &aq);
+   va_end(aq);
+
+   return ret;
 }
 
 EAPI Eldbus_Message_Iter *
@@ -701,21 +721,8 @@ eldbus_message_iter_get_and_next(Eldbus_Message_Iter *iter, char signature, ...)
    return EINA_TRUE;
 }
 
-EAPI Eina_Bool
-eldbus_message_iter_arguments_get(Eldbus_Message_Iter *iter, const char *signature, ...)
-{
-   va_list ap;
-   Eina_Bool ret;
-
-   va_start(ap, signature);
-   ret = eldbus_message_iter_arguments_vget(iter, signature, ap);
-   va_end(ap);
-
-   return ret;
-}
-
-EAPI Eina_Bool
-eldbus_message_iter_arguments_vget(Eldbus_Message_Iter *iter, const char *signature, va_list ap)
+static Eina_Bool
+_eldbus_message_iter_arguments_vget(Eldbus_Message_Iter *iter, const char *signature, va_list *aq)
 {
    int iter_type;
    DBusSignatureIter sig_iter;
@@ -739,10 +746,10 @@ eldbus_message_iter_arguments_vget(Eldbus_Message_Iter *iter, const char *signat
           }
 
         if (dbus_type_is_basic(iter_type))
-          get_basic(iter_type, &iter->dbus_iterator, MAKE_PTR_FROM_VA_LIST(ap));
+          get_basic(iter_type, &iter->dbus_iterator, aq);
         else
           {
-             Eldbus_Message_Iter **user_itr = va_arg(ap, Eldbus_Message_Iter **);
+             Eldbus_Message_Iter **user_itr = va_arg(*aq, Eldbus_Message_Iter **);
              Eldbus_Message_Iter *sub_itr;
 
              sub_itr = _message_iterator_new(EINA_FALSE);
@@ -760,6 +767,33 @@ eldbus_message_iter_arguments_vget(Eldbus_Message_Iter *iter, const char *signat
      }
 
    return dbus_signature_iter_get_current_type(&sig_iter) == DBUS_TYPE_INVALID;
+
+}
+
+EAPI Eina_Bool
+eldbus_message_iter_arguments_get(Eldbus_Message_Iter *iter, const char *signature, ...)
+{
+   va_list ap;
+   Eina_Bool ret;
+
+   va_start(ap, signature);
+   ret = _eldbus_message_iter_arguments_vget(iter, signature, &ap);
+   va_end(ap);
+
+   return ret;
+}
+
+EAPI Eina_Bool
+eldbus_message_iter_arguments_vget(Eldbus_Message_Iter *iter, const char *signature, va_list ap)
+{
+   va_list aq;
+   Eina_Bool ret;
+
+   va_copy(aq, ap);
+   ret = _eldbus_message_iter_arguments_vget(iter, signature, &aq);
+   va_end(aq);
+
+   return ret;
 }
 
 EAPI void
@@ -769,9 +803,6 @@ eldbus_message_iter_del(Eldbus_Message_Iter *iter)
    _message_iterator_free(iter);
 }
 
-/* TODO: proper doc
- * Return the *reply* to @msg, i.e. @msg is the message we are replying to.
- */
 EAPI Eldbus_Message *
 eldbus_message_error_new(const Eldbus_Message *msg, const char *error_name, const char *error_msg)
 {
index 7f0610d..4c174cb 100644 (file)
@@ -3,30 +3,21 @@
 
 /**
  * @defgroup Eldbus_Message Message
+ * @ingroup Eldbus
  *
  * @{
  */
 
 /**
- * @brief Constructs a new message to invoke a method on a remote object.
- *
- * @param dest bus name or unique id of the remote applications
- * @param path object path
- * @param iface interface name
- * @param method name of method that will be called
- *
- * @return a new Eldbus_Message, free with eldbus_message_unref()
- */
-EAPI Eldbus_Message        *eldbus_message_method_call_new(const char *dest, const char *path, const char *iface, const char *method) EINA_ARG_NONNULL(1, 2, 3, 4) EINA_WARN_UNUSED_RESULT EINA_MALLOC;
-
-/**
  * @brief Increase message reference.
  */
 EAPI Eldbus_Message        *eldbus_message_ref(Eldbus_Message *msg) EINA_ARG_NONNULL(1);
 
 /**
  * @brief Decrease message reference.
- * If reference == 0 message will be freed and all its children.
+ *
+ * When refcount reaches zero the message and all its resources will be
+ * freed.
  */
 EAPI void                  eldbus_message_unref(Eldbus_Message *msg) EINA_ARG_NONNULL(1);
 
@@ -38,18 +29,30 @@ EAPI const char           *eldbus_message_sender_get(const Eldbus_Message *msg)
 EAPI const char           *eldbus_message_signature_get(const Eldbus_Message *msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
 
 /**
- * @brief Creates a new message that is an error reply to another message.
+ * @brief Create a new message to invoke a method on a remote object.
  *
- * @param reply the message we're replying to
+ * @param dest bus name or unique id of the remote application
+ * @param path object path
+ * @param iface interface name
+ * @param method name of the method to be called
+ *
+ * @return a new Eldbus_Message, free with eldbus_message_unref()
+ */
+EAPI Eldbus_Message        *eldbus_message_method_call_new(const char *dest, const char *path, const char *iface, const char *method) EINA_ARG_NONNULL(1, 2, 3, 4) EINA_WARN_UNUSED_RESULT EINA_MALLOC;
+
+/**
+ * @brief Create a new message that is an error reply to another message.
+ *
+ * @param msg the message we're replying to
  * @param error_name the error name
  * @param error_msg the error message string
  *
- * @return new Eldbus_Message, free with eldbus_message_unref()
+ * @return new Eldbus_Message, free with eldbus_message_unref()
  */
-EAPI Eldbus_Message        *eldbus_message_error_new(const Eldbus_Message *reply, const char *error_name, const char *error_msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+EAPI Eldbus_Message        *eldbus_message_error_new(const Eldbus_Message *msg, const char *error_name, const char *error_msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
 
 /**
- * @brief Constructs a message that is a reply to a method call.
+ * @brief Create a message that is a reply to a method call.
  *
  * @param msg the message we're replying to
  *
@@ -59,38 +62,80 @@ EAPI Eldbus_Message        *eldbus_message_method_return_new(const Eldbus_Messag
 
 
 /**
- * @brief If Eldbus_Message is a message error return EINA_TRUE and fills
- * name and text if their pointers is not null.
+ * @brief Get the error text and name from a Eldbus_Message.
+ *
+ * If @param msg is an error message return EINA_TRUE and fill in the name and
+ * text of the error.
+ *
+ * @param msg The message containing the error
+ * @param name Variable in which to store the error name or @c NULL if it's not
+ * desired.
+ * @param text Variable in which to store the error text or @c NULL if it's not
+ * desired.
  */
 EAPI Eina_Bool             eldbus_message_error_get(const Eldbus_Message *msg, const char **name, const char **text) EINA_ARG_NONNULL(1);
 
 /**
- * @brief Get data from Eldbus_Message. For each complete type we must have
- * a pointer to store its value. In case of complex type Eldbus_Message_Iter
- * needs to be used.
+ * @brief Get the arguments from an Eldbus_Message
+ *
+ * Get the arguments of an Eldbus_Message storing them in the locations pointed
+ * to by the pointer arguments that follow @param signature. Each pointer
+ * argument must be of a type that is appropriate for the correspondent complete
+ * type in @param signature. For complex types such as arrays, structs,
+ * dictionaries or variants, a pointer to Eldbus_Message_Iter* must be provided.
+ *
+ * @param msg The message to get the arguments from.
+ * @param signature The signature of the arguments user is expecting to read
+ * from @param msg
+ * @param ... The pointers in which to store the message arguments
+ *
+ * @return EINA_TRUE if the arguments were read succesfully and stored in the
+ * respective pointer arguments.
  */
 EAPI Eina_Bool             eldbus_message_arguments_get(const Eldbus_Message *msg, const char *signature, ...) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
 
 /**
- * @brief Get data from Eldbus_Message. For each complete type we must have
- * a pointer to store its value, in case of complex type
- * Eldbus_Message_Iter needs to be used.
+ * @brief Get the arguments from an Eldbus_Message using a va_list.
+ *
+ * @param msg The message to get the arguments from.
+ * @param signature The signature user is expecting to read from @param msg.
+ * @param ap The va_list containing the pointer arguments.
+ *
+ * @see eldbus_message_arguments_get()
+ *
+ * @return EINA_TRUE if the arguments were read succesfully and stored in the
+ * respective pointer arguments.
  */
 EAPI Eina_Bool             eldbus_message_arguments_vget(const Eldbus_Message *msg, const char *signature, va_list ap) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
 
 /**
- * @brief Set data to Eldbus_Message.
+ * @brief Append arguments into an Eldbus_Message
+ *
+ * Append arguments into an Eldbus_Message according to the @param signature
+ * provided. For each complete type in @param signature, a value of the
+ * corresponding type must be provided.
  *
- * This function only supports basic type, for complex types use
- * eldbus_message_iter_* functions.
+ * This function supports only basic types. For complex types use
+ * eldbus_message_iter_* family of functions.
+ *
+ * @param msg The message in which arguments are being appended.
+ * @param signature Signature of the arguments that are being appended.
+ * @param ... Values of each argument to append in @param msg.
+ *
+ * @return EINA_TRUE on success, EINA_FALSE otherwise.
  */
 EAPI Eina_Bool             eldbus_message_arguments_append(Eldbus_Message *msg, const char *signature, ...) EINA_ARG_NONNULL(1, 2);
 
 /**
- * @brief Set data to Eldbus_Message.
+ * @brief Append arguments into an Eldbus_Message using a va_list.
+ *
+ * @param msg The message in which arguments are being appended.
+ * @param signature Signature of the arguments that are being appended.
+ * @param ap The va_list containing the arguments to append.
+ *
+ * @see eldbus_message_arguments_append().
  *
- * This function only supports basic types, for complex types use
- * eldbus_message_iter_* functions.
+ * @return EINA_TRUE on success, EINA_FALSE otherwise.
  */
 EAPI Eina_Bool             eldbus_message_arguments_vappend(Eldbus_Message *msg, const char *signature, va_list ap) EINA_ARG_NONNULL(1, 2);
 
index 562d8a7..3f90266 100644 (file)
@@ -213,7 +213,7 @@ _message_iter_basic_array_to_eina_value(char type, Eina_Value *value, Eldbus_Mes
     }
 }
 
-#define ARG "arg%d"
+#define ARG "arg%u"
 
 typedef struct _Eldbus_Struct_Desc
 {
@@ -222,7 +222,7 @@ typedef struct _Eldbus_Struct_Desc
 } Eldbus_Struct_Desc;
 
 static void *
-_ops_malloc(const Eina_Value_Struct_Operations *ops, const Eina_Value_Struct_Desc *desc)
+_ops_malloc(const Eina_Value_Struct_Operations *ops EINA_UNUSED, const Eina_Value_Struct_Desc *desc)
 {
    Eldbus_Struct_Desc *edesc = (Eldbus_Struct_Desc*)desc;
    edesc->refcount++;
@@ -231,7 +231,7 @@ _ops_malloc(const Eina_Value_Struct_Operations *ops, const Eina_Value_Struct_Des
 }
 
 static void
-_ops_free(const Eina_Value_Struct_Operations *ops, const Eina_Value_Struct_Desc *desc, void *memory)
+_ops_free(const Eina_Value_Struct_Operations *ops EINA_UNUSED, const Eina_Value_Struct_Desc *desc, void *memory)
 {
    Eldbus_Struct_Desc *edesc = (Eldbus_Struct_Desc*) desc;
    edesc->refcount--;
@@ -282,7 +282,7 @@ _message_iter_struct_to_eina_value(Eldbus_Message_Iter *iter)
         Eina_Value *v;
 
         m = calloc(1, sizeof(Eina_Value_Struct_Member));
-        sprintf(name, ARG, z);
+        snprintf(name, 7, ARG, z);
         m->name = strdup(name);
         offset = _type_offset(type, offset);
         m->offset = offset;
index eb37f4c..9b75175 100644 (file)
@@ -176,7 +176,7 @@ _eldbus_object_free(Eldbus_Object *obj)
 }
 
 static void
-_on_connection_free(void *data, const void *dead_pointer)
+_on_connection_free(void *data, const void *dead_pointer EINA_UNUSED)
 {
    Eldbus_Object *obj = data;
    ELDBUS_OBJECT_CHECK(obj);
@@ -644,27 +644,33 @@ EAPI Eldbus_Pending *
 eldbus_object_peer_ping(Eldbus_Object *obj, Eldbus_Message_Cb cb, const void *data)
 {
    Eldbus_Message *msg;
+   Eldbus_Pending *p;
    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
    msg = eldbus_object_method_call_new(obj, ELDBUS_FDO_INTEFACE_PEER, "Ping");
-   return eldbus_object_send(obj, msg, cb, data, -1);
+   p = eldbus_object_send(obj, msg, cb, data, -1);
+   return p;
 }
 
 EAPI Eldbus_Pending *
 eldbus_object_peer_machine_id_get(Eldbus_Object *obj, Eldbus_Message_Cb cb, const void *data)
 {
    Eldbus_Message *msg;
+   Eldbus_Pending *p;
    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
    msg = eldbus_object_method_call_new(obj, ELDBUS_FDO_INTEFACE_PEER,
                                       "GetMachineId");
-   return eldbus_object_send(obj, msg, cb, data, -1);
+   p = eldbus_object_send(obj, msg, cb, data, -1);
+   return p;
 }
 
 EAPI Eldbus_Pending *
 eldbus_object_introspect(Eldbus_Object *obj, Eldbus_Message_Cb cb, const void *data)
 {
    Eldbus_Message *msg;
+   Eldbus_Pending *p;
    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
    msg = eldbus_object_method_call_new(obj, ELDBUS_FDO_INTERFACE_INTROSPECTABLE,
                                       "Introspect");
-   return eldbus_object_send(obj, msg, cb, data, -1);
+   p = eldbus_object_send(obj, msg, cb, data, -1);
+   return p;
 }
index b26c68c..514b40e 100644 (file)
@@ -3,6 +3,7 @@
 
 /**
  * @defgroup Eldbus_Object_Mapper Object Mapper
+ * @ingroup Eldbus
  *
  * @{
  */
index aaddd44..7740901 100644 (file)
@@ -103,17 +103,22 @@ eldbus_connection_send(Eldbus_Connection *conn, Eldbus_Message *msg, Eldbus_Mess
    return pending;
 }
 
+/*
+ * On success @param msg is unref'd or its ref is stolen by the returned
+ * Eldbus_Pending.
+ */
 Eldbus_Pending *
 _eldbus_connection_send(Eldbus_Connection *conn, Eldbus_Message *msg, Eldbus_Message_Cb cb, const void *cb_data, double timeout)
 {
    Eldbus_Pending *pending;
    Eldbus_Message *error_msg;
    DBG("conn=%p, msg=%p, cb=%p, cb_data=%p, timeout=%f",
-          conn, msg, cb, cb_data, timeout);
+       conn, msg, cb, cb_data, timeout);
 
    if (!cb)
      {
         dbus_connection_send(conn->dbus_conn, msg->dbus_msg, NULL);
+        eldbus_message_unref(msg);
         return NULL;
      }
 
@@ -127,7 +132,10 @@ _eldbus_connection_send(Eldbus_Connection *conn, Eldbus_Message *msg, Eldbus_Mes
    pending->interface = eina_stringshare_add(dbus_message_get_interface(msg->dbus_msg));
    pending->method = eina_stringshare_add(dbus_message_get_member(msg->dbus_msg));
    pending->path = eina_stringshare_add(dbus_message_get_path(msg->dbus_msg));
-   pending->msg_sent = eldbus_message_ref(msg);
+
+   /* Steal the reference */
+   pending->msg_sent = msg;
+
    EINA_MAGIC_SET(pending, ELDBUS_PENDING_MAGIC);
 
    if (!dbus_connection_send_with_reply(conn->dbus_conn,
@@ -210,7 +218,7 @@ eldbus_pending_cancel(Eldbus_Pending *pending)
    dbus_pending_call_cancel(pending->dbus_pending);
 
    error_message = eldbus_message_error_new(pending->msg_sent,
-                                           "org.enlightenment.DBus.Canceled",
+                                           ELDBUS_ERROR_PENDING_CANCELED,
                                            "Canceled by user.");
    eldbus_pending_dispatch(pending, error_message);
 }
index 6f6e6f2..98c0085 100644 (file)
@@ -3,6 +3,7 @@
 
 /**
  * @defgroup Eldbus_Pending Pending
+ * @ingroup Eldbus
  *
  * @{
  */
index 223eb7a..c17e443 100644 (file)
@@ -1,8 +1,10 @@
 #ifndef ELDBUS_PRIVATE_H
 #define ELDBUS_PRIVATE_H
 
+#include <dbus/dbus.h>
 #include <Eina.h>
 #include "eina_safety_checks.h"
+#include <Ecore.h>
 #include "Eldbus.h"
 #include "eldbus_private_types.h"
 
@@ -82,10 +84,4 @@ Eldbus_Signal_Handler  *_eldbus_signal_handler_add(Eldbus_Connection *conn, cons
 
 Eldbus_Message         *eldbus_message_signal_new(const char *path, const char *interface, const char *name) EINA_ARG_NONNULL(1, 2, 3) EINA_WARN_UNUSED_RESULT;
 
-#ifdef HAVE_VA_LIST_AS_ARRAY
-#define MAKE_PTR_FROM_VA_LIST(arg) ((va_list *)(arg))
-#else
-#define MAKE_PTR_FROM_VA_LIST(arg) (&(arg))
-#endif
-
 #endif
index 40a7cf3..bc4765d 100644 (file)
@@ -1,11 +1,6 @@
 #ifndef ELDBUS_PRIVATE_TYPES_H
 #define ELDBUS_PRIVATE_TYPES_H 1
 
-#include "Eldbus.h"
-#include <Eina.h>
-#include <dbus/dbus.h>
-#include <Ecore.h>
-
 typedef struct _Eldbus_Connection_Name
 {
    const char *name;
@@ -19,6 +14,7 @@ typedef struct _Eldbus_Connection_Name
       Eina_List   *to_delete;
    } event_handlers;
    Eldbus_Signal_Handler *name_owner_changed;
+   Eldbus_Pending *name_owner_get;
 } Eldbus_Connection_Name;
 
 typedef struct _Eldbus_Object_Context_Event_Cb
@@ -149,8 +145,9 @@ struct _Eldbus_Service_Object
    Eina_Inlist *data;
    Eldbus_Service_Object *parent;
    Eina_Inlist *children;
+
    //ObjectManager data
-   Eina_Bool has_objectmanager:1;
+   Eldbus_Service_Interface *objmanager;
    Eina_List *iface_added;
    Eina_List *iface_removed;
    Ecore_Idler *idler_iface_changed;
index ca24f30..90f5590 100644 (file)
@@ -1,3 +1,7 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include "eldbus_private.h"
 #include "eldbus_private_types.h"
 
@@ -29,6 +33,7 @@ struct _Eldbus_Proxy
    Eina_Inlist              *pendings;
    Eina_List                *handlers;
    Eina_Inlist              *cbs_free;
+   Eina_Inlist              *data;
    Eldbus_Proxy_Context_Event event_handlers[ELDBUS_PROXY_EVENT_LAST];
    Eina_Hash *props;
    Eldbus_Signal_Handler *properties_changed;
@@ -184,12 +189,13 @@ _eldbus_proxy_free(Eldbus_Proxy *proxy)
 }
 
 static void
-_on_object_free(void *data, const void *dead_pointer)
+_on_object_free(void *data, const void *dead_pointer EINA_UNUSED)
 {
    Eldbus_Proxy *proxy = data;
    ELDBUS_PROXY_CHECK(proxy);
    DBG("proxy=%p, refcount=%d, interface=%s, obj=%p",
        proxy, proxy->refcount, proxy->interface, proxy->obj);
+   eldbus_data_del_all(&(proxy->data));
    _eldbus_proxy_clear(proxy);
    _eldbus_proxy_free(proxy);
 }
@@ -234,6 +240,7 @@ _eldbus_proxy_unref(Eldbus_Proxy *proxy)
    if (proxy->refcount > 0) return;
 
    eldbus_object_free_cb_del(proxy->obj, _on_object_free, proxy);
+   eldbus_data_del_all(&(proxy->data));
    _eldbus_proxy_clear(proxy);
    _eldbus_proxy_free(proxy);
 }
@@ -273,6 +280,31 @@ eldbus_proxy_free_cb_del(Eldbus_Proxy *proxy, Eldbus_Free_Cb cb, const void *dat
    proxy->cbs_free = eldbus_cbs_free_del(proxy->cbs_free, cb, data);
 }
 
+EAPI void
+eldbus_proxy_data_set(Eldbus_Proxy *proxy, const char *key, const void *data)
+{
+   ELDBUS_PROXY_CHECK(proxy);
+   EINA_SAFETY_ON_NULL_RETURN(key);
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   eldbus_data_set(&(proxy->data), key, data);
+}
+
+EAPI void *
+eldbus_proxy_data_get(const Eldbus_Proxy *proxy, const char *key)
+{
+   ELDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
+   return eldbus_data_get(&(((Eldbus_Proxy *)proxy)->data), key);
+}
+
+EAPI void *
+eldbus_proxy_data_del(Eldbus_Proxy *proxy, const char *key)
+{
+   ELDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
+   return eldbus_data_del(&(((Eldbus_Proxy *)proxy)->data), key);
+}
+
 static void
 _property_changed_iter(void *data, const void *key, Eldbus_Message_Iter *var)
 {
@@ -539,7 +571,6 @@ eldbus_proxy_method_call_new(Eldbus_Proxy *proxy, const char *member)
 static Eldbus_Pending *
 _eldbus_proxy_vcall(Eldbus_Proxy *proxy, const char *member, Eldbus_Message_Cb cb, const void *cb_data, double timeout, const char *signature, va_list ap)
 {
-   Eldbus_Pending *pending;
    Eldbus_Message *msg = eldbus_proxy_method_call_new(proxy, member);
    EINA_SAFETY_ON_NULL_RETURN_VAL(msg, NULL);
 
@@ -550,9 +581,7 @@ _eldbus_proxy_vcall(Eldbus_Proxy *proxy, const char *member, Eldbus_Message_Cb c
         return NULL;
      }
 
-   pending = _eldbus_proxy_send(proxy, msg, cb, cb_data, timeout);
-   eldbus_message_unref(msg);
-   return pending;
+   return _eldbus_proxy_send(proxy, msg, cb, cb_data, timeout);
 }
 
 EAPI Eldbus_Pending *
@@ -628,7 +657,6 @@ eldbus_proxy_property_set(Eldbus_Proxy *proxy, const char *name, const char *sig
 {
    Eldbus_Message *msg;
    Eldbus_Message_Iter *iter, *variant;
-   Eldbus_Pending *pending;
 
    ELDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
    EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
@@ -653,10 +681,7 @@ eldbus_proxy_property_set(Eldbus_Proxy *proxy, const char *name, const char *sig
      }
    eldbus_message_iter_container_close(iter, variant);
 
-   pending = eldbus_proxy_send(proxy->obj->properties, msg, cb, data, -1);
-   eldbus_message_unref(msg);
-
-   return pending;
+   return eldbus_proxy_send(proxy->obj->properties, msg, cb, data, -1);
 }
 
 EAPI Eldbus_Pending *
@@ -703,7 +728,7 @@ _property_iter(void *data, const void *key, Eldbus_Message_Iter *var)
 }
 
 static void
-_props_get_all(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
+_props_get_all(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
 {
    Eldbus_Proxy *proxy = data;
    Eldbus_Message_Iter *dict;
index dd27fdb..9249948 100644 (file)
@@ -3,6 +3,7 @@
 
 /**
  * @defgroup Eldbus_Proxy Proxy
+ * @ingroup Eldbus
  *
  * @{
  */
index 951f669..e6946c2 100644 (file)
@@ -1,5 +1,9 @@
-#include "eldbus_private_types.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include "eldbus_private.h"
+#include "eldbus_private_types.h"
 
 #define DBUS_ANNOTATION(name, value) \
         "<annotation" \
@@ -502,21 +506,27 @@ _managed_obj_append(Eldbus_Service_Object *obj, Eldbus_Message_Iter *array, Eina
 {
    Eldbus_Message_Iter *obj_entry, *array_interface;
    Eina_Iterator *iface_iter;
-   Eldbus_Service_Interface *children_iface;
+   Eldbus_Service_Interface *iface;
    Eldbus_Service_Object *children;
 
    if (first) goto foreach;
-   if (obj->has_objectmanager) return EINA_TRUE;
+   if (obj->objmanager) return EINA_TRUE;
 
    eldbus_message_iter_arguments_append(array, "{oa{sa{sv}}}", &obj_entry);
    eldbus_message_iter_arguments_append(obj_entry, "oa{sa{sv}}", obj->path,
-                                    &array_interface);
+                                       &array_interface);
    iface_iter = eina_hash_iterator_data_new(obj->interfaces);
-   EINA_ITERATOR_FOREACH(iface_iter, children_iface)
+
+   EINA_ITERATOR_FOREACH(iface_iter, iface)
      {
         Eina_Bool ret;
-        ret = _propmgr_iface_props_append(children_iface, array_interface);
-        if (ret) continue;
+
+        if (eina_list_data_find(obj->iface_added, iface))
+          continue;
+
+        ret = _propmgr_iface_props_append(iface, array_interface);
+        if (ret)
+          continue;
 
         eina_iterator_free(iface_iter);
         return EINA_FALSE;
@@ -700,118 +710,95 @@ _props_free(void *data)
    free(p);
 }
 
-struct iface_remove_data {
-   const char *obj_path;
-   const char *iface;
-};
-
-static Eina_Bool
-_iface_changed_send(void *data)
+static void
+_object_manager_iface_added_emit(Eldbus_Service_Object *obj,
+                                 Eldbus_Service_Object *parent)
 {
-   Eldbus_Service_Object *parent = data;
-
-   while (parent->iface_added)
+   Eina_List *l;
+   Eldbus_Service_Interface *iface;
+   Eldbus_Message_Iter *iter, *array;
+   Eldbus_Message *sig = eldbus_message_signal_new(parent->path,
+                                                 ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
+                                                 "InterfacesAdded");
+   EINA_SAFETY_ON_NULL_RETURN(sig);
+   iter = eldbus_message_iter_get(sig);
+   eldbus_message_iter_arguments_append(iter, "oa{sa{sv}}", obj->path,
+                                       &array);
+
+   EINA_LIST_FOREACH(obj->iface_added, l, iface)
      {
-        Eldbus_Service_Interface *iface, *next_iface;
-        Eldbus_Message *msg;
-        Eldbus_Message_Iter *array_iface, *main_iter;
-        Eina_List *l, *l2;
-
-        iface = eina_list_data_get(parent->iface_added);
-        parent->iface_added = eina_list_remove_list(parent->iface_added,
-                                                    parent->iface_added);
-
-        msg = eldbus_message_signal_new(parent->path,
-                                       ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
-                                       "InterfacesAdded");
-        if (!msg)
-          {
-             ERR("msg == NULL");
-             continue;
-          }
-        main_iter = eldbus_message_iter_get(msg);
-        eldbus_message_iter_arguments_append(main_iter, "oa{sa{sv}}",
-                                         iface->obj->path, &array_iface);
-        if (!_propmgr_iface_props_append(iface, array_iface))
-          goto error;
-        EINA_LIST_FOREACH_SAFE(parent->iface_added, l, l2, next_iface)
+        if (!_propmgr_iface_props_append(iface, array))
           {
-             if (iface->obj->path != next_iface->obj->path)
-               continue;
-             parent->iface_added = eina_list_remove(parent->iface_added,
-                                                    next_iface);
-             if (!_propmgr_iface_props_append(next_iface, array_iface))
-               goto error;
+             ERR("Could not append properties to InterfacesAdded signal");
+             eldbus_message_unref(sig);
+             goto done;
           }
-
-        eldbus_message_iter_container_close(main_iter, array_iface);
-        eldbus_connection_send(parent->conn, msg, NULL, NULL, -1);
-        continue;
-error:
-        ERR("Error appending InterfacesAdded to msg.");
-        eldbus_message_unref(msg);
      }
+   eldbus_message_iter_container_close(iter, array);
+   eldbus_connection_send(parent->conn, sig, NULL, NULL, -1);
 
-   while (parent->iface_removed)
+done:
+   obj->iface_added = eina_list_free(obj->iface_added);
+}
+
+static void
+_object_manager_iface_removed_emit(Eldbus_Service_Object *obj,
+                                   Eldbus_Service_Object *parent)
+{
+   Eina_List *l;
+   const char *name;
+   Eldbus_Message_Iter *iter, *array;
+   Eldbus_Message *sig = eldbus_message_signal_new(parent->path,
+                                                 ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
+                                                 "InterfacesRemoved");
+   EINA_SAFETY_ON_NULL_RETURN(sig);
+
+   iter = eldbus_message_iter_get(sig);
+   eldbus_message_iter_arguments_append(iter, "oas", obj->path, &array);
+
+   EINA_LIST_FOREACH(obj->iface_removed, l, name)
      {
-        Eldbus_Message *msg;
-        Eldbus_Message_Iter *array_iface, *main_iter;
-        struct iface_remove_data *iface_data, *iface_data_next;
-        Eina_List *l, *l2;
-
-        iface_data = eina_list_data_get(parent->iface_removed);
-        parent->iface_removed = eina_list_remove_list(parent->iface_removed,
-                                                      parent->iface_removed);
-
-        msg = eldbus_message_signal_new(parent->path,
-                                       ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
-                                       "InterfacesRemoved");
-        EINA_SAFETY_ON_NULL_GOTO(msg, error2);
-        main_iter = eldbus_message_iter_get(msg);
-
-        eldbus_message_iter_arguments_append(main_iter, "oas", iface_data->obj_path,
-                                         &array_iface);
-        eldbus_message_iter_basic_append(array_iface, 's', iface_data->iface);
-
-        EINA_LIST_FOREACH_SAFE(parent->iface_removed, l, l2, iface_data_next)
-          {
-             if (iface_data->obj_path != iface_data_next->obj_path)
-               continue;
-             parent->iface_removed = eina_list_remove(parent->iface_removed,
-                                                      iface_data_next);
-             eldbus_message_iter_basic_append(array_iface, 's',
-                                             iface_data_next->iface);
-             eina_stringshare_del(iface_data_next->iface);
-             eina_stringshare_del(iface_data_next->obj_path);
-             free(iface_data_next);
-          }
-        eldbus_message_iter_container_close(main_iter, array_iface);
-        eldbus_connection_send(parent->conn, msg, NULL, NULL, -1);
-error2:
-        eina_stringshare_del(iface_data->iface);
-        eina_stringshare_del(iface_data->obj_path);
-        free(iface_data);
+        eldbus_message_iter_arguments_append(array, name);
+        eina_stringshare_del(name);
      }
-
-   parent->idler_iface_changed = NULL;
-   return EINA_FALSE;
+   eldbus_message_iter_container_close(iter, array);
+   eldbus_connection_send(parent->conn, sig, NULL, NULL, -1);
+   obj->iface_removed = eina_list_free(obj->iface_removed);
 }
 
 static Eldbus_Service_Object *
-_find_object_manager_parent(Eldbus_Service_Object *obj)
+_object_manager_parent_find(Eldbus_Service_Object *obj)
 {
    if (!obj->parent)
      return NULL;
-   if (obj->parent->has_objectmanager)
+   if (obj->parent->objmanager)
      return obj->parent;
-   return _find_object_manager_parent(obj->parent);
+   return _object_manager_parent_find(obj->parent);
+}
+
+static Eina_Bool
+_object_manager_changes_process(void *data)
+{
+   Eldbus_Service_Object *obj = data;
+   Eldbus_Service_Object *parent = _object_manager_parent_find(obj);
+
+   obj->idler_iface_changed = NULL;
+
+   if (!parent)
+     return EINA_FALSE;
+
+   if (obj->iface_added)
+     _object_manager_iface_added_emit(obj, parent);
+   if (obj->iface_removed)
+     _object_manager_iface_removed_emit(obj, parent);
+
+   return EINA_FALSE;
 }
 
 static Eldbus_Service_Interface *
 _eldbus_service_interface_add(Eldbus_Service_Object *obj, const char *interface)
 {
    Eldbus_Service_Interface *iface;
-   Eldbus_Service_Object *parent;
 
    iface = eina_hash_find(obj->interfaces, interface);
    if (iface) return iface;
@@ -826,14 +813,11 @@ _eldbus_service_interface_add(Eldbus_Service_Object *obj, const char *interface)
    iface->obj = obj;
    eina_hash_add(obj->interfaces, iface->name, iface);
 
-   parent = _find_object_manager_parent(obj);
-   if (parent)
-     {
-        if (!parent->idler_iface_changed)
-          parent->idler_iface_changed = ecore_idler_add(_iface_changed_send,
-                                                        parent);
-        parent->iface_added = eina_list_append(parent->iface_added, iface);
-     }
+   if (!obj->idler_iface_changed)
+     obj->idler_iface_changed = ecore_idler_add(_object_manager_changes_process,
+                                                obj);
+   obj->iface_added = eina_list_append(obj->iface_added, iface);
+
    return iface;
 }
 
@@ -993,7 +977,9 @@ static void
 _interface_free(Eldbus_Service_Interface *interface)
 {
    const char *sig;
-   Eldbus_Service_Object *parent;
+   Eldbus_Service_Object *obj;
+   Eina_List *l;
+
    if (interface == introspectable || interface == properties_iface ||
        interface == objmanager)
      return;
@@ -1010,23 +996,28 @@ _interface_free(Eldbus_Service_Interface *interface)
    if (interface->prop_invalidated)
      eina_array_free(interface->prop_invalidated);
 
-   parent = _find_object_manager_parent(interface->obj);
-   if (parent)
+   obj = interface->obj;
+   l = eina_list_data_find_list(obj->iface_added, interface);
+   if (l)
      {
-        struct iface_remove_data *data;
-
-        data = malloc(sizeof(struct iface_remove_data));
-        EINA_SAFETY_ON_NULL_GOTO(data, end);
-        data->obj_path = eina_stringshare_add(interface->obj->path);
-        data->iface = eina_stringshare_add(interface->name);
-
-        if (!parent->idler_iface_changed)
-          parent->idler_iface_changed = ecore_idler_add(_iface_changed_send,
-                                                        parent);
-        parent->iface_removed = eina_list_append(parent->iface_removed, data);
-        parent->iface_added = eina_list_remove(parent->iface_added, interface);
+        /* Adding and removing the interface in the same main loop iteration.
+         * Let's not send any signal */
+        obj->iface_added = eina_list_remove_list(obj->iface_added, l);
+        if (!obj->iface_added && !obj->iface_removed && obj->idler_iface_changed)
+          obj->idler_iface_changed = ecore_idler_del(obj->idler_iface_changed);
      }
-end:
+   else
+     {
+        if (!obj->idler_iface_changed)
+          {
+             obj->idler_iface_changed = ecore_idler_add(
+                _object_manager_changes_process, obj);
+          }
+
+        obj->iface_removed = eina_list_append(
+           obj->iface_removed, eina_stringshare_ref(interface->name));
+     }
+
    eina_stringshare_del(interface->name);
    free(interface);
 }
@@ -1036,7 +1027,11 @@ _object_free(Eldbus_Service_Object *obj)
 {
    Eina_Iterator *iterator;
    Eldbus_Service_Interface *iface;
-   struct iface_remove_data *data;
+
+   /* Flush ObjectManager interface before the entire object goes away */
+   if (obj->idler_iface_changed)
+     ecore_idler_del(obj->idler_iface_changed);
+   _object_manager_changes_process(obj);
 
    iterator = eina_hash_iterator_data_new(obj->interfaces);
    EINA_ITERATOR_FOREACH(iterator, iface)
@@ -1069,15 +1064,6 @@ _object_free(Eldbus_Service_Object *obj)
 
    eldbus_data_del_all(&obj->data);
 
-   EINA_LIST_FREE(obj->iface_removed, data)
-     {
-        eina_stringshare_del(data->iface);
-        eina_stringshare_del(data->obj_path);
-        free(data);
-     }
-   eina_list_free(obj->iface_added);
-   if (obj->idler_iface_changed)
-     ecore_idler_del(obj->idler_iface_changed);
    eina_hash_free(obj->interfaces);
    eina_iterator_free(iterator);
    if (obj->introspection_data)
@@ -1087,7 +1073,7 @@ _object_free(Eldbus_Service_Object *obj)
 }
 
 static void
-_on_connection_free(void *data, const void *dead_pointer)
+_on_connection_free(void *data, const void *dead_pointer EINA_UNUSED)
 {
    Eldbus_Service_Object *obj = data;
    dbus_connection_unregister_object_path(obj->conn->dbus_conn, obj->path);
@@ -1122,14 +1108,14 @@ eldbus_service_object_unregister(Eldbus_Service_Interface *iface)
 }
 
 static void
-_object_unregister(DBusConnection *conn, void *user_data)
+_object_unregister(DBusConnection *conn EINA_UNUSED, void *user_data)
 {
    Eldbus_Service_Object *obj = user_data;
    _object_free(obj);
 }
 
 static DBusHandlerResult
-_object_handler(DBusConnection *conn, DBusMessage *msg, void *user_data)
+_object_handler(DBusConnection *conn EINA_UNUSED, DBusMessage *msg, void *user_data)
 {
    Eldbus_Service_Object *obj;
    Eldbus_Service_Interface *iface;
@@ -1196,7 +1182,6 @@ _object_handler(DBusConnection *conn, DBusMessage *msg, void *user_data)
    if (!reply) return DBUS_HANDLER_RESULT_HANDLED;
 
    _eldbus_connection_send(obj->conn, reply, NULL, NULL, -1);
-   eldbus_message_unref(reply);
 
    return DBUS_HANDLER_RESULT_HANDLED;
 }
@@ -1259,7 +1244,6 @@ eldbus_service_signal_send(const Eldbus_Service_Interface *iface, Eldbus_Message
    ELDBUS_SERVICE_INTERFACE_CHECK_RETVAL(iface, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(signal_msg, EINA_FALSE);
    _eldbus_connection_send(iface->obj->conn, signal_msg, NULL, NULL, -1);
-   eldbus_message_unref(signal_msg);
    return EINA_TRUE;
 }
 
@@ -1441,11 +1425,28 @@ eldbus_service_object_manager_attach(Eldbus_Service_Interface *iface)
    ELDBUS_SERVICE_INTERFACE_CHECK_RETVAL(iface, EINA_FALSE);
 
    obj = iface->obj;
-   if (!eina_hash_find(obj->interfaces, objmanager->name))
-     if (!eina_hash_add(obj->interfaces, objmanager->name, objmanager))
-       return EINA_FALSE;
 
-   obj->has_objectmanager = EINA_TRUE;
+   /* We already have it and we registered it ourselves */
+   if (obj->objmanager)
+     return EINA_TRUE;
+
+   /* Ugh. User already registered the ObjectManager interface himself? */
+   if (eina_hash_find(obj->interfaces, obj->objmanager->name))
+     return EINA_FALSE;
+
+   if (!eina_hash_add(obj->interfaces, objmanager->name, objmanager))
+     return EINA_FALSE;
+
+   /*
+    * Flush the iface_added and iface_removed, otherwise it could be sent
+    * with path equal to our path rather than from the previous
+    * ObjectManager
+    */
+   if (obj->idler_iface_changed)
+     ecore_idler_del(obj->idler_iface_changed);
+   _object_manager_changes_process(obj);
+
+   obj->objmanager = objmanager;
    obj->introspection_dirty = EINA_TRUE;
    return EINA_TRUE;
 }
@@ -1458,8 +1459,14 @@ eldbus_service_object_manager_detach(Eldbus_Service_Interface *iface)
 
    ELDBUS_SERVICE_INTERFACE_CHECK_RETVAL(iface, EINA_FALSE);
    obj = iface->obj;
+
+   /* Flush our iface_added/iface_removed before our ObjectManager goes away */
+   if (obj->idler_iface_changed)
+     ecore_idler_del(obj->idler_iface_changed);
+   _object_manager_changes_process(obj);
+
    ret = eina_hash_del(obj->interfaces, objmanager->name, NULL);
-   obj->has_objectmanager = EINA_FALSE;
+   obj->objmanager = NULL;
    obj->introspection_dirty = EINA_TRUE;
    //properties + introspectable
    if (eina_hash_population(iface->obj->interfaces) < 3)
index 08a04f3..f36903b 100644 (file)
@@ -3,6 +3,7 @@
 
 /**
  * @defgroup Eldbus_Service Service
+ * @ingroup Eldbus
  *
  * @{
  */
index 1ff4990..8fedf21 100644 (file)
@@ -144,7 +144,7 @@ eldbus_signal_handler_match_extra_set(Eldbus_Signal_Handler *sh, ...)
 static void _on_handler_of_conn_free(void *data, const void *dead_pointer);
 
 static void
-_on_connection_free(void *data, const void *dead_pointer)
+_on_connection_free(void *data, const void *dead_pointer EINA_UNUSED)
 {
    Eldbus_Signal_Handler *sh = data;
    eldbus_signal_handler_free_cb_del(sh, _on_handler_of_conn_free, sh->conn);
index f1501e7..b842bfc 100644 (file)
@@ -3,6 +3,7 @@
 
 /**
  * @defgroup Eldbus_Signal_Handler Signal Handler
+ * @ingroup Eldbus
  *
  * @{
  */