/** * up_tool_do_monitor: **/ static gboolean up_tool_do_monitor (UpClient *client) { GPtrArray *devices; guint i; g_print ("Monitoring activity from the power daemon. Press Ctrl+C to cancel.\n"); g_signal_connect (client, "device-added", G_CALLBACK (up_tool_device_added_cb), NULL); g_signal_connect (client, "device-removed", G_CALLBACK (up_tool_device_removed_cb), NULL); g_signal_connect (client, "notify", G_CALLBACK (up_tool_changed_cb), NULL); devices = up_client_get_devices (client); for (i=0; i < devices->len; i++) { UpDevice *device; device = g_ptr_array_index (devices, i); g_signal_connect (device, "notify", G_CALLBACK (up_tool_device_changed_cb), NULL); } g_main_loop_run (loop); return FALSE; }
static void update_sb(UpClient *client) { guint u; guint bat_count = 0; gboolean ac_online = FALSE; for(u = 0; u < MAX_BATTERIES; u++) { sbe_batteries[u].sbe_visible = 0; } GPtrArray *devices = up_client_get_devices(client); for(u = 0; u < devices->len; u++) { UpDevice *device = (UpDevice*)g_ptr_array_index(devices, u); UpDeviceKind kind; g_object_get(device, "kind", &kind, NULL); if(kind == UP_DEVICE_KIND_LINE_POWER) { gboolean online; g_object_get(device, "online", &online, NULL); sbe_printf(&sbe_ac, "AC %s", (online ? "on" : "off")); if(online) { ac_online = TRUE; } } if(kind == UP_DEVICE_KIND_BATTERY) { if(bat_count < MAX_BATTERIES) { struct sb_entry *sbe = &sbe_batteries[bat_count]; gboolean bat_empty = FALSE; gboolean bat_charging = FALSE; gboolean bat_discharging = FALSE; guint state; double energy_rate; double energy_full; double energy_now; g_object_get(device, "state", &state, "energy", &energy_now, "energy-full", &energy_full, "energy-rate", &energy_rate, NULL); const char *str; switch(state) { case UP_DEVICE_STATE_CHARGING: if(energy_rate > 0.0) { bat_charging = TRUE; } str = "chrg"; break; case UP_DEVICE_STATE_DISCHARGING: if(energy_rate > 0.0) { bat_discharging = TRUE; } str = "dsch"; break; case UP_DEVICE_STATE_EMPTY: bat_empty = TRUE; str = "empt"; break; case UP_DEVICE_STATE_FULLY_CHARGED: str = "full"; break; case UP_DEVICE_STATE_PENDING_CHARGE: case UP_DEVICE_STATE_PENDING_DISCHARGE: str = "idle"; break; default: str = "unkn"; break; } double percent = (energy_now / energy_full) * 100.0; sbe_printf(sbe, "B%d %s %.1f%%", bat_count, str, percent); sbe->sbe_visible = 1; if(bat_empty) { sbe->sbe_background = COLOR_RED; } else if(bat_charging) { sbe->sbe_background = COLOR_YELLOW; } else if(bat_discharging) { if(percent < 5.0) { sbe->sbe_background = COLOR_RED; } else if(percent < 15.0) { sbe->sbe_background = COLOR_YELLOW; } else { sbe->sbe_background = COLOR_GREEN; } } else { sbe->sbe_background = 0x444444; } bat_count++; } } } if(ac_online) { sbe_ac.sbe_background = COLOR_GREEN; } else { sbe_ac.sbe_background = 0x444444; } sb_update(&sb); }
/** * main: **/ int main (int argc, char **argv) { gint retval = EXIT_FAILURE; guint i; GOptionContext *context; gboolean opt_dump = FALSE; gboolean opt_wakeups = FALSE; gboolean opt_enumerate = FALSE; gboolean opt_monitor = FALSE; gchar *opt_show_info = FALSE; gboolean opt_version = FALSE; gboolean ret; GError *error = NULL; gchar *text = NULL; UpClient *client; UpDevice *device; const GOptionEntry entries[] = { { "enumerate", 'e', 0, G_OPTION_ARG_NONE, &opt_enumerate, _("Enumerate objects paths for devices"), NULL }, { "dump", 'd', 0, G_OPTION_ARG_NONE, &opt_dump, _("Dump all parameters for all objects"), NULL }, { "wakeups", 'w', 0, G_OPTION_ARG_NONE, &opt_wakeups, _("Get the wakeup data"), NULL }, { "monitor", 'm', 0, G_OPTION_ARG_NONE, &opt_monitor, _("Monitor activity from the power daemon"), NULL }, { "monitor-detail", 0, 0, G_OPTION_ARG_NONE, &opt_monitor_detail, _("Monitor with detail"), NULL }, { "show-info", 'i', 0, G_OPTION_ARG_STRING, &opt_show_info, _("Show information about object path"), NULL }, { "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, "Print version of client and daemon", NULL }, { NULL } }; g_type_init (); context = g_option_context_new ("UPower tool"); g_option_context_add_main_entries (context, entries, NULL); g_option_context_add_group (context, egg_debug_get_option_group ()); g_option_context_parse (context, &argc, &argv, NULL); g_option_context_free (context); loop = g_main_loop_new (NULL, FALSE); client = up_client_new (); if (opt_version) { gchar *daemon_version; g_object_get (client, "daemon-version", &daemon_version, NULL); g_print ("UPower client version %s\n" "UPower daemon version %s\n", PACKAGE_VERSION, daemon_version); g_free (daemon_version); retval = 0; goto out; } /* wakeups */ if (opt_wakeups) { up_tool_show_wakeups (); retval = EXIT_SUCCESS; goto out; } if (opt_enumerate || opt_dump) { GPtrArray *devices; ret = up_client_enumerate_devices_sync (client, NULL, &error); if (!ret) { egg_warning ("failed to enumerate: %s", error->message); goto out; } devices = up_client_get_devices (client); for (i=0; i < devices->len; i++) { device = (UpDevice*) g_ptr_array_index (devices, i); if (opt_enumerate) { g_print ("%s\n", up_device_get_object_path (device)); } else { g_print ("Device: %s\n", up_device_get_object_path (device)); text = up_device_to_text (device); g_print ("%s\n", text); g_free (text); } } g_ptr_array_unref (devices); if (opt_dump) { g_print ("Daemon:\n"); up_client_print (client); } retval = EXIT_SUCCESS; goto out; } if (opt_monitor || opt_monitor_detail) { ret = up_client_enumerate_devices_sync (client, NULL, &error); if (!ret) { egg_warning ("failed to enumerate: %s", error->message); goto out; } if (!up_tool_do_monitor (client)) goto out; retval = EXIT_SUCCESS; goto out; } if (opt_show_info != NULL) { device = up_device_new (); ret = up_device_set_object_path_sync (device, opt_show_info, NULL, &error); if (!ret) { g_print ("failed to set path: %s\n", error->message); g_error_free (error); } else { text = up_device_to_text (device); g_print ("%s\n", text); g_free (text); } g_object_unref (device); retval = EXIT_SUCCESS; goto out; } out: g_object_unref (client); return retval; }
/* This function currently exists to allow the multiple batteries supported * by the upower backend to appear as a single composite battery device (since * at the current time this is all that battstat supports). * * This entire function is filled with logic to make multiple batteries * appear as one "composite" battery. Comments included as appropriate. * * For more information about some of the assumptions made in the following * code please see the following mailing list post and the resulting thread: * * http://lists.freedesktop.org/archives/hal/2005-July/002841.html */ void battstat_upower_get_battery_info( BatteryStatus *status ) { GPtrArray *devices = up_client_get_devices( upc ); /* The calculation to get overall percentage power remaining is as follows: * * Sum( Current charges ) / Sum( Full Capacities ) * * We can't just take an average of all of the percentages since this * doesn't deal with the case that one battery might have a larger * capacity than the other. * * In order to do this calculation, we need to keep a running total of * current charge and full capacities. */ double current_charge_total = 0, full_capacity_total = 0; /* Record the time remaining as reported by upower. This is used in the event * that the system has exactly one battery (since, then, upower is capable * of providing an accurate time remaining report and we should trust it.) */ gint64 remaining_time = 0; /* The total (dis)charge rate of the system is the sum of the rates of * the individual batteries. */ double rate_total = 0; /* We need to know if we should report the composite battery as present * at all. The logic is that if at least one actual battery is installed * then the composite battery will be reported to exist. */ int present = 0; /* We need to know if we are on AC power or not. Eventually, we can look * at the AC adaptor upower devices to determine that. For now, we assume that * if any battery is discharging then we must not be on AC power. Else, by * default, we must be on AC. */ int on_ac_power = 1; /* Finally, we consider the composite battery to be "charging" if at least * one of the actual batteries in the system is charging. */ int charging = 0; /* A list iterator. */ GSList *item; /* For each physical battery bay... */ int i; for( i = 0; i < devices->len; i++ ) { UpDevice *upd = g_ptr_array_index( devices, i ); int type, state; double current_charge, full_capacity, rate; gint64 time_to_full, time_to_empty; g_object_get( upd, "kind", &type, "state", &state, "energy", ¤t_charge, "energy-full", &full_capacity, "energy-rate", &rate, "time-to-full", &time_to_full, "time-to-empty", &time_to_empty, NULL ); /* Only count batteries here */ if (type != UP_DEVICE_KIND_BATTERY) continue; /* At least one battery present -> composite battery is present. */ present++; /* At least one battery charging -> composite battery is charging. */ if( state == UP_DEVICE_STATE_CHARGING ) charging = 1; /* At least one battery is discharging -> we're not on AC. */ if( state == UP_DEVICE_STATE_DISCHARGING ) on_ac_power = 0; /* Sum the totals for current charge, design capacity, (dis)charge rate. */ current_charge_total += current_charge; full_capacity_total += full_capacity; rate_total += rate; /* Record remaining time too, incase this is the only battery. */ remaining_time = (state == UP_DEVICE_STATE_DISCHARGING ? time_to_empty : time_to_full); } if( !present || full_capacity_total <= 0 || (charging && !on_ac_power) ) { /* Either no battery is present or something has gone horribly wrong. * In either case we must return that the composite battery is not * present. */ status->present = FALSE; status->percent = 0; status->minutes = -1; status->on_ac_power = TRUE; status->charging = FALSE; g_ptr_array_unref( devices ); return; } /* Else, our composite battery is present. */ status->present = TRUE; /* As per above, overall charge is: * * Sum( Current charges ) / Sum( Full Capacities ) */ status->percent = ( current_charge_total / full_capacity_total ) * 100.0 + 0.5; if( present == 1 ) { /* In the case of exactly one battery, report the time remaining figure * from upower directly since it might have come from an authorative source * (ie: the PMU or APM subsystem). * * upower gives remaining time in seconds with a 0 to mean that the * remaining time is unknown. Battstat uses minutes and -1 for * unknown time remaining. */ if( remaining_time == 0 ) status->minutes = -1; else status->minutes = (remaining_time + 30) / 60; } /* Rest of cases to deal with multiple battery systems... */ else if( !on_ac_power && rate_total != 0 ) { /* Then we're discharging. Calculate time remaining until at zero. */ double remaining; remaining = current_charge_total; remaining /= rate_total; status->minutes = (int) floor( remaining * 60.0 + 0.5 ); } else if( charging && rate_total != 0 ) { /* Calculate time remaining until charged. For systems with more than * one battery, this code is very approximate. The assumption is that if * one battery reaches full charge before the other that the other will * start charging faster due to the increase in available power (similar * to how a laptop will charge faster if you're not using it). */ double remaining; remaining = full_capacity_total - current_charge_total; if( remaining < 0 ) remaining = 0; remaining /= rate_total; status->minutes = (int) floor( remaining * 60.0 + 0.5 ); } else { /* On AC power and not charging -or- rate is unknown. */ status->minutes = -1; } /* These are simple and well-explained above. */ status->charging = charging; status->on_ac_power = on_ac_power; g_ptr_array_unref( devices ); }
static void set_ac_battery_ui_mode (CcPowerPanel *self) { gboolean has_batteries = FALSE; gboolean has_lid = FALSE; #if ! UP_CHECK_VERSION(0,99,0) gboolean ret; GError *error = NULL; #endif GPtrArray *devices; guint i; UpDevice *device; UpDeviceKind kind; CcPowerPanelPrivate *priv = self->priv; #if ! UP_CHECK_VERSION(0,99,0) /* this is sync, but it's cached in the daemon and so quick */ ret = up_client_enumerate_devices_sync (self->priv->up_client, NULL, &error); if (!ret) { g_warning ("failed to get device list: %s", error->message); g_error_free (error); goto out; } #endif devices = up_client_get_devices (self->priv->up_client); for (i=0; i<devices->len; i++) { device = g_ptr_array_index (devices, i); g_object_get (device, "kind", &kind, NULL); if (kind == UP_DEVICE_KIND_BATTERY || kind == UP_DEVICE_KIND_UPS) { has_batteries = TRUE; break; } } g_ptr_array_unref (devices); has_lid = up_client_get_lid_is_present (self->priv->up_client); #if ! UP_CHECK_VERSION(0,99,0) out: #endif if (has_lid) { gtk_widget_show(WID("combobox_lid_ac")); gtk_widget_show(WID("label_lid_action")); } else { gtk_widget_hide (WID("combobox_lid_ac")); gtk_widget_hide (WID("label_lid_action")); } if (has_batteries) { gtk_widget_show (WID("label_header_battery")); gtk_widget_show (WID("label_header_ac")); gtk_widget_show (WID("combobox_sleep_battery")); gtk_widget_show (WID("combobox_display_battery")); gtk_widget_show (WID("label_critical")); gtk_widget_show (WID("combobox_critical")); gtk_widget_show (WID("separator_indicator")); gtk_widget_show (WID("frame_battery")); } else { gtk_widget_hide (WID("label_header_battery")); gtk_widget_hide (WID("label_header_ac")); gtk_widget_hide (WID("combobox_sleep_battery")); gtk_widget_hide (WID("combobox_display_battery")); gtk_widget_hide (WID("label_critical")); gtk_widget_hide (WID("combobox_critical")); gtk_widget_hide (WID("separator_indicator")); gtk_widget_hide (WID("frame_battery")); } if (has_lid && has_batteries) { gtk_widget_show (WID("combobox_lid_battery")); } else { gtk_widget_hide (WID("combobox_lid_battery")); } }