wmbiff: EXAMINE before STATUS
[dockapps.git] / wmbattery / upower.c
blob6db4fd10a359e5bfff16e03edf0263cbae654b3e
1 /* Not particularly good interface to hal, for programs that used to use
2 * apm.
3 */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <upower.h>
10 #include "apm.h"
12 #define MAX_RETRIES 3
14 static UpClient * up;
16 struct context {
17 int current;
18 int needed;
19 guint state;
20 int percentage;
21 gboolean ac;
22 int time;
25 static void get_devinfo(gpointer device, gpointer result)
27 gboolean online;
28 gdouble percentage;
29 guint state;
30 guint kind;
31 gint64 time_to_empty;
32 gint64 time_to_full;
33 struct context *ctx = result;
35 g_object_get(G_OBJECT(device), "percentage", &percentage,
36 "online", &online,
37 "state", &state,
38 "kind", &kind,
39 "time-to-empty", &time_to_empty,
40 "time-to-full", &time_to_full,
41 NULL);
42 if (kind == UP_DEVICE_KIND_BATTERY) {
43 if (ctx->current == ctx->needed) {
44 ctx->percentage = (int)percentage;
45 ctx->state = state;
46 if (time_to_empty)
47 ctx->time = time_to_empty;
48 else
49 ctx->time = time_to_full;
51 ctx->current++;
52 } else if (kind == UP_DEVICE_KIND_LINE_POWER) {
53 ctx->ac |= online;
57 int upower_supported(void)
59 up = up_client_new();
61 if (!up) {
62 return 0;
63 } else {
64 GPtrArray *devices = up_client_get_devices(up);
66 if (!devices) {
67 return 0;
68 } else {
69 g_ptr_array_unref(devices);
70 return 1;
75 /* Fill the passed apm_info struct. */
76 int upower_read(int battery, apm_info *info)
78 GPtrArray *devices = NULL;
79 static int retries = 0;
81 up = up_client_new();
83 if (!up)
84 return -1;
86 #if !UP_CHECK_VERSION(0, 9, 99)
87 /* Allow a battery that was not present before to appear. */
88 up_client_enumerate_devices_sync(up, NULL, NULL);
89 #endif
91 devices = up_client_get_devices(up);
93 if (!devices) {
94 retries++;
95 if (retries < MAX_RETRIES)
96 return 0; /* fine immediately after hibernation */
97 else
98 return -1;
101 retries = 0;
102 info->battery_flags = 0;
103 info->using_minutes = 0;
105 struct context ctx = {
106 .current = 0,
107 .needed = battery - 1,
108 .state = UP_DEVICE_STATE_UNKNOWN,
109 .percentage = -1,
110 .ac = FALSE,
111 .time = -1
114 g_ptr_array_foreach(devices, &get_devinfo, &ctx);
116 info->ac_line_status = ctx.ac;
118 /* remaining_time and charge_level.percentage are not a mandatory
119 * keys, so if not present, -1 will be returned */
120 info->battery_time = ctx.time;
121 info->battery_percentage = ctx.percentage;
122 if (ctx.state == UP_DEVICE_STATE_DISCHARGING) {
123 info->battery_status = BATTERY_STATUS_CHARGING;
124 /* charge_level.warning and charge_level.low are not
125 * required to be available; this is good enough */
126 if (info->battery_percentage < 1)
127 info->battery_status = BATTERY_STATUS_CRITICAL;
128 else if (info->battery_percentage < 10)
129 info->battery_status = BATTERY_STATUS_LOW;
130 } else if (info->ac_line_status && ctx.state == UP_DEVICE_STATE_CHARGING) {
131 info->battery_status = BATTERY_STATUS_CHARGING;
132 info->battery_flags = info->battery_flags | BATTERY_FLAGS_CHARGING;
133 } else if (info->ac_line_status) {
134 /* Must be fully charged. */
135 info->battery_status = BATTERY_STATUS_HIGH;
136 } else {
137 fprintf(stderr, "unknown battery state\n");
140 if (ctx.percentage < 0) {
141 info->battery_percentage = 0;
142 info->battery_time = 0;
143 info->battery_status = BATTERY_STATUS_ABSENT;
146 g_ptr_array_free(devices, TRUE);
147 return 0;