summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Lima (Etrunko) <eduardo.lima@intel.com>2013-10-11 16:57:14 -0300
committerEduardo Lima (Etrunko) <eduardo.lima@intel.com>2013-10-11 16:57:14 -0300
commit026514f3613091344e20d0bd53bcf81c8e634060 (patch)
tree572e278d099cc9c017317b0643bb826ca0f5da46
parentbe1e479c31cb4f94911d5b61693dd65f73a0cb43 (diff)
parentc3003e0b016334cb4251564499037459811928d7 (diff)
Merge branch 'backports'
-rw-r--r--src/lib/Eldbus.h1
-rw-r--r--src/lib/eldbus_core.c12
-rw-r--r--src/lib/eldbus_freedesktop.c14
-rw-r--r--src/lib/eldbus_freedesktop.h13
-rw-r--r--src/lib/eldbus_object.c2
-rw-r--r--src/lib/eldbus_pending.c8
-rw-r--r--src/lib/eldbus_proxy.c46
-rw-r--r--src/lib/eldbus_proxy.h6
-rw-r--r--src/lib/eldbus_service.c307
9 files changed, 261 insertions, 148 deletions
diff --git a/src/lib/Eldbus.h b/src/lib/Eldbus.h
index e49061d..cc069a0 100644
--- a/src/lib/Eldbus.h
+++ b/src/lib/Eldbus.h
@@ -126,6 +126,7 @@ extern "C" {
126#define ELDBUS_FDO_INTERFACE_INTROSPECTABLE "org.freedesktop.DBus.Introspectable" 126#define ELDBUS_FDO_INTERFACE_INTROSPECTABLE "org.freedesktop.DBus.Introspectable"
127#define ELDBUS_FDO_INTEFACE_PEER "org.freedesktop.DBus.Peer" 127#define ELDBUS_FDO_INTEFACE_PEER "org.freedesktop.DBus.Peer"
128#define ELDBUS_ERROR_PENDING_CANCELED "org.enlightenment.DBus.Canceled" 128#define ELDBUS_ERROR_PENDING_CANCELED "org.enlightenment.DBus.Canceled"
129#define ELDBUS_ERROR_PENDING_TIMEOUT "org.freedesktop.DBus.Error.NoReply"
129 130
130typedef struct _Eldbus_Version 131typedef struct _Eldbus_Version
131{ 132{
diff --git a/src/lib/eldbus_core.c b/src/lib/eldbus_core.c
index bd73659..a81a60a 100644
--- a/src/lib/eldbus_core.c
+++ b/src/lib/eldbus_core.c
@@ -876,6 +876,8 @@ cb_signal_dispatcher(Eldbus_Connection *conn, DBusMessage *msg)
876 if (!dbus_message_has_sender(msg, sh->sender)) continue; 876 if (!dbus_message_has_sender(msg, sh->sender)) continue;
877 } 877 }
878 if (sh->path && !dbus_message_has_path(msg, sh->path)) continue; 878 if (sh->path && !dbus_message_has_path(msg, sh->path)) continue;
879 if (sh->interface && !dbus_message_has_interface(msg, sh->interface))
880 continue;
879 if (sh->member && !dbus_message_has_member(msg, sh->member)) continue; 881 if (sh->member && !dbus_message_has_member(msg, sh->member)) continue;
880 if (!extra_arguments_check(msg, sh)) continue; 882 if (!extra_arguments_check(msg, sh)) continue;
881 883
@@ -997,7 +999,8 @@ _connection_get(Eldbus_Connection_Type type, const char *address)
997 if (!conn->dbus_conn || dbus_error_is_set(&err)) 999 if (!conn->dbus_conn || dbus_error_is_set(&err))
998 { 1000 {
999 free(conn); 1001 free(conn);
1000 ERR("Error connecting to bus: %s", err.message); 1002 ERR("Error connecting to bus of type %d. error name: %s error message: %s",
1003 type, err.name, err.message);
1001 return NULL; 1004 return NULL;
1002 } 1005 }
1003 1006
@@ -1134,6 +1137,13 @@ _eldbus_connection_free(Eldbus_Connection *conn)
1134 conn->refcount = 1; 1137 conn->refcount = 1;
1135 eldbus_cbs_free_dispatch(&(conn->cbs_free), conn); 1138 eldbus_cbs_free_dispatch(&(conn->cbs_free), conn);
1136 1139
1140 /**
1141 * Flush all messages in outgoing queue, also this will send all
1142 * ObjectManager and Property changed signals of all paths that
1143 * this connection is server.
1144 */
1145 dbus_connection_flush(conn->dbus_conn);
1146
1137 EINA_INLIST_FOREACH_SAFE(conn->pendings, list, p) 1147 EINA_INLIST_FOREACH_SAFE(conn->pendings, list, p)
1138 eldbus_pending_cancel(p); 1148 eldbus_pending_cancel(p);
1139 1149
diff --git a/src/lib/eldbus_freedesktop.c b/src/lib/eldbus_freedesktop.c
index 2862753..f0a79bd 100644
--- a/src/lib/eldbus_freedesktop.c
+++ b/src/lib/eldbus_freedesktop.c
@@ -81,6 +81,20 @@ eldbus_object_managed_objects_get(Eldbus_Object *obj, Eldbus_Message_Cb cb, cons
81 return p; 81 return p;
82} 82}
83 83
84EAPI Eldbus_Signal_Handler *
85eldbus_object_manager_interfaces_added(Eldbus_Object *obj, Eldbus_Signal_Cb cb, const void *cb_data)
86{
87 return eldbus_object_signal_handler_add(obj, ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
88 "InterfacesAdded", cb, cb_data);
89}
90
91EAPI Eldbus_Signal_Handler *
92eldbus_object_manager_interfaces_removed(Eldbus_Object *obj, Eldbus_Signal_Cb cb, const void *cb_data)
93{
94 return eldbus_object_signal_handler_add(obj, ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
95 "InterfacesRemoved", cb, cb_data);
96}
97
84EAPI Eldbus_Pending * 98EAPI Eldbus_Pending *
85eldbus_hello(Eldbus_Connection *conn, Eldbus_Message_Cb cb, const void *cb_data) 99eldbus_hello(Eldbus_Connection *conn, Eldbus_Message_Cb cb, const void *cb_data)
86{ 100{
diff --git a/src/lib/eldbus_freedesktop.h b/src/lib/eldbus_freedesktop.h
index 46406e6..8a66b06 100644
--- a/src/lib/eldbus_freedesktop.h
+++ b/src/lib/eldbus_freedesktop.h
@@ -98,9 +98,14 @@ EAPI Eldbus_Pending *eldbus_object_introspect(Eldbus_Object *obj, Eldbus_
98 * After enable you can call eldbus_proxy_property_local_get() or 98 * After enable you can call eldbus_proxy_property_local_get() or
99 * eldbus_proxy_property_local_get_all() to get cached properties. 99 * eldbus_proxy_property_local_get_all() to get cached properties.
100 * 100 *
101 * @note After enable, it will asynchrony get the properties values. 101 * @param proxy bus+path+interface that the properties belong
102 * @param enable enable or disable properties monitor
103 * @return EINA_TRUE if already have cached properties
104 * EINA_FALSE if it will asynchrony get the properties.
105 * You should listen for a ELDBUS_PROXY_EVENT_PROPERTY_LOADED
106 * to know when properties finish to load.
102 */ 107 */
103EAPI void eldbus_proxy_properties_monitor(Eldbus_Proxy *proxy, Eina_Bool enable) EINA_ARG_NONNULL(1); 108EAPI Eina_Bool eldbus_proxy_properties_monitor(Eldbus_Proxy *proxy, Eina_Bool enable) EINA_ARG_NONNULL(1);
104 109
105EAPI Eldbus_Pending *eldbus_proxy_property_get(Eldbus_Proxy *proxy, const char *name, Eldbus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2, 3); 110EAPI Eldbus_Pending *eldbus_proxy_property_get(Eldbus_Proxy *proxy, const char *name, Eldbus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2, 3);
106EAPI 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); 111EAPI 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);
@@ -134,6 +139,10 @@ EAPI const Eina_Hash *eldbus_proxy_property_local_get_all(Eldbus_Proxy *pro
134 139
135EAPI Eldbus_Pending *eldbus_object_managed_objects_get(Eldbus_Object *obj, Eldbus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2); 140EAPI Eldbus_Pending *eldbus_object_managed_objects_get(Eldbus_Object *obj, Eldbus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
136 141
142EAPI Eldbus_Signal_Handler *eldbus_object_manager_interfaces_added(Eldbus_Object *obj, Eldbus_Signal_Cb cb, const void *cb_data) EINA_ARG_NONNULL(1);
143
144EAPI Eldbus_Signal_Handler *eldbus_object_manager_interfaces_removed(Eldbus_Object *obj, Eldbus_Signal_Cb cb, const void *cb_data) EINA_ARG_NONNULL(1);
145
137/** 146/**
138 * @} 147 * @}
139 */ 148 */
diff --git a/src/lib/eldbus_object.c b/src/lib/eldbus_object.c
index 9b75175..faef28f 100644
--- a/src/lib/eldbus_object.c
+++ b/src/lib/eldbus_object.c
@@ -421,7 +421,7 @@ eldbus_object_event_callback_add(Eldbus_Object *obj, Eldbus_Object_Event_Type ty
421 ELDBUS_FDO_INTERFACE_OBJECT_MANAGER, 421 ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
422 "InterfacesRemoved", 422 "InterfacesRemoved",
423 _cb_interfaces_removed, obj); 423 _cb_interfaces_removed, obj);
424 EINA_SAFETY_ON_NULL_RETURN(obj->interfaces_added); 424 EINA_SAFETY_ON_NULL_RETURN(obj->interfaces_removed);
425 eldbus_signal_handler_match_extra_set(obj->interfaces_removed, 425 eldbus_signal_handler_match_extra_set(obj->interfaces_removed,
426 "arg0", obj->path, NULL); 426 "arg0", obj->path, NULL);
427 break; 427 break;
diff --git a/src/lib/eldbus_pending.c b/src/lib/eldbus_pending.c
index 4174ac1..bf561bb 100644
--- a/src/lib/eldbus_pending.c
+++ b/src/lib/eldbus_pending.c
@@ -51,8 +51,8 @@ cb_pending(DBusPendingCall *dbus_pending, void *user_data)
51 INF("timeout to pending %p", pending); 51 INF("timeout to pending %p", pending);
52 dbus_pending_call_cancel(dbus_pending); 52 dbus_pending_call_cancel(dbus_pending);
53 msg = eldbus_message_error_new(pending->msg_sent, 53 msg = eldbus_message_error_new(pending->msg_sent,
54 "org.enlightenment.DBus.Timeout", 54 ELDBUS_ERROR_PENDING_TIMEOUT,
55 "This call was not completed."); 55 "This call was not completed in time.");
56 eldbus_pending_dispatch(pending, msg); 56 eldbus_pending_dispatch(pending, msg);
57 return; 57 return;
58 } 58 }
@@ -218,8 +218,8 @@ eldbus_pending_cancel(Eldbus_Pending *pending)
218 dbus_pending_call_cancel(pending->dbus_pending); 218 dbus_pending_call_cancel(pending->dbus_pending);
219 219
220 error_message = eldbus_message_error_new(pending->msg_sent, 220 error_message = eldbus_message_error_new(pending->msg_sent,
221 ELDBUS_ERROR_PENDING_CANCELED, 221 ELDBUS_ERROR_PENDING_CANCELED,
222 "Canceled by user."); 222 "Canceled by user.");
223 eldbus_pending_dispatch(pending, error_message); 223 eldbus_pending_dispatch(pending, error_message);
224} 224}
225 225
diff --git a/src/lib/eldbus_proxy.c b/src/lib/eldbus_proxy.c
index c0fceef..9f02751 100644
--- a/src/lib/eldbus_proxy.c
+++ b/src/lib/eldbus_proxy.c
@@ -333,7 +333,7 @@ _property_changed_iter(void *data, const void *key, Eldbus_Message_Iter *var)
333 event.value = value; 333 event.value = value;
334 event.proxy = proxy; 334 event.proxy = proxy;
335 _eldbus_proxy_event_callback_call(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED, 335 _eldbus_proxy_event_callback_call(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
336 &event); 336 &event);
337 eina_value_free(st_value); 337 eina_value_free(st_value);
338 eina_value_flush(&stack_value); 338 eina_value_flush(&stack_value);
339} 339}
@@ -689,7 +689,7 @@ eldbus_proxy_property_get_all(Eldbus_Proxy *proxy, Eldbus_Message_Cb cb, const v
689{ 689{
690 ELDBUS_PROXY_CHECK_RETVAL(proxy, NULL); 690 ELDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
691 return eldbus_proxy_call(proxy->obj->properties, "GetAll", cb, data, -1, 691 return eldbus_proxy_call(proxy->obj->properties, "GetAll", cb, data, -1,
692 "s", proxy->interface); 692 "s", proxy->interface);
693} 693}
694 694
695EAPI Eldbus_Signal_Handler * 695EAPI Eldbus_Signal_Handler *
@@ -698,7 +698,7 @@ eldbus_proxy_properties_changed_callback_add(Eldbus_Proxy *proxy, Eldbus_Signal_
698 Eldbus_Signal_Handler *sh; 698 Eldbus_Signal_Handler *sh;
699 ELDBUS_PROXY_CHECK_RETVAL(proxy, NULL); 699 ELDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
700 sh = eldbus_proxy_signal_handler_add(proxy->obj->properties, 700 sh = eldbus_proxy_signal_handler_add(proxy->obj->properties,
701 "PropertiesChanged", cb, data); 701 "PropertiesChanged", cb, data);
702 EINA_SAFETY_ON_NULL_RETURN_VAL(sh, NULL); 702 EINA_SAFETY_ON_NULL_RETURN_VAL(sh, NULL);
703 eldbus_signal_handler_match_extra_set(sh, "arg0", proxy->interface, NULL); 703 eldbus_signal_handler_match_extra_set(sh, "arg0", proxy->interface, NULL);
704 return sh; 704 return sh;
@@ -733,6 +733,7 @@ _props_get_all(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EI
733 Eldbus_Proxy *proxy = data; 733 Eldbus_Proxy *proxy = data;
734 Eldbus_Message_Iter *dict; 734 Eldbus_Message_Iter *dict;
735 const char *name, *error_msg; 735 const char *name, *error_msg;
736 Eldbus_Proxy_Event_Property_Loaded event;
736 737
737 if (eldbus_message_error_get(msg, &name, &error_msg)) 738 if (eldbus_message_error_get(msg, &name, &error_msg))
738 { 739 {
@@ -750,30 +751,21 @@ _props_get_all(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EI
750 return; 751 return;
751 } 752 }
752 eldbus_message_iter_dict_iterate(dict, "sv", _property_iter, proxy); 753 eldbus_message_iter_dict_iterate(dict, "sv", _property_iter, proxy);
754
755 event.proxy = proxy;
756 _eldbus_proxy_event_callback_call(proxy, ELDBUS_PROXY_EVENT_PROPERTY_LOADED,
757 &event);
753} 758}
754 759
755EAPI void 760EAPI Eina_Bool
756eldbus_proxy_properties_monitor(Eldbus_Proxy *proxy, Eina_Bool enable) 761eldbus_proxy_properties_monitor(Eldbus_Proxy *proxy, Eina_Bool enable)
757{ 762{
758 ELDBUS_PROXY_CHECK(proxy); 763 ELDBUS_PROXY_CHECK_RETVAL(proxy, EINA_FALSE);
759 if (proxy->monitor_enabled == enable) 764 if (proxy->monitor_enabled == enable)
760 return; 765 return proxy->props ? !!eina_hash_population(proxy->props) : EINA_FALSE;
761 766
762 proxy->monitor_enabled = enable; 767 proxy->monitor_enabled = enable;
763 if (enable) 768 if (!enable)
764 {
765 if (!proxy->props)
766 proxy->props = eina_hash_string_superfast_new(_props_cache_free);
767 eldbus_proxy_property_get_all(proxy, _props_get_all, proxy);
768
769 if (proxy->properties_changed)
770 return;
771 proxy->properties_changed =
772 eldbus_proxy_properties_changed_callback_add(proxy,
773 _properties_changed,
774 proxy);
775 }
776 else
777 { 769 {
778 Eldbus_Proxy_Context_Event *ce_prop_changed, *ce_prop_removed; 770 Eldbus_Proxy_Context_Event *ce_prop_changed, *ce_prop_removed;
779 ce_prop_changed = proxy->event_handlers + ELDBUS_PROXY_EVENT_PROPERTY_CHANGED; 771 ce_prop_changed = proxy->event_handlers + ELDBUS_PROXY_EVENT_PROPERTY_CHANGED;
@@ -789,7 +781,21 @@ eldbus_proxy_properties_monitor(Eldbus_Proxy *proxy, Eina_Bool enable)
789 eldbus_signal_handler_unref(proxy->properties_changed); 781 eldbus_signal_handler_unref(proxy->properties_changed);
790 proxy->properties_changed = NULL; 782 proxy->properties_changed = NULL;
791 } 783 }
784 return EINA_TRUE;
792 } 785 }
786
787 if (!proxy->props)
788 proxy->props = eina_hash_string_superfast_new(_props_cache_free);
789
790 eldbus_proxy_property_get_all(proxy, _props_get_all, proxy);
791
792 if (proxy->properties_changed)
793 return !!eina_hash_population(proxy->props);
794 proxy->properties_changed =
795 eldbus_proxy_properties_changed_callback_add(proxy,
796 _properties_changed,
797 proxy);
798 return !!eina_hash_population(proxy->props);
793} 799}
794 800
795EAPI Eina_Value * 801EAPI Eina_Value *
diff --git a/src/lib/eldbus_proxy.h b/src/lib/eldbus_proxy.h
index 9249948..5752001 100644
--- a/src/lib/eldbus_proxy.h
+++ b/src/lib/eldbus_proxy.h
@@ -111,6 +111,7 @@ typedef enum
111 ELDBUS_PROXY_EVENT_PROPERTY_CHANGED = 0, 111 ELDBUS_PROXY_EVENT_PROPERTY_CHANGED = 0,
112 ELDBUS_PROXY_EVENT_PROPERTY_REMOVED, 112 ELDBUS_PROXY_EVENT_PROPERTY_REMOVED,
113 ELDBUS_PROXY_EVENT_DEL, 113 ELDBUS_PROXY_EVENT_DEL,
114 ELDBUS_PROXY_EVENT_PROPERTY_LOADED,
114 ELDBUS_PROXY_EVENT_LAST /**< sentinel, not a real event type */ 115 ELDBUS_PROXY_EVENT_LAST /**< sentinel, not a real event type */
115} Eldbus_Proxy_Event_Type; 116} Eldbus_Proxy_Event_Type;
116 117
@@ -121,6 +122,11 @@ typedef struct _Eldbus_Proxy_Event_Property_Changed
121 const Eina_Value *value; 122 const Eina_Value *value;
122} Eldbus_Proxy_Event_Property_Changed; 123} Eldbus_Proxy_Event_Property_Changed;
123 124
125typedef struct _Eldbus_Proxy_Event_Property_Loaded
126{
127 const Eldbus_Proxy *proxy;
128} Eldbus_Proxy_Event_Property_Loaded;
129
124typedef struct _Eldbus_Proxy_Event_Property_Removed 130typedef struct _Eldbus_Proxy_Event_Property_Removed
125{ 131{
126 const char *interface; 132 const char *interface;
diff --git a/src/lib/eldbus_service.c b/src/lib/eldbus_service.c
index 8f5ec2a..4c793c8 100644
--- a/src/lib/eldbus_service.c
+++ b/src/lib/eldbus_service.c
@@ -676,6 +676,7 @@ _eldbus_service_object_add(Eldbus_Connection *conn, const char *path)
676 { 676 {
677 obj->parent->children = eina_inlist_append(obj->parent->children, 677 obj->parent->children = eina_inlist_append(obj->parent->children,
678 EINA_INLIST_GET(obj)); 678 EINA_INLIST_GET(obj));
679 obj->parent->introspection_dirty = EINA_TRUE;
679 return obj; 680 return obj;
680 } 681 }
681 682
@@ -714,7 +715,6 @@ static void
714_object_manager_iface_added_emit(Eldbus_Service_Object *obj, 715_object_manager_iface_added_emit(Eldbus_Service_Object *obj,
715 Eldbus_Service_Object *parent) 716 Eldbus_Service_Object *parent)
716{ 717{
717 Eina_List *l;
718 Eldbus_Service_Interface *iface; 718 Eldbus_Service_Interface *iface;
719 Eldbus_Message_Iter *iter, *array; 719 Eldbus_Message_Iter *iter, *array;
720 Eldbus_Message *sig = eldbus_message_signal_new(parent->path, 720 Eldbus_Message *sig = eldbus_message_signal_new(parent->path,
@@ -725,7 +725,7 @@ _object_manager_iface_added_emit(Eldbus_Service_Object *obj,
725 eldbus_message_iter_arguments_append(iter, "oa{sa{sv}}", obj->path, 725 eldbus_message_iter_arguments_append(iter, "oa{sa{sv}}", obj->path,
726 &array); 726 &array);
727 727
728 EINA_LIST_FOREACH(obj->iface_added, l, iface) 728 EINA_LIST_FREE(obj->iface_added, iface)
729 { 729 {
730 if (!_propmgr_iface_props_append(iface, array)) 730 if (!_propmgr_iface_props_append(iface, array))
731 { 731 {
@@ -736,6 +736,7 @@ _object_manager_iface_added_emit(Eldbus_Service_Object *obj,
736 } 736 }
737 eldbus_message_iter_container_close(iter, array); 737 eldbus_message_iter_container_close(iter, array);
738 eldbus_connection_send(parent->conn, sig, NULL, NULL, -1); 738 eldbus_connection_send(parent->conn, sig, NULL, NULL, -1);
739 return;
739 740
740done: 741done:
741 obj->iface_added = eina_list_free(obj->iface_added); 742 obj->iface_added = eina_list_free(obj->iface_added);
@@ -749,8 +750,8 @@ _object_manager_iface_removed_emit(Eldbus_Service_Object *obj,
749 const char *name; 750 const char *name;
750 Eldbus_Message_Iter *iter, *array; 751 Eldbus_Message_Iter *iter, *array;
751 Eldbus_Message *sig = eldbus_message_signal_new(parent->path, 752 Eldbus_Message *sig = eldbus_message_signal_new(parent->path,
752 ELDBUS_FDO_INTERFACE_OBJECT_MANAGER, 753 ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
753 "InterfacesRemoved"); 754 "InterfacesRemoved");
754 EINA_SAFETY_ON_NULL_RETURN(sig); 755 EINA_SAFETY_ON_NULL_RETURN(sig);
755 756
756 iter = eldbus_message_iter_get(sig); 757 iter = eldbus_message_iter_get(sig);
@@ -758,7 +759,7 @@ _object_manager_iface_removed_emit(Eldbus_Service_Object *obj,
758 759
759 EINA_LIST_FOREACH(obj->iface_removed, l, name) 760 EINA_LIST_FOREACH(obj->iface_removed, l, name)
760 { 761 {
761 eldbus_message_iter_arguments_append(array, name); 762 eldbus_message_iter_arguments_append(array, "s", name);
762 eina_stringshare_del(name); 763 eina_stringshare_del(name);
763 } 764 }
764 eldbus_message_iter_container_close(iter, array); 765 eldbus_message_iter_container_close(iter, array);
@@ -785,7 +786,15 @@ _object_manager_changes_process(void *data)
785 obj->idler_iface_changed = NULL; 786 obj->idler_iface_changed = NULL;
786 787
787 if (!parent) 788 if (!parent)
788 return EINA_FALSE; 789 {
790 const char *name;
791
792 obj->iface_added = eina_list_free(obj->iface_added);
793 EINA_LIST_FREE(obj->iface_removed, name)
794 eina_stringshare_del(name);
795
796 return EINA_FALSE;
797 }
789 798
790 if (obj->iface_added) 799 if (obj->iface_added)
791 _object_manager_iface_added_emit(obj, parent); 800 _object_manager_iface_added_emit(obj, parent);
@@ -973,6 +982,101 @@ fail:
973 return NULL; 982 return NULL;
974} 983}
975 984
985static Eina_Bool
986_idler_propschanged(void *data)
987{
988 Eldbus_Service_Interface *iface = data;
989 Eldbus_Message *msg;
990 Eldbus_Message_Iter *main_iter, *dict, *array_invalidate;
991 Eina_Hash *added = NULL;
992 Property *prop;
993
994 iface->idler_propschanged = NULL;
995
996 added = eina_hash_string_small_new(NULL);
997 msg = eldbus_message_signal_new(iface->obj->path, properties_iface->name,
998 properties_iface->signals[0].name);
999 EINA_SAFETY_ON_NULL_GOTO(msg, error);
1000
1001 main_iter = eldbus_message_iter_get(msg);
1002 if (!eldbus_message_iter_arguments_append(main_iter, "sa{sv}", iface->name, &dict))
1003 {
1004 eldbus_message_unref(msg);
1005 goto error;
1006 }
1007
1008 if (!iface->props_changed)
1009 goto invalidate;
1010 while ((prop = eina_array_pop(iface->props_changed)))
1011 {
1012 Eldbus_Message_Iter *entry, *var;
1013 Eldbus_Message *error_reply = NULL;
1014 Eina_Bool ret;
1015 Eldbus_Property_Get_Cb getter = NULL;
1016
1017 if (eina_hash_find(added, prop->property->name))
1018 continue;
1019 eina_hash_add(added, prop->property->name, prop);
1020
1021 if (prop->property->get_func)
1022 getter = prop->property->get_func;
1023 else if (iface->get_func)
1024 getter = iface->get_func;
1025
1026 if (!getter || prop->is_invalidate)
1027 continue;
1028
1029 EINA_SAFETY_ON_FALSE_GOTO(
1030 eldbus_message_iter_arguments_append(dict, "{sv}", &entry), error);
1031
1032 eldbus_message_iter_basic_append(entry, 's', prop->property->name);
1033 var = eldbus_message_iter_container_new(entry, 'v',
1034 prop->property->type);
1035
1036 ret = getter(iface, prop->property->name, var, NULL, &error_reply);
1037 if (!ret)
1038 {
1039 eldbus_message_unref(msg);
1040 if (error_reply)
1041 {
1042 ERR("Error reply was set without pass any input message.");
1043 eldbus_message_unref(error_reply);
1044 }
1045 ERR("Getter of property %s returned error.", prop->property->name);
1046 goto error;
1047 }
1048
1049 eldbus_message_iter_container_close(entry, var);
1050 eldbus_message_iter_container_close(dict, entry);
1051 }
1052invalidate:
1053 eldbus_message_iter_container_close(main_iter, dict);
1054
1055 eldbus_message_iter_arguments_append(main_iter, "as", &array_invalidate);
1056
1057 if (!iface->prop_invalidated)
1058 goto end;
1059 while ((prop = eina_array_pop(iface->prop_invalidated)))
1060 {
1061 if (!prop->is_invalidate)
1062 continue;
1063 eldbus_message_iter_basic_append(array_invalidate, 's',
1064 prop->property->name);
1065 }
1066end:
1067 eldbus_message_iter_container_close(main_iter, array_invalidate);
1068
1069 eldbus_service_signal_send(iface, msg);
1070error:
1071 if (added)
1072 eina_hash_free(added);
1073 if (iface->props_changed)
1074 eina_array_flush(iface->props_changed);
1075 if (iface->prop_invalidated)
1076 eina_array_flush(iface->prop_invalidated);
1077 return ECORE_CALLBACK_CANCEL;
1078}
1079
976static void 1080static void
977_interface_free(Eldbus_Service_Interface *interface) 1081_interface_free(Eldbus_Service_Interface *interface)
978{ 1082{
@@ -984,6 +1088,15 @@ _interface_free(Eldbus_Service_Interface *interface)
984 interface == objmanager) 1088 interface == objmanager)
985 return; 1089 return;
986 1090
1091 /**
1092 * flush props changes before remove interface
1093 */
1094 if (interface->idler_propschanged)
1095 {
1096 ecore_idler_del(interface->idler_propschanged);
1097 _idler_propschanged(interface);
1098 }
1099
987 eina_hash_free(interface->methods); 1100 eina_hash_free(interface->methods);
988 while ((sig = eina_array_pop(interface->sign_of_signals))) 1101 while ((sig = eina_array_pop(interface->sign_of_signals)))
989 eina_stringshare_del(sig); 1102 eina_stringshare_del(sig);
@@ -991,8 +1104,6 @@ _interface_free(Eldbus_Service_Interface *interface)
991 eina_hash_free(interface->properties); 1104 eina_hash_free(interface->properties);
992 if (interface->props_changed) 1105 if (interface->props_changed)
993 eina_array_free(interface->props_changed); 1106 eina_array_free(interface->props_changed);
994 if (interface->idler_propschanged)
995 ecore_idler_del(interface->idler_propschanged);
996 if (interface->prop_invalidated) 1107 if (interface->prop_invalidated)
997 eina_array_free(interface->prop_invalidated); 1108 eina_array_free(interface->prop_invalidated);
998 1109
@@ -1004,7 +1115,10 @@ _interface_free(Eldbus_Service_Interface *interface)
1004 * Let's not send any signal */ 1115 * Let's not send any signal */
1005 obj->iface_added = eina_list_remove_list(obj->iface_added, l); 1116 obj->iface_added = eina_list_remove_list(obj->iface_added, l);
1006 if (!obj->iface_added && !obj->iface_removed && obj->idler_iface_changed) 1117 if (!obj->iface_added && !obj->iface_removed && obj->idler_iface_changed)
1007 obj->idler_iface_changed = ecore_idler_del(obj->idler_iface_changed); 1118 {
1119 ecore_idler_del(obj->idler_iface_changed);
1120 obj->idler_iface_changed = NULL;
1121 }
1008 } 1122 }
1009 else 1123 else
1010 { 1124 {
@@ -1022,21 +1136,60 @@ _interface_free(Eldbus_Service_Interface *interface)
1022 free(interface); 1136 free(interface);
1023} 1137}
1024 1138
1139static void _children_ifaces_add_removed_flush(Eldbus_Service_Object *obj)
1140{
1141 Eldbus_Service_Object *children;
1142
1143 EINA_INLIST_FOREACH(obj->children, children)
1144 {
1145 /**
1146 * if there a object manager in some child
1147 * that object manager is responsible for they
1148 * children objects
1149 */
1150 if (!obj->objmanager)
1151 _children_ifaces_add_removed_flush(children);
1152 }
1153
1154 if (obj->idler_iface_changed)
1155 {
1156 ecore_idler_del(obj->idler_iface_changed);
1157 _object_manager_changes_process(obj);
1158 }
1159}
1160
1025static void 1161static void
1026_object_free(Eldbus_Service_Object *obj) 1162_object_free(Eldbus_Service_Object *obj)
1027{ 1163{
1028 Eina_Iterator *iterator; 1164 Eina_Iterator *iterator;
1029 Eldbus_Service_Interface *iface; 1165 Eldbus_Service_Interface *iface;
1030 1166
1031 /* Flush ObjectManager interface before the entire object goes away */ 1167 if (obj->objmanager)
1032 if (obj->idler_iface_changed) 1168 {
1033 ecore_idler_del(obj->idler_iface_changed); 1169 Eldbus_Service_Object *children;
1034 _object_manager_changes_process(obj); 1170
1171 /**
1172 * Flush the iface_add/removed of all children objects
1173 * that this object is the ObjectManager
1174 */
1175 EINA_INLIST_FOREACH(obj->children, children)
1176 _children_ifaces_add_removed_flush(children);
1177 }
1035 1178
1036 iterator = eina_hash_iterator_data_new(obj->interfaces); 1179 iterator = eina_hash_iterator_data_new(obj->interfaces);
1037 EINA_ITERATOR_FOREACH(iterator, iface) 1180 EINA_ITERATOR_FOREACH(iterator, iface)
1038 _interface_free(iface); 1181 _interface_free(iface);
1039 1182
1183 /**
1184 * Flush our iface_add/removed if this object are
1185 * children of some other path with ObjectManager
1186 */
1187 if (obj->idler_iface_changed)
1188 {
1189 ecore_idler_del(obj->idler_iface_changed);
1190 _object_manager_changes_process(obj);
1191 }
1192
1040 while (obj->children) 1193 while (obj->children)
1041 { 1194 {
1042 Eldbus_Service_Object *child; 1195 Eldbus_Service_Object *child;
@@ -1055,6 +1208,7 @@ _object_free(Eldbus_Service_Object *obj)
1055 child->parent = NULL; 1208 child->parent = NULL;
1056 } 1209 }
1057 } 1210 }
1211
1058 if (obj->parent) 1212 if (obj->parent)
1059 obj->parent->children = eina_inlist_remove(obj->parent->children, 1213 obj->parent->children = eina_inlist_remove(obj->parent->children,
1060 EINA_INLIST_GET(obj)); 1214 EINA_INLIST_GET(obj));
@@ -1110,16 +1264,17 @@ _object_unregister(DBusConnection *conn EINA_UNUSED, void *user_data)
1110} 1264}
1111 1265
1112static DBusHandlerResult 1266static DBusHandlerResult
1113_object_handler(DBusConnection *conn EINA_UNUSED, DBusMessage *msg, void *user_data) 1267_object_handler(DBusConnection *dbus_conn EINA_UNUSED, DBusMessage *msg, void *user_data)
1114{ 1268{
1115 Eldbus_Service_Object *obj; 1269 Eldbus_Service_Object *obj;
1116 Eldbus_Service_Interface *iface; 1270 Eldbus_Service_Interface *iface;
1117 const Eldbus_Method *method; 1271 const Eldbus_Method *method;
1118 Eldbus_Message *eldbus_msg; 1272 Eldbus_Message *eldbus_msg, *reply;
1119 Eldbus_Message *reply; 1273 Eldbus_Connection *conn;
1120 1274
1121 obj = user_data; 1275 obj = user_data;
1122 if (!obj) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 1276 if (!obj) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1277 conn = obj->conn;
1123 1278
1124 DBG("Connection@%p Got message:\n" 1279 DBG("Connection@%p Got message:\n"
1125 " Type: %s\n" 1280 " Type: %s\n"
@@ -1145,6 +1300,9 @@ _object_handler(DBusConnection *conn EINA_UNUSED, DBusMessage *msg, void *user_d
1145 dbus_message_ref(eldbus_msg->dbus_msg); 1300 dbus_message_ref(eldbus_msg->dbus_msg);
1146 dbus_message_iter_init(eldbus_msg->dbus_msg, &eldbus_msg->iterator->dbus_iterator); 1301 dbus_message_iter_init(eldbus_msg->dbus_msg, &eldbus_msg->iterator->dbus_iterator);
1147 1302
1303 eldbus_init();
1304 eldbus_connection_ref(conn);
1305
1148 if (!_have_signature(method->in, eldbus_msg)) 1306 if (!_have_signature(method->in, eldbus_msg))
1149 reply = eldbus_message_error_new(eldbus_msg, DBUS_ERROR_INVALID_SIGNATURE, 1307 reply = eldbus_message_error_new(eldbus_msg, DBUS_ERROR_INVALID_SIGNATURE,
1150 "See introspectable to know the expected signature"); 1308 "See introspectable to know the expected signature");
@@ -1164,7 +1322,10 @@ _object_handler(DBusConnection *conn EINA_UNUSED, DBusMessage *msg, void *user_d
1164 1322
1165 eldbus_message_unref(eldbus_msg); 1323 eldbus_message_unref(eldbus_msg);
1166 if (reply) 1324 if (reply)
1167 _eldbus_connection_send(obj->conn, reply, NULL, NULL, -1); 1325 _eldbus_connection_send(conn, reply, NULL, NULL, -1);
1326
1327 eldbus_connection_unref(conn);
1328 eldbus_shutdown();
1168 1329
1169 return DBUS_HANDLER_RESULT_HANDLED; 1330 return DBUS_HANDLER_RESULT_HANDLED;
1170} 1331}
@@ -1255,101 +1416,6 @@ eldbus_service_object_data_del(Eldbus_Service_Interface *iface, const char *key)
1255 return eldbus_data_del(&(((Eldbus_Service_Object *)iface->obj)->data), key); 1416 return eldbus_data_del(&(((Eldbus_Service_Object *)iface->obj)->data), key);
1256} 1417}
1257 1418
1258static Eina_Bool
1259_idler_propschanged(void *data)
1260{
1261 Eldbus_Service_Interface *iface = data;
1262 Eldbus_Message *msg;
1263 Eldbus_Message_Iter *main_iter, *dict, *array_invalidate;
1264 Eina_Hash *added = NULL;
1265 Property *prop;
1266
1267 iface->idler_propschanged = NULL;
1268
1269 added = eina_hash_string_small_new(NULL);
1270 msg = eldbus_message_signal_new(iface->obj->path, properties_iface->name,
1271 properties_iface->signals[0].name);
1272 EINA_SAFETY_ON_NULL_GOTO(msg, error);
1273
1274 main_iter = eldbus_message_iter_get(msg);
1275 if (!eldbus_message_iter_arguments_append(main_iter, "sa{sv}", iface->name, &dict))
1276 {
1277 eldbus_message_unref(msg);
1278 goto error;
1279 }
1280
1281 if (!iface->props_changed)
1282 goto invalidate;
1283 while ((prop = eina_array_pop(iface->props_changed)))
1284 {
1285 Eldbus_Message_Iter *entry, *var;
1286 Eldbus_Message *error_reply = NULL;
1287 Eina_Bool ret;
1288 Eldbus_Property_Get_Cb getter = NULL;
1289
1290 if (eina_hash_find(added, prop->property->name))
1291 continue;
1292 eina_hash_add(added, prop->property->name, prop);
1293
1294 if (prop->property->get_func)
1295 getter = prop->property->get_func;
1296 else if (iface->get_func)
1297 getter = iface->get_func;
1298
1299 if (!getter || prop->is_invalidate)
1300 continue;
1301
1302 EINA_SAFETY_ON_FALSE_GOTO(
1303 eldbus_message_iter_arguments_append(dict, "{sv}", &entry), error);
1304
1305 eldbus_message_iter_basic_append(entry, 's', prop->property->name);
1306 var = eldbus_message_iter_container_new(entry, 'v',
1307 prop->property->type);
1308
1309 ret = getter(iface, prop->property->name, var, NULL, &error_reply);
1310 if (!ret)
1311 {
1312 eldbus_message_unref(msg);
1313 if (error_reply)
1314 {
1315 ERR("Error reply was set without pass any input message.");
1316 eldbus_message_unref(error_reply);
1317 }
1318 ERR("Getter of property %s returned error.", prop->property->name);
1319 goto error;
1320 }
1321
1322 eldbus_message_iter_container_close(entry, var);
1323 eldbus_message_iter_container_close(dict, entry);
1324 }
1325invalidate:
1326 eldbus_message_iter_container_close(main_iter, dict);
1327
1328 eldbus_message_iter_arguments_append(main_iter, "as", &array_invalidate);
1329
1330 if (!iface->prop_invalidated)
1331 goto end;
1332 while ((prop = eina_array_pop(iface->prop_invalidated)))
1333 {
1334 if (!prop->is_invalidate)
1335 continue;
1336 eldbus_message_iter_basic_append(array_invalidate, 's',
1337 prop->property->name);
1338 }
1339end:
1340 eldbus_message_iter_container_close(main_iter, array_invalidate);
1341
1342 eldbus_service_signal_send(iface, msg);
1343error:
1344 if (added)
1345 eina_hash_free(added);
1346 if (iface->props_changed)
1347 eina_array_flush(iface->props_changed);
1348 if (iface->prop_invalidated)
1349 eina_array_flush(iface->prop_invalidated);
1350 return ECORE_CALLBACK_CANCEL;
1351}
1352
1353EAPI Eina_Bool 1419EAPI Eina_Bool
1354eldbus_service_property_changed(const Eldbus_Service_Interface *interface, const char *name) 1420eldbus_service_property_changed(const Eldbus_Service_Interface *interface, const char *name)
1355{ 1421{
@@ -1437,22 +1503,23 @@ eldbus_service_object_manager_attach(Eldbus_Service_Interface *iface)
1437EAPI Eina_Bool 1503EAPI Eina_Bool
1438eldbus_service_object_manager_detach(Eldbus_Service_Interface *iface) 1504eldbus_service_object_manager_detach(Eldbus_Service_Interface *iface)
1439{ 1505{
1440 Eldbus_Service_Object *obj; 1506 Eldbus_Service_Object *obj, *children;
1441 Eina_Bool ret; 1507 Eina_Bool ret;
1442 1508
1443 ELDBUS_SERVICE_INTERFACE_CHECK_RETVAL(iface, EINA_FALSE); 1509 ELDBUS_SERVICE_INTERFACE_CHECK_RETVAL(iface, EINA_FALSE);
1444 obj = iface->obj; 1510 obj = iface->obj;
1511 if (!obj->objmanager)
1512 return EINA_TRUE;
1445 1513
1446 /* Flush our iface_added/iface_removed before our ObjectManager goes away */ 1514 /**
1447 if (obj->idler_iface_changed) 1515 * Flush the iface_add/removed of all children objects
1448 ecore_idler_del(obj->idler_iface_changed); 1516 * that this object is the ObjectManager
1449 _object_manager_changes_process(obj); 1517 */
1518 EINA_INLIST_FOREACH(obj->children, children)
1519 _children_ifaces_add_removed_flush(children);
1450 1520
1451 ret = eina_hash_del(obj->interfaces, objmanager->name, NULL); 1521 ret = eina_hash_del(obj->interfaces, objmanager->name, NULL);
1452 obj->objmanager = NULL; 1522 obj->objmanager = NULL;
1453 obj->introspection_dirty = EINA_TRUE; 1523 obj->introspection_dirty = EINA_TRUE;
1454 //properties + introspectable
1455 if (eina_hash_population(iface->obj->interfaces) < 3)
1456 eldbus_service_object_unregister(iface);
1457 return ret; 1524 return ret;
1458} 1525}