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-08-31 16:47:48 -0300
commit132e320017101f796473a93bf4e0feb0dc3698ad (patch)
treea1c99b376022a78de26d4ecf3008af16d9614a64
parent6a1025c09e7c2f0489c64a3d09e48fd4197213fc (diff)
eldbus: Created Emodel implementation for Eldbus
-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_Model_Common.h5
-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.c15
-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.c419
-rw-r--r--src/lib/eldbus/eldbus_model_arguments.eo40
-rw-r--r--src/lib/eldbus/eldbus_model_arguments_private.h29
-rw-r--r--src/lib/eldbus/eldbus_model_connection.c372
-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.c103
-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.c546
-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.c684
-rw-r--r--src/lib/eldbus/eldbus_model_proxy.eo39
-rw-r--r--src/lib/eldbus/eldbus_model_proxy_private.h30
-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.h9
-rw-r--r--src/lib/eldbus/eldbus_proxy.c36
-rw-r--r--src/tests/eldbus/eldbus_fake_server.c182
-rw-r--r--src/tests/eldbus/eldbus_fake_server.h29
-rw-r--r--src/tests/eldbus/eldbus_suite.c9
-rw-r--r--src/tests/eldbus/eldbus_suite.h7
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model.c412
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model.h32
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model_connection.c201
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model_method.c220
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model_object.c200
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model_proxy.c184
-rw-r--r--src/tests/eldbus/eldbus_test_eldbus_model_signal.c220
-rw-r--r--src/tests/eldbus/eldbus_test_fake_server_eldbus_model_proxy.c264
45 files changed, 5499 insertions, 13 deletions
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 @@
1 1
2### Library 2### Library
3 3
4eldbus_eolian_files = \
5 lib/eldbus/eldbus_model_connection.eo \
6 lib/eldbus/eldbus_model_object.eo \
7 lib/eldbus/eldbus_model_proxy.eo \
8 lib/eldbus/eldbus_model_method.eo \
9 lib/eldbus/eldbus_model_arguments.eo \
10 lib/eldbus/eldbus_model_signal.eo
11
12eldbus_eolian_c = $(eldbus_eolian_files:%.eo=%.eo.c)
13eldbus_eolian_h = $(eldbus_eolian_files:%.eo=%.eo.h)
14
15BUILT_SOURCES += \
16 $(eldbus_eolian_c) \
17 $(eldbus_eolian_h)
18
19CLEANFILES += \
20 $(eldbus_eolian_c) \
21 $(eldbus_eolian_h)
22
23eldbuseolianfilesdir = $(datadir)/eolian/include/eldbus-@VMAJ@
24eldbuseolianfiles_DATA = $(eldbus_eolian_files)
25
26EXTRA_DIST += \
27 ${eldbuseolianfiles_DATA}
28
4lib_LTLIBRARIES += lib/eldbus/libeldbus.la 29lib_LTLIBRARIES += lib/eldbus/libeldbus.la
5 30
6installed_eldbusmainheadersdir = $(includedir)/eldbus-@VMAJ@ 31installed_eldbusmainheadersdir = $(includedir)/eldbus-@VMAJ@
@@ -17,6 +42,8 @@ lib/eldbus/eldbus_signal_handler.h \
17lib/eldbus/eldbus_message_helper.h \ 42lib/eldbus/eldbus_message_helper.h \
18lib/eldbus/eldbus_message_eina_value.h 43lib/eldbus/eldbus_message_eina_value.h
19 44
45nodist_installed_eldbusmainheaders_DATA = $(eldbus_eolian_h)
46
20lib_eldbus_libeldbus_la_SOURCES = \ 47lib_eldbus_libeldbus_la_SOURCES = \
21lib/eldbus/eldbus_private.h \ 48lib/eldbus/eldbus_private.h \
22lib/eldbus/eldbus_private_types.h \ 49lib/eldbus/eldbus_private_types.h \
@@ -30,13 +57,20 @@ lib/eldbus/eldbus_service.c \
30lib/eldbus/eldbus_signal_handler.c \ 57lib/eldbus/eldbus_signal_handler.c \
31lib/eldbus/eldbus_message_helper.c \ 58lib/eldbus/eldbus_message_helper.c \
32lib/eldbus/eldbus_message_to_eina_value.c \ 59lib/eldbus/eldbus_message_to_eina_value.c \
33lib/eldbus/eldbus_message_from_eina_value.c 60lib/eldbus/eldbus_message_from_eina_value.c \
61lib/eldbus/eldbus_model_connection.c \
62lib/eldbus/eldbus_model_object.c \
63lib/eldbus/eldbus_model_proxy.c \
64lib/eldbus/eldbus_model_method.c \
65lib/eldbus/eldbus_model_arguments.c \
66lib/eldbus/eldbus_model_signal.c \
67lib/eldbus/eldbus_introspection.c
34 68
35lib_eldbus_libeldbus_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ 69lib_eldbus_libeldbus_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
36-include $(top_builddir)/config.h \ 70-include $(top_builddir)/config.h \
37@ELDBUS_CFLAGS@ 71@ELDBUS_CFLAGS@ @EFL_CFLAGS@
38lib_eldbus_libeldbus_la_LIBADD = @ELDBUS_LIBS@ 72lib_eldbus_libeldbus_la_LIBADD = @ELDBUS_LIBS@ @EFL_LIBS@
39lib_eldbus_libeldbus_la_DEPENDENCIES = @ELDBUS_INTERNAL_LIBS@ 73lib_eldbus_libeldbus_la_DEPENDENCIES = @ELDBUS_INTERNAL_LIBS@ @EFL_INTERNAL_LIBS@
40lib_eldbus_libeldbus_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@ 74lib_eldbus_libeldbus_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
41 75
42### Binary 76### Binary
@@ -74,12 +108,20 @@ TESTS += tests/eldbus/eldbus_suite
74tests_eldbus_eldbus_suite_SOURCES = \ 108tests_eldbus_eldbus_suite_SOURCES = \
75tests/eldbus/eldbus_suite.c \ 109tests/eldbus/eldbus_suite.c \
76tests/eldbus/eldbus_test_eldbus_init.c \ 110tests/eldbus/eldbus_test_eldbus_init.c \
111tests/eldbus/eldbus_test_eldbus_model.c \
112tests/eldbus/eldbus_test_eldbus_model_connection.c \
113tests/eldbus/eldbus_test_eldbus_model_object.c \
114tests/eldbus/eldbus_test_eldbus_model_proxy.c \
115tests/eldbus/eldbus_test_eldbus_model_method.c \
116tests/eldbus/eldbus_test_eldbus_model_signal.c \
117tests/eldbus/eldbus_test_fake_server_eldbus_model_proxy.c \
118tests/eldbus/eldbus_fake_server.c \
77tests/eldbus/eldbus_suite.h 119tests/eldbus/eldbus_suite.h
78 120
79tests_eldbus_eldbus_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl @CHECK_CFLAGS@ @ELDBUS_CFLAGS@ \ 121tests_eldbus_eldbus_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl @CHECK_CFLAGS@ @ELDBUS_CFLAGS@ \
80-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eldbus\" 122@EFL_CFLAGS@ -DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eldbus\"
81 123
82tests_eldbus_eldbus_suite_LDADD = @CHECK_LIBS@ @USE_ELDBUS_LIBS@ 124tests_eldbus_eldbus_suite_LDADD = @CHECK_LIBS@ @USE_ELDBUS_LIBS@ @USE_EFL_LIBS@
83tests_eldbus_eldbus_suite_DEPENDENCIES = @USE_ELDBUS_INTERNAL_LIBS@ 125tests_eldbus_eldbus_suite_DEPENDENCIES = @USE_ELDBUS_INTERNAL_LIBS@
84 126
85endif 127endif
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 @@
1 1
2if HAVE_CXX11 2if HAVE_CXX11
3 3
4### Generated headers
5
6generated_eldbus_cxx_bindings = \
7 lib/eldbus/eldbus_model_connection.eo.hh \
8 lib/eldbus/eldbus_model_object.eo.hh \
9 lib/eldbus/eldbus_model_proxy.eo.hh \
10 lib/eldbus/eldbus_model_method.eo.hh \
11 lib/eldbus/eldbus_model_arguments.eo.hh \
12 lib/eldbus/eldbus_model_signal.eo.hh
13
14lib/eldbus/Eldbus_Model.hh: $(generated_eldbus_cxx_bindings)
15 @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
16 @echo @ECHO_E@ "#include <Eldbus_Model.h>" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
17 @echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
18 @for i in $(generated_eldbus_cxx_bindings); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh; done
19 @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
20
21generated_eldbus_cxx_all = \
22 $(generated_eldbus_cxx_bindings) \
23 lib/eldbus/Eldbus_Model.hh
24
25CLEANFILES += $(generated_eldbus_cxx_all)
26
27nodist_installed_eldbuscxxmainheaders_DATA = $(generated_eldbus_cxx_all)
28
4### Library 29### Library
5 30
6installed_eldbuscxxmainheadersdir = $(includedir)/eldbus_cxx-@VMAJ@ 31installed_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 \
17lib/elocation/gen/eldbus_geo_clue2_location.c \ 17lib/elocation/gen/eldbus_geo_clue2_location.c \
18lib/elocation/gen/eldbus_geo_clue2_manager.c 18lib/elocation/gen/eldbus_geo_clue2_manager.c
19 19
20lib_elocation_libelocation_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ELOCATION_CFLAGS@ 20lib_elocation_libelocation_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ELOCATION_CFLAGS@ @EFL_CFLAGS@
21lib_elocation_libelocation_la_LIBADD = @ELOCATION_LIBS@ 21lib_elocation_libelocation_la_LIBADD = @ELOCATION_LIBS@
22lib_elocation_libelocation_la_DEPENDENCIES = @ELOCATION_INTERNAL_LIBS@ 22lib_elocation_libelocation_la_DEPENDENCIES = @ELOCATION_INTERNAL_LIBS@
23lib_elocation_libelocation_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@ 23lib_elocation_libelocation_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
diff --git a/src/lib/efl/Efl_Model_Common.h b/src/lib/efl/Efl_Model_Common.h
index 1ff4356114..4f51b49d1a 100644
--- a/src/lib/efl/Efl_Model_Common.h
+++ b/src/lib/efl/Efl_Model_Common.h
@@ -95,3 +95,8 @@ EAPI Eina_Value_Struct_Desc *efl_model_value_struct_desc_new(unsigned int member
95 * @param desc The struct description. If @c NULL, the function returns immediately. 95 * @param desc The struct description. If @c NULL, the function returns immediately.
96 */ 96 */
97EAPI void efl_model_value_struct_desc_free(Eina_Value_Struct_Desc *desc); 97EAPI void efl_model_value_struct_desc_free(Eina_Value_Struct_Desc *desc);
98
99EAPI void efl_model_property_changed_notify(Efl_Model_Base *model, const char *property);
100
101EAPI void efl_model_property_invalidated_notify(Efl_Model_Base *model, const char *property);
102
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 @@
79#include <Eina.h> 79#include <Eina.h>
80#include <stdarg.h> 80#include <stdarg.h>
81#include <Efl_Config.h> 81#include <Efl_Config.h>
82#include <Eo.h>
83#include <Efl.h>
82 84
83#ifdef EAPI 85#ifdef EAPI
84# undef EAPI 86# undef EAPI
@@ -236,6 +238,13 @@ typedef void (*Eldbus_Signal_Cb)(void *data, const Eldbus_Message *msg);
236#include "eldbus_proxy.h" 238#include "eldbus_proxy.h"
237#include "eldbus_freedesktop.h" 239#include "eldbus_freedesktop.h"
238#include "eldbus_service.h" 240#include "eldbus_service.h"
241#include "eldbus_introspection.h"
242#include "eldbus_model_arguments.eo.h"
243#include "eldbus_model_connection.eo.h"
244#include "eldbus_model_method.eo.h"
245#include "eldbus_model_object.eo.h"
246#include "eldbus_model_proxy.eo.h"
247#include "eldbus_model_signal.eo.h"
239 248
240#ifdef __cplusplus 249#ifdef __cplusplus
241} 250}
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 @@
1#ifndef _ELDBUS_MODEL_H
2#define _ELDBUS_MODEL_H
3
4#include <Eldbus.h>
5#include <Efl.h>
6#include <Eo.h>
7
8#ifdef __cplusplus
9extern "C" {
10#endif
11
12#include <eldbus_model_connection.eo.h>
13#include <eldbus_model_object.eo.h>
14#include <eldbus_model_proxy.eo.h>
15#include <eldbus_model_arguments.eo.h>
16#include <eldbus_model_method.eo.h>
17#include <eldbus_model_signal.eo.h>
18
19#ifdef __cplusplus
20}
21#endif
22
23#endif
diff --git a/src/lib/eldbus/eldbus_core.c b/src/lib/eldbus/eldbus_core.c
index 1e4fde5d5b..715ce8e50d 100644
--- a/src/lib/eldbus/eldbus_core.c
+++ b/src/lib/eldbus/eldbus_core.c
@@ -73,6 +73,7 @@ EAPI const Eldbus_Version * eldbus_version = &_version;
73 73
74static int _eldbus_init_count = 0; 74static int _eldbus_init_count = 0;
75int _eldbus_log_dom = -1; 75int _eldbus_log_dom = -1;
76int eldbus_model_log_dom = -1;
76 77
77/* We don't save ELDBUS_CONNECTION_TYPE_UNKNOWN in here so we need room for 78/* We don't save ELDBUS_CONNECTION_TYPE_UNKNOWN in here so we need room for
78 * last - 1 elements */ 79 * last - 1 elements */
@@ -104,6 +105,16 @@ eldbus_init(void)
104 return 0; 105 return 0;
105 } 106 }
106 107
108 eldbus_model_log_dom = eina_log_domain_register("eldbus_model", EINA_COLOR_CYAN);
109 if (eldbus_model_log_dom < 0)
110 {
111 EINA_LOG_ERR("Unable to create an 'eldbus_model' log domain");
112 eina_log_domain_unregister(_eldbus_log_dom);
113 _eldbus_log_dom = -1;
114 eina_shutdown();
115 return 0;
116 }
117
107 if (!ecore_init()) 118 if (!ecore_init())
108 { 119 {
109 ERR("Unable to initialize ecore"); 120 ERR("Unable to initialize ecore");
@@ -144,6 +155,8 @@ signal_handler_failed:
144 eldbus_message_shutdown(); 155 eldbus_message_shutdown();
145message_failed: 156message_failed:
146 ecore_shutdown(); 157 ecore_shutdown();
158 eina_log_domain_unregister(eldbus_model_log_dom);
159 eldbus_model_log_dom = -1;
147 eina_log_domain_unregister(_eldbus_log_dom); 160 eina_log_domain_unregister(_eldbus_log_dom);
148 _eldbus_log_dom = -1; 161 _eldbus_log_dom = -1;
149 eina_shutdown(); 162 eina_shutdown();
@@ -245,6 +258,8 @@ eldbus_shutdown(void)
245 eldbus_message_shutdown(); 258 eldbus_message_shutdown();
246 259
247 ecore_shutdown(); 260 ecore_shutdown();
261 eina_log_domain_unregister(eldbus_model_log_dom);
262 eldbus_model_log_dom = -1;
248 eina_log_domain_unregister(_eldbus_log_dom); 263 eina_log_domain_unregister(_eldbus_log_dom);
249 _eldbus_log_dom = -1; 264 _eldbus_log_dom = -1;
250 eina_shutdown(); 265 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
240EAPI 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); 240EAPI 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);
241 241
242/** 242/**
243 * Set a property with a Eina_Value.
244 *
245 * @param proxy The proxy object on which to do the query.
246 * @param name The property name to get.
247 * @param sig
248 * @param value The value to set.
249 * @param cb The callback to be called when receiving an answer.
250 * @param data Data to be passed to the callback.
251 * @return Eldbus_Pending object corresponding to the message sent.
252 */
253EAPI 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);
254
255/**
243 * Get all properties. 256 * Get all properties.
244 * 257 *
245 * @param proxy The proxy object on which to do the query. 258 * @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 @@
1#include "eldbus_introspection.h"
2
3typedef struct _Eldbus_Introspection_Element_Parse_Table Eldbus_Introspection_Element_Parse_Table;
4
5struct _Eldbus_Introspection_Element_Parse_Table
6{
7 const char *name;
8 void *(*parse)(Eina_Simple_XML_Node_Tag *tag);
9 Eina_List **list;
10};
11
12static const char *_eldbus_introspection_attribute_value_get(Eina_Inlist *, const char *);
13static void *_eldbus_introspection_parse_node(Eina_Simple_XML_Node_Tag *);
14static void *_eldbus_introspection_parse_interface(Eina_Simple_XML_Node_Tag *);
15static void *_eldbus_introspection_parse_method(Eina_Simple_XML_Node_Tag *);
16static void *_eldbus_introspection_parse_signal(Eina_Simple_XML_Node_Tag *);
17static void *_eldbus_introspection_parse_argument(Eina_Simple_XML_Node_Tag *);
18static void *_eldbus_introspection_parse_property(Eina_Simple_XML_Node_Tag *);
19static void *_eldbus_introspection_parse_annotation(Eina_Simple_XML_Node_Tag *);
20static void _eldbus_introspection_parse_children(Eina_Inlist *, const Eldbus_Introspection_Element_Parse_Table[]);
21static void _eldbus_introspection_interface_free(Eldbus_Introspection_Interface *);
22static void _eldbus_introspection_method_free(Eldbus_Introspection_Method *);
23static void _eldbus_introspection_signal_free(Eldbus_Introspection_Signal *);
24static void _eldbus_introspection_argument_free(Eldbus_Introspection_Argument *);
25static void _eldbus_introspection_property_free(Eldbus_Introspection_Property *);
26static void _eldbus_introspection_annotation_free(Eldbus_Introspection_Annotation *);
27
28EAPI Eldbus_Introspection_Node *
29eldbus_introspection_parse(const char *xml)
30{
31 EINA_SAFETY_ON_NULL_RETURN_VAL(xml, NULL);
32
33 Eldbus_Introspection_Node *node = NULL;
34
35 Eina_Simple_XML_Node_Root *xml_root = eina_simple_xml_node_load(xml, strlen(xml), EINA_TRUE);
36
37 Eina_Simple_XML_Node *xml_node = (Eina_Simple_XML_Node*)eina_inlist_last(xml_root->children);
38 EINA_SAFETY_ON_FALSE_GOTO(EINA_SIMPLE_XML_NODE_TAG == xml_node->type, free_root);
39
40 node = (Eldbus_Introspection_Node*)_eldbus_introspection_parse_node((Eina_Simple_XML_Node_Tag*)xml_node);
41
42free_root:
43 eina_simple_xml_node_root_free(xml_root);
44
45 return node;
46}
47
48static void *
49_eldbus_introspection_parse_node(Eina_Simple_XML_Node_Tag *tag)
50{
51 Eldbus_Introspection_Node *node = calloc(1, sizeof(Eldbus_Introspection_Node));
52 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
53
54 const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
55 node->name = eina_stringshare_add(name);
56
57 Eldbus_Introspection_Element_Parse_Table table[] = {
58 {"node", _eldbus_introspection_parse_node, &node->nodes},
59 {"interface", _eldbus_introspection_parse_interface, &node->interfaces},
60 {NULL, NULL, NULL}
61 };
62 _eldbus_introspection_parse_children(tag->children, table);
63
64 return node;
65}
66
67EAPI void
68eldbus_introspection_node_free(Eldbus_Introspection_Node *node)
69{
70 EINA_SAFETY_ON_NULL_RETURN(node);
71
72 Eldbus_Introspection_Node *child_node;
73 EINA_LIST_FREE(node->nodes, child_node)
74 eldbus_introspection_node_free(child_node);
75
76 Eldbus_Introspection_Interface *interface;
77 EINA_LIST_FREE(node->interfaces, interface)
78 _eldbus_introspection_interface_free(interface);
79
80 eina_stringshare_del(node->name);
81 free(node);
82}
83
84static const char *
85_eldbus_introspection_attribute_value_get(Eina_Inlist *attributes, const char *key)
86{
87 Eina_Simple_XML_Attribute *attribute;
88 EINA_INLIST_FOREACH(attributes, attribute)
89 {
90 if (strcmp(attribute->key, key) == 0)
91 return attribute->value;
92 }
93
94 return NULL;
95}
96
97static void *
98_eldbus_introspection_parse_interface(Eina_Simple_XML_Node_Tag *tag)
99{
100 Eldbus_Introspection_Interface *interface = calloc(1, sizeof(Eldbus_Introspection_Interface));
101 EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
102
103 const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
104 EINA_SAFETY_ON_NULL_GOTO(name, error); // required
105 interface->name = eina_stringshare_add(name);
106
107 Eldbus_Introspection_Element_Parse_Table table[] = {
108 {"method", _eldbus_introspection_parse_method, &interface->methods},
109 {"signal", _eldbus_introspection_parse_signal, &interface->signals},
110 {"property", _eldbus_introspection_parse_property, &interface->properties},
111 {"annotation", _eldbus_introspection_parse_annotation, &interface->annotations},
112 {NULL, NULL, NULL}
113 };
114 _eldbus_introspection_parse_children(tag->children, table);
115
116 return interface;
117
118error:
119 _eldbus_introspection_interface_free(interface);
120 return NULL;
121}
122
123static void
124_eldbus_introspection_interface_free(Eldbus_Introspection_Interface *interface)
125{
126 EINA_SAFETY_ON_NULL_RETURN(interface);
127
128 Eldbus_Introspection_Method *method;
129 EINA_LIST_FREE(interface->methods, method)
130 _eldbus_introspection_method_free(method);
131
132 Eldbus_Introspection_Signal *signal;
133 EINA_LIST_FREE(interface->signals, signal)
134 _eldbus_introspection_signal_free(signal);
135
136 Eldbus_Introspection_Property *property;
137 EINA_LIST_FREE(interface->properties, property)
138 _eldbus_introspection_property_free(property);
139
140 Eldbus_Introspection_Annotation *annotation;
141 EINA_LIST_FREE(interface->annotations, annotation)
142 _eldbus_introspection_annotation_free(annotation);
143
144 eina_stringshare_del(interface->name);
145 free(interface);
146}
147
148static void *
149_eldbus_introspection_parse_method(Eina_Simple_XML_Node_Tag *tag)
150{
151 Eldbus_Introspection_Method *method = calloc(1, sizeof(Eldbus_Introspection_Method));
152 EINA_SAFETY_ON_NULL_RETURN_VAL(method, NULL);
153
154 const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
155 EINA_SAFETY_ON_NULL_GOTO(name, error); // required
156 method->name = eina_stringshare_add(name);
157
158 Eldbus_Introspection_Element_Parse_Table table[] = {
159 {"arg", _eldbus_introspection_parse_argument, &method->arguments},
160 {"annotation", _eldbus_introspection_parse_annotation, &method->annotations},
161 {NULL, NULL, NULL}
162 };
163 _eldbus_introspection_parse_children(tag->children, table);
164
165 return method;
166
167error:
168 _eldbus_introspection_method_free(method);
169 return NULL;
170}
171
172static void
173_eldbus_introspection_method_free(Eldbus_Introspection_Method *method)
174{
175 EINA_SAFETY_ON_NULL_RETURN(method);
176
177 Eldbus_Introspection_Argument *argument;
178 EINA_LIST_FREE(method->arguments, argument)
179 _eldbus_introspection_argument_free(argument);
180
181 Eldbus_Introspection_Annotation *annotation;
182 EINA_LIST_FREE(method->annotations, annotation)
183 _eldbus_introspection_annotation_free(annotation);
184
185 eina_stringshare_del(method->name);
186 free(method);
187}
188
189static void *
190_eldbus_introspection_parse_signal(Eina_Simple_XML_Node_Tag *tag)
191{
192 Eldbus_Introspection_Signal *signal = calloc(1, sizeof(Eldbus_Introspection_Signal));
193 EINA_SAFETY_ON_NULL_RETURN_VAL(signal, NULL);
194
195 const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
196 EINA_SAFETY_ON_NULL_GOTO(name, error); // required
197 signal->name = eina_stringshare_add(name);
198
199 Eldbus_Introspection_Element_Parse_Table table[] = {
200 {"arg", _eldbus_introspection_parse_argument, &signal->arguments},
201 {"annotation", _eldbus_introspection_parse_annotation, &signal->annotations},
202 {NULL, NULL, NULL}
203 };
204 _eldbus_introspection_parse_children(tag->children, table);
205
206 return signal;
207
208error:
209 _eldbus_introspection_signal_free(signal);
210 return NULL;
211}
212
213static void
214_eldbus_introspection_signal_free(Eldbus_Introspection_Signal *signal)
215{
216 EINA_SAFETY_ON_NULL_RETURN(signal);
217
218 Eldbus_Introspection_Argument *argument;
219 EINA_LIST_FREE(signal->arguments, argument)
220 _eldbus_introspection_argument_free(argument);
221
222 Eldbus_Introspection_Annotation *annotation;
223 EINA_LIST_FREE(signal->annotations, annotation)
224 _eldbus_introspection_annotation_free(annotation);
225
226 eina_stringshare_del(signal->name);
227 free(signal);
228}
229
230static void *
231_eldbus_introspection_parse_argument(Eina_Simple_XML_Node_Tag *tag)
232{
233 Eldbus_Introspection_Argument *argument = calloc(1, sizeof(Eldbus_Introspection_Argument));
234 EINA_SAFETY_ON_NULL_RETURN_VAL(argument, NULL);
235
236 const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
237 argument->name = eina_stringshare_add(name);
238
239 const char *type = _eldbus_introspection_attribute_value_get(tag->attributes, "type");
240 EINA_SAFETY_ON_NULL_GOTO(type, error); // required
241 argument->type = eina_stringshare_add(type);
242
243 const char *direction = _eldbus_introspection_attribute_value_get(tag->attributes, "direction");
244 if (direction)
245 {
246 //EINA_SAFETY_ON_NULL_GOTO(direction, error); // required for methods only
247 if (strcmp(direction, "in") == 0)
248 argument->direction = ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN;
249 else
250 if (strcmp(direction, "out") == 0)
251 argument->direction = ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_OUT;
252 else
253 argument->direction = ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_NONE;
254 }
255
256 return argument;
257
258error:
259 _eldbus_introspection_argument_free(argument);
260 return NULL;
261}
262
263static void
264_eldbus_introspection_argument_free(Eldbus_Introspection_Argument *argument)
265{
266 EINA_SAFETY_ON_NULL_RETURN(argument);
267 eina_stringshare_del(argument->name);
268 eina_stringshare_del(argument->type);
269 free(argument);
270}
271
272static void *
273_eldbus_introspection_parse_property(Eina_Simple_XML_Node_Tag *tag)
274{
275 Eldbus_Introspection_Property *property = calloc(1, sizeof(Eldbus_Introspection_Property));
276 EINA_SAFETY_ON_NULL_RETURN_VAL(property, NULL);
277
278 const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
279 EINA_SAFETY_ON_NULL_GOTO(name, error); // required
280 property->name = eina_stringshare_add(name);
281
282 const char *type = _eldbus_introspection_attribute_value_get(tag->attributes, "type");
283 EINA_SAFETY_ON_NULL_GOTO(type, error); // required
284 property->type = eina_stringshare_add(type);
285
286 const char *access = _eldbus_introspection_attribute_value_get(tag->attributes, "access");
287 EINA_SAFETY_ON_NULL_GOTO(access, error); // required
288 if (strcmp(access, "read") == 0)
289 property->access = ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READ;
290 else
291 if (strcmp(access, "write") == 0)
292 property->access = ELDBUS_INTROSPECTION_PROPERTY_ACCESS_WRITE;
293 else
294 if (strcmp(access, "readwrite") == 0)
295 property->access = ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE;
296 else
297 EINA_SAFETY_ON_TRUE_GOTO(!!"Unknown property access", error);
298
299 Eldbus_Introspection_Element_Parse_Table table[] = {
300 {"annotation", _eldbus_introspection_parse_annotation, &property->annotations},
301 {NULL, NULL, NULL}
302 };
303 _eldbus_introspection_parse_children(tag->children, table);
304
305 return property;
306
307error:
308 _eldbus_introspection_property_free(property);
309 return NULL;
310}
311
312static void
313_eldbus_introspection_property_free(Eldbus_Introspection_Property *property)
314{
315 EINA_SAFETY_ON_NULL_RETURN(property);
316
317 Eldbus_Introspection_Annotation *annotation;
318 EINA_LIST_FREE(property->annotations, annotation)
319 _eldbus_introspection_annotation_free(annotation);
320
321 eina_stringshare_del(property->name);
322 eina_stringshare_del(property->type);
323 free(property);
324}
325
326static void *
327_eldbus_introspection_parse_annotation(Eina_Simple_XML_Node_Tag *tag)
328{
329 Eldbus_Introspection_Annotation *annotation = calloc(1, sizeof(Eldbus_Introspection_Annotation));
330 EINA_SAFETY_ON_NULL_RETURN_VAL(annotation, NULL);
331
332 const char *name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
333 EINA_SAFETY_ON_NULL_GOTO(name, error); // required
334 annotation->name = eina_stringshare_add(name);
335
336 const char *value = _eldbus_introspection_attribute_value_get(tag->attributes, "value");
337 EINA_SAFETY_ON_NULL_GOTO(value, error); // required
338 annotation->value = eina_stringshare_add(value);
339
340 return annotation;
341
342error:
343 _eldbus_introspection_annotation_free(annotation);
344 return NULL;
345}
346
347static void
348_eldbus_introspection_annotation_free(Eldbus_Introspection_Annotation *annotation)
349{
350 EINA_SAFETY_ON_NULL_RETURN(annotation);
351 eina_stringshare_del(annotation->name);
352 eina_stringshare_del(annotation->value);
353 free(annotation);
354}
355
356static void
357_eldbus_introspection_parse_children(Eina_Inlist *children, const Eldbus_Introspection_Element_Parse_Table table[])
358{
359 Eina_Simple_XML_Node *child;
360 EINA_INLIST_FOREACH(children, child)
361 {
362 if (EINA_SIMPLE_XML_NODE_TAG != child->type)
363 continue;
364
365 Eina_Simple_XML_Node_Tag *tag = (Eina_Simple_XML_Node_Tag*)child;
366
367 for (const Eldbus_Introspection_Element_Parse_Table *it = table; it->name; ++it)
368 {
369 if (strcmp(tag->name, it->name) != 0)
370 continue;
371
372 void *item = it->parse(tag);
373 if (item)
374 *it->list = eina_list_append(*it->list, item);
375 }
376 }
377}
378
379EAPI Eldbus_Introspection_Interface *
380eldbus_introspection_interface_find(Eina_List *interfaces, const char *name)
381{
382 Eina_List *it;
383 Eldbus_Introspection_Interface *interface;
384 EINA_LIST_FOREACH(interfaces, it, interface)
385 {
386 if (strcmp(interface->name, name) == 0)
387 return interface;
388 }
389
390 return NULL;
391}
392
393EAPI Eldbus_Introspection_Property *
394eldbus_introspection_property_find(Eina_List *properties, const char *name)
395{
396 Eina_List *it;
397 Eldbus_Introspection_Property *property;
398 EINA_LIST_FOREACH(properties, it, property)
399 {
400 if (strcmp(property->name, name) == 0)
401 return property;
402 }
403
404 return NULL;
405}
406
407EAPI Eldbus_Introspection_Argument *
408eldbus_introspection_argument_find(Eina_List *arguments, const char *name)
409{
410 Eina_List *it;
411 Eldbus_Introspection_Argument *argument;
412 EINA_LIST_FOREACH(arguments, it, argument)
413 {
414 if (strcmp(argument->name, name) == 0)
415 return argument;
416 }
417
418 return NULL;
419}
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 @@
1#ifndef _ELDBUS_INTROSPECTION_INTROSPECTION_H
2#define _ELDBUS_INTROSPECTION_INTROSPECTION_H
3
4#include <Eina.h>
5
6// DTD conversion form: http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd
7
8typedef struct _Eldbus_Introspection_Node Eldbus_Introspection_Node;
9typedef struct _Eldbus_Introspection_Interface Eldbus_Introspection_Interface;
10typedef struct _Eldbus_Introspection_Method Eldbus_Introspection_Method;
11typedef struct _Eldbus_Introspection_Signal Eldbus_Introspection_Signal;
12typedef struct _Eldbus_Introspection_Argument Eldbus_Introspection_Argument;
13typedef struct _Eldbus_Introspection_Property Eldbus_Introspection_Property;
14typedef struct _Eldbus_Introspection_Annotation Eldbus_Introspection_Annotation;
15
16typedef enum
17{
18 ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_NONE = 0,
19 ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN,
20 ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_OUT,
21
22} Eldbus_Introspection_Argument_Direction;
23
24typedef enum
25{
26 ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READ,
27 ELDBUS_INTROSPECTION_PROPERTY_ACCESS_WRITE,
28 ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE,
29} Eldbus_Introspection_Property_Access;
30
31struct _Eldbus_Introspection_Node
32{
33 Eina_Stringshare *name; // optional
34 Eina_List *nodes;
35 Eina_List *interfaces;
36};
37
38struct _Eldbus_Introspection_Interface
39{
40 Eina_Stringshare *name;
41 Eina_List *methods;
42 Eina_List *signals;
43 Eina_List *properties;
44 Eina_List *annotations;
45};
46
47struct _Eldbus_Introspection_Method
48{
49 Eina_Stringshare *name;
50 Eina_List *arguments;
51 Eina_List *annotations;
52};
53
54struct _Eldbus_Introspection_Signal
55{
56 Eina_Stringshare *name;
57 Eina_List *arguments;
58 Eina_List *annotations;
59};
60
61struct _Eldbus_Introspection_Argument
62{
63 Eina_Stringshare *name; // optional
64 Eina_Stringshare *type;
65 Eldbus_Introspection_Argument_Direction direction;
66};
67
68struct _Eldbus_Introspection_Property
69{
70 Eina_Stringshare *name;
71 Eina_Stringshare *type;
72 Eldbus_Introspection_Property_Access access;
73 Eina_List *annotations;
74};
75
76struct _Eldbus_Introspection_Annotation
77{
78 Eina_Stringshare *name;
79 Eina_Stringshare *value;
80};
81
82/**
83 * @brief Parses the introspection xml abstracting it to an object tree
84 *
85 * @param xml The introspection xml
86 * @return The introspection object tree
87 */
88EAPI Eldbus_Introspection_Node *eldbus_introspection_parse(const char *xml);
89
90/**
91 * @brief Frees the introspection object tree
92 *
93 * @param node The root node of introspection tree
94 */
95EAPI void eldbus_introspection_node_free(Eldbus_Introspection_Node *node);
96
97/**
98 * @brief Finds an interface by name
99 *
100 * @param interfaces The list of interfaces of type @c Eldbus_Introspection_Interface
101 * @param name The interfaces's name to search for
102 * @return Returns the interface found or @c NULL if not
103 */
104EAPI Eldbus_Introspection_Interface *eldbus_introspection_interface_find(Eina_List *interfaces, const char *name);
105
106/**
107 * @brief Finds a property by name
108 *
109 * @param properties The list of properties of type @c Eldbus_Introspection_Property
110 * @param name The properties's name to search for
111 * @return Returns the property found or @c NULL if not
112 */
113EAPI Eldbus_Introspection_Property *eldbus_introspection_property_find(Eina_List *properties, const char *name);
114
115/**
116 * @brief Finds an argument by name
117 *
118 * @param arguments The list of arguments of type @c Eldbus_Introspection_Property
119 * @param name The arguments's name to search for
120 * @return Returns the argument found or @c NULL if not
121 */
122EAPI Eldbus_Introspection_Argument *eldbus_introspection_argument_find(Eina_List *arguments, const char *name);
123
124#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 @@
1#include "eldbus_private.h" 1#include "eldbus_private.h"
2#include "eldbus_private_types.h" 2#include "eldbus_private_types.h"
3 3
4#include <dbus/dbus-protocol.h>
5
4static Eina_Bool 6static Eina_Bool
5_compatible_type(int dbus_type, const Eina_Value_Type *value_type) 7_compatible_type(int dbus_type, const Eina_Value_Type *value_type)
6{ 8{
@@ -205,7 +207,7 @@ _array_append(const char *type, const Eina_Value *value_array, Eldbus_Message_It
205} 207}
206 208
207static Eina_Bool 209static Eina_Bool
208_basic_append(char type, const Eina_Value *value, const Eina_Value_Struct_Desc *desc, unsigned idx, Eldbus_Message_Iter *iter) 210_basic_append_value_struct(char type, const Eina_Value *value, const Eina_Value_Struct_Desc *desc, unsigned idx, Eldbus_Message_Iter *iter)
209{ 211{
210 EINA_SAFETY_ON_FALSE_RETURN_VAL( 212 EINA_SAFETY_ON_FALSE_RETURN_VAL(
211 _compatible_type(type, desc->members[idx].type), EINA_FALSE); 213 _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
305 { 307 {
306 DBG("type: %s", type); 308 DBG("type: %s", type);
307 if (type[0] != 'v' && !type[1]) 309 if (type[0] != 'v' && !type[1])
308 r = _basic_append(type[0], value, st.desc, i, iter); 310 r = _basic_append_value_struct(type[0], value, st.desc, i, iter);
309 else if (type[0] == 'a') 311 else if (type[0] == 'a')
310 { 312 {
311 Eina_Value value_array; 313 Eina_Value value_array;
@@ -367,3 +369,121 @@ eldbus_message_from_eina_value(const char *signature, Eldbus_Message *msg, const
367 369
368 return _message_iter_from_eina_value_struct(signature, iter, value); 370 return _message_iter_from_eina_value_struct(signature, iter, value);
369} 371}
372
373static Eina_Bool
374_basic_append_value(char type, const Eina_Value *value, Eldbus_Message_Iter *iter)
375{
376 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
377 const Eina_Value_Type *value_type = eina_value_type_get(value);
378 EINA_SAFETY_ON_FALSE_RETURN_VAL(_compatible_type(type, value_type), EINA_FALSE);
379 switch (type)
380 {
381 case 'i'://int
382 case 'h'://fd
383 {
384 int32_t i;
385 eina_value_get(value, &i);
386 eldbus_message_iter_basic_append(iter, type, i);
387 break;
388 }
389 case 's':
390 case 'o'://object path
391 case 'g'://signature
392 {
393 const char *txt;
394 eina_value_get(value, &txt);
395 eldbus_message_iter_basic_append(iter, type, txt);
396 break;
397 }
398 case 'b'://boolean
399 case 'y'://byte
400 {
401 unsigned char byte;
402 eina_value_get(value, &byte);
403 eldbus_message_iter_basic_append(iter, type, byte);
404 break;
405 }
406 case 'n'://int16
407 {
408 int16_t i;
409 eina_value_get(value, &i);
410 eldbus_message_iter_basic_append(iter, type, i);
411 break;
412 }
413 case 'q'://uint16
414 {
415 uint16_t i;
416 eina_value_get(value, &i);
417 eldbus_message_iter_basic_append(iter, type, i);
418 break;
419 }
420 case 'u'://uint32
421 {
422 uint32_t i;
423 eina_value_get(value, &i);
424 eldbus_message_iter_basic_append(iter, type, i);
425 break;
426 }
427 case 'x'://int64
428 {
429 int64_t i;
430 eina_value_get(value, &i);
431 eldbus_message_iter_basic_append(iter, type, i);
432 break;
433 }
434 case 't'://uint64
435 {
436 uint64_t i;
437 eina_value_get(value, &i);
438 eldbus_message_iter_basic_append(iter, type, i);
439 break;
440 }
441 case 'd'://double
442 {
443 double d;
444 eina_value_get(value, &d);
445 eldbus_message_iter_basic_append(iter, type, d);
446 break;
447 }
448 default:
449 ERR("Unexpected type %c", type);
450 return EINA_FALSE;
451 }
452 return EINA_TRUE;
453}
454
455Eina_Bool
456_message_iter_from_eina_value(const char *signature, Eldbus_Message_Iter *iter, const Eina_Value *value)
457{
458 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
459
460 const Eina_Value_Type *value_type = eina_value_type_get(value);
461 if (EINA_VALUE_TYPE_STRUCT == value_type || EINA_VALUE_TYPE_ARRAY == value_type)
462 return _message_iter_from_eina_value_struct(signature, iter, value);
463
464 Eina_Bool result = EINA_TRUE;
465 DBusSignatureIter signature_iter;
466 dbus_signature_iter_init(&signature_iter, signature);
467 char *type;
468 while ((type = dbus_signature_iter_get_signature(&signature_iter)))
469 {
470 DBG("type: %s", type);
471 if (DBUS_TYPE_VARIANT != type[0] && DBUS_TYPE_INVALID == type[1])
472 result = _basic_append_value(type[0], value, iter);
473 else if (DBUS_TYPE_ARRAY == type[0] ||
474 DBUS_STRUCT_BEGIN_CHAR == type[0] ||
475 DBUS_TYPE_VARIANT == type[0])
476 {
477 ERR("Not a basic type");
478 result = EINA_FALSE;
479 }
480 else
481 {
482 ERR("Unknown type %c", type[0]);
483 result = EINA_FALSE;
484 }
485 dbus_free(type);
486 if (!result || !dbus_signature_iter_next(&signature_iter)) break;
487 }
488 return result;
489}
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 @@
3 3
4static void _message_iter_basic_array_to_eina_value(char type, Eina_Value *value, Eldbus_Message_Iter *iter); 4static void _message_iter_basic_array_to_eina_value(char type, Eina_Value *value, Eldbus_Message_Iter *iter);
5 5
6static const Eina_Value_Type * 6const Eina_Value_Type *
7_dbus_type_to_eina_value_type(char type) 7_dbus_type_to_eina_value_type(char type)
8{ 8{
9 switch (type) 9 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..3329b081bc
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_arguments.c
@@ -0,0 +1,419 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "eldbus_model_arguments_private.h"
6#include "eldbus_model_private.h"
7
8#include <Eina.h>
9#include <Eldbus.h>
10
11#define MY_CLASS ELDBUS_MODEL_ARGUMENTS_CLASS
12#define MY_CLASS_NAME "Eldbus_Model_Arguments"
13
14#define ARGUMENT_FORMAT "arg%u"
15
16static void _eldbus_model_arguments_efl_model_base_properties_load(Eo *, Eldbus_Model_Arguments_Data *);
17static void _eldbus_model_arguments_efl_model_base_children_load(Eo *, Eldbus_Model_Arguments_Data *);
18static void _eldbus_model_arguments_unload(Eldbus_Model_Arguments_Data *);
19static bool _eldbus_model_arguments_is_input_argument(Eldbus_Model_Arguments_Data *, const char *);
20static bool _eldbus_model_arguments_is_output_argument(Eldbus_Model_Arguments_Data *, const char *);
21static Eina_Bool _eldbus_model_arguments_property_set(Eldbus_Model_Arguments_Data *, Eina_Value *, const char *);
22static unsigned int _eldbus_model_arguments_argument_index_get(Eldbus_Model_Arguments_Data *, const char *);
23
24static void
25_eldbus_model_arguments_hash_free(Eina_Value *value)
26{
27 eina_value_free(value);
28}
29
30static Eo_Base*
31_eldbus_model_arguments_eo_base_constructor(Eo *obj, Eldbus_Model_Arguments_Data *pd)
32{
33 DBG("(%p)", obj);
34 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
35
36 pd->obj = obj;
37 pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
38 pd->properties_array = NULL;
39 pd->properties_hash = eina_hash_string_superfast_new(EINA_FREE_CB(_eldbus_model_arguments_hash_free));
40 pd->pending_list = NULL;
41 pd->proxy = NULL;
42 pd->arguments = NULL;
43 pd->name = NULL;
44 return obj;
45}
46
47static void
48_eldbus_model_arguments_constructor(Eo *obj EINA_UNUSED,
49 Eldbus_Model_Arguments_Data *pd,
50 Eldbus_Proxy *proxy,
51 const char *name,
52 const Eina_List *arguments)
53{
54 DBG("(%p)", obj);
55 EINA_SAFETY_ON_NULL_RETURN(proxy);
56 EINA_SAFETY_ON_NULL_RETURN(name);
57
58 pd->proxy = eldbus_proxy_ref(proxy);
59 pd->arguments = arguments;
60 pd->name = eina_stringshare_add(name);
61}
62
63static void
64_eldbus_model_arguments_eo_base_destructor(Eo *obj, Eldbus_Model_Arguments_Data *pd)
65{
66 DBG("(%p)", obj);
67
68 _eldbus_model_arguments_unload(pd);
69
70 eina_hash_free(pd->properties_hash);
71
72 eina_stringshare_del(pd->name);
73 eldbus_proxy_unref(pd->proxy);
74
75 eo_do_super(obj, MY_CLASS, eo_destructor());
76}
77
78static Efl_Model_Load_Status
79_eldbus_model_arguments_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
80 Eldbus_Model_Arguments_Data *pd,
81 Eina_Array * const* properties_array)
82{
83 DBG("(%p)", obj);
84 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
85 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
86
87 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
88 {
89 ERR("%s", "o not loaded.");
90 return EFL_MODEL_LOAD_STATUS_ERROR;
91 }
92
93 *(Eina_Array**)properties_array = pd->properties_array;
94 return pd->load.status;
95}
96
97static void
98_eldbus_model_arguments_efl_model_base_properties_load(Eo *obj, Eldbus_Model_Arguments_Data *pd)
99{
100 DBG("(%p)", obj);
101
102 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
103 return;
104
105 unsigned int arguments_count = eina_list_count(pd->arguments);
106
107 pd->properties_array = eina_array_new(arguments_count);
108 EINA_SAFETY_ON_NULL_RETURN(pd->properties_array);
109
110 for (unsigned int i = 0; i < arguments_count; ++i)
111 {
112 Eina_Stringshare *name = eina_stringshare_printf(ARGUMENT_FORMAT, i);
113 EINA_SAFETY_ON_NULL_RETURN(name);
114
115 Eina_Bool ret = eina_array_push(pd->properties_array, name);
116 EINA_SAFETY_ON_FALSE_RETURN(ret);
117
118 Eldbus_Introspection_Argument *arg = eina_list_nth(pd->arguments, i);
119 const Eina_Value_Type *type = _dbus_type_to_eina_value_type(arg->type[0]);
120
121 Eina_Value *value = eina_value_new(type);
122 EINA_SAFETY_ON_NULL_RETURN(value);
123
124 ret = eina_hash_add(pd->properties_hash, name, value);
125 EINA_SAFETY_ON_FALSE_RETURN(ret);
126 }
127
128 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
129}
130
131static Efl_Model_Load_Status
132_eldbus_model_arguments_efl_model_base_property_set(Eo *obj EINA_UNUSED,
133 Eldbus_Model_Arguments_Data *pd,
134 const char *property,
135 Eina_Value const* value)
136{
137 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
138 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
139 DBG("(%p): property=%s", obj, property);
140
141 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
142 return EFL_MODEL_LOAD_STATUS_ERROR;
143
144 if (!_eldbus_model_arguments_is_input_argument(pd, property))
145 {
146 WRN("Property (argument) not found or it is for output only: %s", property);
147 return EFL_MODEL_LOAD_STATUS_ERROR;
148 }
149
150 Eina_Value *prop_value = eina_hash_find(pd->properties_hash, property);
151 EINA_SAFETY_ON_NULL_RETURN_VAL(prop_value, EFL_MODEL_LOAD_STATUS_ERROR);
152
153 eina_value_flush(prop_value);
154 Eina_Bool ret = eina_value_copy(value, prop_value);
155 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
156
157 return pd->load.status;
158}
159
160static Efl_Model_Load_Status
161_eldbus_model_arguments_efl_model_base_property_get(Eo *obj EINA_UNUSED,
162 Eldbus_Model_Arguments_Data *pd,
163 const char *property,
164 Eina_Value const ** value)
165{
166 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
167 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
168 DBG("(%p): property=%s", obj, property);
169
170 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
171 return EFL_MODEL_LOAD_STATUS_ERROR;
172
173 if (!_eldbus_model_arguments_is_output_argument(pd, property))
174 {
175 WRN("Property (argument) not found or it is for input only: %s", property);
176 return EFL_MODEL_LOAD_STATUS_ERROR;
177 }
178
179 *value = eina_hash_find(pd->properties_hash, property);
180 EINA_SAFETY_ON_NULL_RETURN_VAL(*value, EFL_MODEL_LOAD_STATUS_ERROR);
181
182 return pd->load.status;
183}
184
185static void
186_eldbus_model_arguments_efl_model_base_load(Eo *obj, Eldbus_Model_Arguments_Data *pd EINA_UNUSED)
187{
188 DBG("(%p)", obj);
189
190 eo_do(obj, efl_model_properties_load());
191 eo_do(obj, efl_model_children_load());
192}
193
194static Efl_Model_Load_Status
195_eldbus_model_arguments_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd)
196{
197 DBG("(%p)", obj);
198 return pd->load.status;
199}
200
201static void
202_eldbus_model_arguments_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd)
203{
204 DBG("(%p)", obj);
205
206 _eldbus_model_arguments_unload(pd);
207
208 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
209}
210
211Eo *
212_eldbus_model_arguments_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd EINA_UNUSED)
213{
214 DBG("(%p)", obj);
215 return NULL;
216}
217
218static Efl_Model_Load_Status
219_eldbus_model_arguments_efl_model_base_child_del(Eo *obj EINA_UNUSED,
220 Eldbus_Model_Arguments_Data *pd EINA_UNUSED,
221 Eo *child EINA_UNUSED)
222{
223 DBG("(%p)", obj);
224 return EFL_MODEL_LOAD_STATUS_ERROR;
225}
226
227static Efl_Model_Load_Status
228_eldbus_model_arguments_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
229 Eldbus_Model_Arguments_Data *pd,
230 unsigned start EINA_UNUSED,
231 unsigned count EINA_UNUSED,
232 Eina_Accessor **children_accessor)
233{
234 DBG("(%p)", obj);
235 *children_accessor = NULL;
236 return pd->load.status;
237}
238
239static Efl_Model_Load_Status
240_eldbus_model_arguments_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
241 Eldbus_Model_Arguments_Data *pd,
242 unsigned *children_count)
243{
244 DBG("(%p)", obj);
245 *children_count = 0;
246 return pd->load.status;
247}
248
249static void
250_eldbus_model_arguments_efl_model_base_children_load(Eo *obj, Eldbus_Model_Arguments_Data *pd)
251{
252 DBG("(%p)", obj);
253
254 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
255 return;
256
257 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
258}
259
260static const char *
261_eldbus_model_arguments_name_get(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd)
262{
263 return pd->name;
264}
265
266static void
267_eldbus_model_arguments_unload(Eldbus_Model_Arguments_Data *pd)
268{
269 EINA_SAFETY_ON_NULL_RETURN(pd);
270
271 Eldbus_Pending *pending;
272 EINA_LIST_FREE(pd->pending_list, pending)
273 eldbus_pending_cancel(pending);
274
275 if (pd->properties_array)
276 {
277 unsigned int i;
278 Eina_Stringshare *property;
279 Eina_Array_Iterator it;
280 EINA_ARRAY_ITER_NEXT(pd->properties_array, i, property, it)
281 eina_stringshare_del(property);
282 eina_array_free(pd->properties_array);
283 pd->properties_array = NULL;
284 }
285
286 eina_hash_free_buckets(pd->properties_hash);
287}
288
289bool
290eldbus_model_arguments_process_arguments(Eldbus_Model_Arguments_Data *pd,
291 const Eldbus_Message *msg,
292 Eldbus_Pending *pending)
293{
294 DBG("(%p)", pd->obj);
295
296 pd->pending_list = eina_list_remove(pd->pending_list, pending);
297
298 const char *error_name, *error_text;
299 if (eldbus_message_error_get(msg, &error_name, &error_text))
300 {
301 ERR("%s: %s", error_name, error_text);
302 efl_model_error_notify(pd->obj);
303 return false;
304 }
305
306 Eina_Value *value_struct = eldbus_message_to_eina_value(msg);
307 if (NULL == value_struct)
308 {
309 INF("%s", "No output arguments");
310 return true;
311 }
312
313 Eina_Array *changed_properties = eina_array_new(1);
314
315 bool result = false;
316 unsigned int i = 0;
317 const Eina_List *it;
318 const Eldbus_Introspection_Argument *argument;
319 EINA_LIST_FOREACH(pd->arguments, it, argument)
320 {
321 if (ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN != argument->direction)
322 {
323 const Eina_Stringshare *property = eina_array_data_get(pd->properties_array, i);
324 EINA_SAFETY_ON_NULL_GOTO(property, on_error);
325
326 Eina_Bool ret = _eldbus_model_arguments_property_set(pd, value_struct, property);
327 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
328
329 ret = eina_array_push(changed_properties, property);
330 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
331 }
332
333 ++i;
334 }
335
336 if (eina_array_count(changed_properties))
337 {
338 Efl_Model_Property_Event evt = {.changed_properties = changed_properties};
339 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
340 }
341
342 result = true;
343
344on_error:
345 eina_array_free(changed_properties);
346 eina_value_free(value_struct);
347 return result;
348}
349
350static Eina_Bool
351_eldbus_model_arguments_property_set(Eldbus_Model_Arguments_Data *pd,
352 Eina_Value *value_struct,
353 const char *property)
354{
355 Eina_Value *prop_value = eina_hash_find(pd->properties_hash, property);
356 EINA_SAFETY_ON_NULL_RETURN_VAL(prop_value, EINA_FALSE);
357
358 Eina_Value value;
359 Eina_Bool ret = eina_value_struct_value_get(value_struct, "arg0", &value);
360 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EINA_FALSE);
361
362 eina_value_flush(prop_value);
363 ret = eina_value_copy(&value, prop_value);
364 eina_value_flush(&value);
365 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EINA_FALSE);
366
367 return ret;
368}
369
370static bool
371_eldbus_model_arguments_is_input_argument(Eldbus_Model_Arguments_Data *pd, const char *argument)
372{
373 const unsigned int i = _eldbus_model_arguments_argument_index_get(pd, argument);
374 if (i >= eina_array_count(pd->properties_array))
375 {
376 WRN("Argument not found: %s", argument);
377 return false;
378 }
379
380 Eldbus_Introspection_Argument *argument_introspection =
381 eina_list_nth(pd->arguments, i);
382 EINA_SAFETY_ON_NULL_RETURN_VAL(argument_introspection, false);
383
384 return ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN == argument_introspection->direction;
385}
386
387static bool
388_eldbus_model_arguments_is_output_argument(Eldbus_Model_Arguments_Data *pd, const char *argument)
389{
390 const unsigned int i = _eldbus_model_arguments_argument_index_get(pd, argument);
391 if (i >= eina_array_count(pd->properties_array))
392 {
393 WRN("Argument not found: %s", argument);
394 return false;
395 }
396
397 Eldbus_Introspection_Argument *argument_introspection =
398 eina_list_nth(pd->arguments, i);
399 EINA_SAFETY_ON_NULL_RETURN_VAL(argument_introspection, false);
400
401 return ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN != argument_introspection->direction;
402}
403
404static unsigned int
405_eldbus_model_arguments_argument_index_get(Eldbus_Model_Arguments_Data *pd, const char *argument)
406{
407 unsigned int i = 0;
408 const Eina_Stringshare *name;
409 Eina_Array_Iterator it;
410 EINA_ARRAY_ITER_NEXT(pd->properties_array, i, name, it)
411 {
412 if (strcmp(name, argument) == 0)
413 return i;
414 }
415
416 return ++i;
417}
418
419#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 @@
1class Eldbus.Model_Arguments (Eo.Base, Efl.Model.Base) {
2 legacy_prefix: null;
3 methods {
4 constructor {
5 [[Custom Eldbus_Model_Arguments constructor.
6
7 @since 1.16]]
8 params {
9 @in proxy: Eldbus_Proxy*; [[Eldbus proxy]]
10 @in name: const(char)*; [[Name]]
11 @in arguments: const(Eina_List)*; [[The introspected arguments]]
12 }
13 }
14 @property name {
15 get {}
16 values {
17 value: const(char)*;
18 }
19 }
20 }
21 implements {
22 Eo.Base.constructor;
23 Eo.Base.destructor;
24 Efl.Model.Base.properties.get;
25 Efl.Model.Base.properties_load;
26 Efl.Model.Base.property.set;
27 Efl.Model.Base.property.get;
28 Efl.Model.Base.load;
29 Efl.Model.Base.load_status.get;
30 Efl.Model.Base.unload;
31 Efl.Model.Base.child_add;
32 Efl.Model.Base.child_del;
33 Efl.Model.Base.children_slice.get;
34 Efl.Model.Base.children_count.get;
35 Efl.Model.Base.children_load;
36 }
37 constructors {
38 .constructor;
39 }
40}
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..fc93552a81
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_arguments_private.h
@@ -0,0 +1,29 @@
1#ifndef _ELDBUS_MODEL_ARGUMENTS_PRIVATE_H
2#define _ELDBUS_MODEL_ARGUMENTS_PRIVATE_H
3
4#include "Eldbus_Model.h"
5
6#include <stdbool.h>
7
8typedef struct _Eldbus_Model_Arguments_Data Eldbus_Model_Arguments_Data;
9
10/**
11 * eldbus_model_arguments
12 */
13struct _Eldbus_Model_Arguments_Data
14{
15 Eo *obj;
16 Efl_Model_Load load;
17 Eldbus_Proxy *proxy;
18 Eina_Array *properties_array;
19 Eina_Hash *properties_hash;
20 Eina_Stringshare *name;
21 Eina_List *pending_list;
22 const Eina_List *arguments;
23 Eina_Value tmp_value;
24};
25
26bool eldbus_model_arguments_process_arguments(Eldbus_Model_Arguments_Data *, const Eldbus_Message *, Eldbus_Pending *);
27
28#endif
29
diff --git a/src/lib/eldbus/eldbus_model_connection.c b/src/lib/eldbus/eldbus_model_connection.c
new file mode 100644
index 0000000000..72173b695e
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_connection.c
@@ -0,0 +1,372 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "eldbus_model_connection_private.h"
6#include "eldbus_model_private.h"
7
8#define MY_CLASS ELDBUS_MODEL_CONNECTION_CLASS
9#define MY_CLASS_NAME "Eldbus_Model_Connection"
10
11#define UNIQUE_NAME_PROPERTY "unique_name"
12
13static void _eldbus_model_connection_efl_model_base_properties_load(Eo *, Eldbus_Model_Connection_Data *);
14static void _eldbus_model_connection_efl_model_base_children_load(Eo *, Eldbus_Model_Connection_Data *);
15static void _eldbus_model_connection_names_list_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
16static void _eldbus_model_connection_connect(Eldbus_Model_Connection_Data *);
17static void _eldbus_model_connection_disconnect(Eldbus_Model_Connection_Data *);
18static void _eldbus_model_connection_clear(Eldbus_Model_Connection_Data *);
19
20static Eo_Base*
21_eldbus_model_connection_eo_base_constructor(Eo *obj, Eldbus_Model_Connection_Data *pd)
22{
23 DBG("(%p)", obj);
24 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
25
26 pd->obj = obj;
27 pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
28 pd->connection = NULL;
29 pd->properties_array = NULL;
30 pd->children_list = NULL;
31 pd->type = ELDBUS_CONNECTION_TYPE_UNKNOWN;
32 pd->address = NULL;
33 pd->private = false;
34 pd->unique_name = NULL;
35 pd->pending_list = NULL;
36
37 return obj;
38}
39
40static void
41_eldbus_model_connection_constructor(Eo *obj EINA_UNUSED,
42 Eldbus_Model_Connection_Data *pd,
43 int type,
44 const char* address,
45 Eina_Bool private)
46{
47 DBG("(%p)", obj);
48
49 pd->type = type;
50 pd->address = eina_stringshare_add(address);
51 pd->private = private;
52}
53
54static void
55_eldbus_model_connection_eo_base_destructor(Eo *obj, Eldbus_Model_Connection_Data *pd)
56{
57 DBG("(%p)", obj);
58
59 eina_stringshare_del(pd->address);
60
61 _eldbus_model_connection_clear(pd);
62
63 eo_do_super(obj, MY_CLASS, eo_destructor());
64}
65
66static Efl_Model_Load_Status
67_eldbus_model_connection_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
68 Eldbus_Model_Connection_Data *pd,
69 Eina_Array * const* properties_array)
70{
71 DBG("(%p)", obj);
72 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
73 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
74
75 if (NULL == pd->properties_array)
76 {
77 pd->properties_array = eina_array_new(1);
78 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->properties_array, EFL_MODEL_LOAD_STATUS_ERROR);
79
80 Eina_Bool ret = eina_array_push(pd->properties_array, UNIQUE_NAME_PROPERTY);
81 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
82 }
83
84 *(Eina_Array**)properties_array = pd->properties_array;
85 return pd->load.status;
86}
87
88static void
89_eldbus_model_connection_efl_model_base_properties_load(Eo *obj, Eldbus_Model_Connection_Data *pd)
90{
91 DBG("(%p)", obj);
92
93 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
94 return;
95
96 if (!pd->connection)
97 _eldbus_model_connection_connect(pd);
98
99 pd->unique_name = eina_value_new(EINA_VALUE_TYPE_STRING);
100 EINA_SAFETY_ON_NULL_RETURN(pd->unique_name);
101
102 const char *unique_name = eldbus_connection_unique_name_get(pd->connection);
103 Eina_Bool ret = eina_value_set(pd->unique_name, unique_name);
104 EINA_SAFETY_ON_FALSE_RETURN(ret);
105
106 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
107}
108
109static Efl_Model_Load_Status
110_eldbus_model_connection_efl_model_base_property_set(Eo *obj EINA_UNUSED,
111 Eldbus_Model_Connection_Data *pd EINA_UNUSED,
112 const char *property EINA_UNUSED,
113 Eina_Value const* value EINA_UNUSED)
114{
115 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
116 DBG("(%p): property=%s", obj, property);
117 return EFL_MODEL_LOAD_STATUS_ERROR;
118}
119
120static Efl_Model_Load_Status
121_eldbus_model_connection_efl_model_base_property_get(Eo *obj EINA_UNUSED,
122 Eldbus_Model_Connection_Data *pd,
123 const char *property,
124 Eina_Value const **value)
125{
126 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
127 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
128 DBG("(%p): property=%s", obj, property);
129
130 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
131 return EFL_MODEL_LOAD_STATUS_ERROR;
132
133 if (strcmp(property, UNIQUE_NAME_PROPERTY) != 0)
134 return EFL_MODEL_LOAD_STATUS_ERROR;
135
136 *value = pd->unique_name;
137 return pd->load.status;
138}
139
140static void
141_eldbus_model_connection_efl_model_base_load(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
142{
143 DBG("(%p)", obj);
144
145 if (!pd->connection)
146 _eldbus_model_connection_connect(pd);
147
148 _eldbus_model_connection_efl_model_base_properties_load(obj, pd);
149 _eldbus_model_connection_efl_model_base_children_load(obj, pd);
150}
151
152static Efl_Model_Load_Status
153_eldbus_model_connection_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
154{
155 DBG("(%p)", obj);
156 return pd->load.status;
157}
158
159static void
160_eldbus_model_connection_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
161{
162 DBG("(%p)", obj);
163
164 _eldbus_model_connection_clear(pd);
165
166 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
167}
168
169Eo *
170_eldbus_model_connection_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd EINA_UNUSED)
171{
172 DBG("(%p)", obj);
173 return NULL;
174}
175
176static Efl_Model_Load_Status
177_eldbus_model_connection_efl_model_base_child_del(Eo *obj EINA_UNUSED,
178 Eldbus_Model_Connection_Data *pd EINA_UNUSED,
179 Eo *child EINA_UNUSED)
180{
181 DBG("(%p)", obj);
182 return EFL_MODEL_LOAD_STATUS_ERROR;
183}
184
185static Efl_Model_Load_Status
186_eldbus_model_connection_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
187 Eldbus_Model_Connection_Data *pd,
188 unsigned start,
189 unsigned count,
190 Eina_Accessor **children_accessor)
191{
192 DBG("(%p)", obj);
193
194 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
195 {
196 WRN("(%p): Children not loaded", obj);
197 *children_accessor = NULL;
198 return pd->load.status;
199 }
200
201 *children_accessor = efl_model_list_slice(pd->children_list, start, count);
202 return pd->load.status;
203}
204
205static Efl_Model_Load_Status
206_eldbus_model_connection_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
207 Eldbus_Model_Connection_Data *pd,
208 unsigned *children_count)
209{
210 DBG("(%p)", obj);
211 *children_count = eina_list_count(pd->children_list);
212 return pd->load.status;
213}
214
215static void
216_eldbus_model_connection_efl_model_base_children_load(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
217{
218 DBG("(%p)", obj);
219
220 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
221 return;
222
223 if (!pd->connection)
224 _eldbus_model_connection_connect(pd);
225
226 Eldbus_Pending *pending = eldbus_names_list(pd->connection, &_eldbus_model_connection_names_list_cb, pd);
227 pd->pending_list = eina_list_append(pd->pending_list, pending);
228
229 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
230}
231
232static const char *
233_eldbus_model_connection_address_get(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
234{
235 return pd->address;
236}
237
238static void
239_eldbus_model_connection_address_set(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd, const char *value)
240{
241 eina_stringshare_del(pd->address);
242 pd->address = eina_stringshare_add(value);
243}
244
245static Eina_Bool
246_eldbus_model_connection_private_get(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
247{
248 return pd->private;
249}
250
251static void
252_eldbus_model_connection_private_set(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd, Eina_Bool value)
253{
254 pd->private = value;
255}
256
257static int
258_eldbus_model_connection_type_get(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
259{
260 return pd->type;
261}
262
263static void
264_eldbus_model_connection_type_set(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd, int value)
265{
266 pd->type = value;
267}
268
269static void
270_eldbus_model_connection_connect(Eldbus_Model_Connection_Data *pd)
271{
272 EINA_SAFETY_ON_NULL_RETURN(pd);
273
274 if (ELDBUS_CONNECTION_TYPE_ADDRESS == pd->type)
275 {
276 if (pd->private)
277 pd->connection = eldbus_address_connection_get(pd->address);
278 else
279 pd->connection = eldbus_private_address_connection_get(pd->address);
280 }
281 else
282 {
283 if (pd->private)
284 pd->connection = eldbus_private_connection_get(pd->type);
285 else
286 pd->connection = eldbus_connection_get(pd->type);
287 }
288
289 // TODO: Register for disconnection event
290
291 EINA_SAFETY_ON_FALSE_RETURN(NULL != pd->connection);
292}
293
294static void
295_eldbus_model_connection_disconnect(Eldbus_Model_Connection_Data *pd)
296{
297 EINA_SAFETY_ON_NULL_RETURN(pd);
298 eldbus_connection_unref(pd->connection);
299 pd->connection = NULL;
300}
301
302static void
303_eldbus_model_connection_clear(Eldbus_Model_Connection_Data *pd)
304{
305 EINA_SAFETY_ON_NULL_RETURN(pd);
306 if (!pd->connection)
307 return;
308
309 eina_value_free(pd->unique_name);
310 pd->unique_name = NULL;
311
312 Eo *child;
313 EINA_LIST_FREE(pd->children_list, child)
314 eo_unref(child);
315
316 Eldbus_Pending *pending;
317 EINA_LIST_FREE(pd->pending_list, pending)
318 eldbus_pending_cancel(pending);
319
320 if (pd->properties_array)
321 {
322 eina_array_free(pd->properties_array);
323 pd->properties_array = NULL;
324 }
325
326 _eldbus_model_connection_disconnect(pd);
327}
328
329static void
330_eldbus_model_connection_names_list_cb(void *data,
331 const Eldbus_Message *msg,
332 Eldbus_Pending *pending)
333{
334 Eldbus_Model_Connection_Data *pd = (Eldbus_Model_Connection_Data*)data;
335 DBG("(%p)", pd->obj);
336
337 pd->pending_list = eina_list_remove(pd->pending_list, pending);
338
339 const char *error_name, *error_text;
340 if (eldbus_message_error_get(msg, &error_name, &error_text))
341 {
342 ERR("%s: %s", error_name, error_text);
343 efl_model_error_notify(pd->obj);
344 return;
345 }
346
347 Eldbus_Message_Iter *array = NULL;
348 if (!eldbus_message_arguments_get(msg, "as", &array))
349 {
350 ERR("%s", "Error getting arguments.");
351 return;
352 }
353
354 const char *bus;
355 while (eldbus_message_iter_get_and_next(array, 's', &bus))
356 {
357 DBG("(%p): bus = %s", pd->obj, bus);
358
359 Eo *child = eo_add(ELDBUS_MODEL_OBJECT_CLASS, NULL,
360 eldbus_model_object_connection_constructor(pd->connection, bus, "/"));
361
362 pd->children_list = eina_list_append(pd->children_list, child);
363 }
364
365 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
366
367 unsigned int count = eina_list_count(pd->children_list);
368 if (count)
369 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
370}
371
372#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..3f2e5ab389
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_connection.eo
@@ -0,0 +1,49 @@
1class Eldbus.Model_Connection (Eo.Base, Efl.Model.Base) {
2 legacy_prefix: null;
3 methods {
4 constructor {
5 [[Custom Eldbus_Model_Connection constructor.
6
7 @since 1.16]]
8 params {
9 @in type: int; [[The connection type]]
10 @in address: const(char)*; [[Remote address of dbus]]
11 @in private_: bool; [[Non shared dbus connection]]
12 }
13 }
14 @property type {
15 values {
16 value: int;
17 }
18 }
19 @property address {
20 values {
21 value: const(char)*;
22 }
23 }
24 @property private {
25 values {
26 value: bool;
27 }
28 }
29 }
30 implements {
31 Eo.Base.constructor;
32 Eo.Base.destructor;
33 Efl.Model.Base.properties.get;
34 Efl.Model.Base.properties_load;
35 Efl.Model.Base.property.set;
36 Efl.Model.Base.property.get;
37 Efl.Model.Base.load;
38 Efl.Model.Base.load_status.get;
39 Efl.Model.Base.unload;
40 Efl.Model.Base.child_add;
41 Efl.Model.Base.child_del;
42 Efl.Model.Base.children_slice.get;
43 Efl.Model.Base.children_count.get;
44 Efl.Model.Base.children_load;
45 }
46 constructors {
47 .constructor;
48 }
49}
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..4123f92b07
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_connection_private.h
@@ -0,0 +1,28 @@
1#ifndef _ELDBUS_MODEL_CONNECTION_PRIVATE_H
2#define _ELDBUS_MODEL_CONNECTION_PRIVATE_H
3
4#include "Eldbus_Model.h"
5
6#include <stdbool.h>
7
8typedef struct _Eldbus_Model_Connection_Data Eldbus_Model_Connection_Data;
9
10/**
11 * eldbus_model_connection
12 */
13struct _Eldbus_Model_Connection_Data
14{
15 Eo *obj;
16 Efl_Model_Load load;
17 Eldbus_Connection *connection;
18 Eina_Array *properties_array;
19 Eina_List *children_list;
20 Eldbus_Connection_Type type;
21 Eina_Stringshare *address;
22 bool private;
23 Eina_Value *unique_name;
24 Eina_List *pending_list;
25};
26
27#endif
28
diff --git a/src/lib/eldbus/eldbus_model_method.c b/src/lib/eldbus/eldbus_model_method.c
new file mode 100644
index 0000000000..0f4e88b7cf
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_method.c
@@ -0,0 +1,103 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "eldbus_model_arguments_private.h"
6#include "eldbus_model_method_private.h"
7#include "eldbus_model_private.h"
8#include "eldbus_proxy.h"
9
10#include <Eina.h>
11
12#include <stdbool.h>
13
14#define MY_CLASS ELDBUS_MODEL_METHOD_CLASS
15#define MY_CLASS_NAME "Eldbus_Model_Method"
16
17static void _eldbus_model_method_call_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
18
19static Eo_Base*
20_eldbus_model_method_eo_base_constructor(Eo *obj, Eldbus_Model_Method_Data *pd)
21{
22 DBG("(%p)", obj);
23 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
24
25 pd->obj = obj;
26 pd->method = NULL;
27 return obj;
28}
29
30static void
31_eldbus_model_method_constructor(Eo *obj EINA_UNUSED,
32 Eldbus_Model_Method_Data *pd,
33 Eldbus_Proxy *proxy,
34 const Eldbus_Introspection_Method *method)
35{
36 DBG("(%p)", obj);
37 EINA_SAFETY_ON_NULL_RETURN(proxy);
38 EINA_SAFETY_ON_NULL_RETURN(method);
39 eo_do_super(obj, MY_CLASS, eldbus_model_arguments_constructor(proxy, method->name, method->arguments));
40
41 pd->method = method;
42}
43
44static Efl_Model_Load_Status
45_eldbus_model_method_call(Eo *obj EINA_UNUSED, Eldbus_Model_Method_Data *pd EINA_UNUSED)
46{
47 DBG("(%p)", obj);
48 Eldbus_Model_Arguments_Data *data = eo_data_scope_get(obj, ELDBUS_MODEL_ARGUMENTS_CLASS);
49 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EFL_MODEL_LOAD_STATUS_ERROR);
50
51 Eldbus_Message *msg = eldbus_proxy_method_call_new(data->proxy, data->name);
52 Eldbus_Message_Iter *iter = eldbus_message_iter_get(msg);
53
54 unsigned int i = 0;
55 const Eina_List *it;
56 const Eldbus_Introspection_Argument *argument;
57 EINA_LIST_FOREACH(data->arguments, it, argument)
58 {
59 if (ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN != argument->direction)
60 continue;
61
62 const Eina_Stringshare *name = eina_array_data_get(data->properties_array, i);
63 EINA_SAFETY_ON_NULL_GOTO(name, on_error);
64
65 const Eina_Value *value = eina_hash_find(data->properties_hash, name);
66 EINA_SAFETY_ON_NULL_GOTO(value, on_error);
67
68 Eina_Bool ret;
69 const char *signature = argument->type;
70 if (dbus_type_is_basic(signature[0]))
71 ret = _message_iter_from_eina_value(signature, iter, value);
72 else
73 ret = _message_iter_from_eina_value_struct(signature, iter, value);
74
75 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
76
77 ++i;
78 }
79
80 Eldbus_Pending *pending = eldbus_proxy_send(data->proxy, msg, _eldbus_model_method_call_cb, pd, -1);
81 data->pending_list = eina_list_append(data->pending_list, pending);
82
83 return data->load.status;
84
85on_error:
86 eldbus_message_unref(msg);
87 return EFL_MODEL_LOAD_STATUS_ERROR;
88}
89
90static void
91_eldbus_model_method_call_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
92{
93 Eldbus_Model_Method_Data *pd = (Eldbus_Model_Method_Data*)data;
94 DBG("(%p)", pd->obj);
95
96 Eldbus_Model_Arguments_Data *args_data = eo_data_scope_get(pd->obj, ELDBUS_MODEL_ARGUMENTS_CLASS);
97 EINA_SAFETY_ON_NULL_RETURN(args_data);
98
99 if (eldbus_model_arguments_process_arguments(args_data, msg, pending))
100 eo_do(pd->obj, eo_event_callback_call(ELDBUS_MODEL_METHOD_EVENT_SUCCESSFUL_CALL, NULL));
101}
102
103#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 @@
1class Eldbus.Model_Method (Eldbus.Model_Arguments) {
2 legacy_prefix: null;
3 methods {
4 constructor {
5 [[Custom Eldbus_Model_Method constructor.
6
7 @since 1.16]]
8 params {
9 @in proxy: Eldbus_Proxy*; [[Eldbus proxy]]
10 @in method: const(Eldbus_Introspection_Method)*; [[The introspected method]]
11 }
12 }
13 call {
14 [[Calls the method. The properties must have been set.
15
16 The event EMODEL_EVENT_PROPERTIES_CHANGED is raised for output arguments (properties).
17
18 The event ELDBUS_MODEL_METHOD_EVENT_METHOD_CALLED is raised for a successful call. Otherwise
19 the event EMODEL_EVENT_LOAD_STATUS with the status set to EMODEL_LOAD_STATUS_ERROR is raised.
20
21 @since 1.16]]
22 return: Efl.Model.Load_Status; [[#Emodel_Load_Status on success, #EMODEL_LOAD_STATUS_ERROR otherwise.]]
23 }
24 }
25 implements {
26 Eo.Base.constructor;
27 }
28 constructors {
29 .constructor;
30 }
31 events {
32 successful,call; [[Event dispatched for a successful method call.]]
33 }
34
35}
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 @@
1#ifndef _ELDBUS_MODEL_METHOD_PRIVATE_H
2#define _ELDBUS_MODEL_METHOD_PRIVATE_H
3
4#include "Eldbus_Model.h"
5
6typedef struct _Eldbus_Model_Method_Data Eldbus_Model_Method_Data;
7
8/**
9 * eldbus_model_method
10 */
11struct _Eldbus_Model_Method_Data
12{
13 Eo *obj;
14 const Eldbus_Introspection_Method *method;
15};
16
17#endif
18
diff --git a/src/lib/eldbus/eldbus_model_object.c b/src/lib/eldbus/eldbus_model_object.c
new file mode 100644
index 0000000000..a50c848391
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_object.c
@@ -0,0 +1,546 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "eldbus_model_object_private.h"
6#include "eldbus_model_private.h"
7
8#include <Eina.h>
9
10#define MY_CLASS ELDBUS_MODEL_OBJECT_CLASS
11#define MY_CLASS_NAME "Eldbus_Model_Object"
12
13#define UNIQUE_NAME_PROPERTY "unique_name"
14
15static void _eldbus_model_object_efl_model_base_properties_load(Eo *, Eldbus_Model_Object_Data *);
16static void _eldbus_model_object_efl_model_base_children_load(Eo *, Eldbus_Model_Object_Data *);
17static bool _eldbus_model_object_introspect(Eldbus_Model_Object_Data *, const char *, const char *);
18static void _eldbus_model_object_introspect_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
19static void _eldbus_model_object_connect(Eldbus_Model_Object_Data *);
20static void _eldbus_model_object_disconnect(Eldbus_Model_Object_Data *);
21static void _eldbus_model_object_clear(Eldbus_Model_Object_Data *);
22static void _eldbus_model_object_introspect_nodes(Eldbus_Model_Object_Data *, const char *, Eina_List *);
23static char *_eldbus_model_object_concatenate_path(const char *, const char *);
24static void _eldbus_model_object_create_children(Eldbus_Model_Object_Data *, Eldbus_Object *, Eina_List *);
25
26static Eo_Base*
27_eldbus_model_object_eo_base_constructor(Eo *obj, Eldbus_Model_Object_Data *pd)
28{
29 DBG("(%p)", obj);
30 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
31
32 pd->obj = obj;
33 pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
34 pd->connection = NULL;
35 pd->object_list = NULL;
36 pd->properties_array = NULL;
37 pd->children_list = NULL;
38 pd->type = ELDBUS_CONNECTION_TYPE_UNKNOWN;
39 pd->address = NULL;
40 pd->private = false;
41 pd->bus = NULL;
42 pd->path = NULL;
43 pd->unique_name = NULL;
44 pd->pending_list = NULL;
45 pd->introspection = NULL;
46
47 return obj;
48}
49
50static void
51_eldbus_model_object_constructor(Eo *obj EINA_UNUSED,
52 Eldbus_Model_Object_Data *pd,
53 int type,
54 const char* address,
55 Eina_Bool private,
56 const char* bus,
57 const char* path)
58{
59 DBG("(%p)", obj);
60 EINA_SAFETY_ON_NULL_RETURN(bus);
61 EINA_SAFETY_ON_NULL_RETURN(path);
62
63 pd->type = type;
64 pd->address = eina_stringshare_add(address);
65 pd->private = private;
66 pd->bus = eina_stringshare_add(bus);
67 pd->path = eina_stringshare_add(path);
68}
69
70static void
71_eldbus_model_object_connection_constructor(Eo *obj EINA_UNUSED,
72 Eldbus_Model_Object_Data *pd,
73 Eldbus_Connection *connection,
74 const char* bus,
75 const char* path)
76{
77 DBG("(%p)", obj);
78 EINA_SAFETY_ON_NULL_RETURN(connection);
79 EINA_SAFETY_ON_NULL_RETURN(bus);
80 EINA_SAFETY_ON_NULL_RETURN(path);
81
82 pd->connection = eldbus_connection_ref(connection);
83 pd->bus = eina_stringshare_add(bus);
84 pd->path = eina_stringshare_add(path);
85}
86
87static void
88_eldbus_model_object_eo_base_destructor(Eo *obj, Eldbus_Model_Object_Data *pd)
89{
90 DBG("(%p)", obj);
91
92 eina_stringshare_del(pd->address);
93 eina_stringshare_del(pd->bus);
94 eina_stringshare_del(pd->path);
95
96 _eldbus_model_object_clear(pd);
97
98 eo_do_super(obj, MY_CLASS, eo_destructor());
99}
100
101static Efl_Model_Load_Status
102_eldbus_model_object_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
103 Eldbus_Model_Object_Data *pd,
104 Eina_Array * const* properties_array)
105{
106 DBG("(%p)", obj);
107 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
108 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
109
110 if (NULL == pd->properties_array)
111 {
112 pd->properties_array = eina_array_new(1);
113 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->properties_array, EFL_MODEL_LOAD_STATUS_ERROR);
114
115 Eina_Bool ret = eina_array_push(pd->properties_array, UNIQUE_NAME_PROPERTY);
116 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
117 }
118
119 *(Eina_Array**)properties_array = pd->properties_array;
120 return pd->load.status;
121}
122
123static void
124_eldbus_model_object_efl_model_base_properties_load(Eo *obj, Eldbus_Model_Object_Data *pd)
125{
126 DBG("(%p)", obj);
127
128 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
129 return;
130
131 if (!pd->connection)
132 _eldbus_model_object_connect(pd);
133
134 pd->unique_name = eina_value_new(EINA_VALUE_TYPE_STRING);
135 EINA_SAFETY_ON_NULL_RETURN(pd->unique_name);
136
137 const char *unique_name = eldbus_connection_unique_name_get(pd->connection);
138 Eina_Bool ret = eina_value_set(pd->unique_name, unique_name);
139 EINA_SAFETY_ON_FALSE_RETURN(ret);
140
141 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
142}
143
144static Efl_Model_Load_Status
145_eldbus_model_object_efl_model_base_property_set(Eo *obj EINA_UNUSED,
146 Eldbus_Model_Object_Data *pd EINA_UNUSED,
147 const char *property EINA_UNUSED,
148 Eina_Value const* value EINA_UNUSED)
149{
150 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
151 DBG("(%p): property=%s", obj, property);
152 return EFL_MODEL_LOAD_STATUS_ERROR;
153}
154
155static Efl_Model_Load_Status
156_eldbus_model_object_efl_model_base_property_get(Eo *obj EINA_UNUSED,
157 Eldbus_Model_Object_Data *pd,
158 const char *property,
159 Eina_Value const**value)
160{
161 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
162 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
163 DBG("(%p): property=%s", obj, property);
164
165 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
166 return EFL_MODEL_LOAD_STATUS_ERROR;
167
168 if (strcmp(property, UNIQUE_NAME_PROPERTY) != 0)
169 return EFL_MODEL_LOAD_STATUS_ERROR;
170
171 *value = pd->unique_name;
172 return pd->load.status;
173}
174
175static void
176_eldbus_model_object_efl_model_base_load(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
177{
178 DBG("(%p)", obj);
179
180 if (!pd->connection)
181 _eldbus_model_object_connect(pd);
182
183 _eldbus_model_object_efl_model_base_properties_load(obj, pd);
184 _eldbus_model_object_efl_model_base_children_load(obj, pd);
185}
186
187static Efl_Model_Load_Status
188_eldbus_model_object_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
189{
190 DBG("(%p)", obj);
191 return pd->load.status;
192}
193
194static void
195_eldbus_model_object_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
196{
197 DBG("(%p)", obj);
198
199 _eldbus_model_object_clear(pd);
200
201 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
202}
203
204Eo *
205_eldbus_model_object_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd EINA_UNUSED)
206{
207 DBG("(%p)", obj);
208 return NULL;
209}
210
211static Efl_Model_Load_Status
212_eldbus_model_object_efl_model_base_child_del(Eo *obj EINA_UNUSED,
213 Eldbus_Model_Object_Data *pd EINA_UNUSED,
214 Eo *child EINA_UNUSED)
215{
216 DBG("(%p)", obj);
217 return EFL_MODEL_LOAD_STATUS_ERROR;
218}
219
220static Efl_Model_Load_Status
221_eldbus_model_object_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
222 Eldbus_Model_Object_Data *pd,
223 unsigned start,
224 unsigned count,
225 Eina_Accessor **children_accessor)
226{
227 fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
228 DBG("(%p)", obj);
229 fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
230
231 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
232 {
233 WRN("(%p): Children not loaded", obj);
234 *children_accessor = NULL;
235 return pd->load.status;
236 }
237 else
238 WRN("(%p): Children already loaded", obj);
239
240 fprintf(stderr, "%p\n", pd->children_list);
241
242 *children_accessor = efl_model_list_slice(pd->children_list, start, count);
243 return pd->load.status;
244}
245
246static Efl_Model_Load_Status
247_eldbus_model_object_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
248 Eldbus_Model_Object_Data *pd,
249 unsigned *children_count)
250{
251 DBG("(%p)", obj);
252 *children_count = eina_list_count(pd->children_list);
253 return pd->load.status;
254}
255
256static void
257_eldbus_model_object_efl_model_base_children_load(Eo *obj, Eldbus_Model_Object_Data *pd)
258{
259 DBG("(%p)", obj);
260
261 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
262 return;
263
264 if (!pd->connection)
265 _eldbus_model_object_connect(pd);
266
267 if (!_eldbus_model_object_introspect(pd, pd->bus, pd->path))
268 return;
269
270 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
271}
272
273static const char *
274_eldbus_model_object_address_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
275{
276 return pd->address;
277}
278
279static void
280_eldbus_model_object_address_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, const char *value)
281{
282 eina_stringshare_del(pd->address);
283 pd->address = eina_stringshare_add(value);
284}
285
286static Eina_Bool
287_eldbus_model_object_private_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
288{
289 return pd->private;
290}
291
292static void
293_eldbus_model_object_private_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, Eina_Bool value)
294{
295 pd->private = value;
296}
297
298static int
299_eldbus_model_object_type_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
300{
301 return pd->type;
302}
303
304static void
305_eldbus_model_object_type_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, int value)
306{
307 pd->type = value;
308}
309
310static const char *
311_eldbus_model_object_bus_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
312{
313 return pd->bus;
314}
315
316static void
317_eldbus_model_object_bus_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, const char *value)
318{
319 eina_stringshare_del(pd->bus);
320 pd->bus = eina_stringshare_add(value);
321}
322
323static const char *
324_eldbus_model_object_path_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
325{
326 return pd->path;
327}
328
329static void
330_eldbus_model_object_path_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, const char *value)
331{
332 eina_stringshare_del(pd->path);
333 pd->path = eina_stringshare_add(value);
334}
335
336static void
337_eldbus_model_object_connect(Eldbus_Model_Object_Data *pd)
338{
339 EINA_SAFETY_ON_NULL_RETURN(pd);
340
341 if (ELDBUS_CONNECTION_TYPE_ADDRESS == pd->type)
342 {
343 if (pd->private)
344 pd->connection = eldbus_address_connection_get(pd->address);
345 else
346 pd->connection = eldbus_private_address_connection_get(pd->address);
347 }
348 else
349 {
350 if (pd->private)
351 pd->connection = eldbus_private_connection_get(pd->type);
352 else
353 pd->connection = eldbus_connection_get(pd->type);
354 }
355
356 // TODO: Register for disconnection event
357
358 EINA_SAFETY_ON_FALSE_RETURN(NULL != pd->connection);
359}
360
361static void
362_eldbus_model_object_disconnect(Eldbus_Model_Object_Data *pd)
363{
364 EINA_SAFETY_ON_NULL_RETURN(pd);
365 eldbus_connection_unref(pd->connection);
366 pd->connection = NULL;
367}
368
369static void
370_eldbus_model_object_clear(Eldbus_Model_Object_Data *pd)
371{
372 EINA_SAFETY_ON_NULL_RETURN(pd);
373 if (!pd->connection)
374 return;
375
376 eina_value_free(pd->unique_name);
377 pd->unique_name = NULL;
378
379 Eo *child;
380 EINA_LIST_FREE(pd->children_list, child)
381 eo_unref(child);
382
383 Eldbus_Pending *pending;
384 EINA_LIST_FREE(pd->pending_list, pending)
385 eldbus_pending_cancel(pending);
386
387 if (pd->properties_array)
388 {
389 eina_array_free(pd->properties_array);
390 pd->properties_array = NULL;
391 }
392
393 Eldbus_Object *object;
394 EINA_LIST_FREE(pd->object_list, object)
395 eldbus_object_unref(object);
396
397 if (pd->introspection)
398 {
399 eldbus_introspection_node_free(pd->introspection);
400 pd->introspection = NULL;
401 }
402
403 _eldbus_model_object_disconnect(pd);
404}
405
406
407static bool
408_eldbus_model_object_introspect(Eldbus_Model_Object_Data *pd,
409 const char *bus,
410 const char *path)
411{
412 EINA_SAFETY_ON_NULL_RETURN_VAL(bus, false);
413 EINA_SAFETY_ON_NULL_RETURN_VAL(path, false);
414
415 DBG("(%p) Introspecting: bus = %s, path = %s", pd->obj, bus, path);
416
417 Eldbus_Object *object = eldbus_object_get(pd->connection, bus, path);
418 if (!object)
419 {
420 ERR("(%p): Cannot get object: bus=%s, path=%s", pd->obj, bus, path);
421 return false;
422 }
423 pd->object_list = eina_list_append(pd->object_list, object);
424
425 // TODO: Register for interface added/removed event
426
427 Eldbus_Pending *pending = eldbus_object_introspect(object, &_eldbus_model_object_introspect_cb, pd);
428 eldbus_pending_data_set(pending, "object", object);
429 pd->pending_list = eina_list_append(pd->pending_list, pending);
430 return true;
431}
432
433static void
434_eldbus_model_object_introspect_cb(void *data,
435 const Eldbus_Message *msg,
436 Eldbus_Pending *pending)
437{
438 Eldbus_Model_Object_Data *pd = (Eldbus_Model_Object_Data*)data;
439 DBG("(%p)", pd->obj);
440
441 pd->pending_list = eina_list_remove(pd->pending_list, pending);
442 Eldbus_Object *object = eldbus_pending_data_get(pending, "object");
443
444 const char *error_name, *error_text;
445 if (eldbus_message_error_get(msg, &error_name, &error_text))
446 {
447 ERR("%s: %s", error_name, error_text);
448 efl_model_error_notify(pd->obj);
449 return;
450 }
451
452 const char *xml = NULL;
453 if (!eldbus_message_arguments_get(msg, "s", &xml))
454 {
455 ERR("Error getting arguments.");
456 return;
457 }
458 EINA_SAFETY_ON_NULL_RETURN(xml);
459
460 const char *current_path = eldbus_object_path_get(object);
461 EINA_SAFETY_ON_NULL_RETURN(current_path);
462
463 DBG("(%p): introspect of bus = %s, path = %s =>\n%s", pd->obj, pd->bus, current_path, xml);
464
465 pd->introspection = eldbus_introspection_parse(xml);
466 EINA_SAFETY_ON_NULL_RETURN(pd->introspection);
467
468 _eldbus_model_object_introspect_nodes(pd, current_path, pd->introspection->nodes);
469 _eldbus_model_object_create_children(pd, object, pd->introspection->interfaces);
470
471 if (eina_list_count(pd->pending_list) == 0)
472 {
473 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
474
475 unsigned int count = eina_list_count(pd->children_list);
476 if (count)
477 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
478 }
479}
480
481static void
482_eldbus_model_object_introspect_nodes(Eldbus_Model_Object_Data *pd, const char *current_path, Eina_List *nodes)
483{
484 EINA_SAFETY_ON_NULL_RETURN(pd);
485 EINA_SAFETY_ON_NULL_RETURN(current_path);
486
487 Eina_List *it;
488 Eldbus_Introspection_Node *node;
489 EINA_LIST_FOREACH(nodes, it, node)
490 {
491 const char *relative_path = node->name;
492 EINA_SAFETY_ON_NULL_RETURN(relative_path);
493
494 char *absolute_path = _eldbus_model_object_concatenate_path(current_path, relative_path);
495 EINA_SAFETY_ON_NULL_RETURN(absolute_path);
496
497 _eldbus_model_object_introspect(pd, pd->bus, absolute_path);
498
499 free(absolute_path);
500 }
501}
502
503static char *
504_eldbus_model_object_concatenate_path(const char *root_path, const char *relative_path)
505{
506 Eina_Strbuf *buffer = eina_strbuf_new();
507 EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, NULL);
508
509 Eina_Bool ret = eina_strbuf_append(buffer, root_path);
510 if (strcmp(root_path, "/") != 0)
511 ret = ret && eina_strbuf_append_char(buffer, '/');
512 ret = ret && eina_strbuf_append(buffer, relative_path);
513 EINA_SAFETY_ON_FALSE_GOTO(ret, free_buffer);
514
515 char *absolute_path = eina_strbuf_string_steal(buffer);
516
517 eina_strbuf_free(buffer);
518
519 return absolute_path;
520
521free_buffer:
522 eina_strbuf_free(buffer);
523 return NULL;
524}
525
526static void
527_eldbus_model_object_create_children(Eldbus_Model_Object_Data *pd, Eldbus_Object *object, Eina_List *interfaces)
528{
529 const char *current_path = eldbus_object_path_get(object);
530 EINA_SAFETY_ON_NULL_RETURN(current_path);
531
532 Eina_List *it;
533 Eldbus_Introspection_Interface *interface;
534 EINA_LIST_FOREACH(interfaces, it, interface)
535 {
536 WRN("(%p) Creating child: bus = %s, path = %s, interface = %s", pd->obj, pd->bus, current_path, interface->name);
537
538 // TODO: increment reference to keep 'interface' in memory
539 Eo *child = eo_add_ref(ELDBUS_MODEL_PROXY_CLASS, NULL,
540 eldbus_model_proxy_constructor(object, interface));
541
542 pd->children_list = eina_list_append(pd->children_list, child);
543 }
544}
545
546#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..68cbc81d0f
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_object.eo
@@ -0,0 +1,73 @@
1class Eldbus.Model_Object (Eo.Base, Efl.Model.Base) {
2 legacy_prefix: null;
3 data: Eldbus_Model_Object_Data;
4 methods {
5 constructor {
6 [[Custom Eldbus_Model_Object constructor.
7
8 @since 1.16]]
9 params {
10 @in type: int; [[The connection type]]
11 @in address: const(char)*; [[Remote address of dbus]]
12 @in private_: bool; [[Non shared dbus connection]]
13 @in bus: const(char)*; [[DBus Name or unique-id]]
14 @in path: const(char)*; [[DBus path]]
15 }
16 }
17 connection_constructor {
18 [[Custom Eldbus_Model_Object connection_constructor.
19
20 @since 1.16]]
21 params {
22 @in connection: Eldbus_Connection*; [[Eldbus connection]]
23 @in bus: const(char)*; [[DBus Name or unique-id]]
24 @in path: const(char)*; [[DBus path]]
25 }
26 }
27 @property type {
28 values {
29 value: int;
30 }
31 }
32 @property address {
33 values {
34 value: const(char)*;
35 }
36 }
37 @property private {
38 values {
39 value: bool;
40 }
41 }
42 @property bus {
43 values {
44 value: const(char)*;
45 }
46 }
47 @property path {
48 values {
49 value: const(char)*;
50 }
51 }
52 }
53 implements {
54 Eo.Base.constructor;
55 Eo.Base.destructor;
56 Efl.Model.Base.properties.get;
57 Efl.Model.Base.properties_load;
58 Efl.Model.Base.property.set;
59 Efl.Model.Base.property.get;
60 Efl.Model.Base.load;
61 Efl.Model.Base.load_status.get;
62 Efl.Model.Base.unload;
63 Efl.Model.Base.child_add;
64 Efl.Model.Base.child_del;
65 Efl.Model.Base.children_slice.get;
66 Efl.Model.Base.children_count.get;
67 Efl.Model.Base.children_load;
68 }
69 constructors {
70 .constructor;
71 .connection_constructor;
72 }
73}
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..745492143e
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_object_private.h
@@ -0,0 +1,32 @@
1#ifndef _ELDBUS_MODEL_OBJECT_PRIVATE_H
2#define _ELDBUS_MODEL_OBJECT_PRIVATE_H
3
4#include "Eldbus_Model.h"
5
6#include <stdbool.h>
7
8typedef struct _Eldbus_Model_Object_Data Eldbus_Model_Object_Data;
9
10/**
11 * eldbus_model_object
12 */
13struct _Eldbus_Model_Object_Data
14{
15 Eo *obj;
16 Efl_Model_Load load;
17 Eldbus_Connection *connection;
18 Eina_List *object_list;
19 Eina_Array *properties_array;
20 Eina_List *children_list;
21 Eldbus_Connection_Type type;
22 Eina_Stringshare *address;
23 bool private;
24 Eina_Stringshare *bus;
25 Eina_Stringshare *path;
26 Eina_Value *unique_name;
27 Eina_List *pending_list;
28 Eldbus_Introspection_Node *introspection;
29};
30
31#endif
32
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 @@
1#ifndef _ELDBUS_MODEL_PRIVATE_H
2#define _ELDBUS_MODEL_PRIVATE_H
3
4#include "eldbus_private.h"
5
6#include <Eo.h>
7#include <Efl.h>
8
9/* logging support */
10extern int eldbus_model_log_dom;
11
12#ifdef CRI
13# undef CRI
14#endif
15#define CRI(...) EINA_LOG_DOM_CRIT(eldbus_model_log_dom, __VA_ARGS__)
16
17#ifdef ERR
18# undef ERR
19#endif
20#define ERR(...) EINA_LOG_DOM_ERR(eldbus_model_log_dom, __VA_ARGS__)
21
22#ifdef WRN
23# undef WRN
24#endif
25#define WRN(...) EINA_LOG_DOM_WARN(eldbus_model_log_dom, __VA_ARGS__)
26
27#ifdef INF
28# undef INF
29#endif
30#define INF(...) EINA_LOG_DOM_INFO(eldbus_model_log_dom, __VA_ARGS__)
31
32#ifdef DBG
33# undef DBG
34#endif
35#define DBG(...) EINA_LOG_DOM_DBG(eldbus_model_log_dom, __VA_ARGS__)
36
37#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..36b50fd960
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_proxy.c
@@ -0,0 +1,684 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "eldbus_model_proxy_private.h"
6#include "eldbus_model_private.h"
7
8#include <Eina.h>
9
10#define MY_CLASS ELDBUS_MODEL_PROXY_CLASS
11#define MY_CLASS_NAME "Eldbus_Model_Proxy"
12
13static void _eldbus_model_proxy_efl_model_base_properties_load(Eo *, Eldbus_Model_Proxy_Data *);
14static void _eldbus_model_proxy_efl_model_base_children_load(Eo *, Eldbus_Model_Proxy_Data *);
15static bool _eldbus_model_proxy_load(Eldbus_Model_Proxy_Data *);
16static void _eldbus_model_proxy_unload(Eldbus_Model_Proxy_Data *);
17static void _eldbus_model_proxy_property_get_all_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
18static void _eldbus_model_proxy_property_set_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
19static void _eldbus_model_proxy_start_monitor(Eldbus_Model_Proxy_Data *);
20static void _eldbus_model_proxy_stop_monitor(Eldbus_Model_Proxy_Data *);
21static void _eldbus_model_proxy_property_changed_cb(void *, Eldbus_Proxy *, void *);
22static void _eldbus_model_proxy_property_invalidated_cb(void *, Eldbus_Proxy *, void *);
23static bool _eldbus_model_proxy_is_property_writeable(Eldbus_Model_Proxy_Data *, const char *);
24static bool _eldbus_model_proxy_is_property_readable(Eldbus_Model_Proxy_Data *, const char *);
25static const char *_eldbus_model_proxy_property_type_get(Eldbus_Model_Proxy_Data *, const char *);
26static void _eldbus_model_proxy_create_methods_children(Eldbus_Model_Proxy_Data *);
27static void _eldbus_model_proxy_create_signals_children(Eldbus_Model_Proxy_Data *);
28
29typedef struct _Eldbus_Model_Proxy_Property_Set_Data Eldbus_Model_Proxy_Property_Set_Data;
30
31struct _Eldbus_Model_Proxy_Property_Set_Data
32{
33 Eldbus_Model_Proxy_Data *pd;
34 Eina_Stringshare *property;
35 Eina_Value value;
36};
37
38static Eldbus_Model_Proxy_Property_Set_Data * _eldbus_model_proxy_property_set_data_new(Eldbus_Model_Proxy_Data *, const char *, const Eina_Value *);
39static void _eldbus_model_proxy_property_set_data_free(Eldbus_Model_Proxy_Property_Set_Data *);
40
41static void
42_eldbus_model_proxy_hash_free(Eina_Value *value)
43{
44 eina_value_free(value);
45}
46
47static Eo_Base*
48_eldbus_model_proxy_eo_base_constructor(Eo *obj, Eldbus_Model_Proxy_Data *pd)
49{
50 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
51
52 pd->obj = obj;
53 pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
54 pd->object = NULL;
55 pd->proxy = NULL;
56 pd->properties_array = NULL;
57 pd->properties_hash = eina_hash_string_superfast_new(EINA_FREE_CB(_eldbus_model_proxy_hash_free));
58 pd->children_list = NULL;
59 pd->name = NULL;
60 pd->pending_list = NULL;
61 pd->monitoring = false;
62 pd->interface = NULL;
63 return obj;
64}
65
66static void
67_eldbus_model_proxy_constructor(Eo *obj EINA_UNUSED,
68 Eldbus_Model_Proxy_Data *pd,
69 Eldbus_Object *object,
70 const Eldbus_Introspection_Interface *interface)
71{
72 DBG("(%p)", obj);
73 EINA_SAFETY_ON_NULL_RETURN(object);
74 EINA_SAFETY_ON_NULL_RETURN(interface);
75
76 pd->object = eldbus_object_ref(object);
77 pd->name = eina_stringshare_add(interface->name);
78 pd->interface = interface;
79}
80
81static void
82_eldbus_model_proxy_eo_base_destructor(Eo *obj, Eldbus_Model_Proxy_Data *pd)
83{
84 DBG("(%p)", obj);
85
86 _eldbus_model_proxy_unload(pd);
87
88 eina_hash_free(pd->properties_hash);
89
90 eina_stringshare_del(pd->name);
91 eldbus_object_unref(pd->object);
92
93 eo_do_super(obj, MY_CLASS, eo_destructor());
94}
95
96static Efl_Model_Load_Status
97_eldbus_model_proxy_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
98 Eldbus_Model_Proxy_Data *pd,
99 Eina_Array * const* properties_array)
100{
101 DBG("(%p)", obj);
102 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
103 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
104
105 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
106 {
107 WRN("%s", "Properties not loaded.");
108 return EFL_MODEL_LOAD_STATUS_ERROR;
109 }
110
111 *(Eina_Array**)properties_array = pd->properties_array;
112 return pd->load.status;
113}
114
115static void
116_eldbus_model_proxy_efl_model_base_properties_load(Eo *obj, Eldbus_Model_Proxy_Data *pd)
117{
118 DBG("(%p)", obj);
119
120 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
121 return;
122
123 if (!_eldbus_model_proxy_load(pd))
124 return;
125
126 const unsigned int properties_count = eina_list_count(pd->interface->properties);
127
128 pd->properties_array = eina_array_new(properties_count);
129 EINA_SAFETY_ON_NULL_RETURN(pd->properties_array);
130
131 if (0 == properties_count)
132 {
133 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
134 return;
135 }
136
137 Eina_List *it;
138 Eldbus_Introspection_Property *property;
139 EINA_LIST_FOREACH(pd->interface->properties, it, property)
140 {
141 Eina_Stringshare *name = eina_stringshare_add(property->name);
142 EINA_SAFETY_ON_NULL_RETURN(name);
143
144 Eina_Bool ret = eina_array_push(pd->properties_array, name);
145 EINA_SAFETY_ON_FALSE_RETURN(ret);
146 }
147
148 Eldbus_Pending *pending = eldbus_proxy_property_get_all(pd->proxy, _eldbus_model_proxy_property_get_all_cb, pd);
149 pd->pending_list = eina_list_append(pd->pending_list, pending);
150
151 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES);
152}
153
154static Efl_Model_Load_Status
155_eldbus_model_proxy_efl_model_base_property_set(Eo *obj EINA_UNUSED,
156 Eldbus_Model_Proxy_Data *pd,
157 const char *property,
158 Eina_Value const* value)
159{
160 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
161 DBG("(%p): property=%s", obj, property);
162
163 if (!_eldbus_model_proxy_is_property_writeable(pd, property))
164 {
165 WRN("Property is read-only: %s", property);
166 return EFL_MODEL_LOAD_STATUS_ERROR;
167 }
168
169 Eldbus_Model_Proxy_Property_Set_Data *data =
170 _eldbus_model_proxy_property_set_data_new(pd, property, value);
171 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EFL_MODEL_LOAD_STATUS_ERROR);
172
173 const char *signature = _eldbus_model_proxy_property_type_get(pd, property);
174 EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EFL_MODEL_LOAD_STATUS_ERROR);
175
176 Eldbus_Pending *pending = eldbus_proxy_property_value_set
177 (pd->proxy, property, signature, (Eina_Value*)value, _eldbus_model_proxy_property_set_cb, data);
178 pd->pending_list = eina_list_append(pd->pending_list, pending);
179
180 return pd->load.status;
181}
182
183static Efl_Model_Load_Status
184_eldbus_model_proxy_efl_model_base_property_get(Eo *obj EINA_UNUSED,
185 Eldbus_Model_Proxy_Data *pd,
186 const char *property,
187 Eina_Value const **value)
188{
189 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
190 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
191
192 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
193 return EFL_MODEL_LOAD_STATUS_ERROR;
194
195 if (!_eldbus_model_proxy_is_property_readable(pd, property))
196 {
197 WRN("Property is write-only: %s", property);
198 return EFL_MODEL_LOAD_STATUS_ERROR;
199 }
200
201 *value = eina_hash_find(pd->properties_hash, property);
202
203 if(!*value)
204 {
205 *value = &pd->tmp_value;
206 return EFL_MODEL_LOAD_STATUS_ERROR;
207 }
208
209 return pd->load.status;
210}
211
212static void
213_eldbus_model_proxy_efl_model_base_load(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
214{
215 if (!_eldbus_model_proxy_load(pd))
216 return;
217
218 _eldbus_model_proxy_efl_model_base_properties_load(obj, pd);
219 _eldbus_model_proxy_efl_model_base_children_load(obj, pd);
220}
221
222static Efl_Model_Load_Status
223_eldbus_model_proxy_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
224{
225 DBG("(%p)", obj);
226 return pd->load.status;
227}
228
229static void
230_eldbus_model_proxy_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
231{
232 DBG("(%p)", obj);
233
234 _eldbus_model_proxy_unload(pd);
235
236 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
237}
238
239Eo *
240_eldbus_model_proxy_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd EINA_UNUSED)
241{
242 DBG("(%p)", obj);
243 return NULL;
244}
245
246static Efl_Model_Load_Status
247_eldbus_model_proxy_efl_model_base_child_del(Eo *obj EINA_UNUSED,
248 Eldbus_Model_Proxy_Data *pd EINA_UNUSED,
249 Eo *child EINA_UNUSED)
250{
251 DBG("(%p)", obj);
252 return EFL_MODEL_LOAD_STATUS_ERROR;
253}
254
255static Efl_Model_Load_Status
256_eldbus_model_proxy_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
257 Eldbus_Model_Proxy_Data *pd,
258 unsigned start,
259 unsigned count,
260 Eina_Accessor **children_accessor)
261{
262 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
263 {
264 WRN("(%p): Children not loaded", obj);
265 *children_accessor = NULL;
266 return pd->load.status;
267 }
268
269 *children_accessor = efl_model_list_slice(pd->children_list, start, count);
270 return pd->load.status;
271}
272
273static Efl_Model_Load_Status
274_eldbus_model_proxy_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
275 Eldbus_Model_Proxy_Data *pd,
276 unsigned *children_count)
277{
278 DBG("(%p)", obj);
279 *children_count = eina_list_count(pd->children_list);
280 return pd->load.status;
281}
282
283static void
284_eldbus_model_proxy_efl_model_base_children_load(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
285{
286 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
287 return;
288
289 if (!_eldbus_model_proxy_load(pd))
290 return;
291
292 _eldbus_model_proxy_create_methods_children(pd);
293 _eldbus_model_proxy_create_signals_children(pd);
294
295 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
296
297 unsigned int count = eina_list_count(pd->children_list);
298 if (count)
299 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
300}
301
302static void
303_eldbus_model_proxy_create_methods_children(Eldbus_Model_Proxy_Data *pd)
304{
305 Eina_List *it;
306 Eldbus_Introspection_Method *method;
307
308 EINA_LIST_FOREACH(pd->interface->methods, it, method)
309 {
310 const char *bus = eldbus_object_bus_name_get(pd->object);
311 EINA_SAFETY_ON_NULL_RETURN(bus);
312
313 const char *path = eldbus_object_path_get(pd->object);
314 EINA_SAFETY_ON_NULL_RETURN(path);
315
316 const char *interface_name = pd->interface->name;
317 EINA_SAFETY_ON_NULL_RETURN(interface_name);
318
319 const char *method_name = method->name;
320 EINA_SAFETY_ON_NULL_RETURN(method_name);
321
322 INF("(%p) Creating method child: bus = %s, path = %s, method = %s::%s", pd->obj, bus, path, interface_name, method_name);
323
324 Eo *child = eo_add(ELDBUS_MODEL_METHOD_CLASS, NULL,
325 eldbus_model_method_constructor(pd->proxy, method));
326
327 pd->children_list = eina_list_append(pd->children_list, child);
328 }
329}
330
331static void
332_eldbus_model_proxy_create_signals_children(Eldbus_Model_Proxy_Data *pd)
333{
334 Eina_List *it;
335 Eldbus_Introspection_Signal *signal;
336 EINA_LIST_FOREACH(pd->interface->signals, it, signal)
337 {
338 const char *bus = eldbus_object_bus_name_get(pd->object);
339 EINA_SAFETY_ON_NULL_RETURN(bus);
340
341 const char *path = eldbus_object_path_get(pd->object);
342 EINA_SAFETY_ON_NULL_RETURN(path);
343
344 const char *interface_name = pd->interface->name;
345 EINA_SAFETY_ON_NULL_RETURN(interface_name);
346
347 const char *signal_name = signal->name;
348 EINA_SAFETY_ON_NULL_RETURN(signal_name);
349
350 DBG("(%p) Creating signal child: bus = %s, path = %s, signal = %s::%s", pd->obj, bus, path, interface_name, signal_name);
351
352 Eo *child = eo_add(ELDBUS_MODEL_SIGNAL_CLASS, NULL,
353 eldbus_model_signal_constructor(pd->proxy, signal));
354
355 pd->children_list = eina_list_append(pd->children_list, child);
356 }
357}
358
359static const char *
360_eldbus_model_proxy_name_get(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
361{
362 return pd->name;
363}
364
365static bool
366_eldbus_model_proxy_load(Eldbus_Model_Proxy_Data *pd)
367{
368 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, false);
369 if (pd->proxy)
370 return true;
371
372 pd->proxy = eldbus_proxy_get(pd->object, pd->name);
373 if (!pd->proxy)
374 {
375 ERR("Cannot get proxy for interface: %s", pd->name);
376 return false;
377 }
378
379 return true;
380}
381
382static void
383_eldbus_model_proxy_unload(Eldbus_Model_Proxy_Data *pd)
384{
385 EINA_SAFETY_ON_NULL_RETURN(pd);
386
387 Eo *child;
388 EINA_LIST_FREE(pd->children_list, child)
389 eo_unref(child);
390
391 Eldbus_Pending *pending;
392 EINA_LIST_FREE(pd->pending_list, pending)
393 eldbus_pending_cancel(pending);
394
395 if (pd->properties_array)
396 {
397 unsigned int i;
398 Eina_Stringshare *property;
399 Eina_Array_Iterator it;
400 EINA_ARRAY_ITER_NEXT(pd->properties_array, i, property, it)
401 eina_stringshare_del(property);
402 eina_array_free(pd->properties_array);
403 pd->properties_array = NULL;
404 }
405
406 eina_hash_free_buckets(pd->properties_hash);
407
408 _eldbus_model_proxy_stop_monitor(pd);
409
410 if (pd->proxy)
411 {
412 eldbus_proxy_unref(pd->proxy);
413 pd->proxy = NULL;
414 }
415}
416
417static void
418_eldbus_model_proxy_start_monitor(Eldbus_Model_Proxy_Data *pd)
419{
420 if (pd->monitoring)
421 return;
422 pd->monitoring = true;
423
424 eldbus_proxy_event_callback_add(pd->proxy,
425 ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
426 _eldbus_model_proxy_property_changed_cb,
427 pd);
428
429 eldbus_proxy_event_callback_add(pd->proxy,
430 ELDBUS_PROXY_EVENT_PROPERTY_REMOVED,
431 _eldbus_model_proxy_property_invalidated_cb,
432 pd);
433}
434
435static void
436_eldbus_model_proxy_stop_monitor(Eldbus_Model_Proxy_Data *pd)
437{
438 if (!pd->monitoring)
439 return;
440 pd->monitoring = false;
441
442 eldbus_proxy_event_callback_del(pd->proxy,
443 ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
444 _eldbus_model_proxy_property_changed_cb,
445 pd);
446
447 eldbus_proxy_event_callback_del(pd->proxy,
448 ELDBUS_PROXY_EVENT_PROPERTY_REMOVED,
449 _eldbus_model_proxy_property_invalidated_cb,
450 pd);
451}
452
453static void
454_eldbus_model_proxy_property_changed_cb(void *data,
455 Eldbus_Proxy *proxy EINA_UNUSED,
456 void *event_info)
457{
458 Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
459 DBG("(%p)", pd->obj);
460
461 Eldbus_Object_Event_Property_Changed *event = (Eldbus_Object_Event_Property_Changed*)event_info;
462
463 Eina_Value *prop_value = eina_hash_find(pd->properties_hash, event->name);
464 EINA_SAFETY_ON_NULL_RETURN(prop_value);
465
466 Eina_Bool ret = eina_value_copy(event->value, prop_value);
467 EINA_SAFETY_ON_FALSE_RETURN(ret);
468
469 efl_model_property_changed_notify(pd->obj, event->name);
470}
471
472static void
473_eldbus_model_proxy_property_invalidated_cb(void *data,
474 Eldbus_Proxy *proxy EINA_UNUSED,
475 void *event_info)
476{
477 Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
478 DBG("(%p)", pd->obj);
479
480 Eldbus_Proxy_Event_Property_Changed *event = (Eldbus_Proxy_Event_Property_Changed*)event_info;
481
482 // TODO: eldbus_proxy_property_get(event->name) ?
483
484 Efl_Model_Property_Event evt = {0};
485 evt.invalidated_properties = eina_array_new(1);
486 EINA_SAFETY_ON_NULL_RETURN(evt.invalidated_properties);
487
488 Eina_Bool ret = eina_array_push(evt.invalidated_properties, event->name);
489 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
490
491on_error:
492 eina_array_free(evt.invalidated_properties);
493 efl_model_property_invalidated_notify(pd->obj, event->name);
494}
495
496static void
497_eldbus_model_proxy_property_get_all_cb(void *data,
498 const Eldbus_Message *msg,
499 Eldbus_Pending *pending)
500{
501 Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
502
503 pd->pending_list = eina_list_remove(pd->pending_list, pending);
504
505 const char *error_name, *error_text;
506 if (eldbus_message_error_get(msg, &error_name, &error_text))
507 {
508 ERR("%s: %s", error_name, error_text);
509 efl_model_error_notify(pd->obj);
510 return;
511 }
512
513 Eldbus_Message_Iter *values = NULL;
514 if (!eldbus_message_arguments_get(msg, "a{sv}", &values))
515 {
516 ERR("%s", "Error getting arguments.");
517 return;
518 }
519
520 Eina_List *it;
521 Eldbus_Introspection_Property *prop;
522 EINA_LIST_FOREACH(pd->interface->properties, it, prop)
523 {
524 const Eina_Value_Type *type = _dbus_type_to_eina_value_type(prop->type[0]);
525 Eina_Value *value = eina_value_new(type);
526 EINA_SAFETY_ON_NULL_RETURN(value);
527
528 Eina_Bool ret = eina_hash_add(pd->properties_hash, prop->name, value);
529 EINA_SAFETY_ON_FALSE_RETURN(ret);
530 }
531
532 Eina_Array *changed_properties = eina_array_new(1);
533 Eldbus_Message_Iter *entry;
534 while (eldbus_message_iter_get_and_next(values, 'e', &entry))
535 {
536 const char *property;
537 Eldbus_Message_Iter *variant;
538 if (!eldbus_message_iter_arguments_get(entry, "sv", &property, &variant))
539 continue;
540
541 Eina_Value *struct_value = eldbus_message_iter_struct_like_to_eina_value(variant);
542 EINA_SAFETY_ON_NULL_GOTO(struct_value, on_error);
543
544 Eina_Value arg0;
545 Eina_Bool ret = eina_value_struct_value_get(struct_value, "arg0", &arg0);
546 eina_value_free(struct_value);
547 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
548
549 Eina_Value *prop_value = eina_hash_find(pd->properties_hash, property);
550 EINA_SAFETY_ON_NULL_GOTO(prop_value, on_error);
551
552 ret = eina_value_copy(&arg0, prop_value);
553 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
554
555 eina_value_flush(&arg0);
556
557 ret = eina_array_push(changed_properties, property);
558 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
559 }
560
561 _eldbus_model_proxy_start_monitor(pd);
562
563 if (eina_array_count(changed_properties))
564 {
565 Efl_Model_Property_Event evt = {.changed_properties = changed_properties};
566 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
567 }
568
569 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
570
571on_error:
572 eina_array_free(changed_properties);
573}
574
575
576static void
577_eldbus_model_proxy_property_set_cb(void *data,
578 const Eldbus_Message *msg,
579 Eldbus_Pending *pending)
580{
581 Eldbus_Model_Proxy_Property_Set_Data *property_set_data = (Eldbus_Model_Proxy_Property_Set_Data *)data;
582 Eldbus_Model_Proxy_Data *pd = property_set_data->pd;
583
584 pd->pending_list = eina_list_remove(pd->pending_list, pending);
585
586 const char *error_name, *error_text;
587 if (eldbus_message_error_get(msg, &error_name, &error_text))
588 {
589 ERR("%s: %s", error_name, error_text);
590 efl_model_error_notify(pd->obj);
591 goto on_error;
592 }
593
594 Eina_Value *prop_value = eina_hash_find(pd->properties_hash,
595 property_set_data->property);
596 EINA_SAFETY_ON_NULL_GOTO(prop_value, on_error);
597
598 Eina_Bool ret = eina_value_copy(&property_set_data->value, prop_value);
599 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
600
601 Efl_Model_Property_Event evt = {.changed_properties = pd->properties_array};
602 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
603 efl_model_property_changed_notify(pd->obj, property_set_data->property);
604
605on_error:
606 _eldbus_model_proxy_property_set_data_free(property_set_data);
607}
608
609static bool
610_eldbus_model_proxy_is_property_writeable(Eldbus_Model_Proxy_Data *pd, const char *property)
611{
612 Eldbus_Introspection_Property *property_introspection =
613 eldbus_introspection_property_find(pd->interface->properties, property);
614 if (NULL == property_introspection)
615 {
616 WRN("Property not found: %s", property);
617 return false;
618 }
619
620 return ELDBUS_INTROSPECTION_PROPERTY_ACCESS_WRITE == property_introspection->access
621 || ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE == property_introspection->access;
622}
623
624static bool
625_eldbus_model_proxy_is_property_readable(Eldbus_Model_Proxy_Data *pd, const char *property)
626{
627 Eldbus_Introspection_Property *property_introspection =
628 eldbus_introspection_property_find(pd->interface->properties, property);
629 if (NULL == property_introspection)
630 {
631 WRN("Property not found: %s", property);
632 return false;
633 }
634
635 return ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READ == property_introspection->access
636 || ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE == property_introspection->access;
637}
638
639static const char *
640_eldbus_model_proxy_property_type_get(Eldbus_Model_Proxy_Data *pd, const char *property)
641{
642 Eldbus_Introspection_Property *property_introspection =
643 eldbus_introspection_property_find(pd->interface->properties, property);
644 if (NULL == property_introspection)
645 {
646 WRN("Property not found: %s", property);
647 return NULL;
648 }
649
650 return property_introspection->type;
651
652}
653
654static Eldbus_Model_Proxy_Property_Set_Data *
655_eldbus_model_proxy_property_set_data_new(Eldbus_Model_Proxy_Data *pd,
656 const char *property,
657 const Eina_Value *value)
658{
659 Eldbus_Model_Proxy_Property_Set_Data *data = calloc(1, sizeof(Eldbus_Model_Proxy_Property_Set_Data));
660 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
661
662 data->pd = pd;
663 data->property = eina_stringshare_add(property);
664 Eina_Bool ret = eina_value_copy(value, &data->value);
665 EINA_SAFETY_ON_FALSE_GOTO(ret, error);
666
667 return data;
668
669error:
670 eina_stringshare_del(data->property);
671 free(data);
672 return NULL;
673}
674
675static void
676_eldbus_model_proxy_property_set_data_free(Eldbus_Model_Proxy_Property_Set_Data *data)
677{
678 EINA_SAFETY_ON_NULL_RETURN(data);
679 eina_stringshare_del(data->property);
680 eina_value_flush(&data->value);
681 free(data);
682}
683
684#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 @@
1class Eldbus.Model_Proxy (Eo.Base, Efl.Model.Base) {
2 legacy_prefix: null;
3 methods {
4 constructor {
5 [[Custom Eldbus_Model_Proxy constructor.
6
7 @since 1.16]]
8 params {
9 @in object: Eldbus_Object *; [[Eldbus object]]
10 @in interface: const(Eldbus_Introspection_Interface)*; [[The introspected interface]]
11 }
12 }
13 @property name {
14 get {}
15 values {
16 value: const(char)*;
17 }
18 }
19 }
20 implements {
21 Eo.Base.constructor;
22 Eo.Base.destructor;
23 Efl.Model.Base.properties.get;
24 Efl.Model.Base.properties_load;
25 Efl.Model.Base.property.set;
26 Efl.Model.Base.property.get;
27 Efl.Model.Base.load;
28 Efl.Model.Base.load_status.get;
29 Efl.Model.Base.unload;
30 Efl.Model.Base.child_add;
31 Efl.Model.Base.child_del;
32 Efl.Model.Base.children_slice.get;
33 Efl.Model.Base.children_count.get;
34 Efl.Model.Base.children_load;
35 }
36 constructors {
37 .constructor;
38 }
39}
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..02153fc2b9
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_proxy_private.h
@@ -0,0 +1,30 @@
1#ifndef _ELDBUS_MODEL_PROXY_PRIVATE_H
2#define _ELDBUS_MODEL_PROXY_PRIVATE_H
3
4#include "Eldbus_Model.h"
5
6#include <stdbool.h>
7
8typedef struct _Eldbus_Model_Proxy_Data Eldbus_Model_Proxy_Data;
9
10/**
11 * eldbus_model_proxy
12 */
13struct _Eldbus_Model_Proxy_Data
14{
15 Eo *obj;
16 Efl_Model_Load load;
17 Eldbus_Object *object;
18 Eldbus_Proxy *proxy;
19 Eina_Array *properties_array;
20 Eina_Hash *properties_hash;
21 Eina_List *children_list;
22 Eina_Stringshare *name;
23 Eina_List *pending_list;
24 bool monitoring;
25 const Eldbus_Introspection_Interface *interface;
26 Eina_Value tmp_value;
27};
28
29#endif
30
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 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "eldbus_model_arguments_private.h"
6#include "eldbus_model_signal_private.h"
7#include "eldbus_model_private.h"
8
9#include <Eina.h>
10
11#define MY_CLASS ELDBUS_MODEL_SIGNAL_CLASS
12#define MY_CLASS_NAME "Eldbus_Model_Signal"
13
14static void _eldbus_model_signal_handler_cb(void *, const Eldbus_Message *);
15static void _eldbus_model_signal_callback_add(Eldbus_Model_Signal_Data *);
16static void _eldbus_model_signal_callback_del(Eldbus_Model_Signal_Data *);
17
18static Eo_Base*
19_eldbus_model_signal_eo_base_constructor(Eo *obj, Eldbus_Model_Signal_Data *pd)
20{
21 DBG("(%p)", obj);
22 eo_do_super(obj, MY_CLASS, eo_constructor());
23
24 pd->obj = obj;
25 pd->handler = NULL;
26 pd->signal = NULL;
27 return obj;
28}
29
30static void
31_eldbus_model_signal_constructor(Eo *obj EINA_UNUSED,
32 Eldbus_Model_Signal_Data *pd,
33 Eldbus_Proxy *proxy,
34 const Eldbus_Introspection_Signal *signal)
35{
36 DBG("(%p)", obj);
37 EINA_SAFETY_ON_NULL_RETURN(proxy);
38 EINA_SAFETY_ON_NULL_RETURN(signal);
39 eo_do_super(obj, MY_CLASS, eldbus_model_arguments_constructor(proxy, signal->name, signal->arguments));
40
41 pd->signal = signal;
42}
43
44static void
45_eldbus_model_signal_eo_base_destructor(Eo *obj, Eldbus_Model_Signal_Data *pd)
46{
47 DBG("(%p)", obj);
48
49 _eldbus_model_signal_callback_del(pd);
50
51 eo_do_super(obj, MY_CLASS, eo_destructor());
52}
53
54static void
55_eldbus_model_signal_efl_model_base_properties_load(Eo *obj, Eldbus_Model_Signal_Data *pd)
56{
57 DBG("(%p)", obj);
58
59 Eldbus_Model_Arguments_Data *args_data = eo_data_scope_get(pd->obj, ELDBUS_MODEL_ARGUMENTS_CLASS);
60 EINA_SAFETY_ON_NULL_RETURN(args_data);
61
62 if (args_data->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
63 return;
64
65 _eldbus_model_signal_callback_add(pd);
66
67 eo_do_super(obj, MY_CLASS, efl_model_properties_load());
68}
69
70static void