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:
M | clients/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);
}