mirror of https://github.com/ericonr/sndio.git
If available, use the hardware output.level to control the volume.
With this change, there's a single outputs.level control: either the hardware one or software one. Consequently, there can't be control name clashes and there's no need to move hardware's top-level controls into the "hw/" group.
This commit is contained in:
parent
fab9b7cb7e
commit
e5f270a89f
89
sndiod/dev.c
89
sndiod/dev.c
|
@ -349,8 +349,26 @@ dev_midi_vol(struct dev *d, struct slot *s)
|
|||
void
|
||||
dev_midi_master(struct dev *d)
|
||||
{
|
||||
struct ctl *c;
|
||||
unsigned int master, v;
|
||||
struct sysex x;
|
||||
|
||||
if (d->master_enabled)
|
||||
master = d->master;
|
||||
else {
|
||||
master = 0;
|
||||
for (c = d->ctl_list; c != NULL; c = c->next) {
|
||||
if (c->type != CTL_NUM ||
|
||||
strcmp(c->group, "") != 0 ||
|
||||
strcmp(c->node0.name, "output") != 0 ||
|
||||
strcmp(c->func, "level") != 0)
|
||||
continue;
|
||||
v = (c->curval * 127 + c->maxval / 2) / c->maxval;
|
||||
if (master < v)
|
||||
master = v;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&x, 0, sizeof(struct sysex));
|
||||
x.start = SYSEX_START;
|
||||
x.type = SYSEX_TYPE_RT;
|
||||
|
@ -358,7 +376,7 @@ dev_midi_master(struct dev *d)
|
|||
x.id0 = SYSEX_CONTROL;
|
||||
x.id1 = SYSEX_MASTER;
|
||||
x.u.master.fine = 0;
|
||||
x.u.master.coarse = d->master;
|
||||
x.u.master.coarse = master;
|
||||
x.u.master.end = SYSEX_END;
|
||||
midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(master));
|
||||
}
|
||||
|
@ -442,8 +460,10 @@ dev_midi_omsg(void *arg, unsigned char *msg, int len)
|
|||
if (x->id0 == SYSEX_CONTROL && x->id1 == SYSEX_MASTER) {
|
||||
if (len == SYSEX_SIZE(master)) {
|
||||
dev_master(d, x->u.master.coarse);
|
||||
dev_onval(d, CTLADDR_MASTER,
|
||||
x->u.master.coarse);
|
||||
if (d->master_enabled) {
|
||||
dev_onval(d, CTLADDR_MASTER,
|
||||
x->u.master.coarse);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -655,7 +675,8 @@ dev_mix_adjvol(struct dev *d)
|
|||
}
|
||||
if (weight > i->opt->maxweight)
|
||||
weight = i->opt->maxweight;
|
||||
i->mix.weight = ADATA_MUL(weight, MIDI_TO_ADATA(d->master));
|
||||
i->mix.weight = d->master_enabled ?
|
||||
ADATA_MUL(weight, MIDI_TO_ADATA(d->master)) : weight;
|
||||
#ifdef DEBUG
|
||||
if (log_level >= 3) {
|
||||
slot_log(i);
|
||||
|
@ -946,15 +967,30 @@ dev_onmove(struct dev *d, int delta)
|
|||
void
|
||||
dev_master(struct dev *d, unsigned int master)
|
||||
{
|
||||
struct ctl *c;
|
||||
unsigned int v;
|
||||
|
||||
if (log_level >= 2) {
|
||||
dev_log(d);
|
||||
log_puts(": master volume set to ");
|
||||
log_putu(master);
|
||||
log_puts("\n");
|
||||
}
|
||||
d->master = master;
|
||||
if (d->mode & MODE_PLAY)
|
||||
dev_mix_adjvol(d);
|
||||
if (d->master_enabled) {
|
||||
d->master = master;
|
||||
if (d->mode & MODE_PLAY)
|
||||
dev_mix_adjvol(d);
|
||||
} else {
|
||||
for (c = d->ctl_list; c != NULL; c = c->next) {
|
||||
if (c->type != CTL_NUM ||
|
||||
strcmp(c->group, "") != 0 ||
|
||||
strcmp(c->node0.name, "output") != 0 ||
|
||||
strcmp(c->func, "level") != 0)
|
||||
continue;
|
||||
v = (master * c->maxval + 64) / 127;
|
||||
dev_setctl(d, c->addr, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1121,6 +1157,7 @@ dev_open(struct dev *d)
|
|||
int i;
|
||||
char name[CTL_NAMEMAX];
|
||||
|
||||
d->master_enabled = 0;
|
||||
d->mode = d->reqmode;
|
||||
d->round = d->reqround;
|
||||
d->bufsz = d->reqbufsz;
|
||||
|
@ -1149,8 +1186,6 @@ dev_open(struct dev *d)
|
|||
name, -1, "level",
|
||||
NULL, -1, 127, d->slot[i].vol);
|
||||
}
|
||||
dev_addctl(d, "", CTL_NUM,
|
||||
CTLADDR_MASTER, "output", -1, "level", NULL, -1, 127, d->master);
|
||||
|
||||
d->pstate = DEV_INIT;
|
||||
return 1;
|
||||
|
@ -2337,8 +2372,36 @@ dev_rmctl(struct dev *d, int addr)
|
|||
void
|
||||
dev_ctlsync(struct dev *d)
|
||||
{
|
||||
struct ctl *c;
|
||||
struct ctlslot *s;
|
||||
int i;
|
||||
int found, i;
|
||||
|
||||
found = 0;
|
||||
for (c = d->ctl_list; c != NULL; c = c->next) {
|
||||
if (c->addr != CTLADDR_MASTER &&
|
||||
c->type == CTL_NUM &&
|
||||
strcmp(c->group, "") == 0 &&
|
||||
strcmp(c->node0.name, "output") == 0 &&
|
||||
strcmp(c->func, "level") == 0)
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if (d->master_enabled && found) {
|
||||
if (log_level >= 2) {
|
||||
dev_log(d);
|
||||
log_puts(": software master level control disabled\n");
|
||||
}
|
||||
d->master_enabled = 0;
|
||||
dev_rmctl(d, CTLADDR_MASTER);
|
||||
} else if (!d->master_enabled && !found) {
|
||||
if (log_level >= 2) {
|
||||
dev_log(d);
|
||||
log_puts(": software master level control enabled\n");
|
||||
}
|
||||
d->master_enabled = 1;
|
||||
dev_addctl(d, "", CTL_NUM, CTLADDR_MASTER,
|
||||
"output", -1, "level", NULL, -1, 127, d->master);
|
||||
}
|
||||
|
||||
for (s = d->ctlslot, i = DEV_NCTLSLOT; i > 0; i--, s++) {
|
||||
if (s->ops)
|
||||
|
@ -2392,8 +2455,10 @@ dev_setctl(struct dev *d, int addr, int val)
|
|||
dev_ref(d);
|
||||
} else {
|
||||
if (addr == CTLADDR_MASTER) {
|
||||
dev_master(d, val);
|
||||
dev_midi_master(d);
|
||||
if (d->master_enabled) {
|
||||
dev_master(d, val);
|
||||
dev_midi_master(d);
|
||||
}
|
||||
} else {
|
||||
num = addr - CTLADDR_SLOT_LEVEL(0);
|
||||
slot_setvol(d->slot + num, val);
|
||||
|
|
|
@ -244,7 +244,9 @@ struct dev {
|
|||
#define MMC_START 2 /* attempting to start */
|
||||
#define MMC_RUN 3 /* started */
|
||||
unsigned int tstate; /* one of above */
|
||||
unsigned int master; /* master volume controller */
|
||||
|
||||
unsigned int master; /* software vol. knob */
|
||||
unsigned int master_enabled; /* 1 if h/w has no vo. knob */
|
||||
|
||||
/*
|
||||
* control
|
||||
|
|
|
@ -65,18 +65,17 @@ dev_sioctl_ondesc(void *arg, struct sioctl_desc *desc, int val)
|
|||
dev_rmctl(d, addr);
|
||||
|
||||
/*
|
||||
* prefix group names we use (top-level and "app") with "hw."
|
||||
* prefix group names we use (currently "app") with "hw/"
|
||||
* to ensure that all controls have unique names when multiple
|
||||
* sndiod's are chained
|
||||
*/
|
||||
if (desc->group[0] == 0)
|
||||
group = GROUP_PREFIX;
|
||||
else {
|
||||
if (strcmp(desc->group, "app") == 0) {
|
||||
group = group_buf;
|
||||
if (snprintf(group_buf, CTL_NAMEMAX, GROUP_PREFIX "/%s",
|
||||
desc->group) >= CTL_NAMEMAX)
|
||||
return;
|
||||
}
|
||||
} else
|
||||
group = desc->group;
|
||||
|
||||
dev_addctl(d, group, desc->type, addr,
|
||||
desc->node0.name, desc->node0.unit, desc->func,
|
||||
|
|
Loading…
Reference in New Issue