21625f40b5
I tried to get the latest versions from dockapps.org, but I haven't tested any of them. More dockapps will be added as time permits.
891 lines
20 KiB
C
891 lines
20 KiB
C
/*
|
|
* Copyright (c) 2007 Daniel Borca All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <X11/Xlib.h>
|
|
#include <X11/xpm.h>
|
|
|
|
#include "dockapp.h"
|
|
#include "sensors.h"
|
|
#include "system.h"
|
|
#include "util.h"
|
|
|
|
#include "font.h"
|
|
#include "frame0.xpm"
|
|
#include "frame1.xpm"
|
|
#include "frame2.xpm"
|
|
#include "frame3.xpm"
|
|
#include "frame4.xpm"
|
|
#include "frame5.xpm"
|
|
|
|
|
|
#define DockApp App.d
|
|
|
|
#define NELEM(tab) (const int)(sizeof(tab) / sizeof((tab)[0]))
|
|
|
|
#define INSIDE(x, y, xmin, ymin, xmax, ymax) ((x) >= (xmin) && (x) <= (xmax) && (y) >= (ymin) && (y) <= (ymax))
|
|
|
|
#define SWITCH_FRAME(a, n) \
|
|
do { \
|
|
if ((a)->frames[n].v) { \
|
|
(a)->page = n; \
|
|
(a)->millis = (a)->frames[n].u; \
|
|
(a)->handle = handle_frame##n; \
|
|
(a)->update = update_frame##n; \
|
|
(a)->frames[n].p = 0; \
|
|
(a)->update(a, 1); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define SCROLL_START(start, num_items, max_items) \
|
|
do { \
|
|
if ((start) > (num_items) - (max_items)) { \
|
|
(start) = (num_items) - (max_items); \
|
|
} \
|
|
if ((start) < 0) { \
|
|
(start) = 0; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define MAX_DISPLAY_CPU 2
|
|
#define MAX_DISPLAY_NET 2
|
|
#define MAX_DISPLAY_TEMP 5
|
|
|
|
|
|
typedef struct {
|
|
Pixmap f;
|
|
Pixmap m;
|
|
int v;
|
|
int u;
|
|
int p;
|
|
} FRAME;
|
|
|
|
typedef struct {
|
|
int row;
|
|
int height;
|
|
const int *width;
|
|
const int *offset;
|
|
} FONT;
|
|
|
|
typedef struct APP {
|
|
DOCKAPP d;
|
|
FONT fontx9;
|
|
FONT fontx8;
|
|
FONT fontx7;
|
|
FONT fontx6;
|
|
FONT meter2;
|
|
Pixmap font;
|
|
SENSOR *list;
|
|
FRAME *frames;
|
|
void (*handle) (struct APP *a, XEvent *event);
|
|
void (*update) (const struct APP *a, int full);
|
|
int page;
|
|
int millis;
|
|
} APP;
|
|
|
|
|
|
static int
|
|
draw_text (const APP *a, const FONT *font, const char *str, int dx, int dy)
|
|
{
|
|
const DOCKAPP *d = (DOCKAPP *)a;
|
|
|
|
int ch;
|
|
|
|
while ((ch = *(unsigned char *)str++)) {
|
|
int w = font->width[ch];
|
|
dockapp_copy_area(d, a->font, font->offset[ch], font->row, w, font->height, dx, dy);
|
|
dx += w;
|
|
}
|
|
|
|
/*printf("dx = %d\n", dx);*/
|
|
return dx;
|
|
}
|
|
|
|
|
|
static void
|
|
draw_meter (const APP *a, const FONT *meter, int num, int den, int dx, int dy)
|
|
{
|
|
const DOCKAPP *d = (DOCKAPP *)a;
|
|
|
|
const int w = meter->width[0];
|
|
const int h = meter->height;
|
|
int col = 1 * w;
|
|
|
|
if (num) {
|
|
int ratio = w * num / den;
|
|
|
|
XCopyArea(d->display, a->font, a->font, d->gc,
|
|
1 * w, meter->row,
|
|
w, h,
|
|
2 * w, meter->row);
|
|
XCopyArea(d->display, a->font, a->font, d->gc,
|
|
0 * w, meter->row,
|
|
ratio, h,
|
|
2 * w, meter->row);
|
|
col = 2 * w;
|
|
}
|
|
dockapp_copy_area(d, a->font, col, meter->row, w, h, dx, dy);
|
|
}
|
|
|
|
|
|
static void handle_frame0 (APP *a, XEvent *event);
|
|
#define handle_frame1 handle_frameN
|
|
#define handle_frame2 handle_frameN
|
|
#define handle_frame3 handle_frameN
|
|
#define handle_frame4 handle_frameN
|
|
#define handle_frame5 handle_frameN
|
|
static void handle_frameN (APP *a, XEvent *event);
|
|
static void update_frame0 (const APP *a, int full);
|
|
static void update_frame1 (const APP *a, int full);
|
|
static void update_frame2 (const APP *a, int full);
|
|
static void update_frame3 (const APP *a, int full);
|
|
static void update_frame4 (const APP *a, int full);
|
|
static void update_frame5 (const APP *a, int full);
|
|
|
|
|
|
static void
|
|
handle_frame0 (APP *a, XEvent *event)
|
|
{
|
|
XButtonPressedEvent *bevent;
|
|
|
|
switch (event->type) {
|
|
case ButtonPress:
|
|
bevent = (XButtonPressedEvent *)event;
|
|
switch (bevent->button & 0xFF) {
|
|
case Button1:
|
|
/*printf("handle0: b1\n");*/
|
|
if (INSIDE(bevent->x, bevent->y, 4, 4, 10, 10)) {
|
|
/*printf("next: %d %d\n", bevent->x, bevent->y);*/
|
|
break;
|
|
}
|
|
if (INSIDE(bevent->x, bevent->y, 50, 4, 56, 10)) {
|
|
/*printf("quit: %d %d\n", bevent->x, bevent->y);*/
|
|
((DOCKAPP *)a)->quit = True;
|
|
break;
|
|
}
|
|
if (INSIDE(bevent->x, bevent->y, 1, 1, 59, 13)) {
|
|
/*printf("time: %d %d\n", bevent->x, bevent->y);*/
|
|
SWITCH_FRAME(a, 1);
|
|
break;
|
|
}
|
|
if (INSIDE(bevent->x, bevent->y, 1, 16, 59, 27)) {
|
|
/*printf("cpu : %d %d\n", bevent->x, bevent->y);*/
|
|
SWITCH_FRAME(a, 2);
|
|
break;
|
|
}
|
|
if (INSIDE(bevent->x, bevent->y, 1, 30, 29, 41)) {
|
|
/*printf("wifi: %d %d\n", bevent->x, bevent->y);*/
|
|
SWITCH_FRAME(a, 3);
|
|
break;
|
|
}
|
|
if (INSIDE(bevent->x, bevent->y, 32, 30, 59, 41)) {
|
|
/*printf("temp: %d %d\n", bevent->x, bevent->y);*/
|
|
SWITCH_FRAME(a, 4);
|
|
break;
|
|
}
|
|
if (INSIDE(bevent->x, bevent->y, 1, 44, 59, 59)) {
|
|
/*printf("batt: %d %d\n", bevent->x, bevent->y);*/
|
|
SWITCH_FRAME(a, 5);
|
|
break;
|
|
}
|
|
break;
|
|
case Button2:
|
|
/*printf("handle0: b2\n");*/
|
|
break;
|
|
case Button3:
|
|
/*printf("handle0: b3\n");*/
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
handle_frameN (APP *a, XEvent *event)
|
|
{
|
|
XButtonPressedEvent *bevent;
|
|
|
|
switch (event->type) {
|
|
case ButtonPress:
|
|
bevent = (XButtonPressedEvent *)event;
|
|
switch (bevent->button & 0xFF) {
|
|
case Button1:
|
|
/*printf("handleN: b1\n");*/
|
|
SWITCH_FRAME(a, 0);
|
|
break;
|
|
case Button2:
|
|
/*printf("handleN: b2\n");*/
|
|
break;
|
|
case Button3:
|
|
/*printf("handleN: b3\n");*/
|
|
break;
|
|
case Button4:
|
|
/*printf("handle0: b4\n");*/
|
|
a->frames[a->page].p--;
|
|
a->update(a, 0);
|
|
break;
|
|
case Button5:
|
|
/*printf("handle0: b5\n");*/
|
|
a->frames[a->page].p++;
|
|
a->update(a, 0);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
update_frame0 (const APP *a, int full)
|
|
{
|
|
const DOCKAPP *d = (DOCKAPP *)a;
|
|
const FRAME *frame = &a->frames[0];
|
|
|
|
char buf[16];
|
|
|
|
time_t at;
|
|
struct tm *bt;
|
|
|
|
static CPUSTAT avg;
|
|
|
|
int wifi;
|
|
|
|
int temp;
|
|
int crit;
|
|
|
|
int on_line;
|
|
int battery;
|
|
BATSTAT total;
|
|
|
|
if (full) {
|
|
if (!d->iswindowed) {
|
|
dockapp_set_shape(d, frame->m);
|
|
}
|
|
|
|
dockapp_copy_area(d, frame->f, 0, 0, d->width, d->height, 0, 0);
|
|
}
|
|
|
|
at = time(NULL);
|
|
bt = localtime(&at);
|
|
sprintf(buf, "%2d:%02d", bt->tm_hour, bt->tm_min);
|
|
draw_text(a, &a->fontx9, buf, 15, 2);
|
|
|
|
if (system_get_cpu_load(0, &avg, NULL) > 0) {
|
|
sprintf(buf, "__CPU__%3d%%", avg.used);
|
|
} else {
|
|
strcpy(buf, " _____");
|
|
}
|
|
draw_text(a, &a->fontx8, buf, 1, 17);
|
|
|
|
if (system_get_best_wifi(&wifi)) {
|
|
sprintf(buf, "%3d\xF7", wifi);
|
|
} else {
|
|
strcpy(buf, " \xF7");
|
|
}
|
|
draw_text(a, &a->fontx8, buf, 0, 31);
|
|
|
|
if (system_get_max_temp(a->list, &temp, &crit)) {
|
|
sprintf(buf, "%3d\xF8", temp);
|
|
} else {
|
|
strcpy(buf, " \xF8");
|
|
}
|
|
draw_text(a, &a->fontx8, buf, 31, 31);
|
|
|
|
battery = system_get_battery(a->list, 0, &total, NULL);
|
|
on_line = system_get_ac_adapter(a->list);
|
|
if (battery) {
|
|
int ratio = 100 * total.curr_cap / total.full_cap;
|
|
int ch = 0xB0;
|
|
if (ratio >= 33) {
|
|
ch++;
|
|
}
|
|
if (ratio >= 66) {
|
|
ch++;
|
|
}
|
|
if (total.rate) {
|
|
if (on_line) {
|
|
/* charging */
|
|
int estimate = 60 * (total.full_cap - total.curr_cap) / total.rate;
|
|
int hours = estimate / 60;
|
|
if (hours > 99) {
|
|
hours = 99;
|
|
}
|
|
sprintf(buf, "%c__%2d:%02d\xAE\x98", ch, hours, estimate % 60);
|
|
} else {
|
|
/* discharging */
|
|
int estimate = 60 * total.curr_cap / total.rate;
|
|
int hours = estimate / 60;
|
|
if (hours > 99) {
|
|
hours = 99;
|
|
}
|
|
sprintf(buf, "%c__%2d:%02d__ ", ch, hours, estimate % 60);
|
|
}
|
|
} else {
|
|
if (on_line) {
|
|
/* bat + AC */
|
|
sprintf(buf, "%c__%3d%%___\x98", ch, ratio);
|
|
} else {
|
|
/* bat */
|
|
sprintf(buf, "%c__%3d%%___ ", ch, ratio);
|
|
}
|
|
}
|
|
draw_meter(a, &a->meter2, total.curr_cap, total.full_cap, 3, 55);
|
|
} else {
|
|
if (on_line) {
|
|
/* only AC */
|
|
strcpy(buf, " _____\x98");
|
|
} else {
|
|
/* nada */
|
|
strcpy(buf, " _____ ");
|
|
}
|
|
draw_meter(a, &a->meter2, 0, 0, 3, 55);
|
|
}
|
|
draw_text(a, &a->fontx9, buf, 2, 44);
|
|
|
|
dockapp_update(d);
|
|
}
|
|
|
|
|
|
static void
|
|
update_frame1 (const APP *a, int full)
|
|
{
|
|
const DOCKAPP *d = (DOCKAPP *)a;
|
|
const FRAME *frame = &a->frames[1];
|
|
|
|
char buf[16];
|
|
|
|
time_t at;
|
|
struct tm *bt;
|
|
|
|
int days, hours, mins;
|
|
|
|
static const char *dow[] = {
|
|
"___SUNDAY___",
|
|
"___MONDAY___",
|
|
"__TUESDAY__",
|
|
"WEDNESDAY",
|
|
"_THURSDAY_",
|
|
"___FRIDAY___",
|
|
"_SATURDAY_"
|
|
};
|
|
static const char *mon[] = {
|
|
"JAN", "FEB", "MAR", "APR",
|
|
"MAY", "JUN", "JUL", "AUG",
|
|
"SEP", "OCT", "NOV", "DEC"
|
|
};
|
|
|
|
if (full) {
|
|
if (!d->iswindowed) {
|
|
dockapp_set_shape(d, frame->m);
|
|
}
|
|
|
|
dockapp_copy_area(d, frame->f, 0, 0, d->width, d->height, 0, 0);
|
|
}
|
|
|
|
at = time(NULL);
|
|
bt = localtime(&at);
|
|
draw_text(a, &a->fontx9, dow[bt->tm_wday], 3, 2);
|
|
|
|
sprintf(buf, "%-2d %s", bt->tm_mday, mon[bt->tm_mon]);
|
|
draw_text(a, &a->fontx9, buf, 10, 13);
|
|
|
|
sprintf(buf, "%d", 1900 + bt->tm_year);
|
|
draw_text(a, &a->fontx9, buf, 16, 24);
|
|
|
|
draw_text(a, &a->fontx7, "UPTIME", 15, 39);
|
|
strcpy(buf, " _ _ ");
|
|
if (system_get_uptime(&days, &hours, &mins)) {
|
|
if (days > 999) {
|
|
days = 999;
|
|
}
|
|
sprintf(buf, "%03d_%02d:%02d", days, hours, mins);
|
|
}
|
|
draw_text(a, &a->fontx8, buf, 2, 48);
|
|
|
|
dockapp_update(d);
|
|
}
|
|
|
|
|
|
static void
|
|
update_frame2 (const APP *a, int full)
|
|
{
|
|
const DOCKAPP *d = (DOCKAPP *)a;
|
|
FRAME *frame = &a->frames[2];
|
|
|
|
char buf[16];
|
|
|
|
int speed[8];
|
|
static CPUSTAT load[8];
|
|
int mem_free, mem_total, swp_free, swp_total;
|
|
int i, j, n, k;
|
|
|
|
if (full) {
|
|
if (!d->iswindowed) {
|
|
dockapp_set_shape(d, frame->m);
|
|
}
|
|
|
|
dockapp_copy_area(d, frame->f, 0, 0, d->width, d->height, 0, 0);
|
|
}
|
|
|
|
n = system_get_cpu_speed(NELEM(speed), speed);
|
|
system_get_cpu_load(NELEM(load), NULL, load);
|
|
|
|
SCROLL_START(frame->p, n, MAX_DISPLAY_CPU);
|
|
j = frame->p + MAX_DISPLAY_CPU;
|
|
if (n < MAX_DISPLAY_CPU) {
|
|
while (j > n) {
|
|
j--;
|
|
draw_text(a, &a->fontx7, " ", 2, 2 + j * 20);
|
|
draw_text(a, &a->fontx7, " ", 2, 10 + j * 20);
|
|
}
|
|
}
|
|
|
|
for (k = 0, i = 0; k < j; i++, k++) {
|
|
int r;
|
|
char *gov;
|
|
|
|
if (speed[i] < 0) {
|
|
k--;
|
|
continue;
|
|
}
|
|
|
|
r = k - frame->p;
|
|
|
|
if (r < 0) {
|
|
continue;
|
|
}
|
|
|
|
sprintf(buf, "CPU%d %4d M", i, speed[i]);
|
|
draw_text(a, &a->fontx7, buf, 2, 2 + r * 20);
|
|
|
|
strcpy(buf, " ");
|
|
if (load[i].used >= 0) {
|
|
sprintf(buf, "%3d%%", load[i].used);
|
|
}
|
|
draw_text(a, &a->fontx7, buf, 2, 10 + r * 20);
|
|
|
|
gov = " ";
|
|
if (system_get_cpu_gov(i, sizeof(buf), buf)) {
|
|
if (!strcmp(buf, "performance")) {
|
|
gov = "PERFRM";
|
|
} else if (!strcmp(buf, "powersave")) {
|
|
gov = "PWRSAV";
|
|
} else if (!strcmp(buf, "userspace")) {
|
|
gov = "USRSPC";
|
|
} else if (!strcmp(buf, "ondemand")) {
|
|
gov = "ONDMND";
|
|
} else if (!strcmp(buf, "conservative")) {
|
|
gov = "CONSRV";
|
|
}
|
|
}
|
|
draw_text(a, &a->fontx7, gov, 27, 10 + r * 20);
|
|
}
|
|
|
|
if (system_get_mem_stat(&mem_free, &mem_total, &swp_free, &swp_total)) {
|
|
strcpy(buf, " ");
|
|
if (mem_total) {
|
|
sprintf(buf, "MEM %3d%%", 100 * (mem_total - mem_free) / mem_total);
|
|
}
|
|
draw_text(a, &a->fontx7, buf, 7, 42);
|
|
strcpy(buf, " ");
|
|
if (swp_total) {
|
|
sprintf(buf, "SWP %3d%%", 100 * (swp_total - swp_free) / swp_total);
|
|
}
|
|
draw_text(a, &a->fontx7, buf, 7, 50);
|
|
}
|
|
|
|
dockapp_update(d);
|
|
}
|
|
|
|
|
|
static void
|
|
update_frame3 (const APP *a, int full)
|
|
{
|
|
const DOCKAPP *d = (DOCKAPP *)a;
|
|
FRAME *frame = &a->frames[3];
|
|
|
|
char buf[16];
|
|
|
|
IFSTAT ifs[8];
|
|
int i, j, n;
|
|
|
|
if (full) {
|
|
if (!d->iswindowed) {
|
|
dockapp_set_shape(d, frame->m);
|
|
}
|
|
|
|
dockapp_copy_area(d, frame->f, 0, 0, d->width, d->height, 0, 0);
|
|
}
|
|
|
|
n = system_get_netif(NELEM(ifs), ifs);
|
|
|
|
SCROLL_START(frame->p, n, MAX_DISPLAY_NET);
|
|
j = frame->p + MAX_DISPLAY_NET;
|
|
if (n < MAX_DISPLAY_NET) {
|
|
while (j > n) {
|
|
j--;
|
|
draw_text(a, &a->fontx7, " ", 2, 2 + j * 30);
|
|
draw_text(a, &a->fontx7, " ", 2, 2 + j * 30 + 9);
|
|
draw_text(a, &a->fontx6, " _ _ _ ", 2, 2 + j * 30 + 18);
|
|
}
|
|
}
|
|
|
|
for (i = frame->p; i < j; i++) {
|
|
int r = i - frame->p;
|
|
|
|
strupr(ifs[i].name, ifs[i].name);
|
|
ifs[i].name[6] = '\0';
|
|
if (ifs[i].wlink >= 0) {
|
|
sprintf(buf, "%-6s_%3d\xF7", ifs[i].name, ifs[i].wlink);
|
|
draw_text(a, &a->fontx7, buf, 2, 2 + r * 30);
|
|
strupr(buf, ifs[i].essid);
|
|
buf[11] = '\0';
|
|
} else {
|
|
sprintf(buf, "%-6s_ _", ifs[i].name);
|
|
draw_text(a, &a->fontx7, buf, 2, 2 + r * 30);
|
|
strcpy(buf, " ");
|
|
}
|
|
draw_text(a, &a->fontx7, buf, 2, 2 + r * 30 + 9);
|
|
if (ifs[i].ipv4 != -1) {
|
|
int addr = ifs[i].ipv4;
|
|
sprintf(buf, "%3d.%3d.%3d.%3d", (addr >> 24) & 0xFF, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF);
|
|
} else {
|
|
strcpy(buf, " _ _ _ ");
|
|
}
|
|
draw_text(a, &a->fontx6, buf, 2, 2 + r * 30 + 18);
|
|
}
|
|
|
|
dockapp_update(d);
|
|
}
|
|
|
|
|
|
static void
|
|
update_frame4 (const APP *a, int full)
|
|
{
|
|
const DOCKAPP *d = (DOCKAPP *)a;
|
|
FRAME *frame = &a->frames[4];
|
|
|
|
char buf[16];
|
|
|
|
TEMPSTAT temp[16];
|
|
int i, j, n;
|
|
|
|
if (full) {
|
|
if (!d->iswindowed) {
|
|
dockapp_set_shape(d, frame->m);
|
|
}
|
|
|
|
dockapp_copy_area(d, frame->f, 0, 0, d->width, d->height, 0, 0);
|
|
}
|
|
|
|
n = system_get_temperature(a->list, NELEM(temp), temp);
|
|
|
|
SCROLL_START(frame->p, n, MAX_DISPLAY_TEMP);
|
|
j = frame->p + MAX_DISPLAY_TEMP;
|
|
if (n < MAX_DISPLAY_TEMP) {
|
|
while (j > n) {
|
|
j--;
|
|
draw_text(a, &a->fontx7, " _ ", 1, 1 + j * 12);
|
|
}
|
|
}
|
|
|
|
for (i = frame->p; i < j; i++) {
|
|
int r = i - frame->p;
|
|
|
|
if (!strncmp(temp[i].name, "Core ", 5) && isdigit(temp[i].name[5]) && !temp[i].name[6]) {
|
|
temp[i].name[3] = temp[i].name[5];
|
|
}
|
|
temp[i].name[4] = '\0';
|
|
strupr(temp[i].name, temp[i].name);
|
|
sprintf(buf, "%-4s:%3d\xA7%3d", temp[i].name, temp[i].temp, temp[i].max);
|
|
if (!temp[i].max) {
|
|
int l = strlen(buf);
|
|
buf[--l] = ' ';
|
|
buf[--l] = ' ';
|
|
buf[--l] = ' ';
|
|
}
|
|
draw_text(a, &a->fontx7, buf, 1, 1 + r * 12);
|
|
}
|
|
|
|
dockapp_update(d);
|
|
}
|
|
|
|
|
|
static void
|
|
update_frame5 (const APP *a, int full)
|
|
{
|
|
const DOCKAPP *d = (DOCKAPP *)a;
|
|
const FRAME *frame = &a->frames[5];
|
|
|
|
char buf[16];
|
|
|
|
int on_line;
|
|
int battery;
|
|
BATSTAT total, batt[2];
|
|
|
|
int i;
|
|
|
|
if (full) {
|
|
if (!d->iswindowed) {
|
|
dockapp_set_shape(d, frame->m);
|
|
}
|
|
|
|
dockapp_copy_area(d, frame->f, 0, 0, d->width, d->height, 0, 0);
|
|
}
|
|
|
|
on_line = system_get_ac_adapter(a->list);
|
|
battery = system_get_battery(a->list, NELEM(batt), &total, batt);
|
|
|
|
for (i = 0; i < battery; i++) {
|
|
char *state;
|
|
int ratio = 100 * batt[i].curr_cap / batt[i].full_cap;
|
|
if (batt[i].rate) {
|
|
int estimate;
|
|
int hours;
|
|
if (on_line) {
|
|
estimate = 60 * (batt[i].full_cap - batt[i].curr_cap) / batt[i].rate;
|
|
state = "CHARGING ";
|
|
} else {
|
|
estimate = 60 * batt[i].curr_cap / batt[i].rate;
|
|
state = "DISCHARGING";
|
|
}
|
|
hours = estimate / 60;
|
|
if (hours > 99) {
|
|
hours = 99;
|
|
}
|
|
sprintf(buf, "%3d%% %2d:%02d", ratio, hours, estimate % 60);
|
|
} else {
|
|
sprintf(buf, "%3d%% _ ", ratio);
|
|
state = "STEADY ";
|
|
}
|
|
draw_text(a, &a->fontx7, batt[i].name, 2, 1 + i * 30);
|
|
draw_text(a, &a->fontx7, state, 2, 9 + i * 30);
|
|
draw_text(a, &a->fontx7, buf, 2, 17 + i * 30);
|
|
draw_meter(a, &a->meter2, batt[i].curr_cap, batt[i].full_cap, 3, 25 + i * 30);
|
|
}
|
|
for (; i < 2; i++) {
|
|
draw_text(a, &a->fontx7, " ", 2, 1 + i * 30);
|
|
draw_text(a, &a->fontx7, " ", 2, 9 + i * 30);
|
|
draw_text(a, &a->fontx7, " _ ", 2, 17 + i * 30);
|
|
draw_text(a, &a->fontx7, " ", 2, 20 + i * 30);
|
|
}
|
|
|
|
dockapp_update(d);
|
|
}
|
|
|
|
|
|
static int
|
|
update_text (SENSOR *list)
|
|
{
|
|
(void)list;
|
|
/* XXX cool stuff here */
|
|
}
|
|
|
|
|
|
static int
|
|
run_text (SENSOR *list, unsigned long millis)
|
|
{
|
|
struct timeval timeout;
|
|
fd_set rset;
|
|
|
|
struct stat buf;
|
|
int redir = fstat(STDOUT_FILENO, &buf) == 0 &&
|
|
(S_ISREG(buf.st_mode) || S_ISFIFO(buf.st_mode));
|
|
|
|
for (;;) {
|
|
update_text(list);
|
|
|
|
if (redir) {
|
|
break;
|
|
}
|
|
|
|
printf("not yet implemented -- press Enter to quit\n");
|
|
|
|
timeout.tv_sec = millis / 1000;
|
|
timeout.tv_usec = (millis % 1000) * 1000;
|
|
|
|
FD_ZERO(&rset);
|
|
FD_SET(0, &rset);
|
|
if (select(0 + 1, &rset, NULL, NULL, &timeout) > 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void
|
|
args (int argc, char **argv, int *iswindowed, const char **display_name, int *textmode)
|
|
{
|
|
const char *myself = argv[0];
|
|
|
|
*iswindowed = 0;
|
|
*display_name = NULL;
|
|
*textmode = 0;
|
|
|
|
while (--argc) {
|
|
const char *p = *++argv;
|
|
if (!strcmp(p, "-h") || !strcmp(p, "--help")) {
|
|
printf("wmfu v1.0 (c) 2007 Daniel Borca\n");
|
|
printf("wmfu is distributed under GNU GPL v2\n\n");
|
|
printf("usage: %s [OPTIONS]\n", myself);
|
|
printf(" -display <name> use specified display\n");
|
|
printf(" --windowed run in regular window\n");
|
|
printf(" --textmode run in text mode\n");
|
|
exit(0);
|
|
}
|
|
if (!strcmp(p, "-display")) {
|
|
if (argc < 2) {
|
|
fprintf(stderr, "%s: argument to `%s' is missing\n", myself, p);
|
|
exit(1);
|
|
}
|
|
--argc;
|
|
*display_name = *++argv;
|
|
}
|
|
if (!strcmp(p, "--windowed")) {
|
|
*iswindowed = 1;
|
|
}
|
|
if (!strcmp(p, "--textmode")) {
|
|
*textmode = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
int rv;
|
|
|
|
APP App;
|
|
FRAME frames[6];
|
|
|
|
int iswindowed;
|
|
const char *display_name;
|
|
int textmode;
|
|
|
|
args(argc, argv, &iswindowed, &display_name, &textmode);
|
|
|
|
App.list = sensors_init();
|
|
if (App.list == NULL) {
|
|
fprintf(stderr, "Error allocating sensor structure\n");
|
|
return -1;
|
|
}
|
|
|
|
if (textmode) {
|
|
int rv = run_text(App.list, 1000);
|
|
sensors_free(App.list);
|
|
return rv;
|
|
}
|
|
|
|
rv = dockapp_open_window(&DockApp, display_name, "wmfu", iswindowed, argc, argv);
|
|
if (rv != 0) {
|
|
fprintf(stderr, "Could not open display `%s'\n", display_name);
|
|
sensors_free(App.list);
|
|
return rv;
|
|
}
|
|
|
|
frames[0].v = dockapp_xpm2pixmap(&DockApp, frame0_xpm, &frames[0].f, &frames[0].m, NULL, 0);
|
|
if (!frames[0].v) {
|
|
fprintf(stderr, "Error initializing frame\n");
|
|
sensors_free(App.list);
|
|
return -1;
|
|
}
|
|
|
|
if (!dockapp_xpm2pixmap(&DockApp, font_xpm, &App.font, NULL, NULL, 0)) {
|
|
fprintf(stderr, "Error initializing font\n");
|
|
sensors_free(App.list);
|
|
return -1;
|
|
}
|
|
|
|
App.fontx9.row = FONTX9_ROW;
|
|
App.fontx9.height = 9;
|
|
App.fontx9.width = fontx9_width;
|
|
App.fontx9.offset = fontx9_offset;
|
|
|
|
App.fontx8.row = FONTX8_ROW;
|
|
App.fontx8.height = 8;
|
|
App.fontx8.width = fontx8_width;
|
|
App.fontx8.offset = fontx8_offset;
|
|
|
|
App.fontx7.row = FONTX7_ROW;
|
|
App.fontx7.height = 7;
|
|
App.fontx7.width = fontx7_width;
|
|
App.fontx7.offset = fontx7_offset;
|
|
|
|
App.fontx6.row = FONTX6_ROW;
|
|
App.fontx6.height = 6;
|
|
App.fontx6.width = fontx6_width;
|
|
App.fontx6.offset = fontx6_offset;
|
|
|
|
App.meter2.row = METER2_ROW;
|
|
App.meter2.height = 2;
|
|
App.meter2.width = meter2_width;
|
|
App.meter2.offset = NULL;
|
|
|
|
frames[1].v = dockapp_xpm2pixmap(&DockApp, frame1_xpm, &frames[1].f, &frames[1].m, NULL, 0);
|
|
frames[2].v = dockapp_xpm2pixmap(&DockApp, frame2_xpm, &frames[2].f, &frames[2].m, NULL, 0);
|
|
frames[3].v = dockapp_xpm2pixmap(&DockApp, frame3_xpm, &frames[3].f, &frames[3].m, NULL, 0);
|
|
frames[4].v = dockapp_xpm2pixmap(&DockApp, frame4_xpm, &frames[4].f, &frames[4].m, NULL, 0);
|
|
frames[5].v = dockapp_xpm2pixmap(&DockApp, frame5_xpm, &frames[5].f, &frames[5].m, NULL, 0);
|
|
|
|
frames[0].u = 2000;
|
|
frames[1].u = 10000;
|
|
frames[2].u = 5000;
|
|
frames[3].u = 5000;
|
|
frames[4].u = 5000;
|
|
frames[5].u = 10000;
|
|
|
|
App.frames = frames;
|
|
SWITCH_FRAME(&App, 0);
|
|
|
|
dockapp_set_eventmask(&DockApp, ButtonPressMask);
|
|
|
|
#if 1
|
|
while (!DockApp.quit) {
|
|
XEvent event;
|
|
if (dockapp_nextevent_or_timeout(&DockApp, &event, App.millis)) {
|
|
App.handle(&App, &event);
|
|
} else {
|
|
App.update(&App, 0);
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
int i;
|
|
for (i = 0; i < 1000; i++) {
|
|
App.update(&App, 0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
XCloseDisplay(DockApp.display);
|
|
|
|
sensors_free(App.list);
|
|
return 0;
|
|
}
|