/sys/doc/ Documentation archive


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

audio mixer



Here is a very simple audio mixer which I put together
to control a SB audio card on inferno/plan9. I'll convert it
into a library  but  though maybe someone could be 
interested on it right now.



implement WmMixer;

include "sys.m";
	sys: Sys;

include "draw.m";
	draw: Draw;
	Rect, Display, Image: import draw;
	ctxt: ref Draw->Context;

include "tk.m";
	tk: Tk;
	Toplevel: import tk;

include "tklib.m";
	tklib: Tklib;

include	"wmlib.m";
	wmlib: Wmlib;

include "bufio.m";
bufio: Bufio;
Iobuf: import bufio;


WmMixer: module
{
	init:	fn(ctxt: ref Draw->Context, argv: list of string);
};

mixer_cfg := array[50] of string;

Ctl: adt {
	titlename: string;
	tkname:	string;
	devnam:	string;
	default:	int;
};


ctltab := array[20] of { Ctl
	("Volume","audio", "audio out", 50),
	("Speakers","speaker", "speaker out", 0),
	("Treble","treb", "treb out", 50),
	("Bass","bass", "bass out", 50),
#	("CD", "cd", "cd", 0),
	("Line", "line", "line", 0),
#	("Mic","mic", "mic", 0),
	("","", "", 0)
};

afd: ref sys->FD;

init(xctxt: ref Draw->Context, argv: list of string)
{
	sys  = load Sys  Sys->PATH;
	draw = load Draw Draw->PATH;
	tk   = load Tk   Tk->PATH;
	wmlib= load Wmlib Wmlib->PATH;
	tklib= load Tklib Tklib->PATH;
	bufio = load Bufio Bufio->PATH;

	ctxt = xctxt;

	tklib->init(ctxt);
	wmlib->init();

	tkargs := "";
	argv = tl argv;
	if(argv != nil) {
		tkargs = hd argv;
		argv = tl argv;
	}

	t := tk->toplevel(ctxt.screen, tkargs+" -borderwidth 2 -relief raised");

	menubut := wmlib->titlebar(t, "Mixer", Wmlib->Appl);

	cmd := chan of string;
	tk->namechan(t, cmd, "c");

	# generate tk cmd based on ctltab
	names:="";
	for (i:=0; i < len ctltab &&  ctltab[i].titlename != nil; i++) {
		mixer_cfg[i] = "scale ."+ctltab[i].tkname+" -orient horizontal -from -0 "+
			"-to 100 -label {"+ctltab[i].titlename+"} -command { send c "+
			ctltab[i].tkname+"}";
		names += "."+ctltab[i].tkname+" ";
	}
	mixer_cfg[i++]="pack .Wm_t -fill x";
	mixer_cfg[i++]="pack "+names+" -fill x";
	mixer_cfg[i++]="pack propagate . 0";
	mixer_cfg[i++]="update";

	tklib->tkcmds(t, mixer_cfg);

	parsevol(t);

	for(;;) alt {
	menu := <-menubut =>
		if(menu[0] == 'e') {
			return;
		}
		wmlib->titlectl(t, menu);
	action := <-cmd =>
		# action syntax is "obj val"
		sp:=-1;
		for (i := 0; i < len action; i++) if (action[i] == ' ') sp = i;
		if (sp != -1) {
			which := action[0:sp];
			val:= int action[sp+1:];
			setvol(which,val);
		}
	}
}

parsevol(top: ref Tk->Toplevel)
{
	if ((vol := bufio->open("/dev/volume", bufio->ORDWR)) == nil) {
		sys->print("Audioctl: Can't open /dev/volume: %r\n");
		exit;
	}
	while ((s := vol.gets('\n')) != nil) {
		sp := -1;
		for (i := 0; i < len s; i++) if (s[i] == ' ') sp = i;
		if (sp <= 1) {
			sys->print("Audioctl: /dev/volume bad:\n%s\n", s);
			exit;
		}
		for (i = 0; i < len ctltab && ctltab[i].titlename != nil; i++) {
			if (ctltab[i].devnam == s[0:sp]) {
				setvol(ctltab[i].devnam,ctltab[i].default);
				tk->cmd(top,"."+ctltab[i].tkname+" set "+string ctltab[i].default);
			}
		}
	}
	tk->cmd(top,"update");
	vol.close();
}

setvol(name: string, val: int)
{
	if (afd == nil) {
		afd = sys->open("/dev/volume", sys->ORDWR);
		if(afd == nil) {
			sys->print("Audioctl: Can't open /dev/volume: %r\n");
			exit;
		}
	}
	s:=name+" "+string val;
	b := array of byte s;
	l := len b;
	sys->write(afd,b,l);
}