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
|
void
|
||||||
dev_midi_master(struct dev *d)
|
dev_midi_master(struct dev *d)
|
||||||
{
|
{
|
||||||
|
struct ctl *c;
|
||||||
|
unsigned int master, v;
|
||||||
struct sysex x;
|
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));
|
memset(&x, 0, sizeof(struct sysex));
|
||||||
x.start = SYSEX_START;
|
x.start = SYSEX_START;
|
||||||
x.type = SYSEX_TYPE_RT;
|
x.type = SYSEX_TYPE_RT;
|
||||||
|
@ -358,7 +376,7 @@ dev_midi_master(struct dev *d)
|
||||||
x.id0 = SYSEX_CONTROL;
|
x.id0 = SYSEX_CONTROL;
|
||||||
x.id1 = SYSEX_MASTER;
|
x.id1 = SYSEX_MASTER;
|
||||||
x.u.master.fine = 0;
|
x.u.master.fine = 0;
|
||||||
x.u.master.coarse = d->master;
|
x.u.master.coarse = master;
|
||||||
x.u.master.end = SYSEX_END;
|
x.u.master.end = SYSEX_END;
|
||||||
midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(master));
|
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 (x->id0 == SYSEX_CONTROL && x->id1 == SYSEX_MASTER) {
|
||||||
if (len == SYSEX_SIZE(master)) {
|
if (len == SYSEX_SIZE(master)) {
|
||||||
dev_master(d, x->u.master.coarse);
|
dev_master(d, x->u.master.coarse);
|
||||||
dev_onval(d, CTLADDR_MASTER,
|
if (d->master_enabled) {
|
||||||
x->u.master.coarse);
|
dev_onval(d, CTLADDR_MASTER,
|
||||||
|
x->u.master.coarse);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -655,7 +675,8 @@ dev_mix_adjvol(struct dev *d)
|
||||||
}
|
}
|
||||||
if (weight > i->opt->maxweight)
|
if (weight > i->opt->maxweight)
|
||||||
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
|
#ifdef DEBUG
|
||||||
if (log_level >= 3) {
|
if (log_level >= 3) {
|
||||||
slot_log(i);
|
slot_log(i);
|
||||||
|
@ -946,15 +967,30 @@ dev_onmove(struct dev *d, int delta)
|
||||||
void
|
void
|
||||||
dev_master(struct dev *d, unsigned int master)
|
dev_master(struct dev *d, unsigned int master)
|
||||||
{
|
{
|
||||||
|
struct ctl *c;
|
||||||
|
unsigned int v;
|
||||||
|
|
||||||
if (log_level >= 2) {
|
if (log_level >= 2) {
|
||||||
dev_log(d);
|
dev_log(d);
|
||||||
log_puts(": master volume set to ");
|
log_puts(": master volume set to ");
|
||||||
log_putu(master);
|
log_putu(master);
|
||||||
log_puts("\n");
|
log_puts("\n");
|
||||||
}
|
}
|
||||||
d->master = master;
|
if (d->master_enabled) {
|
||||||
if (d->mode & MODE_PLAY)
|
d->master = master;
|
||||||
dev_mix_adjvol(d);
|
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;
|
int i;
|
||||||
char name[CTL_NAMEMAX];
|
char name[CTL_NAMEMAX];
|
||||||
|
|
||||||
|
d->master_enabled = 0;
|
||||||
d->mode = d->reqmode;
|
d->mode = d->reqmode;
|
||||||
d->round = d->reqround;
|
d->round = d->reqround;
|
||||||
d->bufsz = d->reqbufsz;
|
d->bufsz = d->reqbufsz;
|
||||||
|
@ -1149,8 +1186,6 @@ dev_open(struct dev *d)
|
||||||
name, -1, "level",
|
name, -1, "level",
|
||||||
NULL, -1, 127, d->slot[i].vol);
|
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;
|
d->pstate = DEV_INIT;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2337,8 +2372,36 @@ dev_rmctl(struct dev *d, int addr)
|
||||||
void
|
void
|
||||||
dev_ctlsync(struct dev *d)
|
dev_ctlsync(struct dev *d)
|
||||||
{
|
{
|
||||||
|
struct ctl *c;
|
||||||
struct ctlslot *s;
|
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++) {
|
for (s = d->ctlslot, i = DEV_NCTLSLOT; i > 0; i--, s++) {
|
||||||
if (s->ops)
|
if (s->ops)
|
||||||
|
@ -2392,8 +2455,10 @@ dev_setctl(struct dev *d, int addr, int val)
|
||||||
dev_ref(d);
|
dev_ref(d);
|
||||||
} else {
|
} else {
|
||||||
if (addr == CTLADDR_MASTER) {
|
if (addr == CTLADDR_MASTER) {
|
||||||
dev_master(d, val);
|
if (d->master_enabled) {
|
||||||
dev_midi_master(d);
|
dev_master(d, val);
|
||||||
|
dev_midi_master(d);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
num = addr - CTLADDR_SLOT_LEVEL(0);
|
num = addr - CTLADDR_SLOT_LEVEL(0);
|
||||||
slot_setvol(d->slot + num, val);
|
slot_setvol(d->slot + num, val);
|
||||||
|
|
|
@ -244,7 +244,9 @@ struct dev {
|
||||||
#define MMC_START 2 /* attempting to start */
|
#define MMC_START 2 /* attempting to start */
|
||||||
#define MMC_RUN 3 /* started */
|
#define MMC_RUN 3 /* started */
|
||||||
unsigned int tstate; /* one of above */
|
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
|
* control
|
||||||
|
|
|
@ -65,18 +65,17 @@ dev_sioctl_ondesc(void *arg, struct sioctl_desc *desc, int val)
|
||||||
dev_rmctl(d, addr);
|
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
|
* to ensure that all controls have unique names when multiple
|
||||||
* sndiod's are chained
|
* sndiod's are chained
|
||||||
*/
|
*/
|
||||||
if (desc->group[0] == 0)
|
if (strcmp(desc->group, "app") == 0) {
|
||||||
group = GROUP_PREFIX;
|
|
||||||
else {
|
|
||||||
group = group_buf;
|
group = group_buf;
|
||||||
if (snprintf(group_buf, CTL_NAMEMAX, GROUP_PREFIX "/%s",
|
if (snprintf(group_buf, CTL_NAMEMAX, GROUP_PREFIX "/%s",
|
||||||
desc->group) >= CTL_NAMEMAX)
|
desc->group) >= CTL_NAMEMAX)
|
||||||
return;
|
return;
|
||||||
}
|
} else
|
||||||
|
group = desc->group;
|
||||||
|
|
||||||
dev_addctl(d, group, desc->type, addr,
|
dev_addctl(d, group, desc->type, addr,
|
||||||
desc->node0.name, desc->node0.unit, desc->func,
|
desc->node0.name, desc->node0.unit, desc->func,
|
||||||
|
|
Loading…
Reference in New Issue