summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuilherme Lepsch <lepsch@expertisesolutions.com.br>2015-01-09 14:20:14 -0200
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2015-07-21 22:04:31 -0300
commit000ca1fc2f6f71f3b65865076d73557077bc4183 (patch)
treee535501d42bfd41a63f95c8aba99d5d0288fdd8d
parentd7a921788f076d658bde2041f21dc2630b68f880 (diff)
downloadefl-000ca1fc2f6f71f3b65865076d73557077bc4183.tar.gz
eldbus: Created Emodel implementation for Eldbus
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile_Efl.am1
-rw-r--r--src/Makefile_Eldbus.am54
-rw-r--r--src/Makefile_Eldbus_Cxx.am25
-rw-r--r--src/Makefile_Elocation.am2
-rw-r--r--src/lib/efl/Efl.h1
-rw-r--r--src/lib/efl/Efl_Model_Common.h65
-rw-r--r--src/lib/efl/interfaces/efl_model_common.c135
-rw-r--r--src/lib/eldbus/Eldbus.h9
-rw-r--r--src/lib/eldbus/Eldbus_Model.h23
-rw-r--r--src/lib/eldbus/eldbus_core.c17
-rw-r--r--src/lib/eldbus/eldbus_freedesktop.h13
-rw-r--r--src/lib/eldbus/eldbus_introspection.c419
-rw-r--r--src/lib/eldbus/eldbus_introspection.h124
-rw-r--r--src/lib/eldbus/eldbus_message_from_eina_value.c124
-rw-r--r--src/lib/eldbus/eldbus_message_to_eina_value.c2
-rw-r--r--src/lib/eldbus/eldbus_model_arguments.c421
-rw-r--r--src/lib/eldbus/eldbus_model_arguments.eo40
-rw-r--r--src/lib/eldbus/eldbus_model_arguments_private.h30
-rw-r--r--src/lib/eldbus/eldbus_model_connection.c368
-rw-r--r--src/lib/eldbus/eldbus_model_connection.eo49
-rw-r--r--src/lib/eldbus/eldbus_model_connection_private.h28
-rw-r--r--src/lib/eldbus/eldbus_model_method.c105
-rw-r--r--src/lib/eldbus/eldbus_model_method.eo35
-rw-r--r--src/lib/eldbus/eldbus_model_method_private.h18
-rw-r--r--src/lib/eldbus/eldbus_model_object.c542
-rw-r--r--src/lib/eldbus/eldbus_model_object.eo73
-rw-r--r--src/lib/eldbus/eldbus_model_object_private.h32
-rw-r--r--src/lib/eldbus/eldbus_model_private.h37
-rw-r--r--src/lib/eldbus/eldbus_model_proxy.c725
-rw-r--r--src/lib/eldbus/eldbus_model_proxy.eo39
-rw-r--r--src/lib/eldbus/eldbus_model_proxy_private.h31
-rw-r--r--src/lib/eldbus/eldbus_model_signal.c116
-rw-r--r--src/lib/eldbus/eldbus_model_signal.eo23
-rw-r--r--src/lib/eldbus/eldbus_model_signal_private.h19
-rw-r--r--src/lib/eldbus/eldbus_private.h7
-rw-r--r--src/lib/eldbus/eldbus_proxy.c36
-rw-r--r--src/tests/eldbus/eldbus_fake_server.c181
-rw-r--r--src/tests/eldbus/eldbus_fake_server.h29
-rw-r--r--src/tests/eldbus/eldbus_suite.c11
-rw-r--r--src/tests/eldbus/eldbus_suite.h7
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model.c417
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model.h32
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model_connection.c200
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model_method.c220
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model_object.c201
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model_proxy.c184
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model_signal.c219
-rw-r--r--src/tests/eldbus/eldbus_test_fake_server_eldbus_model_proxy.c246
49 files changed, 5710 insertions, 27 deletions
diff --git a/configure.ac b/configure.ac
index 2069102f58..13de36cc2e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3918,7 +3918,7 @@ EFL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [emile])
ECORE_EVAS_MODULE([extn], [${want_ecore_evas_extn}])
ECORE_EVAS_MODULE([ews], [yes])
ECORE_EVAS_MODULE([fb], [${want_fb}])
-ECORE_EVAS_MODULE([drm], [${want_drm}],
+ECORE_EVAS_MODULE([drm], [${want_drm}],
[EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_drm}], [ecore-drm])])
ECORE_EVAS_MODULE([gl-drm], [${want_gl_drm}],
[EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_gl_drm}], [ecore-drm])])
diff --git a/src/Makefile_Efl.am b/src/Makefile_Efl.am
index b64223ee7d..0f237f61b1 100644
--- a/src/Makefile_Efl.am
+++ b/src/Makefile_Efl.am
@@ -40,6 +40,7 @@ lib_LTLIBRARIES += lib/efl/libefl.la
lib_efl_libefl_la_SOURCES = \
lib/efl/interfaces/efl_interfaces_main.c \
+lib/efl/interfaces/efl_model_common.c \
lib/efl/interfaces/efl_gfx_shape.c
lib_efl_libefl_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl -I$(top_srcdir)/src/lib/efl @EFL_CFLAGS@ -DEFL_GFX_FILTER_BETA
diff --git a/src/Makefile_Eldbus.am b/src/Makefile_Eldbus.am
index 66ca2bf913..a64cedd498 100644
--- a/src/Makefile_Eldbus.am
+++ b/src/Makefile_Eldbus.am
@@ -1,6 +1,31 @@
### Library
+eldbus_eolian_files = \
+ lib/eldbus/eldbus_model_connection.eo \
+ lib/eldbus/eldbus_model_object.eo \
+ lib/eldbus/eldbus_model_proxy.eo \
+ lib/eldbus/eldbus_model_method.eo \
+ lib/eldbus/eldbus_model_arguments.eo \
+ lib/eldbus/eldbus_model_signal.eo
+
+eldbus_eolian_c = $(eldbus_eolian_files:%.eo=%.eo.c)
+eldbus_eolian_h = $(eldbus_eolian_files:%.eo=%.eo.h)
+
+BUILT_SOURCES += \
+ $(eldbus_eolian_c) \
+ $(eldbus_eolian_h)
+
+CLEANFILES += \
+ $(eldbus_eolian_c) \
+ $(eldbus_eolian_h)
+
+eldbuseolianfilesdir = $(datadir)/eolian/include/eldbus-@VMAJ@
+eldbuseolianfiles_DATA = $(eldbus_eolian_files)
+
+EXTRA_DIST += \
+ ${eldbuseolianfiles_DATA}
+
lib_LTLIBRARIES += lib/eldbus/libeldbus.la
installed_eldbusmainheadersdir = $(includedir)/eldbus-@VMAJ@
@@ -17,6 +42,8 @@ lib/eldbus/eldbus_signal_handler.h \
lib/eldbus/eldbus_message_helper.h \
lib/eldbus/eldbus_message_eina_value.h
+nodist_installed_eldbusmainheaders_DATA = $(eldbus_eolian_h)
+
lib_eldbus_libeldbus_la_SOURCES = \
lib/eldbus/eldbus_private.h \
lib/eldbus/eldbus_private_types.h \
@@ -30,13 +57,20 @@ lib/eldbus/eldbus_service.c \
lib/eldbus/eldbus_signal_handler.c \
lib/eldbus/eldbus_message_helper.c \
lib/eldbus/eldbus_message_to_eina_value.c \
-lib/eldbus/eldbus_message_from_eina_value.c
+lib/eldbus/eldbus_message_from_eina_value.c \
+lib/eldbus/eldbus_model_connection.c \
+lib/eldbus/eldbus_model_object.c \
+lib/eldbus/eldbus_model_proxy.c \
+lib/eldbus/eldbus_model_method.c \
+lib/eldbus/eldbus_model_arguments.c \
+lib/eldbus/eldbus_model_signal.c \
+lib/eldbus/eldbus_introspection.c
lib_eldbus_libeldbus_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-include $(top_builddir)/config.h \
-@ELDBUS_CFLAGS@
-lib_eldbus_libeldbus_la_LIBADD = @ELDBUS_LIBS@
-lib_eldbus_libeldbus_la_DEPENDENCIES = @ELDBUS_INTERNAL_LIBS@
+@ELDBUS_CFLAGS@ @EFL_CFLAGS@
+lib_eldbus_libeldbus_la_LIBADD = @ELDBUS_LIBS@ @EFL_LIBS@
+lib_eldbus_libeldbus_la_DEPENDENCIES = @ELDBUS_INTERNAL_LIBS@ @EFL_INTERNAL_LIBS@
lib_eldbus_libeldbus_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
### Binary
@@ -74,12 +108,20 @@ TESTS += tests/eldbus/eldbus_suite
tests_eldbus_eldbus_suite_SOURCES = \
tests/eldbus/eldbus_suite.c \
tests/eldbus/eldbus_test_eldbus_init.c \
+tests/eldbus/eldbus_test_eldbus_model.c \
+tests/eldbus/eldbus_test_eldbus_model_connection.c \
+tests/eldbus/eldbus_test_eldbus_model_object.c \
+tests/eldbus/eldbus_test_eldbus_model_proxy.c \
+tests/eldbus/eldbus_test_eldbus_model_method.c \
+tests/eldbus/eldbus_test_eldbus_model_signal.c \
+tests/eldbus/eldbus_test_fake_server_eldbus_model_proxy.c \
+tests/eldbus/eldbus_fake_server.c \
tests/eldbus/eldbus_suite.h
tests_eldbus_eldbus_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl @CHECK_CFLAGS@ @ELDBUS_CFLAGS@ \
--DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eldbus\"
+@EFL_CFLAGS@ -DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eldbus\"
-tests_eldbus_eldbus_suite_LDADD = @CHECK_LIBS@ @USE_ELDBUS_LIBS@
+tests_eldbus_eldbus_suite_LDADD = @CHECK_LIBS@ @USE_ELDBUS_LIBS@ @USE_EFL_LIBS@
tests_eldbus_eldbus_suite_DEPENDENCIES = @USE_ELDBUS_INTERNAL_LIBS@
endif
diff --git a/src/Makefile_Eldbus_Cxx.am b/src/Makefile_Eldbus_Cxx.am
index ad17184428..7d13509df4 100644
--- a/src/Makefile_Eldbus_Cxx.am
+++ b/src/Makefile_Eldbus_Cxx.am
@@ -1,6 +1,31 @@
if HAVE_CXX11
+### Generated headers
+
+generated_eldbus_cxx_bindings = \
+ lib/eldbus/eldbus_model_connection.eo.hh \
+ lib/eldbus/eldbus_model_object.eo.hh \
+ lib/eldbus/eldbus_model_proxy.eo.hh \
+ lib/eldbus/eldbus_model_method.eo.hh \
+ lib/eldbus/eldbus_model_arguments.eo.hh \
+ lib/eldbus/eldbus_model_signal.eo.hh
+
+lib/eldbus/Eldbus_Model.hh: $(generated_eldbus_cxx_bindings)
+ @echo @ECHO_E@ "#ifndef EFL_CXX_ELDBUS_MODEL_HH\n#define EFL_CXX_ELDBUS_MODEL_HH\n" > $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
+ @echo @ECHO_E@ "#include <Eldbus_Model.h>" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
+ @echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
+ @for i in $(generated_eldbus_cxx_bindings); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh; done
+ @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
+
+generated_eldbus_cxx_all = \
+ $(generated_eldbus_cxx_bindings) \
+ lib/eldbus/Eldbus_Model.hh
+
+CLEANFILES += $(generated_eldbus_cxx_all)
+
+nodist_installed_eldbuscxxmainheaders_DATA = $(generated_eldbus_cxx_all)
+
### Library
installed_eldbuscxxmainheadersdir = $(includedir)/eldbus_cxx-@VMAJ@
diff --git a/src/Makefile_Elocation.am b/src/Makefile_Elocation.am
index 604b50d512..82ff192724 100644
--- a/src/Makefile_Elocation.am
+++ b/src/Makefile_Elocation.am
@@ -17,7 +17,7 @@ lib/elocation/gen/eldbus_geo_clue2_client.c \
lib/elocation/gen/eldbus_geo_clue2_location.c \
lib/elocation/gen/eldbus_geo_clue2_manager.c
-lib_elocation_libelocation_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ELOCATION_CFLAGS@
+lib_elocation_libelocation_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ELOCATION_CFLAGS@ @EFL_CFLAGS@
lib_elocation_libelocation_la_LIBADD = @ELOCATION_LIBS@
lib_elocation_libelocation_la_DEPENDENCIES = @ELOCATION_INTERNAL_LIBS@
lib_elocation_libelocation_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h
index 7a2ea8fa70..1bcb192b2d 100644
--- a/src/lib/efl/Efl.h
+++ b/src/lib/efl/Efl.h
@@ -147,7 +147,6 @@ typedef enum _Efl_Gfx_Fill_Spread
#include "interfaces/efl_player.eo.h"
#include "interfaces/efl_text.eo.h"
#include "interfaces/efl_text_properties.eo.h"
-#include "interfaces/efl_model_base.eo.h"
EAPI extern const Eo_Event_Description _EFL_GFX_CHANGED;
EAPI extern const Eo_Event_Description _EFL_GFX_PATH_CHANGED;
diff --git a/src/lib/efl/Efl_Model_Common.h b/src/lib/efl/Efl_Model_Common.h
index ce1ed3b66b..360e509e4e 100644
--- a/src/lib/efl/Efl_Model_Common.h
+++ b/src/lib/efl/Efl_Model_Common.h
@@ -1,9 +1,3 @@
-#ifndef _EFL_MODEL_COMMON_H
-#define _EFL_MODEL_COMMON_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
/**
* @struct _Efl_Model_Children_Event
@@ -31,8 +25,59 @@ struct _Efl_Model_Children_Event
*/
typedef struct _Efl_Model_Children_Event Efl_Model_Children_Event;
+#include "interfaces/efl_model_base.eo.h"
+
+ /**
+ * @brief Sets the new load status signaling an event if changed
+ *
+ * @param model The model to call the event @c EFL_MODEL_EVENT_LOAD_STATUS
+ * @param load The load status to be changed
+ * @param status The new status
+ */
+EAPI void efl_model_load_set(Efl_Model_Base *model, Efl_Model_Load *load, Efl_Model_Load_Status status) EINA_ARG_NONNULL(1, 2);
+
+/**
+ * @brief Slices a list
+ *
+ * If the @p start and @p count are 0, a new accessor of the entire list is returned
+ *
+ * @param list The list to get the slice
+ * @param start The nth element to start the slice
+ * @param count The number of elements
+ * @return The accessor to the sliced elements or @c NULL if error
+ */
+EAPI Eina_Accessor *efl_model_list_slice(Eina_List *list, unsigned start, unsigned count) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Notifies an error with an @c EFL_MODEL_EVENT_LOAD_STATUS
+ *
+ * @param model The model to be notified
+ */
+EAPI void efl_model_error_notify(Efl_Model_Base *model) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Callback to setup a member of @c Eina_Value_Struct
+ *
+ * @param data The user data
+ * @param index The member index
+ * @param member The member to fill its name and type. Must use @c Eina_Stringshare for name.
+ */
+typedef void (*Efl_Model_Value_Struct_Member_Setup_Cb)(void *data, int index, Eina_Value_Struct_Member *member);
+
+/**
+ * @brief Creates a new struct description
+ *
+ * @param member_count The number of struct members
+ * @param setup_cb The callback to setup struct members
+ * @param data The user data
+ * @return Returns the struct description
+ */
+EAPI Eina_Value_Struct_Desc *efl_model_value_struct_desc_new(unsigned int member_count, Efl_Model_Value_Struct_Member_Setup_Cb setup_cb, void *data) EINA_ARG_NONNULL(2);
+
+/**
+ * @brief Frees the memory allocated to the struct description.
+ *
+ * @param desc The struct description. If @c NULL, the function returns immediately.
+ */
+EAPI void efl_model_value_struct_desc_free(Eina_Value_Struct_Desc *desc);
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/src/lib/efl/interfaces/efl_model_common.c b/src/lib/efl/interfaces/efl_model_common.c
new file mode 100644
index 0000000000..ec83e60639
--- /dev/null
+++ b/src/lib/efl/interfaces/efl_model_common.c
@@ -0,0 +1,135 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Efl.h"
+
+void
+efl_model_load_set(Efl_Model_Base *model, Efl_Model_Load *load, Efl_Model_Load_Status status)
+{
+ Efl_Model_Load new_load = {.status = status};
+
+ if ((load->status & (EFL_MODEL_LOAD_STATUS_LOADED | EFL_MODEL_LOAD_STATUS_LOADING)) &&
+ (new_load.status & (EFL_MODEL_LOAD_STATUS_LOADED | EFL_MODEL_LOAD_STATUS_LOADING)))
+ {
+ // Merge status
+ new_load.status = load->status | new_load.status;
+
+ // Removes incompatible statuses (LOADING vs LOADED)
+ switch (status)
+ {
+ case EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES:
+ new_load.status &= ~EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES;
+ break;
+ case EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES:
+ new_load.status &= ~EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES;
+ break;
+ case EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN:
+ new_load.status &= ~EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN;
+ break;
+ case EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN:
+ new_load.status &= ~EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN;
+ break;
+ case EFL_MODEL_LOAD_STATUS_LOADED:
+ new_load.status &= ~EFL_MODEL_LOAD_STATUS_LOADING;
+ break;
+ case EFL_MODEL_LOAD_STATUS_LOADING:
+ new_load.status &= ~EFL_MODEL_LOAD_STATUS_LOADED;
+ break;
+ default: break;
+ }
+ }
+
+ if (load->status != new_load.status)
+ {
+ load->status = new_load.status;
+ eo_do(model, eo_event_callback_call(EFL_MODEL_BASE_EVENT_LOAD_STATUS, load));
+ }
+}
+
+Eina_Accessor *
+efl_model_list_slice(Eina_List *list, unsigned start, unsigned count)
+{
+ fprintf(stderr, "efl_model_list_slice\n");
+ if ((start == 0) && (count == 0))
+ {
+ fprintf(stderr, "efl_model_list_slice start == 0 count == 0\n");
+ return eina_list_accessor_new(list);
+ }
+
+ Eina_List *nth_list = eina_list_nth_list(list, (start - 1));
+ if (!nth_list)
+ return NULL;
+
+ Eina_List *it, *result = NULL;
+ const void *data;
+ EINA_LIST_FOREACH(nth_list, it, data)
+ {
+ result = eina_list_append(result, data);
+ if (eina_list_count(result) == count)
+ break;
+ }
+
+ return eina_list_accessor_new(result);
+}
+
+void
+efl_model_error_notify(Efl_Model_Base *model)
+{
+ Efl_Model_Load load = {.status = EFL_MODEL_LOAD_STATUS_ERROR};
+ eo_do(model, eo_event_callback_call(EFL_MODEL_BASE_EVENT_LOAD_STATUS, &load));
+}
+
+typedef struct _Efl_Model_Value_Struct_Desc
+{
+ Eina_Value_Struct_Desc base;
+ void *data;
+ Eina_Value_Struct_Member members[];
+} Efl_Model_Value_Struct_Desc;
+
+Eina_Value_Struct_Desc *
+efl_model_value_struct_desc_new(unsigned int member_count, Efl_Model_Value_Struct_Member_Setup_Cb setup_cb, void *data)
+{
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(member_count > 0, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(setup_cb, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
+
+ Efl_Model_Value_Struct_Desc *desc = malloc(sizeof(Efl_Model_Value_Struct_Desc) + member_count * sizeof(Eina_Value_Struct_Member));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
+
+ desc->base.version = EINA_VALUE_STRUCT_DESC_VERSION;
+ desc->base.ops = EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE;
+ desc->base.members = desc->members;
+ desc->base.member_count = member_count;
+ desc->base.size = 0;
+ desc->data = data;
+
+ unsigned int offset = 0;
+ for (size_t i = 0; i < member_count; ++i)
+ {
+ Eina_Value_Struct_Member *m = (Eina_Value_Struct_Member *)desc->members + i;
+
+ m->offset = offset;
+ setup_cb(data, i, m);
+
+ unsigned int size = m->type->value_size;
+ if (size % sizeof(void *) != 0)
+ size += size - (size % sizeof(void *));
+
+ offset += size;
+ }
+
+ desc->base.size = offset;
+ return &desc->base;
+}
+
+void
+efl_model_value_struct_desc_free(Eina_Value_Struct_Desc *desc)
+{
+ if (!desc) return;
+
+ for (size_t i = 0; i < desc->member_count; i++)
+ eina_stringshare_del(desc->members[i].name);
+ free(desc);
+}
+
diff --git a/src/lib/eldbus/Eldbus.h b/src/lib/eldbus/Eldbus.h
index ee1195420b..f22fae31f6 100644
--- a/src/lib/eldbus/Eldbus.h
+++ b/src/lib/eldbus/Eldbus.h
@@ -79,6 +79,8 @@
#include <Eina.h>
#include <stdarg.h>
#include <Efl_Config.h>
+#include <Eo.h>
+#include <Efl.h>
#ifdef EAPI
# undef EAPI
@@ -236,6 +238,13 @@ typedef void (*Eldbus_Signal_Cb)(void *data, const Eldbus_Message *msg);
#include "eldbus_proxy.h"
#include "eldbus_freedesktop.h"
#include "eldbus_service.h"
+#include "eldbus_introspection.h"
+#include "eldbus_model_arguments.eo.h"
+#include "eldbus_model_connection.eo.h"
+#include "eldbus_model_method.eo.h"
+#include "eldbus_model_object.eo.h"
+#include "eldbus_model_proxy.eo.h"
+#include "eldbus_model_signal.eo.h"
#ifdef __cplusplus
}
diff --git a/src/lib/eldbus/Eldbus_Model.h b/src/lib/eldbus/Eldbus_Model.h
new file mode 100644
index 0000000000..9edbd77332
--- /dev/null
+++ b/src/lib/eldbus/Eldbus_Model.h
@@ -0,0 +1,23 @@
+#ifndef _ELDBUS_MODEL_H
+#define _ELDBUS_MODEL_H
+
+#include <Eldbus.h>
+#include <Efl.h>
+#include <Eo.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <eldbus_model_connection.eo.h>
+#include <eldbus_model_object.eo.h>
+#include <eldbus_model_proxy.eo.h>
+#include <eldbus_model_arguments.eo.h>
+#include <eldbus_model_method.eo.h>
+#include <eldbus_model_signal.eo.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/eldbus/eldbus_core.c b/src/lib/eldbus/eldbus_core.c
index 48ea7c01e9..9147080975 100644
--- a/src/lib/eldbus/eldbus_core.c
+++ b/src/lib/eldbus/eldbus_core.c
@@ -73,8 +73,9 @@ EAPI const Eldbus_Version * eldbus_version = &_version;
static int _eldbus_init_count = 0;
int _eldbus_log_dom = -1;
+int eldbus_model_log_dom = -1;
-/* We don't save ELDBUS_CONNECTION_TYPE_UNKNOWN in here so we need room for
+/* We don't save ELDBUS_CONNECTION_TYPE_UNKNOWN in here so we need room for
* last - 1 elements */
static void *shared_connections[ELDBUS_CONNECTION_TYPE_LAST - 1];
static Eina_Hash *address_connections = NULL;
@@ -104,6 +105,16 @@ eldbus_init(void)
return 0;
}
+ eldbus_model_log_dom = eina_log_domain_register("eldbus_model", EINA_COLOR_CYAN);
+ if (eldbus_model_log_dom < 0)
+ {
+ EINA_LOG_ERR("Unable to create an 'eldbus_model' log domain");
+ eina_log_domain_unregister(_eldbus_log_dom);
+ _eldbus_log_dom = -1;
+ eina_shutdown();
+ return 0;
+ }
+
if (!ecore_init())
{
ERR("Unable to initialize ecore");
@@ -144,6 +155,8 @@ signal_handler_failed:
eldbus_message_shutdown();
message_failed:
ecore_shutdown();
+ eina_log_domain_unregister(eldbus_model_log_dom);
+ eldbus_model_log_dom = -1;
eina_log_domain_unregister(_eldbus_log_dom);
_eldbus_log_dom = -1;
eina_shutdown();
@@ -245,6 +258,8 @@ eldbus_shutdown(void)
eldbus_message_shutdown();
ecore_shutdown();
+ eina_log_domain_unregister(eldbus_model_log_dom);
+ eldbus_model_log_dom = -1;
eina_log_domain_unregister(_eldbus_log_dom);
_eldbus_log_dom = -1;
eina_shutdown();
diff --git a/src/lib/eldbus/eldbus_freedesktop.h b/src/lib/eldbus/eldbus_freedesktop.h
index 1b2901ca4d..35b1a4e244 100644
--- a/src/lib/eldbus/eldbus_freedesktop.h
+++ b/src/lib/eldbus/eldbus_freedesktop.h
@@ -240,6 +240,19 @@ EAPI Eldbus_Pending *eldbus_proxy_property_get(Eldbus_Proxy *proxy, const
EAPI Eldbus_Pending *eldbus_proxy_property_set(Eldbus_Proxy *proxy, const char *name, const char *sig, const void *value, Eldbus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2, 3, 4);
/**
+ * Set a property with a Eina_Value.
+ *
+ * @param proxy The proxy object on which to do the query.
+ * @param name The property name to get.
+ * @param sig
+ * @param value The value to set.
+ * @param cb The callback to be called when receiving an answer.
+ * @param data Data to be passed to the callback.
+ * @return Eldbus_Pending object corresponding to the message sent.
+ */
+EAPI Eldbus_Pending *eldbus_proxy_property_value_set(Eldbus_Proxy *proxy, const char *name, const char *sig, const Eina_Value *value, Eldbus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2, 3, 4);
+
+/**
* Get all properties.
*
* @param proxy The proxy object on which to do the query.
diff --git a/src/lib/eldbus/eldbus_introspection.c b/src/lib/eldbus/eldbus_introspection.c
new file mode 100644
index 0000000000..8fb574bc99
--- /dev/null
+++ b/src/lib/eldbus/eldbus_introspection.c
@@ -0,0 +1,419 @@
+#include "eldbus_introspection.h"
+
+typedef struct _Eldbus_Introspection_Element_Parse_Table Eldbus_Introspection_Element_Parse_Table;
+
+struct _Eldbus_Introspection_Element_Parse_Table
+{
+ const char *name;
+ void *(*parse)(Eina_Simple_XML_Node_Tag *tag);
+ Eina_List **list;
+};
+
+static const char *_eldbus_introspection_attribute_value_get(Eina_Inlist *, const char *);
+static void *_eldbus_introspection_parse_node(Eina_Simple_XML_Node_Tag *);
+static void *_eldbus_introspection_parse_interface(Eina_Simple_XML_Node_Tag *);
+static void *_eldbus_introspection_parse_method(Eina_Simple_XML_Node_Tag *);
+static void *_eldbus_introspection_parse_signal(Eina_Simple_XML_Node_Tag *);
+static void *_eldbus_introspection_parse_argument(Eina_Simple_XML_Node_Tag *);
+static void *_eldbus_introspection_parse_property(Eina_Simple_XML_Node_Tag *);
+static void *_eldbus_introspection_parse_annotation(Eina_Simple_XML_Node_Tag *);
+static void _eldbus_introspection_parse_children(Eina_Inlist *, const Eldbus_Introspection_Element_Parse_Table[]);
+static void _eldbus_introspection_interface_free(Eldbus_Introspection_Interface *);
+static void _eldbus_introspection_method_free(Eldbus_Introspection_Method *);
+static void _eldbus_introspection_signal_free(Eldbus_Introspection_Signal *);
+static void _eldbus_introspection_argument_free(Eldbus_Introspection_Argument *);
+static void _eldbus_introspection_property_free(Eldbus_Introspection_Property *);
+static void _eldbus_introspection_annotation_free(Eldbus_Introspection_Annotation *);
+
+EAPI Eldbus_Introspection_Node *
+eldbus_introspection_parse(const char *xml)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(xml, NULL);
+
+ Eldbus_Introspection_Node *node = NULL;
+
+ Eina_Simple_XML_Node_Root *xml_root = eina_simple_xml_node_load(xml, strlen(xml), EINA_TRUE);
+
+ Eina_Simple_XML_Node *xml_node = (Eina_Simple_XML_Node*)eina_inlist_last(xml_root->children);
+ EINA_SAFETY_ON_FALSE_GOTO(EINA_SIMPLE_XML_NODE_TAG == xml_node->type, free_root);
+
+ node = (Eldbus_Introspection_Node*)_eldbus_introspection_parse_node((Eina_Simple_XML_Node_Tag*)xml_node);
+
+free_root:
+ eina_simple_xml_node_root_free(xml_root);
+
+ return node;
+}
+
+static void *
+_eldbus_introspection_parse_node(Eina_Simple_XML_Node_Tag *tag)
+{
+ Eldbus_Introspection_Node *node = calloc(1, sizeof(Eldbus_Introspection_Node));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
+
+ const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
+ node->name = eina_stringshare_add(name);
+
+ Eldbus_Introspection_Element_Parse_Table table[] = {
+ {"node", _eldbus_introspection_parse_node, &node->nodes},
+ {"interface", _eldbus_introspection_parse_interface, &node->interfaces},
+ {NULL, NULL, NULL}
+ };
+ _eldbus_introspection_parse_children(tag->children, table);
+
+ return node;
+}
+
+EAPI void
+eldbus_introspection_node_free(Eldbus_Introspection_Node *node)
+{
+ EINA_SAFETY_ON_NULL_RETURN(node);
+
+ Eldbus_Introspection_Node *child_node;
+ EINA_LIST_FREE(node->nodes, child_node)
+ eldbus_introspection_node_free(child_node);
+
+ Eldbus_Introspection_Interface *interface;
+ EINA_LIST_FREE(node->interfaces, interface)
+ _eldbus_introspection_interface_free(interface);
+
+ eina_stringshare_del(node->name);
+ free(node);
+}
+
+static const char *
+_eldbus_introspection_attribute_value_get(Eina_Inlist *attributes, const char *key)
+{
+ Eina_Simple_XML_Attribute *attribute;
+ EINA_INLIST_FOREACH(attributes, attribute)
+ {
+ if (strcmp(attribute->key, key) == 0)
+ return attribute->value;
+ }
+
+ return NULL;
+}
+
+static void *
+_eldbus_introspection_parse_interface(Eina_Simple_XML_Node_Tag *tag)
+{
+ Eldbus_Introspection_Interface *interface = calloc(1, sizeof(Eldbus_Introspection_Interface));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
+
+ const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
+ EINA_SAFETY_ON_NULL_GOTO(name, error); // required
+ interface->name = eina_stringshare_add(name);
+
+ Eldbus_Introspection_Element_Parse_Table table[] = {
+ {"method", _eldbus_introspection_parse_method, &interface->methods},
+ {"signal", _eldbus_introspection_parse_signal, &interface->signals},
+ {"property", _eldbus_introspection_parse_property, &interface->properties},
+ {"annotation", _eldbus_introspection_parse_annotation, &interface->annotations},
+ {NULL, NULL, NULL}
+ };
+ _eldbus_introspection_parse_children(tag->children, table);
+
+ return interface;
+
+error:
+ _eldbus_introspection_interface_free(interface);
+ return NULL;
+}
+
+static void
+_eldbus_introspection_interface_free(Eldbus_Introspection_Interface *interface)
+{
+ EINA_SAFETY_ON_NULL_RETURN(interface);
+
+ Eldbus_Introspection_Method *method;
+ EINA_LIST_FREE(interface->methods, method)
+ _eldbus_introspection_method_free(method);
+
+ Eldbus_Introspection_Signal *signal;
+ EINA_LIST_FREE(interface->signals, signal)
+ _eldbus_introspection_signal_free(signal);
+
+ Eldbus_Introspection_Property *property;
+ EINA_LIST_FREE(interface->properties, property)
+ _eldbus_introspection_property_free(property);
+
+ Eldbus_Introspection_Annotation *annotation;
+ EINA_LIST_FREE(interface->annotations, annotation)
+ _eldbus_introspection_annotation_free(annotation);
+
+ eina_stringshare_del(interface->name);
+ free(interface);
+}
+
+static void *
+_eldbus_introspection_parse_method(Eina_Simple_XML_Node_Tag *tag)
+{
+ Eldbus_Introspection_Method *method = calloc(1, sizeof(Eldbus_Introspection_Method));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(method, NULL);
+
+ const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
+ EINA_SAFETY_ON_NULL_GOTO(name, error); // required
+ method->name = eina_stringshare_add(name);
+
+ Eldbus_Introspection_Element_Parse_Table table[] = {
+ {"arg", _eldbus_introspection_parse_argument, &method->arguments},
+ {"annotation", _eldbus_introspection_parse_annotation, &method->annotations},
+ {NULL, NULL, NULL}
+ };
+ _eldbus_introspection_parse_children(tag->children, table);
+
+ return method;
+
+error:
+ _eldbus_introspection_method_free(method);
+ return NULL;
+}
+
+static void
+_eldbus_introspection_method_free(Eldbus_Introspection_Method *method)
+{
+ EINA_SAFETY_ON_NULL_RETURN(method);
+
+ Eldbus_Introspection_Argument *argument;
+ EINA_LIST_FREE(method->arguments, argument)
+ _eldbus_introspection_argument_free(argument);
+
+ Eldbus_Introspection_Annotation *annotation;
+ EINA_LIST_FREE(method->annotations, annotation)
+ _eldbus_introspection_annotation_free(annotation);
+
+ eina_stringshare_del(method->name);
+ free(method);
+}
+
+static void *
+_eldbus_introspection_parse_signal(Eina_Simple_XML_Node_Tag *tag)
+{
+ Eldbus_Introspection_Signal *signal = calloc(1, sizeof(Eldbus_Introspection_Signal));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(signal, NULL);
+
+ const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
+ EINA_SAFETY_ON_NULL_GOTO(name, error); // required
+ signal->name = eina_stringshare_add(name);
+
+ Eldbus_Introspection_Element_Parse_Table table[] = {
+ {"arg", _eldbus_introspection_parse_argument, &signal->arguments},
+ {"annotation", _eldbus_introspection_parse_annotation, &signal->annotations},
+ {NULL, NULL, NULL}
+ };
+ _eldbus_introspection_parse_children(tag->children, table);
+
+ return signal;
+
+error:
+ _eldbus_introspection_signal_free(signal);
+ return NULL;
+}
+
+static void
+_eldbus_introspection_signal_free(Eldbus_Introspection_Signal *signal)
+{
+ EINA_SAFETY_ON_NULL_RETURN(signal);
+
+ Eldbus_Introspection_Argument *argument;
+ EINA_LIST_FREE(signal->arguments, argument)
+ _eldbus_introspection_argument_free(argument);
+
+ Eldbus_Introspection_Annotation *annotation;
+ EINA_LIST_FREE(signal->annotations, annotation)
+ _eldbus_introspection_annotation_free(annotation);
+
+ eina_stringshare_del(signal->name);
+ free(signal);
+}
+
+static void *
+_eldbus_introspection_parse_argument(Eina_Simple_XML_Node_Tag *tag)
+{
+ Eldbus_Introspection_Argument *argument = calloc(1, sizeof(Eldbus_Introspection_Argument));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(argument, NULL);
+
+ const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
+ argument->name = eina_stringshare_add(name);
+
+ const char *type = _eldbus_introspection_attribute_value_get(tag->attributes, "type");
+ EINA_SAFETY_ON_NULL_GOTO(type, error); // required
+ argument->type = eina_stringshare_add(type);
+
+ const char *direction = _eldbus_introspection_attribute_value_get(tag->attributes, "direction");
+ if (direction)
+ {
+ //EINA_SAFETY_ON_NULL_GOTO(direction, error); // required for methods only
+ if (strcmp(direction, "in") == 0)
+ argument->direction = ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN;
+ else
+ if (strcmp(direction, "out") == 0)
+ argument->direction = ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_OUT;
+ else
+ argument->direction = ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_NONE;
+ }
+
+ return argument;
+
+error:
+ _eldbus_introspection_argument_free(argument);
+ return NULL;
+}
+
+static void
+_eldbus_introspection_argument_free(Eldbus_Introspection_Argument *argument)
+{
+ EINA_SAFETY_ON_NULL_RETURN(argument);
+ eina_stringshare_del(argument->name);
+ eina_stringshare_del(argument->type);
+ free(argument);
+}
+
+static void *
+_eldbus_introspection_parse_property(Eina_Simple_XML_Node_Tag *tag)
+{
+ Eldbus_Introspection_Property *property = calloc(1, sizeof(Eldbus_Introspection_Property));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(property, NULL);
+
+ const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
+ EINA_SAFETY_ON_NULL_GOTO(name, error); // required
+ property->name = eina_stringshare_add(name);
+
+ const char *type = _eldbus_introspection_attribute_value_get(tag->attributes, "type");
+ EINA_SAFETY_ON_NULL_GOTO(type, error); // required
+ property->type = eina_stringshare_add(type);
+
+ const char *access = _eldbus_introspection_attribute_value_get(tag->attributes, "access");
+ EINA_SAFETY_ON_NULL_GOTO(access, error); // required
+ if (strcmp(access, "read") == 0)
+ property->access = ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READ;
+ else
+ if (strcmp(access, "write") == 0)
+ property->access = ELDBUS_INTROSPECTION_PROPERTY_ACCESS_WRITE;
+ else
+ if (strcmp(access, "readwrite") == 0)
+ property->access = ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE;
+ else
+ EINA_SAFETY_ON_TRUE_GOTO(!!"Unknown property access", error);
+
+ Eldbus_Introspection_Element_Parse_Table table[] = {
+ {"annotation", _eldbus_introspection_parse_annotation, &property->annotations},
+ {NULL, NULL, NULL}
+ };
+ _eldbus_introspection_parse_children(tag->children, table);
+
+ return property;
+
+error:
+ _eldbus_introspection_property_free(property);
+ return NULL;
+}
+
+static void
+_eldbus_introspection_property_free(Eldbus_Introspection_Property *property)
+{
+ EINA_SAFETY_ON_NULL_RETURN(property);
+
+ Eldbus_Introspection_Annotation *annotation;
+ EINA_LIST_FREE(property->annotations, annotation)
+ _eldbus_introspection_annotation_free(annotation);
+
+ eina_stringshare_del(property->name);
+ eina_stringshare_del(property->type);
+ free(property);
+}
+
+static void *
+_eldbus_introspection_parse_annotation(Eina_Simple_XML_Node_Tag *tag)
+{
+ Eldbus_Introspection_Annotation *annotation = calloc(1, sizeof(Eldbus_Introspection_Annotation));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(annotation, NULL);
+
+ const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
+ EINA_SAFETY_ON_NULL_GOTO(name, error); // required
+ annotation->name = eina_stringshare_add(name);
+
+ const char *value = _eldbus_introspection_attribute_value_get(tag->attributes, "value");
+ EINA_SAFETY_ON_NULL_GOTO(value, error); // required
+ annotation->value = eina_stringshare_add(value);
+
+ return annotation;
+
+error:
+ _eldbus_introspection_annotation_free(annotation);
+ return NULL;
+}
+
+static void
+_eldbus_introspection_annotation_free(Eldbus_Introspection_Annotation *annotation)
+{
+ EINA_SAFETY_ON_NULL_RETURN(annotation);
+ eina_stringshare_del(annotation->name);
+ eina_stringshare_del(annotation->value);
+ free(annotation);
+}
+
+static void
+_eldbus_introspection_parse_children(Eina_Inlist *children, const Eldbus_Introspection_Element_Parse_Table table[])
+{
+ Eina_Simple_XML_Node *child;
+ EINA_INLIST_FOREACH(children, child)
+ {
+ if (EINA_SIMPLE_XML_NODE_TAG != child->type)
+ continue;
+
+ Eina_Simple_XML_Node_Tag *tag = (Eina_Simple_XML_Node_Tag*)child;
+
+ for (const Eldbus_Introspection_Element_Parse_Table *it = table; it->name; ++it)
+ {
+ if (strcmp(tag->name, it->name) != 0)
+ continue;
+
+ void *item = it->parse(tag);
+ if (item)
+ *it->list = eina_list_append(*it->list, item);
+ }
+ }
+}
+
+EAPI Eldbus_Introspection_Interface *
+eldbus_introspection_interface_find(Eina_List *interfaces, const char *name)
+{
+ Eina_List *it;
+ Eldbus_Introspection_Interface *interface;
+ EINA_LIST_FOREACH(interfaces, it, interface)
+ {
+ if (strcmp(interface->name, name) == 0)
+ return interface;
+ }
+
+ return NULL;
+}
+
+EAPI Eldbus_Introspection_Property *
+eldbus_introspection_property_find(Eina_List *properties, const char *name)
+{
+ Eina_List *it;
+ Eldbus_Introspection_Property *property;
+ EINA_LIST_FOREACH(properties, it, property)
+ {
+ if (strcmp(property->name, name) == 0)
+ return property;
+ }
+
+ return NULL;
+}
+
+EAPI Eldbus_Introspection_Argument *
+eldbus_introspection_argument_find(Eina_List *arguments, const char *name)
+{
+ Eina_List *it;
+ Eldbus_Introspection_Argument *argument;
+ EINA_LIST_FOREACH(arguments, it, argument)
+ {
+ if (strcmp(argument->name, name) == 0)
+ return argument;
+ }
+
+ return NULL;
+}
diff --git a/src/lib/eldbus/eldbus_introspection.h b/src/lib/eldbus/eldbus_introspection.h
new file mode 100644
index 0000000000..4f3746016c
--- /dev/null
+++ b/src/lib/eldbus/eldbus_introspection.h
@@ -0,0 +1,124 @@
+#ifndef _ELDBUS_INTROSPECTION_INTROSPECTION_H
+#define _ELDBUS_INTROSPECTION_INTROSPECTION_H
+
+#include <Eina.h>
+
+// DTD conversion form: http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd
+
+typedef struct _Eldbus_Introspection_Node Eldbus_Introspection_Node;
+typedef struct _Eldbus_Introspection_Interface Eldbus_Introspection_Interface;
+typedef struct _Eldbus_Introspection_Method Eldbus_Introspection_Method;
+typedef struct _Eldbus_Introspection_Signal Eldbus_Introspection_Signal;
+typedef struct _Eldbus_Introspection_Argument Eldbus_Introspection_Argument;
+typedef struct _Eldbus_Introspection_Property Eldbus_Introspection_Property;
+typedef struct _Eldbus_Introspection_Annotation Eldbus_Introspection_Annotation;
+
+typedef enum
+{
+ ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_NONE = 0,
+ ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN,
+ ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_OUT,
+
+} Eldbus_Introspection_Argument_Direction;
+
+typedef enum
+{
+ ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READ,
+ ELDBUS_INTROSPECTION_PROPERTY_ACCESS_WRITE,
+ ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE,
+} Eldbus_Introspection_Property_Access;
+
+struct _Eldbus_Introspection_Node
+{
+ Eina_Stringshare *name; // optional
+ Eina_List *nodes;
+ Eina_List *interfaces;
+};
+
+struct _Eldbus_Introspection_Interface
+{
+ Eina_Stringshare *name;
+ Eina_List *methods;
+ Eina_List *signals;
+ Eina_List *properties;
+ Eina_List *annotations;
+};
+
+struct _Eldbus_Introspection_Method
+{
+ Eina_Stringshare *name;
+ Eina_List *arguments;
+ Eina_List *annotations;
+};
+
+struct _Eldbus_Introspection_Signal
+{
+ Eina_Stringshare *name;
+ Eina_List *arguments;
+ Eina_List *annotations;
+};
+
+struct _Eldbus_Introspection_Argument
+{
+ Eina_Stringshare *name; // optional
+ Eina_Stringshare *type;
+ Eldbus_Introspection_Argument_Direction direction;
+};
+
+struct _Eldbus_Introspection_Property
+{
+ Eina_Stringshare *name;
+ Eina_Stringshare *type;
+ Eldbus_Introspection_Property_Access access;
+ Eina_List *annotations;
+};
+
+struct _Eldbus_Introspection_Annotation
+{
+ Eina_Stringshare *name;
+ Eina_Stringshare *value;
+};
+
+/**
+ * @brief Parses the introspection xml abstracting it to an object tree
+ *
+ * @param xml The introspection xml
+ * @return The introspection object tree
+ */
+EAPI Eldbus_Introspection_Node *eldbus_introspection_parse(const char *xml);
+
+/**
+ * @brief Frees the introspection object tree
+ *
+ * @param node The root node of introspection tree
+ */
+EAPI void eldbus_introspection_node_free(Eldbus_Introspection_Node *node);
+
+/**
+ * @brief Finds an interface by name
+ *
+ * @param interfaces The list of interfaces of type @c Eldbus_Introspection_Interface
+ * @param name The interfaces's name to search for
+ * @return Returns the interface found or @c NULL if not
+ */
+EAPI Eldbus_Introspection_Interface *eldbus_introspection_interface_find(Eina_List *interfaces, const char *name);
+
+/**
+ * @brief Finds a property by name
+ *
+ * @param properties The list of properties of type @c Eldbus_Introspection_Property
+ * @param name The properties's name to search for
+ * @return Returns the property found or @c NULL if not
+ */
+EAPI Eldbus_Introspection_Property *eldbus_introspection_property_find(Eina_List *properties, const char *name);
+
+/**
+ * @brief Finds an argument by name
+ *
+ * @param arguments The list of arguments of type @c Eldbus_Introspection_Property
+ * @param name The arguments's name to search for
+ * @return Returns the argument found or @c NULL if not
+ */
+EAPI Eldbus_Introspection_Argument *eldbus_introspection_argument_find(Eina_List *arguments, const char *name);
+
+#endif
diff --git a/src/lib/eldbus/eldbus_message_from_eina_value.c b/src/lib/eldbus/eldbus_message_from_eina_value.c
index 05bb9f5e41..3d594fb6ab 100644
--- a/src/lib/eldbus/eldbus_message_from_eina_value.c
+++ b/src/lib/eldbus/eldbus_message_from_eina_value.c
@@ -1,6 +1,8 @@
#include "eldbus_private.h"
#include "eldbus_private_types.h"
+#include <dbus/dbus-protocol.h>
+
static Eina_Bool
_compatible_type(int dbus_type, const Eina_Value_Type *value_type)
{
@@ -205,7 +207,7 @@ _array_append(const char *type, const Eina_Value *value_array, Eldbus_Message_It
}
static Eina_Bool
-_basic_append(char type, const Eina_Value *value, const Eina_Value_Struct_Desc *desc, unsigned idx, Eldbus_Message_Iter *iter)
+_basic_append_value_struct(char type, const Eina_Value *value, const Eina_Value_Struct_Desc *desc, unsigned idx, Eldbus_Message_Iter *iter)
{
EINA_SAFETY_ON_FALSE_RETURN_VAL(
_compatible_type(type, desc->members[idx].type), EINA_FALSE);
@@ -305,7 +307,7 @@ _message_iter_from_eina_value_struct(const char *signature, Eldbus_Message_Iter
{
DBG("type: %s", type);
if (type[0] != 'v' && !type[1])
- r = _basic_append(type[0], value, st.desc, i, iter);
+ r = _basic_append_value_struct(type[0], value, st.desc, i, iter);
else if (type[0] == 'a')
{
Eina_Value value_array;
@@ -367,3 +369,121 @@ eldbus_message_from_eina_value(const char *signature, Eldbus_Message *msg, const
return _message_iter_from_eina_value_struct(signature, iter, value);
}
+
+static Eina_Bool
+_basic_append_value(char type, const Eina_Value *value, Eldbus_Message_Iter *iter)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
+ const Eina_Value_Type *value_type = eina_value_type_get(value);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(_compatible_type(type, value_type), EINA_FALSE);
+ switch (type)
+ {
+ case 'i'://int
+ case 'h'://fd
+ {
+ int32_t i;
+ eina_value_get(value, &i);
+ eldbus_message_iter_basic_append(iter, type, i);
+ break;
+ }
+ case 's':
+ case 'o'://object path
+ case 'g'://signature
+ {
+ const char *txt;
+ eina_value_get(value, &txt);
+ eldbus_message_iter_basic_append(iter, type, txt);
+ break;
+ }
+ case 'b'://boolean
+ case 'y'://byte
+ {
+ unsigned char byte;
+ eina_value_get(value, &byte);
+ eldbus_message_iter_basic_append(iter, type, byte);
+ break;
+ }
+ case 'n'://int16
+ {
+ int16_t i;
+ eina_value_get(value, &i);
+ eldbus_message_iter_basic_append(iter, type, i);
+ break;
+ }
+ case 'q'://uint16
+ {
+ uint16_t i;
+ eina_value_get(value, &i);
+ eldbus_message_iter_basic_append(iter, type, i);
+ break;
+ }
+ case 'u'://uint32
+ {
+ uint32_t i;
+ eina_value_get(value, &i);
+ eldbus_message_iter_basic_append(iter, type, i);
+ break;
+ }
+ case 'x'://int64
+ {
+ int64_t i;
+ eina_value_get(value, &i);
+ eldbus_message_iter_basic_append(iter, type, i);
+ break;
+ }
+ case 't'://uint64
+ {
+ uint64_t i;
+ eina_value_get(value, &i);
+ eldbus_message_iter_basic_append(iter, type, i);
+ break;
+ }
+ case 'd'://double
+ {
+ double d;
+ eina_value_get(value, &d);
+ eldbus_message_iter_basic_append(iter, type, d);
+ break;
+ }
+ default:
+ ERR("Unexpected type %c", type);
+ return EINA_FALSE;
+ }
+ return EINA_TRUE;
+}
+
+Eina_Bool
+_message_iter_from_eina_value(const char *signature, Eldbus_Message_Iter *iter, const Eina_Value *value)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
+
+ const Eina_Value_Type *value_type = eina_value_type_get(value);
+ if (EINA_VALUE_TYPE_STRUCT == value_type || EINA_VALUE_TYPE_ARRAY == value_type)
+ return _message_iter_from_eina_value_struct(signature, iter, value);
+
+ Eina_Bool result = EINA_TRUE;
+ DBusSignatureIter signature_iter;
+ dbus_signature_iter_init(&signature_iter, signature);
+ char *type;
+ while ((type = dbus_signature_iter_get_signature(&signature_iter)))
+ {
+ DBG("type: %s", type);
+ if (DBUS_TYPE_VARIANT != type[0] && DBUS_TYPE_INVALID == type[1])
+ result = _basic_append_value(type[0], value, iter);
+ else if (DBUS_TYPE_ARRAY == type[0] ||
+ DBUS_STRUCT_BEGIN_CHAR == type[0] ||
+ DBUS_TYPE_VARIANT == type[0])
+ {
+ ERR("Not a basic type");
+ result = EINA_FALSE;
+ }
+ else
+ {
+ ERR("Unknown type %c", type[0]);
+ result = EINA_FALSE;
+ }
+ dbus_free(type);
+ if (!result || !dbus_signature_iter_next(&signature_iter)) break;
+ }
+ return result;
+}
diff --git a/src/lib/eldbus/eldbus_message_to_eina_value.c b/src/lib/eldbus/eldbus_message_to_eina_value.c
index bac9860b5c..87258bf3d9 100644
--- a/src/lib/eldbus/eldbus_message_to_eina_value.c
+++ b/src/lib/eldbus/eldbus_message_to_eina_value.c
@@ -3,7 +3,7 @@
static void _message_iter_basic_array_to_eina_value(char type, Eina_Value *value, Eldbus_Message_Iter *iter);
-static const Eina_Value_Type *
+const Eina_Value_Type *
_dbus_type_to_eina_value_type(char type)
{
switch (type)
diff --git a/src/lib/eldbus/eldbus_model_arguments.c b/src/lib/eldbus/eldbus_model_arguments.c
new file mode 100644
index 0000000000..135e66cab7
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_arguments.c
@@ -0,0 +1,421 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_model_arguments_private.h"
+#include "eldbus_model_private.h"
+
+#include <Eina.h>
+#include <Eldbus.h>
+
+#define MY_CLASS ELDBUS_MODEL_ARGUMENTS_CLASS
+#define MY_CLASS_NAME "Eldbus_Model_Arguments"
+
+#define ARGUMENT_FORMAT "arg%u"
+
+static void _eldbus_model_arguments_efl_model_base_properties_load(Eo *, Eldbus_Model_Arguments_Data *);
+static void _eldbus_model_arguments_efl_model_base_children_load(Eo *, Eldbus_Model_Arguments_Data *);
+static void _eldbus_model_arguments_unload(Eldbus_Model_Arguments_Data *);
+static bool _eldbus_model_arguments_is_input_argument(Eldbus_Model_Arguments_Data *, const char *);
+static bool _eldbus_model_arguments_is_output_argument(Eldbus_Model_Arguments_Data *, const char *);
+static bool _eldbus_model_arguments_property_set(Eldbus_Model_Arguments_Data *, Eina_Value *, const char *);
+static unsigned int _eldbus_model_arguments_argument_index_get(Eldbus_Model_Arguments_Data *, const char *);
+static void _eldbus_model_arguments_member_setup_cb(void *data, int index, Eina_Value_Struct_Member *member);
+
+static Eo_Base*
+_eldbus_model_arguments_eo_base_constructor(Eo *obj, Eldbus_Model_Arguments_Data *pd)
+{
+ DBG("(%p)", obj);
+ obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
+
+ pd->obj = obj;
+ pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
+ pd->properties_array = NULL;
+ pd->properties_desc = NULL;
+ pd->properties = NULL;
+ pd->pending_list = NULL;
+ pd->proxy = NULL;
+ pd->arguments = NULL;
+ pd->name = NULL;
+ return obj;
+}
+
+static void
+_eldbus_model_arguments_constructor(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Arguments_Data *pd,
+ Eldbus_Proxy *proxy,
+ const char *name,
+ const Eina_List *arguments)
+{
+ DBG("(%p)", obj);
+ EINA_SAFETY_ON_NULL_RETURN(proxy);
+ EINA_SAFETY_ON_NULL_RETURN(name);
+
+ pd->proxy = eldbus_proxy_ref(proxy);
+ pd->arguments = arguments;
+ pd->name = eina_stringshare_add(name);
+}
+
+static void
+_eldbus_model_arguments_eo_base_destructor(Eo *obj, Eldbus_Model_Arguments_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ _eldbus_model_arguments_unload(pd);
+
+ eina_value_free(pd->properties);
+ efl_model_value_struct_desc_free(pd->properties_desc);
+
+ eina_stringshare_del(pd->name);
+ eldbus_proxy_unref(pd->proxy);
+
+ eo_do_super(obj, MY_CLASS, eo_destructor());
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_arguments_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Arguments_Data *pd,
+ Eina_Array * const* properties_array)
+{
+ DBG("(%p)", obj);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
+ {
+ ERR("%s", "o not loaded.");
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+ }
+
+ *(Eina_Array**)properties_array = pd->properties_array;
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_arguments_efl_model_base_properties_load(Eo *obj, Eldbus_Model_Arguments_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
+ return;
+
+ unsigned int arguments_count = eina_list_count(pd->arguments);
+
+ pd->properties_array = eina_array_new(arguments_count);
+ EINA_SAFETY_ON_NULL_RETURN(pd->properties_array);
+
+ for (unsigned int i = 0; i < arguments_count; ++i)
+ {
+ Eina_Stringshare *name = eina_stringshare_printf(ARGUMENT_FORMAT, i);
+ EINA_SAFETY_ON_NULL_RETURN(name);
+
+ Eina_Bool ret = eina_array_push(pd->properties_array, name);
+ EINA_SAFETY_ON_FALSE_RETURN(ret);
+ }
+
+ if (arguments_count > 0)
+ {
+ if (!pd->properties_desc)
+ {
+ pd->properties_desc = efl_model_value_struct_desc_new(
+ arguments_count,
+ _eldbus_model_arguments_member_setup_cb,
+ pd);
+ }
+
+ pd->properties = eina_value_struct_new(pd->properties_desc);
+ }
+
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_arguments_efl_model_base_property_set(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Arguments_Data *pd,
+ const char *property,
+ Eina_Value const* value)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
+ DBG("(%p): property=%s", obj, property);
+
+ if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+
+ if (!_eldbus_model_arguments_is_input_argument(pd, property))
+ {
+ WRN("Property (argument) not found or it is for output only: %s", property);
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+ }
+
+ // TODO:
+ //Eina_Bool ret = eina_value_struct_value_set(pd->properties, property, &value);
+ //EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ return pd->load.status;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_arguments_efl_model_base_property_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Arguments_Data *pd,
+ const char *property,
+ Eina_Value const ** value)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
+ DBG("(%p): property=%s", obj, property);
+
+ if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+
+ if (!_eldbus_model_arguments_is_output_argument(pd, property))
+ {
+ WRN("Property (argument) not found or it is for input only: %s", property);
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+ }
+
+ Eina_Bool ret = eina_value_struct_value_get(pd->properties, property, &pd->tmp_value);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ *value = &pd->tmp_value;
+
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_arguments_efl_model_base_load(Eo *obj, Eldbus_Model_Arguments_Data *pd EINA_UNUSED)
+{
+ DBG("(%p)", obj);
+
+ eo_do(obj, efl_model_properties_load());
+ eo_do(obj, efl_model_children_load());
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_arguments_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd)
+{
+ DBG("(%p)", obj);
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_arguments_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ _eldbus_model_arguments_unload(pd);
+
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
+}
+
+Eo *
+_eldbus_model_arguments_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd EINA_UNUSED)
+{
+ DBG("(%p)", obj);
+ return NULL;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_arguments_efl_model_base_child_del(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Arguments_Data *pd EINA_UNUSED,
+ Eo *child EINA_UNUSED)
+{
+ DBG("(%p)", obj);
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_arguments_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Arguments_Data *pd,
+ unsigned start EINA_UNUSED,
+ unsigned count EINA_UNUSED,
+ Eina_Accessor **children_accessor)
+{
+ DBG("(%p)", obj);
+ *children_accessor = NULL;
+ return pd->load.status;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_arguments_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Arguments_Data *pd,
+ unsigned *children_count)
+{
+ DBG("(%p)", obj);
+ *children_count = 0;
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_arguments_efl_model_base_children_load(Eo *obj, Eldbus_Model_Arguments_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
+ return;
+
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+}
+
+static const char *
+_eldbus_model_arguments_name_get(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd)
+{
+ return pd->name;
+}
+
+static void
+_eldbus_model_arguments_unload(Eldbus_Model_Arguments_Data *pd)
+{
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+
+ Eldbus_Pending *pending;
+ EINA_LIST_FREE(pd->pending_list, pending)
+ eldbus_pending_cancel(pending);
+
+ if (pd->properties_array)
+ {
+ unsigned int i;
+ Eina_Stringshare *property;
+ Eina_Array_Iterator it;
+ EINA_ARRAY_ITER_NEXT(pd->properties_array, i, property, it)
+ eina_stringshare_del(property);
+ eina_array_free(pd->properties_array);
+ pd->properties_array = NULL;
+ }
+
+ eina_value_free(pd->properties);
+ pd->properties = NULL;
+}
+
+bool
+eldbus_model_arguments_process_arguments(Eldbus_Model_Arguments_Data *pd,
+ const Eldbus_Message *msg,
+ Eldbus_Pending *pending)
+{
+ DBG("(%p)", pd->obj);
+
+ pd->pending_list = eina_list_remove(pd->pending_list, pending);
+
+ const char *error_name, *error_text;
+ if (eldbus_message_error_get(msg, &error_name, &error_text))
+ {
+ ERR("%s: %s", error_name, error_text);
+ efl_model_error_notify(pd->obj);
+ return false;
+ }
+
+ Eina_Value *value_struct = eldbus_message_to_eina_value(msg);
+ if (NULL == value_struct)
+ {
+ INF("%s", "No output arguments");
+ return true;
+ }
+
+ bool result = false, changed = false;
+ unsigned int i = 0;
+ const Eina_List *it;
+ const Eldbus_Introspection_Argument *argument;
+ EINA_LIST_FOREACH(pd->arguments, it, argument)
+ {
+ if (ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN != argument->direction)
+ {
+ const Eina_Stringshare *property = eina_array_data_get(pd->properties_array, i);
+ EINA_SAFETY_ON_NULL_GOTO(property, on_error);
+
+ bool ret = _eldbus_model_arguments_property_set(pd, value_struct, property);
+ EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
+
+ changed = true;
+ }
+
+ ++i;
+ }
+
+ if (changed)
+ {
+ Efl_Model_Property_Event evt = {.changed_properties = pd->properties};
+ eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
+ }
+
+ result = true;
+
+on_error:
+ eina_value_free(value_struct);
+ return result;
+}
+
+static bool
+_eldbus_model_arguments_property_set(Eldbus_Model_Arguments_Data *pd,
+ Eina_Value *value_struct,
+ const char *property)
+{
+ Eina_Value value = {0};
+
+ Eina_Bool ret = eina_value_struct_value_get(value_struct, "arg0", &value);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
+
+ ret = eina_value_struct_value_set(pd->properties, property, &value);
+ eina_value_flush(&value);
+ return ret;
+}
+
+static bool
+_eldbus_model_arguments_is_input_argument(Eldbus_Model_Arguments_Data *pd, const char *argument)
+{
+ const unsigned int i = _eldbus_model_arguments_argument_index_get(pd, argument);
+ if (i >= eina_array_count(pd->properties_array))
+ {
+ WRN("Argument not found: %s", argument);
+ return false;
+ }
+
+ Eldbus_Introspection_Argument *argument_introspection =
+ eina_list_nth(pd->arguments, i);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(argument_introspection, false);
+
+ return ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN == argument_introspection->direction;
+}
+
+static bool
+_eldbus_model_arguments_is_output_argument(Eldbus_Model_Arguments_Data *pd, const char *argument)
+{
+ const unsigned int i = _eldbus_model_arguments_argument_index_get(pd, argument);
+ if (i >= eina_array_count(pd->properties_array))
+ {
+ WRN("Argument not found: %s", argument);
+ return false;
+ }
+
+ Eldbus_Introspection_Argument *argument_introspection =
+ eina_list_nth(pd->arguments, i);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(argument_introspection, false);
+
+ return ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN != argument_introspection->direction;
+}
+
+static unsigned int
+_eldbus_model_arguments_argument_index_get(Eldbus_Model_Arguments_Data *pd, const char *argument)
+{
+ unsigned int i = 0;
+ const Eina_Stringshare *name;
+ Eina_Array_Iterator it;
+ EINA_ARRAY_ITER_NEXT(pd->properties_array, i, name, it)
+ {
+ if (strcmp(name, argument) == 0)
+ return i;
+ }
+
+ return ++i;
+}
+
+static void
+_eldbus_model_arguments_member_setup_cb(void *data, int index, Eina_Value_Struct_Member *member)
+{
+ Eldbus_Model_Arguments_Data *pd = (Eldbus_Model_Arguments_Data*)data;
+
+ member->name = eina_stringshare_ref(eina_array_data_get(pd->properties_array, index));
+
+ Eldbus_Introspection_Argument *arg = eina_list_nth(pd->arguments, index);
+ member->type = _dbus_type_to_eina_value_type(arg->type[0]);
+}
+
+#include "eldbus_model_arguments.eo.c"
diff --git a/src/lib/eldbus/eldbus_model_arguments.eo b/src/lib/eldbus/eldbus_model_arguments.eo
new file mode 100644
index 0000000000..64f39f9ce2
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_arguments.eo
@@ -0,0 +1,40 @@
+class Eldbus.Model_Arguments (Eo.Base, Efl.Model.Base) {
+ legacy_prefix: null;
+ methods {
+ constructor {
+ [[Custom Eldbus_Model_Arguments constructor.
+
+ @since 1.16]]
+ params {
+ @in proxy: Eldbus_Proxy*; [[Eldbus proxy]]
+ @in name: const(char)*; [[Name]]
+ @in arguments: const(Eina_List)*; [[The introspected arguments]]
+ }
+ }
+ @property name {
+ get {}
+ values {
+ value: const(char)*;
+ }
+ }
+ }
+ implements {
+ Eo.Base.constructor;
+ Eo.Base.destructor;
+ Efl.Model.Base.properties.get;
+ Efl.Model.Base.properties_load;
+ Efl.Model.Base.property.set;
+ Efl.Model.Base.property.get;
+ Efl.Model.Base.load;
+ Efl.Model.Base.load_status.get;
+ Efl.Model.Base.unload;
+ Efl.Model.Base.child_add;
+ Efl.Model.Base.child_del;
+ Efl.Model.Base.children_slice.get;
+ Efl.Model.Base.children_count.get;
+ Efl.Model.Base.children_load;
+ }
+ constructors {
+ .constructor;
+ }
+}
diff --git a/src/lib/eldbus/eldbus_model_arguments_private.h b/src/lib/eldbus/eldbus_model_arguments_private.h
new file mode 100644
index 0000000000..1181c1af43
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_arguments_private.h
@@ -0,0 +1,30 @@
+#ifndef _ELDBUS_MODEL_ARGUMENTS_PRIVATE_H
+#define _ELDBUS_MODEL_ARGUMENTS_PRIVATE_H
+
+#include "Eldbus_Model.h"
+
+#include <stdbool.h>
+
+typedef struct _Eldbus_Model_Arguments_Data Eldbus_Model_Arguments_Data;
+
+/**
+ * eldbus_model_arguments
+ */
+struct _Eldbus_Model_Arguments_Data
+{
+ Eo *obj;
+ Efl_Model_Load load;
+ Eldbus_Proxy *proxy;
+ Eina_Array *properties_array;
+ Eina_Value_Struct_Desc *properties_desc;
+ Eina_Value *properties;
+ Eina_Stringshare *name;
+ Eina_List *pending_list;
+ const Eina_List *arguments;
+ Eina_Value tmp_value;
+};
+
+bool eldbus_model_arguments_process_arguments(Eldbus_Model_Arguments_Data *, const Eldbus_Message *, Eldbus_Pending *);
+
+#endif
+
diff --git a/src/lib/eldbus/eldbus_model_connection.c b/src/lib/eldbus/eldbus_model_connection.c
new file mode 100644
index 0000000000..427c0109b9
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_connection.c
@@ -0,0 +1,368 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_model_connection_private.h"
+#include "eldbus_model_private.h"
+
+#define MY_CLASS ELDBUS_MODEL_CONNECTION_CLASS
+#define MY_CLASS_NAME "Eldbus_Model_Connection"
+
+#define UNIQUE_NAME_PROPERTY "unique_name"
+
+static void _eldbus_model_connection_efl_model_base_properties_load(Eo *, Eldbus_Model_Connection_Data *);
+static void _eldbus_model_connection_efl_model_base_children_load(Eo *, Eldbus_Model_Connection_Data *);
+static void _eldbus_model_connection_names_list_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
+static void _eldbus_model_connection_connect(Eldbus_Model_Connection_Data *);
+static void _eldbus_model_connection_disconnect(Eldbus_Model_Connection_Data *);
+static void _eldbus_model_connection_unload(Eldbus_Model_Connection_Data *);
+
+static Eo_Base*
+_eldbus_model_connection_eo_base_constructor(Eo *obj, Eldbus_Model_Connection_Data *pd)
+{
+ DBG("(%p)", obj);
+ obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
+
+ pd->obj = obj;
+ pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
+ pd->connection = NULL;
+ pd->properties_array = NULL;
+ pd->children_list = NULL;
+ pd->type = ELDBUS_CONNECTION_TYPE_UNKNOWN;
+ pd->address = NULL;
+ pd->private = false;
+ pd->unique_name = NULL;
+ pd->pending_list = NULL;
+
+ return obj;
+}
+
+static void
+_eldbus_model_connection_constructor(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Connection_Data *pd,
+ int type,
+ const char* address,
+ Eina_Bool private)
+{
+ DBG("(%p)", obj);
+
+ pd->type = type;
+ pd->address = eina_stringshare_add(address);
+ pd->private = private;
+}
+
+static void
+_eldbus_model_connection_eo_base_destructor(Eo *obj, Eldbus_Model_Connection_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ eina_stringshare_del(pd->address);
+
+ _eldbus_model_connection_unload(pd);
+
+ eo_do_super(obj, MY_CLASS, eo_destructor());
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_connection_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Connection_Data *pd,
+ Eina_Array * const* properties_array)
+{
+ DBG("(%p)", obj);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ if (NULL == pd->properties_array)
+ {
+ pd->properties_array = eina_array_new(1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd->properties_array, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ Eina_Bool ret = eina_array_push(pd->properties_array, UNIQUE_NAME_PROPERTY);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
+ }
+
+ *(Eina_Array**)properties_array = pd->properties_array;
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_connection_efl_model_base_properties_load(Eo *obj, Eldbus_Model_Connection_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
+ return;
+
+ if (!pd->connection)
+ _eldbus_model_connection_connect(pd);
+
+ pd->unique_name = eina_stringshare_add(eldbus_connection_unique_name_get(pd->connection));
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_connection_efl_model_base_property_set(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Connection_Data *pd EINA_UNUSED,
+ const char *property EINA_UNUSED,
+ Eina_Value const* value EINA_UNUSED)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
+ DBG("(%p): property=%s", obj, property);
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_connection_efl_model_base_property_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Connection_Data *pd,
+ const char *property,
+ Eina_Value const **value)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
+ DBG("(%p): property=%s", obj, property);
+
+ if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+
+ if (strcmp(property, UNIQUE_NAME_PROPERTY) != 0)
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+
+ eina_value_setup(value, EINA_VALUE_TYPE_STRING);
+ eina_value_set(value, pd->unique_name);
+
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_connection_efl_model_base_load(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ if (!pd->connection)
+ _eldbus_model_connection_connect(pd);
+
+ _eldbus_model_connection_efl_model_base_properties_load(obj, pd);
+ _eldbus_model_connection_efl_model_base_children_load(obj, pd);
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_connection_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
+{
+ DBG("(%p)", obj);
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_connection_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ _eldbus_model_connection_unload(pd);
+
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
+}
+
+Eo *
+_eldbus_model_connection_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd EINA_UNUSED)
+{
+ DBG("(%p)", obj);
+ return NULL;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_connection_efl_model_base_child_del(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Connection_Data *pd EINA_UNUSED,
+ Eo *child EINA_UNUSED)
+{
+ DBG("(%p)", obj);
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_connection_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Connection_Data *pd,
+ unsigned start,
+ unsigned count,
+ Eina_Accessor **children_accessor)
+{
+ DBG("(%p)", obj);
+
+ if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
+ {
+ WRN("(%p): Children not loaded", obj);
+ *children_accessor = NULL;
+ return pd->load.status;
+ }
+
+ *children_accessor = efl_model_list_slice(pd->children_list, start, count);
+ return pd->load.status;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_connection_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Connection_Data *pd,
+ unsigned *children_count)
+{
+ DBG("(%p)", obj);
+ *children_count = eina_list_count(pd->children_list);
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_connection_efl_model_base_children_load(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
+ return;
+
+ if (!pd->connection)
+ _eldbus_model_connection_connect(pd);
+
+ Eldbus_Pending *pending = eldbus_names_list(pd->connection, &_eldbus_model_connection_names_list_cb, pd);
+ pd->pending_list = eina_list_append(pd->pending_list, pending);
+
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
+}
+
+static const char *
+_eldbus_model_connection_address_get(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
+{
+ return pd->address;
+}
+
+static void
+_eldbus_model_connection_address_set(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd, const char *value)
+{
+ eina_stringshare_del(pd->address);
+ pd->address = eina_stringshare_add(value);
+}
+
+static Eina_Bool
+_eldbus_model_connection_private_get(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
+{
+ return pd->private;
+}
+
+static void
+_eldbus_model_connection_private_set(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd, Eina_Bool value)
+{
+ pd->private = value;
+}
+
+static int
+_eldbus_model_connection_type_get(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
+{
+ return pd->type;
+}
+
+static void
+_eldbus_model_connection_type_set(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd, int value)
+{
+ pd->type = value;
+}
+
+static void
+_eldbus_model_connection_connect(Eldbus_Model_Connection_Data *pd)
+{
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+
+ if (ELDBUS_CONNECTION_TYPE_ADDRESS == pd->type)
+ {
+ if (pd->private)
+ pd->connection = eldbus_address_connection_get(pd->address);
+ else
+ pd->connection = eldbus_private_address_connection_get(pd->address);
+ }
+ else
+ {
+ if (pd->private)
+ pd->connection = eldbus_private_connection_get(pd->type);
+ else
+ pd->connection = eldbus_connection_get(pd->type);
+ }
+
+ // TODO: Register for disconnection event
+
+ EINA_SAFETY_ON_FALSE_RETURN(NULL != pd->connection);
+}
+
+static void
+_eldbus_model_connection_disconnect(Eldbus_Model_Connection_Data *pd)
+{
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+ eldbus_connection_unref(pd->connection);
+ pd->connection = NULL;
+}
+
+static void
+_eldbus_model_connection_unload(Eldbus_Model_Connection_Data *pd)
+{
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+ if (!pd->connection)
+ return;
+
+ eina_stringshare_del(pd->unique_name);
+ pd->unique_name = NULL;
+
+ Eo *child;
+ EINA_LIST_FREE(pd->children_list, child)
+ eo_unref(child);
+
+ Eldbus_Pending *pending;
+ EINA_LIST_FREE(pd->pending_list, pending)
+ eldbus_pending_cancel(pending);
+
+ if (pd->properties_array)
+ {
+ eina_array_free(pd->properties_array);
+ pd->properties_array = NULL;
+ }
+
+ _eldbus_model_connection_disconnect(pd);
+}
+
+static void
+_eldbus_model_connection_names_list_cb(void *data,
+ const Eldbus_Message *msg,
+ Eldbus_Pending *pending)
+{
+ Eldbus_Model_Connection_Data *pd = (Eldbus_Model_Connection_Data*)data;
+ DBG("(%p)", pd->obj);
+
+ pd->pending_list = eina_list_remove(pd->pending_list, pending);
+
+ const char *error_name, *error_text;
+ if (eldbus_message_error_get(msg, &error_name, &error_text))
+ {
+ ERR("%s: %s", error_name, error_text);
+ efl_model_error_notify(pd->obj);
+ return;
+ }
+
+ Eldbus_Message_Iter *array = NULL;
+ if (!eldbus_message_arguments_get(msg, "as", &array))
+ {
+ ERR("%s", "Error getting arguments.");
+ return;
+ }
+
+ const char *bus;
+ while (eldbus_message_iter_get_and_next(array, 's', &bus))
+ {
+ DBG("(%p): bus = %s", pd->obj, bus);
+
+ Eo *child = eo_add(ELDBUS_MODEL_OBJECT_CLASS, NULL,
+ eldbus_model_object_connection_constructor(pd->connection, bus, "/"));
+
+ pd->children_list = eina_list_append(pd->children_list, child);
+ }
+
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ unsigned int count = eina_list_count(pd->children_list);
+ if (count)
+ eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
+}
+
+#include "eldbus_model_connection.eo.c"
diff --git a/src/lib/eldbus/eldbus_model_connection.eo b/src/lib/eldbus/eldbus_model_connection.eo
new file mode 100644
index 0000000000..d1e00504a2
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_connection.eo
@@ -0,0 +1,49 @@
+class Eldbus.Model_Connection (Eo.Base, Efl.Model.Base) {
+ legacy_prefix: null;
+ methods {
+ constructor {
+ [[Custom Eldbus_Model_Connection constructor.
+
+ @since 1.16]]
+ params {
+ @in type: int; [[The connection type]]
+ @in address: const(char)*; [[Remote address of dbus]]
+ @in private: bool; [[Non shared dbus connection]]
+ }
+ }
+ @property type {
+ values {
+ value: int;
+ }
+ }
+ @property address {
+ values {
+ value: const(char)*;
+ }
+ }
+ @property private {
+ values {
+ value: bool;
+ }
+ }
+ }
+ implements {
+ Eo.Base.constructor;
+ Eo.Base.destructor;
+ Efl.Model.Base.properties.get;
+ Efl.Model.Base.properties_load;
+ Efl.Model.Base.property.set;
+ Efl.Model.Base.property.get;
+ Efl.Model.Base.load;
+ Efl.Model.Base.load_status.get;
+ Efl.Model.Base.unload;
+ Efl.Model.Base.child_add;
+ Efl.Model.Base.child_del;
+ Efl.Model.Base.children_slice.get;
+ Efl.Model.Base.children_count.get;
+ Efl.Model.Base.children_load;
+ }
+ constructors {
+ .constructor;
+ }
+}
diff --git a/src/lib/eldbus/eldbus_model_connection_private.h b/src/lib/eldbus/eldbus_model_connection_private.h
new file mode 100644
index 0000000000..1eff30b76c
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_connection_private.h
@@ -0,0 +1,28 @@
+#ifndef _ELDBUS_MODEL_CONNECTION_PRIVATE_H
+#define _ELDBUS_MODEL_CONNECTION_PRIVATE_H
+
+#include "Eldbus_Model.h"
+
+#include <stdbool.h>
+
+typedef struct _Eldbus_Model_Connection_Data Eldbus_Model_Connection_Data;
+
+/**
+ * eldbus_model_connection
+ */
+struct _Eldbus_Model_Connection_Data
+{
+ Eo *obj;
+ Efl_Model_Load load;
+ Eldbus_Connection *connection;
+ Eina_Array *properties_array;
+ Eina_List *children_list;
+ Eldbus_Connection_Type type;
+ Eina_Stringshare *address;
+ bool private;
+ Eina_Stringshare *unique_name;
+ Eina_List *pending_list;
+};
+
+#endif
+
diff --git a/src/lib/eldbus/eldbus_model_method.c b/src/lib/eldbus/eldbus_model_method.c
new file mode 100644
index 0000000000..5d9804ea67
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_method.c
@@ -0,0 +1,105 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_model_arguments_private.h"
+#include "eldbus_model_method_private.h"
+#include "eldbus_model_private.h"
+#include "eldbus_proxy.h"
+
+#include <Eina.h>
+
+#include <stdbool.h>
+
+#define MY_CLASS ELDBUS_MODEL_METHOD_CLASS
+#define MY_CLASS_NAME "Eldbus_Model_Method"
+
+static void _eldbus_model_method_call_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
+
+static Eo_Base*
+_eldbus_model_method_eo_base_constructor(Eo *obj, Eldbus_Model_Method_Data *pd)
+{
+ DBG("(%p)", obj);
+ obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
+
+ pd->obj = obj;
+ pd->method = NULL;
+ return obj;
+}
+
+static void
+_eldbus_model_method_constructor(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Method_Data *pd,
+ Eldbus_Proxy *proxy,
+ const Eldbus_Introspection_Method *method)
+{
+ DBG("(%p)", obj);
+ EINA_SAFETY_ON_NULL_RETURN(proxy);
+ EINA_SAFETY_ON_NULL_RETURN(method);
+ eo_do_super(obj, MY_CLASS, eldbus_model_arguments_constructor(proxy, method->name, method->arguments));
+
+ pd->method = method;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_method_call(Eo *obj EINA_UNUSED, Eldbus_Model_Method_Data *pd EINA_UNUSED)
+{
+ DBG("(%p)", obj);
+ Eldbus_Model_Arguments_Data *data = eo_data_scope_get(obj, ELDBUS_MODEL_ARGUMENTS_CLASS);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ Eldbus_Message *msg = eldbus_proxy_method_call_new(data->proxy, data->name);
+ Eldbus_Message_Iter *iter = eldbus_message_iter_get(msg);
+
+ unsigned int i = 0;
+ const Eina_List *it;
+ const Eldbus_Introspection_Argument *argument;
+ EINA_LIST_FOREACH(data->arguments, it, argument)
+ {
+ if (ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN != argument->direction)
+ continue;
+
+ const Eina_Stringshare *name = eina_array_data_get(data->properties_array, i);
+ EINA_SAFETY_ON_NULL_GOTO(name, on_error);
+
+ Eina_Value value = {0};
+ Eina_Bool ret = eina_value_struct_value_get(data->properties, name, &value);
+ EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
+
+ const char *signature = argument->type;
+ if (dbus_type_is_basic(signature[0]))
+ ret = _message_iter_from_eina_value(signature, iter, &value);
+ else
+ ret = _message_iter_from_eina_value_struct(signature, iter, &value);
+
+ eina_value_flush(&value);
+
+ EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
+
+ ++i;
+ }
+
+ Eldbus_Pending *pending = eldbus_proxy_send(data->proxy, msg, _eldbus_model_method_call_cb, pd, -1);
+ data->pending_list = eina_list_append(data->pending_list, pending);
+
+ return data->load.status;
+
+on_error:
+ eldbus_message_unref(msg);
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+}
+
+static void
+_eldbus_model_method_call_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
+{
+ Eldbus_Model_Method_Data *pd = (Eldbus_Model_Method_Data*)data;
+ DBG("(%p)", pd->obj);
+
+ Eldbus_Model_Arguments_Data *args_data = eo_data_scope_get(pd->obj, ELDBUS_MODEL_ARGUMENTS_CLASS);
+ EINA_SAFETY_ON_NULL_RETURN(args_data);
+
+ if (eldbus_model_arguments_process_arguments(args_data, msg, pending))
+ eo_do(pd->obj, eo_event_callback_call(ELDBUS_MODEL_METHOD_EVENT_SUCCESSFUL_CALL, NULL));
+}
+
+#include "eldbus_model_method.eo.c"
diff --git a/src/lib/eldbus/eldbus_model_method.eo b/src/lib/eldbus/eldbus_model_method.eo
new file mode 100644
index 0000000000..8b9d71411f
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_method.eo
@@ -0,0 +1,35 @@
+class Eldbus.Model_Method (Eldbus.Model_Arguments) {
+ legacy_prefix: null;
+ methods {
+ constructor {
+ [[Custom Eldbus_Model_Method constructor.
+
+ @since 1.16]]
+ params {
+ @in proxy: Eldbus_Proxy*; [[Eldbus proxy]]
+ @in method: const(Eldbus_Introspection_Method)*; [[The introspected method]]
+ }
+ }
+ call {
+ [[Calls the method. The properties must have been set.
+
+ The event EMODEL_EVENT_PROPERTIES_CHANGED is raised for output arguments (properties).
+
+ The event ELDBUS_MODEL_METHOD_EVENT_METHOD_CALLED is raised for a successful call. Otherwise
+ the event EMODEL_EVENT_LOAD_STATUS with the status set to EMODEL_LOAD_STATUS_ERROR is raised.
+
+ @since 1.16]]
+ return: Efl.Model.Load_Status; [[#Emodel_Load_Status on success, #EMODEL_LOAD_STATUS_ERROR otherwise.]]
+ }
+ }
+ implements {
+ Eo.Base.constructor;
+ }
+ constructors {
+ .constructor;
+ }
+ events {
+ successful,call; [[Event dispatched for a successful method call.]]
+ }
+
+}
diff --git a/src/lib/eldbus/eldbus_model_method_private.h b/src/lib/eldbus/eldbus_model_method_private.h
new file mode 100644
index 0000000000..5092b50b53
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_method_private.h
@@ -0,0 +1,18 @@
+#ifndef _ELDBUS_MODEL_METHOD_PRIVATE_H
+#define _ELDBUS_MODEL_METHOD_PRIVATE_H
+
+#include "Eldbus_Model.h"
+
+typedef struct _Eldbus_Model_Method_Data Eldbus_Model_Method_Data;
+
+/**
+ * eldbus_model_method
+ */
+struct _Eldbus_Model_Method_Data
+{
+ Eo *obj;
+ const Eldbus_Introspection_Method *method;
+};
+
+#endif
+
diff --git a/src/lib/eldbus/eldbus_model_object.c b/src/lib/eldbus/eldbus_model_object.c
new file mode 100644
index 0000000000..0cf462c380
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_object.c
@@ -0,0 +1,542 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_model_object_private.h"
+#include "eldbus_model_private.h"
+
+#include <Eina.h>
+
+#define MY_CLASS ELDBUS_MODEL_OBJECT_CLASS
+#define MY_CLASS_NAME "Eldbus_Model_Object"
+
+#define UNIQUE_NAME_PROPERTY "unique_name"
+
+static void _eldbus_model_object_efl_model_base_properties_load(Eo *, Eldbus_Model_Object_Data *);
+static void _eldbus_model_object_efl_model_base_children_load(Eo *, Eldbus_Model_Object_Data *);
+static bool _eldbus_model_object_introspect(Eldbus_Model_Object_Data *, const char *, const char *);
+static void _eldbus_model_object_introspect_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
+static void _eldbus_model_object_connect(Eldbus_Model_Object_Data *);
+static void _eldbus_model_object_disconnect(Eldbus_Model_Object_Data *);
+static void _eldbus_model_object_unload(Eldbus_Model_Object_Data *);
+static void _eldbus_model_object_introspect_nodes(Eldbus_Model_Object_Data *, const char *, Eina_List *);
+static char *_eldbus_model_object_concatenate_path(const char *, const char *);
+static void _eldbus_model_object_create_children(Eldbus_Model_Object_Data *, Eldbus_Object *, Eina_List *);
+
+static Eo_Base*
+_eldbus_model_object_eo_base_constructor(Eo *obj, Eldbus_Model_Object_Data *pd)
+{
+ DBG("(%p)", obj);
+ obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
+
+ pd->obj = obj;
+ pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
+ pd->connection = NULL;
+ pd->object_list = NULL;
+ pd->properties_array = NULL;
+ pd->children_list = NULL;
+ pd->type = ELDBUS_CONNECTION_TYPE_UNKNOWN;
+ pd->address = NULL;
+ pd->private = false;
+ pd->bus = NULL;
+ pd->path = NULL;
+ pd->unique_name = NULL;
+ pd->pending_list = NULL;
+ pd->introspection = NULL;
+
+ return obj;
+}
+
+static void
+_eldbus_model_object_constructor(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Object_Data *pd,
+ int type,
+ const char* address,
+ Eina_Bool private,
+ const char* bus,
+ const char* path)
+{
+ DBG("(%p)", obj);
+ EINA_SAFETY_ON_NULL_RETURN(bus);
+ EINA_SAFETY_ON_NULL_RETURN(path);
+
+ pd->type = type;
+ pd->address = eina_stringshare_add(address);
+ pd->private = private;
+ pd->bus = eina_stringshare_add(bus);
+ pd->path = eina_stringshare_add(path);
+}
+
+static void
+_eldbus_model_object_connection_constructor(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Object_Data *pd,
+ Eldbus_Connection *connection,
+ const char* bus,
+ const char* path)
+{
+ DBG("(%p)", obj);
+ EINA_SAFETY_ON_NULL_RETURN(connection);
+ EINA_SAFETY_ON_NULL_RETURN(bus);
+ EINA_SAFETY_ON_NULL_RETURN(path);
+
+ pd->connection = eldbus_connection_ref(connection);
+ pd->bus = eina_stringshare_add(bus);
+ pd->path = eina_stringshare_add(path);
+}
+
+static void
+_eldbus_model_object_eo_base_destructor(Eo *obj, Eldbus_Model_Object_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ eina_stringshare_del(pd->address);
+ eina_stringshare_del(pd->bus);
+ eina_stringshare_del(pd->path);
+
+ _eldbus_model_object_unload(pd);
+
+ eo_do_super(obj, MY_CLASS, eo_destructor());
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_object_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Object_Data *pd,
+ Eina_Array * const* properties_array)
+{
+ DBG("(%p)", obj);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ if (NULL == pd->properties_array)
+ {
+ pd->properties_array = eina_array_new(1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd->properties_array, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ Eina_Bool ret = eina_array_push(pd->properties_array, UNIQUE_NAME_PROPERTY);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
+ }
+
+ *(Eina_Array**)properties_array = pd->properties_array;
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_object_efl_model_base_properties_load(Eo *obj, Eldbus_Model_Object_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
+ return;
+
+ if (!pd->connection)
+ _eldbus_model_object_connect(pd);
+
+ pd->unique_name = eina_stringshare_add(eldbus_connection_unique_name_get(pd->connection));
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_object_efl_model_base_property_set(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Object_Data *pd EINA_UNUSED,
+ const char *property EINA_UNUSED,
+ Eina_Value const* value EINA_UNUSED)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
+ DBG("(%p): property=%s", obj, property);
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_object_efl_model_base_property_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Object_Data *pd,
+ const char *property,
+ Eina_Value const**value)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
+ DBG("(%p): property=%s", obj, property);
+
+ if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+
+ if (strcmp(property, UNIQUE_NAME_PROPERTY) != 0)
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+
+ eina_value_setup(value, EINA_VALUE_TYPE_STRING);
+ eina_value_set(value, pd->unique_name);
+
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_object_efl_model_base_load(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ if (!pd->connection)
+ _eldbus_model_object_connect(pd);
+
+ _eldbus_model_object_efl_model_base_properties_load(obj, pd);
+ _eldbus_model_object_efl_model_base_children_load(obj, pd);
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_object_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
+{
+ DBG("(%p)", obj);
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_object_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ _eldbus_model_object_unload(pd);
+
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
+}
+
+Eo *
+_eldbus_model_object_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd EINA_UNUSED)
+{
+ DBG("(%p)", obj);
+ return NULL;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_object_efl_model_base_child_del(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Object_Data *pd EINA_UNUSED,
+ Eo *child EINA_UNUSED)
+{
+ DBG("(%p)", obj);
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_object_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Object_Data *pd,
+ unsigned start,
+ unsigned count,
+ Eina_Accessor **children_accessor)
+{
+ fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
+ DBG("(%p)", obj);
+ fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
+
+ if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
+ {
+ WRN("(%p): Children not loaded", obj);
+ *children_accessor = NULL;
+ return pd->load.status;
+ }
+ else
+ WRN("(%p): Children already loaded", obj);
+
+ fprintf(stderr, "%p\n", pd->children_list);
+
+ *children_accessor = efl_model_list_slice(pd->children_list, start, count);
+ return pd->load.status;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_object_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Object_Data *pd,
+ unsigned *children_count)
+{
+ DBG("(%p)", obj);
+ *children_count = eina_list_count(pd->children_list);
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_object_efl_model_base_children_load(Eo *obj, Eldbus_Model_Object_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
+ return;
+
+ if (!pd->connection)
+ _eldbus_model_object_connect(pd);
+
+ if (!_eldbus_model_object_introspect(pd, pd->bus, pd->path))
+ return;
+
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
+}
+
+static const char *
+_eldbus_model_object_address_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
+{
+ return pd->address;
+}
+
+static void
+_eldbus_model_object_address_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, const char *value)
+{
+ eina_stringshare_del(pd->address);
+ pd->address = eina_stringshare_add(value);
+}
+
+static Eina_Bool
+_eldbus_model_object_private_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
+{
+ return pd->private;
+}
+
+static void
+_eldbus_model_object_private_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, Eina_Bool value)
+{
+ pd->private = value;
+}
+
+static int
+_eldbus_model_object_type_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
+{
+ return pd->type;
+}
+
+static void
+_eldbus_model_object_type_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, int value)
+{
+ pd->type = value;
+}
+
+static const char *
+_eldbus_model_object_bus_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
+{
+ return pd->bus;
+}
+
+static void
+_eldbus_model_object_bus_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, const char *value)
+{
+ eina_stringshare_del(pd->bus);
+ pd->bus = eina_stringshare_add(value);
+}
+
+static const char *
+_eldbus_model_object_path_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
+{
+ return pd->path;
+}
+
+static void
+_eldbus_model_object_path_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, const char *value)
+{
+ eina_stringshare_del(pd->path);
+ pd->path = eina_stringshare_add(value);
+}
+
+static void
+_eldbus_model_object_connect(Eldbus_Model_Object_Data *pd)
+{
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+
+ if (ELDBUS_CONNECTION_TYPE_ADDRESS == pd->type)
+ {
+ if (pd->private)
+ pd->connection = eldbus_address_connection_get(pd->address);
+ else
+ pd->connection = eldbus_private_address_connection_get(pd->address);
+ }
+ else
+ {
+ if (pd->private)
+ pd->connection = eldbus_private_connection_get(pd->type);
+ else
+ pd->connection = eldbus_connection_get(pd->type);
+ }
+
+ // TODO: Register for disconnection event
+
+ EINA_SAFETY_ON_FALSE_RETURN(NULL != pd->connection);
+}
+
+static void
+_eldbus_model_object_disconnect(Eldbus_Model_Object_Data *pd)
+{
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+ eldbus_connection_unref(pd->connection);
+ pd->connection = NULL;
+}
+
+static void
+_eldbus_model_object_unload(Eldbus_Model_Object_Data *pd)
+{
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+ if (!pd->connection)
+ return;
+
+ eina_stringshare_del(pd->unique_name);
+ pd->unique_name = NULL;
+
+ Eo *child;
+ EINA_LIST_FREE(pd->children_list, child)
+ eo_unref(child);
+
+ Eldbus_Pending *pending;
+ EINA_LIST_FREE(pd->pending_list, pending)
+ eldbus_pending_cancel(pending);
+
+ if (pd->properties_array)
+ {
+ eina_array_free(pd->properties_array);
+ pd->properties_array = NULL;
+ }
+
+ Eldbus_Object *object;
+ EINA_LIST_FREE(pd->object_list, object)
+ eldbus_object_unref(object);
+
+ if (pd->introspection)
+ {
+ eldbus_introspection_node_free(pd->introspection);
+ pd->introspection = NULL;
+ }
+
+ _eldbus_model_object_disconnect(pd);
+}
+
+
+static bool
+_eldbus_model_object_introspect(Eldbus_Model_Object_Data *pd,
+ const char *bus,
+ const char *path)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(bus, false);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(path, false);
+
+ DBG("(%p) Introspecting: bus = %s, path = %s", pd->obj, bus, path);
+
+ Eldbus_Object *object = eldbus_object_get(pd->connection, bus, path);
+ if (!object)
+ {
+ ERR("(%p): Cannot get object: bus=%s, path=%s", pd->obj, bus, path);
+ return false;
+ }
+ pd->object_list = eina_list_append(pd->object_list, object);
+
+ // TODO: Register for interface added/removed event
+
+ Eldbus_Pending *pending = eldbus_object_introspect(object, &_eldbus_model_object_introspect_cb, pd);
+ eldbus_pending_data_set(pending, "object", object);
+ pd->pending_list = eina_list_append(pd->pending_list, pending);
+ return true;
+}
+
+static void
+_eldbus_model_object_introspect_cb(void *data,
+ const Eldbus_Message *msg,
+ Eldbus_Pending *pending)
+{
+ Eldbus_Model_Object_Data *pd = (Eldbus_Model_Object_Data*)data;
+ DBG("(%p)", pd->obj);
+
+ pd->pending_list = eina_list_remove(pd->pending_list, pending);
+ Eldbus_Object *object = eldbus_pending_data_get(pending, "object");
+
+ const char *error_name, *error_text;
+ if (eldbus_message_error_get(msg, &error_name, &error_text))
+ {
+ ERR("%s: %s", error_name, error_text);
+ efl_model_error_notify(pd->obj);
+ return;
+ }
+
+ const char *xml = NULL;
+ if (!eldbus_message_arguments_get(msg, "s", &xml))
+ {
+ ERR("Error getting arguments.");
+ return;
+ }
+ EINA_SAFETY_ON_NULL_RETURN(xml);
+
+ const char *current_path = eldbus_object_path_get(object);
+ EINA_SAFETY_ON_NULL_RETURN(current_path);
+
+ DBG("(%p): introspect of bus = %s, path = %s =>\n%s", pd->obj, pd->bus, current_path, xml);
+
+ pd->introspection = eldbus_introspection_parse(xml);
+ EINA_SAFETY_ON_NULL_RETURN(pd->introspection);
+
+ _eldbus_model_object_introspect_nodes(pd, current_path, pd->introspection->nodes);
+ _eldbus_model_object_create_children(pd, object, pd->introspection->interfaces);
+
+ if (eina_list_count(pd->pending_list) == 0)
+ {
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ unsigned int count = eina_list_count(pd->children_list);
+ if (count)
+ eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
+ }
+}
+
+static void
+_eldbus_model_object_introspect_nodes(Eldbus_Model_Object_Data *pd, const char *current_path, Eina_List *nodes)
+{
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+ EINA_SAFETY_ON_NULL_RETURN(current_path);
+
+ Eina_List *it;
+ Eldbus_Introspection_Node *node;
+ EINA_LIST_FOREACH(nodes, it, node)
+ {
+ const char *relative_path = node->name;
+ EINA_SAFETY_ON_NULL_RETURN(relative_path);
+
+ char *absolute_path = _eldbus_model_object_concatenate_path(current_path, relative_path);
+ EINA_SAFETY_ON_NULL_RETURN(absolute_path);
+
+ _eldbus_model_object_introspect(pd, pd->bus, absolute_path);
+
+ free(absolute_path);
+ }
+}
+
+static char *
+_eldbus_model_object_concatenate_path(const char *root_path, const char *relative_path)
+{
+ Eina_Strbuf *buffer = eina_strbuf_new();
+ EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, NULL);
+
+ Eina_Bool ret = eina_strbuf_append(buffer, root_path);
+ if (strcmp(root_path, "/") != 0)
+ ret = ret && eina_strbuf_append_char(buffer, '/');
+ ret = ret && eina_strbuf_append(buffer, relative_path);
+ EINA_SAFETY_ON_FALSE_GOTO(ret, free_buffer);
+
+ char *absolute_path = eina_strbuf_string_steal(buffer);
+
+ eina_strbuf_free(buffer);
+
+ return absolute_path;
+
+free_buffer:
+ eina_strbuf_free(buffer);
+ return NULL;
+}
+
+static void
+_eldbus_model_object_create_children(Eldbus_Model_Object_Data *pd, Eldbus_Object *object, Eina_List *interfaces)
+{
+ const char *current_path = eldbus_object_path_get(object);
+ EINA_SAFETY_ON_NULL_RETURN(current_path);
+
+ Eina_List *it;
+ Eldbus_Introspection_Interface *interface;
+ EINA_LIST_FOREACH(interfaces, it, interface)
+ {
+ WRN("(%p) Creating child: bus = %s, path = %s, interface = %s", pd->obj, pd->bus, current_path, interface->name);
+
+ // TODO: increment reference to keep 'interface' in memory
+ Eo *child = eo_add_ref(ELDBUS_MODEL_PROXY_CLASS, NULL,
+ eldbus_model_proxy_constructor(object, interface));
+
+ pd->children_list = eina_list_append(pd->children_list, child);
+ }
+}
+
+#include "eldbus_model_object.eo.c"
diff --git a/src/lib/eldbus/eldbus_model_object.eo b/src/lib/eldbus/eldbus_model_object.eo
new file mode 100644
index 0000000000..b5b4848825
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_object.eo
@@ -0,0 +1,73 @@
+class Eldbus.Model_Object (Eo.Base, Efl.Model.Base) {
+ legacy_prefix: null;
+ data: Eldbus_Model_Object_Data;
+ methods {
+ constructor {
+ [[Custom Eldbus_Model_Object constructor.
+
+ @since 1.16]]
+ params {
+ @in type: int; [[The connection type]]
+ @in address: const(char)*; [[Remote address of dbus]]
+ @in private: bool; [[Non shared dbus connection]]
+ @in bus: const(char)*; [[DBus Name or unique-id]]
+ @in path: const(char)*; [[DBus path]]
+ }
+ }
+ connection_constructor {
+ [[Custom Eldbus_Model_Object connection_constructor.
+
+ @since 1.16]]
+ params {
+ @in connection: Eldbus_Connection*; [[Eldbus connection]]
+ @in bus: const(char)*; [[DBus Name or unique-id]]
+ @in path: const(char)*; [[DBus path]]
+ }
+ }
+ @property type {
+ values {
+ value: int;
+ }
+ }
+ @property address {
+ values {
+ value: const(char)*;
+ }
+ }
+ @property private {
+ values {
+ value: bool;
+ }
+ }
+ @property bus {
+ values {
+ value: const(char)*;
+ }
+ }
+ @property path {
+ values {
+ value: const(char)*;
+ }
+ }
+ }
+ implements {
+ Eo.Base.constructor;
+ Eo.Base.destructor;
+ Efl.Model.Base.properties.get;
+ Efl.Model.Base.properties_load;
+ Efl.Model.Base.property.set;
+ Efl.Model.Base.property.get;
+ Efl.Model.Base.load;
+ Efl.Model.Base.load_status.get;
+ Efl.Model.Base.unload;
+ Efl.Model.Base.child_add;
+ Efl.Model.Base.child_del;
+ Efl.Model.Base.children_slice.get;
+ Efl.Model.Base.children_count.get;
+ Efl.Model.Base.children_load;
+ }
+ constructors {
+ .constructor;
+ .connection_constructor;
+ }
+}
diff --git a/src/lib/eldbus/eldbus_model_object_private.h b/src/lib/eldbus/eldbus_model_object_private.h
new file mode 100644
index 0000000000..dd5747c35a
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_object_private.h
@@ -0,0 +1,32 @@
+#ifndef _ELDBUS_MODEL_OBJECT_PRIVATE_H
+#define _ELDBUS_MODEL_OBJECT_PRIVATE_H
+
+#include "Eldbus_Model.h"
+
+#include <stdbool.h>
+
+typedef struct _Eldbus_Model_Object_Data Eldbus_Model_Object_Data;
+
+/**
+ * eldbus_model_object
+ */
+struct _Eldbus_Model_Object_Data
+{
+ Eo *obj;
+ Efl_Model_Load load;
+ Eldbus_Connection *connection;
+ Eina_List *object_list;
+ Eina_Array *properties_array;
+ Eina_List *children_list;
+ Eldbus_Connection_Type type;
+ Eina_Stringshare *address;
+ bool private;
+ Eina_Stringshare *bus;
+ Eina_Stringshare *path;
+ Eina_Stringshare *unique_name;
+ Eina_List *pending_list;
+ Eldbus_Introspection_Node *introspection;
+};
+
+#endif
+
diff --git a/src/lib/eldbus/eldbus_model_private.h b/src/lib/eldbus/eldbus_model_private.h
new file mode 100644
index 0000000000..784b4226b5
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_private.h
@@ -0,0 +1,37 @@
+#ifndef _ELDBUS_MODEL_PRIVATE_H
+#define _ELDBUS_MODEL_PRIVATE_H
+
+#include "eldbus_private.h"
+
+#include <Eo.h>
+#include <Efl.h>
+
+/* logging support */
+extern int eldbus_model_log_dom;
+
+#ifdef CRI
+# undef CRI
+#endif
+#define CRI(...) EINA_LOG_DOM_CRIT(eldbus_model_log_dom, __VA_ARGS__)
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(eldbus_model_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(eldbus_model_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(eldbus_model_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(eldbus_model_log_dom, __VA_ARGS__)
+
+#endif
diff --git a/src/lib/eldbus/eldbus_model_proxy.c b/src/lib/eldbus/eldbus_model_proxy.c
new file mode 100644
index 0000000000..60e057ba40
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_proxy.c
@@ -0,0 +1,725 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_model_proxy_private.h"
+#include "eldbus_model_private.h"
+
+#include <Eina.h>
+
+#define MY_CLASS ELDBUS_MODEL_PROXY_CLASS
+#define MY_CLASS_NAME "Eldbus_Model_Proxy"
+
+static void _eldbus_model_proxy_efl_model_base_properties_load(Eo *, Eldbus_Model_Proxy_Data *);
+static void _eldbus_model_proxy_efl_model_base_children_load(Eo *, Eldbus_Model_Proxy_Data *);
+static bool _eldbus_model_proxy_load(Eldbus_Model_Proxy_Data *);
+static void _eldbus_model_proxy_unload(Eldbus_Model_Proxy_Data *);
+static void _eldbus_model_proxy_property_get_all_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
+static void _eldbus_model_proxy_property_set_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
+static void _eldbus_model_proxy_start_monitor(Eldbus_Model_Proxy_Data *);
+static void _eldbus_model_proxy_stop_monitor(Eldbus_Model_Proxy_Data *);
+static void _eldbus_model_proxy_property_changed_cb(void *, Eldbus_Proxy *, void *);
+static void _eldbus_model_proxy_property_invalidated_cb(void *, Eldbus_Proxy *, void *);
+static bool _eldbus_model_proxy_is_property_writeable(Eldbus_Model_Proxy_Data *, const char *);
+static bool _eldbus_model_proxy_is_property_readable(Eldbus_Model_Proxy_Data *, const char *);
+static const char *_eldbus_model_proxy_property_type_get(Eldbus_Model_Proxy_Data *, const char *);
+static void _eldbus_model_proxy_create_methods_children(Eldbus_Model_Proxy_Data *);
+static void _eldbus_model_proxy_create_signals_children(Eldbus_Model_Proxy_Data *);
+static void _eldbus_model_proxy_member_setup_cb(void *data, int index, Eina_Value_Struct_Member *member);
+
+typedef struct _Eldbus_Model_Proxy_Property_Set_Data Eldbus_Model_Proxy_Property_Set_Data;
+
+struct _Eldbus_Model_Proxy_Property_Set_Data
+{
+ Eldbus_Model_Proxy_Data *pd;
+ Eina_Stringshare *property;
+ Eina_Value value;
+};
+
+static Eldbus_Model_Proxy_Property_Set_Data * _eldbus_model_proxy_property_set_data_new(Eldbus_Model_Proxy_Data *, const char *, Eina_Value *);
+static void _eldbus_model_proxy_property_set_data_free(Eldbus_Model_Proxy_Property_Set_Data *);
+
+static Eo_Base*
+_eldbus_model_proxy_eo_base_constructor(Eo *obj, Eldbus_Model_Proxy_Data *pd)
+{
+ WRN("_eldbus_model_proxy_eo_base_constructor (%p)", obj);
+ obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
+ WRN("_eldbus_model_proxy_eo_base_constructor (%p) 2", obj);
+
+ pd->obj = obj;
+ pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
+ pd->object = NULL;
+ pd->proxy = NULL;
+ pd->properties_array = NULL;
+ pd->properties_desc = NULL;
+ pd->properties = NULL;
+ pd->children_list = NULL;
+ pd->name = NULL;
+ pd->pending_list = NULL;
+ pd->monitoring = false;
+ pd->interface = NULL;
+ return obj;
+}
+
+static void
+_eldbus_model_proxy_constructor(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Proxy_Data *pd,
+ Eldbus_Object *object,
+ const Eldbus_Introspection_Interface *interface)
+{
+ DBG("(%p)", obj);
+ EINA_SAFETY_ON_NULL_RETURN(object);
+ EINA_SAFETY_ON_NULL_RETURN(interface);
+
+ pd->object = eldbus_object_ref(object);
+ pd->name = eina_stringshare_add(interface->name);
+ pd->interface = interface;
+}
+
+static void
+_eldbus_model_proxy_eo_base_destructor(Eo *obj, Eldbus_Model_Proxy_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ _eldbus_model_proxy_unload(pd);
+
+ eina_value_free(pd->properties);
+ efl_model_value_struct_desc_free(pd->properties_desc);
+
+ eina_stringshare_del(pd->name);
+ eldbus_object_unref(pd->object);
+
+ eo_do_super(obj, MY_CLASS, eo_destructor());
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_proxy_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Proxy_Data *pd,
+ Eina_Array * const* properties_array)
+{
+ DBG("(%p)", obj);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
+ {
+ WRN("%s", "Properties not loaded.");
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+ }
+
+ *(Eina_Array**)properties_array = pd->properties_array;
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_proxy_efl_model_base_properties_load(Eo *obj, Eldbus_Model_Proxy_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
+ return;
+
+ if (!_eldbus_model_proxy_load(pd))
+ return;
+
+ const unsigned int properties_count = eina_list_count(pd->interface->properties);
+
+ pd->properties_array = eina_array_new(properties_count);
+ EINA_SAFETY_ON_NULL_RETURN(pd->properties_array);
+
+ if (0 == properties_count)
+ {
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+ return;
+ }
+
+ Eina_List *it;
+ Eldbus_Introspection_Property *property;
+ EINA_LIST_FOREACH(pd->interface->properties, it, property)
+ {
+ Eina_Stringshare *name = eina_stringshare_add(property->name);
+ EINA_SAFETY_ON_NULL_RETURN(name);
+
+ Eina_Bool ret = eina_array_push(pd->properties_array, name);
+ EINA_SAFETY_ON_FALSE_RETURN(ret);
+ }
+
+ Eldbus_Pending *pending = eldbus_proxy_property_get_all(pd->proxy, _eldbus_model_proxy_property_get_all_cb, pd);
+ pd->pending_list = eina_list_append(pd->pending_list, pending);
+
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES);
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_proxy_efl_model_base_property_set(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Proxy_Data *pd,
+ const char *property,
+ Eina_Value const* value)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
+ DBG("(%p): property=%s", obj, property);
+
+ ERR("proxy property get commented");
+
+ if (!_eldbus_model_proxy_is_property_writeable(pd, property))
+ {
+ WRN("Property is read-only: %s", property);
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+ }
+
+ Eldbus_Model_Proxy_Property_Set_Data *data =
+ _eldbus_model_proxy_property_set_data_new(pd, property, (Eina_Value*)value);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ const char *signature = _eldbus_model_proxy_property_type_get(pd, property);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ Eldbus_Pending *pending = eldbus_proxy_property_value_set
+ (pd->proxy, property, signature, (Eina_Value*)value, _eldbus_model_proxy_property_set_cb, data);
+ pd->pending_list = eina_list_append(pd->pending_list, pending);
+
+ return pd->load.status;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_proxy_efl_model_base_property_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Proxy_Data *pd,
+ const char *property,
+ Eina_Value const **value)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
+ WRN("(%p): property=%s", obj, property);
+
+ if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+
+ if (!_eldbus_model_proxy_is_property_readable(pd, property))
+ {
+ WRN("Property is write-only: %s", property);
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+ }
+
+ WRN("\n");
+
+ Eina_Bool ret = eina_value_struct_value_get(pd->properties, property, &pd->tmp_value);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ WRN("\n");
+
+ *value = &pd->tmp_value;
+
+ WRN("\n");
+
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_proxy_efl_model_base_load(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
+{
+ WRN("(%p)", obj);
+
+ if (!_eldbus_model_proxy_load(pd))
+ return;
+
+ WRN("(%p)", obj);
+
+ _eldbus_model_proxy_efl_model_base_properties_load(obj, pd);
+ WRN("(%p)", obj);
+ _eldbus_model_proxy_efl_model_base_children_load(obj, pd);
+ WRN("(%p)", obj);
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_proxy_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
+{
+ DBG("(%p)", obj);
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_proxy_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ _eldbus_model_proxy_unload(pd);
+
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
+}
+
+Eo *
+_eldbus_model_proxy_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd EINA_UNUSED)
+{
+ DBG("(%p)", obj);
+ return NULL;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_proxy_efl_model_base_child_del(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Proxy_Data *pd EINA_UNUSED,
+ Eo *child EINA_UNUSED)
+{
+ DBG("(%p)", obj);
+ return EFL_MODEL_LOAD_STATUS_ERROR;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_proxy_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Proxy_Data *pd,
+ unsigned start,
+ unsigned count,
+ Eina_Accessor **children_accessor)
+{
+ fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
+ WRN("(%p)", obj);
+ fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
+
+ if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
+ {
+ WRN("(%p): Children not loaded", obj);
+ *children_accessor = NULL;
+ return pd->load.status;
+ }
+
+ *children_accessor = efl_model_list_slice(pd->children_list, start, count);
+ return pd->load.status;
+}
+
+static Efl_Model_Load_Status
+_eldbus_model_proxy_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Proxy_Data *pd,
+ unsigned *children_count)
+{
+ DBG("(%p)", obj);
+ *children_count = eina_list_count(pd->children_list);
+ return pd->load.status;
+}
+
+static void
+_eldbus_model_proxy_efl_model_base_children_load(Eo *obj, Eldbus_Model_Proxy_Data *pd)
+{
+ WRN("\n");
+
+ if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
+ return;
+ WRN("\n");
+
+ if (!_eldbus_model_proxy_load(pd))
+ return;
+ WRN("\n");
+
+ _eldbus_model_proxy_create_methods_children(pd);
+ WRN("\n");
+ _eldbus_model_proxy_create_signals_children(pd);
+ WRN("\n");
+
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+ WRN("\n");
+
+ unsigned int count = eina_list_count(pd->children_list);
+ WRN("\n");
+ if (count)
+ eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
+ WRN("\n");
+}
+
+static void
+_eldbus_model_proxy_create_methods_children(Eldbus_Model_Proxy_Data *pd)
+{
+ WRN("\n");
+ Eina_List *it;
+ WRN("\n");
+ Eldbus_Introspection_Method *method;
+ WRN("\n");
+ EINA_LIST_FOREACH(pd->interface->methods, it, method)
+ {
+ WRN("\n");
+ const char *bus = eldbus_object_bus_name_get(pd->object);
+ EINA_SAFETY_ON_NULL_RETURN(bus);
+ WRN("\n");
+
+ const char *path = eldbus_object_path_get(pd->object);
+ EINA_SAFETY_ON_NULL_RETURN(path);
+ WRN("\n");
+
+ const char *interface_name = pd->interface->name;
+ EINA_SAFETY_ON_NULL_RETURN(interface_name);
+ WRN("\n");
+
+ const char *method_name = method->name;
+ EINA_SAFETY_ON_NULL_RETURN(method_name);
+ WRN("\n");
+
+ INF("(%p) Creating method child: bus = %s, path = %s, method = %s::%s", pd->obj, bus, path, interface_name, method_name);
+ WRN("\n");
+
+ Eo *child = eo_add(ELDBUS_MODEL_METHOD_CLASS, NULL,
+ eldbus_model_method_constructor(pd->proxy, method));
+ WRN("\n");
+
+ pd->children_list = eina_list_append(pd->children_list, child);
+ WRN("\n");
+ }
+ WRN("\n");
+}
+
+static void
+_eldbus_model_proxy_create_signals_children(Eldbus_Model_Proxy_Data *pd)
+{
+ Eina_List *it;
+ Eldbus_Introspection_Signal *signal;
+ EINA_LIST_FOREACH(pd->interface->signals, it, signal)
+ {
+ const char *bus = eldbus_object_bus_name_get(pd->object);
+ EINA_SAFETY_ON_NULL_RETURN(bus);
+
+ const char *path = eldbus_object_path_get(pd->object);
+ EINA_SAFETY_ON_NULL_RETURN(path);
+
+ const char *interface_name = pd->interface->name;
+ EINA_SAFETY_ON_NULL_RETURN(interface_name);
+
+ const char *signal_name = signal->name;
+ EINA_SAFETY_ON_NULL_RETURN(signal_name);
+
+ DBG("(%p) Creating signal child: bus = %s, path = %s, signal = %s::%s", pd->obj, bus, path, interface_name, signal_name);
+
+ Eo *child = eo_add(ELDBUS_MODEL_SIGNAL_CLASS, NULL,
+ eldbus_model_signal_constructor(pd->proxy, signal));
+
+ pd->children_list = eina_list_append(pd->children_list, child);
+ }
+}
+
+static const char *
+_eldbus_model_proxy_name_get(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
+{
+ return pd->name;
+}
+
+static bool
+_eldbus_model_proxy_load(Eldbus_Model_Proxy_Data *pd)
+{
+ WRN("\n");
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd, false);
+ if (pd->proxy)
+ return true;
+
+ WRN("\n");
+ pd->proxy = eldbus_proxy_get(pd->object, pd->name);
+ WRN("\n");
+ if (!pd->proxy)
+ {
+ ERR("Cannot get proxy for interface: %s", pd->name);
+ return false;
+ }
+ WRN("\n");
+
+ return true;
+}
+
+static void
+_eldbus_model_proxy_unload(Eldbus_Model_Proxy_Data *pd)
+{
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+
+ Eo *child;
+ EINA_LIST_FREE(pd->children_list, child)
+ eo_unref(child);
+
+ Eldbus_Pending *pending;
+ EINA_LIST_FREE(pd->pending_list, pending)
+ eldbus_pending_cancel(pending);
+
+ if (pd->properties_array)
+ {
+ unsigned int i;
+ Eina_Stringshare *property;
+ Eina_Array_Iterator it;
+ EINA_ARRAY_ITER_NEXT(pd->properties_array, i, property, it)
+ eina_stringshare_del(property);
+ eina_array_free(pd->properties_array);
+ pd->properties_array = NULL;
+ }
+
+ eina_value_free(pd->properties);
+ pd->properties = NULL;
+
+ _eldbus_model_proxy_stop_monitor(pd);
+
+ if (pd->proxy)
+ {
+ eldbus_proxy_unref(pd->proxy);
+ pd->proxy = NULL;
+ }
+}
+
+static void
+_eldbus_model_proxy_start_monitor(Eldbus_Model_Proxy_Data *pd)
+{
+ if (pd->monitoring)
+ return;
+ pd->monitoring = true;
+
+ eldbus_proxy_event_callback_add(pd->proxy,
+ ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
+ _eldbus_model_proxy_property_changed_cb,
+ pd);
+
+ eldbus_proxy_event_callback_add(pd->proxy,
+ ELDBUS_PROXY_EVENT_PROPERTY_REMOVED,
+ _eldbus_model_proxy_property_invalidated_cb,
+ pd);
+}
+
+static void
+_eldbus_model_proxy_stop_monitor(Eldbus_Model_Proxy_Data *pd)
+{
+ if (!pd->monitoring)
+ return;
+ pd->monitoring = false;
+
+ eldbus_proxy_event_callback_del(pd->proxy,
+ ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
+ _eldbus_model_proxy_property_changed_cb,
+ pd);
+
+ eldbus_proxy_event_callback_del(pd->proxy,
+ ELDBUS_PROXY_EVENT_PROPERTY_REMOVED,
+ _eldbus_model_proxy_property_invalidated_cb,
+ pd);
+}
+
+static void
+_eldbus_model_proxy_property_changed_cb(void *data,
+ Eldbus_Proxy *proxy EINA_UNUSED,
+ void *event_info)
+{
+ Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
+ DBG("(%p)", pd->obj);
+
+ Eldbus_Object_Event_Property_Changed *event = (Eldbus_Object_Event_Property_Changed*)event_info;
+
+ Eina_Bool ret = eina_value_struct_value_set(pd->properties, event->name, event->value);
+ EINA_SAFETY_ON_FALSE_RETURN(ret);
+
+ Efl_Model_Property_Event evt = {.changed_properties = pd->properties_array};
+ eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
+}
+
+static void
+_eldbus_model_proxy_property_invalidated_cb(void *data,
+ Eldbus_Proxy *proxy EINA_UNUSED,
+ void *event_info)
+{
+ Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
+ DBG("(%p)", pd->obj);
+
+ Eldbus_Proxy_Event_Property_Changed *event = (Eldbus_Proxy_Event_Property_Changed*)event_info;
+
+ // TODO: eldbus_proxy_property_get(event->name) ?
+
+ Efl_Model_Property_Event evt = {0};
+ evt.invalidated_properties = eina_array_new(1);
+ EINA_SAFETY_ON_NULL_RETURN(evt.invalidated_properties);
+
+ Eina_Bool ret = eina_array_push(evt.invalidated_properties, event->name);
+ EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
+
+on_error:
+ eina_array_free(evt.invalidated_properties);
+}
+
+static void
+_eldbus_model_proxy_property_get_all_cb(void *data,
+ const Eldbus_Message *msg,
+ Eldbus_Pending *pending)
+{
+ Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
+ WRN("(%p)", pd->obj);
+
+ pd->pending_list = eina_list_remove(pd->pending_list, pending);
+
+ const char *error_name, *error_text;
+ if (eldbus_message_error_get(msg, &error_name, &error_text))
+ {
+ ERR("%s: %s", error_name, error_text);
+ efl_model_error_notify(pd->obj);
+ return;
+ }
+
+ Eldbus_Message_Iter *values = NULL;
+ if (!eldbus_message_arguments_get(msg, "a{sv}", &values))
+ {
+ ERR("%s", "Error getting arguments.");
+ return;
+ }
+
+ if (!pd->properties_desc)
+ {
+ pd->properties_desc = efl_model_value_struct_desc_new(
+ eina_list_count(pd->interface->properties),
+ _eldbus_model_proxy_member_setup_cb,
+ pd);
+ }
+ EINA_SAFETY_ON_TRUE_RETURN(pd->properties);
+ pd->properties = eina_value_struct_new(pd->properties_desc);
+
+ bool changed = false;
+ Eldbus_Message_Iter *entry;
+ while (eldbus_message_iter_get_and_next(values, 'e', &entry))
+ {
+ const char *property;
+ Eldbus_Message_Iter *variant;
+ if (!eldbus_message_iter_arguments_get(entry, "sv", &property, &variant))
+ continue;
+
+ WRN("(%p): Adding property value: %s", pd->obj, property);
+
+ Eina_Value *struct_value = eldbus_message_iter_struct_like_to_eina_value(variant);
+ EINA_SAFETY_ON_NULL_RETURN(struct_value);
+
+ Eina_Value arg0;
+ Eina_Bool ret = eina_value_struct_value_get(struct_value, "arg0", &arg0);
+ eina_value_free(struct_value);
+ EINA_SAFETY_ON_FALSE_RETURN(ret);
+
+ fprintf(stderr, "arg0: %s\n", eina_value_to_string(&arg0));
+
+ ret = eina_value_struct_value_set(pd->properties, property, &arg0);
+ eina_value_flush(&arg0);
+ EINA_SAFETY_ON_FALSE_RETURN(ret);
+
+ changed = true;
+ }
+
+ _eldbus_model_proxy_start_monitor(pd);
+
+ if (changed)
+ {
+ Efl_Model_Property_Event evt = {.changed_properties = pd->properties_array};
+ eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
+ }
+
+ efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+}
+
+
+static void
+_eldbus_model_proxy_property_set_cb(void *data,
+ const Eldbus_Message *msg,
+ Eldbus_Pending *pending)
+{
+ Eldbus_Model_Proxy_Property_Set_Data *property_set_data = (Eldbus_Model_Proxy_Property_Set_Data *)data;
+ Eldbus_Model_Proxy_Data *pd = property_set_data->pd;
+ WRN("(%p)", pd->obj);
+
+ pd->pending_list = eina_list_remove(pd->pending_list, pending);
+
+ const char *error_name, *error_text;
+ if (eldbus_message_error_get(msg, &error_name, &error_text))
+ {
+ ERR("%s: %s", error_name, error_text);
+ efl_model_error_notify(pd->obj);
+ goto on_error;
+ }
+
+ Eina_Bool ret = eina_value_struct_value_set(pd->properties,
+ property_set_data->property,
+ &property_set_data->value);
+ EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
+
+ Efl_Model_Property_Event evt = {.changed_properties = pd->properties_array};
+ eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
+
+on_error:
+ _eldbus_model_proxy_property_set_data_free(property_set_data);
+}
+
+static bool
+_eldbus_model_proxy_is_property_writeable(Eldbus_Model_Proxy_Data *pd, const char *property)
+{
+ Eldbus_Introspection_Property *property_introspection =
+ eldbus_introspection_property_find(pd->interface->properties, property);
+ if (NULL == property_introspection)
+ {
+ WRN("Property not found: %s", property);
+ return false;
+ }
+
+ return ELDBUS_INTROSPECTION_PROPERTY_ACCESS_WRITE == property_introspection->access
+ || ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE == property_introspection->access;
+}
+
+static bool
+_eldbus_model_proxy_is_property_readable(Eldbus_Model_Proxy_Data *pd, const char *property)
+{
+ Eldbus_Introspection_Property *property_introspection =
+ eldbus_introspection_property_find(pd->interface->properties, property);
+ if (NULL == property_introspection)
+ {
+ WRN("Property not found: %s", property);
+ return false;
+ }
+
+ return ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READ == property_introspection->access
+ || ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE == property_introspection->access;
+}
+
+static const char *
+_eldbus_model_proxy_property_type_get(Eldbus_Model_Proxy_Data *pd, const char *property)
+{
+ Eldbus_Introspection_Property *property_introspection =
+ eldbus_introspection_property_find(pd->interface->properties, property);
+ if (NULL == property_introspection)
+ {
+ WRN("Property not found: %s", property);
+ return NULL;
+ }
+
+ return property_introspection->type;
+
+}
+
+static Eldbus_Model_Proxy_Property_Set_Data *
+_eldbus_model_proxy_property_set_data_new(Eldbus_Model_Proxy_Data *pd,
+ const char *property,
+ Eina_Value *value)
+{
+ Eldbus_Model_Proxy_Property_Set_Data *data = calloc(1, sizeof(Eldbus_Model_Proxy_Property_Set_Data));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
+
+ data->pd = pd;
+ data->property = eina_stringshare_add(property);
+ Eina_Bool ret = eina_value_copy(value, &data->value);
+ EINA_SAFETY_ON_FALSE_GOTO(ret, error);
+
+ return data;
+
+error:
+ eina_stringshare_del(data->property);
+ free(data);
+ return NULL;
+}
+
+static void
+_eldbus_model_proxy_property_set_data_free(Eldbus_Model_Proxy_Property_Set_Data *data)
+{
+ EINA_SAFETY_ON_NULL_RETURN(data);
+ eina_stringshare_del(data->property);
+ eina_value_flush(&data->value);
+ free(data);
+}
+
+static void
+_eldbus_model_proxy_member_setup_cb(void *data, int index, Eina_Value_Struct_Member *member)
+{
+ Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
+
+ member->name = eina_stringshare_ref(eina_array_data_get(pd->properties_array, index));
+
+ Eldbus_Introspection_Property *property = eina_list_nth(pd->interface->properties, index);
+ member->type = _dbus_type_to_eina_value_type(property->type[0]);
+}
+
+#include "eldbus_model_proxy.eo.c"
diff --git a/src/lib/eldbus/eldbus_model_proxy.eo b/src/lib/eldbus/eldbus_model_proxy.eo
new file mode 100644
index 0000000000..2bab11937d
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_proxy.eo
@@ -0,0 +1,39 @@
+class Eldbus.Model_Proxy (Eo.Base, Efl.Model.Base) {
+ legacy_prefix: null;
+ methods {
+ constructor {
+ [[Custom Eldbus_Model_Proxy constructor.
+
+ @since 1.16]]
+ params {
+ @in object: Eldbus_Object *; [[Eldbus object]]
+ @in interface: const(Eldbus_Introspection_Interface)*; [[The introspected interface]]
+ }
+ }
+ @property name {
+ get {}
+ values {
+ value: const(char)*;
+ }
+ }
+ }
+ implements {
+ Eo.Base.constructor;
+ Eo.Base.destructor;
+ Efl.Model.Base.properties.get;
+ Efl.Model.Base.properties_load;
+ Efl.Model.Base.property.set;
+ Efl.Model.Base.property.get;
+ Efl.Model.Base.load;
+ Efl.Model.Base.load_status.get;
+ Efl.Model.Base.unload;
+ Efl.Model.Base.child_add;
+ Efl.Model.Base.child_del;
+ Efl.Model.Base.children_slice.get;
+ Efl.Model.Base.children_count.get;
+ Efl.Model.Base.children_load;
+ }
+ constructors {
+ .constructor;
+ }
+}
diff --git a/src/lib/eldbus/eldbus_model_proxy_private.h b/src/lib/eldbus/eldbus_model_proxy_private.h
new file mode 100644
index 0000000000..2a7a5edd1d
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_proxy_private.h
@@ -0,0 +1,31 @@
+#ifndef _ELDBUS_MODEL_PROXY_PRIVATE_H
+#define _ELDBUS_MODEL_PROXY_PRIVATE_H
+
+#include "Eldbus_Model.h"
+
+#include <stdbool.h>
+
+typedef struct _Eldbus_Model_Proxy_Data Eldbus_Model_Proxy_Data;
+
+/**
+ * eldbus_model_proxy
+ */
+struct _Eldbus_Model_Proxy_Data
+{
+ Eo *obj;
+ Efl_Model_Load load;
+ Eldbus_Object *object;
+ Eldbus_Proxy *proxy;
+ Eina_Array *properties_array;
+ Eina_Value_Struct_Desc *properties_desc;
+ Eina_Value *properties;
+ Eina_List *children_list;
+ Eina_Stringshare *name;
+ Eina_List *pending_list;
+ bool monitoring;
+ const Eldbus_Introspection_Interface *interface;
+ Eina_Value tmp_value;
+};
+
+#endif
+
diff --git a/src/lib/eldbus/eldbus_model_signal.c b/src/lib/eldbus/eldbus_model_signal.c
new file mode 100644
index 0000000000..2c4f6dbdd3
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_signal.c
@@ -0,0 +1,116 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_model_arguments_private.h"
+#include "eldbus_model_signal_private.h"
+#include "eldbus_model_private.h"
+
+#include <Eina.h>
+
+#define MY_CLASS ELDBUS_MODEL_SIGNAL_CLASS
+#define MY_CLASS_NAME "Eldbus_Model_Signal"
+
+static void _eldbus_model_signal_handler_cb(void *, const Eldbus_Message *);
+static void _eldbus_model_signal_callback_add(Eldbus_Model_Signal_Data *);
+static void _eldbus_model_signal_callback_del(Eldbus_Model_Signal_Data *);
+
+static Eo_Base*
+_eldbus_model_signal_eo_base_constructor(Eo *obj, Eldbus_Model_Signal_Data *pd)
+{
+ DBG("(%p)", obj);
+ eo_do_super(obj, MY_CLASS, eo_constructor());
+
+ pd->obj = obj;
+ pd->handler = NULL;
+ pd->signal = NULL;
+ return obj;
+}
+
+static void
+_eldbus_model_signal_constructor(Eo *obj EINA_UNUSED,
+ Eldbus_Model_Signal_Data *pd,
+ Eldbus_Proxy *proxy,
+ const Eldbus_Introspection_Signal *signal)
+{
+ DBG("(%p)", obj);
+ EINA_SAFETY_ON_NULL_RETURN(proxy);
+ EINA_SAFETY_ON_NULL_RETURN(signal);
+ eo_do_super(obj, MY_CLASS, eldbus_model_arguments_constructor(proxy, signal->name, signal->arguments));
+
+ pd->signal = signal;
+}
+
+static void
+_eldbus_model_signal_eo_base_destructor(Eo *obj, Eldbus_Model_Signal_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ _eldbus_model_signal_callback_del(pd);
+
+ eo_do_super(obj, MY_CLASS, eo_destructor());
+}
+
+static void
+_eldbus_model_signal_efl_model_base_properties_load(Eo *obj, Eldbus_Model_Signal_Data *pd)
+{
+ DBG("(%p)", obj);
+
+ Eldbus_Model_Arguments_Data *args_data = eo_data_scope_get(pd->obj, ELDBUS_MODEL_ARGUMENTS_CLASS);
+ EINA_SAFETY_ON_NULL_RETURN(args_data);
+
+ if (args_data->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
+ return;
+
+ _eldbus_model_signal_callback_add(pd);
+
+ eo_do_super(obj, MY_CLASS, efl_model_properties_load());
+}
+
+static void
+_eldbus_model_signal_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Signal_Data *pd)
+{
+ DBG("(%p)", obj);
+ _eldbus_model_signal_callback_del(pd);
+ eo_do_super(obj, MY_CLASS, efl_model_unload());
+}
+
+static void
+_eldbus_model_signal_callback_add(Eldbus_Model_Signal_Data *pd)
+{
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+ DBG("(%p)", pd->obj);
+ EINA_SAFETY_ON_FALSE_RETURN(NULL == pd->handler);
+
+ Eldbus_Model_Arguments_Data *args_data = eo_data_scope_get(pd->obj, ELDBUS_MODEL_ARGUMENTS_CLASS);
+ EINA_SAFETY_ON_NULL_RETURN(args_data);
+
+ pd->handler = eldbus_proxy_signal_handler_add(args_data->proxy, pd->signal->name, _eldbus_model_signal_handler_cb, pd);
+}
+
+static void
+_eldbus_model_signal_callback_del(Eldbus_Model_Signal_Data *pd)
+{
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+ DBG("(%p)", pd->obj);
+
+ if (pd->handler)
+ {
+ eldbus_signal_handler_unref(pd->handler);
+ pd->handler = NULL;
+ }
+}
+
+static void
+_eldbus_model_signal_handler_cb(void *data, const Eldbus_Message *msg)
+{
+ Eldbus_Model_Signal_Data *pd = (Eldbus_Model_Signal_Data*)data;
+ DBG("(%p)", pd->obj);
+
+ Eldbus_Model_Arguments_Data *args_data = eo_data_scope_get(pd->obj, ELDBUS_MODEL_ARGUMENTS_CLASS);
+ EINA_SAFETY_ON_NULL_RETURN(args_data);
+
+ eldbus_model_arguments_process_arguments(args_data, msg, NULL);
+}
+
+#include "eldbus_model_signal.eo.c"
diff --git a/src/lib/eldbus/eldbus_model_signal.eo b/src/lib/eldbus/eldbus_model_signal.eo
new file mode 100644
index 0000000000..237b149dbe
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_signal.eo
@@ -0,0 +1,23 @@
+class Eldbus.Model_Signal (Eldbus.Model_Arguments) {
+ legacy_prefix: null;
+ methods {
+ constructor {
+ [[Custom Eldbus_Model_Signal constructor.
+
+ @since 1.16]]
+ params {
+ @in proxy: Eldbus_Proxy*; [[Eldbus proxy]]
+ @in signal: const(Eldbus_Introspection_Signal)*; [[The introspected method]]
+ }
+ }
+ }
+ implements {
+ Eo.Base.constructor;
+ Eo.Base.destructor;
+ Efl.Model.Base.properties_load;
+ Efl.Model.Base.unload;
+ }
+ constructors {
+ .constructor;
+ }
+}
diff --git a/src/lib/eldbus/eldbus_model_signal_private.h b/src/lib/eldbus/eldbus_model_signal_private.h
new file mode 100644
index 0000000000..5bef898f2c
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_signal_private.h
@@ -0,0 +1,19 @@
+#ifndef _ELDBUS_MODEL_SIGNAL_PRIVATE_H
+#define _ELDBUS_MODEL_SIGNAL_PRIVATE_H
+
+#include "Eldbus_Model.h"
+
+typedef struct _Eldbus_Model_Signal_Data Eldbus_Model_Signal_Data;
+
+/**
+ * eldbus_model_signal
+ */
+struct _Eldbus_Model_Signal_Data
+{
+ Eo *obj;
+ Eldbus_Signal_Handler *handler;
+ const Eldbus_Introspection_Signal *signal;
+};
+
+#endif
+
diff --git a/src/lib/eldbus/eldbus_private.h b/src/lib/eldbus/eldbus_private.h
index 7b4bdde449..21b1e98bf3 100644
--- a/src/lib/eldbus/eldbus_private.h
+++ b/src/lib/eldbus/eldbus_private.h
@@ -76,8 +76,9 @@ Eldbus_Pending *_eldbus_connection_send(Eldbus_Connection *conn, Eldbus_
Eldbus_Message *_eldbus_connection_send_and_block(Eldbus_Connection *conn, Eldbus_Message *msg, double timeout);
Eldbus_Message_Iter *eldbus_message_iter_sub_iter_get(Eldbus_Message_Iter *iter);
-Eina_Value *_message_iter_struct_to_eina_value(Eldbus_Message_Iter *iter);
-Eina_Bool _message_iter_from_eina_value_struct(const char *signature, Eldbus_Message_Iter *iter, const Eina_Value *value);
+Eina_Value *_message_iter_struct_to_eina_value(Eldbus_Message_Iter *iter);
+Eina_Bool _message_iter_from_eina_value(const char *signature, Eldbus_Message_Iter *iter, const Eina_Value *value);
+Eina_Bool _message_iter_from_eina_value_struct(const char *signature, Eldbus_Message_Iter *iter, const Eina_Value *value);
void eldbus_connection_name_ref(Eldbus_Connection_Name *cn);
void eldbus_connection_name_unref(Eldbus_Connection *conn, Eldbus_Connection_Name *cn);
@@ -85,4 +86,6 @@ 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;
+const Eina_Value_Type *_dbus_type_to_eina_value_type(char type);
+
#endif
diff --git a/src/lib/eldbus/eldbus_proxy.c b/src/lib/eldbus/eldbus_proxy.c
index e543bb6bfb..d8d3cbfbd6 100644
--- a/src/lib/eldbus/eldbus_proxy.c
+++ b/src/lib/eldbus/eldbus_proxy.c
@@ -728,6 +728,42 @@ eldbus_proxy_property_set(Eldbus_Proxy *proxy, const char *name, const char *sig
}
EAPI Eldbus_Pending *
+eldbus_proxy_property_value_set(Eldbus_Proxy *proxy, const char *name, const char *sig, const Eina_Value *value, Eldbus_Message_Cb cb, const void *data)
+{
+ Eldbus_Message *msg;
+ Eldbus_Message_Iter *iter, *variant;
+
+ ELDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sig, NULL);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(dbus_signature_validate_single(sig, NULL), NULL);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL((_type_is_number(sig[0]) || value), NULL);
+
+ msg = eldbus_proxy_method_call_new(proxy->obj->properties, "Set");
+ iter = eldbus_message_iter_get(msg);
+ eldbus_message_iter_basic_append(iter, 's', proxy->interface);
+ eldbus_message_iter_basic_append(iter, 's', name);
+ variant = eldbus_message_iter_container_new(iter, 'v', sig);
+ if (dbus_type_is_basic(sig[0]))
+ {
+ if (!_message_iter_from_eina_value(sig, variant, value))
+ goto error;
+ }
+ else
+ {
+ if (!_message_iter_from_eina_value_struct(sig, variant, value))
+ goto error;
+ }
+ eldbus_message_iter_container_close(iter, variant);
+
+ return eldbus_proxy_send(proxy->obj->properties, msg, cb, data, -1);
+
+error:
+ eldbus_message_unref(msg);
+ return NULL;
+}
+
+EAPI Eldbus_Pending *
eldbus_proxy_property_get_all(Eldbus_Proxy *proxy, Eldbus_Message_Cb cb, const void *data)
{
ELDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
diff --git a/src/tests/eldbus/eldbus_fake_server.c b/src/tests/eldbus/eldbus_fake_server.c
new file mode 100644
index 0000000000..18798ed68b
--- /dev/null
+++ b/src/tests/eldbus/eldbus_fake_server.c
@@ -0,0 +1,181 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "eldbus_fake_server.h"
+
+#include <Ecore.h>
+
+#include <check.h>
+
+#define FAKE_SERVER_DATA_KEY "data"
+
+static void _fake_server_name_request_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
+static Eina_Bool _fakse_server_property_get(const Eldbus_Service_Interface *, const char *, Eldbus_Message_Iter *, const Eldbus_Message *, Eldbus_Message **);
+static Eldbus_Message *_fake_server_property_set(const Eldbus_Service_Interface *, const char *, Eldbus_Message_Iter *, const Eldbus_Message *);
+static Eldbus_Message *_fake_server_sum(const Eldbus_Service_Interface *, const Eldbus_Message *);
+static Eldbus_Message *_fake_server_ping(const Eldbus_Service_Interface *, const Eldbus_Message *);
+static Eina_Bool _fake_server_send_pong_signal(void *);
+
+static Eldbus_Connection *conn;
+
+static const Eldbus_Method methods[] = {
+ {
+ FAKE_SERVER_SUM_METHOD_NAME, ELDBUS_ARGS({"i", "a"}, {"i", "b"}), ELDBUS_ARGS({"i", "result"}),
+ _fake_server_sum
+ },
+ {
+ FAKE_SERVER_PING_METHOD_NAME, ELDBUS_ARGS({"i", "a"}), NULL,
+ _fake_server_ping
+ },
+ { 0 }
+};
+
+enum
+{
+ FAKE_SERVER_PONG_SIGNAL = 0
+};
+
+static const Eldbus_Signal signals[] = {
+ [FAKE_SERVER_PONG_SIGNAL] = {FAKE_SERVER_PONG_SIGNAL_NAME, ELDBUS_ARGS({ "i", NULL }), 0},
+ { 0 }
+};
+
+static const Eldbus_Property properties[] = {
+ { FAKE_SERVER_READONLY_PROPERTY, "i", _fakse_server_property_get, NULL, 0 },
+ { FAKE_SERVER_WRITEONLY_PROPERTY, "i", NULL, _fake_server_property_set, 0 },
+ { FAKE_SERVER_READWRITE_PROPERTY, "i", _fakse_server_property_get, _fake_server_property_set, 0 },
+ { 0 }
+};
+
+static const Eldbus_Service_Interface_Desc test_interface_desc = {
+ FAKE_SERVER_INTERFACE, methods, signals, properties, NULL, NULL
+};
+
+
+Eldbus_Service_Interface *
+fake_server_start(Fake_Server_Data *data)
+{
+ ck_assert_ptr_ne(NULL, data);
+
+ conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
+
+ Eldbus_Service_Interface *interface = eldbus_service_interface_register(conn, FAKE_SERVER_PATH, &test_interface_desc);
+ eldbus_service_object_data_set(interface, FAKE_SERVER_DATA_KEY, data);
+
+ eldbus_name_request(conn, FAKE_SERVER_BUS, ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE,
+ _fake_server_name_request_cb, interface);
+
+ ecore_main_loop_begin();
+
+ return interface;
+}
+
+void
+fake_server_stop(Eldbus_Service_Interface *interface)
+{
+ eldbus_service_object_unregister(interface);
+ eldbus_connection_unref(conn);
+}
+
+static Eldbus_Message *
+_fake_server_sum(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+ int a, b;
+ if (!eldbus_message_arguments_get(msg, "ii", &a, &b))
+ return eldbus_message_error_new(msg, "Invalid arguments", "Error getting arguments..");
+
+ int sum = a + b;
+
+ Eldbus_Message *reply = eldbus_message_method_return_new(msg);
+ eldbus_message_arguments_append(reply, "i", sum);
+ return reply;
+}
+
+static Eldbus_Message *
+_fake_server_ping(const Eldbus_Service_Interface *iface , const Eldbus_Message *msg)
+{
+ int a;
+ if (!eldbus_message_arguments_get(msg, "i", &a))
+ return eldbus_message_error_new(msg, "Invalid arguments", "Error getting arguments..");
+
+ Fake_Server_Data *pd = eldbus_service_object_data_get(iface, FAKE_SERVER_DATA_KEY);
+ ck_assert_ptr_ne(NULL, pd);
+
+ pd->pong_response = a + 1;
+ Ecore_Timer *timer = ecore_timer_add(0.1, _fake_server_send_pong_signal, iface);
+ ck_assert_ptr_ne(NULL, timer);
+
+ return NULL;
+}
+
+static Eina_Bool
+_fake_server_send_pong_signal(void *data)
+{
+ Eldbus_Service_Interface *iface = (Eldbus_Service_Interface*)data;
+
+ Fake_Server_Data *pd = eldbus_service_object_data_get(iface, FAKE_SERVER_DATA_KEY);
+ ck_assert_ptr_ne(NULL, pd);
+
+ eldbus_service_signal_emit(iface, FAKE_SERVER_PONG_SIGNAL, pd->pong_response);
+ return ECORE_CALLBACK_CANCEL;
+}
+
+Eina_Bool
+_fakse_server_property_get(const Eldbus_Service_Interface *iface,
+ const char *propname,
+ Eldbus_Message_Iter *iter,
+ const Eldbus_Message *request_msg EINA_UNUSED,
+ Eldbus_Message **error EINA_UNUSED)
+{
+ Fake_Server_Data *data = eldbus_service_object_data_get(iface, FAKE_SERVER_DATA_KEY);
+ ck_assert_ptr_ne(NULL, data);
+
+ if (strcmp(propname, FAKE_SERVER_READONLY_PROPERTY) == 0)
+ eldbus_message_iter_arguments_append(iter, "i", data->readonly_property);
+ else
+ if (strcmp(propname, FAKE_SERVER_READWRITE_PROPERTY) == 0)
+ eldbus_message_iter_arguments_append(iter, "i", data->readwrite_property);
+ else
+ return EINA_FALSE;
+
+ return EINA_TRUE;
+}
+
+Eldbus_Message *
+_fake_server_property_set(const Eldbus_Service_Interface *iface,
+ const char *propname,
+ Eldbus_Message_Iter *iter,
+ const Eldbus_Message *msg)
+{
+ Fake_Server_Data *data = eldbus_service_object_data_get(iface, FAKE_SERVER_DATA_KEY);
+ ck_assert_ptr_ne(NULL, data);
+
+ if (strcmp(propname, FAKE_SERVER_WRITEONLY_PROPERTY) == 0)
+ eldbus_message_iter_arguments_get(iter, "i", &data->writeonly_property);
+ else
+ if (strcmp(propname, FAKE_SERVER_READWRITE_PROPERTY) == 0)
+ eldbus_message_iter_arguments_get(iter, "i", &data->readwrite_property);
+ else
+ return eldbus_message_error_new(msg, "Invalid property", "Invalid property.");
+
+ return eldbus_message_method_return_new(msg);
+}
+
+static void
+_fake_server_name_request_cb(void *data EINA_UNUSED,
+ const Eldbus_Message *msg,
+ Eldbus_Pending *pending EINA_UNUSED)
+{
+ if (eldbus_message_error_get(msg, NULL, NULL))
+ ck_abort_msg("error on _fake_server_name_request_cb");
+
+ unsigned int reply;
+ if (!eldbus_message_arguments_get(msg, "u", &reply))
+ ck_abort_msg("error geting arguments on _fake_server_name_request_cb");
+
+ if (ELDBUS_NAME_REQUEST_REPLY_PRIMARY_OWNER != reply)
+ ck_abort_msg("error name already in use");
+
+ ecore_main_loop_quit();
+}
diff --git a/src/tests/eldbus/eldbus_fake_server.h b/src/tests/eldbus/eldbus_fake_server.h
new file mode 100644
index 0000000000..00b4c86573
--- /dev/null
+++ b/src/tests/eldbus/eldbus_fake_server.h
@@ -0,0 +1,29 @@
+#ifndef _ELDBUS_FAKE_SERVER_H
+#define _ELDBUS_FAKE_SERVER_H
+
+#include <Eldbus.h>
+
+#define FAKE_SERVER_BUS "org.Enlightenment"
+#define FAKE_SERVER_PATH "/org/enlightenment"
+#define FAKE_SERVER_INTERFACE "org.enlightenment.FakeServer"
+#define FAKE_SERVER_READONLY_PROPERTY "r"
+#define FAKE_SERVER_WRITEONLY_PROPERTY "w"
+#define FAKE_SERVER_READWRITE_PROPERTY "rw"
+#define FAKE_SERVER_SUM_METHOD_NAME "Sum"
+#define FAKE_SERVER_PING_METHOD_NAME "Ping"
+#define FAKE_SERVER_PONG_SIGNAL_NAME "Pong"
+
+typedef struct _Fake_Server_Data Fake_Server_Data;
+
+struct _Fake_Server_Data
+{
+ int readonly_property;
+ int writeonly_property;
+ int readwrite_property;
+ int pong_response;
+};
+
+Eldbus_Service_Interface *fake_server_start(Fake_Server_Data *data);
+void fake_server_stop(Eldbus_Service_Interface *interface);
+
+#endif
diff --git a/src/tests/eldbus/eldbus_suite.c b/src/tests/eldbus/eldbus_suite.c
index 5c6743decf..3aca778394 100644
--- a/src/tests/eldbus/eldbus_suite.c
+++ b/src/tests/eldbus/eldbus_suite.c
@@ -18,8 +18,15 @@ struct _Eldbus_Test_Case
};
static const Eldbus_Test_Case etc[] = {
- { "eldbus_init", eldbus_test_eldbus_init },
- { }
+ //{ "eldbus_init", eldbus_test_eldbus_init },
+ /* { "eldbus_model", eldbus_test_eldbus_model }, */
+ /* { "eldbus_model_connection", eldbus_test_eldbus_model_connection }, */
+ /* { "eldbus_model_object", eldbus_test_eldbus_model_object }, */
+ /* { "eldbus_model_proxy", eldbus_test_eldbus_model_proxy }, */
+ { "eldbus_test_fake_server_eldbus_model_proxy", eldbus_test_fake_server_eldbus_model_proxy },
+ { "eldbus_model_method", eldbus_test_eldbus_model_method },
+ { "eldbus_model_signal", eldbus_test_eldbus_model_signal },
+ { NULL, NULL }
};
static void
diff --git a/src/tests/eldbus/eldbus_suite.h b/src/tests/eldbus/eldbus_suite.h
index 400d2278ae..5410fe4e90 100644
--- a/src/tests/eldbus/eldbus_suite.h
+++ b/src/tests/eldbus/eldbus_suite.h
@@ -4,5 +4,12 @@
#include <check.h>
void eldbus_test_eldbus_init(TCase *tc);
+void eldbus_test_eldbus_model(TCase *tc);
+void eldbus_test_eldbus_model_connection(TCase *tc);
+void eldbus_test_eldbus_model_object(TCase *tc);
+void eldbus_test_eldbus_model_proxy(TCase *tc);
+void eldbus_test_fake_server_eldbus_model_proxy(TCase *tc);
+void eldbus_test_eldbus_model_method(TCase *tc);
+void eldbus_test_eldbus_model_signal(TCase *tc);
#endif
diff --git a/src/tests/eldbus/eldbus_test_eldbus_model.c b/src/tests/eldbus/eldbus_test_eldbus_model.c
new file mode 100644
index 0000000000..94bcda5248
--- /dev/null
+++ b/src/tests/eldbus/eldbus_test_eldbus_model.c
@@ -0,0 +1,417 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_suite.h"
+#include "eldbus_test_eldbus_model.h"
+
+#include <Ecore.h>
+#include <Eina.h>
+#include <Eldbus.h>
+#include <Eldbus_Model.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static Eina_Bool
+_eo_event_quit_cb(void *data EINA_UNUSED,
+ Eo *obj EINA_UNUSED,
+ const Eo_Event_Description *desc EINA_UNUSED,
+ void *event_info EINA_UNUSED)
+{
+ ecore_main_loop_quit();
+ return EINA_FALSE;
+}
+
+void
+efl_model_wait_for_event(Eo *obj, const Eo_Event_Description* event)
+{
+ eo_do(obj, eo_event_callback_add(event, _eo_event_quit_cb, NULL));
+ ecore_main_loop_begin();
+ eo_do(obj, eo_event_callback_del(event, _eo_event_quit_cb, NULL));
+}
+
+static Eina_Bool
+_event_load_status_quit_cb(void *data, Eo *obj EINA_UNUSED,
+ const Eo_Event_Description *desc EINA_UNUSED,
+ void *event_info EINA_UNUSED)
+{
+ printf("_event_load_status_quit_cb\n");
+ Efl_Model_Load_Status expected_status = (Efl_Model_Load_Status)data;
+ Efl_Model_Load *actual_load = (Efl_Model_Load*)event_info;
+
+ if (expected_status == actual_load->status)
+ {
+ ecore_main_loop_quit();
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+void
+efl_model_wait_for_load_status(Efl_Model_Base *efl_model, Efl_Model_Load_Status expected_status)
+{
+ Efl_Model_Load_Status actual_status;
+ eo_do(efl_model, actual_status = efl_model_load_status_get());
+ if (expected_status == actual_status)
+ return;
+
+ eo_do(efl_model, eo_event_callback_add(EFL_MODEL_BASE_EVENT_LOAD_STATUS, _event_load_status_quit_cb, (void*)expected_status));
+ ecore_main_loop_begin();
+ eo_do(efl_model, eo_event_callback_del(EFL_MODEL_BASE_EVENT_LOAD_STATUS, _event_load_status_quit_cb, (void*)expected_status));
+}
+
+Efl_Model_Base *
+efl_model_nth_child_get(Efl_Model_Base *efl_model, unsigned int n)
+{
+ Eina_Accessor *accessor;
+ Efl_Model_Load_Status status;
+ eo_do(efl_model, status = efl_model_children_slice_get(n, 1, &accessor));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_ne(NULL, accessor);
+ Eo *child = NULL;
+ Eina_Bool ret = eina_accessor_data_get(accessor, 0, (void**)&child);
+ eina_accessor_free(accessor);
+ ck_assert(ret);
+ ck_assert_ptr_ne(NULL, child);
+ return child;
+}
+
+Efl_Model_Base *
+efl_model_first_child_get(Efl_Model_Base *efl_model)
+{
+ return efl_model_nth_child_get(efl_model, 1);
+}
+
+void
+efl_model_load_and_wait_for_load_status(Eo *obj, Efl_Model_Load_Status expected_status)
+{
+ eo_do(obj, efl_model_load());
+ efl_model_wait_for_load_status(obj, expected_status);
+}
+
+void
+check_init(void)
+{
+ int ret = eldbus_init();
+ ck_assert_int_ge(ret, 1);
+}
+
+void
+check_shutdown(void)
+{
+ int ret = eldbus_shutdown();
+ ck_assert_int_eq(ret, 0);
+}
+
+void
+check_property(Eo *object, const char *property_name, const char *expected_value)
+{
+ Eina_Value const* property_value;
+ Efl_Model_Load_Status status;
+ eo_do(object, status = efl_model_property_get(property_name, &property_value));
+ ck_assert_msg(EFL_MODEL_LOAD_STATUS_ERROR != status, "Nonexistent property: %s", property_name);
+ char *actual_value = eina_value_to_string(property_value);
+ if (!actual_value)
+ ck_assert_ptr_eq(expected_value, actual_value);
+ else
+ {
+ bool is_property_equal = strcmp(expected_value, actual_value) == 0;
+ ck_assert_msg(is_property_equal, "'%s' != '%s'", expected_value, actual_value);
+ free(actual_value);
+ }
+}
+
+Eo *
+create_connection(void)
+{
+ Eo *connection = eo_add_ref(ELDBUS_MODEL_CONNECTION_CLASS, NULL,
+ eldbus_model_connection_constructor(ELDBUS_CONNECTION_TYPE_SESSION,
+ NULL,
+ EINA_FALSE));
+ ck_assert_ptr_ne(NULL, connection);
+ return connection;
+}
+
+Eo *
+create_and_load_connection(void)
+{
+ Eo *connection = create_connection();
+ efl_model_load_and_wait_for_load_status(connection, EFL_MODEL_LOAD_STATUS_LOADED);
+ return connection;
+}
+
+Eo *
+create_object(void)
+{
+ Eo *object = eo_add_ref(ELDBUS_MODEL_OBJECT_CLASS, NULL,
+ eldbus_model_object_constructor(ELDBUS_CONNECTION_TYPE_SESSION,
+ NULL,
+ EINA_FALSE,
+ ELDBUS_FDO_BUS,
+ ELDBUS_FDO_PATH));
+ ck_assert_ptr_ne(NULL, object);
+ return object;
+}
+
+Eo *
+create_and_load_object(void)
+{
+ Eo *object = create_object();
+ efl_model_load_and_wait_for_load_status(object, EFL_MODEL_LOAD_STATUS_LOADED);
+ return object;
+}
+
+void
+check_efl_model_load_status_get(Efl_Model_Base *efl_model, Efl_Model_Load_Status expected_load_status)
+{
+ Efl_Model_Load_Status actual_load_status;
+ eo_do(efl_model, actual_load_status = efl_model_load_status_get());
+ ck_assert_int_eq(expected_load_status, actual_load_status);
+}
+
+void
+check_efl_model_children_count_eq(Efl_Model_Base *efl_model, unsigned int expected_children_count)
+{
+ unsigned int actual_children_count = 0;
+ eo_do(efl_model, efl_model_children_count_get(&actual_children_count));
+ ck_assert_int_eq(expected_children_count, actual_children_count);
+}
+
+void
+check_efl_model_children_count_ge(Efl_Model_Base *efl_model, unsigned int minimum_children_count)
+{
+ unsigned int actual_children_count = 0;
+ Efl_Model_Load_Status status;
+ eo_do(efl_model, status = efl_model_children_count_get(&actual_children_count));
+ // A minimum count only exists if model have EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN
+ ck_assert((EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN & status) == EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ ck_assert_int_ge(actual_children_count, minimum_children_count);
+}
+
+void
+check_efl_model_children_slice_get(Efl_Model_Base *efl_model)
+{
+ unsigned int count = 0;
+ Efl_Model_Load_Status status;
+ eo_do(efl_model, status = efl_model_children_count_get(&count));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_msg(count, "There must be at least 1 child to test");
+
+ // Test slice all
+ Eina_Accessor *accessor;
+ eo_do(efl_model, status = efl_model_children_slice_get(0, 0, &accessor));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_ne(NULL, accessor);
+ // Get first child
+ Eo *first_child = NULL;
+ Eina_Bool ret = eina_accessor_data_get(accessor, 0, (void**)&first_child);
+ ck_assert(ret);
+ ck_assert_ptr_ne(NULL, first_child);
+ // get last child
+ Eo *last_child = NULL;
+ ret = eina_accessor_data_get(accessor, count - 1, (void**)&last_child);
+ ck_assert(ret);
+ ck_assert_ptr_ne(NULL, last_child);
+ // Test nonexistent child
+ Eo *nonexistent_child = NULL;
+ ret = eina_accessor_data_get(accessor, count, (void**)&nonexistent_child);
+ ck_assert(!ret);
+ ck_assert_ptr_eq(NULL, nonexistent_child);
+ eina_accessor_free(accessor);
+
+ // Test slice first child
+ Eo *child = NULL;
+ eo_do(efl_model, status = efl_model_children_slice_get(1, 1, &accessor));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_ne(NULL, accessor);
+ ret = eina_accessor_data_get(accessor, 0, (void**)&child);
+ ck_assert(ret);
+ ck_assert_ptr_ne(NULL, child);
+ ret = eina_accessor_data_get(accessor, 1, (void**)&child);
+ ck_assert(!ret);
+ ck_assert_ptr_eq(first_child, child);
+ eina_accessor_free(accessor);
+
+ // Test slice last child
+ eo_do(efl_model, status = efl_model_children_slice_get(count, 1, &accessor));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_ne(NULL, accessor);
+ ret = eina_accessor_data_get(accessor, 0, (void**)&child);
+ ck_assert(ret);
+ ck_assert_ptr_ne(NULL, child);
+ ret = eina_accessor_data_get(accessor, 1, (void**)&child);
+ ck_assert(!ret);
+ ck_assert_ptr_eq(last_child, child);
+ eina_accessor_free(accessor);
+
+ // Test slice nonexistent element
+ eo_do(efl_model, status = efl_model_children_slice_get(count + 1, 1, &accessor));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_eq(NULL, accessor);
+}
+
+START_TEST(smoke)
+{
+ check_init();
+
+ Eo *connection = create_and_load_connection();
+ eo_unref(connection);
+
+ check_shutdown();
+}
+END_TEST
+
+START_TEST(object)
+{
+ check_init();
+
+ Eo *root = create_object();
+
+ efl_model_load_and_wait_for_load_status(root, EFL_MODEL_LOAD_STATUS_LOADED);
+
+ eo_unref(root);
+
+ check_shutdown();
+}
+END_TEST
+
+START_TEST(proxy)
+{
+ check_init();
+
+ Eo *root = create_object();
+
+ efl_model_load_and_wait_for_load_status(root, EFL_MODEL_LOAD_STATUS_LOADED);
+
+ Eina_Accessor *accessor = NULL;
+ eo_do(root, efl_model_children_slice_get(0, 0, &accessor));
+ ck_assert_ptr_ne(NULL, accessor);
+
+ unsigned int i;
+ Eo *proxy;
+ EINA_ACCESSOR_FOREACH(accessor, i, proxy)
+ {
+ fprintf(stderr, "proxy %p\n", proxy);
+ efl_model_load_and_wait_for_load_status(proxy, EFL_MODEL_LOAD_STATUS_LOADED);
+ }
+ eina_accessor_free(accessor);
+
+ eo_unref(root);
+
+ check_shutdown();
+}
+END_TEST
+
+void
+eldbus_test_eldbus_model(TCase *tc)
+{
+ tcase_add_test(tc, smoke);
+ tcase_add_test(tc, object);
+ tcase_add_test(tc, proxy);
+}
+
+Eldbus_Model_Proxy *
+eldbus_model_proxy_from_object_get(Eldbus_Model_Object *object, const char *interface_name)
+{
+ Eina_Accessor *accessor;
+ Efl_Model_Load_Status status;
+ eo_do(object, status = efl_model_children_slice_get(0, 0, &accessor));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_ne(NULL, accessor);
+
+ Eo *proxy = NULL;
+ unsigned int i;
+ EINA_ACCESSOR_FOREACH(accessor, i, proxy)
+ {
+ const char *name;
+ eo_do(proxy, name = eldbus_model_proxy_name_get());
+ ck_assert_ptr_ne(NULL, name);
+ if (strcmp(name, interface_name) == 0)
+ goto end;
+ }
+ proxy = NULL;
+
+end:
+ eina_accessor_free(accessor);
+ return proxy;
+}
+
+static Eldbus_Model_Arguments *
+_eldbus_model_arguments_from_proxy_get(Eldbus_Model_Proxy *proxy, const char *method_name, const Eo_Class *klass)
+{
+ Eina_Accessor *accessor;
+ Efl_Model_Load_Status status;
+ eo_do(proxy, status = efl_model_children_slice_get(0, 0, &accessor));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_ne(NULL, accessor);
+
+ Eo *child = NULL;
+ unsigned int i;
+ EINA_ACCESSOR_FOREACH(accessor, i, child)
+ {
+ if (!eo_isa(child, klass))
+ continue;
+
+ const char *name;
+ eo_do(child, name = eldbus_model_arguments_name_get/*eldbus_model_arguments_name_get*/());
+ ck_assert_ptr_ne(NULL, name);
+ if (strcmp(name, method_name) == 0)
+ goto end;
+ }
+ child = NULL;
+
+end:
+ eina_accessor_free(accessor);
+ return child;
+}
+
+Eldbus_Model_Method *
+eldbus_model_method_from_proxy_get(Eldbus_Model_Proxy *proxy, const char *method_name)
+{
+ return _eldbus_model_arguments_from_proxy_get(proxy, method_name, ELDBUS_MODEL_METHOD_CLASS);
+}
+
+Eldbus_Model_Signal *
+eldbus_model_signal_from_proxy_get(Eldbus_Model_Proxy *proxy, const char *signal_name)
+{
+ return _eldbus_model_arguments_from_proxy_get(proxy, signal_name, ELDBUS_MODEL_SIGNAL_CLASS);
+}
+
+void
+check_efl_model_property_int_eq(Efl_Model_Base *efl_model, const char *property, int expected_value)
+{
+ Eina_Value const* property_value;
+ Efl_Model_Load_Status status;
+ eo_do(efl_model, status = efl_model_property_get(property, &property_value));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
+
+ const Eina_Value_Type *property_type = eina_value_type_get(property_value);
+ ck_assert_ptr_eq(EINA_VALUE_TYPE_INT, property_type);
+
+ fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
+
+ int actual_value = 0;
+ eina_value_get(property_value, &actual_value);
+ ck_assert_int_eq(expected_value, actual_value);
+
+ fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
+}
+
+void
+check_efl_model_property_int_set(Efl_Model_Base *efl_model, const char *property, int value)
+{
+ Eina_Value eina_value;
+ eina_value_setup(&eina_value, EINA_VALUE_TYPE_INT);
+ eina_value_set(&eina_value, value);
+ Efl_Model_Load_Status status;
+ eo_do(efl_model, status = efl_model_property_set(property, &eina_value));
+ eina_value_flush(&eina_value);
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+}
+
diff --git a/src/tests/eldbus/eldbus_test_eldbus_model.h b/src/tests/eldbus/eldbus_test_eldbus_model.h
new file mode 100644
index 0000000000..2d8603a72d
--- /dev/null
+++ b/src/tests/eldbus/eldbus_test_eldbus_model.h
@@ -0,0 +1,32 @@
+#ifndef _ELDBUS_TEST_ELDBUS_MODEL_H
+#define _ELDBUS_TEST_ELDBUS_MODEL_H
+
+#include <Eldbus_Model.h>
+#include <Efl.h>
+#include <Eo.h>
+
+void check_init(void);
+void check_shutdown(void);
+Eo *create_connection(void);
+Eo *create_and_load_connection(void);
+Eo *create_object(void);
+Eo *create_and_load_object(void);
+
+void efl_model_wait_for_event(Eo *obj, const Eo_Event_Description *event);
+void efl_model_wait_for_load_status(Eo *obj, Efl_Model_Load_Status expected_status);
+void efl_model_load_and_wait_for_load_status(Eo *obj, Efl_Model_Load_Status expected_status);
+Efl_Model_Base *efl_model_nth_child_get(Efl_Model_Base *obj, unsigned int n);
+Efl_Model_Base *efl_model_first_child_get(Efl_Model_Base *efl_model);
+
+void check_efl_model_load_status_get(Efl_Model_Base *obj, Efl_Model_Load_Status expected_load_status);
+void check_efl_model_children_count_eq(Efl_Model_Base *obj, unsigned int expected_children_count);
+void check_efl_model_children_count_ge(Efl_Model_Base *obj, unsigned int minimum_children_count);
+void check_efl_model_children_slice_get(Efl_Model_Base *efl_model);
+void check_efl_model_property_int_eq(Efl_Model_Base *obj, const char *property, int expected_value);
+void check_efl_model_property_int_set(Efl_Model_Base *obj, const char *property, int value);
+
+Eldbus_Model_Proxy *eldbus_model_proxy_from_object_get(Eldbus_Model_Object *object, const char *interface_name);
+Eldbus_Model_Method *eldbus_model_method_from_proxy_get(Eldbus_Model_Proxy *proxy, const char *method_name);
+Eldbus_Model_Signal *eldbus_model_signal_from_proxy_get(Eldbus_Model_Proxy *proxy, const char *signal_name);
+
+#endif
diff --git a/src/tests/eldbus/eldbus_test_eldbus_model_connection.c b/src/tests/eldbus/eldbus_test_eldbus_model_connection.c
new file mode 100644
index 0000000000..94a135af4c
--- /dev/null
+++ b/src/tests/eldbus/eldbus_test_eldbus_model_connection.c
@@ -0,0 +1,200 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_suite.h"
+#include "eldbus_test_eldbus_model.h"
+
+#include <Ecore.h>
+#include <Eina.h>
+#include <Eldbus_Model.h>
+
+#include <stdbool.h>
+
+static Eo *connection = NULL;
+static Eo *unloaded_connection = NULL;
+
+#define UNIQUE_NAME_PROPERTY "unique_name"
+
+static void
+_setup(void)
+{
+ check_init();
+ connection = create_and_load_connection();
+ unloaded_connection = create_connection();
+}
+
+static void
+_teardown(void)
+{
+ eo_unref(unloaded_connection);
+ eo_unref(connection);
+ check_shutdown();
+}
+
+START_TEST(load_status_get)
+{
+ check_efl_model_load_status_get(connection, EFL_MODEL_LOAD_STATUS_LOADED);
+ check_efl_model_load_status_get(unloaded_connection, EFL_MODEL_LOAD_STATUS_UNLOADED);
+}
+END_TEST
+
+START_TEST(properties_list_get)
+{
+ Eina_Array *properties = NULL;
+ Efl_Model_Load_Status status;
+ eo_do(connection, status = efl_model_properties_get(&properties));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_ne(NULL, properties);
+
+ const unsigned int expected_properties_count = 1;
+ unsigned int actual_properties_count = eina_array_count(properties);
+ ck_assert_int_eq(expected_properties_count, actual_properties_count);
+
+ // Unloaded connection populates its properties
+ eo_do(unloaded_connection, status = efl_model_properties_get(&properties));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_UNLOADED, status);
+ ck_assert_ptr_ne(NULL, properties);
+
+ actual_properties_count = eina_array_count(properties);
+ ck_assert_int_eq(expected_properties_count, actual_properties_count);
+}
+END_TEST
+
+START_TEST(property_get)
+{
+ Eina_Value const* property_value;
+ Efl_Model_Load_Status status;
+ eo_do(connection, status = efl_model_property_get(UNIQUE_NAME_PROPERTY, &property_value));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ // Nonexistent property must return EFL_MODEL_LOAD_STATUS_ERROR
+ eo_do(connection, status = efl_model_property_get("nonexistent", &property_value));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+START_TEST(property_set)
+{
+ // Nonexistent property must return EFL_MODEL_LOAD_STATUS_ERROR
+ Eina_Value value;
+ eina_value_setup(&value, EINA_VALUE_TYPE_INT);
+ eina_value_set(&value, 1);
+ Efl_Model_Load_Status status;
+ eo_do(connection, status = efl_model_property_set("nonexistent", &value));
+ eina_value_flush(&value);
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+
+ // UNIQUE_NAME_PROPERTY is read-only
+ eo_do(connection, status = efl_model_property_set(UNIQUE_NAME_PROPERTY, &value));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+
+ // The model must be loaded to be able to set its properties
+ const char *expected_value = "unloaded";
+ eina_value_setup(&value, EINA_VALUE_TYPE_STRING);
+ eina_value_set(&value, expected_value);
+ eo_do(unloaded_connection, status = efl_model_property_set(UNIQUE_NAME_PROPERTY, &value));
+ eina_value_flush(&value);
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+static void
+_test_children_count(Eo *efl_model)
+{
+ // At least this connection <unique_name> and 'org.freedesktop.DBus' must exist
+ check_efl_model_children_count_ge(efl_model, 2);
+}
+
+START_TEST(children_count)
+{
+ _test_children_count(connection);
+}
+END_TEST
+
+START_TEST(children_slice_get)
+{
+ check_efl_model_children_slice_get(connection);
+
+ // Unloaded connection must return EFL_MODEL_LOAD_STATUS_UNLOADED
+ Eina_Accessor *accessor;
+ Efl_Model_Load_Status status;
+ eo_do(unloaded_connection, status = efl_model_children_slice_get(0, 0, &accessor));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_UNLOADED, status);
+ ck_assert_ptr_eq(NULL, accessor);
+}
+END_TEST
+
+START_TEST(unload)
+{
+ check_efl_model_load_status_get(connection, EFL_MODEL_LOAD_STATUS_LOADED);
+ eo_do(connection, efl_model_unload());
+ check_efl_model_load_status_get(connection, EFL_MODEL_LOAD_STATUS_UNLOADED);
+
+ check_efl_model_children_count_eq(connection, 0);
+}
+END_TEST
+
+START_TEST(properties_load)
+{
+ eo_do(unloaded_connection, efl_model_properties_load());
+ check_efl_model_load_status_get(unloaded_connection, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+}
+END_TEST
+
+START_TEST(children_load)
+{
+ eo_do(unloaded_connection, efl_model_children_load());
+
+ check_efl_model_load_status_get(unloaded_connection, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
+
+ efl_model_wait_for_load_status(unloaded_connection, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ check_efl_model_load_status_get(unloaded_connection, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ _test_children_count(unloaded_connection);
+}
+END_TEST
+
+START_TEST(child_add)
+{
+ Eo *child;
+ eo_do(connection, child = efl_model_child_add());
+ ck_assert_ptr_eq(NULL, child);
+}
+END_TEST
+
+START_TEST(child_del)
+{
+ unsigned int expected_children_count = 0;
+ Efl_Model_Load_Status status;
+ eo_do(connection, status = efl_model_children_count_get(&expected_children_count));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ Eo *child = efl_model_first_child_get(connection);
+ eo_do(connection, status = efl_model_child_del(child));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+
+ unsigned int actual_children_count = 0;
+ eo_do(connection, status = efl_model_children_count_get(&actual_children_count));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ ck_assert_int_le(expected_children_count, actual_children_count);
+}
+END_TEST
+
+void eldbus_test_eldbus_model_connection(TCase *tc)
+{
+ tcase_add_checked_fixture(tc, _setup, _teardown);
+ tcase_add_test(tc, load_status_get);
+ tcase_add_test(tc, properties_list_get);
+ tcase_add_test(tc, property_get);
+ tcase_add_test(tc, property_set);
+ tcase_add_test(tc, children_count);
+ tcase_add_test(tc, children_slice_get);
+ tcase_add_test(tc, unload);
+ tcase_add_test(tc, properties_load);
+ tcase_add_test(tc, children_load);
+ tcase_add_test(tc, child_add);
+ tcase_add_test(tc, child_del);
+}
diff --git a/src/tests/eldbus/eldbus_test_eldbus_model_method.c b/src/tests/eldbus/eldbus_test_eldbus_model_method.c
new file mode 100644
index 0000000000..7c2f6176ff
--- /dev/null
+++ b/src/tests/eldbus/eldbus_test_eldbus_model_method.c
@@ -0,0 +1,220 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_fake_server.h"
+#include "eldbus_suite.h"
+#include "eldbus_test_eldbus_model.h"
+
+#include <Ecore.h>
+#include <Eina.h>
+#include <Eldbus_Model.h>
+
+#include <stdbool.h>
+
+#define ARGUMENT_A "arg0"
+#define ARGUMENT_B "arg1"
+#define ARGUMENT_RESULT "arg2"
+
+static Eo *fake_server_object = NULL;
+static Eo *fake_server_proxy = NULL;
+static Eldbus_Service_Interface *fake_server = NULL;
+static Fake_Server_Data fake_server_data = {0};
+static Eo *method = NULL;
+
+static void
+_setup(void)
+{
+ check_init();
+
+ fake_server = fake_server_start(&fake_server_data);
+
+ fake_server_object = eo_add(ELDBUS_MODEL_OBJECT_CLASS, NULL,
+ eldbus_model_object_constructor(ELDBUS_CONNECTION_TYPE_SESSION,
+ NULL,
+ EINA_FALSE,
+ FAKE_SERVER_BUS,
+ FAKE_SERVER_PATH));
+ ck_assert_ptr_ne(NULL, fake_server_object);
+
+ efl_model_load_and_wait_for_load_status(fake_server_object, EFL_MODEL_LOAD_STATUS_LOADED);
+
+ fake_server_proxy = eldbus_model_proxy_from_object_get(fake_server_object, FAKE_SERVER_INTERFACE);
+ ck_assert_ptr_ne(NULL, fake_server_proxy);
+
+ efl_model_load_and_wait_for_load_status(fake_server_proxy, EFL_MODEL_LOAD_STATUS_LOADED);
+
+ method = eldbus_model_method_from_proxy_get(fake_server_proxy, FAKE_SERVER_SUM_METHOD_NAME);
+ ck_assert_ptr_ne(NULL, method);
+
+ efl_model_load_and_wait_for_load_status(method, EFL_MODEL_LOAD_STATUS_LOADED);
+}
+
+static void
+_teardown(void)
+{
+ eo_unref(fake_server_object);
+
+ fake_server_stop(fake_server);
+
+ check_shutdown();
+}
+
+START_TEST(load_status_get)
+{
+ check_efl_model_load_status_get(method, EFL_MODEL_LOAD_STATUS_LOADED);
+}
+END_TEST
+
+START_TEST(properties_list_get)
+{
+ Eina_Array *properties = NULL;
+ Efl_Model_Load_Status status;
+ eo_do(method, status = efl_model_properties_get(&properties));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_ne(NULL, properties);
+
+ const unsigned int expected_properties_count = 3; // a, b and result arguments of 'sum' method
+ const unsigned int actual_properties_count = eina_array_count(properties);
+ ck_assert_int_eq(expected_properties_count, actual_properties_count);
+}
+END_TEST
+
+START_TEST(property_get)
+{
+ // Input only property returns error
+ Eina_Value const* dummy;
+ Efl_Model_Load_Status status;
+ eo_do(method, status = efl_model_property_get(ARGUMENT_A, &dummy));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+
+ eo_do(method, status = efl_model_property_get(ARGUMENT_RESULT, &dummy));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ // Nonexistent property returns error
+ eo_do(method, status = efl_model_property_get("nonexistent", &dummy));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+START_TEST(property_set)
+{
+ // Output argument returns error
+ Eina_Value dummy = {0};
+ Efl_Model_Load_Status status;
+ eo_do(method, status = efl_model_property_set(ARGUMENT_RESULT, &dummy));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+static void
+_test_method_children_count(Eo *efl_model)
+{
+ check_efl_model_children_count_eq(efl_model, 0);
+}
+
+START_TEST(children_count)
+{
+ _test_method_children_count(method);
+}
+END_TEST
+
+START_TEST(children_slice_get)
+{
+ Eina_Accessor *accessor;
+ Efl_Model_Load_Status status;
+ eo_do(method, status = efl_model_children_slice_get(1, 1, &accessor));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_eq(NULL, accessor);
+}
+END_TEST
+
+static void
+_check_unload(void)
+{
+ check_efl_model_load_status_get(method, EFL_MODEL_LOAD_STATUS_LOADED);
+ eo_do(method, efl_model_unload());
+ check_efl_model_load_status_get(method, EFL_MODEL_LOAD_STATUS_UNLOADED);
+
+ check_efl_model_children_count_eq(method, 0);
+}
+
+START_TEST(unload)
+{
+ _check_unload();
+}
+END_TEST
+
+START_TEST(properties_load)
+{
+ _check_unload();
+
+ eo_do(method, efl_model_properties_load());
+ efl_model_wait_for_load_status(method, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+
+ check_efl_model_load_status_get(method, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+}
+END_TEST
+
+START_TEST(children_load)
+{
+ _check_unload();
+
+ eo_do(method, efl_model_children_load());
+ efl_model_wait_for_load_status(method, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ check_efl_model_load_status_get(method, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ _test_method_children_count(method);
+}
+END_TEST
+
+START_TEST(child_add)
+{
+ Eo *child;
+ eo_do(method, child = efl_model_child_add());
+ ck_assert_ptr_eq(NULL, child);
+}
+END_TEST
+
+START_TEST(child_del)
+{
+ // efl_model_child_del always returns ERROR
+ Eo *child = NULL;
+ Efl_Model_Load_Status status;
+ eo_do(method, status = efl_model_child_del(child));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+START_TEST(call)
+{
+ check_efl_model_property_int_set(method, ARGUMENT_A, 12345678);
+ check_efl_model_property_int_set(method, ARGUMENT_B, 87654321);
+
+ Efl_Model_Load_Status status;
+ eo_do(method, status = eldbus_model_method_call());
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ efl_model_wait_for_event(method, ELDBUS_MODEL_METHOD_EVENT_SUCCESSFUL_CALL);
+
+ check_efl_model_property_int_eq(method, ARGUMENT_RESULT, 99999999);
+}
+END_TEST
+
+void eldbus_test_eldbus_model_method(TCase *tc)
+{
+ tcase_add_checked_fixture(tc, _setup, _teardown);
+ tcase_add_test(tc, load_status_get);
+ tcase_add_test(tc, properties_list_get);
+ tcase_add_test(tc, property_get);
+ tcase_add_test(tc, property_set);
+ tcase_add_test(tc, children_count);
+ tcase_add_test(tc, children_slice_get);
+ tcase_add_test(tc, unload);
+ tcase_add_test(tc, properties_load);
+ tcase_add_test(tc, children_load);
+ tcase_add_test(tc, child_add);
+ tcase_add_test(tc, child_del);
+ tcase_add_test(tc, call);
+}
diff --git a/src/tests/eldbus/eldbus_test_eldbus_model_object.c b/src/tests/eldbus/eldbus_test_eldbus_model_object.c
new file mode 100644
index 0000000000..b1acb177cb
--- /dev/null
+++ b/src/tests/eldbus/eldbus_test_eldbus_model_object.c
@@ -0,0 +1,201 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_suite.h"
+#include "eldbus_test_eldbus_model.h"
+
+#include <Ecore.h>
+#include <Eina.h>
+#include <Eldbus_Model.h>
+
+#include <stdbool.h>
+
+static Eo *object = NULL;
+static Eo *unloaded_object = NULL;
+
+#define UNIQUE_NAME_PROPERTY "unique_name"
+
+static void
+_setup(void)
+{
+ check_init();
+ object = create_and_load_object();
+ unloaded_object = create_object();
+}
+
+static void
+_teardown(void)
+{
+ eo_unref(unloaded_object);
+ eo_unref(object);
+ check_shutdown();
+}
+
+START_TEST(load_status_get)
+{
+ check_efl_model_load_status_get(object, EFL_MODEL_LOAD_STATUS_LOADED);
+ check_efl_model_load_status_get(unloaded_object, EFL_MODEL_LOAD_STATUS_UNLOADED);
+}
+END_TEST
+
+START_TEST(properties_list_get)
+{
+ Eina_Array *properties = NULL;
+ Efl_Model_Load_Status status;
+ eo_do(object, status = efl_model_properties_get(&properties));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_ne(NULL, properties);
+
+ const unsigned int expected_properties_count = 1;
+ unsigned int actual_properties_count = eina_array_count(properties);
+ ck_assert_int_eq(expected_properties_count, actual_properties_count);
+
+ // Unloaded object populates its properties
+ eo_do(unloaded_object, status = efl_model_properties_get(&properties));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_UNLOADED, status);
+ ck_assert_ptr_ne(NULL, properties);
+
+ actual_properties_count = eina_array_count(properties);
+ ck_assert_int_eq(expected_properties_count, actual_properties_count);
+}
+END_TEST
+
+START_TEST(property_get)
+{
+ Eina_Value property_value;
+ Efl_Model_Load_Status status;
+ eo_do(object, status = efl_model_property_get(UNIQUE_NAME_PROPERTY, &property_value));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ eina_value_flush(&property_value);
+
+ // Nonexistent property must return EFL_MODEL_LOAD_STATUS_ERROR
+ eo_do(object, status = efl_model_property_get("nonexistent", &property_value));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+START_TEST(property_set)
+{
+ // Nonexistent property must return EFL_MODEL_LOAD_STATUS_ERROR
+ Eina_Value value;
+ eina_value_setup(&value, EINA_VALUE_TYPE_INT);
+ eina_value_set(&value, 1);
+ Efl_Model_Load_Status status;
+ eo_do(object, status = efl_model_property_set("nonexistent", &value));
+ eina_value_flush(&value);
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+
+ // UNIQUE_NAME_PROPERTY is read-only
+ eo_do(object, status = efl_model_property_set(UNIQUE_NAME_PROPERTY, &value));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+
+ // The model must be loaded to be able to set its properties
+ const char *expected_value = "unloaded";
+ eina_value_setup(&value, EINA_VALUE_TYPE_STRING);
+ eina_value_set(&value, expected_value);
+ eo_do(unloaded_object, status = efl_model_property_set(UNIQUE_NAME_PROPERTY, &value));
+ eina_value_flush(&value);
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+static void
+_test_children_count(Eo *efl_model)
+{
+ // 'org.freedesktop.DBus' and 'org.freedesktop.DBus.Introspectable'
+ check_efl_model_children_count_ge(efl_model, 2);
+}
+
+START_TEST(children_count)
+{
+ _test_children_count(object);
+}
+END_TEST
+
+START_TEST(children_slice_get)
+{
+ check_efl_model_children_slice_get(object);
+
+ // Unloaded object must return EFL_MODEL_LOAD_STATUS_UNLOADED
+ Eina_Accessor *accessor;
+ Efl_Model_Load_Status status;
+ eo_do(unloaded_object, status = efl_model_children_slice_get(0, 0, &accessor));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_UNLOADED, status);
+ ck_assert_ptr_eq(NULL, accessor);
+}
+END_TEST
+
+START_TEST(unload)
+{
+ check_efl_model_load_status_get(object, EFL_MODEL_LOAD_STATUS_LOADED);
+ eo_do(object, efl_model_unload());
+ check_efl_model_load_status_get(object, EFL_MODEL_LOAD_STATUS_UNLOADED);
+
+ check_efl_model_children_count_eq(object, 0);
+}
+END_TEST
+
+START_TEST(properties_load)
+{
+ eo_do(unloaded_object, efl_model_properties_load());
+ check_efl_model_load_status_get(unloaded_object, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+}
+END_TEST
+
+START_TEST(children_load)
+{
+ eo_do(unloaded_object, efl_model_children_load());
+
+ check_efl_model_load_status_get(unloaded_object, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
+
+ efl_model_wait_for_load_status(unloaded_object, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ check_efl_model_load_status_get(unloaded_object, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ _test_children_count(unloaded_object);
+}
+END_TEST
+
+START_TEST(child_add)
+{
+ Eo *child;
+ eo_do(object, child = efl_model_child_add());
+ ck_assert_ptr_eq(NULL, child);
+}
+END_TEST
+
+START_TEST(child_del)
+{
+ unsigned int expected_children_count = 0;
+ Efl_Model_Load_Status status;
+ eo_do(object, status = efl_model_children_count_get(&expected_children_count));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ Eo *child = efl_model_first_child_get(object);
+ eo_do(object, status = efl_model_child_del(child));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+
+ unsigned int actual_children_count = 0;
+ eo_do(object, status = efl_model_children_count_get(&actual_children_count));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ ck_assert_int_le(expected_children_count, actual_children_count);
+}
+END_TEST
+
+void eldbus_test_eldbus_model_object(TCase *tc)
+{
+ tcase_add_checked_fixture(tc, _setup, _teardown);
+ tcase_add_test(tc, load_status_get);
+ tcase_add_test(tc, properties_list_get);
+ tcase_add_test(tc, property_get);
+ tcase_add_test(tc, property_set);
+ tcase_add_test(tc, children_count);
+ tcase_add_test(tc, children_slice_get);
+ tcase_add_test(tc, unload);
+ tcase_add_test(tc, properties_load);
+ tcase_add_test(tc, children_load);
+ tcase_add_test(tc, child_add);
+ tcase_add_test(tc, child_del);
+}
diff --git a/src/tests/eldbus/eldbus_test_eldbus_model_proxy.c b/src/tests/eldbus/eldbus_test_eldbus_model_proxy.c
new file mode 100644
index 0000000000..01bf1d8d5b
--- /dev/null
+++ b/src/tests/eldbus/eldbus_test_eldbus_model_proxy.c
@@ -0,0 +1,184 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_suite.h"
+#include "eldbus_test_eldbus_model.h"
+
+#include <Ecore.h>
+#include <Eina.h>
+#include <Eldbus_Model.h>
+
+#include <stdbool.h>
+
+static Eo *dbus_object1 = NULL;
+static Eo *dbus_object2 = NULL;
+static Eo *dbus_proxy = NULL;
+static Eo *unloaded_dbus_proxy = NULL;
+
+static void
+_setup(void)
+{
+ check_init();
+ dbus_object1 = create_and_load_object();
+ dbus_object2 = create_and_load_object();
+
+ dbus_proxy = eldbus_model_proxy_from_object_get(dbus_object1, ELDBUS_FDO_INTERFACE);
+ ck_assert_ptr_ne(NULL, dbus_proxy);
+ efl_model_load_and_wait_for_load_status(dbus_proxy, EFL_MODEL_LOAD_STATUS_LOADED);
+
+ unloaded_dbus_proxy = eldbus_model_proxy_from_object_get(dbus_object2, ELDBUS_FDO_INTERFACE);
+ ck_assert_ptr_ne(NULL, dbus_proxy);
+}
+
+static void
+_teardown(void)
+{
+ eo_unref(dbus_object2);
+ eo_unref(dbus_object1);
+ check_shutdown();
+}
+
+START_TEST(load_status_get)
+{
+ check_efl_model_load_status_get(dbus_proxy, EFL_MODEL_LOAD_STATUS_LOADED);
+ check_efl_model_load_status_get(unloaded_dbus_proxy, EFL_MODEL_LOAD_STATUS_UNLOADED);
+}
+END_TEST
+
+START_TEST(properties_list_get)
+{
+ // ELDBUS_FDO_INTERFACE have no properties
+ Eina_Array *properties = NULL;
+ Efl_Model_Load_Status status;
+ eo_do(dbus_proxy, status = efl_model_properties_get(&properties));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_ne(NULL, properties);
+ ck_assert_int_eq(0, eina_array_count(properties));
+
+ // Must be loaded to get the properties
+ eo_do(unloaded_dbus_proxy, status = efl_model_properties_get(&properties));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+START_TEST(property_get)
+{
+ // Nonexistent property must return EFL_MODEL_LOAD_STATUS_ERROR
+ Eina_Value property_value;
+ Efl_Model_Load_Status status;
+ eo_do(dbus_proxy, status = efl_model_property_get("nonexistent", &property_value));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+START_TEST(property_set)
+{
+ // Nonexistent property must return EFL_MODEL_LOAD_STATUS_ERROR
+ Eina_Value value;
+ eina_value_setup(&value, EINA_VALUE_TYPE_INT);
+ eina_value_set(&value, 1);
+ Efl_Model_Load_Status status;
+ eo_do(dbus_proxy, status = efl_model_property_set("nonexistent", &value));
+ eina_value_flush(&value);
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+static void
+_test_dbus_proxy_children_count(Eo *efl_model)
+{
+ // 'org.freedesktop.DBus::AddMatch' and 'org.freedesktop.DBus::ListNames' at least
+ check_efl_model_children_count_ge(efl_model, 2);
+}
+
+START_TEST(children_count)
+{
+ _test_dbus_proxy_children_count(dbus_proxy);
+}
+END_TEST
+
+START_TEST(children_slice_get)
+{
+ check_efl_model_children_slice_get(dbus_proxy);
+
+ // Unloaded dbus_proxy must return EFL_MODEL_LOAD_STATUS_UNLOADED
+ Eina_Accessor *accessor;
+ Efl_Model_Load_Status status;
+ eo_do(unloaded_dbus_proxy, status = efl_model_children_slice_get(0, 0, &accessor));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_UNLOADED, status);
+ ck_assert_ptr_eq(NULL, accessor);
+}
+END_TEST
+
+START_TEST(unload)
+{
+ check_efl_model_load_status_get(dbus_proxy, EFL_MODEL_LOAD_STATUS_LOADED);
+ eo_do(dbus_proxy, efl_model_unload());
+ check_efl_model_load_status_get(dbus_proxy, EFL_MODEL_LOAD_STATUS_UNLOADED);
+
+ check_efl_model_children_count_eq(dbus_proxy, 0);
+}
+END_TEST
+
+START_TEST(properties_load)
+{
+ eo_do(unloaded_dbus_proxy, efl_model_properties_load());
+ check_efl_model_load_status_get(unloaded_dbus_proxy, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+}
+END_TEST
+
+START_TEST(children_load)
+{
+ eo_do(unloaded_dbus_proxy, efl_model_children_load());
+
+ efl_model_wait_for_load_status(unloaded_dbus_proxy, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ check_efl_model_load_status_get(unloaded_dbus_proxy, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ _test_dbus_proxy_children_count(unloaded_dbus_proxy);
+}
+END_TEST
+
+START_TEST(child_add)
+{
+ Eo *child;
+ eo_do(dbus_proxy, child = efl_model_child_add());
+ ck_assert_ptr_eq(NULL, child);
+}
+END_TEST
+
+START_TEST(child_del)
+{
+ unsigned int expected_children_count = 0;
+ Efl_Model_Load_Status status;
+ eo_do(dbus_proxy, status = efl_model_children_count_get(&expected_children_count));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ Eo *child = efl_model_first_child_get(dbus_proxy);
+ eo_do(dbus_proxy, status = efl_model_child_del(child));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+
+ unsigned int actual_children_count = 0;
+ eo_do(dbus_proxy, status = efl_model_children_count_get(&actual_children_count));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ ck_assert_int_le(expected_children_count, actual_children_count);
+}
+END_TEST
+
+void eldbus_test_eldbus_model_proxy(TCase *tc)
+{
+ tcase_add_checked_fixture(tc, _setup, _teardown);
+ tcase_add_test(tc, load_status_get);
+ tcase_add_test(tc, properties_list_get);
+ tcase_add_test(tc, property_get);
+ tcase_add_test(tc, property_set);
+ tcase_add_test(tc, children_count);
+ tcase_add_test(tc, children_slice_get);
+ tcase_add_test(tc, unload);
+ tcase_add_test(tc, properties_load);
+ tcase_add_test(tc, children_load);
+ tcase_add_test(tc, child_add);
+ tcase_add_test(tc, child_del);
+}
diff --git a/src/tests/eldbus/eldbus_test_eldbus_model_signal.c b/src/tests/eldbus/eldbus_test_eldbus_model_signal.c
new file mode 100644
index 0000000000..ed880cad11
--- /dev/null
+++ b/src/tests/eldbus/eldbus_test_eldbus_model_signal.c
@@ -0,0 +1,219 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_fake_server.h"
+#include "eldbus_suite.h"
+#include "eldbus_test_eldbus_model.h"
+
+#include <Ecore.h>
+#include <Eina.h>
+#include <Eldbus_Model.h>
+
+#include <stdbool.h>
+
+#define ARGUMENT_A "arg0"
+
+static Eo *fake_server_object = NULL;
+static Eo *fake_server_proxy = NULL;
+static Eldbus_Service_Interface *fake_server = NULL;
+static Fake_Server_Data fake_server_data = {0};
+static Eo *pong_signal = NULL;
+
+static void
+_setup(void)
+{
+ check_init();
+
+ fake_server = fake_server_start(&fake_server_data);
+
+ fake_server_object = eo_add(ELDBUS_MODEL_OBJECT_CLASS, NULL,
+ eldbus_model_object_constructor(ELDBUS_CONNECTION_TYPE_SESSION,
+ NULL,
+ EINA_FALSE,
+ FAKE_SERVER_BUS,
+ FAKE_SERVER_PATH));
+ ck_assert_ptr_ne(NULL, fake_server_object);
+
+ efl_model_load_and_wait_for_load_status(fake_server_object, EFL_MODEL_LOAD_STATUS_LOADED);
+
+ fake_server_proxy = eldbus_model_proxy_from_object_get(fake_server_object, FAKE_SERVER_INTERFACE);
+ ck_assert_ptr_ne(NULL, fake_server_proxy);
+
+ efl_model_load_and_wait_for_load_status(fake_server_proxy, EFL_MODEL_LOAD_STATUS_LOADED);
+
+ pong_signal = eldbus_model_signal_from_proxy_get(fake_server_proxy, FAKE_SERVER_PONG_SIGNAL_NAME);
+ ck_assert_ptr_ne(NULL, pong_signal);
+
+ efl_model_load_and_wait_for_load_status(pong_signal, EFL_MODEL_LOAD_STATUS_LOADED);
+}
+
+static void
+_teardown(void)
+{
+ eo_unref(fake_server_object);
+
+ fake_server_stop(fake_server);
+
+ check_shutdown();
+}
+
+START_TEST(load_status_get)
+{
+ check_efl_model_load_status_get(pong_signal, EFL_MODEL_LOAD_STATUS_LOADED);
+}
+END_TEST
+
+START_TEST(properties_list_get)
+{
+ Eina_Array *properties = NULL;
+ Efl_Model_Load_Status status;
+ eo_do(pong_signal, status = efl_model_properties_get(&properties));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_ne(NULL, properties);
+
+ const unsigned int expected_properties_count = 1; // 'response' only
+ const unsigned int actual_properties_count = eina_array_count(properties);
+ ck_assert_int_eq(expected_properties_count, actual_properties_count);
+}
+END_TEST
+
+START_TEST(property_get)
+{
+ // Signal properties always have output direction
+ Eina_Value dummy = {0};
+ Efl_Model_Load_Status status;
+ eo_do(pong_signal, status = efl_model_property_get(ARGUMENT_A, &dummy));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ // Nonexistent property must return EFL_MODEL_LOAD_STATUS_ERROR
+ eo_do(pong_signal, status = efl_model_property_get("nonexistent", &dummy));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+START_TEST(property_set)
+{
+ // Signals have output arguments only. All returns error
+ Eina_Value dummy = {0};
+ Efl_Model_Load_Status status;
+ eo_do(pong_signal, status = efl_model_property_set(ARGUMENT_A, &dummy));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+static void
+_test_signal_children_count(Eo *efl_model)
+{
+ check_efl_model_children_count_eq(efl_model, 0);
+}
+
+START_TEST(children_count)
+{
+ _test_signal_children_count(pong_signal);
+}
+END_TEST
+
+START_TEST(children_slice_get)
+{
+ Eina_Accessor *accessor;
+ Efl_Model_Load_Status status;
+ eo_do(pong_signal, status = efl_model_children_slice_get(1, 1, &accessor));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_eq(NULL, accessor);
+}
+END_TEST
+
+static void
+_check_unload(void)
+{
+ check_efl_model_load_status_get(pong_signal, EFL_MODEL_LOAD_STATUS_LOADED);
+ eo_do(pong_signal, efl_model_unload());
+ check_efl_model_load_status_get(pong_signal, EFL_MODEL_LOAD_STATUS_UNLOADED);
+
+ check_efl_model_children_count_eq(pong_signal, 0);
+}
+
+START_TEST(unload)
+{
+ _check_unload();
+}
+END_TEST
+
+START_TEST(properties_load)
+{
+ _check_unload();
+
+ eo_do(pong_signal, efl_model_properties_load());
+ efl_model_wait_for_load_status(pong_signal, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+
+ check_efl_model_load_status_get(pong_signal, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+}
+END_TEST
+
+START_TEST(children_load)
+{
+ _check_unload();
+
+ eo_do(pong_signal, efl_model_children_load());
+ efl_model_wait_for_load_status(pong_signal, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ check_efl_model_load_status_get(pong_signal, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ _test_signal_children_count(pong_signal);
+}
+END_TEST
+
+START_TEST(child_add)
+{
+ Eo *child;
+ eo_do(pong_signal, child = efl_model_child_add());
+ ck_assert_ptr_eq(NULL, child);
+}
+END_TEST
+
+START_TEST(child_del)
+{
+ // efl_model_child_del always returns ERROR
+ Eo *child = NULL;
+ Efl_Model_Load_Status status;
+ eo_do(pong_signal, status = efl_model_child_del(child));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+START_TEST(signals)
+{
+ Eldbus_Model_Method *ping_method = eldbus_model_method_from_proxy_get(fake_server_proxy, FAKE_SERVER_PING_METHOD_NAME);
+ ck_assert_ptr_ne(NULL, ping_method);
+
+ efl_model_load_and_wait_for_load_status(ping_method, EFL_MODEL_LOAD_STATUS_LOADED);
+
+ check_efl_model_property_int_set(ping_method, ARGUMENT_A, 99);
+
+ Efl_Model_Load_Status status;
+ eo_do(ping_method, status = eldbus_model_method_call());
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ efl_model_wait_for_event(pong_signal, EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED);
+
+ check_efl_model_property_int_eq(pong_signal, ARGUMENT_A, 100);
+}
+END_TEST
+
+void eldbus_test_eldbus_model_signal(TCase *tc)
+{
+ /* tcase_add_checked_fixture(tc, _setup, _teardown); */
+ /* tcase_add_test(tc, load_status_get); */
+ /* tcase_add_test(tc, properties_list_get); */
+ /* tcase_add_test(tc, property_get); */
+ /* tcase_add_test(tc, property_set); */
+ /* tcase_add_test(tc, children_count); */
+ /* tcase_add_test(tc, children_slice_get); */
+ /* tcase_add_test(tc, unload); */
+ /* tcase_add_test(tc, properties_load); */
+ /* tcase_add_test(tc, children_load); */
+ /* tcase_add_test(tc, child_add); */
+ /* tcase_add_test(tc, child_del); */
+ /* tcase_add_test(tc, signals); */
+}
diff --git a/src/tests/eldbus/eldbus_test_fake_server_eldbus_model_proxy.c b/src/tests/eldbus/eldbus_test_fake_server_eldbus_model_proxy.c
new file mode 100644
index 0000000000..a7d77d6a21
--- /dev/null
+++ b/src/tests/eldbus/eldbus_test_fake_server_eldbus_model_proxy.c
@@ -0,0 +1,246 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eldbus_fake_server.h"
+#include "eldbus_suite.h"
+#include "eldbus_test_eldbus_model.h"
+
+#include <Ecore.h>
+#include <Eina.h>
+#include <Eldbus_Model.h>
+
+#include <stdbool.h>
+
+static Eo *fake_server_object = NULL;
+static Eo *fake_server_proxy = NULL;
+static Eldbus_Service_Interface *fake_server = NULL;
+static Fake_Server_Data fake_server_data = {0};
+
+#define FAKE_SERVER_READONLY_PROPERTY_VALUE 1111
+#define FAKE_SERVER_WRITEONLY_PROPERTY_VALUE 2222
+#define FAKE_SERVER_READWRITE_PROPERTY_VALUE 3333
+
+static void
+_setup(void)
+{
+ check_init();
+
+ fake_server_data = (Fake_Server_Data){
+ .readonly_property = FAKE_SERVER_READONLY_PROPERTY_VALUE,
+ .writeonly_property = FAKE_SERVER_WRITEONLY_PROPERTY_VALUE,
+ .readwrite_property = FAKE_SERVER_READWRITE_PROPERTY_VALUE
+ };
+ fake_server = fake_server_start(&fake_server_data);
+
+ fake_server_object = eo_add(ELDBUS_MODEL_OBJECT_CLASS, NULL,
+ eldbus_model_object_constructor(ELDBUS_CONNECTION_TYPE_SESSION,
+ NULL,
+ EINA_FALSE,
+ FAKE_SERVER_BUS,
+ FAKE_SERVER_PATH));
+ ck_assert_ptr_ne(NULL, fake_server_object);
+
+ efl_model_load_and_wait_for_load_status(fake_server_object, EFL_MODEL_LOAD_STATUS_LOADED);
+
+ fake_server_proxy = eldbus_model_proxy_from_object_get(fake_server_object, FAKE_SERVER_INTERFACE);
+
+ efl_model_load_and_wait_for_load_status(fake_server_proxy, EFL_MODEL_LOAD_STATUS_LOADED);
+}
+
+static void
+_teardown(void)
+{
+ eo_unref(fake_server_object);
+
+ fake_server_stop(fake_server);
+
+ check_shutdown();
+}
+
+START_TEST(load_status_get)
+{
+ check_efl_model_load_status_get(fake_server_proxy, EFL_MODEL_LOAD_STATUS_LOADED);
+}
+END_TEST
+
+START_TEST(properties_get)
+{
+ Eina_Array *properties = NULL;
+ Efl_Model_Load_Status status;
+ eo_do(fake_server_proxy, status = efl_model_properties_get(&properties));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+ ck_assert_ptr_ne(NULL, properties);
+
+ const unsigned int expected_properties_count = 3; // FAKE_SERVER_READONLY_PROPERTY, FAKE_SERVER_WRITEONLY_PROPERTY and FAKE_SERVER_READWRITE_PROPERTY properties
+ const unsigned int actual_properties_count = eina_array_count(properties);
+ ck_assert_int_eq(expected_properties_count, actual_properties_count);
+}
+END_TEST
+
+START_TEST(property_get)
+{
+ /* check_efl_model_property_int_eq(fake_server_proxy, FAKE_SERVER_READONLY_PROPERTY, FAKE_SERVER_READONLY_PROPERTY_VALUE); */
+ check_efl_model_property_int_eq(fake_server_proxy, FAKE_SERVER_READWRITE_PROPERTY, FAKE_SERVER_READWRITE_PROPERTY_VALUE);
+
+ /* // Write-only property returns error */
+ /* Eina_Value const* dummy; */
+ /* Efl_Model_Load_Status status; */
+ /* eo_do(fake_server_proxy, status = efl_model_property_get(FAKE_SERVER_WRITEONLY_PROPERTY, &dummy)); */
+ /* ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status); */
+}
+END_TEST
+
+static void
+_check_property_set(const char *property_name, int expected_property_value, int *actual_property_value)
+{
+ Eina_Value value;
+ eina_value_setup(&value, EINA_VALUE_TYPE_INT);
+ eina_value_set(&value, expected_property_value);
+ Efl_Model_Load_Status status;
+ eo_do(fake_server_proxy, status = efl_model_property_set(property_name, &value));
+ eina_value_flush(&value);
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ efl_model_wait_for_event(fake_server_proxy, EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED);
+
+ ck_assert_int_eq(expected_property_value, *actual_property_value);
+}
+
+START_TEST(property_set)
+{
+ _check_property_set(FAKE_SERVER_WRITEONLY_PROPERTY, 0x12345678, &fake_server_data.writeonly_property);
+ _check_property_set(FAKE_SERVER_READWRITE_PROPERTY, 0x76543210, &fake_server_data.readwrite_property);
+
+ // Read-only property returns error
+ Eina_Value dummy = {0};
+ Efl_Model_Load_Status status;
+ eo_do(fake_server_proxy, status = efl_model_property_set(FAKE_SERVER_READONLY_PROPERTY, &dummy));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+}
+END_TEST
+
+static void
+_test_fake_server_proxy_children_count(Eo *efl_model)
+{
+ // 'Sum' and 'Ping' methods and 'Pong' signal
+ check_efl_model_children_count_eq(efl_model, 3);
+}
+
+START_TEST(children_count)
+{
+ _test_fake_server_proxy_children_count(fake_server_proxy);
+}
+END_TEST
+
+START_TEST(children_slice_get)
+{
+ Eldbus_Model_Arguments *method1 = efl_model_nth_child_get(fake_server_proxy, 1);
+ Eldbus_Model_Arguments *method2 = efl_model_nth_child_get(fake_server_proxy, 2);
+ Eldbus_Model_Arguments *signal1 = efl_model_nth_child_get(fake_server_proxy, 3);
+
+ const char *actual_method1_name;
+ eo_do(method1, actual_method1_name = eldbus_model_arguments_name_get());
+ const char *actual_method2_name;
+ eo_do(method2, actual_method2_name = eldbus_model_arguments_name_get());
+ const char *actual_signal1_name;
+ eo_do(signal1, actual_signal1_name = eldbus_model_arguments_name_get());
+
+ ck_assert_ptr_ne(NULL, actual_method1_name);
+ ck_assert_ptr_ne(NULL, actual_method2_name);
+ ck_assert_ptr_ne(NULL, actual_signal1_name);
+
+ // Eldbus doesn't have order for method names. Methods order are determined by Eina_Hash
+ if (strcmp(FAKE_SERVER_SUM_METHOD_NAME, actual_method1_name) == 0)
+ ck_assert(strcmp(FAKE_SERVER_PING_METHOD_NAME, actual_method2_name) == 0);
+ else
+ ck_assert(strcmp(FAKE_SERVER_SUM_METHOD_NAME, actual_method2_name) == 0);
+
+ ck_assert(strcmp(FAKE_SERVER_PONG_SIGNAL_NAME, actual_signal1_name) == 0);
+}
+END_TEST
+
+static void
+_check_unload(void)
+{
+ check_efl_model_load_status_get(fake_server_proxy, EFL_MODEL_LOAD_STATUS_LOADED);
+ eo_do(fake_server_proxy, efl_model_unload());
+ check_efl_model_load_status_get(fake_server_proxy, EFL_MODEL_LOAD_STATUS_UNLOADED);
+
+ check_efl_model_children_count_eq(fake_server_proxy, 0);
+}
+
+START_TEST(unload)
+{
+ _check_unload();
+}
+END_TEST
+
+START_TEST(properties_load)
+{
+ _check_unload();
+
+ eo_do(fake_server_proxy, efl_model_properties_load());
+ efl_model_wait_for_load_status(fake_server_proxy, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+
+ check_efl_model_load_status_get(fake_server_proxy, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+}
+END_TEST
+
+START_TEST(children_load)
+{
+ _check_unload();
+
+ eo_do(fake_server_proxy, efl_model_children_load());
+ efl_model_wait_for_load_status(fake_server_proxy, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ check_efl_model_load_status_get(fake_server_proxy, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ _test_fake_server_proxy_children_count(fake_server_proxy);
+}
+END_TEST
+
+START_TEST(child_add)
+{
+ Eo *child;
+ eo_do(fake_server_proxy, child = efl_model_child_add());
+ ck_assert_ptr_eq(NULL, child);
+}
+END_TEST
+
+START_TEST(child_del)
+{
+ // Tests that it is not possible to delete children
+ unsigned int expected_children_count = 0;
+ Efl_Model_Load_Status status;
+ eo_do(fake_server_proxy, status = efl_model_children_count_get(&expected_children_count));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ // efl_model_child_del always returns ERROR
+ Eo *child = efl_model_first_child_get(fake_server_proxy);
+ eo_do(fake_server_proxy, status = efl_model_child_del(child));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_ERROR, status);
+
+ unsigned int actual_children_count = 0;
+ eo_do(fake_server_proxy, status = efl_model_children_count_get(&actual_children_count));
+ ck_assert_int_eq(EFL_MODEL_LOAD_STATUS_LOADED, status);
+
+ ck_assert_int_le(expected_children_count, actual_children_count);
+}
+END_TEST
+
+void eldbus_test_fake_server_eldbus_model_proxy(TCase *tc)
+{
+ tcase_add_checked_fixture(tc, _setup, _teardown);
+ tcase_add_test(tc, load_status_get);
+ tcase_add_test(tc, properties_get);
+ tcase_add_test(tc, property_get);
+ tcase_add_test(tc, property_set);
+ tcase_add_test(tc, children_count);
+ tcase_add_test(tc, children_slice_get);
+ tcase_add_test(tc, unload);
+ tcase_add_test(tc, properties_load);
+ tcase_add_test(tc, children_load);
+ tcase_add_test(tc, child_add);
+ tcase_add_test(tc, child_del);
+}