minor tweaks in speed and format setting routines.

don't stop exploring the feeders if a feeder fails to initialise.
This commit is contained in:
cg 2001-04-08 20:20:52 +00:00
parent cca900c66b
commit f51ad0092e
3 changed files with 72 additions and 65 deletions

View File

@ -184,7 +184,7 @@ chn_wrfeed(struct pcm_channel *c)
amt = sndbuf_getfree(b);
ret = (amt > 0)? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC;
if (ret == 0)
if (ret == 0 && sndbuf_getfree(b) < amt)
chn_wakeup(c);
/*
if (!(irqc & 63) || (ret != 0))
@ -724,9 +724,8 @@ chn_tryspeed(struct pcm_channel *c, int speed)
c->speed = speed;
sndbuf_setspd(bs, speed);
RANGE(speed, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
sndbuf_setspd(b, speed);
DEB(printf("try speed %d, ", sndbuf_getspd(b)));
sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, sndbuf_getspd(b)));
DEB(printf("try speed %d, ", speed));
sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, speed));
DEB(printf("got speed %d, ", sndbuf_getspd(b)));
delta = sndbuf_getspd(b) - sndbuf_getspd(bs);
@ -789,23 +788,17 @@ chn_tryformat(struct pcm_channel *c, u_int32_t fmt)
struct snd_dbuf *b = c->bufhard;
struct snd_dbuf *bs = c->bufsoft;
int r;
u_int32_t hwfmt;
CHN_LOCKASSERT(c);
if (CANCHANGE(c)) {
DEB(printf("want format %d\n", fmt));
c->format = fmt;
hwfmt = c->format;
c->feederflags &= ~(1 << FEEDER_FMT);
if (!fmtvalid(hwfmt, chn_getcaps(c)->fmtlist))
c->feederflags |= 1 << FEEDER_FMT;
r = chn_buildfeeder(c);
if (r == 0) {
hwfmt = c->feeder->desc->out;
sndbuf_setfmt(b, hwfmt);
sndbuf_setfmt(b, c->feeder->desc->out);
sndbuf_setfmt(bs, fmt);
chn_resetbuf(c);
CHANNEL_SETFORMAT(c->methods, c->devinfo, hwfmt);
CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b));
r = chn_tryspeed(c, c->speed);
}
return r;
@ -958,24 +951,33 @@ chn_buildfeeder(struct pcm_channel *c)
{
struct feeder_class *fc;
struct pcm_feederdesc desc;
u_int32_t tmp[2], src, dst, type, flags;
u_int32_t tmp[2], type, flags;
CHN_LOCKASSERT(c);
while (chn_removefeeder(c) == 0);
KASSERT((c->feeder == NULL), ("feeder chain not empty"));
c->align = sndbuf_getalign(c->bufsoft);
fc = feeder_getclass(NULL);
if (fc == NULL)
if (fc == NULL) {
DEB(printf("can't find root feeder\n"));
return EINVAL;
if (chn_addfeeder(c, fc, NULL))
}
if (chn_addfeeder(c, fc, NULL)) {
DEB(printf("can't add root feeder\n"));
return EINVAL;
}
c->feeder->desc->out = c->format;
flags = c->feederflags;
src = c->feeder->desc->out;
if ((c->flags & CHN_F_MAPPED) && (flags != 0))
if ((c->flags & CHN_F_MAPPED) && (flags != 0)) {
DEB(printf("can't build feeder chain on mapped channel\n"));
return EINVAL;
DEB(printf("not mapped, flags %x, ", flags));
}
DEB(printf("not mapped, flags %x\n", flags));
for (type = FEEDER_RATE; type <= FEEDER_LAST; type++) {
if (flags & (1 << type)) {
desc.type = type;
@ -985,33 +987,38 @@ chn_buildfeeder(struct pcm_channel *c)
DEB(printf("find feeder type %d, ", type));
fc = feeder_getclass(&desc);
DEB(printf("got %p\n", fc));
if (fc == NULL)
if (fc == NULL) {
DEB(printf("can't find required feeder type %d\n", type));
return EINVAL;
dst = fc->desc->in;
if (src != dst) {
DEB(printf("build fmtchain from %x to %x: ", src, dst));
tmp[0] = dst;
}
if (c->feeder->desc->out != fc->desc->in) {
DEB(printf("build fmtchain from %x to %x: ", c->feeder->desc->out, fc->desc->in));
tmp[0] = fc->desc->in;
tmp[1] = 0;
if (chn_fmtchain(c, tmp) == 0)
if (chn_fmtchain(c, tmp) == 0) {
DEB(printf("failed\n"));
return EINVAL;
}
DEB(printf("ok\n"));
}
if (chn_addfeeder(c, fc, fc->desc))
if (chn_addfeeder(c, fc, fc->desc)) {
DEB(printf("can't add feeder %p, output %x\n", fc, fc->desc->out));
return EINVAL;
src = fc->desc->out;
DEB(printf("added feeder %p, output %x\n", fc, src));
dst = 0;
flags &= ~(1 << type);
}
DEB(printf("added feeder %p, output %x\n", fc, c->feeder->desc->out));
}
}
if (!fmtvalid(src, chn_getcaps(c)->fmtlist)) {
if (chn_fmtchain(c, chn_getcaps(c)->fmtlist) == 0)
if (!fmtvalid(c->feeder->desc->out, chn_getcaps(c)->fmtlist)) {
if (chn_fmtchain(c, chn_getcaps(c)->fmtlist) == 0) {
DEB(printf("can't build fmtchain from %x\n", c->feeder->desc->out));
return EINVAL;
DEB(printf("built fmtchain from %x to %x\n", src, c->feeder->desc->out));
flags &= ~(1 << FEEDER_FMT);
}
DEB(printf("built fmtchain from %x\n", c->feeder->desc->out));
}
return 0;
}

View File

@ -69,6 +69,7 @@ feeder_register(void *p)
i = 0;
while ((feedercnt < MAXFEEDERS) && (fc->desc[i].type > 0)) {
printf("adding feeder %s, %x -> %x\n", fc->name, fc->desc[i].in, fc->desc[i].out);
fte = malloc(sizeof(*fte), M_FEEDER, M_WAITOK | M_ZERO);
fte->feederclass = fc;
fte->desc = &fc->desc[i];
@ -132,8 +133,10 @@ feeder_create(struct feeder_class *fc, struct pcm_feederdesc *desc)
}
f->data = fc->data;
f->source = NULL;
f->class = fc;
err = FEEDER_INIT(f);
if (err) {
printf("feeder_init(%p) on %s returned %d\n", f, fc->name, err);
feeder_destroy(f);
return NULL;
} else
@ -230,9 +233,8 @@ feeder_fmtchain(u_int32_t *to, struct pcm_feeder *source, struct pcm_feeder *sto
{
struct feedertab_entry *fte;
struct pcm_feeder *try, *ret;
struct pcm_feederdesc trydesc;
/* printf("trying %s...\n", source->name); */
/* printf("trying %s (%x -> %x)...\n", source->class->name, source->desc->in, source->desc->out); */
if (fmtvalid(source->desc->out, to)) {
/* printf("got it\n"); */
return source;
@ -241,27 +243,24 @@ feeder_fmtchain(u_int32_t *to, struct pcm_feeder *source, struct pcm_feeder *sto
if (maxdepth < 0)
return NULL;
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)) {
trydesc.out = fte->desc->out;
trydesc.idx = fte->idx;
try = feeder_create(fte->feederclass, &trydesc);
if (try == NULL)
return NULL;
try->source = source;
ret = chainok(try, stop)? feeder_fmtchain(to, try, stop, maxdepth - 1) : NULL;
if (ret != NULL)
return ret;
feeder_destroy(try);
if (fte->desc == NULL)
goto no;
if (fte->desc->type != FEEDER_FMT)
goto no;
if (fte->desc->in == source->desc->out) {
try = feeder_create(fte->feederclass, fte->desc);
if (try) {
try->source = source;
ret = chainok(try, stop)? feeder_fmtchain(to, try, stop, maxdepth - 1) : NULL;
if (ret != NULL)
return ret;
feeder_destroy(try);
}
}
no:
}
/* printf("giving up %s...\n", source->name); */
/* printf("giving up %s...\n", source->class->name); */
return NULL;
}
@ -287,7 +286,7 @@ chn_fmtchain(struct pcm_channel *c, u_int32_t *to)
#endif
while (try && (try != stop)) {
#ifdef FEEDER_DEBUG
printf("%s [%d]", try->name, try->desc->idx);
printf("%s [%d]", try->class->name, try->desc->idx);
if (try->source)
printf(" -> ");
#endif
@ -298,7 +297,7 @@ chn_fmtchain(struct pcm_channel *c, u_int32_t *to)
try = try->source;
}
#ifdef FEEDER_DEBUG
printf("%s [%d]\n", try->name, try->desc->idx);
printf("%s [%d]\n", try->class->name, try->desc->idx);
#endif
return c->feeder->desc->out;
}

View File

@ -33,14 +33,6 @@ struct pcm_feederdesc {
int idx;
};
struct pcm_feeder {
KOBJ_FIELDS;
int align;
struct pcm_feederdesc *desc;
void *data;
struct pcm_feeder *source;
};
struct feeder_class {
KOBJ_CLASS_FIELDS;
int align;
@ -48,6 +40,15 @@ struct feeder_class {
void *data;
};
struct pcm_feeder {
KOBJ_FIELDS;
int align;
struct pcm_feederdesc *desc;
void *data;
struct feeder_class *class;
struct pcm_feeder *source;
};
void feeder_register(void *p);
struct feeder_class *feeder_getclass(struct pcm_feederdesc *desc);