shithub: jacksense

ref: 4031e29206730363d343118b7325cd3be4b312bf
dir: /jacksense.c/

View raw version
#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, lp, cmd, ctl, vol, lastvol, newvol;
	int debug, hpsafevol, spsafevol;
	u32int x, y[4], has, had, c;
	char *s, *a[16], tmp[32];
	Biobuf *b;

	debug = 0;
	hpsafevol = 65;
	spsafevol = 70;
	ARGBEGIN{
	case 'd':
		debug++;
		break;
	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;
	lp = -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 && strcmp(a[2], "inout") != 0))
			continue;
		if(strcmp(a[3], "jack") == 0 && strcmp(a[6], "hpout") == 0){
			hp = atoi(a[1]);
			if(debug) fprint(2, "hpout pin %d\n", hp);
		}
		if(strcmp(a[3], "fix") == 0){
			if(strcmp(a[6], "speaker") == 0){
				sp = atoi(a[1]);
				if(debug) fprint(2, "speaker pin %d\n", sp);
			}else if(strcmp(a[4], "int") == 0){
				/* fallback for built-in speakers/etc */
				lp = atoi(a[1]);
				if(debug) fprint(2, "speaker fallback pin %d\n", lp);
			}
		}
	}
	Bterm(b);
	if(sp < 0)
		sp = lp;
	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(;;){
		c = 0;
again:
		if(write(cmd, &x, 4) != 4 || read(cmd, y, sizeof(y)) < 4)
			sysfatal("command failed: %r");
		has = y[0] & (1<<31);
		if(has != had){
			if(c++ < 2){
				sleep(75);
				goto again;
			}
			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;

			if(fprint(ctl, "pin %d", has ? hp : sp) < 0)
				fprint(2, "vol: %r\n");
			if(fprint(vol, "master 0 0") < 0)
				fprint(2, "vol: %r\n");
			sleep(100);
			if(fprint(vol, "master %d %d", newvol, newvol) < 0)
				fprint(2, "vol: %r\n");
		}
		had = has;
		sleep(300);
	}
}