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])])
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
/**
- * @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
/**
* @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"
#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
{
/**
* @defgroup Eldbus_Conneciton Connection
+ * @ingroup Eldbus
*
* @{
*/
+#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 \
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);
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);
}
}
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");
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,
}
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() */
}
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);
}
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() */
}
static void
-cb_timeout_toggle(DBusTimeout *timeout, void *data)
+cb_timeout_toggle(DBusTimeout *timeout, void *data EINA_UNUSED)
{
Eldbus_Timeout_Data *td;
}
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;
}
}
+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);
&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)
{
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;
}
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(
Eldbus_Connection *conn;
DBG("Getting connection with type %d", type);
+
+ if (!type)
+ return NULL;
+
conn = shared_connections[type - 1];
if (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);
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);
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);
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
free(data);
}
free(found);
+ eldbus_connection_name_gc(conn, cn);
}
EAPI void
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;
}
#define ELDBUS_FREEDESKTOP_H 1
/**
- * @defgroup Eldbus_Basic Basic Methods
+ * @defgroup Eldbus_Basic Basic FreeDesktop.Org Methods
+ * @ingroup Eldbus
*
* @{
*/
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;
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)
{
}
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
}
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;
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 \
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;
}
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 *
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;
}
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);
}
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
_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)
{
/**
* @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);
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 a 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
*
/**
- * @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);
}
}
-#define ARG "arg%d"
+#define ARG "arg%u"
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++;
}
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--;
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;
}
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);
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;
}
/**
* @defgroup Eldbus_Object_Mapper Object Mapper
+ * @ingroup Eldbus
*
* @{
*/
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;
}
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,
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);
}
/**
* @defgroup Eldbus_Pending Pending
+ * @ingroup Eldbus
*
* @{
*/
#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"
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
#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;
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
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;
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
#include "eldbus_private.h"
#include "eldbus_private_types.h"
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;
}
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);
}
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);
}
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)
{
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);
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 *
{
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);
}
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 *
}
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;
/**
* @defgroup Eldbus_Proxy Proxy
+ * @ingroup Eldbus
*
* @{
*/
-#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" \
{
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;
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;
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;
}
_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;
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);
}
{
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)
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)
}
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);
}
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;
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;
}
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;
}
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;
}
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)
/**
* @defgroup Eldbus_Service Service
+ * @ingroup Eldbus
*
* @{
*/
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);
/**
* @defgroup Eldbus_Signal_Handler Signal Handler
+ * @ingroup Eldbus
*
* @{
*/