diff --git a/configure.ac b/configure.ac index 475c29472..a15c4978a 100644 --- a/configure.ac +++ b/configure.ac @@ -548,6 +548,7 @@ PKG_CHECK_MODULES(E, [ eina >= ${efl_version} dbus-1 edbus >= ${efl_version} + edbus2 >= ${efl_version} eio >= ${efl_version} $hal_mount $eeze_mount @@ -570,6 +571,7 @@ efreet-trash >= ${efl_version} \ eina >= ${efl_version} \ dbus-1 \ edbus >= ${efl_version} \ +edbus2 \ eio >= ${efl_version} \ $hal_mount \ $udisks_mount \ diff --git a/src/bin/e.h b/src/bin/e.h index 8a06c4ff3..f996b7521 100644 --- a/src/bin/e.h +++ b/src/bin/e.h @@ -113,6 +113,7 @@ void *alloca (size_t); # include # include # include +# include # include # ifdef HAVE_HAL diff --git a/src/modules/Makefile_battery.am b/src/modules/Makefile_battery.am index fa6c0576d..d3b39dc14 100644 --- a/src/modules/Makefile_battery.am +++ b/src/modules/Makefile_battery.am @@ -18,7 +18,7 @@ else if HAVE_OPENBSD battery_module_la_SOURCES += battery/e_mod_openbsd.c else -battery_module_la_SOURCES += battery/e_mod_dbus.c +battery_module_la_SOURCES += battery/e_mod_upower.c endif endif diff --git a/src/modules/battery/e_mod_dbus.c b/src/modules/battery/e_mod_dbus.c deleted file mode 100644 index 06f4c7e88..000000000 --- a/src/modules/battery/e_mod_dbus.c +++ /dev/null @@ -1,390 +0,0 @@ -#include "e.h" -#include "e_mod_main.h" - -static void _battery_dbus_battery_props(void *data, void *reply_data, DBusError *error); -static void _battery_dbus_ac_adapter_props(void *data, void *reply_data, DBusError *error); -static void _battery_dbus_battery_property_changed(void *data, DBusMessage *msg); -static void _battery_dbus_battery_add(const char *udi); -static void _battery_dbus_battery_del(const char *udi); -static void _battery_dbus_ac_adapter_add(const char *udi); -static void _battery_dbus_ac_adapter_del(const char *udi); -static void _battery_dbus_find_battery(void *user_data, void *reply_data, DBusError *err); -static void _battery_dbus_find_ac(void *user_data, void *reply_data, DBusError *err); -static void _battery_dbus_is_battery(void *user_data, void *reply_data, DBusError *err); -static void _battery_dbus_is_ac_adapter(void *user_data, void *reply_data, DBusError *err); -static void _battery_dbus_dev_add(void *data, DBusMessage *msg); -static void _battery_dbus_dev_del(void *data, DBusMessage *msg); - -extern Eina_List *device_batteries; -extern Eina_List *device_ac_adapters; -extern double init_time; - -static E_DBus_Connection *e_dbus_conn = NULL; - -int -_battery_dbus_start(void) -{ - e_dbus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM); - if (!e_dbus_conn) return 0; - // FIXME: e_dbus doesn't allow us to track this pending call - e_hal_manager_find_device_by_capability - (e_dbus_conn, "battery", _battery_dbus_find_battery, NULL); - e_hal_manager_find_device_by_capability - (e_dbus_conn, "ac_adapter", _battery_dbus_find_ac, NULL); - battery_config->dbus.dev_add = - e_dbus_signal_handler_add(e_dbus_conn, E_HAL_SENDER, - E_HAL_MANAGER_PATH, - E_HAL_MANAGER_INTERFACE, - "DeviceAdded", _battery_dbus_dev_add, NULL); - battery_config->dbus.dev_del = - e_dbus_signal_handler_add(e_dbus_conn, E_HAL_SENDER, - E_HAL_MANAGER_PATH, - E_HAL_MANAGER_INTERFACE, - "DeviceRemoved", _battery_dbus_dev_del, NULL); - init_time = ecore_time_get(); - return 1; -} - -void -_battery_dbus_stop(void) -{ - Ac_Adapter *ac; - Battery *bat; - - if (!e_dbus_conn) return; - - if (battery_config->dbus.have) - { - dbus_pending_call_cancel(battery_config->dbus.have); - battery_config->dbus.have = NULL; - } - if (battery_config->dbus.dev_add) - { - e_dbus_signal_handler_del(e_dbus_conn, battery_config->dbus.dev_add); - battery_config->dbus.dev_add = NULL; - } - if (battery_config->dbus.dev_del) - { - e_dbus_signal_handler_del(e_dbus_conn, battery_config->dbus.dev_del); - battery_config->dbus.dev_del = NULL; - } - EINA_LIST_FREE(device_ac_adapters, ac) - { - e_dbus_signal_handler_del(e_dbus_conn, ac->prop_change); - eina_stringshare_del(ac->udi); - eina_stringshare_del(ac->product); - free(ac); - } - EINA_LIST_FREE(device_batteries, bat) - { - e_dbus_signal_handler_del(e_dbus_conn, bat->prop_change); - eina_stringshare_del(bat->udi); - eina_stringshare_del(bat->technology); - eina_stringshare_del(bat->type); - eina_stringshare_del(bat->charge_units); - eina_stringshare_del(bat->model); - eina_stringshare_del(bat->vendor); - free(bat); - } - e_dbus_connection_close(e_dbus_conn); - e_dbus_conn = NULL; -} - -static void -_battery_dbus_battery_props(void *data, void *reply_data, DBusError *error __UNUSED__) -{ - E_Hal_Properties *ret = reply_data; - Battery *bat = data; - int err = 0; - const char *str; - - if (dbus_error_is_set(error)) - { - dbus_error_free(error); - return; - } - if (!ret) return; - -#undef GET_BOOL -#undef GET_INT -#undef GET_STR -#define GET_BOOL(val, s) bat->val = e_hal_property_bool_get(ret, s, &err) -#define GET_INT(val, s) bat->val = e_hal_property_int_get(ret, s, &err) -#define GET_STR(val, s) \ - if (bat->val) eina_stringshare_del(bat->val); \ - bat->val = NULL; \ - str = e_hal_property_string_get(ret, s, &err); \ - if (str) \ - { \ - bat->val = eina_stringshare_ref(str); \ - } - - GET_BOOL(present, "battery.present"); - GET_STR(technology, "battery.reporting.technology"); - GET_STR(model, "battery.model"); - GET_STR(vendor, "battery.vendor"); - GET_STR(type, "battery.type"); - GET_STR(charge_units, "battery.reporting.unit"); - GET_INT(percent, "battery.charge_level.percentage"); - GET_BOOL(can_charge, "battery.is_rechargeable"); - GET_INT(current_charge, "battery.charge_level.current"); - GET_INT(charge_rate, "battery.charge_level.rate"); - GET_INT(design_charge, "battery.charge_level.design"); - GET_INT(last_full_charge, "battery.charge_level.last_full"); - if (e_hal_property_bool_get(ret, "battery.rechargeable.is_charging", &err)) - { - bat->charging = 1; - GET_INT(time_full, "battery.remaining_time"); - bat->time_left = -1; - } - else - { - bat->charging = 0; - GET_INT(time_left, "battery.remaining_time"); - bat->time_full = -1; - } - bat->got_prop = 1; - _battery_device_update(); -} - -static void -_battery_dbus_ac_adapter_props(void *data, void *reply_data, DBusError *error __UNUSED__) -{ - E_Hal_Properties *ret = reply_data; - Ac_Adapter *ac = data; - int err = 0; - const char *str; - - if (dbus_error_is_set(error)) - { - dbus_error_free(error); - return; - } - if (!ret) return; - -#undef GET_BOOL -#undef GET_STR -#define GET_BOOL(val, s) ac->val = e_hal_property_bool_get(ret, s, &err) -#define GET_STR(val, s) \ - if (ac->val) eina_stringshare_del(ac->val); \ - ac->val = NULL; \ - str = e_hal_property_string_get(ret, s, &err); \ - if (str) \ - { \ - ac->val = eina_stringshare_ref(str); \ - } - - GET_BOOL(present, "ac_adapter.present"); - GET_STR(product, "info.product"); - _battery_device_update(); -} - -static void -_battery_dbus_battery_property_changed(void *data, DBusMessage *msg __UNUSED__) -{ - // FIXME: e_dbus doesn't allow us to track this pending call - e_hal_device_get_all_properties(e_dbus_conn, ((Battery *)data)->udi, - _battery_dbus_battery_props, data); -} - -static void -_battery_dbus_ac_adapter_property_changed(void *data, DBusMessage *msg __UNUSED__) -{ - // FIXME: e_dbus doesn't allow us to track this pending call - e_hal_device_get_all_properties(e_dbus_conn, ((Ac_Adapter *)data)->udi, - _battery_dbus_ac_adapter_props, data); -} - -static void -_battery_dbus_battery_add(const char *udi) -{ - Battery *bat; - - bat = _battery_battery_find(udi); - if (!bat) - { - bat = E_NEW(Battery, 1); - if (!bat) return; - bat->udi = eina_stringshare_add(udi); - device_batteries = eina_list_append(device_batteries, bat); - bat->prop_change = - e_dbus_signal_handler_add(e_dbus_conn, E_HAL_SENDER, udi, - E_HAL_DEVICE_INTERFACE, "PropertyModified", - _battery_dbus_battery_property_changed, - bat); - } - // FIXME: e_dbus doesn't allow us to track this pending call - e_hal_device_get_all_properties(e_dbus_conn, udi, - _battery_dbus_battery_props, bat); - - _battery_device_update(); -} - -static void -_battery_dbus_battery_del(const char *udi) -{ - Battery *bat; - - bat = _battery_battery_find(udi); - if (bat) - { - e_dbus_signal_handler_del(e_dbus_conn, bat->prop_change); - device_batteries = eina_list_remove(device_batteries, bat); - eina_stringshare_del(bat->udi); - eina_stringshare_del(bat->technology); - eina_stringshare_del(bat->type); - eina_stringshare_del(bat->charge_units); - eina_stringshare_del(bat->model); - eina_stringshare_del(bat->vendor); - free(bat); - return; - } - _battery_device_update(); -} - -static void -_battery_dbus_ac_adapter_add(const char *udi) -{ - Ac_Adapter *ac; - - ac = E_NEW(Ac_Adapter, 1); - if (!ac) return; - ac->udi = eina_stringshare_add(udi); - device_ac_adapters = eina_list_append(device_ac_adapters, ac); - ac->prop_change = - e_dbus_signal_handler_add(e_dbus_conn, E_HAL_SENDER, udi, - E_HAL_DEVICE_INTERFACE, "PropertyModified", - _battery_dbus_ac_adapter_property_changed, - ac); - // FIXME: e_dbus doesn't allow us to track this pending call - e_hal_device_get_all_properties(e_dbus_conn, udi, - _battery_dbus_ac_adapter_props, ac); - _battery_device_update(); -} - -static void -_battery_dbus_ac_adapter_del(const char *udi) -{ - Ac_Adapter *ac; - - ac = _battery_ac_adapter_find(udi); - if (ac) - { - e_dbus_signal_handler_del(e_dbus_conn, ac->prop_change); - device_ac_adapters = eina_list_remove(device_ac_adapters, ac); - eina_stringshare_del(ac->udi); - eina_stringshare_del(ac->product); - free(ac); - return; - } - _battery_device_update(); -} - -static void -_battery_dbus_find_battery(void *user_data __UNUSED__, void *reply_data, DBusError *err __UNUSED__) -{ - Eina_List *l; - char *device; - E_Hal_Manager_Find_Device_By_Capability_Return *ret; - - ret = reply_data; - if (dbus_error_is_set(err)) - { - dbus_error_free(err); - return; - } - if (!ret) return; - - if (eina_list_count(ret->strings) < 1) return; - EINA_LIST_FOREACH(ret->strings, l, device) - _battery_dbus_battery_add(device); -} - -static void -_battery_dbus_find_ac(void *user_data __UNUSED__, void *reply_data, DBusError *err __UNUSED__) -{ - Eina_List *l; - char *device; - E_Hal_Manager_Find_Device_By_Capability_Return *ret; - - ret = reply_data; - if (dbus_error_is_set(err)) - { - dbus_error_free(err); - return; - } - if (!ret) return; - - if (eina_list_count(ret->strings) < 1) return; - EINA_LIST_FOREACH(ret->strings, l, device) - _battery_dbus_ac_adapter_add(device); -} - -static void -_battery_dbus_is_battery(void *user_data, void *reply_data, DBusError *err) -{ - char *udi = user_data; - E_Hal_Device_Query_Capability_Return *ret; - - ret = reply_data; - if (dbus_error_is_set(err)) - { - dbus_error_free(err); - goto error; - } - if (!ret) goto error; - if (ret->boolean) - _battery_dbus_battery_add(udi); -error: - eina_stringshare_del(udi); -} - -static void -_battery_dbus_is_ac_adapter(void *user_data, void *reply_data, DBusError *err) -{ - char *udi = user_data; - E_Hal_Device_Query_Capability_Return *ret; - - ret = reply_data; - if (dbus_error_is_set(err)) - { - dbus_error_free(err); - goto error; - } - if (!ret) goto error; - - if (ret->boolean) - _battery_dbus_ac_adapter_add(udi); -error: - eina_stringshare_del(udi); -} - -static void -_battery_dbus_dev_add(void *data __UNUSED__, DBusMessage *msg) -{ - DBusError err; - char *udi = NULL; - - dbus_error_init(&err); - dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID); - if (!udi) return; - // FIXME: e_dbus doesn't allow us to track this pending call - e_hal_device_query_capability(e_dbus_conn, udi, "battery", - _battery_dbus_is_battery, (void *)eina_stringshare_add(udi)); - e_hal_device_query_capability(e_dbus_conn, udi, "ac_adapter", - _battery_dbus_is_ac_adapter, (void *)eina_stringshare_add(udi)); -} - -static void -_battery_dbus_dev_del(void *data __UNUSED__, DBusMessage *msg) -{ - DBusError err; - char *udi = NULL; - - dbus_error_init(&err); - dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID); - if (!udi) return; - _battery_dbus_battery_del(udi); - _battery_dbus_ac_adapter_del(udi); -} - diff --git a/src/modules/battery/e_mod_main.c b/src/modules/battery/e_mod_main.c index 866dbe6f0..3d44d815f 100644 --- a/src/modules/battery/e_mod_main.c +++ b/src/modules/battery/e_mod_main.c @@ -88,9 +88,6 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style) #ifdef HAVE_EEZE eeze_init(); -#elif !defined __OpenBSD__ - e_dbus_init(); - e_hal_init(); #endif evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, @@ -109,9 +106,6 @@ _gc_shutdown(E_Gadcon_Client *gcc) #ifdef HAVE_EEZE eeze_shutdown(); -#elif !defined __OpenBSD__ - e_hal_shutdown(); - e_dbus_shutdown(); #endif inst = gcc->data; @@ -380,7 +374,7 @@ _battery_config_updated(void) #elif defined __OpenBSD__ ok = _battery_openbsd_start(); #else - ok = _battery_dbus_start(); + ok = _battery_upower_start(); #endif } if (ok) return; @@ -858,7 +852,7 @@ e_modapi_shutdown(E_Module *m __UNUSED__) #elif defined __OpenBSD__ _battery_openbsd_stop(); #else - _battery_dbus_stop(); + _battery_upower_stop(); #endif #ifdef HAVE_ENOTIFY diff --git a/src/modules/battery/e_mod_main.h b/src/modules/battery/e_mod_main.h index 61c8a7747..f4c96b58d 100644 --- a/src/modules/battery/e_mod_main.h +++ b/src/modules/battery/e_mod_main.h @@ -4,7 +4,7 @@ #ifdef HAVE_EEZE # include #else -# include +# include #endif typedef struct _Config Config; @@ -58,15 +58,6 @@ struct _Config #if defined HAVE_EEZE || defined __OpenBSD__ Eina_Bool fuzzy; int fuzzcount; -#else - struct { - // FIXME: on bat_conf del dbus_pending_call_cancel(dbus.have); - // then set dbus.have to NULL - DBusPendingCall *have; - // FIXME: on bat_conf del e_dbus_signal_handler_del() these - E_DBus_Signal_Handler *dev_add; - E_DBus_Signal_Handler *dev_del; - } dbus; #endif }; @@ -78,9 +69,6 @@ struct _Battery const char *udi; #if defined HAVE_EEZE || defined __OpenBSD__ Ecore_Poller *poll; -#else - E_DBus_Signal_Handler *prop_change; - Eina_Bool can_charge:1; #endif Eina_Bool present:1; Eina_Bool charging:1; @@ -108,6 +96,7 @@ struct _Battery const char *model; const char *vendor; Eina_Bool got_prop:1; + EDBus_Proxy *proxy; #ifdef __OpenBSD__ int * mib; #endif @@ -116,11 +105,9 @@ struct _Battery struct _Ac_Adapter { const char *udi; -#ifndef HAVE_EEZE - E_DBus_Signal_Handler *prop_change; -#endif Eina_Bool present:1; const char *product; + EDBus_Proxy *proxy; #ifdef __OpenBSD__ int * mib; #endif @@ -136,8 +123,8 @@ void _battery_udev_stop(void); /* end e_mod_udev.c */ #elif !defined __OpenBSD__ /* in e_mod_dbus.c */ -int _battery_dbus_start(void); -void _battery_dbus_stop(void); +int _battery_upower_start(void); +void _battery_upower_stop(void); /* end e_mod_dbus.c */ #else /* in e_mod_openbsd.c */ diff --git a/src/modules/battery/e_mod_upower.c b/src/modules/battery/e_mod_upower.c new file mode 100644 index 000000000..2013f313f --- /dev/null +++ b/src/modules/battery/e_mod_upower.c @@ -0,0 +1,363 @@ +#include "e.h" +#include "e_mod_main.h" + +#define BUS "org.freedesktop.UPower" +#define PATH "/org/freedesktop/UPower" +#define IFACE "org.freedesktop.UPower" + +extern Eina_List *device_batteries; +extern Eina_List *device_ac_adapters; +extern double init_time; + +static EDBus_Connection *conn; +static EDBus_Proxy *upower_proxy; + +static void _battery_free(Battery *bat); +static void _ac_free(Ac_Adapter *ac); + +static void +_ac_get_all_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending __UNUSED__) +{ + Ac_Adapter *ac = data; + EDBus_Message_Iter *array, *dict, *variant; + + if (edbus_message_error_get(msg, NULL, NULL)) + return; + if (!edbus_message_arguments_get(msg, "a{sv}", &array)) + return; + while (edbus_message_iter_get_and_next(array, 'e', &dict)) + { + char *key; + if (!edbus_message_iter_arguments_get(dict, "sv", &key, &variant)) + continue; + if (!strcmp(key, "Online")) + { + Eina_Bool b; + edbus_message_iter_arguments_get(variant, "b", &b); + ac->present = b; + } + } + _battery_device_update(); +} + +static void +_ac_changed_cb(void *data, const EDBus_Message *msg __UNUSED__) +{ + Ac_Adapter *ac = data; + edbus_proxy_property_get_all(ac->proxy, _ac_get_all_cb, ac); +} + +static void +_process_ac(EDBus_Proxy *proxy) +{ + Ac_Adapter *ac; + ac = E_NEW(Ac_Adapter, 1); + if (!ac) goto error; + ac->proxy = proxy; + ac->udi = eina_stringshare_add(edbus_object_path_get(edbus_proxy_object_get(proxy))); + edbus_proxy_property_get_all(proxy, _ac_get_all_cb, ac); + edbus_proxy_signal_handler_add(proxy, "Changed", _ac_changed_cb, ac); + device_ac_adapters = eina_list_append(device_ac_adapters, ac); + return; +error: + edbus_object_unref(edbus_proxy_object_get(proxy)); + return; +} + +static const char *bat_techologys[] = { + "Unknown", + "Lithium ion", + "Lithium polymer", + "Lithium iron phosphate", + "Lead acid", + "Nickel cadmium", + "Nickel metal hydride" +}; + +static void +_bat_get_all_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending __UNUSED__) +{ + Battery *bat = data; + EDBus_Message_Iter *array, *dict, *variant; + + bat->got_prop = EINA_TRUE; + if (edbus_message_error_get(msg, NULL, NULL)) + return; + if (!edbus_message_arguments_get(msg, "a{sv}", &array)) + return; + while (edbus_message_iter_get_and_next(array, 'e', &dict)) + { + char *key; + if (!edbus_message_iter_arguments_get(dict, "sv", &key, &variant)) + continue; + if (!strcmp(key, "IsPresent")) + { + Eina_Bool b; + edbus_message_iter_arguments_get(variant, "b", &b); + bat->present = b; + } + else if (!strcmp(key, "TimeToEmpty")) + { + int64_t empty = 0; + edbus_message_iter_arguments_get(variant, "x", &empty); + bat->time_left = (int) empty; + if (empty > 0) + bat->charging = EINA_FALSE; + else + bat->charging = EINA_TRUE; + } + else if (!strcmp(key, "Percentage")) + { + double d; + edbus_message_iter_arguments_get(variant, "d", &d); + bat->percent = (int) d; + } + else if (!strcmp(key, "Energy")) + { + double d; + edbus_message_iter_arguments_get(variant, "d", &d); + bat->current_charge = (int) d; + } + else if (!strcmp(key, "EnergyFullDesign")) + { + double d; + edbus_message_iter_arguments_get(variant, "d", &d); + bat->design_charge = (int) d; + } + else if (!strcmp(key, "EnergyFull")) + { + double d; + edbus_message_iter_arguments_get(variant, "d", &d); + bat->last_full_charge = (int) d; + } + else if (!strcmp(key, "TimeToFull")) + { + int64_t full = 0; + edbus_message_iter_arguments_get(variant, "x", &full); + bat->time_full = (int) full; + } + else if (!strcmp(key, "Technology")) + { + uint32_t tec = 0; + edbus_message_iter_arguments_get(variant, "u", &tec); + bat->technology = bat_techologys[tec]; + } + else if (!strcmp(key, "Model")) + { + char *txt; + if (!edbus_message_iter_arguments_get(variant, "s", &txt)) + continue; + if (bat->model) + eina_stringshare_del(bat->model); + bat->model = eina_stringshare_add(txt); + } + else if (!strcmp(key, "Vendor")) + { + char *txt; + if (!edbus_message_iter_arguments_get(variant, "s", &txt)) + continue; + if (bat->vendor) + eina_stringshare_del(bat->vendor); + bat->vendor = eina_stringshare_add(txt); + } + } + _battery_device_update(); +} + +static void +_bat_changed_cb(void *data, const EDBus_Message *msg __UNUSED__) +{ + Battery *bat = data; + edbus_proxy_property_get_all(bat->proxy, _bat_get_all_cb, bat); +} + +static void +_process_battery(EDBus_Proxy *proxy) +{ + Battery *bat; + + bat = E_NEW(Battery, 1); + if (!bat) + { + edbus_object_unref(edbus_proxy_object_get(proxy)); + return; + } + + bat->proxy = proxy; + bat->udi = eina_stringshare_add(edbus_object_path_get(edbus_proxy_object_get(proxy))); + edbus_proxy_property_get_all(proxy, _bat_get_all_cb, bat); + edbus_proxy_signal_handler_add(proxy, "Changed", _bat_changed_cb, bat); + device_batteries = eina_list_append(device_batteries, bat); + _battery_device_update(); +} + +static void +_device_type_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending __UNUSED__) +{ + EDBus_Proxy *proxy = data; + EDBus_Message_Iter *variant; + EDBus_Object *obj; + unsigned int type = 0; + char *signature; + + if (edbus_message_error_get(msg, NULL, NULL)) + goto error; + + if (!edbus_message_arguments_get(msg, "v", &variant)) + goto error; + + signature = edbus_message_iter_signature_get(variant); + if (!signature || signature[0] != 'u') + goto error; + + edbus_message_iter_arguments_get(variant, "u", &type); + if (type == 1) + _process_ac(proxy); + else if (type == 2) + _process_battery(proxy); + else + goto error; + + return; +error: + obj = edbus_proxy_object_get(proxy); + edbus_proxy_unref(proxy); + edbus_object_unref(obj); + return; +} + +static void +_process_enumerate_path(char *path) +{ + EDBus_Object *obj; + EDBus_Proxy *proxy; + + if (!path || !path[0]) + return; + + obj = edbus_object_get(conn, BUS, path); + EINA_SAFETY_ON_FALSE_RETURN(obj); + proxy = edbus_proxy_get(obj, "org.freedesktop.UPower.Device"); + edbus_proxy_property_get(proxy, "Type", _device_type_cb, proxy); +} + +static void +_enumerate_cb(void *data __UNUSED__, const EDBus_Message *msg, EDBus_Pending *pending __UNUSED__) +{ + char *path; + EDBus_Message_Iter *array; + if (edbus_message_error_get(msg, NULL, NULL)) + return; + + if (!edbus_message_arguments_get(msg, "ao", &array)) + return; + + while (edbus_message_iter_get_and_next(array, 'o', &path)) + _process_enumerate_path(path); +} + +static void +_device_added_cb(void *data __UNUSED__, const EDBus_Message *msg) +{ + char *path; + if (!edbus_message_arguments_get(msg, "o", &path)) + return; + _process_enumerate_path(path); +} + +static void +_device_removed_cb(void *data __UNUSED__, const EDBus_Message *msg) +{ + Battery *bat; + Ac_Adapter *ac; + char *path; + + if (!edbus_message_arguments_get(msg, "o", &path)) + return; + bat = _battery_battery_find(path); + if (bat) + { + _battery_free(bat); + _battery_device_update(); + return; + } + ac = _battery_ac_adapter_find(path); + if (ac) + { + _ac_free(ac); + _battery_device_update(); + } +} + +int +_battery_upower_start(void) +{ + EDBus_Object *obj; + + edbus_init(); + conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SYSTEM); + EINA_SAFETY_ON_NULL_RETURN_VAL(conn, 0); + + obj = edbus_object_get(conn, BUS, PATH); + EINA_SAFETY_ON_NULL_GOTO(obj, obj_error); + upower_proxy = edbus_proxy_get(obj, IFACE); + EINA_SAFETY_ON_NULL_GOTO(upower_proxy, proxy_error); + edbus_proxy_call(upower_proxy, "EnumerateDevices", _enumerate_cb, NULL, -1, ""); + edbus_proxy_signal_handler_add(upower_proxy, "DeviceAdded", _device_added_cb, NULL); + edbus_proxy_signal_handler_add(upower_proxy, "DeviceRemoved", _device_removed_cb, NULL); + return 1; + +proxy_error: + edbus_object_unref(obj); +obj_error: + edbus_connection_unref(conn); + return 0; +} + +void +_battery_upower_stop(void) +{ + Eina_List *list, *list2; + Battery *bat; + Ac_Adapter *ac; + EDBus_Object *obj; + + EINA_LIST_FOREACH_SAFE(device_batteries, list, list2, bat) + _battery_free(bat); + EINA_LIST_FOREACH_SAFE(device_ac_adapters, list, list2, ac) + _ac_free(ac); + + obj = edbus_proxy_object_get(upower_proxy); + edbus_proxy_unref(upower_proxy); + edbus_object_unref(obj); + edbus_connection_unref(conn); + edbus_shutdown(); +} + +static void +_battery_free(Battery *bat) +{ + EDBus_Object *obj = edbus_proxy_object_get(bat->proxy); + edbus_proxy_unref(bat->proxy); + edbus_object_unref(obj); + + device_batteries = eina_list_remove(device_batteries, bat); + eina_stringshare_del(bat->udi); + if (bat->model) + eina_stringshare_del(bat->model); + if (bat->vendor) + eina_stringshare_del(bat->vendor); + free(bat); +} + +static void +_ac_free(Ac_Adapter *ac) +{ + EDBus_Object *obj = edbus_proxy_object_get(ac->proxy); + edbus_proxy_unref(ac->proxy); + edbus_object_unref(obj); + + device_ac_adapters = eina_list_remove(device_ac_adapters, ac); + eina_stringshare_del(ac->udi); + free(ac); +}