summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuilherme Lepsch <lepsch@expertisesolutions.com.br>2015-01-09 14:20:14 -0200
committerCedric BAIL <cedric@osg.samsung.com>2015-12-10 12:02:30 -0800
commit10fa1b5b4b2454437c00a9b8931bb3f9ddb9e99c (patch)
treeb4238f5f83b55463ad2e88e97dc968f2a607a668
parent48b22214493958fc852f101009b0e8a88aa77e05 (diff)
eldbus: add efl.model implementation.
Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
-rw-r--r--src/Makefile_Eldbus.am65
-rw-r--r--src/Makefile_Eldbus_Cxx.am21
-rw-r--r--src/Makefile_Elocation.am2
-rw-r--r--src/examples/eldbus/.gitignore1
-rw-r--r--src/lib/.gitignore1
-rw-r--r--src/lib/eldbus/Eldbus.h14
-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.c469
-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.c417
-rw-r--r--src/lib/eldbus/eldbus_model_arguments.eo40
-rw-r--r--src/lib/eldbus/eldbus_model_arguments_private.h28
-rw-r--r--src/lib/eldbus/eldbus_model_connection.c361
-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.c102
-rw-r--r--src/lib/eldbus/eldbus_model_method.eo35
-rw-r--r--src/lib/eldbus/eldbus_model_method_private.h18
-rw-r--r--src/lib/eldbus/eldbus_model_object.c542
-rw-r--r--src/lib/eldbus/eldbus_model_object.eo73
-rw-r--r--src/lib/eldbus/eldbus_model_object_private.h32
-rw-r--r--src/lib/eldbus/eldbus_model_private.h37
-rw-r--r--src/lib/eldbus/eldbus_model_proxy.c718
-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.c106
-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
46 files changed, 5563 insertions, 13 deletions
diff --git a/src/Makefile_Eldbus.am b/src/Makefile_Eldbus.am
index 66ca2bf..c5113db 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,9 +42,20 @@ 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 \
50lib/eldbus/eldbus_model_private.h \
51lib/eldbus/eldbus_model_proxy_private.h \
52lib/eldbus/eldbus_model_object_private.h \
53lib/eldbus/eldbus_model_arguments_private.h \
54lib/eldbus/eldbus_model_connection_private.h \
55lib/eldbus/eldbus_model_signal_private.h \
56lib/eldbus/eldbus_model_method_private.h \
57lib/eldbus/eldbus_introspection.h \
58lib/eldbus/Eldbus_Model.h \
23lib/eldbus/eldbus_proxy.c \ 59lib/eldbus/eldbus_proxy.c \
24lib/eldbus/eldbus_core.c \ 60lib/eldbus/eldbus_core.c \
25lib/eldbus/eldbus_message.c \ 61lib/eldbus/eldbus_message.c \
@@ -30,13 +66,20 @@ lib/eldbus/eldbus_service.c \
30lib/eldbus/eldbus_signal_handler.c \ 66lib/eldbus/eldbus_signal_handler.c \
31lib/eldbus/eldbus_message_helper.c \ 67lib/eldbus/eldbus_message_helper.c \
32lib/eldbus/eldbus_message_to_eina_value.c \ 68lib/eldbus/eldbus_message_to_eina_value.c \
33lib/eldbus/eldbus_message_from_eina_value.c 69lib/eldbus/eldbus_message_from_eina_value.c \
70lib/eldbus/eldbus_model_connection.c \
71lib/eldbus/eldbus_model_object.c \
72lib/eldbus/eldbus_model_proxy.c \
73lib/eldbus/eldbus_model_method.c \
74lib/eldbus/eldbus_model_arguments.c \
75lib/eldbus/eldbus_model_signal.c \
76lib/eldbus/eldbus_introspection.c
34 77
35lib_eldbus_libeldbus_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ 78lib_eldbus_libeldbus_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
36-include $(top_builddir)/config.h \ 79-include $(top_builddir)/config.h \
37@ELDBUS_CFLAGS@ 80@ELDBUS_CFLAGS@ @EFL_CFLAGS@
38lib_eldbus_libeldbus_la_LIBADD = @ELDBUS_LIBS@ 81lib_eldbus_libeldbus_la_LIBADD = @ELDBUS_LIBS@ @EFL_LIBS@
39lib_eldbus_libeldbus_la_DEPENDENCIES = @ELDBUS_INTERNAL_LIBS@ 82lib_eldbus_libeldbus_la_DEPENDENCIES = @ELDBUS_INTERNAL_LIBS@ @EFL_INTERNAL_LIBS@
40lib_eldbus_libeldbus_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@ 83lib_eldbus_libeldbus_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
41 84
42### Binary 85### Binary
@@ -74,12 +117,22 @@ TESTS += tests/eldbus/eldbus_suite
74tests_eldbus_eldbus_suite_SOURCES = \ 117tests_eldbus_eldbus_suite_SOURCES = \
75tests/eldbus/eldbus_suite.c \ 118tests/eldbus/eldbus_suite.c \
76tests/eldbus/eldbus_test_eldbus_init.c \ 119tests/eldbus/eldbus_test_eldbus_init.c \
120tests/eldbus/eldbus_test_eldbus_model.h \
121tests/eldbus/eldbus_fake_server.h \
122tests/eldbus/eldbus_test_eldbus_model.c \
123tests/eldbus/eldbus_test_eldbus_model_connection.c \
124tests/eldbus/eldbus_test_eldbus_model_object.c \
125tests/eldbus/eldbus_test_eldbus_model_proxy.c \
126tests/eldbus/eldbus_test_eldbus_model_method.c \
127tests/eldbus/eldbus_test_eldbus_model_signal.c \
128tests/eldbus/eldbus_test_fake_server_eldbus_model_proxy.c \
129tests/eldbus/eldbus_fake_server.c \
77tests/eldbus/eldbus_suite.h 130tests/eldbus/eldbus_suite.h
78 131
79tests_eldbus_eldbus_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl @CHECK_CFLAGS@ @ELDBUS_CFLAGS@ \ 132tests_eldbus_eldbus_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl @CHECK_CFLAGS@ @ELDBUS_CFLAGS@ \
80-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eldbus\" 133@EFL_CFLAGS@ -DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eldbus\"
81 134
82tests_eldbus_eldbus_suite_LDADD = @CHECK_LIBS@ @USE_ELDBUS_LIBS@ 135tests_eldbus_eldbus_suite_LDADD = @CHECK_LIBS@ @USE_ELDBUS_LIBS@ @USE_EFL_LIBS@
83tests_eldbus_eldbus_suite_DEPENDENCIES = @USE_ELDBUS_INTERNAL_LIBS@ 136tests_eldbus_eldbus_suite_DEPENDENCIES = @USE_ELDBUS_INTERNAL_LIBS@
84 137
85endif 138endif
diff --git a/src/Makefile_Eldbus_Cxx.am b/src/Makefile_Eldbus_Cxx.am
index ad17184..d265b2c 100644
--- a/src/Makefile_Eldbus_Cxx.am
+++ b/src/Makefile_Eldbus_Cxx.am
@@ -1,6 +1,27 @@
1 1
2if HAVE_CXX11 2if HAVE_CXX11
3 3
4### Generated headers
5
6generated_eldbus_cxx_bindings = $(eldbus_eolian_files:%.eo=%.eo.hh)
7generated_eldbus_cxx_impl_bindings = $(eldbus_eolian_files:%.eo=%.eo.impl.hh)
8
9lib/eldbus/Eldbus_Model.hh: $(generated_eldbus_cxx_bindings)
10 @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
11 @echo @ECHO_E@ "#include <Eldbus_Model.h>" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
12 @echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
13 @for i in $(generated_eldbus_cxx_bindings); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh; done
14 @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
15
16generated_eldbus_cxx_all = \
17 $(generated_eldbus_cxx_bindings) \
18 $(generated_eldbus_cxx_impl_bindings) \
19 lib/eldbus/Eldbus_Model.hh
20
21CLEANFILES += $(generated_eldbus_cxx_all)
22
23nodist_installed_eldbuscxxmainheaders_DATA = $(generated_eldbus_cxx_all)
24
4### Library 25### Library
5 26
6installed_eldbuscxxmainheadersdir = $(includedir)/eldbus_cxx-@VMAJ@ 27installed_eldbuscxxmainheadersdir = $(includedir)/eldbus_cxx-@VMAJ@
diff --git a/src/Makefile_Elocation.am b/src/Makefile_Elocation.am
index 604b50d..82ff192 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/examples/eldbus/.gitignore b/src/examples/eldbus/.gitignore
index db67874..70650f4 100644
--- a/src/examples/eldbus/.gitignore
+++ b/src/examples/eldbus/.gitignore
@@ -8,3 +8,4 @@
8/ofono-dial 8/ofono-dial
9/server 9/server
10/simple-signal-emit 10/simple-signal-emit
11/dbusmodel
diff --git a/src/lib/.gitignore b/src/lib/.gitignore
index df511ac..190a85e 100644
--- a/src/lib/.gitignore
+++ b/src/lib/.gitignore
@@ -8,3 +8,4 @@
8/edje/Edje.hh 8/edje/Edje.hh
9/edje/Edje.eo.hh 9/edje/Edje.eo.hh
10/eio/Eio.hh 10/eio/Eio.hh
11/eldbus/Eldbus_Model.hh
diff --git a/src/lib/eldbus/Eldbus.h b/src/lib/eldbus/Eldbus.h
index ee11954..c8f35d8 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,18 @@ 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
243#ifdef EFL_BETA_API_SUPPORT
244
245#include "eldbus_model_arguments.eo.h"
246#include "eldbus_model_connection.eo.h"
247#include "eldbus_model_method.eo.h"
248#include "eldbus_model_object.eo.h"
249#include "eldbus_model_proxy.eo.h"
250#include "eldbus_model_signal.eo.h"
251
252#endif
239 253
240#ifdef __cplusplus 254#ifdef __cplusplus
241} 255}
diff --git a/src/lib/eldbus/Eldbus_Model.h b/src/lib/eldbus/Eldbus_Model.h
new file mode 100644
index 0000000..9edbd77
--- /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 cf149cd..29899d1 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 b629379..838fee0 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 0000000..dbacf74
--- /dev/null
+++ b/src/lib/eldbus/eldbus_introspection.c
@@ -0,0 +1,469 @@
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 Eldbus_Introspection_Node *node;
32 Eina_Simple_XML_Node_Root *xml_root;
33 Eina_Simple_XML_Node *xml_node;
34
35 EINA_SAFETY_ON_NULL_RETURN_VAL(xml, NULL);
36
37 node = NULL;
38 xml_root = eina_simple_xml_node_load(xml, strlen(xml), EINA_TRUE);
39 xml_node = (Eina_Simple_XML_Node*)eina_inlist_last(xml_root->children);
40 EINA_SAFETY_ON_FALSE_GOTO(EINA_SIMPLE_XML_NODE_TAG == xml_node->type, free_root);
41
42 node = (Eldbus_Introspection_Node*)_eldbus_introspection_parse_node((Eina_Simple_XML_Node_Tag*)xml_node);
43
44 free_root:
45 eina_simple_xml_node_root_free(xml_root);
46
47 return node;
48}
49
50static void *
51_eldbus_introspection_parse_node(Eina_Simple_XML_Node_Tag *tag)
52{
53 Eldbus_Introspection_Node *node;;
54 Eldbus_Introspection_Element_Parse_Table table[] = {
55 { "node", _eldbus_introspection_parse_node, NULL },
56 { "interface", _eldbus_introspection_parse_interface, NULL },
57 { NULL, NULL, NULL }
58 };
59 const char *name;
60
61 node = calloc(1, sizeof(Eldbus_Introspection_Node));
62 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
63
64 name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
65 node->name = eina_stringshare_add(name);
66 table[0].list = &node->nodes;
67 table[1].list = &node->interfaces;
68
69 _eldbus_introspection_parse_children(tag->children, table);
70
71 return node;
72}
73
74EAPI void
75eldbus_introspection_node_free(Eldbus_Introspection_Node *node)
76{
77 Eldbus_Introspection_Node *child_node;
78 Eldbus_Introspection_Interface *interface;
79
80 EINA_SAFETY_ON_NULL_RETURN(node);
81
82 EINA_LIST_FREE(node->nodes, child_node)
83 eldbus_introspection_node_free(child_node);
84
85 EINA_LIST_FREE(node->interfaces, interface)
86 _eldbus_introspection_interface_free(interface);
87
88 eina_stringshare_del(node->name);
89 free(node);
90}
91
92static const char *
93_eldbus_introspection_attribute_value_get(Eina_Inlist *attributes, const char *key)
94{
95 Eina_Simple_XML_Attribute *attribute;
96
97 EINA_INLIST_FOREACH(attributes, attribute)
98 {
99 if (strcmp(attribute->key, key) == 0)
100 return attribute->value;
101 }
102
103 return NULL;
104}
105
106static void *
107_eldbus_introspection_parse_interface(Eina_Simple_XML_Node_Tag *tag)
108{
109 Eldbus_Introspection_Interface *interface;
110 Eldbus_Introspection_Element_Parse_Table table[] = {
111 { "method", _eldbus_introspection_parse_method, NULL },
112 { "signal", _eldbus_introspection_parse_signal, NULL },
113 { "property", _eldbus_introspection_parse_property, NULL },
114 { "annotation", _eldbus_introspection_parse_annotation, NULL },
115 { NULL, NULL, NULL }
116 };
117 const char *name;
118
119 interface = calloc(1, sizeof(Eldbus_Introspection_Interface));
120 EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
121
122 name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
123 if (!name) goto error;
124 interface->name = eina_stringshare_add(name);
125 table[0].list = &interface->methods;
126 table[1].list = &interface->signals;
127 table[2].list = &interface->properties;
128 table[3].list = &interface->annotations;
129
130 _eldbus_introspection_parse_children(tag->children, table);
131
132 return interface;
133
134 error:
135 _eldbus_introspection_interface_free(interface);
136 return NULL;
137}
138
139static void
140_eldbus_introspection_interface_free(Eldbus_Introspection_Interface *interface)
141{
142 Eldbus_Introspection_Method *method;
143 Eldbus_Introspection_Signal *signal;
144 Eldbus_Introspection_Property *property;
145 Eldbus_Introspection_Annotation *annotation;
146
147 EINA_SAFETY_ON_NULL_RETURN(interface);
148
149 EINA_LIST_FREE(interface->methods, method)
150 _eldbus_introspection_method_free(method);
151
152 EINA_LIST_FREE(interface->signals, signal)
153 _eldbus_introspection_signal_free(signal);
154
155 EINA_LIST_FREE(interface->properties, property)
156 _eldbus_introspection_property_free(property);
157
158 EINA_LIST_FREE(interface->annotations, annotation)
159 _eldbus_introspection_annotation_free(annotation);
160
161 eina_stringshare_del(interface->name);
162 free(interface);
163}
164
165static void *
166_eldbus_introspection_parse_method(Eina_Simple_XML_Node_Tag *tag)
167{
168 Eldbus_Introspection_Method *method;
169 Eldbus_Introspection_Element_Parse_Table table[] = {
170 { "arg", _eldbus_introspection_parse_argument, NULL },
171 { "annotation", _eldbus_introspection_parse_annotation, NULL },
172 { NULL, NULL, NULL }
173 };
174 const char *name;
175
176 method = calloc(1, sizeof(Eldbus_Introspection_Method));
177 EINA_SAFETY_ON_NULL_RETURN_VAL(method, NULL);
178
179 name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
180 if (!name) goto error;
181 method->name = eina_stringshare_add(name);
182 table[0].list = &method->arguments;
183 table[1].list = &method->annotations;
184
185 _eldbus_introspection_parse_children(tag->children, table);
186
187 return method;
188
189 error:
190 _eldbus_introspection_method_free(method);
191 return NULL;
192}
193
194static void
195_eldbus_introspection_method_free(Eldbus_Introspection_Method *method)
196{
197 Eldbus_Introspection_Argument *argument;
198 Eldbus_Introspection_Annotation *annotation;
199
200 EINA_SAFETY_ON_NULL_RETURN(method);
201
202 EINA_LIST_FREE(method->arguments, argument)
203 _eldbus_introspection_argument_free(argument);
204
205 EINA_LIST_FREE(method->annotations, annotation)
206 _eldbus_introspection_annotation_free(annotation);
207
208 eina_stringshare_del(method->name);
209 free(method);
210}
211
212static void *
213_eldbus_introspection_parse_signal(Eina_Simple_XML_Node_Tag *tag)
214{
215 Eldbus_Introspection_Signal *signal;
216 Eldbus_Introspection_Element_Parse_Table table[] = {
217 { "arg", _eldbus_introspection_parse_argument, NULL },
218 { "annotation", _eldbus_introspection_parse_annotation, NULL },
219 { NULL, NULL, NULL }
220 };
221 const char *name;
222
223 signal = calloc(1, sizeof(Eldbus_Introspection_Signal));
224 EINA_SAFETY_ON_NULL_RETURN_VAL(signal, NULL);
225
226 name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
227 if (!name) goto error;
228 signal->name = eina_stringshare_add(name);
229 table[0].list = &signal->arguments;
230 table[1].list = &signal->annotations;
231
232 _eldbus_introspection_parse_children(tag->children, table);
233
234 return signal;
235
236 error:
237 _eldbus_introspection_signal_free(signal);
238 return NULL;
239}
240
241static void
242_eldbus_introspection_signal_free(Eldbus_Introspection_Signal *signal)
243{
244 Eldbus_Introspection_Argument *argument;
245 Eldbus_Introspection_Annotation *annotation;
246
247 EINA_SAFETY_ON_NULL_RETURN(signal);
248
249 EINA_LIST_FREE(signal->arguments, argument)
250 _eldbus_introspection_argument_free(argument);
251
252 EINA_LIST_FREE(signal->annotations, annotation)
253 _eldbus_introspection_annotation_free(annotation);
254
255 eina_stringshare_del(signal->name);
256 free(signal);
257}
258
259static void *
260_eldbus_introspection_parse_argument(Eina_Simple_XML_Node_Tag *tag)
261{
262 Eldbus_Introspection_Argument *argument;
263 const char *name;
264 const char *type;
265 const char *direction;
266
267 argument = calloc(1, sizeof(Eldbus_Introspection_Argument));
268 EINA_SAFETY_ON_NULL_RETURN_VAL(argument, NULL);
269
270 name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
271 argument->name = eina_stringshare_add(name);
272
273 type = _eldbus_introspection_attribute_value_get(tag->attributes, "type");
274 if (!type) goto error;
275 argument->type = eina_stringshare_add(type);
276
277 direction = _eldbus_introspection_attribute_value_get(tag->attributes, "direction");
278 if (direction)
279 {
280 if (strcmp(direction, "in") == 0)
281 argument->direction = ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN;
282 else
283 if (strcmp(direction, "out") == 0)
284 argument->direction = ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_OUT;
285 else
286 argument->direction = ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_NONE;
287 }
288
289 return argument;
290
291 error:
292 _eldbus_introspection_argument_free(argument);
293 return NULL;
294}
295
296static void
297_eldbus_introspection_argument_free(Eldbus_Introspection_Argument *argument)
298{
299 EINA_SAFETY_ON_NULL_RETURN(argument);
300 eina_stringshare_del(argument->name);
301 eina_stringshare_del(argument->type);
302 free(argument);
303}
304
305static void *
306_eldbus_introspection_parse_property(Eina_Simple_XML_Node_Tag *tag)
307{
308 Eldbus_Introspection_Property *property;
309 Eldbus_Introspection_Element_Parse_Table table[] = {
310 { "annotation", _eldbus_introspection_parse_annotation, NULL },
311 { NULL, NULL, NULL }
312 };
313 const char *name;
314 const char *type;
315 const char *access;
316
317 property = calloc(1, sizeof(Eldbus_Introspection_Property));
318 EINA_SAFETY_ON_NULL_RETURN_VAL(property, NULL);
319
320 name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
321 if (!name) goto error;
322 property->name = eina_stringshare_add(name);
323
324 type = _eldbus_introspection_attribute_value_get(tag->attributes, "type");
325 if (!type) goto error;
326 property->type = eina_stringshare_add(type);
327
328 access = _eldbus_introspection_attribute_value_get(tag->attributes, "access");
329 if (!access) goto error;
330
331 if (strcmp(access, "read") == 0)
332 property->access = ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READ;
333 else if (strcmp(access, "write") == 0)
334 property->access = ELDBUS_INTROSPECTION_PROPERTY_ACCESS_WRITE;
335 else if (strcmp(access, "readwrite") == 0)
336 property->access = ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE;
337 else
338 EINA_SAFETY_ON_TRUE_GOTO(!!"Unknown property access", error);
339 table[0].list = &property->annotations;
340
341 _eldbus_introspection_parse_children(tag->children, table);
342 return property;
343
344 error:
345 _eldbus_introspection_property_free(property);
346 return NULL;
347}
348
349static void
350_eldbus_introspection_property_free(Eldbus_Introspection_Property *property)
351{
352 Eldbus_Introspection_Annotation *annotation;
353
354 EINA_SAFETY_ON_NULL_RETURN(property);
355
356 EINA_LIST_FREE(property->annotations, annotation)
357 _eldbus_introspection_annotation_free(annotation);
358
359 eina_stringshare_del(property->name);
360 eina_stringshare_del(property->type);
361 free(property);
362}
363
364static void *
365_eldbus_introspection_parse_annotation(Eina_Simple_XML_Node_Tag *tag)
366{
367 Eldbus_Introspection_Annotation *annotation;
368 const char *name;
369 const char *value;
370
371 annotation = calloc(1, sizeof(Eldbus_Introspection_Annotation));
372 EINA_SAFETY_ON_NULL_RETURN_VAL(annotation, NULL);
373
374 name = _eldbus_introspection_attribute_value_get(tag->attributes, "name");
375 if (!name) goto error;
376 annotation->name = eina_stringshare_add(name);
377
378 value = _eldbus_introspection_attribute_value_get(tag->attributes, "value");
379 if (!value) goto error;
380 annotation->value = eina_stringshare_add(value);
381
382 return annotation;
383
384 error:
385 _eldbus_introspection_annotation_free(annotation);
386 return NULL;
387}
388
389static void
390_eldbus_introspection_annotation_free(Eldbus_Introspection_Annotation *annotation)
391{
392 EINA_SAFETY_ON_NULL_RETURN(annotation);
393 eina_stringshare_del(annotation->name);
394 eina_stringshare_del(annotation->value);
395 free(annotation);
396}
397
398static void
399_eldbus_introspection_parse_children(Eina_Inlist *children, const Eldbus_Introspection_Element_Parse_Table table[])
400{
401 Eina_Simple_XML_Node *child;
402
403 EINA_INLIST_FOREACH(children, child)
404 {
405 const Eldbus_Introspection_Element_Parse_Table *it;
406 Eina_Simple_XML_Node_Tag *tag;
407 void *item;
408
409 if (EINA_SIMPLE_XML_NODE_TAG != child->type)
410 continue;
411
412 tag = (Eina_Simple_XML_Node_Tag*) child;
413
414 for (it = table; it->name; ++it)
415 {
416 if (strcmp(tag->name, it->name) != 0)
417 continue;
418
419 item = it->parse(tag);
420 if (item)
421 *it->list = eina_list_append(*it->list, item);
422 }
423 }
424}
425
426EAPI Eldbus_Introspection_Interface *
427eldbus_introspection_interface_find(Eina_List *interfaces, const char *name)
428{
429 Eina_List *it;
430 Eldbus_Introspection_Interface *interface;
431
432 EINA_LIST_FOREACH(interfaces, it, interface)
433 {
434 if (strcmp(interface->name, name) == 0)
435 return interface;
436 }
437
438 return NULL;
439}
440
441EAPI Eldbus_Introspection_Property *
442eldbus_introspection_property_find(Eina_List *properties, const char *name)
443{
444 Eina_List *it;
445 Eldbus_Introspection_Property *property;
446
447 EINA_LIST_FOREACH(properties, it, property)
448 {
449 if (strcmp(property->name, name) == 0)
450 return property;
451 }
452
453 return NULL;
454}
455
456EAPI Eldbus_Introspection_Argument *
457eldbus_introspection_argument_find(Eina_List *arguments, const char *name)
458{
459 Eina_List *it;
460 Eldbus_Introspection_Argument *argument;
461
462 EINA_LIST_FOREACH(arguments, it, argument)
463 {
464 if (strcmp(argument->name, name) == 0)
465 return argument;
466 }
467
468 return NULL;
469}
diff --git a/src/lib/eldbus/eldbus_introspection.h b/src/lib/eldbus/eldbus_introspection.h
new file mode 100644
index 0000000..4f37460
--- /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 05bb9f5..3d594fb 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 bac9860..87258bf 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 0000000..f941a72
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_arguments.c
@@ -0,0 +1,417 @@
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 Eina_Bool _eldbus_model_arguments_is_input_argument(Eldbus_Model_Arguments_Data *, const char *);
20static Eina_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 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
34
35 pd->obj = obj;
36 pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
37 pd->properties_array = NULL;
38 pd->properties_hash = eina_hash_string_superfast_new(EINA_FREE_CB(_eldbus_model_arguments_hash_free));
39 pd->pending_list = NULL;
40 pd->proxy = NULL;
41 pd->arguments = NULL;
42 pd->name = NULL;
43 return obj;
44}
45
46static void
47_eldbus_model_arguments_constructor(Eo *obj EINA_UNUSED,
48 Eldbus_Model_Arguments_Data *pd,
49 Eldbus_Proxy *proxy,
50 const char *name,
51 const Eina_List *arguments)
52{
53 EINA_SAFETY_ON_NULL_RETURN(proxy);
54 EINA_SAFETY_ON_NULL_RETURN(name);
55
56 pd->proxy = eldbus_proxy_ref(proxy);
57 pd->arguments = arguments;
58 pd->name = eina_stringshare_add(name);
59}
60
61static void
62_eldbus_model_arguments_eo_base_destructor(Eo *obj, Eldbus_Model_Arguments_Data *pd)
63{
64 _eldbus_model_arguments_unload(pd);
65
66 eina_hash_free(pd->properties_hash);
67
68 eina_stringshare_del(pd->name);
69 eldbus_proxy_unref(pd->proxy);
70
71 eo_do_super(obj, MY_CLASS, eo_destructor());
72}
73
74static Efl_Model_Load_Status
75_eldbus_model_arguments_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
76 Eldbus_Model_Arguments_Data *pd,
77 Eina_Array * const* properties_array)
78{
79 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
80 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
81
82 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
83 {
84 ERR("%s", "o not loaded.");
85 return EFL_MODEL_LOAD_STATUS_ERROR;
86 }
87
88 *(Eina_Array**)properties_array = pd->properties_array;
89 return pd->load.status;
90}
91
92static void
93_eldbus_model_arguments_efl_model_base_properties_load(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd)
94{
95 unsigned int arguments_count;
96 unsigned int i;
97
98 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
99 return;
100
101 arguments_count = eina_list_count(pd->arguments);
102
103 pd->properties_array = eina_array_new(arguments_count);
104 EINA_SAFETY_ON_NULL_RETURN(pd->properties_array);
105
106 for (i = 0; i < arguments_count; ++i)
107 {
108 Eldbus_Introspection_Argument *arg;
109 const Eina_Value_Type *type;
110 Eina_Stringshare *name;
111 Eina_Value *value;
112
113 name = eina_stringshare_printf(ARGUMENT_FORMAT, i);
114 if (!name) continue;
115
116 eina_array_push(pd->properties_array, name);
117
118 arg = eina_list_nth(pd->arguments, i);
119 type = _dbus_type_to_eina_value_type(arg->type[0]);
120 value = eina_value_new(type);
121 eina_hash_add(pd->properties_hash, name, value);
122 }
123
124 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
125}
126
127static Efl_Model_Load_Status
128_eldbus_model_arguments_efl_model_base_property_set(Eo *obj EINA_UNUSED,
129 Eldbus_Model_Arguments_Data *pd,
130 const char *property,
131 Eina_Value const* value)
132{
133 Eina_Value *prop_value;
134 Eina_Bool ret;
135
136 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
137 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
138 DBG("(%p): property=%s", obj, property);
139
140 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
141 return EFL_MODEL_LOAD_STATUS_ERROR;
142
143 if (!_eldbus_model_arguments_is_input_argument(pd, property))
144 {
145 WRN("Property (argument) not found or it is for output only: %s", property);
146 return EFL_MODEL_LOAD_STATUS_ERROR;
147 }
148
149 prop_value = eina_hash_find(pd->properties_hash, property);
150 EINA_SAFETY_ON_NULL_RETURN_VAL(prop_value, EFL_MODEL_LOAD_STATUS_ERROR);
151
152 eina_value_flush(prop_value);
153 ret = eina_value_copy(value, prop_value);
154 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
155
156 return pd->load.status;
157}
158
159static Efl_Model_Load_Status
160_eldbus_model_arguments_efl_model_base_property_get(Eo *obj EINA_UNUSED,
161 Eldbus_Model_Arguments_Data *pd,
162 const char *property,
163 Eina_Value const ** value)
164{
165 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
166 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
167 DBG("(%p): property=%s", obj, property);
168
169 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
170 return EFL_MODEL_LOAD_STATUS_ERROR;
171
172 if (!_eldbus_model_arguments_is_output_argument(pd, property))
173 {
174 WRN("Property (argument) not found or it is for input only: %s", property);
175 return EFL_MODEL_LOAD_STATUS_ERROR;
176 }
177
178 *value = eina_hash_find(pd->properties_hash, property);
179 EINA_SAFETY_ON_NULL_RETURN_VAL(*value, EFL_MODEL_LOAD_STATUS_ERROR);
180
181 return pd->load.status;
182}
183
184static void
185_eldbus_model_arguments_efl_model_base_load(Eo *obj, Eldbus_Model_Arguments_Data *pd EINA_UNUSED)
186{
187 eo_do(obj, efl_model_properties_load());
188 eo_do(obj, efl_model_children_load());
189}
190
191static Efl_Model_Load_Status
192_eldbus_model_arguments_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd)
193{
194 return pd->load.status;
195}
196
197static void
198_eldbus_model_arguments_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd)
199{
200 _eldbus_model_arguments_unload(pd);
201
202 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
203}
204
205static Eo *
206_eldbus_model_arguments_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd EINA_UNUSED)
207{
208 return NULL;
209}
210
211static Efl_Model_Load_Status
212_eldbus_model_arguments_efl_model_base_child_del(Eo *obj EINA_UNUSED,
213 Eldbus_Model_Arguments_Data *pd EINA_UNUSED,
214 Eo *child EINA_UNUSED)
215{
216 return EFL_MODEL_LOAD_STATUS_ERROR;
217}
218
219static Efl_Model_Load_Status
220_eldbus_model_arguments_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
221 Eldbus_Model_Arguments_Data *pd,
222 unsigned start EINA_UNUSED,
223 unsigned count EINA_UNUSED,
224 Eina_Accessor **children_accessor)
225{
226 *children_accessor = NULL;
227 return pd->load.status;
228}
229
230static Efl_Model_Load_Status
231_eldbus_model_arguments_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
232 Eldbus_Model_Arguments_Data *pd,
233 unsigned *children_count)
234{
235 *children_count = 0;
236 return pd->load.status;
237}
238
239static void
240_eldbus_model_arguments_efl_model_base_children_load(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd)
241{
242 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
243 return;
244
245 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
246}
247
248static const char *
249_eldbus_model_arguments_name_get(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd)
250{
251 return pd->name;
252}
253
254static void
255_eldbus_model_arguments_unload(Eldbus_Model_Arguments_Data *pd)
256{
257 Eldbus_Pending *pending;
258
259 EINA_SAFETY_ON_NULL_RETURN(pd);
260
261 EINA_LIST_FREE(pd->pending_list, pending)
262 eldbus_pending_cancel(pending);
263
264 if (pd->properties_array)
265 {
266 Eina_Stringshare *property;
267 Eina_Array_Iterator it;
268 unsigned int i;
269
270 EINA_ARRAY_ITER_NEXT(pd->properties_array, i, property, it)
271 eina_stringshare_del(property);
272 eina_array_free(pd->properties_array);
273 pd->properties_array = NULL;
274 }
275
276 eina_hash_free_buckets(pd->properties_hash);
277}
278
279Eina_Bool
280eldbus_model_arguments_process_arguments(Eldbus_Model_Arguments_Data *pd,
281 const Eldbus_Message *msg,
282 Eldbus_Pending *pending)
283{
284 const Eldbus_Introspection_Argument *argument;
285 const char *error_name, *error_text;
286 const Eina_List *it;
287 Eina_Value *value_struct;
288 Eina_Array *changed_properties;
289 unsigned int i = 0;
290 Eina_Bool result = EINA_FALSE;
291
292 pd->pending_list = eina_list_remove(pd->pending_list, pending);
293 if (eldbus_message_error_get(msg, &error_name, &error_text))
294 {
295 ERR("%s: %s", error_name, error_text);
296 efl_model_error_notify(pd->obj);
297 return EINA_FALSE;
298 }
299
300 value_struct = eldbus_message_to_eina_value(msg);
301 if (value_struct == NULL)
302 {
303 INF("%s", "No output arguments");
304 return EINA_TRUE;
305 }
306
307 changed_properties = eina_array_new(1);
308
309 EINA_LIST_FOREACH(pd->arguments, it, argument)
310 {
311 if (ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN != argument->direction)
312 {
313 const Eina_Stringshare *property;
314 Eina_Bool ret;
315
316 property = eina_array_data_get(pd->properties_array, i);
317 EINA_SAFETY_ON_NULL_GOTO(property, on_error);
318
319 ret = _eldbus_model_arguments_property_set(pd, value_struct, property);
320 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
321
322 ret = eina_array_push(changed_properties, property);
323 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
324 }
325
326 ++i;
327 }
328
329 if (eina_array_count(changed_properties))
330 {
331 Efl_Model_Property_Event evt = {.changed_properties = changed_properties};
332 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
333 }
334
335 result = EINA_TRUE;
336
337on_error:
338 eina_array_free(changed_properties);
339 eina_value_free(value_struct);
340
341 return result;
342}
343
344static Eina_Bool
345_eldbus_model_arguments_property_set(Eldbus_Model_Arguments_Data *pd,
346 Eina_Value *value_struct,
347 const char *property)
348{
349 Eina_Value *prop_value;
350 Eina_Value value;
351 Eina_Bool ret;
352
353 prop_value = eina_hash_find(pd->properties_hash, property);
354 EINA_SAFETY_ON_NULL_RETURN_VAL(prop_value, EINA_FALSE);
355
356 ret = eina_value_struct_value_get(value_struct, "arg0", &value);
357 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EINA_FALSE);
358
359 eina_value_flush(prop_value);
360 ret = eina_value_copy(&value, prop_value);
361 eina_value_flush(&value);
362 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EINA_FALSE);
363
364 return ret;
365}
366
367static Eina_Bool
368_eldbus_model_arguments_is(Eldbus_Model_Arguments_Data *pd,
369 const char *argument,
370 Eldbus_Introspection_Argument_Direction direction)
371{
372 Eldbus_Introspection_Argument *argument_introspection;
373 unsigned int i;
374
375 i = _eldbus_model_arguments_argument_index_get(pd, argument);
376 if (i >= eina_array_count(pd->properties_array))
377 {
378 WRN("Argument not found: %s", argument);
379 return false;
380 }
381
382 argument_introspection = eina_list_nth(pd->arguments, i);
383 EINA_SAFETY_ON_NULL_RETURN_VAL(argument_introspection, EINA_FALSE);
384
385 return argument_introspection->direction == direction;
386}
387
388static Eina_Bool
389_eldbus_model_arguments_is_input_argument(Eldbus_Model_Arguments_Data *pd, const char *argument)
390{
391 return _eldbus_model_arguments_is(pd, argument, ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN);
392}
393
394static Eina_Bool
395_eldbus_model_arguments_is_output_argument(Eldbus_Model_Arguments_Data *pd, const char *argument)
396{
397 return _eldbus_model_arguments_is(pd, argument, ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_OUT) ||
398 _eldbus_model_arguments_is(pd, argument, ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_NONE);
399}
400
401static unsigned int
402_eldbus_model_arguments_argument_index_get(Eldbus_Model_Arguments_Data *pd, const char *argument)
403{
404 const Eina_Stringshare *name;
405 Eina_Array_Iterator it;
406 unsigned int i = 0;
407
408 EINA_ARRAY_ITER_NEXT(pd->properties_array, i, name, it)
409 {
410 if (strcmp(name, argument) == 0)
411 return i;
412 }
413
414 return ++i;
415}
416
417#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 0000000..64f39f9
--- /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 0000000..08e65d8
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_arguments_private.h
@@ -0,0 +1,28 @@
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
26Eina_Bool eldbus_model_arguments_process_arguments(Eldbus_Model_Arguments_Data *, const Eldbus_Message *, Eldbus_Pending *);
27
28#endif
diff --git a/src/lib/eldbus/eldbus_model_connection.c b/src/lib/eldbus/eldbus_model_connection.c
new file mode 100644
index 0000000..6325a5a
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_connection.c
@@ -0,0 +1,361 @@
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 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
24
25 pd->obj = obj;
26 pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
27 pd->connection = NULL;
28 pd->properties_array = NULL;
29 pd->children_list = NULL;
30 pd->type = ELDBUS_CONNECTION_TYPE_UNKNOWN;
31 pd->address = NULL;
32 pd->private = false;
33 pd->unique_name = NULL;
34 pd->pending_list = NULL;
35
36 return obj;
37}
38
39static void
40_eldbus_model_connection_constructor(Eo *obj EINA_UNUSED,
41 Eldbus_Model_Connection_Data *pd,
42 int type,
43 const char* address,
44 Eina_Bool private)
45{
46 pd->type = type;
47 pd->address = eina_stringshare_add(address);
48 pd->private = private;
49}
50
51static void
52_eldbus_model_connection_eo_base_destructor(Eo *obj, Eldbus_Model_Connection_Data *pd)
53{
54 eina_stringshare_del(pd->address);
55
56 _eldbus_model_connection_clear(pd);
57
58 eo_do_super(obj, MY_CLASS, eo_destructor());
59}
60
61static Efl_Model_Load_Status
62_eldbus_model_connection_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
63 Eldbus_Model_Connection_Data *pd,
64 Eina_Array * const* properties_array)
65{
66 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
67 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
68
69 if (pd->properties_array == NULL)
70 {
71 Eina_Bool ret;
72
73 pd->properties_array = eina_array_new(1);
74 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->properties_array, EFL_MODEL_LOAD_STATUS_ERROR);
75
76 ret = eina_array_push(pd->properties_array, UNIQUE_NAME_PROPERTY);
77 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
78 }
79
80 *(Eina_Array**)properties_array = pd->properties_array;
81 return pd->load.status;
82}
83
84static void
85_eldbus_model_connection_efl_model_base_properties_load(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
86{
87 const char *unique_name;
88 Eina_Bool ret;
89
90 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
91 return;
92
93 if (!pd->connection)
94 _eldbus_model_connection_connect(pd);
95
96 pd->unique_name = eina_value_new(EINA_VALUE_TYPE_STRING);
97 EINA_SAFETY_ON_NULL_RETURN(pd->unique_name);
98
99 unique_name = eldbus_connection_unique_name_get(pd->connection);
100 ret = eina_value_set(pd->unique_name, unique_name);
101 EINA_SAFETY_ON_FALSE_RETURN(ret);
102
103 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
104}
105
106static Efl_Model_Load_Status
107_eldbus_model_connection_efl_model_base_property_set(Eo *obj EINA_UNUSED,
108 Eldbus_Model_Connection_Data *pd EINA_UNUSED,
109 const char *property EINA_UNUSED,
110 Eina_Value const* value EINA_UNUSED)
111{
112 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
113 DBG("(%p): property=%s", obj, property);
114 return EFL_MODEL_LOAD_STATUS_ERROR;
115}
116
117static Efl_Model_Load_Status
118_eldbus_model_connection_efl_model_base_property_get(Eo *obj EINA_UNUSED,
119 Eldbus_Model_Connection_Data *pd,
120 const char *property,
121 Eina_Value const **value)
122{
123 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
124 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
125 DBG("(%p): property=%s", obj, property);
126
127 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
128 return EFL_MODEL_LOAD_STATUS_ERROR;
129
130 if (strcmp(property, UNIQUE_NAME_PROPERTY) != 0)
131 return EFL_MODEL_LOAD_STATUS_ERROR;
132
133 *value = pd->unique_name;
134 return pd->load.status;
135}
136
137static void
138_eldbus_model_connection_efl_model_base_load(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
139{
140 if (!pd->connection)
141 _eldbus_model_connection_connect(pd);
142
143 _eldbus_model_connection_efl_model_base_properties_load(obj, pd);
144 _eldbus_model_connection_efl_model_base_children_load(obj, pd);
145}
146
147static Efl_Model_Load_Status
148_eldbus_model_connection_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
149{
150 return pd->load.status;
151}
152
153static void
154_eldbus_model_connection_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
155{
156 _eldbus_model_connection_clear(pd);
157
158 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
159}
160
161static Eo *
162_eldbus_model_connection_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd EINA_UNUSED)
163{
164 return NULL;
165}
166
167static Efl_Model_Load_Status
168_eldbus_model_connection_efl_model_base_child_del(Eo *obj EINA_UNUSED,
169 Eldbus_Model_Connection_Data *pd EINA_UNUSED,
170 Eo *child EINA_UNUSED)
171{
172 return EFL_MODEL_LOAD_STATUS_ERROR;
173}
174
175static Efl_Model_Load_Status
176_eldbus_model_connection_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
177 Eldbus_Model_Connection_Data *pd,
178 unsigned start,
179 unsigned count,
180 Eina_Accessor **children_accessor)
181{
182 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
183 {
184 WRN("(%p): Children not loaded", obj);
185 *children_accessor = NULL;
186 return pd->load.status;
187 }
188
189 *children_accessor = efl_model_list_slice(pd->children_list, start, count);
190 return pd->load.status;
191}
192
193static Efl_Model_Load_Status
194_eldbus_model_connection_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
195 Eldbus_Model_Connection_Data *pd,
196 unsigned *children_count)
197{
198 *children_count = eina_list_count(pd->children_list);
199 return pd->load.status;
200}
201
202static void
203_eldbus_model_connection_efl_model_base_children_load(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
204{
205 Eldbus_Pending *pending;
206
207 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
208 return;
209
210 if (!pd->connection)
211 _eldbus_model_connection_connect(pd);
212
213 pending = eldbus_names_list(pd->connection, &_eldbus_model_connection_names_list_cb, pd);
214 pd->pending_list = eina_list_append(pd->pending_list, pending);
215
216 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
217}
218
219static const char *
220_eldbus_model_connection_address_get(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
221{
222 return pd->address;
223}
224
225static void
226_eldbus_model_connection_address_set(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd, const char *value)
227{
228 eina_stringshare_del(pd->address);
229 pd->address = eina_stringshare_add(value);
230}
231
232static Eina_Bool
233_eldbus_model_connection_private_get(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
234{
235 return pd->private;
236}
237
238static void
239_eldbus_model_connection_private_set(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd, Eina_Bool value)
240{
241 pd->private = value;
242}
243
244static int
245_eldbus_model_connection_type_get(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd)
246{
247 return pd->type;
248}
249
250static void
251_eldbus_model_connection_type_set(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd, int value)
252{
253 pd->type = value;
254}
255
256static void
257_eldbus_model_connection_connect(Eldbus_Model_Connection_Data *pd)
258{
259 EINA_SAFETY_ON_NULL_RETURN(pd);
260
261 if (ELDBUS_CONNECTION_TYPE_ADDRESS == pd->type)
262 {
263 if (pd->private)
264 pd->connection = eldbus_address_connection_get(pd->address);
265 else
266 pd->connection = eldbus_private_address_connection_get(pd->address);
267 }
268 else
269 {
270 if (pd->private)
271 pd->connection = eldbus_private_connection_get(pd->type);
272 else
273 pd->connection = eldbus_connection_get(pd->type);
274 }
275
276 // TODO: Register for disconnection event
277
278 EINA_SAFETY_ON_FALSE_RETURN(pd->connection != NULL);
279}
280
281static void
282_eldbus_model_connection_disconnect(Eldbus_Model_Connection_Data *pd)
283{
284 EINA_SAFETY_ON_NULL_RETURN(pd);
285 eldbus_connection_unref(pd->connection);
286 pd->connection = NULL;
287}
288
289static void
290_eldbus_model_connection_clear(Eldbus_Model_Connection_Data *pd)
291{
292 Eldbus_Pending *pending;
293 Eo *child;
294
295 EINA_SAFETY_ON_NULL_RETURN(pd);
296
297 if (!pd->connection)
298 return;
299
300 eina_value_free(pd->unique_name);
301 pd->unique_name = NULL;
302
303 EINA_LIST_FREE(pd->children_list, child)
304 eo_unref(child);
305
306 EINA_LIST_FREE(pd->pending_list, pending)
307 eldbus_pending_cancel(pending);
308
309 if (pd->properties_array)
310 {
311 eina_array_free(pd->properties_array);
312 pd->properties_array = NULL;
313 }
314
315 _eldbus_model_connection_disconnect(pd);
316}
317
318static void
319_eldbus_model_connection_names_list_cb(void *data,
320 const Eldbus_Message *msg,
321 Eldbus_Pending *pending)
322{
323 Eldbus_Model_Connection_Data *pd = (Eldbus_Model_Connection_Data*)data;
324 const char *error_name, *error_text;
325 Eldbus_Message_Iter *array = NULL;
326 const char *bus;
327 unsigned int count;
328
329 pd->pending_list = eina_list_remove(pd->pending_list, pending);
330
331 if (eldbus_message_error_get(msg, &error_name, &error_text))
332 {
333 ERR("%s: %s", error_name, error_text);
334 efl_model_error_notify(pd->obj);
335 return;
336 }
337
338 if (!eldbus_message_arguments_get(msg, "as", &array))
339 {
340 ERR("%s", "Error getting arguments.");
341 return;
342 }
343
344 while (eldbus_message_iter_get_and_next(array, 's', &bus))
345 {
346 DBG("(%p): bus = %s", pd->obj, bus);
347
348 Eo *child = eo_add(ELDBUS_MODEL_OBJECT_CLASS, NULL,
349 eldbus_model_object_connection_constructor(pd->connection, bus, "/"));
350
351 pd->children_list = eina_list_append(pd->children_list, child);
352 }
353
354 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
355
356 count = eina_list_count(pd->children_list);
357 if (count)
358 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
359}
360
361#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 0000000..3f2e5ab
--- /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 0000000..4123f92
--- /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 0000000..69e55cc
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_method.c
@@ -0,0 +1,102 @@
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 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
23
24 pd->obj = obj;
25 pd->method = NULL;
26 return obj;
27}
28
29static void
30_eldbus_model_method_constructor(Eo *obj EINA_UNUSED,
31 Eldbus_Model_Method_Data *pd,
32 Eldbus_Proxy *proxy,
33 const Eldbus_Introspection_Method *method)
34{
35 EINA_SAFETY_ON_NULL_RETURN(proxy);
36 EINA_SAFETY_ON_NULL_RETURN(method);
37
38 eo_do_super(obj, MY_CLASS, eldbus_model_arguments_constructor(proxy, method->name, method->arguments));
39
40 pd->method = method;
41}
42
43static Efl_Model_Load_Status
44_eldbus_model_method_call(Eo *obj EINA_UNUSED, Eldbus_Model_Method_Data *pd EINA_UNUSED)
45{
46 Eldbus_Model_Arguments_Data *data = eo_data_scope_get(obj, ELDBUS_MODEL_ARGUMENTS_CLASS);
47 Eldbus_Message *msg = eldbus_proxy_method_call_new(data->proxy, data->name);
48 Eldbus_Message_Iter *iter = eldbus_message_iter_get(msg);
49 const Eldbus_Introspection_Argument *argument;
50 const Eina_List *it;
51 Eldbus_Pending *pending;
52 unsigned int i = 0;
53
54 EINA_LIST_FOREACH(data->arguments, it, argument)
55 {
56 const Eina_Stringshare *name;
57 const Eina_Value *value;
58 const char *signature;
59 Eina_Bool ret;
60
61 if (ELDBUS_INTROSPECTION_ARGUMENT_DIRECTION_IN != argument->direction)
62 continue;
63
64 name = eina_array_data_get(data->properties_array, i);
65 if (!name) continue;
66 EINA_SAFETY_ON_NULL_GOTO(name, on_error);
67
68 value = eina_hash_find(data->properties_hash, name);
69 EINA_SAFETY_ON_NULL_GOTO(value, on_error);
70
71 signature = argument->type;
72 if (dbus_type_is_basic(signature[0]))
73 ret = _message_iter_from_eina_value(signature, iter, value);
74 else
75 ret = _message_iter_from_eina_value_struct(signature, iter, value);
76
77 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
78
79 ++i;
80 }
81
82 pending = eldbus_proxy_send(data->proxy, msg, _eldbus_model_method_call_cb, pd, -1);
83 data->pending_list = eina_list_append(data->pending_list, pending);
84
85 return data->load.status;
86
87on_error:
88 eldbus_message_unref(msg);
89 return EFL_MODEL_LOAD_STATUS_ERROR;
90}
91
92static void
93_eldbus_model_method_call_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
94{
95 Eldbus_Model_Method_Data *pd = (Eldbus_Model_Method_Data*)data;
96 Eldbus_Model_Arguments_Data *args_data = eo_data_scope_get(pd->obj, ELDBUS_MODEL_ARGUMENTS_CLASS);
97
98 if (eldbus_model_arguments_process_arguments(args_data, msg, pending))
99 eo_do(pd->obj, eo_event_callback_call(ELDBUS_MODEL_METHOD_EVENT_SUCCESSFUL_CALL, NULL));
100}
101
102#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 0000000..8b9d714
--- /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 0000000..5092b50
--- /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 0000000..115330e
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_object.c
@@ -0,0 +1,542 @@
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 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
30
31 pd->obj = obj;
32 pd->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
33 pd->connection = NULL;
34 pd->object_list = NULL;
35 pd->properties_array = NULL;
36 pd->children_list = NULL;
37 pd->type = ELDBUS_CONNECTION_TYPE_UNKNOWN;
38 pd->address = NULL;
39 pd->private = false;
40 pd->bus = NULL;
41 pd->path = NULL;
42 pd->unique_name = NULL;
43 pd->pending_list = NULL;
44 pd->introspection = NULL;
45
46 return obj;
47}
48
49static void
50_eldbus_model_object_constructor(Eo *obj EINA_UNUSED,
51 Eldbus_Model_Object_Data *pd,
52 int type,
53 const char* address,
54 Eina_Bool private,
55 const char* bus,
56 const char* path)
57{
58 EINA_SAFETY_ON_NULL_RETURN(bus);
59 EINA_SAFETY_ON_NULL_RETURN(path);
60
61 pd->type = type;
62 pd->address = eina_stringshare_add(address);
63 pd->private = private;
64 pd->bus = eina_stringshare_add(bus);
65 pd->path = eina_stringshare_add(path);
66}
67
68static void
69_eldbus_model_object_connection_constructor(Eo *obj EINA_UNUSED,
70 Eldbus_Model_Object_Data *pd,
71 Eldbus_Connection *connection,
72 const char* bus,
73 const char* path)
74{
75 EINA_SAFETY_ON_NULL_RETURN(connection);
76 EINA_SAFETY_ON_NULL_RETURN(bus);
77 EINA_SAFETY_ON_NULL_RETURN(path);
78
79 pd->connection = eldbus_connection_ref(connection);
80 pd->bus = eina_stringshare_add(bus);
81 pd->path = eina_stringshare_add(path);
82}
83
84static void
85_eldbus_model_object_eo_base_destructor(Eo *obj, Eldbus_Model_Object_Data *pd)
86{
87 eina_stringshare_del(pd->address);
88 eina_stringshare_del(pd->bus);
89 eina_stringshare_del(pd->path);
90
91 _eldbus_model_object_clear(pd);
92
93 eo_do_super(obj, MY_CLASS, eo_destructor());
94}
95
96static Efl_Model_Load_Status
97_eldbus_model_object_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
98 Eldbus_Model_Object_Data *pd,
99 Eina_Array * const* properties_array)
100{
101 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
102 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
103
104 if (pd->properties_array == NULL)
105 {
106 Eina_Bool ret;
107
108 pd->properties_array = eina_array_new(1);
109 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->properties_array, EFL_MODEL_LOAD_STATUS_ERROR);
110
111 ret = eina_array_push(pd->properties_array, UNIQUE_NAME_PROPERTY);
112 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EFL_MODEL_LOAD_STATUS_ERROR);
113 }
114
115 *(Eina_Array**)properties_array = pd->properties_array;
116 return pd->load.status;
117}
118
119static void
120_eldbus_model_object_efl_model_base_properties_load(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
121{
122 const char *unique_name;
123 Eina_Bool ret;
124
125 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
126 return;
127
128 if (!pd->connection)
129 _eldbus_model_object_connect(pd);
130
131 pd->unique_name = eina_value_new(EINA_VALUE_TYPE_STRING);
132 EINA_SAFETY_ON_NULL_RETURN(pd->unique_name);
133
134 unique_name = eldbus_connection_unique_name_get(pd->connection);
135 ret = eina_value_set(pd->unique_name, unique_name);
136 EINA_SAFETY_ON_FALSE_RETURN(ret);
137
138 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
139}
140
141static Efl_Model_Load_Status
142_eldbus_model_object_efl_model_base_property_set(Eo *obj EINA_UNUSED,
143 Eldbus_Model_Object_Data *pd EINA_UNUSED,
144 const char *property EINA_UNUSED,
145 Eina_Value const* value EINA_UNUSED)
146{
147 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
148 DBG("(%p): property=%s", obj, property);
149 return EFL_MODEL_LOAD_STATUS_ERROR;
150}
151
152static Efl_Model_Load_Status
153_eldbus_model_object_efl_model_base_property_get(Eo *obj EINA_UNUSED,
154 Eldbus_Model_Object_Data *pd,
155 const char *property,
156 Eina_Value const**value)
157{
158 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
159 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
160 DBG("(%p): property=%s", obj, property);
161
162 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
163 return EFL_MODEL_LOAD_STATUS_ERROR;
164
165 if (strcmp(property, UNIQUE_NAME_PROPERTY) != 0)
166 return EFL_MODEL_LOAD_STATUS_ERROR;
167
168 *value = pd->unique_name;
169 return pd->load.status;
170}
171
172static void
173_eldbus_model_object_efl_model_base_load(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
174{
175 if (!pd->connection)
176 _eldbus_model_object_connect(pd);
177
178 _eldbus_model_object_efl_model_base_properties_load(obj, pd);
179 _eldbus_model_object_efl_model_base_children_load(obj, pd);
180}
181
182static Efl_Model_Load_Status
183_eldbus_model_object_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
184{
185 return pd->load.status;
186}
187
188static void
189_eldbus_model_object_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
190{
191 _eldbus_model_object_clear(pd);
192
193 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
194}
195
196static Eo *
197_eldbus_model_object_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd EINA_UNUSED)
198{
199 return NULL;
200}
201
202static Efl_Model_Load_Status
203_eldbus_model_object_efl_model_base_child_del(Eo *obj EINA_UNUSED,
204 Eldbus_Model_Object_Data *pd EINA_UNUSED,
205 Eo *child EINA_UNUSED)
206{
207 return EFL_MODEL_LOAD_STATUS_ERROR;
208}
209
210static Efl_Model_Load_Status
211_eldbus_model_object_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
212 Eldbus_Model_Object_Data *pd,
213 unsigned start,
214 unsigned count,
215 Eina_Accessor **children_accessor)
216{
217 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
218 {
219 WRN("(%p): Children not loaded", obj);
220 *children_accessor = NULL;
221 return pd->load.status;
222 }
223 else
224 WRN("(%p): Children already loaded", obj);
225
226 *children_accessor = efl_model_list_slice(pd->children_list, start, count);
227 return pd->load.status;
228}
229
230static Efl_Model_Load_Status
231_eldbus_model_object_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
232 Eldbus_Model_Object_Data *pd,
233 unsigned *children_count)
234{
235 *children_count = eina_list_count(pd->children_list);
236 return pd->load.status;
237}
238
239static void
240_eldbus_model_object_efl_model_base_children_load(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
241{
242 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
243 return;
244
245 if (!pd->connection)
246 _eldbus_model_object_connect(pd);
247
248 if (!_eldbus_model_object_introspect(pd, pd->bus, pd->path))
249 return;
250
251 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
252}
253
254static const char *
255_eldbus_model_object_address_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
256{
257 return pd->address;
258}
259
260static void
261_eldbus_model_object_address_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, const char *value)
262{
263 eina_stringshare_del(pd->address);
264 pd->address = eina_stringshare_add(value);
265}
266
267static Eina_Bool
268_eldbus_model_object_private_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
269{
270 return pd->private;
271}
272
273static void
274_eldbus_model_object_private_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, Eina_Bool value)
275{
276 pd->private = value;
277}
278
279static int
280_eldbus_model_object_type_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
281{
282 return pd->type;
283}
284
285static void
286_eldbus_model_object_type_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, int value)
287{
288 pd->type = value;
289}
290
291static const char *
292_eldbus_model_object_bus_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
293{
294 return pd->bus;
295}
296
297static void
298_eldbus_model_object_bus_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, const char *value)
299{
300 eina_stringshare_del(pd->bus);
301 pd->bus = eina_stringshare_add(value);
302}
303
304static const char *
305_eldbus_model_object_path_get(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd)
306{
307 return pd->path;
308}
309
310static void
311_eldbus_model_object_path_set(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd, const char *value)
312{
313 eina_stringshare_del(pd->path);
314 pd->path = eina_stringshare_add(value);
315}
316
317static void
318_eldbus_model_object_connect(Eldbus_Model_Object_Data *pd)
319{
320 EINA_SAFETY_ON_NULL_RETURN(pd);
321
322 if (ELDBUS_CONNECTION_TYPE_ADDRESS == pd->type)
323 {
324 if (pd->private)
325 pd->connection = eldbus_address_connection_get(pd->address);
326 else
327 pd->connection = eldbus_private_address_connection_get(pd->address);
328 }
329 else
330 {
331 if (pd->private)
332 pd->connection = eldbus_private_connection_get(pd->type);
333 else
334 pd->connection = eldbus_connection_get(pd->type);
335 }
336
337 // TODO: Register for disconnection event
338
339 EINA_SAFETY_ON_FALSE_RETURN(NULL != pd->connection);
340}
341
342static void
343_eldbus_model_object_disconnect(Eldbus_Model_Object_Data *pd)
344{
345 EINA_SAFETY_ON_NULL_RETURN(pd);
346 eldbus_connection_unref(pd->connection);
347 pd->connection = NULL;
348}
349
350static void
351_eldbus_model_object_clear(Eldbus_Model_Object_Data *pd)
352{
353 Eldbus_Pending *pending;
354 Eldbus_Object *object;
355 Eo *child;
356
357 EINA_SAFETY_ON_NULL_RETURN(pd);
358 if (!pd->connection)
359 return;
360
361 eina_value_free(pd->unique_name);
362 pd->unique_name = NULL;
363
364 EINA_LIST_FREE(pd->children_list, child)
365 eo_unref(child);
366
367 EINA_LIST_FREE(pd->pending_list, pending)
368 eldbus_pending_cancel(pending);
369
370 if (pd->properties_array)
371 {
372 eina_array_free(pd->properties_array);
373 pd->properties_array = NULL;
374 }
375
376 EINA_LIST_FREE(pd->object_list, object)
377 eldbus_object_unref(object);
378
379 if (pd->introspection)
380 {
381 eldbus_introspection_node_free(pd->introspection);
382 pd->introspection = NULL;
383 }
384
385 _eldbus_model_object_disconnect(pd);
386}
387
388
389static bool
390_eldbus_model_object_introspect(Eldbus_Model_Object_Data *pd,
391 const char *bus,
392 const char *path)
393{
394 Eldbus_Object *object;
395 Eldbus_Pending *pending;
396
397 EINA_SAFETY_ON_NULL_RETURN_VAL(bus, false);
398 EINA_SAFETY_ON_NULL_RETURN_VAL(path, false);
399
400 DBG("(%p) Introspecting: bus = %s, path = %s", pd->obj, bus, path);
401
402 object = eldbus_object_get(pd->connection, bus, path);
403 if (!object)
404 {
405 ERR("(%p): Cannot get object: bus=%s, path=%s", pd->obj, bus, path);
406 return false;
407 }
408 pd->object_list = eina_list_append(pd->object_list, object);
409
410 // TODO: Register for interface added/removed event
411
412 pending = eldbus_object_introspect(object, &_eldbus_model_object_introspect_cb, pd);
413 eldbus_pending_data_set(pending, "object", object);
414 pd->pending_list = eina_list_append(pd->pending_list, pending);
415 return true;
416}
417
418static void
419_eldbus_model_object_introspect_cb(void *data,
420 const Eldbus_Message *msg,
421 Eldbus_Pending *pending)
422{
423 Eldbus_Model_Object_Data *pd = (Eldbus_Model_Object_Data*)data;
424 Eldbus_Object *object;
425 const char *error_name, *error_text;
426 const char *xml = NULL;
427 const char *current_path;
428
429 pd->pending_list = eina_list_remove(pd->pending_list, pending);
430 object = eldbus_pending_data_get(pending, "object");
431
432 if (eldbus_message_error_get(msg, &error_name, &error_text))
433 {
434 ERR("%s: %s", error_name, error_text);
435 efl_model_error_notify(pd->obj);
436 return;
437 }
438
439 if (!eldbus_message_arguments_get(msg, "s", &xml))
440 {
441 ERR("Error getting arguments.");
442 return;
443 }
444 EINA_SAFETY_ON_NULL_RETURN(xml);
445
446 current_path = eldbus_object_path_get(object);
447 EINA_SAFETY_ON_NULL_RETURN(current_path);
448
449 DBG("(%p): introspect of bus = %s, path = %s =>\n%s", pd->obj, pd->bus, current_path, xml);
450
451 pd->introspection = eldbus_introspection_parse(xml);
452 EINA_SAFETY_ON_NULL_RETURN(pd->introspection);
453
454 _eldbus_model_object_introspect_nodes(pd, current_path, pd->introspection->nodes);
455 _eldbus_model_object_create_children(pd, object, pd->introspection->interfaces);
456
457 if (eina_list_count(pd->pending_list) == 0)
458 {
459 unsigned int count;
460
461 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
462
463 count = eina_list_count(pd->children_list);
464 if (count)
465 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
466 }
467}
468
469static void
470_eldbus_model_object_introspect_nodes(Eldbus_Model_Object_Data *pd, const char *current_path, Eina_List *nodes)
471{
472 Eina_List *it;
473 Eldbus_Introspection_Node *node;
474
475 EINA_SAFETY_ON_NULL_RETURN(pd);
476 EINA_SAFETY_ON_NULL_RETURN(current_path);
477
478 EINA_LIST_FOREACH(nodes, it, node)
479 {
480 const char *relative_path;
481 char *absolute_path;
482
483 relative_path = node->name;
484 if (!relative_path) continue;
485
486 absolute_path = _eldbus_model_object_concatenate_path(current_path, relative_path);
487 if (!absolute_path) continue;
488
489 _eldbus_model_object_introspect(pd, pd->bus, absolute_path);
490
491 free(absolute_path);
492 }
493}
494
495static char *
496_eldbus_model_object_concatenate_path(const char *root_path, const char *relative_path)
497{
498 Eina_Strbuf *buffer;
499 char *absolute_path = NULL;
500 Eina_Bool ret;
501
502 buffer = eina_strbuf_new();
503 EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, NULL);
504
505 ret = eina_strbuf_append(buffer, root_path);
506 if (strcmp(root_path, "/") != 0)
507 ret = ret && eina_strbuf_append_char(buffer, '/');
508 ret = ret && eina_strbuf_append(buffer, relative_path);
509 EINA_SAFETY_ON_FALSE_GOTO(ret, free_buffer);
510
511 absolute_path = eina_strbuf_string_steal(buffer);
512
513free_buffer:
514 eina_strbuf_free(buffer);
515 return absolute_path;
516}
517
518static void
519_eldbus_model_object_create_children(Eldbus_Model_Object_Data *pd, Eldbus_Object *object, Eina_List *interfaces)
520{
521 Eldbus_Introspection_Interface *interface;
522 Eina_List *it;
523 const char *current_path;
524
525 current_path = eldbus_object_path_get(object);
526 EINA_SAFETY_ON_NULL_RETURN(current_path);
527
528 EINA_LIST_FOREACH(interfaces, it, interface)
529 {
530 Eo *child;
531
532 WRN("(%p) Creating child: bus = %s, path = %s, interface = %s", pd->obj, pd->bus, current_path, interface->name);
533
534 // TODO: increment reference to keep 'interface' in memory
535 child = eo_add_ref(ELDBUS_MODEL_PROXY_CLASS, NULL,
536 eldbus_model_proxy_constructor(object, interface));
537
538 pd->children_list = eina_list_append(pd->children_list, child);
539 }
540}
541
542#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 0000000..68cbc81
--- /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 0000000..7454921
--- /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 0000000..784b422
--- /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 0000000..ffae0fc
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_proxy.c
@@ -0,0 +1,718 @@
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
64 return obj;
65}
66
67static void
68_eldbus_model_proxy_constructor(Eo *obj EINA_UNUSED,
69 Eldbus_Model_Proxy_Data *pd,
70 Eldbus_Object *object,
71 const Eldbus_Introspection_Interface *interface)
72{
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 _eldbus_model_proxy_unload(pd);
85
86 eina_hash_free(pd->properties_hash);
87
88 eina_stringshare_del(pd->name);
89 eldbus_object_unref(pd->object);
90
91 eo_do_super(obj, MY_CLASS, eo_destructor());
92}
93
94static Efl_Model_Load_Status
95_eldbus_model_proxy_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
96 Eldbus_Model_Proxy_Data *pd,
97 Eina_Array * const* properties_array)
98{
99 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EFL_MODEL_LOAD_STATUS_ERROR);
100 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EFL_MODEL_LOAD_STATUS_ERROR);
101
102 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
103 {
104 WRN("%s", "Properties not loaded.");
105 return EFL_MODEL_LOAD_STATUS_ERROR;
106 }
107
108 *(Eina_Array**)properties_array = pd->properties_array;
109 return pd->load.status;
110}
111
112static void
113_eldbus_model_proxy_efl_model_base_properties_load(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
114{
115 Eldbus_Introspection_Property *property;
116 Eina_List *it;
117 Eldbus_Pending *pending;
118
119 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
120 return;
121
122 if (!_eldbus_model_proxy_load(pd))
123 return;
124
125 const unsigned int properties_count = eina_list_count(pd->interface->properties);
126
127 pd->properties_array = eina_array_new(properties_count);
128 EINA_SAFETY_ON_NULL_RETURN(pd->properties_array);
129
130 if (!properties_count)
131 {
132 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
133 return;
134 }
135
136 EINA_LIST_FOREACH(pd->interface->properties, it, property)
137 {
138 Eina_Stringshare *name;
139 Eina_Bool ret;
140
141 name = eina_stringshare_add(property->name);
142 ret = eina_array_push(pd->properties_array, name);
143 EINA_SAFETY_ON_FALSE_RETURN(ret);
144 }
145
146 pending = eldbus_proxy_property_get_all(pd->proxy, _eldbus_model_proxy_property_get_all_cb, pd);
147 pd->pending_list = eina_list_append(pd->pending_list, pending);
148
149 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES);
150}
151
152static Efl_Model_Load_Status
153_eldbus_model_proxy_efl_model_base_property_set(Eo *obj EINA_UNUSED,
154 Eldbus_Model_Proxy_Data *pd,
155 const char *property,
156 Eina_Value const* value)
157{
158 Eldbus_Model_Proxy_Property_Set_Data *data;
159 const char *signature;
160 Eldbus_Pending *pending;
161
162 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
163
164 DBG("(%p): property=%s", obj, property);
165
166 if (!_eldbus_model_proxy_is_property_writeable(pd, property))
167 {
168 WRN("Property is read-only: %s", property);
169 return EFL_MODEL_LOAD_STATUS_ERROR;
170 }
171
172 data = _eldbus_model_proxy_property_set_data_new(pd, property, value);
173 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EFL_MODEL_LOAD_STATUS_ERROR);
174
175 signature = _eldbus_model_proxy_property_type_get(pd, property);
176 EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EFL_MODEL_LOAD_STATUS_ERROR);
177
178 pending = eldbus_proxy_property_value_set
179 (pd->proxy, property, signature, (Eina_Value*)value, _eldbus_model_proxy_property_set_cb, data);
180 pd->pending_list = eina_list_append(pd->pending_list, pending);
181
182 return pd->load.status;
183}
184
185static Efl_Model_Load_Status
186_eldbus_model_proxy_efl_model_base_property_get(Eo *obj EINA_UNUSED,
187 Eldbus_Model_Proxy_Data *pd,
188 const char *property,
189 Eina_Value const **value)
190{
191 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
192 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EFL_MODEL_LOAD_STATUS_ERROR);
193
194 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
195 return EFL_MODEL_LOAD_STATUS_ERROR;
196
197 if (!_eldbus_model_proxy_is_property_readable(pd, property))
198 {
199 WRN("Property is write-only: %s", property);
200 return EFL_MODEL_LOAD_STATUS_ERROR;
201 }
202
203 *value = eina_hash_find(pd->properties_hash, property);
204
205 if(!*value)
206 {
207 *value = &pd->tmp_value;
208 return EFL_MODEL_LOAD_STATUS_ERROR;
209 }
210
211 return pd->load.status;
212}
213
214static void
215_eldbus_model_proxy_efl_model_base_load(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
216{
217 if (!_eldbus_model_proxy_load(pd))
218 return;
219
220 _eldbus_model_proxy_efl_model_base_properties_load(obj, pd);
221 _eldbus_model_proxy_efl_model_base_children_load(obj, pd);
222}
223
224static Efl_Model_Load_Status
225_eldbus_model_proxy_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
226{
227 return pd->load.status;
228}
229
230static void
231_eldbus_model_proxy_efl_model_base_unload(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
232{
233 _eldbus_model_proxy_unload(pd);
234
235 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_UNLOADED);
236}
237
238static Eo *
239_eldbus_model_proxy_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd EINA_UNUSED)
240{
241 return NULL;
242}
243
244static Efl_Model_Load_Status
245_eldbus_model_proxy_efl_model_base_child_del(Eo *obj EINA_UNUSED,
246 Eldbus_Model_Proxy_Data *pd EINA_UNUSED,
247 Eo *child EINA_UNUSED)
248{
249 return EFL_MODEL_LOAD_STATUS_ERROR;
250}
251
252static Efl_Model_Load_Status
253_eldbus_model_proxy_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED,
254 Eldbus_Model_Proxy_Data *pd,
255 unsigned start,
256 unsigned count,
257 Eina_Accessor **children_accessor)
258{
259 if (!(pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
260 {
261 WRN("(%p): Children not loaded", obj);
262 *children_accessor = NULL;
263 return pd->load.status;
264 }
265
266 *children_accessor = efl_model_list_slice(pd->children_list, start, count);
267 return pd->load.status;
268}
269
270static Efl_Model_Load_Status
271_eldbus_model_proxy_efl_model_base_children_count_get(Eo *obj EINA_UNUSED,
272 Eldbus_Model_Proxy_Data *pd,
273 unsigned *children_count)
274{
275 *children_count = eina_list_count(pd->children_list);
276 return pd->load.status;
277}
278
279static void
280_eldbus_model_proxy_efl_model_base_children_load(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
281{
282 unsigned int count;
283
284 if (pd->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
285 return;
286
287 if (!_eldbus_model_proxy_load(pd))
288 return;
289
290 _eldbus_model_proxy_create_methods_children(pd);
291 _eldbus_model_proxy_create_signals_children(pd);
292
293 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
294
295 count = eina_list_count(pd->children_list);
296 if (count)
297 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
298}
299
300static void
301_eldbus_model_proxy_create_methods_children(Eldbus_Model_Proxy_Data *pd)
302{
303 Eina_List *it;
304 Eldbus_Introspection_Method *method;
305
306 EINA_LIST_FOREACH(pd->interface->methods, it, method)
307 {
308 const char *bus;
309 const char *path;
310 const char *interface_name;
311 const char *method_name;
312 Eo *child;
313
314 bus = eldbus_object_bus_name_get(pd->object);
315 if (!bus) continue;
316
317 path = eldbus_object_path_get(pd->object);
318 if (!path) continue;
319
320 interface_name = pd->interface->name;
321 if (!interface_name) continue;
322
323 method_name = method->name;
324 if (!method_name) continue;
325
326 INF("(%p) Creating method child: bus = %s, path = %s, method = %s::%s", pd->obj, bus, path, interface_name, method_name);
327
328 child = eo_add(ELDBUS_MODEL_METHOD_CLASS, NULL,
329 eldbus_model_method_constructor(pd->proxy, method));
330
331 pd->children_list = eina_list_append(pd->children_list, child);
332 }
333}
334
335static void
336_eldbus_model_proxy_create_signals_children(Eldbus_Model_Proxy_Data *pd)
337{
338 Eina_List *it;
339 Eldbus_Introspection_Signal *signal;
340
341 EINA_LIST_FOREACH(pd->interface->signals, it, signal)
342 {
343 const char *bus;
344 const char *path;
345 const char *interface_name;
346 const char *signal_name;
347 Eo *child;
348
349 bus = eldbus_object_bus_name_get(pd->object);
350 if (!bus) continue;
351
352 path = eldbus_object_path_get(pd->object);
353 if (!path) continue;
354
355 interface_name = pd->interface->name;
356 if (!interface_name) continue;
357
358 signal_name = signal->name;
359 if (!signal_name) continue;
360
361 DBG("(%p) Creating signal child: bus = %s, path = %s, signal = %s::%s", pd->obj, bus, path, interface_name, signal_name);
362
363 child = eo_add(ELDBUS_MODEL_SIGNAL_CLASS, NULL,
364 eldbus_model_signal_constructor(pd->proxy, signal));
365
366 pd->children_list = eina_list_append(pd->children_list, child);
367 }
368}
369
370static const char *
371_eldbus_model_proxy_name_get(Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
372{
373 return pd->name;
374}
375
376static bool
377_eldbus_model_proxy_load(Eldbus_Model_Proxy_Data *pd)
378{
379 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, false);
380
381 if (pd->proxy)
382 return true;
383
384 pd->proxy = eldbus_proxy_get(pd->object, pd->name);
385 if (!pd->proxy)
386 {
387 ERR("Cannot get proxy for interface: %s", pd->name);
388 return false;
389 }
390
391 return true;
392}
393
394static void
395_eldbus_model_proxy_unload(Eldbus_Model_Proxy_Data *pd)
396{
397 Eldbus_Pending *pending;
398 Eo *child;
399
400 EINA_SAFETY_ON_NULL_RETURN(pd);
401
402 EINA_LIST_FREE(pd->children_list, child)
403 eo_unref(child);
404
405 EINA_LIST_FREE(pd->pending_list, pending)
406 eldbus_pending_cancel(pending);
407
408 if (pd->properties_array)
409 {
410 unsigned int i;
411 Eina_Stringshare *property;
412 Eina_Array_Iterator it;
413
414 EINA_ARRAY_ITER_NEXT(pd->properties_array, i, property, it)
415 eina_stringshare_del(property);
416 eina_array_free(pd->properties_array);
417 pd->properties_array = NULL;
418 }
419
420 eina_hash_free_buckets(pd->properties_hash);
421
422 _eldbus_model_proxy_stop_monitor(pd);
423
424 if (pd->proxy)
425 {
426 eldbus_proxy_unref(pd->proxy);
427 pd->proxy = NULL;
428 }
429}
430
431static void
432_eldbus_model_proxy_start_monitor(Eldbus_Model_Proxy_Data *pd)
433{
434 if (pd->monitoring)
435 return;
436
437 pd->monitoring = true;
438
439 eldbus_proxy_event_callback_add(pd->proxy,
440 ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
441 _eldbus_model_proxy_property_changed_cb,
442 pd);
443
444 eldbus_proxy_event_callback_add(pd->proxy,
445 ELDBUS_PROXY_EVENT_PROPERTY_REMOVED,
446 _eldbus_model_proxy_property_invalidated_cb,
447 pd);
448}
449
450static void
451_eldbus_model_proxy_stop_monitor(Eldbus_Model_Proxy_Data *pd)
452{
453 if (!pd->monitoring)
454 return;
455
456 pd->monitoring = false;
457
458 eldbus_proxy_event_callback_del(pd->proxy,
459 ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
460 _eldbus_model_proxy_property_changed_cb,
461 pd);
462
463 eldbus_proxy_event_callback_del(pd->proxy,
464 ELDBUS_PROXY_EVENT_PROPERTY_REMOVED,
465 _eldbus_model_proxy_property_invalidated_cb,
466 pd);
467}
468
469static void
470_eldbus_model_proxy_property_changed_cb(void *data,
471 Eldbus_Proxy *proxy EINA_UNUSED,
472 void *event_info)
473{
474 Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
475 Eldbus_Object_Event_Property_Changed *event = (Eldbus_Object_Event_Property_Changed*)event_info;
476 Eina_Value *prop_value;
477 Eina_Bool ret;
478
479 prop_value = eina_hash_find(pd->properties_hash, event->name);
480 if (!prop_value) return ;
481
482 ret = eina_value_copy(event->value, prop_value);
483 if (!ret) return ;
484
485 efl_model_property_changed_notify(pd->obj, event->name);
486}
487
488static void
489_eldbus_model_proxy_property_invalidated_cb(void *data,
490 Eldbus_Proxy *proxy EINA_UNUSED,
491 void *event_info)
492{
493 Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
494 Eldbus_Proxy_Event_Property_Changed *event = (Eldbus_Proxy_Event_Property_Changed*)event_info;
495
496#if 0
497 Efl_Model_Property_Event evt = {0};
498
499 // TODO: eldbus_proxy_property_get(event->name) ?
500
501 evt.invalidated_properties = eina_array_new(1);
502 EINA_SAFETY_ON_NULL_RETURN(evt.invalidated_properties);
503
504 eina_array_push(evt.invalidated_properties, event->name);
505 eina_array_free(evt.invalidated_properties);
506#endif
507
508 efl_model_property_invalidated_notify(pd->obj, event->name);
509}
510
511static void
512_eldbus_model_proxy_property_get_all_cb(void *data,
513 const Eldbus_Message *msg,
514 Eldbus_Pending *pending)
515{
516 Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
517 Eldbus_Introspection_Property *prop;
518 Eina_Array *changed_properties;
519 Eldbus_Message_Iter *values = NULL;
520 Eldbus_Message_Iter *entry;
521 Eina_List *it;
522 const char *error_name, *error_text;
523
524 pd->pending_list = eina_list_remove(pd->pending_list, pending);
525
526 if (eldbus_message_error_get(msg, &error_name, &error_text))
527 {
528 ERR("%s: %s", error_name, error_text);
529 efl_model_error_notify(pd->obj);
530 return;
531 }
532
533 if (!eldbus_message_arguments_get(msg, "a{sv}", &values))
534 {
535 ERR("%s", "Error getting arguments.");
536 return;
537 }
538
539 EINA_LIST_FOREACH(pd->interface->properties, it, prop)
540 {
541 const Eina_Value_Type *type;
542 Eina_Value *value;
543
544 type = _dbus_type_to_eina_value_type(prop->type[0]);
545 value = eina_value_new(type);
546
547 eina_hash_add(pd->properties_hash, prop->name, value);
548 }
549
550 changed_properties = eina_array_new(1);
551 while (eldbus_message_iter_get_and_next(values, 'e', &entry))
552 {
553 const char *property;
554 Eldbus_Message_Iter *variant;
555 Eina_Value *struct_value;
556 Eina_Value *prop_value;
557 Eina_Value arg0;
558 Eina_Bool ret;
559
560 if (!eldbus_message_iter_arguments_get(entry, "sv", &property, &variant))
561 continue;
562
563 struct_value = eldbus_message_iter_struct_like_to_eina_value(variant);
564 EINA_SAFETY_ON_NULL_GOTO(struct_value, on_error);
565
566 ret = eina_value_struct_value_get(struct_value, "arg0", &arg0);
567 eina_value_free(struct_value);
568 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
569
570 prop_value = eina_hash_find(pd->properties_hash, property);
571 EINA_SAFETY_ON_NULL_GOTO(prop_value, on_error);
572
573 ret = eina_value_copy(&arg0, prop_value);
574 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
575
576 eina_value_flush(&arg0);
577
578 ret = eina_array_push(changed_properties, property);
579 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
580 }
581
582 _eldbus_model_proxy_start_monitor(pd);
583
584 if (eina_array_count(changed_properties))
585 {
586 Efl_Model_Property_Event evt = {
587 .changed_properties = changed_properties
588 };
589
590 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
591 }
592
593 efl_model_load_set(pd->obj, &pd->load, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
594
595 on_error:
596 eina_array_free(changed_properties);
597}
598
599
600static void
601_eldbus_model_proxy_property_set_cb(void *data,
602 const Eldbus_Message *msg,
603 Eldbus_Pending *pending)
604{
605 Eldbus_Model_Proxy_Property_Set_Data *property_set_data = (Eldbus_Model_Proxy_Property_Set_Data *)data;
606 Eldbus_Model_Proxy_Data *pd = property_set_data->pd;
607 const char *error_name, *error_text;
608 Eina_Value *prop_value;
609 Eina_Bool ret;
610
611 pd->pending_list = eina_list_remove(pd->pending_list, pending);
612
613 if (eldbus_message_error_get(msg, &error_name, &error_text))
614 {
615 ERR("%s: %s", error_name, error_text);
616 efl_model_error_notify(pd->obj);
617 goto on_error;
618 }
619
620 prop_value = eina_hash_find(pd->properties_hash,
621 property_set_data->property);
622 EINA_SAFETY_ON_NULL_GOTO(prop_value, on_error);
623
624 ret = eina_value_copy(&property_set_data->value, prop_value);
625 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
626
627 {
628 Efl_Model_Property_Event evt = {
629 .changed_properties = pd->properties_array
630 };
631 eo_do(pd->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
632
633 efl_model_property_changed_notify(pd->obj, property_set_data->property);
634 }
635
636 on_error:
637 _eldbus_model_proxy_property_set_data_free(property_set_data);
638}
639
640static bool
641_eldbus_model_proxy_is_property_writeable(Eldbus_Model_Proxy_Data *pd, const char *property)
642{
643 Eldbus_Introspection_Property *property_introspection =
644 eldbus_introspection_property_find(pd->interface->properties, property);
645
646 if (property_introspection == NULL)
647 {
648 WRN("Property not found: %s", property);
649 return false;
650 }
651
652 return ELDBUS_INTROSPECTION_PROPERTY_ACCESS_WRITE == property_introspection->access
653 || ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE == property_introspection->access;
654}
655
656static bool
657_eldbus_model_proxy_is_property_readable(Eldbus_Model_Proxy_Data *pd, const char *property)
658{
659 Eldbus_Introspection_Property *property_introspection =
660 eldbus_introspection_property_find(pd->interface->properties, property);
661
662 if (property_introspection == NULL)
663 {
664 WRN("Property not found: %s", property);
665 return false;
666 }
667
668 return ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READ == property_introspection->access
669 || ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE == property_introspection->access;
670}
671
672static const char *
673_eldbus_model_proxy_property_type_get(Eldbus_Model_Proxy_Data *pd, const char *property)
674{
675 Eldbus_Introspection_Property *property_introspection =
676 eldbus_introspection_property_find(pd->interface->properties, property);
677
678 if (property_introspection == NULL)
679 {
680 WRN("Property not found: %s", property);
681 return NULL;
682 }
683
684 return property_introspection->type;
685
686}
687
688static Eldbus_Model_Proxy_Property_Set_Data *
689_eldbus_model_proxy_property_set_data_new(Eldbus_Model_Proxy_Data *pd,
690 const char *property,
691 const Eina_Value *value)
692{
693 Eldbus_Model_Proxy_Property_Set_Data *data = calloc(1, sizeof(Eldbus_Model_Proxy_Property_Set_Data));
694 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
695
696 data->pd = pd;
697 data->property = eina_stringshare_add(property);
698 if (!eina_value_copy(value, &data->value))
699 goto error;
700
701 return data;
702
703 error:
704 eina_stringshare_del(data->property);
705 free(data);
706 return NULL;
707}
708
709static void
710_eldbus_model_proxy_property_set_data_free(Eldbus_Model_Proxy_Property_Set_Data *data)
711{
712 EINA_SAFETY_ON_NULL_RETURN(data);
713 eina_stringshare_del(data->property);
714 eina_value_flush(&data->value);
715 free(data);
716}
717
718#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 0000000..2bab119
--- /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 0000000..02153fc
--- /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 0000000..4ef32bb
--- /dev/null
+++ b/src/lib/eldbus/eldbus_model_signal.c
@@ -0,0 +1,106 @@
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 eo_do_super(obj, MY_CLASS, eo_constructor());
22
23 pd->obj = obj;
24 pd->handler = NULL;