summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pcm/feeder.c
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2000-08-20 22:18:56 +0000
committercg <cg@FreeBSD.org>2000-08-20 22:18:56 +0000
commitcc65486f22393469327f3952efc2526af719e4a2 (patch)
treef4dad15d15847c43242bb2f8e08bd8143dae99e5 /sys/dev/sound/pcm/feeder.c
parentb648921accec69a7e5c83e915ded3037cbca7f3d (diff)
downloadFreeBSD-src-cc65486f22393469327f3952efc2526af719e4a2.zip
FreeBSD-src-cc65486f22393469327f3952efc2526af719e4a2.tar.gz
rework feeder sytem to allow feeders in klds
modify driver capability reporting format to list every audio format seperately- required for above and because we could not previously indicate that mono was unsupported. there should be no functional impact.
Diffstat (limited to 'sys/dev/sound/pcm/feeder.c')
-rw-r--r--sys/dev/sound/pcm/feeder.c397
1 files changed, 270 insertions, 127 deletions
diff --git a/sys/dev/sound/pcm/feeder.c b/sys/dev/sound/pcm/feeder.c
index 5eaf89a..91049e6 100644
--- a/sys/dev/sound/pcm/feeder.c
+++ b/sys/dev/sound/pcm/feeder.c
@@ -28,9 +28,6 @@
#include <dev/sound/pcm/sound.h>
-static int chn_addfeeder(pcm_channel *c, pcm_feeder *f);
-static int chn_removefeeder(pcm_channel *c);
-
#define FEEDBUFSZ 8192
static unsigned char ulaw_to_u8[] = {
@@ -103,15 +100,65 @@ static unsigned char u8_to_ulaw[] = {
129, 129, 129, 129, 128, 128, 128, 128,
};
+struct feedertab_entry {
+ SLIST_ENTRY(feedertab_entry) link;
+ pcm_feeder *feeder;
+ struct pcm_feederdesc *desc;
+
+ int idx;
+};
+static SLIST_HEAD(, feedertab_entry) feedertab;
+
+/*****************************************************************************/
+
+void
+feeder_register(void *p)
+{
+ pcm_feeder *f = p;
+ struct feedertab_entry *fte;
+ static int feedercnt = 0;
+ int i;
+
+ if (feedercnt == 0) {
+ if (f->desc)
+ panic("FIRST FEEDER NOT ROOT: %s\n", f->name);
+ SLIST_INIT(&feedertab);
+ fte = malloc(sizeof(*fte), M_DEVBUF, M_NOWAIT);
+ fte->feeder = f;
+ fte->desc = NULL;
+ fte->idx = feedercnt;
+ SLIST_INSERT_HEAD(&feedertab, fte, link);
+ feedercnt++;
+ return;
+ }
+ /* printf("installing feeder: %s\n", f->name); */
+
+ i = 0;
+ while ((feedercnt < MAXFEEDERS) && (f->desc[i].type > 0)) {
+ fte = malloc(sizeof(*fte), M_DEVBUF, M_NOWAIT);
+ fte->feeder = f;
+ fte->desc = &f->desc[i];
+ fte->idx = feedercnt;
+ fte->desc->idx = feedercnt;
+ SLIST_INSERT_HEAD(&feedertab, fte, link);
+ i++;
+ }
+ feedercnt++;
+ if (feedercnt >= MAXFEEDERS)
+ printf("MAXFEEDERS exceeded\n");
+}
+
/*****************************************************************************/
static int
feed_root(pcm_feeder *feeder, pcm_channel *ch, u_int8_t *buffer, u_int32_t count, struct uio *stream)
{
- int ret, c = 0, s;
+ int ret, s;
+
KASSERT(count, ("feed_root: count == 0"));
count &= ~((1 << ch->align) - 1);
KASSERT(count, ("feed_root: aligned count == 0"));
+
s = spltty();
count = min(count, stream->uio_resid);
if (count) {
@@ -119,16 +166,19 @@ feed_root(pcm_feeder *feeder, pcm_channel *ch, u_int8_t *buffer, u_int32_t count
KASSERT(ret == 0, ("feed_root: uiomove failed"));
}
splx(s);
- return c + count;
+
+ return count;
}
-pcm_feeder feeder_root = { "root", 0, NULL, NULL, feed_root };
+static pcm_feeder feeder_root = { "root", 0, NULL, NULL, NULL, feed_root };
+SYSINIT(feeder_root, SI_SUB_DRIVERS, SI_ORDER_FIRST, feeder_register, &feeder_root);
/*****************************************************************************/
static int
-feed_8to16(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
+feed_8to16le(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
{
int i, j, k;
+
k = f->source->feed(f->source, c, b, count / 2, stream);
j = k - 1;
i = j * 2 + 1;
@@ -138,7 +188,17 @@ feed_8to16(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct u
}
return k * 2;
}
-static pcm_feeder feeder_8to16 = { "8to16", 0, NULL, NULL, feed_8to16 };
+
+static struct pcm_feederdesc desc_8to16le[] = {
+ {FEEDER_FMT, AFMT_U8, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {0},
+};
+static pcm_feeder feeder_8to16le =
+ { "8to16le", 0, desc_8to16le, NULL, NULL, feed_8to16le };
+SYSINIT(feeder_8to16le, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_8to16le);
/*****************************************************************************/
@@ -158,10 +218,11 @@ feed_16to8_free(pcm_feeder *f)
}
static int
-feed_16to8le(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
+feed_16leto8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
{
u_int32_t i = 0, toget = count * 2;
int j = 1, k;
+
k = f->source->feed(f->source, c, f->data, min(toget, FEEDBUFSZ), stream);
while (j < k) {
b[i++] = ((u_int8_t *)f->data)[j];
@@ -169,8 +230,17 @@ feed_16to8le(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct
}
return i;
}
-static pcm_feeder feeder_16to8le =
- { "16to8le", 1, feed_16to8_init, feed_16to8_free, feed_16to8le };
+
+static struct pcm_feederdesc desc_16leto8[] = {
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {0},
+};
+static pcm_feeder feeder_16leto8 =
+ { "16leto8", 1, desc_16leto8, feed_16to8_init, feed_16to8_free, feed_16leto8 };
+SYSINIT(feeder_16leto8, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_16leto8);
/*****************************************************************************/
@@ -178,6 +248,7 @@ static int
feed_monotostereo8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
{
int i, j, k = f->source->feed(f->source, c, b, count / 2, stream);
+
j = k - 1;
i = j * 2 + 1;
while (i > 0 && j >= 0) {
@@ -187,8 +258,15 @@ feed_monotostereo8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count,
}
return k * 2;
}
+
+static struct pcm_feederdesc desc_monotostereo8[] = {
+ {FEEDER_FMT, AFMT_U8, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_S8 | AFMT_STEREO, 0},
+ {0},
+};
static pcm_feeder feeder_monotostereo8 =
- { "monotostereo8", 0, NULL, NULL, feed_monotostereo8 };
+ { "monotostereo8", 0, desc_monotostereo8, NULL, NULL, feed_monotostereo8 };
+SYSINIT(feeder_monotostereo8, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_monotostereo8);
/*****************************************************************************/
@@ -212,6 +290,7 @@ feed_stereotomono8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count,
{
u_int32_t i = 0, toget = count * 2;
int j = 0, k;
+
k = f->source->feed(f->source, c, f->data, min(toget, FEEDBUFSZ), stream);
while (j < k) {
b[i++] = ((u_int8_t *)f->data)[j];
@@ -219,9 +298,15 @@ feed_stereotomono8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count,
}
return i;
}
+
+static struct pcm_feederdesc desc_stereotomono8[] = {
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S8, 0},
+ {0},
+};
static pcm_feeder feeder_stereotomono8 =
- { "stereotomono8", 1, feed_stereotomono8_init, feed_stereotomono8_free,
- feed_stereotomono8 };
+ { "stereotomono8", 1, desc_stereotomono8, feed_stereotomono8_init, feed_stereotomono8_free, feed_stereotomono8 };
+SYSINIT(feeder_stereotomono8, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_stereotomono8);
/*****************************************************************************/
@@ -230,6 +315,7 @@ feed_endian(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct
{
u_int8_t t;
int i = 0, j = f->source->feed(f->source, c, b, count, stream);
+
while (i < j) {
t = b[i];
b[i] = b[i + 1];
@@ -238,7 +324,20 @@ feed_endian(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct
}
return i;
}
-static pcm_feeder feeder_endian = { "endian", -1, NULL, NULL, feed_endian };
+
+static struct pcm_feederdesc desc_endian[] = {
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_S16_BE, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_BE, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_BE, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {0},
+};
+static pcm_feeder feeder_endian = { "endian", -1, desc_endian, NULL, NULL, feed_endian };
+SYSINIT(feeder_endian, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_endian);
/*****************************************************************************/
@@ -247,16 +346,35 @@ feed_sign(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct ui
{
int i = 0, j = f->source->feed(f->source, c, b, count, stream);
int ssz = (int)f->data, ofs = ssz - 1;
+
while (i < j) {
b[i + ofs] ^= 0x80;
i += ssz;
}
return i;
}
+
+static struct pcm_feederdesc desc_sign8[] = {
+ {FEEDER_FMT, AFMT_U8, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {0},
+};
static pcm_feeder feeder_sign8 =
- { "sign8", 0, NULL, NULL, feed_sign, (void *)1 };
-static pcm_feeder feeder_sign16 =
- { "sign16", -1, NULL, NULL, feed_sign, (void *)2 };
+ { "sign8", 0, desc_sign8, NULL, NULL, feed_sign, (void *)1 };
+SYSINIT(feeder_sign8, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_sign8);
+
+static struct pcm_feederdesc desc_sign16le[] = {
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {0},
+};
+static pcm_feeder feeder_sign16le =
+ { "sign16le", -1, desc_sign16le, NULL, NULL, feed_sign, (void *)2 };
+SYSINIT(feeder_sign16le, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_sign16le);
/*****************************************************************************/
@@ -264,147 +382,172 @@ static int
feed_table(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
{
int i = 0, j = f->source->feed(f->source, c, b, count, stream);
+
while (i < j) {
b[i] = ((u_int8_t *)f->data)[b[i]];
i++;
}
return i;
}
-static pcm_feeder feeder_ulawtou8 =
- { "ulawtou8", 0, NULL, NULL, feed_table, ulaw_to_u8 };
-static pcm_feeder feeder_u8toulaw =
- { "u8toulaw", 0, NULL, NULL, feed_table, u8_to_ulaw };
-/*****************************************************************************/
-
-struct fmtspec {
- int stereo;
- int sign;
- int bit16;
- int bigendian;
- int ulaw;
- int bad;
+static struct pcm_feederdesc desc_ulawtou8[] = {
+ {FEEDER_FMT, AFMT_MU_LAW, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {0},
};
+static pcm_feeder feeder_ulawtou8 =
+ { "ulawtou8", 0, desc_ulawtou8, NULL, NULL, feed_table, ulaw_to_u8 };
+SYSINIT(feeder_ulawtou8, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_ulawtou8);
-struct fmtcvt {
- pcm_feeder *f;
- struct fmtspec ispec, ospec;
+static struct pcm_feederdesc desc_u8toulaw[] = {
+ {FEEDER_FMT, AFMT_U8, AFMT_MU_LAW, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_MU_LAW | AFMT_STEREO, 0},
+ {0},
};
+static pcm_feeder feeder_u8toulaw =
+ { "u8toulaw", 0, desc_u8toulaw, NULL, NULL, feed_table, u8_to_ulaw };
+SYSINIT(feeder_u8toulaw, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_u8toulaw);
-struct fmtcvt cvttab[] = {
- {&feeder_ulawtou8, {-1, 0, 0, 0, 1}, {-1, 0, 0, 0, 0}},
- {&feeder_u8toulaw, {-1, 0, 0, 0, 0}, {-1, 0, 0, 0, 1}},
- {&feeder_sign8, {-1, 0, 0, 0, 0}, {-1, 1, 0, 0, 0}},
- {&feeder_sign8, {-1, 1, 0, 0, 0}, {-1, 0, 0, 0, 0}},
- {&feeder_monotostereo8, { 0, -1, 0, 0, -1}, { 1, -1, 0, 0, -1}},
- {&feeder_stereotomono8, { 1, -1, 0, 0, -1}, { 0, -1, 0, 0, -1}},
- {&feeder_sign16, {-1, 0, 1, 0, 0}, {-1, 1, 1, 0, 0}},
- {&feeder_sign16, {-1, 1, 1, 0, 0}, {-1, 0, 1, 0, 0}},
- {&feeder_8to16, {-1, -1, 0, 0, 0}, {-1, -1, 1, 0, 0}},
- {&feeder_16to8le, {-1, -1, 1, 0, 0}, {-1, -1, 0, 0, 0}},
- {&feeder_endian, {-1, -1, 1, 0, 0}, {-1, -1, 1, 1, 0}},
- {&feeder_endian, {-1, -1, 1, 1, 0}, {-1, -1, 1, 0, 0}},
-};
-#define FEEDERTABSZ (sizeof(cvttab) / sizeof(struct fmtcvt))
+/*****************************************************************************/
static int
-getspec(u_int32_t fmt, struct fmtspec *spec)
+cmpdesc(struct pcm_feederdesc *n, struct pcm_feederdesc *m)
{
- spec->stereo = (fmt & AFMT_STEREO)? 1 : 0;
- spec->sign = (fmt & AFMT_SIGNED)? 1 : 0;
- spec->bit16 = (fmt & AFMT_16BIT)? 1 : 0;
- spec->bigendian = (fmt & AFMT_BIGENDIAN)? 1 : 0;
- spec->ulaw = (fmt & AFMT_MU_LAW)? 1 : 0;
- spec->bad = (fmt & (AFMT_A_LAW | AFMT_MPEG))? 1 : 0;
- return 0;
+ return ((n->type == m->type) && (n->in == m->in) && (n->out == m->out) && (n->flags == m->flags));
}
-static int
-cmp(int x, int y)
+pcm_feeder *
+feeder_get(struct pcm_feederdesc *desc)
{
- return (x == -1 || x == y || y == -1)? 1 : 0;
-}
+ struct feedertab_entry *fte;
-static int
-cmpspec(struct fmtspec *x, struct fmtspec *y)
-{
- int i = 0;
- if (cmp(x->stereo, y->stereo)) i |= 0x01;
- if (cmp(x->sign, y->sign)) i |= 0x02;
- if (cmp(x->bit16, y->bit16)) i |= 0x04;
- if (cmp(x->bigendian, y->bigendian)) i |= 0x08;
- if (cmp(x->ulaw, y->ulaw)) i |= 0x10;
- return i;
+ SLIST_FOREACH(fte, &feedertab, link) {
+ if ((fte->desc != NULL) && cmpdesc(desc, fte->desc))
+ return fte->feeder;
+ }
+ return NULL;
}
-static int
-cvtapply(pcm_channel *c, struct fmtcvt *cvt, struct fmtspec *s)
+pcm_feeder *
+feeder_getroot()
{
- int i = cmpspec(s, &cvt->ospec);
- chn_addfeeder(c, cvt->f);
- if (cvt->ospec.stereo != -1) s->stereo = cvt->ospec.stereo;
- if (cvt->ospec.sign != -1) s->sign = cvt->ospec.sign;
- if (cvt->ospec.bit16 != -1) s->bit16 = cvt->ospec.bit16;
- if (cvt->ospec.bigendian != -1) s->bigendian = cvt->ospec.bigendian;
- if (cvt->ospec.ulaw != -1) s->ulaw = cvt->ospec.ulaw;
- return i;
+ struct feedertab_entry *fte;
+
+ SLIST_FOREACH(fte, &feedertab, link) {
+ if (fte->desc == NULL)
+ return fte->feeder;
+ }
+ return NULL;
}
int
-chn_feedchain(pcm_channel *c)
+chn_removefeeder(pcm_channel *c)
{
- int i, chosen, iter;
- u_int32_t mask;
- struct fmtspec s, t;
- struct fmtcvt *e;
+ pcm_feeder *f;
- while (chn_removefeeder(c) != -1);
- c->align = 0;
- if ((c->format & chn_getcaps(c)->formats) == c->format)
- return c->format;
- getspec(c->format, &s);
- if (s.bad) return -1;
- getspec(chn_getcaps(c)->bestfmt, &t);
- mask = (~cmpspec(&s, &t)) & 0x1f;
- iter = 0;
- do {
- if (mask == 0 || iter >= 8) break;
- chosen = -1;
- for (i = 0; i < FEEDERTABSZ && chosen == -1; i++) {
- e = &cvttab[i];
- if ((cmpspec(&s, &e->ispec) == 0x1f) &&
- ((~cmpspec(&e->ispec, &e->ospec)) & mask))
- chosen = i;
- }
- if (chosen != -1) mask &= cvtapply(c, &cvttab[chosen], &s);
- iter++;
- } while (chosen != -1);
- return (iter < 8)? chn_getcaps(c)->bestfmt : -1;
+ if (c->feeder->source == NULL)
+ return -1;
+ f = c->feeder->source;
+ if (c->feeder->free)
+ c->feeder->free(c->feeder);
+ free(c->feeder, M_DEVBUF);
+ c->feeder = f;
+ return 0;
}
static int
-chn_addfeeder(pcm_channel *c, pcm_feeder *f)
+chainok(pcm_feeder *test, pcm_feeder *stop)
{
- pcm_feeder *n;
- n = malloc(sizeof(pcm_feeder), M_DEVBUF, M_NOWAIT);
- *n = *f;
- n->source = c->feeder;
- c->feeder = n;
- if (n->init) n->init(n);
- if (n->align > 0) c->align += n->align;
- else if (n->align < 0 && c->align < -n->align) c->align -= n->align;
- return 0;
+ u_int32_t visited[MAXFEEDERS / 32];
+ u_int32_t idx, mask;
+
+ bzero(visited, sizeof(visited));
+ while (test && (test != stop)) {
+ idx = test->desc->idx;
+ if (idx < 0)
+ panic("bad idx %d", idx);
+ if (idx >= MAXFEEDERS)
+ panic("bad idx %d", idx);
+ mask = 1 << (idx & 31);
+ idx >>= 5;
+ if (visited[idx] & mask)
+ return 0;
+ visited[idx] |= mask;
+ test = test->source;
+ }
+ return 1;
}
-static int
-chn_removefeeder(pcm_channel *c)
+static pcm_feeder *
+feeder_fmtchain(u_int32_t *to, pcm_feeder *source, pcm_feeder *stop, int maxdepth)
{
- pcm_feeder *f;
- if (c->feeder == &feeder_root) return -1;
- f = c->feeder->source;
- if (c->feeder->free) c->feeder->free(c->feeder);
- free(c->feeder, M_DEVBUF);
- c->feeder = f;
- return 0;
+ struct feedertab_entry *fte;
+ pcm_feeder *try, *ret;
+ struct pcm_feederdesc *trydesc;
+
+ /* printf("trying %s...\n", source->name); */
+ if (fmtvalid(source->desc->out, to)) {
+ /* printf("got it\n"); */
+ return source;
+ }
+
+ if (maxdepth < 0)
+ return NULL;
+
+ try = malloc(sizeof(*try), M_DEVBUF, M_NOWAIT);
+ trydesc = malloc(sizeof(*trydesc), M_DEVBUF, M_NOWAIT);
+ trydesc->type = FEEDER_FMT;
+ trydesc->in = source->desc->out;
+ trydesc->out = 0;
+ trydesc->flags = 0;
+ trydesc->idx = -1;
+
+ SLIST_FOREACH(fte, &feedertab, link) {
+ if ((fte->desc) && (fte->desc->in == source->desc->out)) {
+ *try = *(fte->feeder);
+ try->source = source;
+ try->desc = trydesc;
+ trydesc->out = fte->desc->out;
+ trydesc->idx = fte->idx;
+ ret = chainok(try, stop)? feeder_fmtchain(to, try, stop, maxdepth - 1) : NULL;
+ if (ret != NULL)
+ return ret;
+ }
+ }
+ free(try, M_DEVBUF);
+ free(trydesc, M_DEVBUF);
+ /* printf("giving up %s...\n", source->name); */
+ return NULL;
}
+u_int32_t
+chn_feedchain(pcm_channel *c, u_int32_t *to)
+{
+ pcm_feeder *try, *stop;
+ int max;
+
+ stop = c->feeder;
+ try = NULL;
+ max = 0;
+ while (try == NULL && max++ < 8)
+ try = feeder_fmtchain(to, c->feeder, stop, max);
+ if (try == NULL)
+ return 0;
+ c->feeder = try;
+ c->align = 0;
+ /* printf("chain: "); */
+ while (try && (try != stop)) {
+ /* printf("%s [%d]", try->name, try->desc->idx); */
+ /* if (try->source) */
+ /* printf(" -> "); */
+ if (try->init)
+ try->init(try);
+ if (try->align > 0)
+ c->align += try->align;
+ else if (try->align < 0 && c->align < -try->align)
+ c->align = -try->align;
+ try = try->source;
+ }
+ /* printf("%s [%d]", try->name, try->desc->idx); */
+ return c->feeder->desc->out;
+}
OpenPOWER on IntegriCloud