aboutsummaryrefslogtreecommitdiff
path: root/xbattext.c
blob: e1d2fbef89ce4961d25b3b8ac750572cd4798df4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
 *  This is a simple X11 program that displays the battery percentage
 *  on NetBSD.
 *
 *  It should be compiled with the following flags:
 *
 *     CFLAGS = -I/usr/X11R7/include -I/usr/pkg/include
 *     LDFLAGS = -lXm -L/usr/X11R7/lib -L/usr/pkg/lib
 *     LDFLAGS += -Wl,-R/usr/X11R7/lib -Wl,-R/usr/pkg/lib
 *
 *  It requires x11/motif to be installed.
 *  The fontList resource controls the font used.
 *
 *  xbattext is written by John Ankarstr\xf6m <john@ankarstrom.se> and
 *  is released into the public domain; do whatever you want with it.
 */

#include <assert.h>
#include <err.h>
#include <fcntl.h>
#include <machine/apmvar.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/envsys.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <Xm/Label.h>
#include <Xm/Xm.h>

/* interval in seconds */
#define INTERVAL 30

/* low battery level */
#define ALERT 30

void update(XtPointer, XtIntervalId *);

/* application state */
Arg wargs[10];
char *s;
int apmfd, alert;
struct apm_power_info info;
Widget toplevel, label;
XmString str;
XtAppContext app_context;
XtIntervalId timer = 0;

int
main(int argc, char* argv[])
{
	toplevel = XtVaAppInitialize(
		&app_context,
		"XBat",
		NULL, 0,
		&argc, argv,
		NULL,
		NULL);

	if ((apmfd = open("/dev/apm", O_RDONLY, 0755)) == -1)
		err(1, "open");

	if ((s = malloc(5*sizeof(char))) == NULL)
		err(1, "malloc");

	XtSetLanguageProc(NULL, NULL, NULL);

	/* create motif label */
	label = XtVaCreateManagedWidget("text",
		xmLabelWidgetClass, toplevel,
		XmNlabel, "",
		NULL);
	alert = 0;

	update(NULL, &timer);
	XtRealizeWidget(toplevel);
	XtAppMainLoop(app_context);
}

/* update battery status and (re-)add timer */
void
update(XtPointer client_data, XtIntervalId *t)
{
	/* remove current timer */
	if (t == NULL && timer) {
		XtRemoveTimeOut(timer);
		timer = 0;
	}

	/* get battery info */
	memset(&info, 0, sizeof(info));
	if (ioctl(apmfd, APM_IOC_GETPOWER, &info) == -1) {
		fprintf(stderr, "ioctl APM_IOC_GETPOWER failed\n");
		sprintf(s, "?");
		goto end;
	}

	/* put battery status into label */
	sprintf(s, "%d%%", info.battery_life);
	str = XmStringCreate(s, XmFONTLIST_DEFAULT_TAG);
	XtSetArg(wargs[0], XmNlabelString, str);
	XtSetValues(label, wargs, 1);
	XmStringFree(str);

	/* change color if low battery */
#ifdef ALERT
	if (!alert && info.battery_life < ALERT) {
		XtVaSetValues(label,
			XtVaTypedArg, XmNforeground, XmRString, "red", 4);
		alert = 1;
	} else if (alert && info.battery_life >= ALERT) {
		XtVaSetValues(label,
			XtVaTypedArg, XmNforeground, XmRString, "black", 4);
		alert = 0;
	}
#endif

	/* add new timer */
end:	timer = XtAppAddTimeOut(app_context, INTERVAL * 1000, update, toplevel);
}