batt-signal/main.c

252 lines
6.7 KiB
C

/*
██████╗░░█████╗░████████╗████████╗░░░░░░░██████╗██╗░██████╗░███╗░░██╗░█████╗░██╗░░░░░
██╔══██╗██╔══██╗╚══██╔══╝╚══██╔══╝░░░░░░██╔════╝██║██╔════╝░████╗░██║██╔══██╗██║░░░░░
██████╦╝███████║░░░██║░░░░░░██║░░░█████╗╚█████╗░██║██║░░██╗░██╔██╗██║███████║██║░░░░░
██╔══██╗██╔══██║░░░██║░░░░░░██║░░░╚════╝░╚═══██╗██║██║░░╚██╗██║╚████║██╔══██║██║░░░░░
██████╦╝██║░░██║░░░██║░░░░░░██║░░░░░░░░░██████╔╝██║╚██████╔╝██║░╚███║██║░░██║███████╗
╚═════╝░╚═╝░░╚═╝░░░╚═╝░░░░░░╚═╝░░░░░░░░░╚═════╝░╚═╝░╚═════╝░╚═╝░░╚══╝╚═╝░░╚═╝╚══════╝
*/
#include <X11/Xatom.h>
#include <X11/Xft/Xft.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/xf86vmode.h>
#include <X11/keysym.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#define FONT_SIZE 24
typedef struct {
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long inputMode;
unsigned long status;
} Hints;
int width, height;
char *message = "Battery is low!!";
void catch_fire(char *, int);
void draw_ui(Display *, Window, Visual *, Colormap, int);
void window_attr(Display *, Window, int);
void alert();
enum state {
Alert,
Normal
};
int main(void) {
time_t lastalert = 0; // a long time ago
enum state laststate = Normal, curstate = Normal;
while (1) {
FILE *battery = fopen("/sys/class/power_supply/BAT0/capacity","r");
FILE *status = fopen("/sys/class/power_supply/BAT0/status","r");
if(battery == NULL || status == NULL) {
catch_fire("batt-signal : Cannot find battery.\n", 100);
}
int cap;
char bat_status[20] = "";
fscanf(battery,"%d", &cap);
fscanf(status, "%s", bat_status);
curstate = cap <= 15 && strcmp(bat_status, "Discharging") == 0 ? Alert : Normal;
if (curstate == Alert && (time(NULL) - lastalert >= 180 || laststate == Normal)) {
alert();
lastalert = time(NULL);
}
laststate = curstate;
printf("%s : %d\n", bat_status, cap);
fclose(battery);
fclose(status);
sleep(1);
}
return 0;
}
void catch_fire(char *string, int error) {
fprintf(stderr, string);
exit(error);
}
void draw_ui(Display *d, Window w, Visual *visual, Colormap cmap, int s) {
// FONT SHENANIGANS
char font_name[strlen("monospace-") + 2];
sprintf(font_name, "monospace-%d", FONT_SIZE);
XftFont *font = XftFontOpenName(d, s, font_name);
printf("lol1\n");
// FONT COLORS
XftColor xft_black, xft_white;
XftColorAllocName(d, visual, cmap, "black", &xft_black);
XftColorAllocName(d, visual, cmap, "white", &xft_white);
XftDraw *xftdraw = XftDrawCreate(d, w, visual, cmap);
// MAKE WHITE RECT
int white_rect_x = width / 24;
int white_rect_y = height / 12;
int white_rect_width = width / 18;
int white_rect_height = height / 6;
XftDrawRect(xftdraw, &xft_white, white_rect_x, white_rect_y, white_rect_width, white_rect_height);
// MAKE BLACK RECT
int black_rect_x = width / 24 + width / 140;
int black_rect_y = height / 12 + height / 100;
int black_rect_width = width / 24;
int black_rect_height = height / 8;
XftDrawRect(xftdraw, &xft_black, black_rect_x, black_rect_y, black_rect_width, black_rect_height);
// MAKE WHITE BAR
int bar_rect_x = width / 24 + width / 36 - width / 120;
int bar_rect_y = height / 12 - height / 100;
int bar_rect_width = width / 60;
int bar_rect_height = height / 60;
XftDrawRect(xftdraw, &xft_white, bar_rect_x, bar_rect_y, bar_rect_width, bar_rect_height);
// PRINT PASS MESSAGE
XftDrawString8(xftdraw, &xft_white, font, white_rect_x *3, height/6, message, strlen(message));
}
void alert()
{
Display *d = XOpenDisplay(NULL);
if (d == NULL)
catch_fire("Cannot open display\n", 1);
int s = DefaultScreen(d);
int depth = DefaultDepth(d, s);
width = DisplayWidth(d, s);
height = DisplayHeight(d, s);
Window w;
Visual *visual = DefaultVisual(d, s);
Colormap cmap = DefaultColormap(d, s);
// IGNORES WM RULES
XSetWindowAttributes attributes;
attributes.override_redirect = True;
attributes.background_pixel = BlackPixel(d, s);
// MAKE THE WINDOW
w = XCreateWindow(d, XRootWindow(d, s), 0, 0, width, height, 0, depth, InputOutput, visual, CWBackPixel | CWOverrideRedirect, &attributes);
// SET WINDOW ATTRIBUTES
window_attr(d, w, s);
// DRAW THE RECTANGLES AND STRINGS
draw_ui(d, w, visual, cmap, s);
//PLAY THE SOUND
pid_t child_id;
child_id = fork();
if (child_id == -1) {
catch_fire("Couldn't fork\n", 1);
} else if (child_id == 0) {
execl("/usr/bin/mpg123", "mpg123", SHAREPREFIX "/lobat.mp3", NULL);
}
while (1) {
int foo;
KeySym ksym;
XEvent e;
XNextEvent(d, &e);
// CHECK IF ANYTHING IS PRESSED
if(e.type == KeyPress)
break;
draw_ui(d, w, visual, cmap, s);
}
XCloseDisplay(d);
}
void window_attr(Display *d, Window w, int s) {
int mode_count;
// VIDEO MODES
XF86VidModeModeInfo **modes, *video_mode;
XF86VidModeGetAllModeLines(d, s, &mode_count, &modes);
video_mode = modes[0];
// DISABLE DECORATIONS
Hints hints;
hints.flags = 2;
hints.decorations = 0;
Atom roperty = XInternAtom(d, "_MOTIF_WM_HINTS", True);
XSelectInput(d, w, ExposureMask | KeyPressMask);
XMapWindow(d, w);
// SETTING FULLSCREEN
XF86VidModeSwitchToMode(d, s, video_mode);
XF86VidModeSetViewPort(d, s, 0, 0);
XMoveResizeWindow(d, w, width/3, height/3, width/3, height/3);
XMapRaised(d, w);
XGrabPointer(d, w, True, 0, GrabModeAsync, GrabModeAsync, w, 0L, CurrentTime);
XGrabKeyboard(d, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
}