Add "maxval" attribute to sioctl_desc structure.

As control may have different max values, make sndioctl
expose floats in the [0:1] range.
This commit is contained in:
Alexandre Ratchov 2020-02-22 14:52:20 +01:00
parent 2207b5e6db
commit e55971c61e
10 changed files with 54 additions and 49 deletions

View File

@ -145,8 +145,9 @@ struct amsg_ctl_desc {
uint8_t type; /* see sioctl_desc structure */
uint8_t __pad1[1];
uint16_t addr; /* control address */
uint16_t __pad2[1];
uint16_t maxval;
uint16_t curval;
uint32_t __pad2[3];
};
/*

View File

@ -90,6 +90,7 @@ sioctl_aucat_rdata(struct sioctl_aucat_hdl *hdl)
strlcpy(desc.func, c->func, SIOCTL_NAMEMAX);
desc.type = c->type;
desc.addr = ntohs(c->addr);
desc.maxval = ntohs(c->maxval);
_sioctl_ondesc_cb(&hdl->sioctl,
&desc, ntohs(c->curval));
rpos += sizeof(struct amsg_ctl_desc);

View File

@ -42,9 +42,6 @@
sizeof(DEVPATH_PREFIX) - 1 + \
sizeof(int) * 3)
#define SUN_TO_SIOCTL(v) (((v) * 127 + 127) / 255)
#define SIOCTL_TO_SUN(v) (((v) * 255 + 63) / 127)
struct volume
{
int nch; /* channels in the level control */
@ -178,10 +175,8 @@ setvol(struct sioctl_sun_hdl *hdl, struct volume *vol, int addr, int val)
ctrl.dev = vol->level_idx;
ctrl.type = AUDIO_MIXER_VALUE;
ctrl.un.value.num_channels = vol->nch;
for (i = 0; i < vol->nch; i++) {
ctrl.un.value.level[i] =
SIOCTL_TO_SUN(vol->level_val[i]);
}
for (i = 0; i < vol->nch; i++)
ctrl.un.value.level[i] = vol->level_val[i];
DPRINTF("vol %d setting to %d\n", addr, vol->level_val[addr]);
if (ioctl(hdl->fd, AUDIO_MIXER_WRITE, &ctrl) < 0) {
DPRINTF("level write failed\n");
@ -233,6 +228,7 @@ scanvol(struct sioctl_sun_hdl *hdl, struct volume *vol)
return 0;
}
desc.type = SIOCTL_NUM;
desc.maxval = AUDIO_MAX_GAIN;
desc.node1.name[0] = 0;
desc.node1.unit = -1;
strlcpy(desc.func, "level", SIOCTL_NAMEMAX);
@ -240,7 +236,7 @@ scanvol(struct sioctl_sun_hdl *hdl, struct volume *vol)
for (i = 0; i < vol->nch; i++) {
desc.node0.unit = i;
desc.addr = vol->base_addr + i;
val = SUN_TO_SIOCTL(ctrl.un.value.level[i]);
val = ctrl.un.value.level[i];
vol->level_val[i] = val;
_sioctl_ondesc_cb(&hdl->sioctl, &desc, val);
}
@ -253,11 +249,12 @@ scanvol(struct sioctl_sun_hdl *hdl, struct volume *vol)
return 0;
}
desc.type = SIOCTL_SW;
desc.maxval = 1;
desc.node1.name[0] = 0;
desc.node1.unit = -1;
strlcpy(desc.func, "mute", SIOCTL_NAMEMAX);
strlcpy(desc.node0.name, vol->name, SIOCTL_NAMEMAX);
val = ctrl.un.ord ? SIOCTL_VALMAX : 0;
val = ctrl.un.ord ? 1 : 0;
vol->mute_val = val;
for (i = 0; i < vol->nch; i++) {
desc.node0.unit = i;
@ -287,7 +284,7 @@ updatevol(struct sioctl_sun_hdl *hdl, struct volume *vol, int idx)
return 0;
}
if (idx == vol->mute_idx) {
val = ctrl.un.ord ? SIOCTL_VALMAX : 0;
val = ctrl.un.ord ? 1 : 0;
if (vol->mute_val == val)
return 1;
vol->mute_val = val;
@ -297,7 +294,7 @@ updatevol(struct sioctl_sun_hdl *hdl, struct volume *vol, int idx)
}
} else {
for (i = 0; i < vol->nch; i++) {
val = SUN_TO_SIOCTL(ctrl.un.value.level[i]);
val = ctrl.un.value.level[i];
if (vol->level_val[i] == val)
continue;
vol->level_val[i] = val;

View File

@ -30,7 +30,6 @@
* limits
*/
#define SIOCTL_NAMEMAX 12 /* max name length */
#define SIOCTL_VALMAX 127 /* max control value */
/*
* private ``handle'' structure
@ -115,6 +114,8 @@ struct sioctl_desc {
char group[SIOCTL_NAMEMAX]; /* group this control belongs to */
struct sioctl_node node0; /* affected node */
struct sioctl_node node1; /* dito for SIOCTL_{VEC,LIST} */
unsigned int maxval; /* max value for SIOCTL_{NUM,VEC} */
int __pad[3];
};
/*

View File

@ -16,11 +16,11 @@
*/
#include <errno.h>
#include <poll.h>
#include <sndio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sndio.h>
struct info {
struct info *next;
@ -52,9 +52,9 @@ void print_val(struct info *, int);
void print_par(struct info *, int, char *);
int parse_name(char **, char *);
int parse_unit(char **, unsigned int *);
int parse_val(char **, unsigned int *);
int parse_val(char **, float *);
int parse_node(char **, char *, int *);
int parse_modeval(char **, int *, int *);
int parse_modeval(char **, int *, float *);
void dump(void);
int cmd(char *);
void commit(void);
@ -78,6 +78,12 @@ isname_next(int c)
return isname_first(c) || (c >= '0' && c <= '9') || (c == '_');
}
static int
ftoi(float f)
{
return f + 0.5;
}
/*
* compare two sioctl_desc structures, used to sort infolist
*/
@ -368,7 +374,7 @@ print_val(struct info *p, int mono)
switch (p->desc.type) {
case SIOCTL_NUM:
case SIOCTL_SW:
printf("%.2g", p->curval / (float)SIOCTL_VALMAX);
printf("%.2g", p->curval / (float)p->desc.maxval);
break;
case SIOCTL_VEC:
case SIOCTL_LIST:
@ -383,7 +389,7 @@ print_val(struct info *p, int mono)
if (more)
printf(",");
print_node(&e->desc.node1, mono);
printf(":%.2g", e->curval / (float)SIOCTL_VALMAX);
printf(":%.2g", e->curval / (float)e->desc.maxval);
more = 1;
}
}
@ -461,25 +467,21 @@ parse_unit(char **line, unsigned int *num)
}
int
parse_val(char **line, unsigned int *num)
parse_val(char **line, float *num)
{
char *p = *line;
unsigned int ival;
float fval;
float val;
int n;
if (sscanf(p, "%g%n", &fval, &n) != 1) {
if (sscanf(p, "%g%n", &val, &n) != 1) {
fprintf(stderr, "number expected near '%s'\n", p);
return 0;
}
if (fval < 0 || fval > 1) {
fprintf(stderr, "%g: expected number between 0 and 1\n", fval);
if (val < 0 || val > 1) {
fprintf(stderr, "%g: expected number between 0 and 1\n", val);
return 0;
}
ival = fval * (SIOCTL_VALMAX + 1);
if (ival > SIOCTL_VALMAX)
ival = SIOCTL_VALMAX;
*num = ival;
*num = val;
*line = p + n;
return 1;
}
@ -515,7 +517,7 @@ parse_node(char **line, char *str, int *unit)
* parse a decimal prefixed by the optional mode
*/
int
parse_modeval(char **line, int *rmode, int *rval)
parse_modeval(char **line, int *rmode, float *rval)
{
char *p = *line;
unsigned mode;
@ -561,12 +563,12 @@ dump(void)
switch (i->desc.type) {
case SIOCTL_NUM:
case SIOCTL_SW:
printf("* (%u)", i->curval);
printf("0..%d (%u)", i->desc.maxval, i->curval);
break;
case SIOCTL_VEC:
case SIOCTL_LIST:
print_node(&i->desc.node1, 0);
printf(":* (%u)", i->curval);
printf(":0..%d (%u)", i->desc.maxval, i->curval);
}
printf("\n");
}
@ -584,7 +586,8 @@ cmd(char *line)
char astr[SIOCTL_NAMEMAX], vstr[SIOCTL_NAMEMAX];
int aunit, vunit;
unsigned npar = 0, nent = 0;
int val, comma, mode;
int comma, mode;
float val;
pos = strrchr(line, '/');
if (pos != NULL) {
@ -637,7 +640,7 @@ cmd(char *line)
if (!matchpar(i, astr, aunit))
continue;
i->mode = mode;
i->newval = val;
i->newval = ftoi(val * i->desc.maxval);
npar++;
}
break;
@ -668,7 +671,7 @@ cmd(char *line)
if (!parse_modeval(&pos, &mode, &val))
return 0;
} else {
val = SIOCTL_VALMAX;
val = 1.;
mode = MODE_SET;
}
nent = 0;
@ -677,7 +680,7 @@ cmd(char *line)
continue;
for (e = i; e != NULL; e = nextent(e, 0)) {
if (matchent(e, vstr, vunit)) {
e->newval = val;
e->newval = ftoi(val * e->desc.maxval);
e->mode = mode;
nent++;
}
@ -723,8 +726,8 @@ commit(void)
break;
case MODE_ADD:
val = i->curval + i->newval;
if (val > SIOCTL_VALMAX)
val = SIOCTL_VALMAX;
if (val > i->desc.maxval)
val = i->desc.maxval;
break;
case MODE_SUB:
val = i->curval - i->newval;
@ -732,11 +735,8 @@ commit(void)
val = 0;
break;
case MODE_TOGGLE:
val = (i->curval >= SIOCTL_VALMAX / 2) ?
0 : SIOCTL_VALMAX;
val = i->curval ? 0 : i->desc.maxval;
}
if (i->desc.type == SIOCTL_SW || i->desc.type == SIOCTL_LIST)
val = val ? SIOCTL_VALMAX : 0;
sioctl_setval(hdl, i->ctladdr, val);
i->curval = val;
}

View File

@ -1147,10 +1147,10 @@ dev_open(struct dev *d)
dev_addctl(d, "app", CTL_NUM,
CTLADDR_SLOT_LEVEL(i),
name, -1, "level",
NULL, -1, d->slot[i].vol);
NULL, -1, 127, d->slot[i].vol);
}
dev_addctl(d, "", CTL_NUM,
CTLADDR_MASTER, "output", -1, "level", NULL, -1, d->master);
CTLADDR_MASTER, "output", -1, "level", NULL, -1, 127, d->master);
d->pstate = DEV_INIT;
return 1;
@ -2259,7 +2259,7 @@ ctl_log(struct ctl *c)
*/
struct ctl *
dev_addctl(struct dev *d, char *gstr, int type, int addr,
char *str0, int unit0, char *func, char *str1, int unit1, int val)
char *str0, int unit0, char *func, char *str1, int unit1, int maxval, int val)
{
struct ctl *c, **pc;
int i;
@ -2276,6 +2276,7 @@ dev_addctl(struct dev *d, char *gstr, int type, int addr,
} else
memset(&c->node1, 0, sizeof(struct ctl_node));
c->addr = addr;
c->maxval = maxval;
c->val_mask = ~0;
c->desc_mask = ~0;
c->curval = val;

View File

@ -139,6 +139,7 @@ struct ctl {
unsigned int val_mask;
unsigned int desc_mask;
unsigned int refs_mask;
unsigned int maxval;
unsigned int curval;
int dirty;
};
@ -309,7 +310,7 @@ int dev_onval(struct dev *, int, int);
int dev_nctl(struct dev *);
void dev_label(struct dev *, int);
struct ctl *dev_addctl(struct dev *, char *, int, int,
char *, int, char *, char *, int, int);
char *, int, char *, char *, int, int, int);
void dev_rmctl(struct dev *, int);
int dev_makeunit(struct dev *, char *);

View File

@ -77,7 +77,7 @@ dev_sioctl_ondesc(void *arg, struct sioctl_desc *desc, int val)
dev_addctl(d, group, desc->type, addr,
desc->node0.name, desc->node0.unit, desc->func,
desc->node1.name, desc->node1.unit, val);
desc->node1.name, desc->node1.unit, desc->maxval, val);
}
void

View File

@ -1543,6 +1543,7 @@ sock_buildmsg(struct sock *f)
desc->type = c->type;
strlcpy(desc->func, c->func, AMSG_CTL_NAMEMAX);
desc->addr = htons(c->addr);
desc->maxval = htons(c->maxval);
desc->curval = htons(c->curval);
size += sizeof(struct amsg_ctl_desc);
desc++;

View File

@ -44,7 +44,8 @@
char *dev_name;
struct pollfd pfds[16];
struct sioctl_hdl *hdl;
unsigned int output_addr, output_val = SIOCTL_VALMAX;
unsigned int output_addr;
int output_val, output_maxval;
int output_found = 0;
int verbose;
@ -70,6 +71,7 @@ dev_ondesc(void *unused, struct sioctl_desc *desc, int val)
strcmp(desc->func, "level") == 0) {
output_found = 1;
output_addr = desc->addr;
output_maxval = desc->maxval;
output_val = val;
if (verbose)
fprintf(stderr, "%s: output at addr %u, value = %u\n",
@ -139,8 +141,8 @@ dev_incrvol(int incr)
if (!dev_connect())
return;
vol = output_val + incr;
if (vol > SIOCTL_VALMAX)
vol = SIOCTL_VALMAX;
if (vol > output_maxval)
vol = output_maxval;
if (vol < 0)
vol = 0;
if (output_val != (unsigned int)vol) {