Compare commits

..

24 Commits

Author SHA1 Message Date
ee01830c33 Add fcitx5 module 2023-09-29 11:25:28 -07:00
cef428daea Added dwmblocks-mu4e 2023-09-29 03:39:29 -07:00
cf2d0ed30e Fix possible resource leak 2023-09-16 11:02:44 -07:00
bb55ac56dd Move some stuff around 2023-09-15 22:10:53 -07:00
e911dd7095 Update blocks.def.h 2023-09-15 15:05:07 -07:00
ae08d6f2ce Create config.def.mk 2023-09-15 15:03:02 -07:00
3b0049fed5 Add space after bluetooth in network 2023-09-09 20:31:16 -07:00
4aaf17b26a Remove PKGBUILD 2023-09-09 02:11:55 -07:00
316e32a6a5 Update Makefile and add config.mk 2023-09-09 02:11:00 -07:00
89073bf8bd Update PKGBUILD 2023-09-09 00:35:10 -07:00
cc78fe00af Ensure pulse gets cleaned up 2023-09-09 00:31:15 -07:00
26b304eeb3 Make pulse listener built in 2023-09-08 23:39:55 -07:00
f009fcb92b Update dwmblocks-battery 2023-07-29 00:18:16 -07:00
76c2d59fcc Merge branch 'main' of git.zander.im:Zander671/dwmblocks 2023-07-28 23:49:57 -07:00
6ae62476ce Update dwmblocks-battery 2023-07-28 23:49:29 -07:00
ca5b3e68ba Fix dwmblocks-volume 2023-06-07 15:30:14 -07:00
def7285b73 Ensure dwmblocks-fcitx5 gets uninstalled in Makefile 2023-05-28 10:56:08 -07:00
a28859d1f2 Added dwmblocks-fcitx5 2023-05-28 10:50:45 -07:00
6165643fb3 Add PKGBUILD 2023-05-23 03:04:48 -07:00
294ad801e4 ix volume script 2023-05-06 14:31:12 -07:00
41c41b7702 pdate icons in scripts 2023-05-04 15:04:51 -07:00
2e64eee765 Clean up dwmblocks-pulse-listener.c 2023-03-06 12:53:36 -08:00
502f596c87 Clean up dwmblocks-pulse-listener.c 2023-02-23 12:07:46 -08:00
b0441e32af Update README.md 2023-02-23 11:59:57 -08:00
14 changed files with 262 additions and 199 deletions

4
.gitignore vendored
View File

@ -1,3 +1,3 @@
blocks.h
dwmblocks
dwmblocks-pulse-listener
config.mk
blocks.h

View File

@ -1,43 +1,38 @@
PREFIX := /usr/local
CC := cc
CFLAGS := -pedantic -Wall -Wno-deprecated-declarations -Os
LDFLAGS := -lX11
PULSEFLAGS := -lpulse
include config.mk
# FreeBSD (uncomment)
#LDFLAGS += -L/usr/local/lib -I/usr/local/include
# # OpenBSD (uncomment)
#LDFLAGS += -L/usr/X11R6/lib -I/usr/X11R6/include
all: options dwmblocks dwmblocks-pulse-listener
all: options dwmblocks
options:
@echo dwmblocks build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "CFLAGS = ${CFLAGS} ${NO_X}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
@echo "PULSEFLAGS = ${PULSEFLAGS}"
dwmblocks: dwmblocks.c blocks.def.h blocks.h
${CC} -o dwmblocks dwmblocks.c ${CFLAGS} ${LDFLAGS}
dwmblocks-pulse-listener: dwmblocks-pulse-listener.c
${CC} -o dwmblocks-pulse-listener dwmblocks-pulse-listener.c ${CFLAGS} ${PULSEFLAGS}
dwmblocks: dwmblocks.c pulse-listener.c blocks.def.h blocks.h
${CC} ${NO_X} -o dwmblocks dwmblocks.c pulse-listener.c ${CFLAGS} ${PULSEFLAGS} ${LDFLAGS}
blocks.h:
cp blocks.def.h $@
config.mk:
cp config.def.mk $@
clean:
rm -f *.o *.gch dwmblocks dwmblocks-pulse-listener
rm -f *.o *.gch dwmblocks
install: dwmblocks
mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f dwmblocks ${DESTDIR}${PREFIX}/bin
cp -f dwmblocks-pulse-listener ${DESTDIR}${PREFIX}/bin
chmod 755 ${DESTDIR}${PREFIX}/bin/dwmblocks
install -m0755 scripts/* ${DESTDIR}${PREFIX}/bin
uninstall:
rm -f ${DESTDIR}${PREFIX}/bin/dwmblocks
rm -f ${DESTDIR}${PREFIX}/bin/dwmblocks \
${DESTDIR}${PREFIX}/bin/dwmblocks-battery \
${DESTDIR}${PREFIX}/bin/dwmblocks-network \
${DESTDIR}${PREFIX}/bin/dwmblocks-volume \
${DESTDIR}${PREFIX}/bin/dwmblocks-fcitx5 \
${DESTDIR}${PREFIX}/bin/dwmblocks-mu4e
.PHONY: all options clean install uninstall

View File

@ -1,15 +1,26 @@
# dwmblocks
Modular status bar for dwm written in c.
# usage
My personal fork of dwmblocks. Original found
[here](https://github.com/torrinfail/dwmblocks).
Dwmblocks is a modular status bar for dwm written in c.
## Usage
To use dwmblocks first run 'make' and then install it with 'sudo make install'.
After that you can put dwmblocks in your xinitrc or other startup script to have it start with dwm.
# modifying blocks
The statusbar is made from text output from commandline programs.
Blocks are added and removed by editing the blocks.h header file.
By default the blocks.h header file is created the first time you run make which copies the default config from blocks.def.h.
This is so you can edit your status bar commands and they will not get overwritten in a future update.
# patches
Here are some patches to dwmblocks that add features that I either don't want to merge in, or that require a dwm patch to work.
I do not maintain these but I will take pull requests to update them.
<br>
<a href=https://gist.github.com/IGeraGera/e4a5583b91b3eec2e81fdceb44dea717>dwmblocks-statuscmd-b6b0be4.diff</a>
After that you can put dwmblocks in your xinitrc or other startup script to have
it start with dwm.
The dwmblocks-pulse-listener program is a small daemon that takes the pid of a
dwmblocks instance and notifies it of pulse audio volume changes.
## Modifying Blocks
The status bar is made from text output from command-line programs. Blocks are
added and removed by editing the blocks.h header file. By default the blocks.h
header file is created the first time you run make which copies the default
config from blocks.def.h. This is so you can edit your status bar commands and
they will not get overwritten in a future update.
## Other Changes
Note that the intervals listed in blocks.h are in milliseconds (1/1000 second).
Because of this, the SECONDS() macro is provided for readability. I also
implemented some changes from Luke Smith's fork found
[here](https://github.com/LukeSmithxyz/dwmblocks).

View File

@ -3,13 +3,22 @@
static const Block blocks[] = {
/*Icon*/ /*Command*/ /*Update Interval*/ /*Update Signal*/
{"", "dwmblocks-battery", SECONDS(10), 0},
// {"", "dwmblocks-battery", SECONDS(10), 0},
{"", "[ \"$(fcitx5-remote)\" -eq 2 ] && printf '和' || printf '英'", 0, 2},
{"", "dwmblocks-mu4e", SECONDS(15), 0},
{"", "dwmblocks-volume", 0, 1},
{"", "date +'%a %b %d'", SECONDS(30), 0},
{"", "date +'%R'", SECONDS(2), 0},
{"", "dwmblocks-network", SECONDS(5), 0},
//{"", "dwmblocks-fcitx5", 250, 0},
};
#include "pulse-listener.h"
static const ThreadCallback thread_callbacks[] = {
pulse_listener_main
};
// sets delimeter between status commands. NULL character ('\0') means no delimeter.
static char delim[] = " ";
static unsigned int delimLen = 5;
static unsigned int delimLen = 2;

14
config.def.mk Normal file
View File

@ -0,0 +1,14 @@
PREFIX := /usr/local
CC := cc
CFLAGS := -pedantic -Wall -Wno-deprecated-declarations -Os
LDFLAGS := -lX11
PULSEFLAGS := -lpulse
NO_X =
# Uncomment to build without X11
# NO_X = -DNO_X
# FreeBSD (uncomment)
#LDFLAGS += -L/usr/local/lib -I/usr/local/include
# OpenBSD (uncomment)
#LDFLAGS += -L/usr/X11R6/lib -I/usr/X11R6/include

View File

@ -1,125 +0,0 @@
#include <pulse/pulseaudio.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/signal.h>
#include <limits.h>
#define ERROR(...) fprintf(stderr, "error: " __VA_ARGS__)
typedef struct {
size_t pid;
unsigned int signum;
} TargetData;
static void sink_info_callback(pa_context *ctx, const pa_sink_info *info,
int eol, TargetData *target) {
if (info && kill(target->pid, target->signum) < 0) {
ERROR("terget process died\n");
exit(1);
}
}
static void server_info_callback(pa_context *ctx, const pa_server_info *info,
TargetData *target) {
pa_operation *op = pa_context_get_sink_info_by_name(
ctx,
info->default_sink_name,
(pa_sink_info_cb_t) sink_info_callback,
target);
pa_operation_unref(op);
}
static void subscribe_callback(pa_context *ctx,
pa_subscription_event_type_t type, uint32_t idx,
TargetData *target) {
unsigned int facility = type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK;
pa_operation *op = NULL;
switch (facility) {
case PA_SUBSCRIPTION_EVENT_SINK:
op = pa_context_get_sink_info_by_index(ctx,
idx,
(pa_sink_info_cb_t) sink_info_callback,
target);
break;
}
if (op) {
pa_operation_unref(op);
}
}
static void state_callback(pa_context *ctx, TargetData *target) {
pa_operation *op;
switch (pa_context_get_state(ctx)) {
case PA_CONTEXT_READY:
op = pa_context_get_server_info(ctx,
(pa_server_info_cb_t) server_info_callback,
target);
pa_operation_unref(op);
pa_context_set_subscribe_callback(ctx,
(pa_context_subscribe_cb_t) subscribe_callback,
target);
op = pa_context_subscribe(ctx, PA_SUBSCRIPTION_MASK_SINK, NULL, NULL);
pa_operation_unref(op);
break;
case PA_CONTEXT_FAILED:
if (kill(target->pid, target->signum) < 0) {
ERROR("terget process died\n");
exit(1);
}
break;
default:
break;
}
}
int main(int argc, const char **argv) {
if (argc < 2) {
ERROR("no pid\n");
return 1;
}
char *endptr = NULL;
unsigned int signum = SIGRTMIN + 1;
if (argc >= 3 && argv[1][0] == '-') {
const char *signumstr = argv[1] + 1;
unsigned long num = strtoul(signumstr, &endptr, 10);
if (num > (SIGRTMAX - SIGRTMIN) + 1) {
ERROR("signal out of range: %lu\n", num);
return 1;
}
signum = SIGRTMIN + num;
++argv;
}
endptr = NULL;
errno = 0;
unsigned long pid = strtoul(argv[1], &endptr, 10);
if (argv[1][0] == '-' || errno == ERANGE) {
ERROR("pid out of range: \"%s\"\n", argv[1]);
return 1;
}
pa_mainloop *mainloop = pa_mainloop_new();
if (!mainloop) {
ERROR("could not create pulse mainloop\n");
return 1;
}
pa_mainloop_api *api = pa_mainloop_get_api(mainloop);
if (!api) {
ERROR("could not create pulse mainloop api\n");
return 1;
}
pa_context *context = pa_context_new(api, "dwmblocks-listener");
if (!context) {
ERROR("could not create pulse context\n");
return 1;
}
TargetData target = { pid, signum };
pa_context_set_state_callback( context,
(pa_context_notify_cb_t)&state_callback,
&target);
if (pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) {
ERROR("could not connect to pulse");
return 1;
}
pa_mainloop_run(mainloop, NULL);
return 0;
}

View File

@ -5,12 +5,13 @@
#include<signal.h>
#include <time.h>
#include <math.h>
#include <pthread.h>
#ifndef NO_X
#include<X11/Xlib.h>
#endif
#ifdef __OpenBSD__
#define SIGPLUS SIGUSR1+1
#define SIGMINUS SIGUSR1-1
#define SIGPLUS (SIGUSR1 + 1)
#define SIGMINUS (SIGUSR1 - 1)
#else
#define SIGPLUS SIGRTMIN
#define SIGMINUS SIGRTMIN
@ -27,6 +28,7 @@ typedef struct {
unsigned int interval;
unsigned int signal;
} Block;
typedef void(*ThreadCallback)(pthread_t *);
void getcmd(const Block *block, char *output);
void getcmds(int time);
void getsigcmds(unsigned int signal);
@ -38,7 +40,9 @@ void setupsignals(void);
int getstatus(char *str, char *last);
void pstdout(void);
int gcd(int n1, int n2);
void startthreads(void);
void statusloop(void);
void stopthreads(void);
void termhandler(void);
#ifndef NO_X
void setroot(void);
@ -57,6 +61,10 @@ static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0};
static char statusstr[2][STATUSLENGTH];
static int statuscontinue = 1;
static pthread_t main_thread;
static pthread_t threads[LENGTH(thread_callbacks)];
static int initdone = 0;
//opens process *cmd and stores output in *output
void getcmd(const Block *block, char *output) {
strcpy(output, block->icon);
@ -87,7 +95,7 @@ void getcmds(int time) {
for (unsigned int i = 0; i < LENGTH(blocks); ++i) {
current = blocks + i;
if ((current->interval != 0 && time % current->interval == 0) || time == -1) {
getcmd(current,statusbar[i]);
getcmd(current, statusbar[i]);
}
}
}
@ -97,7 +105,7 @@ void getsigcmds(unsigned int signal) {
for (unsigned int i = 0; i < LENGTH(blocks); ++i) {
current = blocks + i;
if (current->signal == signal) {
getcmd(current,statusbar[i]);
getcmd(current, statusbar[i]);
}
}
}
@ -141,10 +149,18 @@ int getstatus(char *str, char *last) {
}
void pstdout() {
if (!getstatus(statusstr[0], statusstr[1])) { //Only write out if text has changed.
if (!initdone || !getstatus(statusstr[0], statusstr[1])) { //Only write out if text has changed.
return;
}
printf("%s\n",statusstr[0]);
printf("%s\n", statusstr[0]);
fflush(stdout);
}
void somebar_pstdout() {
if (!initdone || !getstatus(statusstr[0], statusstr[1])) { //Only write out if text has changed.
return;
}
printf("status %s\n", statusstr[0]);
fflush(stdout);
}
@ -158,6 +174,16 @@ int gcd(int n1, int n2) {
return n1;
}
void startthreads() {
main_thread = pthread_self();
for (int i = 0; i < LENGTH(thread_callbacks); ++i) {
pthread_create(&threads[i],
NULL,
(void *(*)(void *)) thread_callbacks[i],
&main_thread);
}
}
void statusloop() {
setupsignals();
unsigned int interval = -1;
@ -166,6 +192,7 @@ void statusloop() {
interval = gcd(blocks[i].interval, interval);
}
}
startthreads();
int i = 0;
getcmds(-1);
long nsec_part = interval * 1000000;
@ -174,6 +201,7 @@ void statusloop() {
const struct timespec sleeptime = { sec_part, nsec_part };
struct timespec tosleep = sleeptime;
while (statuscontinue) {
initdone = 1;
if (nanosleep(&tosleep, &tosleep) < 0) {
continue;
}
@ -183,13 +211,20 @@ void statusloop() {
}
}
void stopthreads() {
for (int i = 0; i < LENGTH(thread_callbacks); ++i) {
pthread_cancel(threads[i]);
pthread_join(threads[i], NULL);
}
}
void termhandler() {
statuscontinue = 0;
}
#ifndef NO_X
void setroot() {
if (!getstatus(statusstr[0], statusstr[1])) { //Only set root if text has changed.
if (!initdone || !getstatus(statusstr[0], statusstr[1])) { //Only set root if text has changed.
return;
}
XStoreName(dpy, root, statusstr[0]);
@ -214,6 +249,8 @@ int main(int argc, char** argv) {
strncpy(delim, argv[++i], delimLen);
} else if (strcmp("-p", argv[i]) == 0) {
writestatus = pstdout;
} else if (strcmp("-s", argv[i]) == 0) {
writestatus = somebar_pstdout;
}
}
#ifndef NO_X
@ -229,5 +266,6 @@ int main(int argc, char** argv) {
#ifndef NO_X
XCloseDisplay(dpy);
#endif
stopthreads();
return 0;
}

103
pulse-listener.c Normal file
View File

@ -0,0 +1,103 @@
#include "pulse-listener.h"
#include <pulse/pulseaudio.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <limits.h>
#define ERROR(...) fprintf(stderr, "error: " __VA_ARGS__)
#ifdef __OpenBSD__
#define SIGMAX (SIGUSR2 - 1)
#define SIGMIN (SIGUSR1 - 1)
#else
#define SIGMAX SIGRTMAX
#define SIGMIN SIGRTMIN
#endif
static void sink_info_callback(pa_context *ctx, const pa_sink_info *info,
int eol, pthread_t *main_thread) {
pthread_kill(*main_thread, SIGMIN + 1);
}
static void server_info_callback(pa_context *ctx, const pa_server_info *info,
pthread_t *main_thread) {
pa_operation *op = pa_context_get_sink_info_by_name(
ctx,
info->default_sink_name,
(pa_sink_info_cb_t) sink_info_callback,
main_thread);
pa_operation_unref(op);
}
static void subscribe_callback(pa_context *ctx,
pa_subscription_event_type_t type, uint32_t idx,
pthread_t *main_thread) {
if ((type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) {
pa_operation *op = pa_context_get_sink_info_by_index(ctx,
idx,
(pa_sink_info_cb_t) sink_info_callback,
main_thread);
pa_operation_unref(op);
}
}
static void state_callback(pa_context *ctx, pthread_t *main_thread) {
pa_operation *op;
switch (pa_context_get_state(ctx)) {
case PA_CONTEXT_READY:
op = pa_context_get_server_info(ctx,
(pa_server_info_cb_t) server_info_callback,
main_thread);
pa_operation_unref(op);
pa_context_set_subscribe_callback(ctx,
(pa_context_subscribe_cb_t) subscribe_callback,
main_thread);
op = pa_context_subscribe(ctx, PA_SUBSCRIPTION_MASK_SINK, NULL, NULL);
pa_operation_unref(op);
break;
case PA_CONTEXT_FAILED:
pthread_kill(*main_thread, SIGMIN + 1);
break;
default:
break;
}
}
static void cleanup(void *data_to_free[2]) {
pa_context_unref(data_to_free[1]);
pa_mainloop_free(data_to_free[0]);
}
void pulse_listener_main(pthread_t *main_thread) {
pthread_setcanceltype(PTHREAD_CANCEL_DISABLE, NULL);
pa_mainloop *mainloop = pa_mainloop_new();
if (!mainloop) {
ERROR("could not create pulse mainloop\n");
return;
}
pa_mainloop_api *api = pa_mainloop_get_api(mainloop);
if (!api) {
ERROR("could not create pulse mainloop api\n");
return;
}
pa_context *context = pa_context_new(api, "dwmblocks-listener");
if (!context) {
ERROR("could not create pulse context\n");
return;
}
pa_context_set_state_callback(context,
(pa_context_notify_cb_t)&state_callback,
main_thread);
if (pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) {
ERROR("could not connect to pulse\n");
return;
}
void *data_to_free[2] = { mainloop, context };
pthread_cleanup_push((void(*)(void *)) cleanup, data_to_free);
pthread_setcanceltype(PTHREAD_CANCEL_ENABLE, NULL);
pa_mainloop_run(mainloop, NULL);
pthread_cleanup_pop(1);
}

8
pulse-listener.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef INCLUDED_PULSE_LISTENER_H
#define INCLUDED_PULSE_LISTENER_H
#include <pthread.h>
void pulse_listener_main(pthread_t *main_thread);
#endif

View File

@ -9,42 +9,37 @@ if [[ "$(uname)" = 'Linux' ]]; then
function is_adapted_connected {
let connected="$(cat /sys/class/power_supply/ADP1/online)"
if ((${connected} == 1)); then
echo 'true'
else
echo 'false'
fi
((${connected} == 1))
}
function get_battery_icon {
function print_battery_icon {
let charge_percent="${1}"
if "$(is_adapted_connected)"; then
echo -n ''
elif ((${charge_percent} <= 10)); then
echo -n ''
if ((${charge_percent} <= 10)); then
echo -n '󰂃'
elif ((${charge_percent} <= 20)); then
echo -n ''
echo -n '󰁻'
elif ((${charge_percent} <= 30)); then
echo -n ''
echo -n '󰁼'
elif ((${charge_percent} <= 40)); then
echo -n ''
echo -n '󰁽'
elif ((${charge_percent} <= 50)); then
echo -n ''
echo -n '󰁾'
elif ((${charge_percent} <= 60)); then
echo -n ''
echo -n '󰁿'
elif ((${charge_percent} <= 70)); then
echo -n ''
echo -n '󰂀'
elif ((${charge_percent} <= 80)); then
echo -n ''
echo -n '󰂁'
elif ((${charge_percent} < 100)); then
echo -n ''
echo -n '󰂂'
else
echo -n ''
echo -n '󰁹'
fi
}
let cp="$(get_battery_percent)"
get_battery_icon "${cp}"
print_battery_icon "${cp}"
is_adapted_connected && echo -n '󱐋'
printf '%3d%%\n' "${cp}"
# Linux ends here
else

12
scripts/dwmblocks-fcitx5 Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env zsh
local ime_sym=''
case "$(fcitx5-remote -n)" in
'keyboard-us')
ime_sym=''
;;
'mozc')
ime_sym="和"
;;
esac
printf '󰌌 %s' "${ime_sym}"

3
scripts/dwmblocks-mu4e Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env zsh
let message_count="$(mu find flag:unread AND maildir:/protonmail/Inbox 2>/dev/null | wc -l)"
(( "${message_count}" > 0 )) && printf ' %s' "${message_count}"

View File

@ -3,11 +3,11 @@
if [[ "$(uname)" = 'Linux' ]]; then
local active_networks="$(nmcli c s --active)"
local output=''
[[ "${active_networks}" = *' wifi '* ]] && output="${output} "
[[ "${active_networks}" = *' ethernet '* ]] && output="${output}"
[[ "${active_networks}" = *' wireguard '* ]] && output="${output} "
(( ${#output} == 0 )) && output=''
bluetoothctl show | grep 'Powered: yes' >/dev/null && output="${output} "
[[ "${active_networks}" = *' wifi '* ]] && output="${output}󰖩 "
[[ "${active_networks}" = *' ethernet '* ]] && output="${output}󰈁"
[[ "${active_networks}" = *' wireguard '* ]] && output="${output}󰖂 "
(( ${#output} == 0 )) && output='󰈂'
bluetoothctl show | grep 'Powered: yes' >/dev/null && output="${output}  "
printf '%s\n' "${output}"
else
echo "${0}: error: unknown os: \"$(uname)\"" >&2

View File

@ -3,12 +3,12 @@
let volume="$(pamixer --get-volume)"
local icon
if [[ "$(pamixer --get-mute)" = "true" ]]; then
icon=''
icon='󰸈'
elif ((${volume} > 50)); then
icon=''
elif ((${volume} > 0)); then
icon='奔'
icon='󰕾'
elif ((${volume} >= 0)); then
icon='󰖀'
else
icon=''
icon=''
fi
printf '%s%3d%%\n' "${icon}" "${volume}"