ref: b8559f471b8904b3033ca397e9582ae74da7056f
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Tue Nov 17 11:23:47 EST 2020
wat.
--- /dev/null
+++ b/README.md
@@ -1,0 +1,9 @@
+# jacksense
+
+A small program to track whether headphones are connected to jack or
+not, and switch between speaker and headphones output accordingly.
+
+It tries to remember the last volume. There are arguments to pass
+"safe" volumes for both speaker and headphones.
+
+Prerequisites: 9front, Intel HDA.
--- /dev/null
+++ b/jacksense.c
@@ -1,0 +1,86 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+static void
+usage(void)
+{
+ fprint(2, "usage: %s [-h hp_safe_volume] [-s sp_safe_volume]\n", argv0);
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ int hp, sp, cmd, ctl, vol, lastvol, newvol;
+ int hpsafevol, spsafevol;
+ u32int x, y[4], has, had;
+ Biobuf *b;
+ char *s, *a[16], tmp[32];
+
+ hpsafevol = 65;
+ spsafevol = 70;
+ ARGBEGIN{
+ case 'h':
+ hpsafevol = atoi(EARGF(usage()));
+ break;
+ case 's':
+ spsafevol = atoi(EARGF(usage()));
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if((cmd = open("/dev/hdacmd", ORDWR)) < 0)
+ sysfatal("%r");
+ if((ctl = open("/dev/audioctl", OWRITE)) < 0)
+ sysfatal("%r");
+ if((vol = open("/dev/volume", ORDWR)) < 0)
+ sysfatal("%r");
+ if((b = Bopen("/dev/audiostat", OREAD)) == nil)
+ sysfatal("%r");
+ sp = -1;
+ hp = -1;
+ while((sp < 0 || hp < 0) && (s = Brdline(b, '\n')) != nil){
+ s[Blinelen(b)-1] = 0;
+ if(tokenize(s, a, nelem(a)) < 8)
+ continue;
+ if(strcmp(a[0], "pin") != 0 || strcmp(a[2], "out") != 0)
+ continue;
+ if(strcmp(a[3], "jack") == 0 && strcmp(a[6], "hpout") == 0)
+ hp = atoi(a[1]);
+ if(strcmp(a[3], "fix") == 0 && strcmp(a[6], "speaker") == 0)
+ sp = atoi(a[1]);
+ }
+ if(sp < 0 || hp < 0){
+ fprint(2, "couldn't detect pins\n");
+ exits("pins");
+ }
+
+ x = 0x0f0900 | (hp<<4)<<16 | (hp>>4)<<24;
+ had = -1;
+ lastvol = (spsafevol < hpsafevol ? spsafevol : hpsafevol)*2/3;
+ for(;;){
+ if(write(cmd, &x, 4) != 4 || read(cmd, y, sizeof(y)) < 4)
+ sysfatal("failed");
+ has = y[0] & (1<<31);
+ if(has != had){
+ newvol = lastvol;
+ if(pread(vol, tmp, sizeof(tmp)-1, 0) > 0 && strncmp(tmp, "master ", 7) == 0)
+ lastvol = atoi(tmp+7);
+ if(had == ~0)
+ newvol = lastvol;
+
+ /* SAVE MY EARS, OK? THANKS */
+ if(has && newvol > hpsafevol)
+ newvol = hpsafevol;
+ else if(!has && newvol > spsafevol)
+ newvol = spsafevol;
+
+ fprint(ctl, "pin %d\n", has ? hp : sp);
+ fprint(vol, "%d\n", newvol);
+ }
+ had = has;
+ sleep(300);
+ }
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,14 @@
+</$objtype/mkfile
+
+BIN=/$objtype/bin/audio
+TARG=jacksense
+CFLAGS=$CFLAGS -p
+
+HFILES=\
+
+OFILES=\
+ jacksense.$O\
+
+default:V: all
+
+</sys/src/cmd/mkone