change tracking of channel counts.
add method for retrieving "buffersize" hints for pcm devices, adjusted for specified minimum, maximum and default values.
This commit is contained in:
parent
89b447d520
commit
afd9c60fd0
@ -41,9 +41,10 @@ struct snddev_channel {
|
|||||||
struct snddev_info {
|
struct snddev_info {
|
||||||
SLIST_HEAD(, snddev_channel) channels;
|
SLIST_HEAD(, snddev_channel) channels;
|
||||||
struct pcm_channel *fakechan;
|
struct pcm_channel *fakechan;
|
||||||
unsigned devcount, reccount, chancount, vchancount;
|
unsigned devcount, playcount, reccount, vchancount;
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
int inprog;
|
int inprog;
|
||||||
|
unsigned int bufsz;
|
||||||
void *devinfo;
|
void *devinfo;
|
||||||
device_t dev;
|
device_t dev;
|
||||||
char status[SND_STATUSLEN];
|
char status[SND_STATUSLEN];
|
||||||
@ -339,19 +340,25 @@ pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t c
|
|||||||
{
|
{
|
||||||
struct pcm_channel *ch;
|
struct pcm_channel *ch;
|
||||||
char *dirs;
|
char *dirs;
|
||||||
int err;
|
int err, *pnum;
|
||||||
|
|
||||||
switch(dir) {
|
switch(dir) {
|
||||||
case PCMDIR_PLAY:
|
case PCMDIR_PLAY:
|
||||||
dirs = "play";
|
dirs = "play";
|
||||||
|
pnum = &d->playcount;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCMDIR_REC:
|
case PCMDIR_REC:
|
||||||
dirs = "record";
|
dirs = "record";
|
||||||
|
pnum = &d->reccount;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCMDIR_VIRTUAL:
|
case PCMDIR_VIRTUAL:
|
||||||
dirs = "virtual";
|
dirs = "virtual";
|
||||||
dir = PCMDIR_PLAY;
|
dir = PCMDIR_PLAY;
|
||||||
|
pnum = &d->vchancount;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -363,19 +370,24 @@ pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t c
|
|||||||
ch->methods = kobj_create(cls, M_DEVBUF, M_WAITOK);
|
ch->methods = kobj_create(cls, M_DEVBUF, M_WAITOK);
|
||||||
if (!ch->methods) {
|
if (!ch->methods) {
|
||||||
free(ch, M_DEVBUF);
|
free(ch, M_DEVBUF);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ch->num = (*pnum)++;
|
||||||
|
|
||||||
ch->pid = -1;
|
ch->pid = -1;
|
||||||
ch->parentsnddev = d;
|
ch->parentsnddev = d;
|
||||||
ch->parentchannel = parent;
|
ch->parentchannel = parent;
|
||||||
snprintf(ch->name, 32, "%s:%d:%s", device_get_nameunit(d->dev), d->chancount, dirs);
|
snprintf(ch->name, 32, "%s:%s:%d", device_get_nameunit(d->dev), dirs, ch->num);
|
||||||
|
|
||||||
err = chn_init(ch, devinfo, dir);
|
err = chn_init(ch, devinfo, dir);
|
||||||
if (err) {
|
if (err) {
|
||||||
device_printf(d->dev, "chn_init() for channel %d (%s) failed: err = %d\n", d->chancount, dirs, err);
|
device_printf(d->dev, "chn_init(%s) failed: err = %d\n", ch->name, err);
|
||||||
kobj_delete(ch->methods, M_DEVBUF);
|
kobj_delete(ch->methods, M_DEVBUF);
|
||||||
free(ch, M_DEVBUF);
|
free(ch, M_DEVBUF);
|
||||||
|
(*pnum)--;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,14 +397,23 @@ pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t c
|
|||||||
int
|
int
|
||||||
pcm_chn_destroy(struct pcm_channel *ch)
|
pcm_chn_destroy(struct pcm_channel *ch)
|
||||||
{
|
{
|
||||||
|
struct snddev_info *d;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
d = ch->parentsnddev;
|
||||||
err = chn_kill(ch);
|
err = chn_kill(ch);
|
||||||
if (err) {
|
if (err) {
|
||||||
device_printf(ch->parentsnddev->dev, "chn_kill() for %s failed, err = %d\n", ch->name, err);
|
device_printf(d->dev, "chn_kill(%s) failed, err = %d\n", ch->name, err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ch->direction == PCMDIR_REC)
|
||||||
|
d->reccount--;
|
||||||
|
else if (ch->flags & CHN_F_VIRTUAL)
|
||||||
|
d->vchancount--;
|
||||||
|
else
|
||||||
|
d->playcount--;
|
||||||
|
|
||||||
kobj_delete(ch->methods, M_DEVBUF);
|
kobj_delete(ch->methods, M_DEVBUF);
|
||||||
free(ch, M_DEVBUF);
|
free(ch, M_DEVBUF);
|
||||||
|
|
||||||
@ -424,21 +445,11 @@ pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch, int mkdev)
|
|||||||
SLIST_INSERT_AFTER(after, sce, link);
|
SLIST_INSERT_AFTER(after, sce, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch->direction == PCMDIR_REC)
|
|
||||||
ch->num = d->reccount++;
|
|
||||||
/*
|
|
||||||
else
|
|
||||||
ch->num = d->playcount++;
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (mkdev) {
|
if (mkdev) {
|
||||||
dsp_register(unit, d->devcount++);
|
dsp_register(unit, d->devcount++);
|
||||||
if (ch->direction == PCMDIR_REC)
|
if (ch->direction == PCMDIR_REC)
|
||||||
dsp_registerrec(unit, ch->num);
|
dsp_registerrec(unit, ch->num);
|
||||||
}
|
}
|
||||||
d->chancount++;
|
|
||||||
if (ch->flags & CHN_F_VIRTUAL)
|
|
||||||
d->vchancount++;
|
|
||||||
|
|
||||||
snd_mtxunlock(d->lock);
|
snd_mtxunlock(d->lock);
|
||||||
|
|
||||||
@ -459,16 +470,13 @@ pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch, int rmdev)
|
|||||||
snd_mtxunlock(d->lock);
|
snd_mtxunlock(d->lock);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
gotit:
|
gotit:
|
||||||
if (ch->flags & CHN_F_VIRTUAL)
|
|
||||||
d->vchancount--;
|
|
||||||
d->chancount--;
|
|
||||||
SLIST_REMOVE(&d->channels, sce, snddev_channel, link);
|
SLIST_REMOVE(&d->channels, sce, snddev_channel, link);
|
||||||
free(sce, M_DEVBUF);
|
free(sce, M_DEVBUF);
|
||||||
|
|
||||||
if (rmdev) {
|
if (rmdev) {
|
||||||
dsp_unregister(unit, --d->devcount);
|
dsp_unregister(unit, --d->devcount);
|
||||||
if (ch->direction == PCMDIR_REC)
|
if (ch->direction == PCMDIR_REC)
|
||||||
dsp_unregisterrec(unit, --d->reccount);
|
dsp_unregisterrec(unit, ch->num);
|
||||||
}
|
}
|
||||||
snd_mtxunlock(d->lock);
|
snd_mtxunlock(d->lock);
|
||||||
|
|
||||||
@ -555,6 +563,22 @@ pcm_getdevinfo(device_t dev)
|
|||||||
return d->devinfo;
|
return d->devinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
pcm_getbuffersize(device_t dev, unsigned int min, unsigned int deflt, unsigned int max)
|
||||||
|
{
|
||||||
|
struct snddev_info *d = device_get_softc(dev);
|
||||||
|
int sz;
|
||||||
|
|
||||||
|
sz = 0;
|
||||||
|
if (resource_int_value(device_get_name(dev), device_get_unit(dev), "buffersize", &sz) == 0)
|
||||||
|
RANGE(sz, min, max);
|
||||||
|
else
|
||||||
|
sz = deflt;
|
||||||
|
d->bufsz = sz;
|
||||||
|
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
|
pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
|
||||||
{
|
{
|
||||||
@ -568,7 +592,7 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
|
|||||||
d->devinfo = devinfo;
|
d->devinfo = devinfo;
|
||||||
d->devcount = 0;
|
d->devcount = 0;
|
||||||
d->reccount = 0;
|
d->reccount = 0;
|
||||||
d->chancount = 0;
|
d->playcount = 0;
|
||||||
d->vchancount = 0;
|
d->vchancount = 0;
|
||||||
d->inprog = 0;
|
d->inprog = 0;
|
||||||
|
|
||||||
@ -587,6 +611,8 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
|
|||||||
sysctl_ctx_free(&d->sysctl_tree);
|
sysctl_ctx_free(&d->sysctl_tree);
|
||||||
goto no;
|
goto no;
|
||||||
}
|
}
|
||||||
|
SYSCTL_ADD_INT(snd_sysctl_tree(dev), SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
|
||||||
|
OID_AUTO, "buffersize", CTLFLAG_RD, &d->bufsz, 0, "");
|
||||||
#endif
|
#endif
|
||||||
if (numplay > 0)
|
if (numplay > 0)
|
||||||
vchan_initsys(dev);
|
vchan_initsys(dev);
|
||||||
@ -606,6 +632,7 @@ pcm_unregister(device_t dev)
|
|||||||
{
|
{
|
||||||
struct snddev_info *d = device_get_softc(dev);
|
struct snddev_info *d = device_get_softc(dev);
|
||||||
struct snddev_channel *sce;
|
struct snddev_channel *sce;
|
||||||
|
struct pcm_channel *ch;
|
||||||
|
|
||||||
snd_mtxlock(d->lock);
|
snd_mtxlock(d->lock);
|
||||||
if (d->inprog) {
|
if (d->inprog) {
|
||||||
@ -619,8 +646,9 @@ pcm_unregister(device_t dev)
|
|||||||
return EBUSY;
|
return EBUSY;
|
||||||
}
|
}
|
||||||
SLIST_FOREACH(sce, &d->channels, link) {
|
SLIST_FOREACH(sce, &d->channels, link) {
|
||||||
if (sce->channel->refcount > 0) {
|
ch = sce->channel;
|
||||||
device_printf(dev, "unregister: channel busy\n");
|
if (ch->refcount > 0) {
|
||||||
|
device_printf(dev, "unregister: channel %s busy (pid %d)", ch->name, ch->pid);
|
||||||
snd_mtxunlock(d->lock);
|
snd_mtxunlock(d->lock);
|
||||||
return EBUSY;
|
return EBUSY;
|
||||||
}
|
}
|
||||||
@ -677,7 +705,7 @@ sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose)
|
|||||||
} else
|
} else
|
||||||
rc++;
|
rc++;
|
||||||
}
|
}
|
||||||
sbuf_printf(s, " (%dp/%dr/%dv channels%s%s)", pc, rc, vc,
|
sbuf_printf(s, " (%dp/%dr/%dv channels%s%s)", d->playcount, d->reccount, d->vchancount,
|
||||||
(d->flags & SD_F_SIMPLEX)? "" : " duplex",
|
(d->flags & SD_F_SIMPLEX)? "" : " duplex",
|
||||||
#ifdef USING_DEVFS
|
#ifdef USING_DEVFS
|
||||||
(device_get_unit(dev) == snd_unit)? " default" : ""
|
(device_get_unit(dev) == snd_unit)? " default" : ""
|
||||||
|
@ -232,6 +232,7 @@ int pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch, int mkdev);
|
|||||||
int pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch, int rmdev);
|
int pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch, int rmdev);
|
||||||
|
|
||||||
int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo);
|
int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo);
|
||||||
|
unsigned int pcm_getbuffersize(device_t dev, unsigned int min, unsigned int deflt, unsigned int max);
|
||||||
int pcm_register(device_t dev, void *devinfo, int numplay, int numrec);
|
int pcm_register(device_t dev, void *devinfo, int numplay, int numrec);
|
||||||
int pcm_unregister(device_t dev);
|
int pcm_unregister(device_t dev);
|
||||||
int pcm_setstatus(device_t dev, char *str);
|
int pcm_setstatus(device_t dev, char *str);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user