torios-dev team mailing list archive
-
torios-dev team
-
Mailing list archive
-
Message #00245
upower battery monitor
Hi,
My development computer is running 14.10, and for some reason the
xfce4-power-manager doesn't display a tray icon in JWM :(
So... I borrowed some stuff from sdesk, and I have a scratched together
tray icon for power 'management'
Basically it displays an icon (from your current icon theme) and if you
pass in:
-s
it will suspend when you close the lid (if your computer can suspend).
if you pass in
-v
it will print out lots of information.
you will need to install all the depends:
build-essential libgtk2.0-dev libgcc1 libupower-glib1 libgio2.0-cil-dev
maybe more... but run this:
gcc `pkg-config gtk+-x11-2.0 --cflags` `pkg-config upower-glib --cflags`
`pkg-config gobject-2.0 --cflags` -finline-small-functions
-ffunction-sections -fdata-sections -fmerge-all-constants
-fomit-frame-pointer -mno-accumulate-outgoing-args -fno-unwind-tables
-fno-asynchronous-unwind-tables -Os batteri.c -o batteri -lgobject-2.0
-lglib-2.0 -lgio-2.0 -lupower-glib -lgtk-x11-2.0 -lgdk-x11-2.0
and you will have a tiny binary (around 14 Kb) that uses aroung 4MB
memory to monitor your power and suspend. Very simple! I eventually
want to make some sort of menu for it, or configuration... but it
solved my problem :)
Sorry if the code is kinda wacky... I don't normally write C, and the
code needs to be cleaned up and done a bit better (i.e comments, no
global variables).
But it works on newer systems, since proc2imdgd doesn't use upower :(
And our polkit rules mean it should work on ToriOS just fine!!
--
Regards
-Israel
ToriOS Team
/*
gcc `pkg-config gtk+-x11-2.0 --cflags` `pkg-config upower-glib --cflags` `pkg-config gobject-2.0 --cflags` batt.c -o batteri -lgobject-2.0 -lglib-2.0 -lgio-2.0 -lupower-glib -lgtk-x11-2.0 -lgdk-x11-2.0
*/
#include <gtk/gtk.h>
#include <libupower-glib/upower.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const gchar* icon;
char tooltip_message[150];
int debug = 0;
int suspend = 0;
GtkStatusIcon *si;
const char* path_icon;
const char* battery_full;
const char* battery_good;
const char* battery_low;
const char* battery_caution;
const char* battery_empty;
//sdesk
static void run(gpointer s){
printf("yo");
}
void key_press_event(GtkWidget *widget, GdkEventKey *event){
g_print("KEY=%s\n",gdk_keyval_name(event->keyval));
}
void button_press_event(GtkWidget *widget, GdkEventButton *event){
g_print("BUTTON=%d\nBUTTON_X=%d\nBUTTON_Y=%d\n",event->button,
(unsigned int) event->x, (unsigned int)event->y);
}
static void leftclick(GtkStatusIcon *si, gpointer s){run(s);}
static void rightclick(GtkStatusIcon *si, guint b,guint a_t, gpointer s){run(s);}
/** refreshes the status icon image from file if it changes */
static void refresh(GFileMonitor *monitor, GFile *file, GFile *to_file, GFileMonitorEvent event, gpointer si){
gtk_status_icon_set_from_file(si,g_file_get_path(file));
}
/** refreshes the background image from file if it changes */
static void bg_refresh(GFileMonitor *monitor, GFile *file, GFile *to_file, GFileMonitorEvent event, gpointer bg){
gtk_image_set_from_file(GTK_IMAGE(bg),g_file_get_path(file));
}
/** gets a new mouse over tooltip from file if it changes */
static void updatetooltip(GFileMonitor *monitor, GFile *file, GFile *to_file, GFileMonitorEvent event, gpointer si){
gtk_status_icon_set_tooltip_markup(si, g_mapped_file_get_contents(g_mapped_file_new(g_file_get_path(file), FALSE, NULL)));
}
//kseds
static void report_combined_battery_status(UpClient* client){
GPtrArray* devices = up_client_get_devices(client);
if (!devices)
return;
// single battery data
UpDevice* device;
UpDeviceKind kind;
UpDeviceState state;
gboolean is_present;
gdouble energy, energy_empty, energy_full, energy_rate;
gdouble percentage;
/*
* Combined battery data.
*/
int num_battery_devices = 0;
// Set the initial state to unknown - there might be no battery devices.
UpDeviceState c_state = 0;
gdouble c_energy = 0, c_energy_full = 0, c_energy_rate = 0;
/*
* Final battery data.
*/
UpDeviceState f_state;
gdouble f_percentage = 0;
gdouble f_charging_time = 0;
gdouble f_discharging_time = 0;
int i;
for (i = 0; i < devices->len; i++) {
device = g_ptr_array_index(devices, i);
g_object_get(device,
"kind", &kind,
"state", &state,
"is-present", &is_present,
"energy", &energy,
"energy-empty", &energy_empty,
"energy-full", &energy_full,
"energy-rate", &energy_rate, NULL);
// Only take into account present battery devices
if (kind != UP_DEVICE_KIND_BATTERY || !is_present)
continue;
num_battery_devices++;
// Only update the state if the current combined state does not indicate
// that a battery device is discharging to keep the system running
//if (c_state != UP_DEVICE_STATE_DISCHARGING)
// c_state = state;
c_state |= (1 << state);
c_energy += energy - energy_empty;
c_energy_full += energy_full;
c_energy_rate += energy_rate;
}
g_ptr_array_unref(devices);
if (c_energy_full > 0)
f_percentage = c_energy / c_energy_full;
if (c_state & (1 << UP_DEVICE_STATE_DISCHARGING))
f_state = UP_DEVICE_STATE_DISCHARGING;
else if (c_state & (1 << UP_DEVICE_STATE_CHARGING))
f_state = UP_DEVICE_STATE_CHARGING;
else if (c_state & (1 << UP_DEVICE_STATE_FULLY_CHARGED))
f_state = UP_DEVICE_STATE_FULLY_CHARGED;
else
f_state = UP_DEVICE_STATE_UNKNOWN;
float percent = f_percentage * 100.0;
const char* status = up_device_state_to_string(c_state);
if (f_state == UP_DEVICE_STATE_DISCHARGING){
status = up_device_state_to_string(c_state);
f_discharging_time = 3600.0 * c_energy / c_energy_rate;
//set icon based on percent
battery_full = "battery-full";
battery_good = "battery-good";
battery_low = "battery-low";
battery_caution = "battery-caution";
battery_empty = "battery-empty";
if(percentage > 80){icon = battery_full;} /// /usr/share/icons/Numix/scalable/status/
else if(percent > 40){icon = battery_good;}
else if(percent > 20){icon = battery_low;}
else if(percent > 5){icon = battery_caution;}
else {icon = battery_empty;}
sprintf(tooltip_message, "State:\t %s \nPercentage: %f \nDischarging Time:\t %f \nLevel:\t %f", status, percent, f_discharging_time, f_percentage);
}
else if (f_state == UP_DEVICE_STATE_CHARGING){
status = up_device_state_to_string(c_state);
f_charging_time = 3600.0 * (c_energy_full - c_energy) / c_energy_rate;
//set icon based on percent
if(percent > 80){icon = "battery-full-charging";} //battery-full-charging";}//-symbolic
else if(percent > 40){icon = "battery-good-charging";}
else if(percent > 20){icon = "battery-low-charging";}
else{icon = "battery-caution-charging";}
sprintf(tooltip_message, "State:\t %s \nPercentage: %f \nCharging Time:\t %f \nLevel:\t %f", status, percent, f_charging_time, f_percentage);
}
int num_batteries = num_battery_devices;
if (!num_battery_devices) {
g_message("\tno battery status data to report, ending");
return;
}
const char* chargin = "";
if(UP_DEVICE_STATE_DISCHARGING){chargin="true";}
else{chargin="false";}
//const char* chargin = //UP_DEVICE_STATE_DISCHARGING ? "false" : "true";
//g_message("\t%s /* charging */,", f_state == UP_DEVICE_STATE_DISCHARGING ? "false" : "true");
float chargin_time = f_charging_time;
float dischargin_time = f_discharging_time;
float percent_level = f_percentage;
//sprintf(tooltip_message, "Level:\t%f", percent_level);
make_icon(icon);
const gchar* gtooltip_message = tooltip_message;
tooltip(tooltip_message);
if(debug){
g_message("\t%d battery device(s) present", num_battery_devices);
g_message(" ");
g_message("State: %s", up_device_state_to_string(c_state));
g_message("Percentage: %f", f_percentage * 100.0);
g_message(" ");
g_message("\t%f /* chargingTime */,", f_charging_time);
g_message("\t%f /* dischargingTime */,", f_discharging_time);
g_message("\t%f /* level */", f_percentage);
g_message("--- end of report ---");
g_message("Icon: %s", icon);
}
}
static void power_device_alteration(UpClient* client, UpDevice* device, gpointer data)
{
UpDeviceKind kind;
g_object_get(device,
"kind", &kind, NULL);
if (kind != UP_DEVICE_KIND_BATTERY)
return;
report_combined_battery_status(client);
}
int make_icon(const gchar* name_of_icon){
if (name_of_icon==NULL){return 2;}
char temp_icon[70];
sprintf(temp_icon,"%s-symbolic", name_of_icon);
name_of_icon=temp_icon;
GdkPixbuf *pix = NULL;
pix = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
name_of_icon,
32,
GTK_ICON_LOOKUP_USE_BUILTIN,
NULL);
gtk_status_icon_set_from_pixbuf(si,pix);
/*
gtk_status_icon_set_from_icon_name(si, name_of_icon);
*/
}
int tooltip(const gchar* tooltip_message){
/** tooltip **/
gtk_status_icon_set_tooltip_markup(si, tooltip_message);
}
int main(int argc, char* argv[]){
char i=1;
gtk_init (&argc, &argv);
while(i<argc && argv[i][0]=='-'){
switch(argv[i][1]){
case 'v':
debug = 1;
break;
case 's':
suspend=1;
break;
case 'h':
g_printerr(
"usage:\n%s [-d] [-s]\n"
" -v turn Verbose mode on\n"
" -s turn suspend on (if possible)\n"
,argv[0]);
return 1;
break;
default:
break;
}
i++;
}
GError* error = NULL;
const char* right="right";
const char* left="left";
UpClient* powerClient = up_client_new();
gboolean is_lid = up_client_get_lid_is_present (powerClient);
gboolean can_suspend=up_client_get_can_suspend (powerClient);
if(suspend*is_lid*can_suspend){
g_message("can suspend");
if(up_client_get_lid_is_closed (powerClient)){
if(up_client_suspend_sync (powerClient,NULL,&error)){
g_message("Suspending");
}
}
}
if (!up_client_enumerate_devices_sync(powerClient, NULL, &error))
g_error("unable to enumerate devices - %s", error->message);
si = gtk_status_icon_new ();
icon = "battery-good";
make_icon(icon);
report_combined_battery_status(powerClient);
g_signal_connect(powerClient, "device-changed",
G_CALLBACK(power_device_alteration), NULL);
g_signal_connect(powerClient, "device-added",
G_CALLBACK(power_device_alteration), NULL);
g_signal_connect(powerClient, "device-removed",
G_CALLBACK(power_device_alteration), NULL);
g_signal_connect(G_OBJECT(si), "activate", G_CALLBACK(leftclick),(gpointer) left);
g_signal_connect(G_OBJECT(si), "popup-menu", G_CALLBACK(rightclick), (gpointer) right);
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
g_object_unref(powerClient);
return 0;
}