From ea5380fccb9f962203726540d69cb490048de7c0 Mon Sep 17 00:00:00 2001 From: Inqiyad Sabr Date: Sun, 19 Oct 2025 23:17:43 +0600 Subject: Add files --- LICENSE | 15 +++++++++++++++ Makefile | 32 ++++++++++++++++++++++++++++++++ README.md | 33 +++++++++++++++++++++++++++++++++ battery.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ block.c | 18 ++++++++++++++++++ block.h | 4 ++++ bstatus.c | 22 ++++++++++++++++++++++ cmus.c | 16 ++++++++++++++++ cpu.c | 38 ++++++++++++++++++++++++++++++++++++++ datetime.c | 14 ++++++++++++++ modules.h | 19 +++++++++++++++++++ 11 files changed, 260 insertions(+) create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 battery.c create mode 100644 block.c create mode 100644 block.h create mode 100644 bstatus.c create mode 100644 cmus.c create mode 100644 cpu.c create mode 100644 datetime.c create mode 100644 modules.h diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6f402f3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +(C) Inqiyad Sabr +All rights are liberated. +This is libre software liberated into the public domain. + +"Anyone" is free to copy, modify, publish, use, compile, sell or distribute this software either in source form or as compiled binary, for any purpose, commercial or non-commercial, and by any means. + +"Anyone" is anyone who does not wish no take away the liberation of this software in their own share. The liberation can be understood by the following clauses: + +1. Anyone who owns a copy of this "software" cannot close the source for any service they provide using this software in the open. + +2. You are liberated to statically link this software. + +The software is provided as is, without warranty of any kind. The author(s) of this LICENSE will not be liable for any damages or claim relating to the software. + +This license is to be understood as being free for those who love open liberation and not for who doesn't. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1610951 --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +.POSIX: + +RM := /bin/rm +DESTDIR := /usr/local/bin + +CFLAGS := -std=c99 -Wfloat-equal -Og +CFLAGS += -Wall -Werror -Wextra -Wpedantic +CFLAGS += -m64 -no-pie -pipe +CFLAGS += -ffunction-sections -fdata-sections +CFLAGS += -D_XOPEN_SOURCE=500L -flto +CFLAGS += -march=native -mtune=generic + +LDFLAGS := -static -Wl,--build-id=none +LDFLAGS += -ffunction-sections -fdata-sections +#LDFLAGS += -Wl,--strip-all +LDFLAGS += -Wl,--flto + +.SUFFIXES: .c .o + +bstatus: $(FILES) *.o + $(CC) $(LDFLAGS) *.o -o bstatus + +.c.o: + $(CC) $(CFLAGS) -c *.c + +clean: + $(RM) ./*.o + +install: + install -s -m0755 bstatus $(DESTDIR) + +.PHONY: make clean install diff --git a/README.md b/README.md new file mode 100644 index 0000000..297020c --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# Bstatus +Broke status, in short `bstatus`. A swaybar status generator written in C and is simple. + +This software is written in <200LoC. + +# Just use i3blocks or i3-* status generators? +People have made many many status generators for i3bar and swaybar with the protocol json but they haven't done it the way I've done it. Hence the reason for not using them. + +# Just use waybar? +No, tbh waybar is over-complicated piece of garbage which even requires GTK to theme it through CSS and it's a complete mess that requires more CPU usage than it should ever require. + +# How does this work? +It follows the swaybar-protocol(7), for that it outputs status in json rather than just printing. There is a block.c file that has a function `block()` that takes four arguments: the status text, foreground color, background color, border color. + +The modules are seperated in their own files sourced through `modules.h`. + +The modules battery and cpu are delayed in the source code for a default of 6 seconds (personal preference), which you can change directly in the source code. + +# Modules +The modules aren't directly portable, I'd say to modify and port it than to comply with all in one file; to be simple. + +- [x] datetime +- [x] battery +- [x] cpu +- [ ] memory +- [ ] volume +- [ ] network + +# Contribute +Send a patch [to my email](sabr@ariamath.xyz) or [at xmpp](xmpp:sabr@ariamath.xyz). + +## Addenum +This is my 3rd rewrite of this software of which I got this to work with the best intuition I have possible written in the most simple way without sacrificing any performance. diff --git a/battery.c b/battery.c new file mode 100644 index 0000000..20283fd --- /dev/null +++ b/battery.c @@ -0,0 +1,49 @@ +#include +#include +#include "block.h" +#define DIR "/sys/class/power_supply/BAT0" +#define EN DIR"/energy_now" +#define EF DIR"/energy_full" +#define ST DIR"/status" +FILE *en; +FILE *ef; +FILE *st; +int c, state, bat_delay = 6; +float en_n, ef_n; +float p; +char pch[13], icon[5]; +void battery(void) { + if (bat_delay++ < 6) goto show_stat; + else bat_delay = 0; + if (!en) en = fopen(EN,"r"); + if (!ef) ef = fopen(EF,"r"); + if (!st) st = fopen(ST,"r"); + if (en && ef && st) { + rewind(en); + rewind(ef); + rewind(st); + en_n = ef_n = 0; + while((c = fgetc(en)) != '\n') + en_n = 10 * en_n + (c - '0'); + while((c = fgetc(ef)) != '\n') + ef_n = 10 * ef_n + (c - '0'); + p = en_n * 100 / ef_n; + state = fgetc(st); + switch(state) { + case 'N': strncpy(icon,"",4); break; + case 'C': strncpy(icon,"󱐋",5); break; + case 'D': if (p > 0 && p <= 10) strncpy(icon," ",5); + else if (p > 10 && p <= 30) strncpy(icon," ",5); + else if (p > 30 && p <= 50) strncpy(icon," ",5); + else if (p > 50 && p <= 79) strncpy(icon," ",5); + else if (p > 79) strncpy(icon," ",5); + } snprintf(pch,13,"%s %02.2f%%",icon,p); + } +show_stat: + if (state == 'D') + block(pch,"#222222","#83a59899","#83a59899"); + else if (p < 30) + block(pch,"#222222","#ea544399","#ea544399"); + else if (state == 'N' || state == 'C') + block(pch,"#222222","#dfb24999","#dfb24999"); +} diff --git a/block.c b/block.c new file mode 100644 index 0000000..efdcb63 --- /dev/null +++ b/block.c @@ -0,0 +1,18 @@ +#include +#define BORDER_WIDTH "10" +void block( + char *text, char *fg, + char *bg, char *bc +){ + fputs("{",stdout); + printf("\"full_text\":\"%s\",",text); + printf("\"color\":\"%s\",",fg); + printf("\"background\":\"%s\",",bg); + printf("\"border\":\"%s\",",bc); + fputs("\"border_top\":\""BORDER_WIDTH"\",",stdout); + fputs("\"border_bottom\":\""BORDER_WIDTH"\",",stdout); + fputs("\"border_left\":\""BORDER_WIDTH"\",",stdout); + fputs("\"border_right\":\""BORDER_WIDTH"\",",stdout); + fputs("\"separator\":false},",stdout); + fflush(stdout); +} diff --git a/block.h b/block.h new file mode 100644 index 0000000..a269756 --- /dev/null +++ b/block.h @@ -0,0 +1,4 @@ +#ifndef BLOCK_H +#define BLOCK_H +void block(char *, char *, char *, char *); +#endif diff --git a/bstatus.c b/bstatus.c new file mode 100644 index 0000000..91a1a11 --- /dev/null +++ b/bstatus.c @@ -0,0 +1,22 @@ +#include +#include "modules.h" +int main(void) +{ + write(1, + "{\"version\":1," + "\"bstatus-version\":\"0.1.1-r1\"," + "\"click_events\":true,"\ + "\"cont_signal\":18,"\ + "\"stop_signal\":19}\n[[],\n", + 102 + ); + for (;;) { + write(1,"[",1); + cmus(); + datetime(); + battery(); + cpu(); + write(1,"],",2); + sleep(1); + } +} diff --git a/cmus.c b/cmus.c new file mode 100644 index 0000000..edd7178 --- /dev/null +++ b/cmus.c @@ -0,0 +1,16 @@ +#include +#include "block.h" +FILE *cmus_stat; +char cmus_str[64]; +void cmus(void) { + if (!cmus_stat) cmus_stat = fopen("/tmp/cmus-status","r"); + int len, c; + len = 0; + if (cmus_stat) { + while (len < 64 && (c = fgetc(cmus_stat)) != EOF) + cmus_str[len++] = c; + rewind(cmus_stat); + cmus_str[len] = '\0'; + } + block(cmus_str,"#222222","#95b18b99","#95b18b99"); +} diff --git a/cpu.c b/cpu.c new file mode 100644 index 0000000..0d53461 --- /dev/null +++ b/cpu.c @@ -0,0 +1,38 @@ +#include +#include "block.h" +#define ICON_CPU " " +FILE *proc_stat; +int stat[8], cpu_delay = 6; +double prev_idle, prev_total, total, idle, usage_p; +char usage_str[11]; +void cpu(void) { + if (cpu_delay++ < 6) goto show_stat; + else cpu_delay = 0; + prev_idle = idle; + prev_total = total; + if (!proc_stat) proc_stat = fopen("/proc/stat","r"); + if (proc_stat) { + int c, i; + fseek(proc_stat,5,0); + for (i = 0;i < 8;i++) stat[i] = 0; + for (i = 0; i < 8;) { + c = fgetc(proc_stat); + if (c != ' ') + stat[i] = 10 * stat[i] + (c - '0'); + else i++; + } + total = stat[0]+stat[1]+stat[2]; + idle = stat[3]+stat[4]; + total += stat[5]+stat[6]+stat[7]; + } + usage_p = (idle + total) - (prev_idle + prev_total); + usage_p -= (idle - prev_idle); + usage_p *= 100; + usage_p /= (idle + total) - (prev_idle + prev_total); + snprintf(usage_str,11,ICON_CPU"%02.2f%%",usage_p); +show_stat: + if (usage_p < 60) + block(usage_str,"#222222","#acae3299","#acae3299"); + else + block(usage_str,"#222222","#ea544399","#ea544399"); +} diff --git a/datetime.c b/datetime.c new file mode 100644 index 0000000..b28102f --- /dev/null +++ b/datetime.c @@ -0,0 +1,14 @@ +#include +#include "block.h" +#define ICON_TIME "󱑎 " +#define ICON_DATE "󰃭 " +char ct[15]; +char cd[29]; +void datetime(void) { + time_t t = time(NULL); + struct tm * lt = localtime(&t); + strftime(ct,sizeof(ct),ICON_TIME"%H:%M:%S",lt); + block(ct,"#222222","#ca91a099","#ca91a099"); + strftime(cd,sizeof(cd),ICON_DATE"%Y-%m-%d %a",lt); + block(cd,"#222222","#ca91a099","#ca91a099"); +} diff --git a/modules.h b/modules.h new file mode 100644 index 0000000..4856487 --- /dev/null +++ b/modules.h @@ -0,0 +1,19 @@ +// datetime +#ifndef DATETIME_H +#define DATETIME_H +void datetime(void); +#endif +// battery +#ifndef BATTERY_H +#define BATTERY_H +void battery(void); +#endif +// cpu +#ifndef CPU_H +#define CPU_H +void cpu(void); +#endif +#ifndef CMUS_H +#define CMUS_H +void cmus(void); +#endif -- cgit v1.2.3