mowc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/mowc
Log | Files | Refs

commit 76393edbbca379c26b86ce81da73490925d4bc70
parent 9912b47cdd62ca7b82a4f06b268aea71132c809d
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Mon,  5 Jul 2021 19:02:41 -0500

overlay: modem power control and brightness control

Diffstat:
Mclients/overlay.c | 225++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 211 insertions(+), 14 deletions(-)

diff --git a/clients/overlay.c b/clients/overlay.c @@ -2,7 +2,10 @@ #include <stddef.h> #include <alsa/asoundlib.h> #include <alsa/control.h> +#include <signal.h> #include <stdio.h> +#include <sys/signalfd.h> +#include <time.h> #include <wld/wayland.h> #include <wld/wld.h> #include <wayland-client.h> @@ -13,11 +16,20 @@ #define LENGTH(a) (sizeof((a)) / sizeof((a)[0])) +#define MAX_BRIGHTNESS_FILE "/sys/class/backlight/backlight/max_brightness" +#define BRIGHTNESS_FILE "/sys/class/backlight/backlight/brightness" +#define MODEM_POWER_FILE "/sys/class/modem-power/modem-power/device/powered" + +#define SLIDER_WIDTH 20 + snd_ctl_t *ctl; +timer_t timer; enum { SchemeNormal, SchemeOn, + SchemeSlider, + SchemePending, SchemeLast, }; @@ -25,6 +37,8 @@ static const char *colors[SchemeLast][2] = { /* fg bg */ [SchemeNormal] = { "#ffffff", "#000000" }, [SchemeOn] = { "#00ff00", "#000000" }, + [SchemePending] = { "#ff0000", "#000000" }, + [SchemeSlider] = { "#0000ff", "#ff0000" }, }; static Clr* scheme[SchemeLast]; @@ -44,12 +58,16 @@ struct { } wl; enum item { + ItemNone, ToggleMic, ToggleSpk, ToggleEar, ToggleHPOut, ToggleHPIn, - ItemNone + ToggleModem, + ToggleLast, + SliderBrightness, + SliderLast } pressed, current; struct text_data { @@ -61,17 +79,27 @@ struct text_data { [ToggleEar] = { "Ear" }, [ToggleHPOut] = { "HPOut" }, [ToggleHPIn] = { "HPIn" }, + [ToggleModem] = { "Modem" }, + [SliderBrightness] = { "Brightness" }, }; struct toggle { struct text_data *td; bool on; + bool pending; } toggles[] = { [ToggleMic] = { &text_data[ToggleMic] }, [ToggleSpk] = { &text_data[ToggleSpk] }, [ToggleEar] = { &text_data[ToggleEar] }, [ToggleHPOut] = { &text_data[ToggleHPOut] }, [ToggleHPIn] = { &text_data[ToggleHPIn] }, + [ToggleModem] = { &text_data[ToggleModem] }, +}; + +struct slider { + int min, max, cur; +} sliders[] = { + [SliderBrightness] = {}, }; enum { @@ -254,6 +282,8 @@ void touchframe(void *data, struct wl_touch *wl_touch); void touchcancel(void *data, struct wl_touch *wl_touch); void toggle_control(int control, enum item toggle); +static void toggle_modem(); +static void writenum(const char *file, long num); static struct wl_registry_listener reglistener = { regglobal, regglobalremove }; @@ -327,16 +357,38 @@ getpressed() { int height = wl.h / 8; int width = wl.w / 2; - int idx = 2 * (touchpoint.y / height) + touchpoint.x / width; + int idx = 2 * (touchpoint.y / height) + touchpoint.x / width + ToggleMic; - /* ItemNone is after last toggle */ - if (idx < ItemNone) + /* Is a toggle */ + if (ItemNone < idx && idx < ToggleLast) return idx; + + /* a slider */ + int level = (touchpoint.y - ((SliderBrightness / 2) * height)) / height; + + if (level >= 0 && level < SliderLast - SliderBrightness) + return SliderBrightness + level; + return ItemNone; } void +update_slider(enum item item) +{ + if (SliderBrightness <= item && item < SliderLast) { + struct slider s = sliders[pressed]; + s.cur = s.min + ((s.max - s.min) * (touchpoint.x - SLIDER_WIDTH / 2)) / wl.w; + /* overflow... */ + if (s.cur > 10*s.max) + s.cur = s.min; + else if (s.cur > s.max) + s.cur = s.max; + writenum(BRIGHTNESS_FILE, s.cur); + } +} + +void touchdown(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y) { if (touchpoint.down) @@ -347,7 +399,7 @@ touchdown(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, touchpoint.y = wl_fixed_to_int(y); touchpoint.id = id; current = pressed = getpressed(); - draw(); + update_slider(pressed); } void @@ -380,10 +432,15 @@ touchup(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, i toggle_control(MIC2_CAPTURE_SWITCH, ToggleHPIn); fprintf(stderr, "toggle hpin\n"); break; + case ToggleModem: + toggle_modem(); + fprintf(stderr, "toggle modem\n"); + break; } } current = pressed = ItemNone; + fprintf(stderr, "modem shit: %d, %d\n", toggles[ToggleModem].on, toggles[ToggleModem].pending); draw(); } @@ -396,7 +453,7 @@ touchmotion(void *data, struct wl_touch *wl_touch, uint32_t time, int32_t id, wl touchpoint.x = wl_fixed_to_int(x); touchpoint.y = wl_fixed_to_int(y); current = getpressed(); - draw(); + update_slider(pressed); } void @@ -421,6 +478,29 @@ toggle_control(int control, enum item toggle) toggles[toggle].on = v; } +static const struct itimerspec on_value = { + .it_interval = { 0, 0 }, + .it_value = { 19, 0 } +}; +static const struct itimerspec off_value = { + .it_value = { 0, 0 } +}; + +void +toggle_modem() +{ + if (toggles[ToggleModem].on) { + writenum(MODEM_POWER_FILE, 0); + toggles[ToggleModem].pending = 0; + toggles[ToggleModem].on = 0; + timer_settime(timer, 0, &off_value, NULL); + } else { + writenum(MODEM_POWER_FILE, 1); + toggles[ToggleModem].pending = 1; + timer_settime(timer, 0, &on_value, NULL); + } +} + unsigned int val_from_enum_string(snd_ctl_t *ctl, snd_ctl_elem_info_t *oldinfo, const char *string) { @@ -532,20 +612,34 @@ draw() { int height = wl.h / 8; int width = wl.w / 2; - int x; + int x, level, pos; unsigned int tx, ty; wld_set_target_surface(wl.drw->renderer, wl.drw->surface); drw_setscheme(wl.drw, scheme[SchemeNormal]); drw_rect(wl.drw, 0, 0, wl.w, wl.h, 1, 1); - for (int i = 0; i < ItemNone; ++i) { - x = (i % 2) * width; + for (int i = ToggleMic; i < ToggleLast; ++i) { + pos = i - 1; + x = (pos % 2) * width; tx = x + width / 2 - text_data[i].tw / 2; - ty = height * (i / 2) + height / 2 - text_data[i].th / 2; + ty = height * (pos / 2) + height / 2 - text_data[i].th / 2; drw_setscheme(wl.drw, scheme[toggles[i].on ? SchemeOn : SchemeNormal]); - drw_rect(wl.drw, x, height * (i / 2), width, height, 1, 0); - drw_rect(wl.drw, x, height * (i / 2), width, height, 0, 1); + if (toggles[i].pending) { + fprintf(stderr, "we are pending!\n"); + drw_setscheme(wl.drw, scheme[SchemePending]); + } + drw_rect(wl.drw, x, height * (pos / 2), width, height, 1, 0); + drw_rect(wl.drw, x, height * (pos / 2), width, height, 0, 1); + drw_text(wl.drw, tx, ty, text_data[i].tw, text_data[i].th, 0, text_data[i].text, 1); + } + + level = (SliderBrightness / 2) * height; + for (int i = SliderBrightness; i < SliderLast; i++, level += height) { + tx = width - text_data[i].tw / 2; + ty = level + height / 2 - text_data[i].th / 2; + drw_setscheme(wl.drw, scheme[SchemeSlider]); + drw_rect(wl.drw, 0, level, wl.w, height, 1, 0); drw_text(wl.drw, tx, ty, text_data[i].tw, text_data[i].th, 0, text_data[i].text, 1); } @@ -587,10 +681,12 @@ wlinit(void) if (!wl.touch) die("seat has no touch support\n"); - for (j = 0; j < ItemNone; ++j) { + + for (j = ToggleMic; j < ToggleLast; ++j) { len = strlen(text_data[j].text); drw_font_getexts(&wl.drw->fonts[0], text_data[j].text, len, &text_data[j].tw, &text_data[j].th); } + drw_font_getexts(&wl.drw->fonts[0], text_data[SliderBrightness].text, len, &text_data[SliderBrightness].tw, &text_data[SliderBrightness].th); /* init appearance */ for (j = 0; j < SchemeLast; j++) @@ -613,19 +709,120 @@ wlinit(void) draw(); } +static long +readnum(const char *file) +{ + char buf[32]; + size_t ret; + long val; + FILE *mb = fopen(file, "r"); + if (mb == NULL) + die("failed to open %s\n", file); + + ret = fread(buf, 1, 32, mb); + if (ret == 0) + die("failed to read from %s\n", file); + + val = strtol(buf, NULL, 10); + if (val == LONG_MIN || val == LONG_MAX) + die("invalid max brightness\n"); + + fclose(mb); + + return val; +} + +void +writenum(const char *file, long num) +{ + char buf[32]; + size_t ret; + long val; + + if ((ret = snprintf(buf, 32, "%d\n", num)) < 0) { + die("snprintf failed\n"); + } + + FILE *mb = fopen(file, "w"); + if (mb == NULL) + die("failed to open %s\n", file); + + ret = fwrite(buf, 1, ret, mb); + if (ret == 0) + die("failed to write %s to %s\n", buf, file); + + fclose(mb); +} + +int +init_brightness() +{ + sliders[SliderBrightness].min = 0; + sliders[SliderBrightness].max = readnum(MAX_BRIGHTNESS_FILE); + sliders[SliderBrightness].cur = readnum(BRIGHTNESS_FILE); + + fprintf(stderr, "brightness: %d, %d, %d\n", sliders[SliderBrightness].min, sliders[SliderBrightness].max, sliders[SliderBrightness].cur); +} + int main() { + struct pollfd fds[2]; + struct signalfd_siginfo fdsi; + sigset_t signals; + size_t ret; + + sigemptyset(&signals); + sigaddset(&signals, SIGALRM); + sigprocmask(SIG_BLOCK, &signals, NULL); + + if (timer_create(CLOCK_MONOTONIC, NULL, &timer) == -1) { + fprintf(stderr, "failed to create timer %s\n", strerror(errno)); + return 1; + } + init_alsa(); + init_brightness(); toggles[ToggleMic].on = controls[MIC1_CAPTURE_SWITCH].vals.i[0]; toggles[ToggleSpk].on = controls[LINE_OUT_PLAYBACK_SWITCH].vals.i[0]; toggles[ToggleEar].on = controls[EARPIECE_PLAYBACK_SWITCH].vals.i[0]; toggles[ToggleHPIn].on = controls[MIC2_CAPTURE_SWITCH].vals.i[0]; toggles[ToggleHPOut].on = controls[HEADPHONE_PLAYBACK_SWITCH].vals.i[0]; + toggles[ToggleModem].on = readnum(MODEM_POWER_FILE); wlinit(); - while (wl_display_dispatch(wl.dpy) != -1); + fds[0].fd = wl_display_get_fd(wl.dpy); + fds[0].events = POLLIN; + fds[1].fd = signalfd(-1, &signals, 0); + fds[1].events = POLLIN; + + while (true) { + if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) == -1) + break; + + if (fds[0].revents & POLLIN) { + if (wl_display_dispatch(wl.dpy) == -1) + break; + } + + if (fds[1].revents & POLLIN) { + fprintf(stderr, "got signal!\n"); + ret = read(fds[1].fd, &fdsi, sizeof(fdsi)); + if (ret != sizeof(fdsi)) + break; + + if (fdsi.ssi_signo == SIGALRM) { + if (readnum(MODEM_POWER_FILE) == 1) { + toggles[ToggleModem].pending = 0; + toggles[ToggleModem].on = 1; + draw(); + } + } + } + + wl_display_flush(wl.dpy); + } snd_ctl_close(ctl); }