enlightenment_my/src/modules/battery/e_mod_upower.c

364 lines
9.6 KiB
C
Raw Normal View History

#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);
}