1 #include "e_bluez_private.h"
6 static Eina_Hash *elements = NULL;
8 typedef struct _E_Bluez_Element_Pending E_Bluez_Element_Pending;
9 typedef struct _E_Bluez_Element_Call_Data E_Bluez_Element_Call_Data;
10 typedef struct _E_Bluez_Element_Property E_Bluez_Element_Property;
11 typedef struct _E_Bluez_Element_Listener E_Bluez_Element_Listener;
13 struct _E_Bluez_Element_Pending
16 DBusPendingCall *pending;
18 E_DBus_Method_Return_Cb user_cb;
22 struct _E_Bluez_Element_Call_Data
24 E_Bluez_Element *element;
25 E_DBus_Method_Return_Cb cb;
26 E_Bluez_Element_Pending *pending;
30 struct _E_Bluez_Element_Property
47 struct _E_Bluez_Element_Listener
50 void (*cb)(void *data, const E_Bluez_Element *element);
52 void (*free_data)(void *data);
56 _e_bluez_element_event_no_free(void *data __UNUSED__, void *ev)
58 E_Bluez_Element *element = ev;
59 e_bluez_element_unref(element);
63 e_bluez_element_event_add(int event_type, E_Bluez_Element *element)
65 e_bluez_element_ref(element);
67 (event_type, element, _e_bluez_element_event_no_free, element);
71 e_bluez_element_call_dispatch_and_free(void *d, DBusMessage *msg, DBusError *err)
73 E_Bluez_Element_Call_Data *data = d;
74 E_Bluez_Element_Pending *pending;
76 pending = data->pending;
77 pending->pending = NULL;
80 data->cb(data->element, msg, err);
83 pending->user_cb(pending->user_data, msg, err);
86 *data->p_list = eina_inlist_remove(*data->p_list, EINA_INLIST_GET(pending));
92 e_bluez_element_pending_cancel_and_free(Eina_Inlist **pending)
96 E_Bluez_Element_Pending *p = (E_Bluez_Element_Pending *)*pending;
99 dbus_pending_call_cancel(p->pending);
101 dbus_error_init(&err);
102 dbus_set_error(&err, "Canceled", "Pending method call was canceled.");
103 e_bluez_element_call_dispatch_and_free(p->data, NULL, &err);
104 dbus_error_free(&err);
109 e_bluez_element_listener_add(E_Bluez_Element *element, void (*cb)(void *data, const E_Bluez_Element *element), const void *data, void (*free_data)(void *data))
111 E_Bluez_Element_Listener *l;
115 ERR("safety check failed: element == NULL");
121 ERR("safety check failed: cb == NULL");
125 l = malloc(sizeof(*l));
128 ERR("could not allocate E_Bluez_Element_Listener");
133 l->data = (void *)data;
134 l->free_data = free_data;
136 element->_listeners = eina_inlist_append
137 (element->_listeners, EINA_INLIST_GET(l));
143 free_data((void *)data);
147 e_bluez_element_listener_del(E_Bluez_Element *element, void (*cb)(void *data, const E_Bluez_Element *element), const void *data)
149 E_Bluez_Element_Listener *l;
151 EINA_SAFETY_ON_NULL_RETURN(element);
152 EINA_SAFETY_ON_NULL_RETURN(cb);
154 EINA_INLIST_FOREACH(element->_listeners, l)
155 if ((l->cb == cb) && (l->data == data))
157 element->_listeners = eina_inlist_remove
158 (element->_listeners, EINA_INLIST_GET(l));
160 l->free_data(l->data);
168 _e_bluez_element_listeners_call_do(E_Bluez_Element *element)
170 E_Bluez_Element_Listener *l, **shadow;
171 unsigned int i, count;
173 /* NB: iterate on a copy in order to allow listeners to be deleted
174 * from callbacks. number of listeners should be small, so the
175 * following should do fine.
177 count = eina_inlist_count(element->_listeners);
181 shadow = alloca(sizeof(*shadow) * count);
186 EINA_INLIST_FOREACH(element->_listeners, l)
189 for (i = 0; i < count; i++)
190 shadow[i]->cb(shadow[i]->data, element);
193 e_bluez_element_event_add(E_BLUEZ_EVENT_ELEMENT_UPDATED, element);
197 _e_bluez_element_listeners_call_idler(void *data)
199 E_Bluez_Element *element = data;
200 _e_bluez_element_listeners_call_do(element);
201 element->_idler.changed = NULL;
202 return ECORE_CALLBACK_CANCEL;
206 _e_bluez_element_listeners_call(E_Bluez_Element *element)
208 if (element->_idler.changed)
211 element->_idler.changed = ecore_idler_add
212 (_e_bluez_element_listeners_call_idler, element);
215 /***********************************************************************
217 ***********************************************************************/
220 _e_bluez_element_dict_entry_free(E_Bluez_Element_Dict_Entry *entry)
224 case DBUS_TYPE_BOOLEAN:
226 case DBUS_TYPE_INT16:
227 case DBUS_TYPE_UINT16:
228 case DBUS_TYPE_UINT32:
231 case DBUS_TYPE_OBJECT_PATH:
232 eina_stringshare_del(entry->value.path);
235 case DBUS_TYPE_STRING:
236 eina_stringshare_del(entry->value.str);
240 ERR("don't know how to free dict entry '%s' of type %c (%d)",
241 entry->name, entry->type, entry->type);
244 eina_stringshare_del(entry->name);
248 static E_Bluez_Element_Dict_Entry *
249 _e_bluez_element_dict_entry_new(DBusMessageIter *itr)
251 E_Bluez_Element_Dict_Entry *entry;
252 DBusMessageIter e_itr, v_itr;
254 const char *key = NULL;
257 dbus_message_iter_recurse(itr, &e_itr);
259 t = dbus_message_iter_get_arg_type(&e_itr);
260 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
262 ERR("invalid format for dict entry. first type not a string: %c (%d)",
267 dbus_message_iter_get_basic(&e_itr, &key);
270 ERR("invalid format for dict entry. no key.");
274 dbus_message_iter_next(&e_itr);
275 t = dbus_message_iter_get_arg_type(&e_itr);
276 if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
278 ERR("invalid format for dict entry '%s'. "
279 "second type not a variant: %c (%d)",
284 dbus_message_iter_recurse(&e_itr, &v_itr);
286 t = dbus_message_iter_get_arg_type(&v_itr);
287 if ((t == DBUS_TYPE_INVALID) || (t == DBUS_TYPE_ARRAY))
289 ERR("invalid type for dict value for entry '%s': %c (%d)",
294 entry = calloc(1, sizeof(*entry));
297 ERR("could not allocate memory for dict entry.");
301 dbus_message_iter_get_basic(&v_itr, &value);
304 case DBUS_TYPE_BOOLEAN:
305 entry->value.boolean = (Eina_Bool)(long)value;
309 entry->value.byte = (unsigned char)(long)value;
312 case DBUS_TYPE_INT16:
313 entry->value.i16 = (short)(long)value;
316 case DBUS_TYPE_UINT16:
317 entry->value.u16 = (unsigned short)(long)value;
320 case DBUS_TYPE_UINT32:
321 entry->value.u32 = (unsigned int)(long)value;
324 case DBUS_TYPE_STRING:
325 entry->value.str = eina_stringshare_add(value);
328 case DBUS_TYPE_OBJECT_PATH:
329 entry->value.path = eina_stringshare_add(value);
333 ERR("don't know how to create dict entry '%s' for of type %c (%d)",
339 entry->name = eina_stringshare_add(key);
344 E_Bluez_Element_Dict_Entry *
345 e_bluez_element_array_dict_find_stringshared(const E_Bluez_Array *array, const char *key)
347 E_Bluez_Element_Dict_Entry *entry;
348 Eina_Array_Iterator iterator;
351 EINA_ARRAY_ITER_NEXT(array->array, i, entry, iterator)
352 if (entry->name == key)
359 e_bluez_element_array_free(E_Bluez_Array *array, E_Bluez_Array *new __UNUSED__)
361 Eina_Array_Iterator iterator;
370 case DBUS_TYPE_BOOLEAN:
372 case DBUS_TYPE_INT16:
373 case DBUS_TYPE_UINT16:
374 case DBUS_TYPE_UINT32:
377 case DBUS_TYPE_OBJECT_PATH:
378 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
379 eina_stringshare_del(item);
382 case DBUS_TYPE_STRING:
383 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
384 eina_stringshare_del(item);
387 case DBUS_TYPE_DICT_ENTRY:
388 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
389 _e_bluez_element_dict_entry_free(item);
393 ERR("don't know how to free array of values of type %c (%d)",
394 array->type, array->type);
397 eina_array_free(array->array);
402 _e_bluez_element_property_value_free(E_Bluez_Element_Property *property)
404 switch (property->type)
409 case DBUS_TYPE_BOOLEAN:
411 case DBUS_TYPE_UINT16:
412 case DBUS_TYPE_UINT32:
415 case DBUS_TYPE_STRING:
416 eina_stringshare_del(property->value.str);
419 case DBUS_TYPE_OBJECT_PATH:
420 eina_stringshare_del(property->value.path);
423 case DBUS_TYPE_ARRAY:
424 e_bluez_element_array_free(property->value.array, NULL);
428 ERR("don't know how to free value of property type %c (%d)",
429 property->type, property->type);
434 _e_bluez_element_get_interface(const char *key)
436 const char *interface = NULL, *tail;
445 if (strcmp(tail, "dapters") == 0)
446 interface = e_bluez_iface_adapter;
451 if (strcmp(tail, "evices") == 0)
452 interface = e_bluez_iface_device;
461 ERR("failed to find interface for property \"%s\"", key);
467 _e_bluez_element_item_register(const char *key, const char *item)
469 E_Bluez_Element *element;
470 const char *interface;
472 interface = _e_bluez_element_get_interface(key);
476 element = e_bluez_element_register(item, interface);
477 if ((element) && (!e_bluez_element_properties_sync(element)))
478 WRN("could not get properties of %s", element->path);
481 /* Match 2 arrays to find which are new and which are old elements
482 * For new elements, register them under prop_name property
483 * For old elements, unregister them, sending proper DEL event
486 _e_bluez_element_array_match(E_Bluez_Array *old, E_Bluez_Array *new, const char *prop_name)
488 Eina_List *deleted = NULL;
489 Eina_Array_Iterator iter_old, iter_new;
490 unsigned int i_old = 0, i_new = 0;
491 void *item_old, *item_new;
498 if (old->type != DBUS_TYPE_OBJECT_PATH)
501 if ((!new) || (!new->array) || eina_array_count(new->array) == 0)
503 if ((!old) || (!old->array) || eina_array_count(old->array) == 0)
509 iter_old = old->array->data;
510 goto out_remove_remaining;
514 iter_new = new->array->data;
515 item_new = *iter_new;
516 EINA_ARRAY_ITER_NEXT(old->array, i_old, item_old, iter_old)
518 if (item_old == item_new)
521 if (i_new >= eina_array_count(new->array))
528 item_new = *iter_new;
532 deleted = eina_list_append(deleted, item_old);
536 for(; i_new < eina_array_count(new->array); iter_new++, i_new++)
538 Eina_Bool found = EINA_FALSE;
539 item_new = *iter_new;
543 EINA_LIST_FOREACH(deleted, l, data)
545 if (data == item_new)
547 deleted = eina_list_remove_list(deleted, l);
554 _e_bluez_element_item_register(prop_name, item_new);
555 DBG("Add element %s\n", (const char *)item_new);
559 /* everybody after i_old on old->array + everybody from deleted list
562 EINA_LIST_FREE(deleted, data)
564 E_Bluez_Element *e = e_bluez_element_get(data);
566 e_bluez_element_unregister(e);
568 DBG("Delete element %s\n", (const char *)data);
571 out_remove_remaining:
572 for(; i_old < eina_array_count(old->array); iter_old++, i_old++)
575 item_old = *iter_old;
579 e = e_bluez_element_get(item_old);
581 e_bluez_element_unregister(e);
583 DBG("Delete element %s\n", (const char *)item_old);
588 _e_bluez_element_property_update(E_Bluez_Element_Property *property, int type, void *data)
590 Eina_Bool changed = EINA_FALSE;
592 if ((type == DBUS_TYPE_STRING || type == DBUS_TYPE_OBJECT_PATH) && data)
593 data = (char *)eina_stringshare_add(data);
595 if (property->type != type)
598 DBG("property type changed from '%c' to '%c'",
599 property->type, type);
601 _e_bluez_element_property_value_free(property);
602 memset(&property->value, 0, sizeof(property->value));
603 property->type = type;
609 case DBUS_TYPE_BOOLEAN:
610 if (changed || property->value.boolean != (Eina_Bool)(long)data)
612 property->value.boolean = (Eina_Bool)(long)data;
619 if (changed || property->value.byte != (unsigned char)(long)data)
621 property->value.byte = (unsigned char)(long)data;
627 case DBUS_TYPE_UINT16:
628 if (changed || property->value.u16 != (unsigned short)(long)data)
630 property->value.u16 = (unsigned short)(long)data;
636 case DBUS_TYPE_UINT32:
637 if (changed || property->value.u32 != (unsigned int)(long)data)
639 property->value.u32 = (unsigned int)(long)data;
645 case DBUS_TYPE_STRING:
648 property->value.str = data;
652 if (property->value.str)
653 eina_stringshare_del(property->value.str);
655 if (property->value.str != data)
657 property->value.str = data;
664 case DBUS_TYPE_OBJECT_PATH:
667 property->value.path = data;
671 if (property->value.path)
672 eina_stringshare_del(property->value.path);
674 if (property->value.path != data)
676 property->value.path = data;
683 case DBUS_TYPE_ARRAY:
685 if (property->value.array)
687 _e_bluez_element_array_match(property->value.array, data, property->name);
688 e_bluez_element_array_free(property->value.array, data);
691 property->value.array = data;
696 ERR("don't know how to update property type %c (%d)", type, type);
702 static E_Bluez_Element_Property *
703 _e_bluez_element_property_new(const char *name, int type, void *data)
705 E_Bluez_Element_Property *property;
707 property = calloc(1, sizeof(*property));
710 eina_stringshare_del(name);
711 ERR("could not allocate property: %s", strerror(errno));
715 property->name = name;
716 _e_bluez_element_property_update(property, type, data);
721 _e_bluez_element_property_free(E_Bluez_Element_Property *property)
723 _e_bluez_element_property_value_free(property);
724 eina_stringshare_del(property->name);
728 /***********************************************************************
730 ***********************************************************************/
732 e_bluez_element_bytes_array_get_stringshared(const E_Bluez_Element *element, const char *property, unsigned int *count)
734 Eina_Array_Iterator iterator;
735 E_Bluez_Array *array;
736 unsigned char *ret, *p;
740 EINA_SAFETY_ON_NULL_RETURN_VAL(element, NULL);
741 EINA_SAFETY_ON_NULL_RETURN_VAL(property, NULL);
742 EINA_SAFETY_ON_NULL_RETURN_VAL(count, NULL);
746 if (!e_bluez_element_property_get_stringshared
747 (element, property, NULL, &array))
750 if ((!array) || (!(array->array)))
753 *count = eina_array_count(array->array);
754 ret = malloc(*count * sizeof(unsigned char));
757 ERR("could not allocate return array of %d bytes: %s",
758 *count, strerror(errno));
764 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
766 *p = (unsigned char)(long)item;
773 e_bluez_element_objects_array_get_stringshared(const E_Bluez_Element *element, const char *property, unsigned int *count, E_Bluez_Element ***p_elements)
775 E_Bluez_Element **ret, **p;
776 Eina_Array_Iterator iterator;
777 E_Bluez_Array *array;
782 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
783 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EINA_FALSE);
784 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
785 EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, EINA_FALSE);
790 if (!e_bluez_element_property_get_stringshared
791 (element, property, &type, &array))
794 if (type != DBUS_TYPE_ARRAY)
796 ERR("property %s is not an array!", property);
800 if ((!array) || (!array->array) || (array->type == DBUS_TYPE_INVALID))
803 if (array->type != DBUS_TYPE_OBJECT_PATH)
805 ERR("property %s is not an array of object paths!", property);
809 *count = eina_array_count(array->array);
810 ret = malloc(*count * sizeof(E_Bluez_Element *));
813 ERR("could not allocate return array of %d elements: %s",
814 *count, strerror(errno));
821 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
823 E_Bluez_Element *e = e_bluez_element_get(item);
835 /* strings are just pointers (references), no strdup or stringshare_add/ref */
837 e_bluez_element_strings_array_get_stringshared(const E_Bluez_Element *element, const char *property, unsigned int *count, const char ***strings)
839 const char **ret, **p;
840 Eina_Array_Iterator iterator;
841 E_Bluez_Array *array;
846 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
847 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EINA_FALSE);
848 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
849 EINA_SAFETY_ON_NULL_RETURN_VAL(strings, EINA_FALSE);
854 if (!e_bluez_element_property_get_stringshared
855 (element, property, &type, &array))
858 if (type != DBUS_TYPE_ARRAY)
860 ERR("property %s is not an array!", property);
864 if ((!array) || (!array->array) || (array->type == DBUS_TYPE_INVALID))
867 if (array->type != DBUS_TYPE_STRING)
869 ERR("property %s is not an array of strings!", property);
873 *count = eina_array_count(array->array);
874 ret = malloc(*count * sizeof(char *));
877 ERR("could not allocate return array of %d strings: %s",
878 *count, strerror(errno));
885 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
899 e_bluez_element_array_print(FILE *fp, E_Bluez_Array *array)
901 Eina_Array_Iterator iterator;
910 case DBUS_TYPE_OBJECT_PATH:
911 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
912 fprintf(fp, "\"%s\", ", (const char *)item);
915 case DBUS_TYPE_STRING:
916 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
917 fprintf(fp, "\"%s\", ", (const char *)item);
921 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
922 fprintf(fp, "%#02hhx (\"%c\"), ", (unsigned char)(long)item,
923 (unsigned char)(long)item);
926 case DBUS_TYPE_UINT16:
927 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
928 fprintf(fp, "%#04hx (%hu), ", (unsigned short)(long)item,
929 (unsigned short)(long)item);
932 case DBUS_TYPE_UINT32:
933 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
934 fprintf(fp, "%#08x (%u), ", (unsigned int)(long)item,
935 (unsigned int)(long)item);
938 case DBUS_TYPE_DICT_ENTRY:
940 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
942 E_Bluez_Element_Dict_Entry *entry = item;
943 fprintf(fp, "%s: ", entry->name);
946 case DBUS_TYPE_OBJECT_PATH:
947 fprintf(fp, "\"%s\", ", entry->value.path);
950 case DBUS_TYPE_STRING:
951 fprintf(fp, "\"%s\", ", entry->value.str);
954 case DBUS_TYPE_BOOLEAN:
955 fprintf(fp, "%hhu, ",
956 entry->value.boolean);
960 fprintf(fp, "%#02hhx (\"%c\"), ",
961 entry->value.byte, entry->value.byte);
964 case DBUS_TYPE_INT16:
965 fprintf(fp, "%#04hx (%hi), ",
966 entry->value.i16, entry->value.i16);
969 case DBUS_TYPE_UINT16:
970 fprintf(fp, "%#04hx (%hu), ",
971 entry->value.u16, entry->value.u16);
974 case DBUS_TYPE_UINT32:
975 fprintf(fp, "%#08x (%u), ",
976 entry->value.u32, entry->value.u32);
980 fprintf(fp, "<UNKNOWN TYPE '%c'>", entry->type);
987 fprintf(fp, "<UNKNOWN ARRAY TYPE '%c'>", array->type);
992 * Print element to file descriptor.
995 e_bluez_element_print(FILE *fp, const E_Bluez_Element *element)
997 const E_Bluez_Element_Property *p;
999 EINA_SAFETY_ON_NULL_RETURN(fp);
1002 fputs("Error: no element to print\n", fp);
1007 "Element %p: %s [%s]\n"
1009 element, element->path, element->interface);
1011 EINA_INLIST_FOREACH(element->props, p)
1013 fprintf(fp, "\t\t%s (%c) = ", p->name, p->type);
1017 case DBUS_TYPE_STRING:
1018 fprintf(fp, "\"%s\"", p->value.str);
1021 case DBUS_TYPE_OBJECT_PATH:
1022 fprintf(fp, "\"%s\"", p->value.path);
1025 case DBUS_TYPE_BOOLEAN:
1026 fprintf(fp, "%hhu", p->value.boolean);
1029 case DBUS_TYPE_BYTE:
1030 fprintf(fp, "%#02hhx (%d), ", p->value.byte, p->value.byte);
1033 case DBUS_TYPE_UINT16:
1034 fprintf(fp, "%hu", p->value.u16);
1037 case DBUS_TYPE_UINT32:
1038 fprintf(fp, "%u", p->value.u32);
1041 case DBUS_TYPE_ARRAY:
1042 e_bluez_element_array_print(fp, p->value.array);
1046 fputs("don't know how to print type", fp);
1053 static E_Bluez_Element *
1054 e_bluez_element_new(const char *path, const char *interface)
1056 E_Bluez_Element *element;
1058 element = calloc(1, sizeof(*element));
1061 ERR("could not allocate element: %s", strerror(errno));
1065 element->path = eina_stringshare_add(path);
1066 element->interface = eina_stringshare_ref(interface);
1067 element->_references = 1;
1073 e_bluez_element_extra_properties_free(E_Bluez_Element *element)
1075 while (element->props)
1077 E_Bluez_Element_Property *prop;
1078 prop = (E_Bluez_Element_Property *)element->props;
1079 element->props = element->props->next;
1080 _e_bluez_element_property_free(prop);
1085 e_bluez_element_free(E_Bluez_Element *element)
1087 if (element->_idler.changed)
1088 ecore_idler_del(element->_idler.changed);
1090 while (element->_listeners)
1092 E_Bluez_Element_Listener *l = (void *)element->_listeners;
1093 element->_listeners = eina_inlist_remove
1094 (element->_listeners, element->_listeners);
1097 l->free_data(l->data);
1102 e_bluez_element_pending_cancel_and_free(&element->_pending.properties_get);
1103 e_bluez_element_pending_cancel_and_free(&element->_pending.property_set);
1104 e_bluez_element_pending_cancel_and_free(&element->_pending.agent_register);
1105 e_bluez_element_pending_cancel_and_free(&element->_pending.agent_unregister);
1107 e_bluez_element_extra_properties_free(element);
1108 eina_stringshare_del(element->interface);
1109 eina_stringshare_del(element->path);
1114 * Add reference to element.
1117 e_bluez_element_ref(E_Bluez_Element *element)
1119 EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
1120 return ++element->_references;
1124 * Remove reference from element.
1126 * If reference count drops to 0 element will be freed.
1129 e_bluez_element_unref(E_Bluez_Element *element)
1132 EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
1134 i = --element->_references;
1136 e_bluez_element_free(element);
1138 ERR("element %p references %d < 0", element, i);
1144 * Send message with callbacks set to work with bluez elements.
1146 * If this call fails (returns @c EINA_FALSE), pending callbacks will not be called,
1147 * not even with error messages.
1149 * @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
1152 e_bluez_element_message_send(E_Bluez_Element *element, const char *method_name, E_DBus_Method_Return_Cb cb, DBusMessage *msg, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
1154 E_Bluez_Element_Call_Data *data;
1155 E_Bluez_Element_Pending *p;
1157 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1158 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1159 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1160 EINA_SAFETY_ON_NULL_RETURN_VAL(msg, EINA_FALSE);
1162 data = malloc(sizeof(*data));
1165 ERR("could not alloc e_bluez_element_call_data: %s",
1167 dbus_message_unref(msg);
1171 p = malloc(sizeof(*p));
1174 ERR("could not alloc E_Bluez_Element_Pending: %s",
1177 dbus_message_unref(msg);
1181 data->element = element;
1184 data->p_list = pending;
1185 p->user_cb = user_cb;
1186 p->user_data = (void *)user_data;
1188 p->pending = e_dbus_message_send
1189 (e_bluez_conn, msg, e_bluez_element_call_dispatch_and_free, -1, data);
1190 dbus_message_unref(msg);
1194 *pending = eina_inlist_append(*pending, EINA_INLIST_GET(p));
1198 ERR("failed to call %s (obj=%s, path=%s, iface=%s)",
1199 method_name, e_bluez_system_bus_name_get(),
1200 element->path, element->interface);
1207 e_bluez_element_call_full(E_Bluez_Element *element, const char *method_name, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
1211 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1212 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1213 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1215 msg = dbus_message_new_method_call
1216 (e_bluez_system_bus_name_get(), element->path, element->interface,
1219 return e_bluez_element_message_send
1220 (element, method_name, cb, msg, pending, user_cb, user_data);
1224 _e_bluez_element_property_value_add(E_Bluez_Element *element, const char *name, int type, void *value)
1226 E_Bluez_Element_Property *p;
1228 name = eina_stringshare_add(name);
1229 EINA_INLIST_FOREACH(element->props, p)
1231 if (p->name == name)
1233 eina_stringshare_del(name);
1234 return _e_bluez_element_property_update(p, type, value);
1238 p = _e_bluez_element_property_new(name, type, value);
1241 ERR("could not create property %s (%c)", name, type);
1245 element->props = eina_inlist_append(element->props, EINA_INLIST_GET(p));
1250 e_bluez_element_iter_get_array(DBusMessageIter *itr, const char *key)
1252 E_Bluez_Array *array;
1253 DBusMessageIter e_itr;
1255 array = malloc(sizeof(E_Bluez_Array));
1258 ERR("could not create new e_bluez array.");
1262 array->array = eina_array_new(16);
1263 if (!(array->array))
1265 ERR("could not create new eina array.");
1270 dbus_message_iter_recurse(itr, &e_itr);
1271 array->type = dbus_message_iter_get_arg_type(&e_itr);
1272 if (array->type == DBUS_TYPE_INVALID)
1274 DBG("array %s is of type 'invalid' (empty?)", key);
1275 eina_array_free(array->array);
1282 switch (array->type)
1284 case DBUS_TYPE_OBJECT_PATH:
1288 dbus_message_iter_get_basic(&e_itr, &path);
1289 path = eina_stringshare_add(path);
1290 eina_array_push(array->array, path);
1291 _e_bluez_element_item_register(key, path);
1295 case DBUS_TYPE_STRING:
1299 dbus_message_iter_get_basic(&e_itr, &str);
1300 str = eina_stringshare_add(str);
1301 eina_array_push(array->array, str);
1305 case DBUS_TYPE_BYTE:
1308 dbus_message_iter_get_basic(&e_itr, &byte);
1309 eina_array_push(array->array, (void *)(long)byte);
1313 case DBUS_TYPE_DICT_ENTRY:
1315 E_Bluez_Element_Dict_Entry *entry;
1316 entry = _e_bluez_element_dict_entry_new(&e_itr);
1318 eina_array_push(array->array, entry);
1323 ERR("don't know how to build array '%s' of type %c (%d)",
1324 key, array->type, array->type);
1325 eina_array_free(array->array);
1330 while (dbus_message_iter_next(&e_itr));
1335 _e_bluez_element_get_properties_callback(void *user_data, DBusMessage *msg, DBusError *err)
1337 E_Bluez_Element *element = user_data;
1338 DBusMessageIter itr, s_itr;
1341 DBG("get_properties msg=%p", msg);
1343 if (!_dbus_callback_check_and_init(msg, &itr, err))
1346 t = dbus_message_iter_get_arg_type(&itr);
1347 if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
1351 dbus_message_iter_recurse(&itr, &s_itr);
1354 DBusMessageIter e_itr, v_itr;
1359 t = dbus_message_iter_get_arg_type(&s_itr);
1360 if (!_dbus_iter_type_check(t, DBUS_TYPE_DICT_ENTRY))
1363 dbus_message_iter_recurse(&s_itr, &e_itr);
1365 t = dbus_message_iter_get_arg_type(&e_itr);
1366 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
1369 dbus_message_iter_get_basic(&e_itr, &key);
1370 dbus_message_iter_next(&e_itr);
1371 t = dbus_message_iter_get_arg_type(&e_itr);
1372 if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
1375 dbus_message_iter_recurse(&e_itr, &v_itr);
1376 t = dbus_message_iter_get_arg_type(&v_itr);
1377 if (t == DBUS_TYPE_ARRAY)
1379 value = e_bluez_element_iter_get_array(&v_itr, key);
1381 else if (t != DBUS_TYPE_INVALID)
1383 dbus_message_iter_get_basic(&v_itr, &value);
1387 ERR("property has invalid type %s", key);
1391 r = _e_bluez_element_property_value_add(element, key, t, value);
1394 ERR("failed to add property value %s (%c)", key, t);
1398 INF("property value changed %s (%c)", key, t);
1402 while (dbus_message_iter_next(&s_itr));
1405 _e_bluez_element_listeners_call(element);
1409 * Sync element properties with server.
1411 * Call method GetProperties() at the given element on server in order to sync
1414 * @param element to call method on server.
1415 * @param cb function to call when server replies or some error happens.
1416 * @param data data to give to cb when it is called.
1418 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1421 e_bluez_element_properties_sync_full(E_Bluez_Element *element, E_DBus_Method_Return_Cb cb, const void *data)
1423 const char name[] = "GetProperties";
1425 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1426 return e_bluez_element_call_full
1427 (element, name, _e_bluez_element_get_properties_callback,
1428 &element->_pending.properties_get, cb, data);
1432 * Sync element properties with server, simple version.
1434 * Call method GetProperties() at the given element on server in order to sync
1435 * them. This is the simple version and there is no check of server reply
1438 * @param element to call method on server.
1440 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1443 e_bluez_element_properties_sync(E_Bluez_Element *element)
1445 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1446 return e_bluez_element_properties_sync_full(element, NULL, NULL);
1450 * Call method SetProperty(prop, {key: value}) at the given element on server.
1452 * This is a server call, not local, so it may fail and in that case
1453 * no property is updated locally. If the value was set the event
1454 * E_BLUEZ_EVENT_ELEMENT_UPDATED will be added to main loop.
1456 * @param element to call method on server.
1457 * @param prop property name.
1458 * @param key dict key name.
1459 * @param type DBus type to use for value.
1460 * @param value pointer to value, just like regular DBus, see
1461 * dbus_message_iter_append_basic().
1462 * @param cb function to call when server replies or some error happens.
1463 * @param data data to give to cb when it is called.
1465 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1468 e_bluez_element_property_dict_set_full(E_Bluez_Element *element, const char *prop, const char *key, int type, const void *value, E_DBus_Method_Return_Cb cb, const void *data)
1470 const char name[] = "SetProperty";
1472 DBusMessageIter itr, variant, dict, entry;
1475 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1476 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
1478 msg = dbus_message_new_method_call
1479 (e_bluez_system_bus_name_get(), element->path, element->interface, name);
1484 dbus_message_iter_init_append(msg, &itr);
1485 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &prop);
1487 if ((size_t)snprintf(typestr, sizeof(typestr),
1488 (DBUS_TYPE_ARRAY_AS_STRING
1489 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1490 DBUS_TYPE_STRING_AS_STRING
1492 DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
1493 type) >= sizeof(typestr))
1495 ERR("sizeof(typestr) is too small!");
1499 if (dbus_message_iter_open_container(&itr, DBUS_TYPE_VARIANT, typestr, &variant))
1501 snprintf(typestr, sizeof(typestr),
1502 (DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1503 DBUS_TYPE_STRING_AS_STRING
1505 DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
1508 if (dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, typestr, &dict))
1510 if (dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry))
1512 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1514 if ((type == DBUS_TYPE_STRING) || (type == DBUS_TYPE_OBJECT_PATH))
1515 dbus_message_iter_append_basic(&entry, type, &value);
1517 dbus_message_iter_append_basic(&entry, type, value);
1519 dbus_message_iter_close_container(&dict, &entry);
1523 ERR("dbus_message_iter_open_container() failed");
1525 dbus_message_iter_close_container(&variant, &dict);
1529 ERR("dbus_message_iter_open_container() failed");
1531 dbus_message_iter_close_container(&itr, &variant);
1535 ERR("dbus_message_iter_open_container() failed");
1538 return e_bluez_element_message_send
1539 (element, name, NULL, msg, &element->_pending.property_set, cb, data);
1543 * Call method SetProperty(prop, value) at the given element on server.
1545 * This is a server call, not local, so it may fail and in that case
1546 * no property is updated locally. If the value was set the event
1547 * E_BLUEZ_EVENT_ELEMENT_UPDATED will be added to main loop.
1549 * @param element to call method on server.
1550 * @param prop property name.
1551 * @param type DBus type to use for value.
1552 * @param value pointer to value, just like regular DBus, see
1553 * dbus_message_iter_append_basic().
1554 * @param cb function to call when server replies or some error happens.
1555 * @param data data to give to cb when it is called.
1557 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1560 e_bluez_element_property_set_full(E_Bluez_Element *element, const char *prop, int type, const void *value, E_DBus_Method_Return_Cb cb, const void *data)
1562 const char name[] = "SetProperty";
1566 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1567 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
1569 msg = dbus_message_new_method_call
1570 (e_bluez_system_bus_name_get(), element->path, element->interface, name);
1575 DBusMessageIter itr, v;
1576 dbus_message_iter_init_append(msg, &itr);
1577 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &prop);
1581 if (dbus_message_iter_open_container(&itr, DBUS_TYPE_VARIANT, typestr, &v))
1583 if ((type == DBUS_TYPE_STRING) || (type == DBUS_TYPE_OBJECT_PATH))
1585 dbus_message_iter_append_basic(&v, type, &value);
1587 else if (type == DBUS_TYPE_BOOLEAN)
1589 unsigned int b = *(char *)value;
1590 dbus_message_iter_append_basic(&v, type, &b);
1594 dbus_message_iter_append_basic(&v, type, value);
1596 dbus_message_iter_close_container(&itr, &v);
1600 ERR("dbus_message_iter_open_container() failed");
1603 return e_bluez_element_message_send
1604 (element, name, NULL, msg, &element->_pending.property_set, cb, data);
1608 * Call method SetProperty(prop, value) at the given element on server.
1610 * This is the simple version and there is no check of server reply
1613 * @param element to call method on server.
1614 * @param prop property name.
1615 * @param type DBus type to use for value.
1616 * @param value pointer to value, just like regular DBus, see
1617 * dbus_message_iter_append_basic().
1619 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1622 e_bluez_element_property_set(E_Bluez_Element *element, const char *prop, int type, const void *value)
1624 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1625 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
1626 return e_bluez_element_property_set_full
1627 (element, prop, type, value, NULL, NULL);
1631 e_bluez_element_call_with_path(E_Bluez_Element *element, const char *method_name, const char *string, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
1633 DBusMessageIter itr;
1636 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1637 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1638 EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
1639 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1641 msg = dbus_message_new_method_call
1642 (e_bluez_system_bus_name_get(), element->path, element->interface,
1648 dbus_message_iter_init_append(msg, &itr);
1649 dbus_message_iter_append_basic(&itr, DBUS_TYPE_OBJECT_PATH, &string);
1651 return e_bluez_element_message_send
1652 (element, method_name, cb, msg, pending, user_cb, user_data);
1656 e_bluez_element_call_with_string(E_Bluez_Element *element, const char *method_name, const char *string, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
1658 DBusMessageIter itr;
1661 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1662 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1663 EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
1664 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1666 msg = dbus_message_new_method_call
1667 (e_bluez_system_bus_name_get(), element->path, element->interface,
1673 dbus_message_iter_init_append(msg, &itr);
1674 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &string);
1676 return e_bluez_element_message_send
1677 (element, method_name, cb, msg, pending, user_cb, user_data);
1681 e_bluez_element_call_with_path_and_string(E_Bluez_Element *element, const char *method_name, const char *path, const char *string, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
1683 DBusMessageIter itr;
1686 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1687 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1688 EINA_SAFETY_ON_NULL_RETURN_VAL(path, EINA_FALSE);
1689 EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
1690 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1692 msg = dbus_message_new_method_call
1693 (e_bluez_system_bus_name_get(), element->path, element->interface,
1699 dbus_message_iter_init_append(msg, &itr);
1700 dbus_message_iter_append_basic(&itr, DBUS_TYPE_OBJECT_PATH, &path);
1701 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &string);
1703 return e_bluez_element_message_send
1704 (element, method_name, cb, msg, pending, user_cb, user_data);
1708 * Get property type.
1710 * If @c EINA_FALSE is returned, then this call failed and parameter-returned
1711 * values shall be considered invalid.
1713 * @param element which element to get the property
1714 * @param name property name, must be previously stringshared
1715 * @param type will contain the value type.
1717 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1720 e_bluez_element_property_type_get_stringshared(const E_Bluez_Element *element, const char *name, int *type)
1722 const E_Bluez_Element_Property *p;
1724 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1725 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
1726 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
1728 EINA_INLIST_FOREACH(element->props, p)
1730 if (p->name == name)
1737 WRN("element %s (%p) has no property with name \"%s\".",
1738 element->path, element, name);
1743 * Get property type.
1745 * If @c EINA_FALSE is returned, then this call failed and parameter-returned
1746 * values shall be considered invalid.
1748 * @param element which element to get the property
1749 * @param name property name
1750 * @param type will contain the value type.
1752 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1755 e_bluez_element_property_type_get(const E_Bluez_Element *element, const char *name, int *type)
1758 name = eina_stringshare_add(name);
1759 ret = e_bluez_element_property_type_get_stringshared(element, name, type);
1760 eina_stringshare_del(name);
1765 e_bluez_element_list_properties(const E_Bluez_Element *element, Eina_Bool (*cb)(void *data, const E_Bluez_Element *element, const char *name, int type, const void *value), const void *data)
1767 e_bluez_element_properties_list(element, cb, data);
1771 e_bluez_element_properties_list(const E_Bluez_Element *element, Eina_Bool (*cb)(void *data, const E_Bluez_Element *element, const char *name, int type, const void *value), const void *data)
1773 const E_Bluez_Element_Property *p;
1775 EINA_SAFETY_ON_NULL_RETURN(element);
1776 EINA_SAFETY_ON_NULL_RETURN(cb);
1778 EINA_INLIST_FOREACH(element->props, p)
1780 const void *value = NULL;
1784 case DBUS_TYPE_STRING:
1785 value = &p->value.str;
1788 case DBUS_TYPE_OBJECT_PATH:
1789 value = &p->value.path;
1792 case DBUS_TYPE_BOOLEAN:
1793 value = (void *)(unsigned long)p->value.boolean;
1796 case DBUS_TYPE_UINT16:
1797 value = &p->value.u16;
1800 case DBUS_TYPE_UINT32:
1801 value = &p->value.u32;
1805 ERR("unsupported type %c", p->type);
1808 if (!cb((void *)data, element, p->name, p->type, value))
1814 * Get dict value given its key inside a dict property.
1816 * This will look into properties for one of type dict that contains
1817 * the given key, to find the property. If no property is found then
1818 * @c EINA_FALSE is returned.
1820 * If @c EINA_FALSE is returned, then this call failed and parameter-returned
1821 * values shall be considered invalid.
1823 * @param element which element to get the property
1824 * @param dict_name property name, must be previously stringshared
1825 * @param key key inside dict, must be previously stringshared
1826 * @param type if provided it will contain the value type.
1827 * @param value where to store the property value, must be a pointer to the
1828 * exact type, (Eina_Bool *) for booleans, (char **) for strings, and so on.
1830 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1833 e_bluez_element_property_dict_get_stringshared(const E_Bluez_Element *element, const char *dict_name, const char *key, int *type, void *value)
1835 const E_Bluez_Element_Property *p;
1837 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1838 EINA_SAFETY_ON_NULL_RETURN_VAL(dict_name, EINA_FALSE);
1839 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
1840 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
1842 EINA_INLIST_FOREACH(element->props, p)
1844 E_Bluez_Element_Dict_Entry *entry;
1845 E_Bluez_Array *array;
1847 if (p->name != dict_name)
1850 if (p->type != DBUS_TYPE_ARRAY)
1852 WRN("element %s (%p) has property \"%s\" is not an array: %c (%d)",
1853 element->path, element, dict_name, p->type, p->type);
1857 array = p->value.array;
1858 if ((!array) || (array->type != DBUS_TYPE_DICT_ENTRY))
1860 int t = array ? array->type : DBUS_TYPE_INVALID;
1861 WRN("element %s (%p) has property \"%s\" is not a dict: %c (%d)",
1862 element->path, element, dict_name, t, t);
1866 entry = e_bluez_element_array_dict_find_stringshared(array, key);
1869 WRN("element %s (%p) has no dict property with name \"%s\" with "
1871 element->path, element, dict_name, key);
1876 *type = entry->type;
1878 switch (entry->type)
1880 case DBUS_TYPE_BOOLEAN:
1881 *(Eina_Bool *)value = entry->value.boolean;
1884 case DBUS_TYPE_BYTE:
1885 *(unsigned char *)value = entry->value.byte;
1888 case DBUS_TYPE_INT16:
1889 *(short *)value = entry->value.i16;
1892 case DBUS_TYPE_UINT16:
1893 *(unsigned short *)value = entry->value.u16;
1896 case DBUS_TYPE_UINT32:
1897 *(unsigned int *)value = entry->value.u32;
1900 case DBUS_TYPE_STRING:
1901 *(const char **)value = entry->value.str;
1904 case DBUS_TYPE_OBJECT_PATH:
1905 *(const char **)value = entry->value.path;
1909 ERR("don't know how to get property %s, key %s type %c (%d)",
1910 dict_name, key, entry->type, entry->type);
1915 WRN("element %s (%p) has no property with name \"%s\".",
1916 element->path, element, dict_name);
1921 * Get property value given its name.
1923 * This will look into properties, to find the property.
1924 * If no property is found then @c EINA_FALSE is returned.
1926 * If @c EINA_FALSE is returned, then this call failed and parameter-returned
1927 * values shall be considered invalid.
1929 * @param element which element to get the property
1930 * @param name property name, must be previously stringshared
1931 * @param type if provided it will contain the value type.
1932 * @param value where to store the property value, must be a pointer to the
1933 * exact type, (Eina_Bool *) for booleans, (char **) for strings, and so on.
1935 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1938 e_bluez_element_property_get_stringshared(const E_Bluez_Element *element, const char *name, int *type, void *value)
1940 const E_Bluez_Element_Property *p;
1942 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1943 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
1944 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
1946 EINA_INLIST_FOREACH(element->props, p)
1948 if (p->name != name)
1956 case DBUS_TYPE_BOOLEAN:
1957 *(Eina_Bool *)value = p->value.boolean;
1960 case DBUS_TYPE_BYTE:
1961 *(unsigned char *)value = p->value.byte;
1964 case DBUS_TYPE_UINT16:
1965 *(unsigned short *)value = p->value.u16;
1968 case DBUS_TYPE_UINT32:
1969 *(unsigned int *)value = p->value.u32;
1972 case DBUS_TYPE_STRING:
1973 *(const char **)value = p->value.str;
1976 case DBUS_TYPE_OBJECT_PATH:
1977 *(const char **)value = p->value.path;
1980 case DBUS_TYPE_ARRAY:
1981 *(E_Bluez_Array **)value = p->value.array;
1985 ERR("don't know how to get property type %c (%d)",
1991 WRN("element %s (%p) has no property with name \"%s\".",
1992 element->path, element, name);
1997 * Get property value given its name.
1999 * This will look into properties, to find the property.
2000 * If no property is found then @c EINA_FALSE is returned.
2002 * If @c EINA_FALSE is returned, then this call failed and parameter-returned
2003 * values shall be considered invalid.
2005 * @param element which element to get the property
2006 * @param name property name
2007 * @param type if provided it will contain the value type.
2008 * @param value where to store the property value, must be a pointer to the
2009 * exact type, (Eina_Bool *) for booleans, (char **) for strings, and so on.
2011 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2014 e_bluez_element_property_get(const E_Bluez_Element *element, const char *name, int *type, void *value)
2017 name = eina_stringshare_add(name);
2018 ret = e_bluez_element_property_get_stringshared
2019 (element, name, type, value);
2020 eina_stringshare_del(name);
2024 struct e_bluez_elements_for_each_data
2026 Eina_Hash_Foreach cb;
2031 _e_bluez_elements_for_each(Eina_Hash *hash __UNUSED__, const char *key, void *data, void *fdata)
2033 struct e_bluez_elements_for_each_data *each_data = fdata;
2035 each_data->cb(elements, key, data, each_data->data);
2040 * Call the given function for each existing element.
2042 * @param cb function to call for each element. It will get as parameters,
2043 * in order: the element pointer and the given @a user_data.
2044 * @param user_data data to give to @a cb for each element.
2047 e_bluez_elements_for_each(Eina_Hash_Foreach cb, const void *user_data)
2049 struct e_bluez_elements_for_each_data data = {cb, (void *)user_data};
2051 EINA_SAFETY_ON_NULL_RETURN(cb);
2053 eina_hash_foreach(elements, (Eina_Hash_Foreach)_e_bluez_elements_for_each,
2058 _e_bluez_elements_get_allocate(unsigned int *count, E_Bluez_Element ***p_elements)
2060 *count = eina_hash_population(elements);
2067 *p_elements = malloc(*count * sizeof(E_Bluez_Element *));
2070 ERR("could not allocate return array of %d elements: %s",
2071 *count, strerror(errno));
2080 _e_bluez_elements_get_all(Eina_Hash *hash __UNUSED__, const char *key __UNUSED__, void *data, void *fdata)
2082 E_Bluez_Element *element = data;
2083 E_Bluez_Element ***p_ret = fdata;
2091 * Get all known elements.
2093 * No reference is added to these elements, since there are no threads
2094 * in the system, you are free to add references yourself right after
2095 * the return of this call without race condition, elements by the
2096 * system (ie: elementRemoved signal)could only be touched on the next
2097 * main loop iteration.
2099 * @param count return the number of elements in array.
2100 * @param p_elements array with all elements, these are not referenced
2101 * and in no particular order, just set if return is 1.
2103 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2106 e_bluez_elements_get_all(unsigned int *count, E_Bluez_Element ***p_elements)
2108 E_Bluez_Element **p;
2110 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
2111 EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, EINA_FALSE);
2113 if (!_e_bluez_elements_get_allocate(count, p_elements))
2117 eina_hash_foreach(elements, (Eina_Hash_Foreach)_e_bluez_elements_get_all,
2122 struct e_bluez_elements_get_all_str_data
2124 E_Bluez_Element **elements;
2130 _e_bluez_elements_get_all_type(Eina_Hash *hash __UNUSED__, const char *key __UNUSED__, void *e, void *user_data)
2132 struct e_bluez_elements_get_all_str_data *data = user_data;
2133 E_Bluez_Element *element = e;
2135 if ((data->str) && (element->interface != data->str))
2138 data->elements[data->count] = element;
2144 * Get all known elements of type.
2146 * No reference is added to these elements, since there are no threads
2147 * in the system, you are free to add references yourself right after
2148 * the return of this call without race condition, elements by the
2149 * system (ie: ElementRemoved signal) could only be touched on the next
2150 * main loop iteration.
2152 * @param type type to filter, or NULL to get all.
2153 * @param count return the number of elements in array.
2154 * @param p_elements array with all elements, these are not referenced
2155 * and in no particular order, just set if return is 1.
2157 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2159 * @see e_bluez_elements_get_all()
2162 e_bluez_elements_get_all_type(const char *type, unsigned int *count, E_Bluez_Element ***p_elements)
2164 struct e_bluez_elements_get_all_str_data data;
2166 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
2167 EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, EINA_FALSE);
2169 if (!_e_bluez_elements_get_allocate(count, p_elements))
2172 data.elements = *p_elements;
2174 data.str = eina_stringshare_add(type);
2175 eina_hash_foreach(elements,
2176 (Eina_Hash_Foreach)_e_bluez_elements_get_all_type,
2179 eina_stringshare_del(data.str);
2180 *count = data.count;
2185 * Get the element registered at given path.
2187 * @param path the path to query for registered object.
2189 * @return element pointer if found, NULL otherwise. No references are added.
2192 e_bluez_element_get(const char *path)
2194 E_Bluez_Element *element;
2196 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2197 element = eina_hash_find(elements, path);
2203 _e_bluez_element_property_changed_callback(void *data, DBusMessage *msg)
2205 E_Bluez_Element *element = (E_Bluez_Element *)data;
2206 DBusMessageIter itr, v_itr;
2207 int t, r, changed = 0;
2208 const char *name = NULL;
2211 DBG("Property changed in element %s", element->path);
2213 if (!_dbus_callback_check_and_init(msg, &itr, NULL))
2216 t = dbus_message_iter_get_arg_type(&itr);
2217 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
2219 ERR("missing name in property changed signal");
2223 dbus_message_iter_get_basic(&itr, &name);
2225 dbus_message_iter_next(&itr);
2226 t = dbus_message_iter_get_arg_type(&itr);
2227 if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
2229 ERR("missing value in property changed signal");
2233 dbus_message_iter_recurse(&itr, &v_itr);
2234 t = dbus_message_iter_get_arg_type(&v_itr);
2236 if (t == DBUS_TYPE_ARRAY)
2238 value = e_bluez_element_iter_get_array(&v_itr, name);
2240 else if (t != DBUS_TYPE_INVALID)
2242 dbus_message_iter_get_basic(&v_itr, &value);
2246 ERR("property has invalid type %s", name);
2250 r = _e_bluez_element_property_value_add(element, name, t, value);
2253 ERR("failed to add property value %s (%c)", name, t);
2257 INF("property value changed %s (%c)", name, t);
2262 _e_bluez_element_listeners_call(element);
2266 * Register the given path, possible creating and element and return it.
2268 * This will check if path is already registered, in that case the
2269 * exiting element is returned. If it was not registered yet, a new
2270 * element is created, registered and returned.
2272 * This call will not add extra references to the object.
2274 * @param path the path to register the element
2276 * @return the registered object, no references are added.
2279 e_bluez_element_register(const char *path, const char *interface)
2281 E_Bluez_Element *element;
2283 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2284 EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
2286 element = eina_hash_find(elements, path);
2290 element = e_bluez_element_new(path, interface);
2294 if (!eina_hash_add(elements, element->path, element))
2296 ERR("could not add element %s to hash, delete it.", path);
2297 e_bluez_element_free(element);
2301 element->signal_handler =
2302 e_dbus_signal_handler_add
2303 (e_bluez_conn, e_bluez_system_bus_name_get(),
2304 element->path, element->interface, "PropertyChanged",
2305 _e_bluez_element_property_changed_callback, element);
2307 e_bluez_element_event_add(E_BLUEZ_EVENT_ELEMENT_ADD, element);
2313 _e_bluez_element_event_unregister_and_free(void *data __UNUSED__, void *ev)
2315 E_Bluez_Element *element = ev;
2316 e_bluez_element_unref(element);
2320 _e_bluez_element_unregister_internal(E_Bluez_Element *element)
2322 if (element->signal_handler)
2324 e_dbus_signal_handler_del(e_bluez_conn, element->signal_handler);
2325 element->signal_handler = NULL;
2328 ecore_event_add(E_BLUEZ_EVENT_ELEMENT_DEL, element,
2329 _e_bluez_element_event_unregister_and_free, NULL);
2333 * Forget about the given element.
2335 * This will remove the element from the pool of known objects, then
2336 * add an E_BLUEZ_EVENT_ELEMENT_DEL and after that will unreference it,
2337 * possible freeing it.
2339 * @param element element to forget about. Its reference will be removed.
2342 e_bluez_element_unregister(E_Bluez_Element *element)
2348 eina_hash_del_by_key(elements, element->path);
2352 * Remove all known elements.
2354 * This will remove all known elements but will NOT add any
2355 * E_BLUEZ_EVENT_ELEMENT_DEL to main loop.
2357 * This is just useful to make sure next e_bluez_manager_sync_elements()
2358 * will not leave any stale elements. This is unlikely to happen, as
2359 * E_Bluez is supposed to catch all required events to avoid stale elements.
2362 e_bluez_manager_clear_elements(void)
2364 e_bluez_elements_shutdown();
2365 e_bluez_elements_init();
2369 * Creates elements hash.
2371 * This has no init counter since its already guarded by other code.
2375 e_bluez_elements_init(void)
2377 EINA_SAFETY_ON_FALSE_RETURN(!elements);
2379 eina_hash_string_superfast_new(EINA_FREE_CB
2380 (_e_bluez_element_unregister_internal));
2384 e_bluez_elements_shutdown(void)
2386 EINA_SAFETY_ON_FALSE_RETURN(!!elements);
2387 eina_hash_free(elements);
2391 static inline Eina_Bool
2392 _e_bluez_element_is(const E_Bluez_Element *element, const char *interface)
2394 return element->interface == interface;
2398 e_bluez_element_is_adapter(const E_Bluez_Element *element)
2400 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
2401 return _e_bluez_element_is(element, e_bluez_iface_adapter);
2405 e_bluez_element_is_device(const E_Bluez_Element *element)
2407 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
2408 return _e_bluez_element_is(element, e_bluez_iface_device);