version 1.35, 2009/10/06 18:06:55 |
version 1.36, 2009/10/09 16:49:48 |
|
|
short *odata; |
short *odata; |
unsigned ocount; |
unsigned ocount; |
|
|
odata = (short *)abuf_wgetblk(obuf, &ocount, obuf->mixitodo); |
odata = (short *)abuf_wgetblk(obuf, &ocount, obuf->w.mix.todo); |
ocount -= ocount % obuf->bpf; |
ocount -= ocount % obuf->bpf; |
if (ocount > zcount) |
if (ocount > zcount) |
ocount = zcount; |
ocount = zcount; |
memset(odata, 0, ocount); |
memset(odata, 0, ocount); |
obuf->mixitodo += ocount; |
obuf->w.mix.todo += ocount; |
} |
} |
|
|
/* |
/* |
|
|
/* |
/* |
* Zero-fill if necessary. |
* Zero-fill if necessary. |
*/ |
*/ |
zcount = ibuf->mixodone + icount * obuf->bpf; |
zcount = ibuf->r.mix.done + icount * obuf->bpf; |
if (zcount > obuf->mixitodo) |
if (zcount > obuf->w.mix.todo) |
mix_bzero(obuf, zcount - obuf->mixitodo); |
mix_bzero(obuf, zcount - obuf->w.mix.todo); |
|
|
/* |
/* |
* Calculate the maximum we can write. |
* Calculate the maximum we can write. |
*/ |
*/ |
odata = (short *)abuf_wgetblk(obuf, &ocount, ibuf->mixodone); |
odata = (short *)abuf_wgetblk(obuf, &ocount, ibuf->r.mix.done); |
ocount /= obuf->bpf; |
ocount /= obuf->bpf; |
if (ocount == 0) |
if (ocount == 0) |
return; |
return; |
|
|
vol = (ibuf->mixweight * ibuf->mixvol) >> ADATA_SHIFT; |
vol = (ibuf->r.mix.weight * ibuf->r.mix.vol) >> ADATA_SHIFT; |
ostart = ibuf->cmin - obuf->cmin; |
ostart = ibuf->cmin - obuf->cmin; |
onext = obuf->cmax - ibuf->cmax + ostart; |
onext = obuf->cmax - ibuf->cmax + ostart; |
icnt = ibuf->cmax - ibuf->cmin + 1; |
icnt = ibuf->cmax - ibuf->cmin + 1; |
|
|
odata += onext; |
odata += onext; |
} |
} |
abuf_rdiscard(ibuf, scount * ibuf->bpf); |
abuf_rdiscard(ibuf, scount * ibuf->bpf); |
ibuf->mixodone += scount * obuf->bpf; |
ibuf->r.mix.done += scount * obuf->bpf; |
|
|
} |
} |
|
|
|
|
{ |
{ |
unsigned fdrop; |
unsigned fdrop; |
|
|
if (i->mixodone > 0) |
if (i->r.mix.done > 0) |
return 1; |
return 1; |
if (i->xrun == XRUN_ERROR) { |
if (i->r.mix.xrun == XRUN_ERROR) { |
abuf_hup(i); |
abuf_hup(i); |
return 0; |
return 0; |
} |
} |
mix_bzero(obuf, obuf->len); |
mix_bzero(obuf, obuf->len); |
fdrop = obuf->mixitodo / obuf->bpf; |
fdrop = obuf->w.mix.todo / obuf->bpf; |
i->mixodone += fdrop * obuf->bpf; |
i->r.mix.done += fdrop * obuf->bpf; |
if (i->xrun == XRUN_SYNC) |
if (i->r.mix.xrun == XRUN_SYNC) |
i->drop += fdrop * i->bpf; |
i->drop += fdrop * i->bpf; |
else { |
else { |
abuf_opos(i, -(int)fdrop); |
abuf_opos(i, -(int)fdrop); |
|
|
if (!abuf_fill(i)) |
if (!abuf_fill(i)) |
continue; /* eof */ |
continue; /* eof */ |
mix_badd(i, obuf); |
mix_badd(i, obuf); |
if (odone > i->mixodone) |
if (odone > i->r.mix.done) |
odone = i->mixodone; |
odone = i->r.mix.done; |
} |
} |
if (LIST_EMPTY(&p->ibuflist) || odone == 0) |
if (LIST_EMPTY(&p->ibuflist) || odone == 0) |
return 0; |
return 0; |
p->u.mix.lat += odone / obuf->bpf; |
p->u.mix.lat += odone / obuf->bpf; |
LIST_FOREACH(i, &p->ibuflist, ient) { |
LIST_FOREACH(i, &p->ibuflist, ient) { |
i->mixodone -= odone; |
i->r.mix.done -= odone; |
} |
} |
abuf_wcommit(obuf, odone); |
abuf_wcommit(obuf, odone); |
obuf->mixitodo -= odone; |
obuf->w.mix.todo -= odone; |
if (!abuf_flush(obuf)) |
if (!abuf_flush(obuf)) |
return 0; /* hup */ |
return 0; /* hup */ |
return 1; |
return 1; |
|
|
} |
} |
} else |
} else |
mix_badd(i, obuf); |
mix_badd(i, obuf); |
if (odone > i->mixodone) |
if (odone > i->r.mix.done) |
odone = i->mixodone; |
odone = i->r.mix.done; |
} |
} |
if (LIST_EMPTY(&p->ibuflist)) { |
if (LIST_EMPTY(&p->ibuflist)) { |
if (p->u.mix.flags & MIX_AUTOQUIT) { |
if (p->u.mix.flags & MIX_AUTOQUIT) { |
|
|
if (!(p->u.mix.flags & MIX_DROP)) |
if (!(p->u.mix.flags & MIX_DROP)) |
return 0; |
return 0; |
mix_bzero(obuf, obuf->len); |
mix_bzero(obuf, obuf->len); |
odone = obuf->mixitodo; |
odone = obuf->w.mix.todo; |
p->u.mix.idle += odone / obuf->bpf; |
p->u.mix.idle += odone / obuf->bpf; |
} |
} |
if (odone == 0) |
if (odone == 0) |
return 0; |
return 0; |
p->u.mix.lat += odone / obuf->bpf; |
p->u.mix.lat += odone / obuf->bpf; |
LIST_FOREACH(i, &p->ibuflist, ient) { |
LIST_FOREACH(i, &p->ibuflist, ient) { |
i->mixodone -= odone; |
i->r.mix.done -= odone; |
} |
} |
abuf_wcommit(obuf, odone); |
abuf_wcommit(obuf, odone); |
obuf->mixitodo -= odone; |
obuf->w.mix.todo -= odone; |
return 1; |
return 1; |
} |
} |
|
|
|
|
*/ |
*/ |
odone = obuf->len; |
odone = obuf->len; |
LIST_FOREACH(i, &p->ibuflist, ient) { |
LIST_FOREACH(i, &p->ibuflist, ient) { |
if (ABUF_ROK(i) && i->mixodone < obuf->mixitodo) { |
if (ABUF_ROK(i) && i->r.mix.done < obuf->w.mix.todo) { |
abuf_run(i); |
abuf_run(i); |
return; |
return; |
} |
} |
if (odone > i->mixodone) |
if (odone > i->r.mix.done) |
odone = i->mixodone; |
odone = i->r.mix.done; |
} |
} |
/* |
/* |
* No blocked inputs. Check if output is blocked. |
* No blocked inputs. Check if output is blocked. |
*/ |
*/ |
if (LIST_EMPTY(&p->ibuflist) || odone == obuf->mixitodo) |
if (LIST_EMPTY(&p->ibuflist) || odone == obuf->w.mix.todo) |
abuf_run(obuf); |
abuf_run(obuf); |
} |
} |
} |
} |
|
|
mix_newin(struct aproc *p, struct abuf *ibuf) |
mix_newin(struct aproc *p, struct abuf *ibuf) |
{ |
{ |
p->u.mix.idle = 0; |
p->u.mix.idle = 0; |
ibuf->mixodone = 0; |
ibuf->r.mix.done = 0; |
ibuf->mixvol = ADATA_UNIT; |
ibuf->r.mix.vol = ADATA_UNIT; |
ibuf->mixweight = ADATA_UNIT; |
ibuf->r.mix.weight = ADATA_UNIT; |
ibuf->mixmaxweight = ADATA_UNIT; |
ibuf->r.mix.maxweight = ADATA_UNIT; |
ibuf->xrun = XRUN_IGNORE; |
ibuf->r.mix.xrun = XRUN_IGNORE; |
} |
} |
|
|
void |
void |
mix_newout(struct aproc *p, struct abuf *obuf) |
mix_newout(struct aproc *p, struct abuf *obuf) |
{ |
{ |
obuf->mixitodo = 0; |
obuf->w.mix.todo = 0; |
} |
} |
|
|
void |
void |
|
|
} |
} |
LIST_FOREACH(buf, &p->ibuflist, ient) { |
LIST_FOREACH(buf, &p->ibuflist, ient) { |
weight = ADATA_UNIT / n; |
weight = ADATA_UNIT / n; |
if (weight > buf->mixmaxweight) |
if (weight > buf->r.mix.maxweight) |
weight = buf->mixmaxweight; |
weight = buf->r.mix.maxweight; |
buf->mixweight = weight; |
buf->r.mix.weight = weight; |
} |
} |
} |
} |
|
|
|
|
struct abuf *obuf = LIST_FIRST(&p->obuflist); |
struct abuf *obuf = LIST_FIRST(&p->obuflist); |
|
|
p->u.mix.lat = 0; |
p->u.mix.lat = 0; |
obuf->mixitodo = 0; |
obuf->w.mix.todo = 0; |
} |
} |
|
|
/* |
/* |
|
|
unsigned i, j, ocnt, inext, istart; |
unsigned i, j, ocnt, inext, istart; |
unsigned icount, ocount, scount; |
unsigned icount, ocount, scount; |
|
|
idata = (short *)abuf_rgetblk(ibuf, &icount, obuf->subidone); |
idata = (short *)abuf_rgetblk(ibuf, &icount, obuf->w.sub.done); |
icount /= ibuf->bpf; |
icount /= ibuf->bpf; |
if (icount == 0) |
if (icount == 0) |
return; |
return; |
|
|
idata += inext; |
idata += inext; |
} |
} |
abuf_wcommit(obuf, scount * obuf->bpf); |
abuf_wcommit(obuf, scount * obuf->bpf); |
obuf->subidone += scount * ibuf->bpf; |
obuf->w.sub.done += scount * ibuf->bpf; |
} |
} |
|
|
/* |
/* |
|
|
{ |
{ |
unsigned fdrop; |
unsigned fdrop; |
|
|
if (i->subidone > 0) |
if (i->w.sub.done > 0) |
return 1; |
return 1; |
if (i->xrun == XRUN_ERROR) { |
if (i->w.sub.xrun == XRUN_ERROR) { |
abuf_eof(i); |
abuf_eof(i); |
return 0; |
return 0; |
} |
} |
fdrop = ibuf->used / ibuf->bpf; |
fdrop = ibuf->used / ibuf->bpf; |
if (i->xrun == XRUN_SYNC) |
if (i->w.sub.xrun == XRUN_SYNC) |
i->silence += fdrop * i->bpf; |
i->silence += fdrop * i->bpf; |
else { |
else { |
abuf_ipos(i, -(int)fdrop); |
abuf_ipos(i, -(int)fdrop); |
|
|
abuf_opos(i->duplex, -(int)fdrop); |
abuf_opos(i->duplex, -(int)fdrop); |
} |
} |
} |
} |
i->subidone += fdrop * ibuf->bpf; |
i->w.sub.done += fdrop * ibuf->bpf; |
return 1; |
return 1; |
} |
} |
|
|
|
|
} |
} |
} else |
} else |
sub_bcopy(ibuf, i); |
sub_bcopy(ibuf, i); |
if (idone > i->subidone) |
if (idone > i->w.sub.done) |
idone = i->subidone; |
idone = i->w.sub.done; |
if (!abuf_flush(i)) |
if (!abuf_flush(i)) |
continue; |
continue; |
} |
} |
|
|
if (idone == 0) |
if (idone == 0) |
return 0; |
return 0; |
LIST_FOREACH(i, &p->obuflist, oent) { |
LIST_FOREACH(i, &p->obuflist, oent) { |
i->subidone -= idone; |
i->w.sub.done -= idone; |
} |
} |
abuf_rdiscard(ibuf, idone); |
abuf_rdiscard(ibuf, idone); |
p->u.sub.lat -= idone / ibuf->bpf; |
p->u.sub.lat -= idone / ibuf->bpf; |
|
|
for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) { |
for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) { |
inext = LIST_NEXT(i, oent); |
inext = LIST_NEXT(i, oent); |
sub_bcopy(ibuf, i); |
sub_bcopy(ibuf, i); |
if (idone > i->subidone) |
if (idone > i->w.sub.done) |
idone = i->subidone; |
idone = i->w.sub.done; |
if (!abuf_flush(i)) |
if (!abuf_flush(i)) |
continue; |
continue; |
} |
} |
if (LIST_EMPTY(&p->obuflist) || idone == 0) |
if (LIST_EMPTY(&p->obuflist) || idone == 0) |
return 0; |
return 0; |
LIST_FOREACH(i, &p->obuflist, oent) { |
LIST_FOREACH(i, &p->obuflist, oent) { |
i->subidone -= idone; |
i->w.sub.done -= idone; |
} |
} |
abuf_rdiscard(ibuf, idone); |
abuf_rdiscard(ibuf, idone); |
p->u.sub.lat -= idone / ibuf->bpf; |
p->u.sub.lat -= idone / ibuf->bpf; |
|
|
*/ |
*/ |
idone = ibuf->len; |
idone = ibuf->len; |
LIST_FOREACH(i, &p->obuflist, oent) { |
LIST_FOREACH(i, &p->obuflist, oent) { |
if (ABUF_WOK(i) && i->subidone < ibuf->used) { |
if (ABUF_WOK(i) && i->w.sub.done < ibuf->used) { |
abuf_run(i); |
abuf_run(i); |
return; |
return; |
} |
} |
if (idone > i->subidone) |
if (idone > i->w.sub.done) |
idone = i->subidone; |
idone = i->w.sub.done; |
} |
} |
/* |
/* |
* No blocked outputs. Check if input is blocked. |
* No blocked outputs. Check if input is blocked. |
|
|
sub_newout(struct aproc *p, struct abuf *obuf) |
sub_newout(struct aproc *p, struct abuf *obuf) |
{ |
{ |
p->u.sub.idle = 0; |
p->u.sub.idle = 0; |
obuf->subidone = 0; |
obuf->w.sub.done = 0; |
obuf->xrun = XRUN_IGNORE; |
obuf->w.sub.xrun = XRUN_IGNORE; |
} |
} |
|
|
void |
void |