123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- #include "u.h"
- #include "lib.h"
- #include "dat.h"
- #include "fns.h"
- #include "error.h"
- #include "devaudio.h"
- enum
- {
- Qdir = 0,
- Qaudio,
- Qvolume,
- Aclosed = 0,
- Aread,
- Awrite,
- Speed = 44100,
- Ncmd = 50, /* max volume command words */
- };
- Dirtab
- audiodir[] =
- {
- ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
- "audio", {Qaudio}, 0, 0666,
- "volume", {Qvolume}, 0, 0666,
- };
- static struct
- {
- QLock lk;
- Rendez vous;
- int amode; /* Aclosed/Aread/Awrite for /audio */
- } audio;
- #define aqlock(a) qlock(&(a)->lk)
- #define aqunlock(a) qunlock(&(a)->lk)
- static struct
- {
- char* name;
- int flag;
- int ilval; /* initial values */
- int irval;
- } volumes[] =
- {
- "audio", Fout, 50, 50,
- "synth", Fin|Fout, 0, 0,
- "cd", Fin|Fout, 0, 0,
- "line", Fin|Fout, 0, 0,
- "mic", Fin|Fout|Fmono, 0, 0,
- "speaker", Fout|Fmono, 0, 0,
- "treb", Fout, 50, 50,
- "bass", Fout, 50, 50,
- "speed", Fin|Fout|Fmono, Speed, Speed,
- 0
- };
- static char Emode[] = "illegal open mode";
- static char Evolume[] = "illegal volume specifier";
- static void
- resetlevel(void)
- {
- int i;
- for(i=0; volumes[i].name; i++)
- audiodevsetvol(i, volumes[i].ilval, volumes[i].irval);
- }
- static void
- audioinit(void)
- {
- }
- static Chan*
- audioattach(char *param)
- {
- return devattach('A', param);
- }
- static Walkqid*
- audiowalk(Chan *c, Chan *nc, char **name, int nname)
- {
- return devwalk(c, nc, name, nname, audiodir, nelem(audiodir), devgen);
- }
- static int
- audiostat(Chan *c, uchar *db, int n)
- {
- return devstat(c, db, n, audiodir, nelem(audiodir), devgen);
- }
- static Chan*
- audioopen(Chan *c, int omode)
- {
- int amode;
- switch((ulong)c->qid.path) {
- default:
- error(Eperm);
- break;
- case Qvolume:
- case Qdir:
- break;
- case Qaudio:
- amode = Awrite;
- if((omode&7) == OREAD)
- amode = Aread;
- aqlock(&audio);
- if(waserror()){
- aqunlock(&audio);
- nexterror();
- }
- if(audio.amode != Aclosed)
- error(Einuse);
- audiodevopen();
- audio.amode = amode;
- poperror();
- aqunlock(&audio);
- break;
- }
- c = devopen(c, omode, audiodir, nelem(audiodir), devgen);
- c->mode = openmode(omode);
- c->flag |= COPEN;
- c->offset = 0;
- return c;
- }
- static void
- audioclose(Chan *c)
- {
- switch((ulong)c->qid.path) {
- default:
- error(Eperm);
- break;
- case Qdir:
- case Qvolume:
- break;
- case Qaudio:
- if(c->flag & COPEN) {
- aqlock(&audio);
- audiodevclose();
- audio.amode = Aclosed;
- aqunlock(&audio);
- }
- break;
- }
- }
- static long
- audioread(Chan *c, void *v, long n, vlong off)
- {
- int liv, riv, lov, rov;
- long m;
- char buf[300];
- int j;
- ulong offset = off;
- char *a;
- a = v;
- switch((ulong)c->qid.path) {
- default:
- error(Eperm);
- break;
- case Qdir:
- return devdirread(c, a, n, audiodir, nelem(audiodir), devgen);
- case Qaudio:
- if(audio.amode != Aread)
- error(Emode);
- aqlock(&audio);
- if(waserror()){
- aqunlock(&audio);
- nexterror();
- }
- n = audiodevread(v, n);
- poperror();
- aqunlock(&audio);
- break;
- case Qvolume:
- j = 0;
- buf[0] = 0;
- for(m=0; volumes[m].name; m++){
- audiodevgetvol(m, &lov, &rov);
- liv = lov;
- riv = rov;
- j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name);
- if((volumes[m].flag & Fmono) || (liv==riv && lov==rov)){
- if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov)
- j += snprint(buf+j, sizeof(buf)-j, " %d", liv);
- else{
- if(volumes[m].flag & Fin)
- j += snprint(buf+j, sizeof(buf)-j,
- " in %d", liv);
- if(volumes[m].flag & Fout)
- j += snprint(buf+j, sizeof(buf)-j,
- " out %d", lov);
- }
- }else{
- if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) &&
- liv==lov && riv==rov)
- j += snprint(buf+j, sizeof(buf)-j,
- " left %d right %d",
- liv, riv);
- else{
- if(volumes[m].flag & Fin)
- j += snprint(buf+j, sizeof(buf)-j,
- " in left %d right %d",
- liv, riv);
- if(volumes[m].flag & Fout)
- j += snprint(buf+j, sizeof(buf)-j,
- " out left %d right %d",
- lov, rov);
- }
- }
- j += snprint(buf+j, sizeof(buf)-j, "\n");
- }
- return readstr(offset, a, n, buf);
- }
- return n;
- }
- static long
- audiowrite(Chan *c, void *vp, long n, vlong off)
- {
- long m;
- int i, v, left, right, in, out;
- Cmdbuf *cb;
- char *a;
- USED(off);
- a = vp;
- switch((ulong)c->qid.path) {
- default:
- error(Eperm);
- break;
- case Qvolume:
- v = Vaudio;
- left = 1;
- right = 1;
- in = 1;
- out = 1;
- cb = parsecmd(vp, n);
- if(waserror()){
- free(cb);
- nexterror();
- }
- for(i = 0; i < cb->nf; i++){
- /*
- * a number is volume
- */
- if(cb->f[i][0] >= '0' && cb->f[i][0] <= '9') {
- m = strtoul(cb->f[i], 0, 10);
- if(!out)
- goto cont0;
- if(left && right)
- audiodevsetvol(v, m, m);
- else if(left)
- audiodevsetvol(v, m, -1);
- else if(right)
- audiodevsetvol(v, -1, m);
- goto cont0;
- }
- for(m=0; volumes[m].name; m++) {
- if(strcmp(cb->f[i], volumes[m].name) == 0) {
- v = m;
- in = 1;
- out = 1;
- left = 1;
- right = 1;
- goto cont0;
- }
- }
- if(strcmp(cb->f[i], "reset") == 0) {
- resetlevel();
- goto cont0;
- }
- if(strcmp(cb->f[i], "in") == 0) {
- in = 1;
- out = 0;
- goto cont0;
- }
- if(strcmp(cb->f[i], "out") == 0) {
- in = 0;
- out = 1;
- goto cont0;
- }
- if(strcmp(cb->f[i], "left") == 0) {
- left = 1;
- right = 0;
- goto cont0;
- }
- if(strcmp(cb->f[i], "right") == 0) {
- left = 0;
- right = 1;
- goto cont0;
- }
- error(Evolume);
- break;
- cont0:;
- }
- free(cb);
- poperror();
- break;
- case Qaudio:
- if(audio.amode != Awrite)
- error(Emode);
- aqlock(&audio);
- if(waserror()){
- aqunlock(&audio);
- nexterror();
- }
- n = audiodevwrite(vp, n);
- poperror();
- aqunlock(&audio);
- break;
- }
- return n;
- }
- void
- audioswab(uchar *a, uint n)
- {
- ulong *p, *ep, b;
- p = (ulong*)a;
- ep = p + (n>>2);
- while(p < ep) {
- b = *p;
- b = (b>>24) | (b<<24) |
- ((b&0xff0000) >> 8) |
- ((b&0x00ff00) << 8);
- *p++ = b;
- }
- }
- Dev audiodevtab = {
- 'A',
- "audio",
- devreset,
- audioinit,
- devshutdown,
- audioattach,
- audiowalk,
- audiostat,
- audioopen,
- devcreate,
- audioclose,
- audioread,
- devbread,
- audiowrite,
- devbwrite,
- devremove,
- devwstat,
- };
|