diff options
| author | Sam Light <sam@lightscale.co.uk> | 2025-09-10 19:37:28 +0100 |
|---|---|---|
| committer | Sam Light <sam@lightscale.co.uk> | 2025-09-10 19:37:28 +0100 |
| commit | d9b456d738e5013d48f41f5e6315ef7c22d6acf0 (patch) | |
| tree | 2e3722f5697cbf883c4b16edc87726b9e510bce1 | |
Initial commit
| -rw-r--r-- | .gitignore | 23 | ||||
| -rw-r--r-- | Makefile.am | 15 | ||||
| -rw-r--r-- | config.h.in | 74 | ||||
| -rw-r--r-- | configure.ac | 56 | ||||
| -rw-r--r-- | src/dwminfo.c | 61 | ||||
| -rw-r--r-- | src/modules/.dirstamp | 0 | ||||
| -rw-r--r-- | src/modules/battery.c | 73 | ||||
| -rw-r--r-- | src/modules/battery.h | 22 | ||||
| -rw-r--r-- | src/modules/pulse.c | 136 | ||||
| -rw-r--r-- | src/modules/pulse.h | 26 | ||||
| -rw-r--r-- | src/modules/time.c | 29 | ||||
| -rw-r--r-- | src/modules/time.h | 15 | ||||
| -rw-r--r-- | src/signal.c | 34 | ||||
| -rw-r--r-- | src/signal.h | 10 | ||||
| -rw-r--r-- | src/somebarinfo.c | 86 | ||||
| -rw-r--r-- | src/text.c | 49 | ||||
| -rw-r--r-- | src/text.h | 21 |
17 files changed, 730 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d6d8760 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +somebarinfo +dwminfo +*.o + + +configure +Makefile +Makefile.in +config.log +config.status +autom4te.cache +aclocal.m4 +install-sh +compile +depcomp +missing +.deps +ar-lib +config.h +config.guess +config.sub +stamp-h1 +.dirstamp diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..6889b3e --- /dev/null +++ b/Makefile.am @@ -0,0 +1,15 @@ +bin_PROGRAMS=somebarinfo dwminfo + +CFLAGS=$(LIBPULSE_CFLAGS) +LDADD=$(LIBPULSE_LIBS) -lm + +COMMON_SOURCES=src/text.c \ + src/signal.c \ + src/modules/pulse.c \ + src/modules/time.c \ + src/modules/battery.c + +somebarinfo_SOURCES=src/somebarinfo.c $(COMMON_SOURCES) + +dwminfo_LDADD=$(LDADD) -lX11 +dwminfo_SOURCES=src/dwminfo.c $(COMMON_SOURCES) diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..8929c27 --- /dev/null +++ b/config.h.in @@ -0,0 +1,74 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if C supports variable-length arrays. */ +#undef HAVE_C_VARARRAYS + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdio.h> header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Define to 1 if C does not support variable-length arrays, and if the + compiler does not already define this. */ +#undef __STDC_NO_VLA__ + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..c0eb433 --- /dev/null +++ b/configure.ac @@ -0,0 +1,56 @@ +AC_INIT([dwxinfo], [0.1.0]) + +AC_CONFIG_HEADERS([config.h]) +AM_INIT_AUTOMAKE([foreign subdir-objects]) +AM_SILENT_RULES([yes]) + +: ${CFLAGS="-O2"} + +AC_PROG_CC +AC_C_CONST +AC_C_VARARRAYS +AC_FUNC_MALLOC +AC_PROG_SED +AC_CHECK_INCLUDES_DEFAULT + +AC_CHECK_HEADER([fcntl.h], [], [ + echo "Missing fcntl.h header" + exit -1 +]) + +AC_CHECK_HEADER([errno.h], [], [ + echo "Missing errno.h header" + exit -1 +]) + +AC_CHECK_HEADER([signal.h], [], [ + echo "Missing signal.h header" + exit -1 +]) + +AC_CHECK_HEADER([poll.h], [], [ + echo "Missing poll.h header" + exit -1 +]) + +PKG_CHECK_MODULES([LIBPULSE], [libpulse]) + +AC_ARG_ENABLE(debug, + AS_HELP_STRING([--enable-debug], [enable debugging, default: yes]), + [case "${enableval}" in + yes) debug=true ;; + no) debug=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;; + esac], + [debug=true]) + +if test x"$debug" = x"true"; then + CFLAGS="$CFLAGS -g" +fi + +CFLAGS="$CFLAGS -Wall" + +AC_CONFIG_FILES([ + Makefile +]) +AC_OUTPUT diff --git a/src/dwminfo.c b/src/dwminfo.c new file mode 100644 index 0000000..8e04b43 --- /dev/null +++ b/src/dwminfo.c @@ -0,0 +1,61 @@ +#include "signal.h" +#include "text.h" + +#include <stdio.h> +#include <unistd.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> + +struct state { + Display * display; + Window window; + struct text * text; +}; + +static int +init_state(struct state * s) +{ + s->display = XOpenDisplay(NULL); + s->window = XDefaultRootWindow(s->display); + s->text = text_new(); + return 0; +} + +static void +deinit_state(struct state * s) +{ + XCloseDisplay(s->display); + text_free(s->text); +} + +static void +update_status(struct state * s) +{ + text_update(s->text); + XStoreName(s->display, s->window, s->text->value); + XSync(s->display, 1); +} + +static void +run_loop(struct state * s) +{ + while(signal_running) { + update_status(s); + usleep(1000 * 500); + } +} + +int main(void) +{ + struct state s; + + signal_setup_actions(); + + init_state(&s); + run_loop(&s); + deinit_state(&s); + + return 0; +} diff --git a/src/modules/.dirstamp b/src/modules/.dirstamp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/modules/.dirstamp diff --git a/src/modules/battery.c b/src/modules/battery.c new file mode 100644 index 0000000..6c656fe --- /dev/null +++ b/src/modules/battery.c @@ -0,0 +1,73 @@ +#include "battery.h" + +#include <stdlib.h> +#include <string.h> +#include <tgmath.h> + +#include <fcntl.h> +#include <unistd.h> + +#define UPDATE_FREQUENCY 20 + +static int +open_battery_file(const char * name) +{ + char path[128]; + snprintf(path, 128, "/sys/class/power_supply/BAT0/%s", name); + return open(path, O_RDONLY); +} + +static int +battery_value(int file) +{ + int val = 0; + char buf[16]; + + memset(&buf, '\0', 16); + lseek(file, 0, SEEK_SET); + read(file, &buf, sizeof(char) * 16); + sscanf(buf, "%d", &val); + + return val; +} + +struct battery * +battery_new() +{ + struct battery * b = malloc(sizeof(struct battery)); + int file = open_battery_file("charge_full"); + + b->full = battery_value(file); + b->file_current = open_battery_file("charge_now"); + b->last_update = 0; + + close(file); + + return b; +} + +void +battery_free(struct battery * b) +{ + close(b->file_current); + free(b); +} + +void battery_update(struct battery * b) +{ + int now; + float percentf; + int percent; + time_t now_time = time(NULL); + + if((now_time - b->last_update) >= UPDATE_FREQUENCY) { + b->last_update = now_time; + + now = battery_value(b->file_current); + + percentf = (100.0f / b->full) * now; + percent = round(percentf); + + snprintf(b->value, BATTERY_VALUE_SIZE, "%d%%", percent); + } +} diff --git a/src/modules/battery.h b/src/modules/battery.h new file mode 100644 index 0000000..92489b5 --- /dev/null +++ b/src/modules/battery.h @@ -0,0 +1,22 @@ +#ifndef _DWXINFO_MODULES_BATTERY_H_ +#define _DWXINFO_MODULES_BATTERY_H_ + +#include <stdio.h> +#include <time.h> + +#define BATTERY_VALUE_SIZE 5 + +struct battery { + int full; + int file_current; + time_t last_update; + + char value[BATTERY_VALUE_SIZE]; +}; + +struct battery * battery_new(); +void battery_free(struct battery *); + +void battery_update(struct battery *); + +#endif diff --git a/src/modules/pulse.c b/src/modules/pulse.c new file mode 100644 index 0000000..cbbfe35 --- /dev/null +++ b/src/modules/pulse.c @@ -0,0 +1,136 @@ +#include "pulse.h" + +#include "../signal.h" + +#include <pulse/mainloop.h> +#include <pulse/context.h> +#include <pulse/introspect.h> +#include <pulse/volume.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <tgmath.h> + +static void +run_loop(struct pulse * p) +{ + p->run_loop = true; + while(p->run_loop && signal_running) { + pa_mainloop_iterate(p->ml, 1, NULL); + } +} + +static void +stop_loop(struct pulse * p) +{ + p->run_loop = false; +} + +static void +server_info_cb(pa_context * ctx, const pa_server_info * info, void * ud) +{ + struct pulse * p = (struct pulse *) ud; + + size_t s = strlen(info->default_sink_name); + + p->default_sink = malloc(s + 1); + memset(p->default_sink, '\0', s + 1); + strncpy(p->default_sink, info->default_sink_name, s); + + stop_loop(p); +} + +static void +state_cb(pa_context * ctx, void * ud) +{ + pa_context_state_t state = pa_context_get_state(ctx); + struct pulse * p = (struct pulse *) ud; + + switch(state) { + + case PA_CONTEXT_READY: + pa_context_get_server_info(p->ctx, server_info_cb, p); + break; + case PA_CONTEXT_FAILED: + case PA_CONTEXT_TERMINATED: + stop_loop(p); + break; + default: break; + + } +} + +struct pulse * +pulse_new() +{ + struct pulse * p = malloc(sizeof(struct pulse)); + + memset(p->value, '\0', PULSE_VALUE_SIZE); + + p->default_sink = NULL; + p->run_loop = false; + + p->ml = pa_mainloop_new(); + p->ctx = pa_context_new(pa_mainloop_get_api(p->ml), NULL); + + pa_context_set_state_callback(p->ctx, state_cb, p); + + pa_context_connect(p->ctx, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL); + + run_loop(p); + + return p; +} + +void +pulse_free(struct pulse * p) +{ + if(p->default_sink != NULL) free(p->default_sink); + + if(p->ctx->proplist) { + pa_proplist_free(p->ctx->proplist); + } + + pa_context_disconnect(p->ctx); + pa_context_unref(p->ctx); + pa_mainloop_free(p->ml); + + free(p); +} + +static void +sink_info_cb(pa_context * ctx, const pa_sink_info * info, int eol, void * ud) +{ + struct pulse * p = (struct pulse *) ud; + pa_volume_t vol, norm; + + if(eol > 0) { + stop_loop(p); + } + else { + if(info->mute) { + strncpy(p->value, "M", PULSE_VALUE_SIZE); + } + else { + vol = pa_cvolume_avg(&info->volume); + vol -= PA_VOLUME_MUTED; + norm = PA_VOLUME_NORM - PA_VOLUME_MUTED; + + vol = round((100.0f / norm) * vol); + snprintf(p->value, PULSE_VALUE_SIZE, "%d%%", vol); + } + } +} + +void +pulse_update(struct pulse * p) +{ + pa_operation * op; + + if(p->default_sink != NULL) { + op = pa_context_get_sink_info_by_name(p->ctx, p->default_sink, sink_info_cb, p); + pa_operation_unref(op); + run_loop(p); + } +} diff --git a/src/modules/pulse.h b/src/modules/pulse.h new file mode 100644 index 0000000..708d05c --- /dev/null +++ b/src/modules/pulse.h @@ -0,0 +1,26 @@ +#ifndef _DWXINFO_PULSE_H_ +#define _DWXINFO_PULSE_H_ + +#include <stdbool.h> + +#define PULSE_VALUE_SIZE 5 + +typedef struct pa_mainloop pa_mainloop; +typedef struct pa_context pa_context; + +struct pulse { + pa_mainloop * ml; + pa_context * ctx; + char * default_sink; + + bool run_loop; + + char value[PULSE_VALUE_SIZE]; +}; + +struct pulse * pulse_new(); +void pulse_free(struct pulse *); + +void pulse_update(struct pulse *); + +#endif diff --git a/src/modules/time.c b/src/modules/time.c new file mode 100644 index 0000000..84f894e --- /dev/null +++ b/src/modules/time.c @@ -0,0 +1,29 @@ +#include "time.h" + +#include <stdlib.h> +#include <time.h> +#include <tgmath.h> + +struct time * +time_new() +{ + struct time * t = malloc(sizeof(struct time)); + return t; +} + +void +time_free(struct time * t) +{ + free(t); +} + +void +time_update(struct time * t) +{ + time_t timer; + struct tm * tm; + + time(&timer); + tm = gmtime(&timer); + strftime(t->value, TIME_VALUE_SIZE, "%F [%a] %T", tm); +} diff --git a/src/modules/time.h b/src/modules/time.h new file mode 100644 index 0000000..2dec7d5 --- /dev/null +++ b/src/modules/time.h @@ -0,0 +1,15 @@ +#ifndef _DWXINFO_MODULES_TIME_H_ +#define _DWXINFO_MODULES_TIME_H_ + +#define TIME_VALUE_SIZE 32 + +struct time { + char value[TIME_VALUE_SIZE]; +}; + +struct time * time_new(); +void time_free(struct time *); + +void time_update(struct time *); + +#endif diff --git a/src/signal.c b/src/signal.c new file mode 100644 index 0000000..e993ae3 --- /dev/null +++ b/src/signal.c @@ -0,0 +1,34 @@ +#include "signal.h" + +#include <string.h> + +sig_atomic_t signal_running; + +static void +handle_signal_shutdown(int sig) +{ + signal_running = 0; +} + +int +signal_setup_actions() +{ + int rc; + struct sigaction action; + + signal_running = 1; + + memset(&action, 0, sizeof(action)); + action.sa_handler = handle_signal_shutdown; + rc = sigemptyset(&action.sa_mask); + if(rc < 0) return rc; + rc = sigaction(SIGINT, &action, 0); + if(rc < 0) return rc; + + rc = sigemptyset(&action.sa_mask); + if(rc < 0) return rc; + rc = sigaction(SIGTERM, &action, 0); + if(rc < 0) return rc; + + return rc; +} diff --git a/src/signal.h b/src/signal.h new file mode 100644 index 0000000..d3a513a --- /dev/null +++ b/src/signal.h @@ -0,0 +1,10 @@ +#ifndef _DWXINFO_SIGNAL_H_ +#define _DWXINFO_SIGNAL_H_ + +#include <signal.h> + +extern sig_atomic_t signal_running; + +int signal_setup_actions(); + +#endif diff --git a/src/somebarinfo.c b/src/somebarinfo.c new file mode 100644 index 0000000..0dc2d50 --- /dev/null +++ b/src/somebarinfo.c @@ -0,0 +1,86 @@ +#include "signal.h" +#include "text.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#define SOMEBAR_CMD "status" + +struct state { + FILE * file; + struct text * text; +}; + +static int +init_state(struct state * s) +{ + char * dir = getenv("XDG_RUNTIME_DIR"); + char * file = "/somebar-0"; + size_t dir_len = strlen(dir); + size_t file_len = strlen(file); + size_t path_len = dir_len + file_len + 1; + char path[path_len]; + + memset(path, '\0', path_len); + + strncat(path, dir, dir_len); + strncat(path, file, file_len); + + s->text = NULL; + + s->file = fopen(path, "a"); + if(s->file == NULL) return -1; + + s->text = text_new(); + return 0; +} + +static void +deinit_state(struct state * s) +{ + if(s->file) fclose(s->file); + if(s->text) text_free(s->text); +} + +static void +update_status(struct state * s) +{ + const size_t + cmd_len = strlen(SOMEBAR_CMD), + msg_len = TEXT_SIZE + cmd_len + 3; + char msg[msg_len]; + + text_update(s->text); + + snprintf(msg, msg_len, "%s %s\n", SOMEBAR_CMD, s->text->value); + + fputs(msg, s->file); + fflush(s->file); +} + +static void +run_loop(struct state * s) +{ + while(signal_running) { + update_status(s); + usleep(1000 * 800); + } +} + +int main(void) +{ + int rc; + struct state s; + + signal_setup_actions(); + + rc = init_state(&s); + + if(rc == 0) run_loop(&s); + + deinit_state(&s); + + return 0; +} diff --git a/src/text.c b/src/text.c new file mode 100644 index 0000000..df3b3c4 --- /dev/null +++ b/src/text.c @@ -0,0 +1,49 @@ +#include "text.h" + +#include "modules/pulse.h" +#include "modules/time.h" +#include "modules/battery.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <tgmath.h> + +struct text * +text_new() +{ + struct text * t = malloc(sizeof(struct text)); + + memset(t->value, '\0', TEXT_SIZE); + + t->battery = battery_new(); + t->time = time_new(); + t->pulse = pulse_new(); + + return t; +} + +void +text_free(struct text * t) +{ + time_free(t->time); + pulse_free(t->pulse); + battery_free(t->battery); + free(t); +} + +void +text_update(struct text * t) +{ + time_update(t->time); + pulse_update(t->pulse); + battery_update(t->battery); + + snprintf( + t->value, TEXT_SIZE, + "VOL: %s | BAT: %s | %s", + t->pulse->value, + t->battery->value, + t->time->value); +} diff --git a/src/text.h b/src/text.h new file mode 100644 index 0000000..752d15f --- /dev/null +++ b/src/text.h @@ -0,0 +1,21 @@ +#ifndef _DWXINFO_TEXT_H_ +#define _DWXINFO_TEXT_H_ + +#include <stdio.h> + +#define TEXT_SIZE 512 + +struct text { + char value[TEXT_SIZE]; + + struct battery * battery; + struct pulse * pulse; + struct time * time; +}; + +struct text * text_new(); +void text_free(struct text *); + +void text_update(struct text *); + +#endif |
