Download raw body.
sndiod: per-program (instead of per-client) level control
This diff is to adjust the volume of all instances of the same program
with a single control. Example, instead of:
firefox0.level
firefox1.level
firefox2.level
...
there will be single "firefox.level" control. There will be no way to
control individual tracks anymore, but that will not be a big loss
beacause there's currently no way to know in advance which sound
corresponds to which firefox instance.
There's a nice side effect:
Currently if a web browser has too many tabs/windows, it may consume
all the controls, preventing other programs from using sndiod. Now,
the number of connections that a single program can make can be
increased (the diff cranks it to 32) which fixes the problem in most
cases.
OK?
Index: dev.c
===================================================================
RCS file: /cvs/src/usr.bin/sndiod/dev.c,v
diff -u -p -r1.122 dev.c
--- dev.c 16 Jun 2025 06:19:29 -0000 1.122
+++ dev.c 16 Jun 2025 18:17:57 -0000
@@ -78,7 +78,6 @@ unsigned int dev_sndnum = 0;
struct ctlslot ctlslot_array[DEV_NCTLSLOT];
struct slot slot_array[DEV_NSLOT];
-unsigned int slot_serial; /* for slot allocation */
/*
* we support/need a single MTC clock source only
@@ -88,27 +87,6 @@ struct mtc mtc_array[1] = {
};
void
-slot_array_init(void)
-{
- unsigned int i;
-
- for (i = 0; i < DEV_NSLOT; i++) {
- slot_array[i].unit = i;
- slot_array[i].ops = NULL;
- slot_array[i].vol = MIDI_MAXCTL;
- slot_array[i].opt = NULL;
- slot_array[i].serial = slot_serial++;
- memset(slot_array[i].name, 0, SLOT_NAMEMAX);
- }
-}
-
-void
-slot_ctlname(struct slot *s, char *name, size_t size)
-{
- snprintf(name, size, "slot%zu", s - slot_array);
-}
-
-void
zomb_onmove(void *arg)
{
}
@@ -298,16 +276,18 @@ mtc_midi_full(struct mtc *mtc)
/*
* send a volume change MIDI message
+ *
+ * XXX: rename to opt_midi_vol() and move to opt.c
*/
void
-dev_midi_vol(struct dev *d, struct slot *s)
+dev_midi_vol(struct opt *o, struct app *a)
{
unsigned char msg[3];
- msg[0] = MIDI_CTL | (s - slot_array);
+ msg[0] = MIDI_CTL | (a - o->app_array);
msg[1] = MIDI_CTL_VOL;
- msg[2] = s->vol;
- dev_midi_send(d, msg, 3);
+ msg[2] = a->vol;
+ midi_send(o->midi, msg, sizeof(msg));
}
/*
@@ -352,9 +332,11 @@ dev_midi_master(struct dev *d)
/*
* send a sndiod-specific slot description MIDI message
+ *
+ * XXX: rename to opt_midi_appdesc() and move to opt.c
*/
void
-dev_midi_slotdesc(struct dev *d, struct slot *s)
+dev_midi_slotdesc(struct opt *o, struct app *a)
{
struct sysex x;
@@ -364,26 +346,26 @@ dev_midi_slotdesc(struct dev *d, struct
x.dev = SYSEX_DEV_ANY;
x.id0 = SYSEX_AUCAT;
x.id1 = SYSEX_AUCAT_SLOTDESC;
- if (s->opt != NULL && s->opt->dev == d)
- slot_ctlname(s, (char *)x.u.slotdesc.name, SYSEX_NAMELEN);
- x.u.slotdesc.chan = (s - slot_array);
+ strlcpy(x.u.slotdesc.name, a->name, SYSEX_NAMELEN);
+ x.u.slotdesc.chan = (a - o->app_array);
x.u.slotdesc.end = SYSEX_END;
- dev_midi_send(d, (unsigned char *)&x, SYSEX_SIZE(slotdesc));
+ midi_send(o->midi, (unsigned char *)&x, SYSEX_SIZE(slotdesc));
}
+/*
+ * XXX: rename to opt_midi_dump() and move to opt.c
+ */
void
-dev_midi_dump(struct dev *d)
+dev_midi_dump(struct opt *o)
{
struct sysex x;
- struct slot *s;
+ struct app *a;
int i;
- dev_midi_master(d);
- for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
- if (s->opt != NULL && s->opt->dev != d)
- continue;
- dev_midi_slotdesc(d, s);
- dev_midi_vol(d, s);
+ dev_midi_master(o->dev);
+ for (i = 0, a = o->app_array; i < OPT_NAPP; i++, a++) {
+ dev_midi_slotdesc(o, a);
+ dev_midi_vol(o, a);
}
x.start = SYSEX_START;
x.type = SYSEX_TYPE_EDU;
@@ -391,7 +373,7 @@ dev_midi_dump(struct dev *d)
x.id0 = SYSEX_AUCAT;
x.id1 = SYSEX_AUCAT_DUMPEND;
x.u.dumpend.end = SYSEX_END;
- dev_midi_send(d, (unsigned char *)&x, SYSEX_SIZE(dumpend));
+ midi_send(o->midi, (unsigned char *)&x, SYSEX_SIZE(dumpend));
}
int
@@ -1523,98 +1505,34 @@ struct slot *
slot_new(struct opt *opt, unsigned int id, char *who,
struct slotops *ops, void *arg, int mode)
{
- char *p;
- char name[SLOT_NAMEMAX];
- char ctl_name[CTL_NAMEMAX];
- unsigned int i, ser, bestser, bestidx;
- struct slot *unit[DEV_NSLOT];
+ struct app *a;
struct slot *s;
+ int i;
- /*
- * create a ``valid'' control name (lowcase, remove [^a-z], truncate)
- */
- for (i = 0, p = who; ; p++) {
- if (i == SLOT_NAMEMAX - 1 || *p == '\0') {
- name[i] = '\0';
- break;
- } else if (*p >= 'A' && *p <= 'Z') {
- name[i++] = *p + 'a' - 'A';
- } else if (*p >= 'a' && *p <= 'z')
- name[i++] = *p;
- }
- if (i == 0)
- strlcpy(name, "noname", SLOT_NAMEMAX);
-
- /*
- * build a unit-to-slot map for this name
- */
- for (i = 0; i < DEV_NSLOT; i++)
- unit[i] = NULL;
- for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
- if (strcmp(s->name, name) == 0)
- unit[s->unit] = s;
- }
-
- /*
- * find the free slot with the least unit number and same id
- */
- for (i = 0; i < DEV_NSLOT; i++) {
- s = unit[i];
- if (s != NULL && s->ops == NULL && s->id == id)
- goto found;
- }
-
- /*
- * find the free slot with the least unit number
- */
- for (i = 0; i < DEV_NSLOT; i++) {
- s = unit[i];
- if (s != NULL && s->ops == NULL) {
- s->id = id;
- goto found;
- }
- }
+ a = opt_mkapp(opt, who);
+ if (a == NULL)
+ return NULL;
/*
- * couldn't find a matching slot, pick oldest free slot
- * and set its name/unit
+ * find a free slot and assign it the smallest possible unit number
*/
- bestser = 0;
- bestidx = DEV_NSLOT;
- for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
- if (s->ops != NULL)
- continue;
- ser = slot_serial - s->serial;
- if (ser > bestser) {
- bestser = ser;
- bestidx = i;
+ i = 0;
+ s = slot_array;
+ while (1) {
+ if (i == DEV_NSLOT) {
+ logx(1, "%s: too many connections", a->name);
+ return NULL;
}
+ if (s->ops == NULL)
+ break;
+ i++;
+ s++;
}
- if (bestidx == DEV_NSLOT) {
- logx(1, "%s: out of sub-device slots", name);
- return NULL;
- }
-
- s = slot_array + bestidx;
- ctl_del(CTL_SLOT_LEVEL, s, NULL);
- s->vol = MIDI_MAXCTL;
- strlcpy(s->name, name, SLOT_NAMEMAX);
- s->serial = slot_serial++;
- for (i = 0; unit[i] != NULL; i++)
- ; /* nothing */
- s->unit = i;
- s->id = id;
- s->opt = opt;
- slot_ctlname(s, ctl_name, CTL_NAMEMAX);
- ctl_new(CTL_SLOT_LEVEL, s, NULL,
- CTL_NUM, "", "app", ctl_name, -1, "level",
- NULL, -1, 127, s->vol);
-
-found:
- /* open device, this may change opt's device */
if (!opt_ref(opt))
return NULL;
+
+ s->app = a;
s->opt = opt;
s->ops = ops;
s->arg = arg;
@@ -1629,10 +1547,8 @@ found:
s->appbufsz = s->opt->dev->bufsz;
s->round = s->opt->dev->round;
s->rate = s->opt->dev->rate;
- dev_midi_slotdesc(s->opt->dev, s);
- dev_midi_vol(s->opt->dev, s);
#ifdef DEBUG
- logx(3, "slot%zu: %s/%s%u", s - slot_array, s->opt->name, s->name, s->unit);
+ logx(3, "slot%zu: %s/%s", s - slot_array, s->opt->name, s->app->name);
#endif
return s;
}
@@ -1660,66 +1576,21 @@ slot_del(struct slot *s)
}
/*
- * change the slot play volume; called either by the slot or by MIDI
+ * change the slot play volume; called by the client
*/
void
slot_setvol(struct slot *s, unsigned int vol)
{
+ struct opt *o = s->opt;
+ struct app *a = s->app;
+
#ifdef DEBUG
logx(3, "slot%zu: setting volume %u", s - slot_array, vol);
#endif
- s->vol = vol;
- s->mix.vol = MIDI_TO_ADATA(s->vol);
-}
-
-/*
- * set device for this slot
- */
-void
-slot_setopt(struct slot *s, struct opt *o)
-{
- struct opt *t;
- struct dev *odev, *ndev;
- struct ctl *c;
-
- if (s->opt == NULL || s->opt == o)
- return;
-
- logx(2, "slot%zu: moving to opt %s", s - slot_array, o->name);
-
- odev = s->opt->dev;
- if (s->ops != NULL) {
- ndev = opt_ref(o);
- if (ndev == NULL)
- return;
-
- if (!dev_iscompat(odev, ndev)) {
- opt_unref(o);
- return;
- }
- }
-
- if (s->pstate == SLOT_RUN || s->pstate == SLOT_STOP)
- slot_detach(s);
-
- t = s->opt;
- s->opt = o;
-
- c = ctl_find(CTL_SLOT_LEVEL, s, NULL);
- ctl_update(c);
-
- if (o->dev != t->dev) {
- dev_midi_slotdesc(odev, s);
- dev_midi_slotdesc(ndev, s);
- dev_midi_vol(ndev, s);
- }
-
- if (s->pstate == SLOT_RUN || s->pstate == SLOT_STOP)
- slot_attach(s);
-
- if (s->ops != NULL) {
- opt_unref(t);
- return;
+ if (a->vol != vol) {
+ opt_appvol(o, a, vol);
+ dev_midi_vol(o, a);
+ ctl_onval(CTL_APP_LEVEL, o, a, vol);
}
}
@@ -1775,7 +1646,7 @@ slot_attach(struct slot *s)
s->next = d->slot_list;
d->slot_list = s;
if (s->mode & MODE_PLAY) {
- s->mix.vol = MIDI_TO_ADATA(s->vol);
+ s->mix.vol = MIDI_TO_ADATA(s->app->vol);
dev_mix_adjvol(d);
}
}
@@ -2073,8 +1944,8 @@ ctlslot_visible(struct ctlslot *s, struc
return (s->opt->dev == c->u.any.arg0);
case CTL_OPT_DEV:
return (s->opt == c->u.any.arg0);
- case CTL_SLOT_LEVEL:
- return (s->opt->dev == c->u.slot_level.slot->opt->dev);
+ case CTL_APP_LEVEL:
+ return (s->opt == c->u.app_level.opt);
default:
return 0;
}
@@ -2146,9 +2017,9 @@ ctl_scope_fmt(char *buf, size_t size, st
case CTL_DEV_MASTER:
return snprintf(buf, size, "dev_master:%s",
c->u.dev_master.dev->name);
- case CTL_SLOT_LEVEL:
- return snprintf(buf, size, "slot_level:%s%u",
- c->u.slot_level.slot->name, c->u.slot_level.slot->unit);
+ case CTL_APP_LEVEL:
+ return snprintf(buf, size, "app_level:%s/%s",
+ c->u.app_level.opt->name, c->u.app_level.app->name);
case CTL_OPT_DEV:
return snprintf(buf, size, "opt_dev:%s/%s",
c->u.opt_dev.opt->name, c->u.opt_dev.dev->name);
@@ -2208,10 +2079,9 @@ ctl_setval(struct ctl *c, int val)
c->val_mask = ~0U;
c->curval = val;
return 1;
- case CTL_SLOT_LEVEL:
- slot_setvol(c->u.slot_level.slot, val);
- // XXX change dev_midi_vol() into slot_midi_vol()
- dev_midi_vol(c->u.slot_level.slot->opt->dev, c->u.slot_level.slot);
+ case CTL_APP_LEVEL:
+ opt_appvol(c->u.app_level.opt, c->u.app_level.app, val);
+ dev_midi_vol(c->u.app_level.opt, c->u.app_level.app);
c->val_mask = ~0U;
c->curval = val;
return 1;
@@ -2272,6 +2142,7 @@ ctl_new(int scope, void *arg0, void *arg
c->u.hw.addr = *(unsigned int *)arg1;
break;
case CTL_OPT_DEV:
+ case CTL_APP_LEVEL:
c->u.any.arg1 = arg1;
break;
default:
@@ -2337,6 +2208,7 @@ ctl_match(struct ctl *c, int scope, void
return 0;
break;
case CTL_OPT_DEV:
+ case CTL_APP_LEVEL:
if (arg1 != NULL && c->u.any.arg1 != arg1)
return 0;
break;
Index: dev.h
===================================================================
RCS file: /cvs/src/usr.bin/sndiod/dev.h,v
diff -u -p -r1.47 dev.h
--- dev.h 20 Dec 2024 07:35:56 -0000 1.47
+++ dev.h 16 Jun 2025 18:17:58 -0000
@@ -26,7 +26,7 @@
/*
* preallocated audio clients
*/
-#define DEV_NSLOT 8
+#define DEV_NSLOT 32
/*
* preallocated control clients
@@ -101,12 +101,7 @@ struct slot {
#define SLOT_STOP 4 /* draining */
int pstate;
-#define SLOT_NAMEMAX 8
- char name[SLOT_NAMEMAX]; /* name matching [a-z]+ */
- unsigned int unit; /* instance of name */
- unsigned int serial; /* global unique number */
- unsigned int vol; /* current (midi) volume */
- unsigned int id; /* process id */
+ struct app *app;
};
/*
@@ -127,7 +122,7 @@ struct ctl {
#define CTL_HW 0
#define CTL_DEV_MASTER 1
#define CTL_OPT_DEV 2
-#define CTL_SLOT_LEVEL 3
+#define CTL_APP_LEVEL 3
unsigned int scope;
union {
struct {
@@ -142,12 +137,9 @@ struct ctl {
struct dev *dev;
} dev_master;
struct {
- struct slot *slot;
- } slot_level;
- struct {
- struct slot *slot;
struct opt *opt;
- } slot_opt;
+ struct app *app;
+ } app_level;
struct {
struct opt *opt;
struct dev *dev;
@@ -287,7 +279,6 @@ extern struct slot slot_array[DEV_NSLOT]
extern struct ctlslot ctlslot_array[DEV_NCTLSLOT];
extern struct mtc mtc_array[1];
-void slot_array_init(void);
size_t chans_fmt(char *, size_t, int, int, int, int, int);
int dev_open(struct dev *);
void dev_close(struct dev *);
@@ -316,10 +307,10 @@ void dev_cycle(struct dev *);
*/
void dev_master(struct dev *, unsigned int);
void dev_midi_send(struct dev *, void *, int);
-void dev_midi_vol(struct dev *, struct slot *);
+void dev_midi_vol(struct opt *, struct app *);
void dev_midi_master(struct dev *);
-void dev_midi_slotdesc(struct dev *, struct slot *);
-void dev_midi_dump(struct dev *);
+void dev_midi_slotdesc(struct opt *o, struct app *a);
+void dev_midi_dump(struct opt *o);
void mtc_midi_qfr(struct mtc *, int);
void mtc_midi_full(struct mtc *);
@@ -336,7 +327,6 @@ struct slot *slot_new(struct opt *, unsi
struct slotops *, void *, int);
void slot_del(struct slot *);
void slot_setvol(struct slot *, unsigned int);
-void slot_setopt(struct slot *, struct opt *);
void slot_start(struct slot *);
void slot_stop(struct slot *, int);
void slot_read(struct slot *);
Index: opt.c
===================================================================
RCS file: /cvs/src/usr.bin/sndiod/opt.c,v
diff -u -p -r1.13 opt.c
--- opt.c 20 Dec 2024 07:35:56 -0000 1.13
+++ opt.c 16 Jun 2025 18:17:58 -0000
@@ -36,6 +36,103 @@ struct midiops opt_midiops = {
opt_midi_exit
};
+struct app *
+opt_mkapp(struct opt *o, char *who)
+{
+ char *p;
+ char name[APP_NAMEMAX];
+ unsigned int i, ser, bestser, bestidx, inuse;
+ struct app *a;
+ struct slot *s;
+
+ /*
+ * create a valid control name (lowcase, remove [^a-z], truncate)
+ */
+ for (i = 0, p = who; ; p++) {
+ if (i == APP_NAMEMAX - 1 || *p == '\0') {
+ name[i] = '\0';
+ break;
+ } else if (*p >= 'A' && *p <= 'Z') {
+ name[i++] = *p + 'a' - 'A';
+ } else if (*p >= 'a' && *p <= 'z')
+ name[i++] = *p;
+ }
+ if (i == 0)
+ strlcpy(name, "noname", APP_NAMEMAX);
+
+ /*
+ * return the app with this name (if any)
+ */
+ for (i = 0, a = o->app_array; i < OPT_NAPP; i++, a++) {
+ if (strcmp(a->name, name) == 0)
+ return a;
+ }
+
+ /*
+ * build a bitmap of app structures currently in use
+ */
+ inuse = 0;
+ for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
+ if (s->app != NULL && s->ops != NULL)
+ inuse |= 1 << (s->app - o->app_array);
+ }
+
+ if (inuse == (1 << OPT_NAPP) - 1) {
+ logx(1, "%s: too many programs", name);
+ return NULL;
+ }
+
+ /*
+ * recycle the oldest free structure
+ */
+
+ o->app_serial++;
+ bestser = 0;
+ bestidx = OPT_NAPP;
+ for (i = 0, a = o->app_array; i < OPT_NAPP; i++, a++) {
+ if (inuse & (1 << i))
+ continue;
+ ser = o->app_serial - a->serial;
+ if (ser > bestser) {
+ bestser = ser;
+ bestidx = i;
+ }
+ }
+
+ a = o->app_array + bestidx;
+
+ ctl_del(CTL_APP_LEVEL, o, a);
+
+ strlcpy(a->name, name, sizeof(a->name));
+ a->serial = o->app_serial;
+ a->vol = MIDI_MAXCTL;
+ ctl_new(CTL_APP_LEVEL, o, a,
+ CTL_NUM, "", "app", a->name, -1, "level",
+ NULL, -1, 127, a->vol);
+ dev_midi_slotdesc(o, a);
+ dev_midi_vol(o, a);
+
+ return a;
+}
+
+void
+opt_appvol(struct opt *o, struct app *a, int vol)
+{
+ struct slot *s;
+ int i;
+
+ a->vol = vol;
+
+ for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
+ if (s->app != a || s->opt != o)
+ continue;
+ s->mix.vol = MIDI_TO_ADATA(vol);
+#ifdef DEBUG
+ logx(3, "%s/%s: setting volume %u", o->name, a->name, vol);
+#endif
+ }
+}
+
void
opt_midi_imsg(void *arg, unsigned char *msg, int len)
{
@@ -56,12 +153,10 @@ opt_midi_omsg(void *arg, unsigned char *
if ((msg[0] & MIDI_CMDMASK) == MIDI_CTL && msg[1] == MIDI_CTL_VOL) {
chan = msg[0] & MIDI_CHANMASK;
- if (chan >= DEV_NSLOT)
- return;
- if (slot_array[chan].opt != o)
+ if (chan >= OPT_NAPP)
return;
- slot_setvol(slot_array + chan, msg[2]);
- ctl_onval(CTL_SLOT_LEVEL, slot_array + chan, NULL, msg[2]);
+ opt_appvol(o, o->app_array + chan, msg[2]);
+ ctl_onval(CTL_APP_LEVEL, o, o->app_array + chan, msg[2]);
return;
}
x = (struct sysex *)msg;
@@ -137,7 +232,7 @@ opt_midi_omsg(void *arg, unsigned char *
return;
if (len != SYSEX_SIZE(dumpreq))
return;
- dev_midi_dump(o->dev);
+ dev_midi_dump(o);
break;
}
}
@@ -389,15 +484,6 @@ opt_setdev(struct opt *o, struct dev *nd
for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
if (s->opt != o)
continue;
-
- if (ndev != odev) {
- dev_midi_slotdesc(odev, s);
- dev_midi_slotdesc(ndev, s);
- dev_midi_vol(ndev, s);
- }
-
- c = ctl_find(CTL_SLOT_LEVEL, s, NULL);
- ctl_update(c);
if (s->pstate == SLOT_RUN || s->pstate == SLOT_STOP) {
slot_initconv(s);
Index: opt.h
===================================================================
RCS file: /cvs/src/usr.bin/sndiod/opt.h,v
diff -u -p -r1.8 opt.h
--- opt.h 22 Apr 2024 10:42:04 -0000 1.8
+++ opt.h 16 Jun 2025 18:17:58 -0000
@@ -18,15 +18,26 @@
#define OPT_H
#define OPT_NMAX 16
+#define OPT_NAPP 8
struct dev;
+struct app {
+#define APP_NAMEMAX 12
+ char name[APP_NAMEMAX]; /* name matching [a-z]+ */
+ unsigned int serial; /* global unique number */
+ int vol;
+};
+
struct opt {
struct opt *next;
struct dev *dev, *alt_first;
struct midi *midi;
struct mtc *mtc; /* if set, MMC-controlled MTC source */
+ struct app app_array[OPT_NAPP];
+ unsigned int app_serial;
+
int num;
#define OPT_NAMEMAX 11
char name[OPT_NAMEMAX + 1];
@@ -40,6 +51,8 @@ struct opt {
extern struct opt *opt_list;
+struct app *opt_mkapp(struct opt *o, char *who);
+void opt_appvol(struct opt *o, struct app *a, int vol);
struct opt *opt_new(struct dev *, char *, int, int, int, int,
int, int, int, unsigned int);
void opt_del(struct opt *);
Index: sndiod.8
===================================================================
RCS file: /cvs/src/usr.bin/sndiod/sndiod.8,v
diff -u -p -r1.17 sndiod.8
--- sndiod.8 3 May 2024 16:47:15 -0000 1.17
+++ sndiod.8 16 Jun 2025 18:17:58 -0000
@@ -440,12 +440,13 @@ exposes the audio device clock
and allows audio device properties to be controlled
through MIDI.
.Pp
-A MIDI channel is assigned to each stream, and the volume
+A MIDI channel is assigned to each program, and the volume
is changed using the standard volume controller (number 7).
Similarly, when the audio client changes its volume,
the same MIDI controller message is sent out; it can be used
for instance for monitoring or as feedback for motorized
faders.
+If there are multiple instances of the same program they will share the same setting.
.Pp
The master volume can be changed using the standard master volume
system exclusive message.
Index: sndiod.c
===================================================================
RCS file: /cvs/src/usr.bin/sndiod/sndiod.c,v
diff -u -p -r1.50 sndiod.c
--- sndiod.c 20 Dec 2024 07:35:56 -0000 1.50
+++ sndiod.c 16 Jun 2025 18:17:58 -0000
@@ -587,8 +587,6 @@ main(int argc, char **argv)
d = NULL;
p = NULL;
- slot_array_init();
-
while ((c = getopt(argc, argv,
"a:b:c:C:de:F:f:j:L:m:Q:q:r:s:t:U:v:w:x:z:")) != -1) {
switch (c) {
Index: sock.c
===================================================================
RCS file: /cvs/src/usr.bin/sndiod/sock.c,v
diff -u -p -r1.54 sock.c
--- sock.c 16 Jun 2025 06:18:18 -0000 1.54
+++ sock.c 16 Jun 2025 18:17:58 -0000
@@ -250,7 +250,7 @@ sock_slot_onvol(void *arg)
struct slot *s = f->slot;
#ifdef DEBUG
- logx(4, "slot%zu: onvol: vol -> %d", s - slot_array, s->vol);
+ logx(4, "slot%zu: onvol: vol -> %u", s - slot_array, s->app->vol);
#endif
if (s->pstate != SOCK_START)
return;
@@ -1005,8 +1005,6 @@ sock_execmsg(struct sock *f)
f->rstate = SOCK_RMSG;
f->lastvol = ctl; /* dont trigger feedback message */
slot_setvol(s, ctl);
- dev_midi_vol(s->opt->dev, s);
- ctl_onval(CTL_SLOT_LEVEL, s, NULL, ctl);
break;
case AMSG_CTLSUB_OLD:
case AMSG_CTLSUB:
@@ -1187,17 +1185,17 @@ sock_buildmsg(struct sock *f)
/*
* if volume changed build a SETVOL message
*/
- if (f->pstate >= SOCK_START && f->slot->vol != f->lastvol) {
+ if (f->pstate >= SOCK_START && f->slot->app->vol != f->lastvol) {
#ifdef DEBUG
logx(3, "sock %d: building SETVOL message, vol = %d", f->fd,
- f->slot->vol);
+ f->slot->app->vol);
#endif
AMSG_INIT(&f->wmsg);
f->wmsg.cmd = htonl(AMSG_SETVOL);
- f->wmsg.u.vol.ctl = htonl(f->slot->vol);
+ f->wmsg.u.vol.ctl = htonl(f->slot->app->vol);
f->wtodo = sizeof(struct amsg);
f->wstate = SOCK_WMSG;
- f->lastvol = f->slot->vol;
+ f->lastvol = f->slot->app->vol;
return 1;
}
sndiod: per-program (instead of per-client) level control