ref: e6819e877e1d9aec3a374fdce1fa1f463fc19ec3
parent: 396e564996f3666b1ad4c10b4ad21dade40607e9
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Fri Jan 18 20:12:39 EST 2013
audiohda: first attempt on audio recording support for intel hda audio, distinguish mode in audio code
--- a/sys/src/9/pc/audioac97.c
+++ b/sys/src/9/pc/audioac97.c
@@ -306,7 +306,7 @@
inavail(void *arg)
{Ring *r = arg;
- return buffered(r);
+ return buffered(r) > 0;
}
static int
@@ -313,7 +313,7 @@
outavail(void *arg)
{Ring *r = arg;
- return available(r);
+ return available(r) > 0;
}
static int
@@ -386,11 +386,14 @@
}
static void
-ac97close(Audio *adev)
+ac97close(Audio *adev, int mode)
{Ctlr *ctlr;
Ring *ring;
uchar z[1];
+
+ if(mode == OREAD)
+ return;
z[0] = 0;
ctlr = adev->ctlr;
--- a/sys/src/9/pc/audiohda.c
+++ b/sys/src/9/pc/audiohda.c
@@ -11,6 +11,8 @@
typedef struct Ctlr Ctlr;
typedef struct Bld Bld;
typedef struct Ring Ring;
+typedef struct Stream Stream;
+
typedef struct Id Id;
typedef struct Widget Widget;
typedef struct Codec Codec;
@@ -226,6 +228,26 @@
ulong wi;
};
+struct Stream {+ Ring ring;
+
+ Bld *blds;
+
+ uint sdctl;
+ uint sdintr;
+ uint sdnum;
+
+ uint afmt;
+ uint atag;
+ int active;
+
+ uint pin;
+ uint cad;
+
+ Widget *conv; /* DAC or ADC */
+ Widget *jack; /* the pin jack */
+};
+
struct Id {Ctlr *ctlr;
uint codec, nid;
@@ -245,8 +267,10 @@
uint convrate, convfmt;
};
};
- Widget *next;
- Widget *from;
+ Widget *next; /* next in function group */
+ Widget *path; /* next in audio path */
+
+ Widget *link; /* temporary for findpath */
};
struct Fungroup {@@ -254,8 +278,6 @@
Codec *codec;
uint type;
Widget *first;
- Widget *mixer;
- Widget *src, *dst;
Fungroup *next;
};
@@ -294,25 +316,13 @@
ulong *rirb;
ulong rirbsize;
- uint sdctl;
- uint sdintr;
- uint sdnum;
+ Stream sout;
+ Stream sin;
- Bld *blds;
-
- Ring ring;
-
uint iss, oss, bss;
uint codecmask;
Codec *codec[Maxcodecs];
-
- Widget *amp, *src;
- uint pin;
- uint cad;
-
- int active;
- uint afmt, atag;
};
#define csr32(c, r) (*(ulong *)&(c)->mem[r])
@@ -589,55 +599,84 @@
}
static Widget *
-findpath(Widget *src)
+findpath(Widget *jack, int type)
{Widget *q[Maxwidgets];
uint l, r, i;
- Widget *w, *v;
-
+ Widget *w, *to;
+
l = r = 0;
- q[r++] = src;
- for(w=src->fg->first; w; w=w->next)
- w->from = nil;
- src->from = src;
+ for(w=jack->fg->first; w != nil; w = w->next)
+ w->link = nil;
+ if(type == Waout){+ q[r++] = jack;
+ jack->link = jack;
+ } else {+ for(w=jack->fg->first; w != nil; w = w->next)
+ if(w->type == type){+ q[r++] = w;
+ w->link = w;
+ }
+ }
+
while(l < r){w = q[l++];
- if(w->type == Waout)
+ if(type == Waout){+ if(w->type == type)
+ return w;
+ } else if(w == jack){+ for(w = jack->link; w != nil; w = w->link)
+ if(w->type == type)
+ return w;
break;
+ }
for(i=0; i<w->nlist; i++){- v = w->list[i];
- if(v == nil || v->from)
+ to = w->list[i];
+ if(to == nil || to->link)
continue;
- v->from = w;
- q[r++] = v;
+ to->link = w;
+ q[r++] = to;
}
}
- if(w->type != Waout)
- return nil;
- return w;
+
+ return nil;
}
static void
-connectpath(Widget *src, Widget *dst)
+disconnectpath(Widget *from, Widget *to)
{- Widget *w, *v;
+ Widget *next;
+
+ for(; from != nil && from != to; from = next){+ next = from->path;
+ from->path = nil;
+ setoutamp(from, 1, nil);
+ setinamp(next, from, 1, nil);
+ }
+ setoutamp(to, 1, nil);
+}
+
+static void
+connectpath(Widget *from, Widget *to)
+{+ Widget *next;
uint i;
- for(w=dst; w != src; w=v){- v = w->from;
- setoutamp(w, 0, nil);
- setinamp(v, w, 0, nil);
- if(v->nlist == 1)
+ for(; from != nil && from != to; from = next){+ next = from->link;
+ from->path = next;
+ setoutamp(from, 0, nil);
+ setinamp(next, from, 0, nil);
+ if(next->nlist == 1)
continue;
- for(i=0; i < v->nlist; i++)
- if(v->list[i] == w){- cmd(v->id, Setconn, i);
+ for(i=0; i < next->nlist; i++)
+ if(next->list[i] == from){+ cmd(next->id, Setconn, i);
break;
}
}
- setoutamp(src, 0, nil);
- cmd(src->id, Setpinctl, Pinctlout);
+ setoutamp(to, 0, nil);
}
static void
@@ -844,41 +883,48 @@
}
static int
-connectpin(Ctlr *ctlr, uint pin, uint cad)
+connectpin(Ctlr *ctlr, Stream *s, int type, uint pin, uint cad)
{- Widget *w, *src, *dst;
+ Widget *jack, *conv;
if(cad >= Maxcodecs || pin >= Maxwidgets || ctlr->codec[cad] == nil)
return -1;
- src = ctlr->codec[cad]->widgets[pin];
- if(src == nil)
+ jack = ctlr->codec[cad]->widgets[pin];
+ if(jack == nil)
return -1;
- if(src->type != Wpin)
+ if(jack->type != Wpin)
return -1;
- if((src->pincap & Pout) == 0)
- return -1;
- dst = findpath(src);
- if(dst == nil)
+ conv = findpath(jack, type);
+ if(conv == nil)
return -1;
- /* mute all widgets, clear stream */
- for(w=src->fg->first; w != nil; w=w->next){- setoutamp(w, 1, nil);
- setinamp(w, nil, 1, nil);
- cmd(w->id, Setstream, 0);
+ if(s->conv != nil && s->jack != nil){+ if(s->conv->type == Waout)
+ disconnectpath(s->conv, s->jack);
+ else
+ disconnectpath(s->jack, s->conv);
+ cmd(s->conv->id, Setstream, 0);
+ cmd(s->jack->id, Setpinctl, 0);
}
- connectpath(src, dst);
+ if(type == Waout){+ connectpath(conv, jack);
+ cmd(jack->id, Setpinctl, Pinctlout);
+ } else {+ connectpath(jack, conv);
+ cmd(jack->id, Setpinctl, Pinctlin);
+ }
- cmd(dst->id, Setconvfmt, ctlr->afmt);
- cmd(dst->id, Setstream, (ctlr->atag << 4) | 0);
- cmd(dst->id, Setchancnt, 1);
+ cmd(conv->id, Setconvfmt, s->afmt);
+ cmd(conv->id, Setstream, (s->atag << 4) | 0);
+ cmd(conv->id, Setchancnt, 1);
- ctlr->amp = dst;
- ctlr->src = src;
- ctlr->pin = pin;
- ctlr->cad = cad;
+ s->conv = conv;
+ s->jack = jack;
+ s->pin = pin;
+ s->cad = cad;
+
return 0;
}
@@ -950,6 +996,29 @@
}
static long
+readring(Ring *r, uchar *p, long n)
+{+ long n0, m;
+
+ n0 = n;
+ while(n > 0){+ if((m = buffered(r)) <= 0)
+ break;
+ if(m > n)
+ m = n;
+ if(p){+ if(r->ri + m > r->nbuf)
+ m = r->nbuf - r->ri;
+ memmove(p, r->buf + r->ri, m);
+ p += m;
+ }
+ r->ri = (r->ri + m) % r->nbuf;
+ n -= m;
+ }
+ return n0 - n;
+}
+
+static long
writering(Ring *r, uchar *p, long n)
{long n0, m;
@@ -973,93 +1042,87 @@
}
static int
-streamalloc(Ctlr *ctlr)
+streamalloc(Ctlr *ctlr, Stream *s, int num)
{Ring *r;
int i;
- r = &ctlr->ring;
- memset(r, 0, sizeof(*r));
+ r = &s->ring;
r->buf = xspanalloc(r->nbuf = Bufsize, 128, 0);
- ctlr->blds = xspanalloc(Nblocks * sizeof(Bld), 128, 0);
- if(r->buf == nil || ctlr->blds == nil){+ s->blds = xspanalloc(Nblocks * sizeof(Bld), 128, 0);
+ if(r->buf == nil || s->blds == nil){ print("hda: no memory for stream\n");return -1;
}
for(i=0; i<Nblocks; i++){- ctlr->blds[i].addrlo = PADDR(r->buf) + i*Blocksize;
- ctlr->blds[i].addrhi = 0;
- ctlr->blds[i].len = Blocksize;
- ctlr->blds[i].flags = 0x01; /* interrupt on completion */
+ s->blds[i].addrlo = PADDR(r->buf) + i*Blocksize;
+ s->blds[i].addrhi = 0;
+ s->blds[i].len = Blocksize;
+ s->blds[i].flags = 0x01; /* interrupt on completion */
}
- /* output dma engine starts after inputs */
- ctlr->sdnum = ctlr->iss;
- ctlr->sdctl = Sdctl0 + ctlr->sdnum*0x20;
- ctlr->sdintr = 1<<ctlr->sdnum;
- ctlr->atag = ctlr->sdnum+1;
- ctlr->afmt = Fmtstereo | Fmtsampw | Fmtdiv1 | Fmtmul1 | Fmtbase441;
- ctlr->active = 0;
+ s->sdnum = num;
+ s->sdctl = Sdctl0 + s->sdnum*0x20;
+ s->sdintr = 1<<s->sdnum;
+ s->atag = s->sdnum+1;
+ s->afmt = Fmtstereo | Fmtsampw | Fmtdiv1 | Fmtmul1 | Fmtbase441;
+ s->active = 0;
/* perform reset */
- csr8(ctlr, ctlr->sdctl) &= ~(Srst | Srun | Scie | Seie | Sdie);
- csr8(ctlr, ctlr->sdctl) |= Srst;
+ csr8(ctlr, s->sdctl) &= ~(Srst | Srun | Scie | Seie | Sdie);
+ csr8(ctlr, s->sdctl) |= Srst;
microdelay(Codecdelay);
- waitup8(ctlr, ctlr->sdctl, Srst, Srst);
- csr8(ctlr, ctlr->sdctl) &= ~Srst;
+ waitup8(ctlr, s->sdctl, Srst, Srst);
+ csr8(ctlr, s->sdctl) &= ~Srst;
microdelay(Codecdelay);
- waitup8(ctlr, ctlr->sdctl, Srst, 0);
+ waitup8(ctlr, s->sdctl, Srst, 0);
/* set stream number */
- csr32(ctlr, ctlr->sdctl) = (ctlr->atag << Stagbit) |
- (csr32(ctlr, ctlr->sdctl) & ~(0xF << Stagbit));
+ csr32(ctlr, s->sdctl) = (s->atag << Stagbit) |
+ (csr32(ctlr, s->sdctl) & ~(0xF << Stagbit));
/* set stream format */
- csr16(ctlr, Sdfmt+ctlr->sdctl) = ctlr->afmt;
+ csr16(ctlr, Sdfmt+s->sdctl) = s->afmt;
/* program stream DMA & parms */
- csr32(ctlr, Sdbdplo+ctlr->sdctl) = PADDR(ctlr->blds);
- csr32(ctlr, Sdbdphi+ctlr->sdctl) = 0;
- csr32(ctlr, Sdcbl+ctlr->sdctl) = r->nbuf;
- csr16(ctlr, Sdlvi+ctlr->sdctl) = (Nblocks - 1) & 0xff;
+ csr32(ctlr, Sdbdplo+s->sdctl) = PADDR(s->blds);
+ csr32(ctlr, Sdbdphi+s->sdctl) = 0;
+ csr32(ctlr, Sdcbl+s->sdctl) = r->nbuf;
+ csr16(ctlr, Sdlvi+s->sdctl) = (Nblocks - 1) & 0xff;
/* mask out ints */
- csr8(ctlr, Sdsts+ctlr->sdctl) = Scompl | Sfifoerr | Sdescerr;
+ csr8(ctlr, Sdsts+s->sdctl) = Scompl | Sfifoerr | Sdescerr;
/* enable global intrs for this stream */
- csr32(ctlr, Intctl) |= ctlr->sdintr;
- csr8(ctlr, ctlr->sdctl) |= Scie | Seie | Sdie;
+ csr32(ctlr, Intctl) |= s->sdintr;
+ csr8(ctlr, s->sdctl) |= Scie | Seie | Sdie;
return 0;
}
static void
-streamstart(Ctlr *ctlr)
+streamstart(Ctlr *ctlr, Stream *s)
{- ctlr->active = 1;
-
- csr8(ctlr, ctlr->sdctl) |= Srun;
- waitup8(ctlr, ctlr->sdctl, Srun, Srun);
+ s->active = 1;
+ csr8(ctlr, s->sdctl) |= Srun;
+ waitup8(ctlr, s->sdctl, Srun, Srun);
}
static void
-streamstop(Ctlr *ctlr)
+streamstop(Ctlr *ctlr, Stream *s)
{- csr8(ctlr, ctlr->sdctl) &= ~Srun;
- waitup8(ctlr, ctlr->sdctl, Srun, 0);
-
- ctlr->active = 0;
+ csr8(ctlr, s->sdctl) &= ~Srun;
+ waitup8(ctlr, s->sdctl, Srun, 0);
+ s->active = 0;
}
static uint
-streampos(Ctlr *ctlr)
+streampos(Ctlr *ctlr, Stream *s)
{- Ring *r;
uint p;
- r = &ctlr->ring;
- p = csr32(ctlr, Sdlpib+ctlr->sdctl);
- if(p >= r->nbuf)
+ p = csr32(ctlr, Sdlpib+s->sdctl);
+ if(p >= s->ring.nbuf)
p = 0;
return p;
}
@@ -1085,12 +1148,21 @@
if(ntok <= 0)
continue;
if(cistrcmp(tok[0], "pin") == 0 && ntok >= 2){- cad = ctlr->cad;
+ cad = ctlr->sout.cad;
pin = strtoul(tok[1], 0, 0);
if(ntok > 2)
cad = strtoul(tok[2], 0, 0);
- connectpin(ctlr, pin, cad);
+ if(connectpin(ctlr, &ctlr->sout, Waout, pin, cad) < 0)
+ error("connectpin failed");}else
+ if(cistrcmp(tok[0], "inpin") == 0 && ntok >= 2){+ cad = ctlr->sout.cad;
+ pin = strtoul(tok[1], 0, 0);
+ if(ntok > 2)
+ cad = strtoul(tok[2], 0, 0);
+ if(connectpin(ctlr, &ctlr->sin, Wain, pin, cad) < 0)
+ error("connectpin failed");+ }else
error(Ebadctl);
}
return n;
@@ -1097,10 +1169,17 @@
}
static int
+inavail(void *arg)
+{+ Ring *r = arg;
+ return buffered(r) > 0;
+}
+
+static int
outavail(void *arg)
{- Ctlr *ctlr = arg;
- return available(&ctlr->ring) > 0;
+ Ring *r = arg;
+ return available(r) > 0;
}
static int
@@ -1108,7 +1187,7 @@
{Ctlr *ctlr = arg;
int delay = ctlr->adev->delay*BytesPerSample;
- return (delay <= 0) || (buffered(&ctlr->ring) <= delay) || (ctlr->active == 0);
+ return (delay <= 0) || (buffered(&ctlr->sout.ring) <= delay) || (ctlr->sout.active == 0);
}
static long
@@ -1116,19 +1195,44 @@
{Ctlr *ctlr;
ctlr = adev->ctlr;
- return buffered(&ctlr->ring);
+ return buffered(&ctlr->sout.ring);
}
static void
hdakick(Ctlr *ctlr)
{- if(ctlr->active)
+ if(ctlr->sout.active)
return;
- if(buffered(&ctlr->ring) > Blocksize)
- streamstart(ctlr);
+ if(buffered(&ctlr->sout.ring) > Blocksize)
+ streamstart(ctlr, &ctlr->sout);
}
static long
+hdaread(Audio *adev, void *vp, long n, vlong)
+{+ uchar *p, *e;
+ Ctlr *ctlr;
+ Ring *ring;
+
+ p = vp;
+ e = p + n;
+ ctlr = adev->ctlr;
+ ring = &ctlr->sin.ring;
+ if(ring->buf == nil || ctlr->sin.conv == nil)
+ return 0;
+ while(p < e) {+ if((n = readring(ring, p, e - p)) <= 0){+ if(!ctlr->sin.active)
+ streamstart(ctlr, &ctlr->sin);
+ sleep(&ring->r, inavail, ring);
+ continue;
+ }
+ p += n;
+ }
+ return p - (uchar*)vp;
+}
+
+static long
hdawrite(Audio *adev, void *vp, long n, vlong)
{uchar *p, *e;
@@ -1138,11 +1242,11 @@
p = vp;
e = p + n;
ctlr = adev->ctlr;
- ring = &ctlr->ring;
+ ring = &ctlr->sout.ring;
while(p < e) { if((n = writering(ring, p, e - p)) <= 0){hdakick(ctlr);
- sleep(&ring->r, outavail, ctlr);
+ sleep(&ring->r, outavail, ring);
continue;
}
p += n;
@@ -1153,23 +1257,28 @@
}
static void
-hdaclose(Audio *adev)
+hdaclose(Audio *adev, int mode)
{Ctlr *ctlr;
uchar z[1];
- Ring *r;
ctlr = adev->ctlr;
- if(!ctlr->active)
- return;
- z[0] = 0;
- r = &ctlr->ring;
- while(r->wi % Blocksize)
- hdawrite(adev, z, sizeof(z), 0);
+ if(mode == OREAD || mode == ORDWR){+ if(ctlr->sin.active)
+ streamstop(ctlr, &ctlr->sin);
+ }
+ if(mode == OWRITE || mode == ORDWR){+ if(ctlr->sout.active){+ z[0] = 0;
+ while(ctlr->sout.ring.wi % Blocksize)
+ hdawrite(adev, z, sizeof(z), 0);
+ }
+ }
}
enum {Vmaster,
+ Vrecord,
Vspeed,
Vdelay,
Nvol,
@@ -1177,6 +1286,7 @@
static Volume voltab[] = {[Vmaster] "master", 0, 0x7f, Stereo, 0,
+ [Vrecord] "record", 0, 0x7f, Stereo, 0,
[Vspeed] "speed", 0, 0, Absolute, 0,
[Vdelay] "delay", 0, 0, Absolute, 0,
0
@@ -1189,8 +1299,8 @@
switch(x){case Vmaster:
- if(ctlr->amp != nil)
- getoutamp(ctlr->amp, a);
+ if(ctlr->sout.conv != nil)
+ getoutamp(ctlr->sout.conv, a);
break;
case Vspeed:
a[0] = adev->speed;
@@ -1209,9 +1319,13 @@
switch(x){case Vmaster:
- if(ctlr->amp != nil)
- setoutamp(ctlr->amp, 0, a);
+ if(ctlr->sout.conv != nil)
+ setoutamp(ctlr->sout.conv, 0, a);
break;
+ case Vrecord:
+ if(ctlr->sin.conv != nil)
+ setinamp(ctlr->sin.conv, nil, 0, a);
+ break;
case Vspeed:
adev->speed = a[0];
break;
@@ -1226,8 +1340,8 @@
fillvoltab(Ctlr *ctlr, Volume *vt)
{memmove(vt, voltab, sizeof(voltab));
- if(ctlr->amp != nil)
- vt[Vmaster].range = getoutamprange(ctlr->amp);
+ if(ctlr->sout.conv != nil)
+ vt[Vmaster].range = getoutamprange(ctlr->sout.conv);
}
static long
@@ -1251,25 +1365,35 @@
{Ctlr *ctlr;
Audio *adev;
- uint sts;
Ring *r;
+ uint sts;
adev = arg;
ctlr = adev->ctlr;
-
ilock(ctlr);
sts = csr32(ctlr, Intsts);
- if(sts & ctlr->sdintr){- /* ack interrupt */
- csr8(ctlr, Sdsts+ctlr->sdctl) |= Scompl;
- r = &ctlr->ring;
- r->ri = streampos(ctlr);
- if(ctlr->active && buffered(r) < Blocksize){- streamstop(ctlr);
- r->ri = r->wi = streampos(ctlr);
+ if(sts & ctlr->sout.sdintr){+ csr8(ctlr, Sdsts+ctlr->sout.sdctl) |= Scompl;
+
+ r = &ctlr->sout.ring;
+ r->ri = streampos(ctlr, &ctlr->sout);
+ if(ctlr->sout.active && buffered(r) < Blocksize){+ streamstop(ctlr, &ctlr->sout);
+ r->ri = r->wi = streampos(ctlr, &ctlr->sout);
}
wakeup(&r->r);
}
+ if(sts & ctlr->sin.sdintr){+ csr8(ctlr, Sdsts+ctlr->sin.sdctl) |= Scompl;
+
+ r = &ctlr->sin.ring;
+ r->wi = streampos(ctlr, &ctlr->sin);
+ if(ctlr->sin.active && available(r) < Blocksize){+ streamstop(ctlr, &ctlr->sin);
+ r->ri = r->wi = streampos(ctlr, &ctlr->sin);
+ }
+ wakeup(&r->r);
+ }
iunlock(ctlr);
}
@@ -1286,20 +1410,21 @@
s = a;
e = s + n;
- s = seprint(s, e, "bufsize %6d buffered %6ld\n", Blocksize, buffered(&ctlr->ring));
+ s = seprint(s, e, "bufsize %6d buffered %6ld\n", Blocksize, buffered(&ctlr->sout.ring));
for(i=0; i<Maxcodecs; i++){if((codec = ctlr->codec[i]) == nil)
continue;
- s = seprint(s, e, "codec %2d pin %3d\n",
- codec->id.codec, ctlr->pin);
+ s = seprint(s, e, "codec %2d pin %3d inpin %3d\n",
+ codec->id.codec, ctlr->sout.pin, ctlr->sin.pin);
for(fg=codec->fgroup; fg; fg=fg->next){ for(w=fg->first; w; w=w->next){if(w->type != Wpin)
continue;
r = w->pin;
- s = seprint(s, e, "pin %3d %s %s %s %s %s %s%s%s\n",
+ s = seprint(s, e, "pin %3d %s%s %s %s %s %s %s%s%s\n",
w->id.nid,
- (w->pincap & Pout) != 0 ? "out" : "in",
+ (w->pincap & Pin) != 0 ? "in" : "",
+ (w->pincap & Pout) != 0 ? "out" : "",
pinport[(r >> 30) & 0x3],
pinloc2[(r >> 28) & 0x3],
pinloc[(r >> 24) & 0xf],
@@ -1312,16 +1437,26 @@
}
}
- s = seprint(s, e, "path ");
- for(w=ctlr->amp; w != nil; w = w->from){+ s = seprint(s, e, "outpath ");
+ for(w=ctlr->sout.conv; w != nil; w = w->path){s = seprint(s, e, "%s %3d %lux %lux %lux", widtype[w->type&7], w->id.nid,
(ulong)w->cap, (ulong)w->pin, (ulong)w->pincap);
- if(w == ctlr->src)
+ if(w == ctlr->sout.jack)
break;
s = seprint(s, e, " → ");
}
s = seprint(s, e, "\n");
+ s = seprint(s, e, "inpath ");
+ for(w=ctlr->sin.jack; w != nil; w = w->path){+ s = seprint(s, e, "%s %3d %lux %lux %lux", widtype[w->type&7], w->id.nid,
+ (ulong)w->cap, (ulong)w->pin, (ulong)w->pincap);
+ if(w == ctlr->sin.conv)
+ break;
+ s = seprint(s, e, " → ");
+ }
+ s = seprint(s, e, "\n");
+
return s - (char*)a;
}
@@ -1561,10 +1696,13 @@
print("#A%d: unable to start hda\n", ctlr->no);return -1;
}
- if(streamalloc(ctlr) < 0){- print("#A%d: streamalloc failed\n", ctlr->no);+ if(streamalloc(ctlr, &ctlr->sout, ctlr->iss) < 0){+ print("#A%d: output streamalloc failed\n", ctlr->no);return -1;
}
+ if(ctlr->iss > 0)
+ if(streamalloc(ctlr, &ctlr->sin, 0) < 0)
+ print("#A%d: input streamalloc failed\n", ctlr->no); if(enumdev(ctlr) < 0){ print("#A%d: no audio codecs found\n", ctlr->no);return -1;
@@ -1574,11 +1712,12 @@
print("#A%d: no output pins found!\n", ctlr->no);return -1;
}
- if(connectpin(ctlr, best, cad) < 0){+ if(connectpin(ctlr, &ctlr->sout, Waout, best, cad) < 0){ print("#A%d: error connecting pin\n", ctlr->no);return -1;
}
+ adev->read = hdaread;
adev->write = hdawrite;
adev->close = hdaclose;
adev->buffered = hdabuffered;
--- a/sys/src/9/pc/audiosb16.c
+++ b/sys/src/9/pc/audiosb16.c
@@ -554,10 +554,12 @@
}
static void
-audioclose(Audio *adev)
+audioclose(Audio *adev, int mode)
{Ctlr *ctlr;
+ if(mode == OREAD)
+ return;
ctlr = adev->ctlr;
sleep(&ctlr->vous, inactive, ctlr);
setempty(ctlr);
--- a/sys/src/9/port/audioif.h
+++ b/sys/src/9/port/audioif.h
@@ -13,7 +13,7 @@
long (*read)(Audio *, void *, long, vlong);
long (*write)(Audio *, void *, long, vlong);
- void (*close)(Audio *);
+ void (*close)(Audio *, int);
long (*volread)(Audio *, void *, long, vlong);
long (*volwrite)(Audio *, void *, long, vlong);
--- a/sys/src/9/port/devaudio.c
+++ b/sys/src/9/port/devaudio.c
@@ -311,7 +311,7 @@
if((c->qid.path == Qaudio) && (c->flag & COPEN)){ if(adev->close){ if(!waserror()){- adev->close(adev);
+ adev->close(adev, c->mode);
poperror();
}
}
--
⑨