<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv=Content-Type content="text/html; charset=utf8"> <title>/usr/web/sources/contrib/dho/mixerfs.c - Plan 9 from Bell Labs</title> <!-- THIS FILE IS AUTOMATICALLY GENERATED. --> <!-- EDIT sources.tr INSTEAD. --> </meta> </head> <body> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;"> <span style="font-size: 10pt"><a href="/plan9/">Plan 9 from Bell Labs</a>’s /usr/web/sources/contrib/dho/mixerfs.c</span></p> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <center><font size=-1> Copyright © 2009 Alcatel-Lucent.<br /> Distributed under the <a href="/plan9/license.html">Lucent Public License version 1.02</a>. <br /> <a href="/plan9/download.html">Download the Plan 9 distribution.</a> </font> </center> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <table width="100%" cellspacing=0 border=0><tr><td align="center"> <table cellspacing=0 cellpadding=5 bgcolor="#eeeeff"><tr><td align="left"> <pre> <!-- END HEADER --> #include <u.h> #include <libc.h> #include <auth.h> #include <fcall.h> #include <thread.h> #include <9p.h> enum { Xmixer = 1, Mixmax = 16, }; Alt *a; Channel *outchan; int nmix; int audiofd; struct muxdata { short *data; long len; long ptr; }; void buffer_thread(void *_p) { struct muxdata *md = mallocz(Mixmax * sizeof(struct muxdata*), 1); int i, j, k, m, minlen, nalts; Req *r = nil; short *out = nil; short *p = nil; minlen = nalts = i = j = k = m = 0; USED(_p); while (1) { while (nmix == 0) sleep(1000); /* mux */ i = alt(a); print("data on alt %d\n", i); /* no more data */ if (i == nmix) { out = mallocz(minlen, 1); /* * we only work on the smallest buffer we have so we don't * over/underflow. */ for (j = 0; j < nalts; j++) for (k = 0; k < minlen; k++) { p = md[i].data + md[i].ptr; print ("p %p\n", p); out[k] += p[k]; md[i].ptr += minlen; if (md[i].ptr == md[i].len) { free(md[i].data); md[i].data = nil; md[i].ptr = md[i].len = 0; } } print ("Sending %d bytes\n", minlen); sendul(outchan, minlen); sendp(outchan, out); /* block waiting for more data */ a[i].op = CHANEND; minlen = nalts = 0; continue; } /* we're getting data, don't block anymore... */ a[nmix].op = CHANNOBLK; r = *(Req **)a[i].v; if (md[i].data == nil) { md[i].data = mallocz(r->ifcall.count, 1); md[i].ptr = 0; } else md[i].data = realloc(md[i].data, r->ifcall.count + md[i].len); if (md[i].data == nil) { respond(r, "no memory"); exits("no memory"); } for (int m = 0; m < r->ifcall.count; m++) { short *ptr = (short *)r->ifcall.data; md[i].data[md[i].len] = *ptr++; } memcpy((char *)(md[i].data + md[i].len), r->ifcall.data, r->ifcall.count); md[i].len += r->ifcall.count; if (minlen == 0 || md[i].len <minlen) minlen = md[i].len; r->ofcall.count = r->ifcall.count; print("oink ack %d bytes\n", r->ifcall.count); nalts++; } } void out_thread(void *p) { USED(p); while (1) { ulong len; short *r; len = recvul(outchan); r = recvp(outchan); print("received %l bytes\n", len); write(audiofd, r, len); } } void fsopen(Req *r) { int i = nmix++; a[nmix].c = a[nmix].v = nil; a[nmix].op = CHANEND; if (i == 16) { respond(r, "all channels in use"); return; } a[i].c = chancreate(sizeof(Req *), 0); a[i].op = CHANRCV; a[i].v = malloc(sizeof(Req *)); r->fid->aux = (void *)a[i].c; respond(r, nil); } void fswrite(Req *r) { Channel *c = (Channel *)r->fid->aux; /* don't bother if you can't fill our minimum buffer size */ if (r->ifcall.count < 8) { r->ofcall.count = 0; respond(r, nil); } else { print("Sending %l bytes\n", r->ifcall.count); sendp(c, r); } /* respond() done in buffer thread */ } Srv fs = { .open= fsopen, .write= fswrite, }; void threadmain(int argc, char **argv) { char *mtpt = "/dev/"; USED(argc); USED(argv); a = mallocz(16 * sizeof (Alt), 1); outchan = chancreate(sizeof (char *), 0); audiofd = open("/dev/audio", OWRITE); proccreate(buffer_thread, a, 32768); proccreate(out_thread, outchan, 32768); fs.tree = alloctree(nil, nil, DMDIR|0777, nil); closefile(createfile(fs.tree->root, "audio", nil, 0666, (void *)Xmixer)); threadpostmountsrv(&fs, "audiomux", mtpt, MBEFORE); recvp(chancreate(sizeof(void *), 0)); } <!-- BEGIN TAIL --> </pre> </td></tr></table> </td></tr></table> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;"> <span style="font-size: 10pt"></span></p> <p style="margin-top: 0; margin-bottom: 0.50in"></p> <p style="margin-top: 0; margin-bottom: 0.33in"></p> <center><table border="0"><tr> <td valign="middle"><a href="http://www.alcatel-lucent.com/"><img border="0" src="/plan9/img/logo_ft.gif" alt="Bell Labs" /> </a></td> <td valign="middle"><a href="http://www.opensource.org"><img border="0" alt="OSI certified" src="/plan9/img/osi-certified-60x50.gif" /> </a></td> <td><img style="padding-right: 45px;" alt="Powered by Plan 9" src="/plan9/img/power36.gif" /> </td> </tr></table></center> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <center> <span style="font-size: 10pt">(<a href="/plan9/">Return to Plan 9 Home Page</a>)</span> </center> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <center><font size=-1> <span style="font-size: 10pt"><a href="http://www.lucent.com/copyright.html">Copyright</a></span> <span style="font-size: 10pt">© 2009 Alcatel-Lucent.</span> <span style="font-size: 10pt">All Rights Reserved.</span> <br /> <span style="font-size: 10pt">Comments to</span> <span style="font-size: 10pt"><a href="mailto:webmaster@plan9.bell-labs.com">webmaster@plan9.bell-labs.com</a>.</span> </font></center> </body> </html>