From e8007feb0080301130ddae20663c6c96013a7f6c Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 28 Aug 2015 08:57:47 +0200 Subject: [PATCH 001/117] move the mixer api to a dedicated "mixer" branch --- Makefile.in | 13 +- configure | 17 --- libsndio/Makefile.in | 16 --- libsndio/amsg.h | 37 ------ libsndio/sndio.h | 47 -------- sndiod/Makefile.in | 4 +- sndiod/defs.h | 3 - sndiod/dev.c | 277 +------------------------------------------ sndiod/dev.h | 62 +--------- sndiod/siofile.c | 3 - sndiod/sock.c | 185 +---------------------------- sndiod/sock.h | 5 - 12 files changed, 7 insertions(+), 662 deletions(-) diff --git a/Makefile.in b/Makefile.in index 1c724aa..479b616 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,42 +1,31 @@ -XVOLKEYS = @xvolkeys@ - all: cd libsndio && ${MAKE} cd sndiod && ${MAKE} - cd sndioctl && ${MAKE} cd aucat && ${MAKE} cd midicat && ${MAKE} - if [ ${XVOLKEYS} = yes ]; then cd xvolkeys && ${MAKE}; fi install: cd libsndio && ${MAKE} install cd sndiod && ${MAKE} install - cd sndioctl && ${MAKE} install cd aucat && ${MAKE} install cd midicat && ${MAKE} install - if [ ${XVOLKEYS} = yes ]; then cd xvolkeys && ${MAKE} install; fi uninstall: - cd xvolkeys && ${MAKE} uninstall cd midicat && ${MAKE} uninstall cd aucat && ${MAKE} uninstall - cd sndioctl && ${MAKE} uninstall cd sndiod && ${MAKE} uninstall cd libsndio && ${MAKE} uninstall clean: cd aucat && ${MAKE} clean cd midicat && ${MAKE} clean - cd sndioctl && ${MAKE} clean cd sndiod && ${MAKE} clean cd libsndio && ${MAKE} clean cd examples && ${MAKE} clean - cd xvolkeys && ${MAKE} clean distclean: clean rm -f \ Makefile aucat/Makefile midicat/Makefile sndiod/Makefile \ - libsndio/Makefile sndioctl/Makefile \ - xvolkeys/Makefile \ + libsndio/Makefile \ examples/Makefile \ contrib/init.d.sndiod diff --git a/configure b/configure index a77574d..d9ed438 100755 --- a/configure +++ b/configure @@ -18,8 +18,6 @@ Usage: configure [options] --disable-alsa disable alsa audio & midi backends --enable-sun enable sun audio backend [$sun] --disable-sun disable sun audio backend ---enable-sun-mixer enable sun audio mixer backend [$sun_mixer] ---disable-sun-mixer disable sun audio mixer backend --enable-rmidi enable character device midi backend [$rmidi] --disable-rmidi disable character device midi backend --enable-xvolkeys build xvolkeys utility (requires X) [$xvolkeys] @@ -34,7 +32,6 @@ prefix=/usr/local # where to install sndio so="libsndio.so.\${MAJ}.\${MIN}" # shared libs to build alsa=no # do we want alsa support ? sun=no # do we want sun support ? -sun_mixer=no # do we want sun mixer support ? rmidi=no # do we want support for raw char dev ? precision=16 # aucat/sndiod arithmetic precision user=_sndio # non-privileged user for sndio daemon @@ -107,12 +104,6 @@ for i; do --disable-sun) sun=no shift;; - --enable-sun-mixer) - sun_mixer=yes - shift;; - --disable-sun-mixer) - sun_mixer=no - shift;; --enable-rmidi) rmidi=yes shift;; @@ -169,13 +160,6 @@ if [ $sun = yes ]; then defs="$defs -DUSE_SUN" fi -# -# if using Sun mixer API, add corresponding parameters -# -if [ $sun_mixer = yes ]; then - defs="$defs -DUSE_SUN_MIXER" -fi - # # if using raw character devices for midi, add corresponding parameters # @@ -215,7 +199,6 @@ user..................... $user precision................ $precision alsa..................... $alsa sun...................... $sun -sun mixer................ $sun_mixer rmidi.................... $rmidi xvolkeys................. $xvolkeys diff --git a/libsndio/Makefile.in b/libsndio/Makefile.in index f9b3319..8ddf3fd 100644 --- a/libsndio/Makefile.in +++ b/libsndio/Makefile.in @@ -34,9 +34,6 @@ MAN3 = \ sio_start.3 sio_stop.3 sio_read.3 sio_write.3 sio_onmove.3 \ sio_nfds.3 sio_pollfd.3 sio_revents.3 sio_eof.3 \ sio_setvol.3 sio_onvol.3 sio_initpar.3 \ - siomix_open.3 \ - siomix_close.3 siomix_setctl.3 siomix_ondesc.3 siomix_onctl.3 \ - siomix_nfds.3 siomix_pollfd.3 siomix_revents.3 siomix_eof.3 \ mio_open.3 \ mio_close.3 mio_read.3 mio_write.3 mio_nfds.3 mio_pollfd.3 \ mio_revents.3 mio_eof.3 @@ -75,15 +72,6 @@ install: ln -sf sio_open.3 ${DESTDIR}${MAN3_DIR}/sio_setvol.3 ln -sf sio_open.3 ${DESTDIR}${MAN3_DIR}/sio_onvol.3 ln -sf sio_open.3 ${DESTDIR}${MAN3_DIR}/sio_initpar.3 - cp siomix_open.3 ${DESTDIR}${MAN3_DIR} - ln -sf siomix_open.3 ${DESTDIR}${MAN3_DIR}/siomix_close.3 - ln -sf siomix_open.3 ${DESTDIR}${MAN3_DIR}/siomix_setctl.3 - ln -sf siomix_open.3 ${DESTDIR}${MAN3_DIR}/siomix_ondesc.3 - ln -sf siomix_open.3 ${DESTDIR}${MAN3_DIR}/siomix_onctl.3 - ln -sf siomix_open.3 ${DESTDIR}${MAN3_DIR}/siomix_nfds.3 - ln -sf siomix_open.3 ${DESTDIR}${MAN3_DIR}/siomix_pollfd.3 - ln -sf siomix_open.3 ${DESTDIR}${MAN3_DIR}/siomix_revents.3 - ln -sf siomix_open.3 ${DESTDIR}${MAN3_DIR}/siomix_eof.3 cp mio_open.3 ${DESTDIR}${MAN3_DIR} ln -sf mio_open.3 ${DESTDIR}${MAN3_DIR}/mio_close.3 ln -sf mio_open.3 ${DESTDIR}${MAN3_DIR}/mio_read.3 @@ -112,7 +100,6 @@ clean: OBJS = debug.o aucat.o \ mio.o mio_rmidi.o mio_alsa.o mio_aucat.o \ sio.o sio_alsa.o sio_aucat.o sio_sun.o \ -siomix.o siomix_aucat.o siomix_sun.o \ issetugid.o strlcat.o strlcpy.o strtonum.o .c.o: @@ -153,6 +140,3 @@ sio_aucat.o: sio_aucat.c aucat.h amsg.h debug.h sio_priv.h sndio.h \ ../bsd-compat/bsd-compat.h sio_sun.o: sio_sun.c debug.h sio_priv.h sndio.h \ ../bsd-compat/bsd-compat.h -siomix.o: siomix.c debug.h siomix_priv.h -siomix_aucat.o: siomix_aucat.c debug.h aucat.h amsg.h siomix_priv.h -siomix_sun.o: siomix_sun.c debug.h amsg.h siomix_priv.h diff --git a/libsndio/amsg.h b/libsndio/amsg.h index 2505c54..0b3c2e9 100644 --- a/libsndio/amsg.h +++ b/libsndio/amsg.h @@ -26,13 +26,6 @@ #define AUCAT_PORT 11025 #define DEFAULT_OPT "default" -/* - * limits - */ -#define AMSG_MIX_NAMEMAX 16 /* max name length */ -#define AMSG_MIX_INTMAX 127 /* max channel number */ -#define AMSG_MIX_HALF 64 /* also bool threshold */ - /* * WARNING: since the protocol may be simultaneously used by static * binaries or by different versions of a shared library, we are not @@ -55,8 +48,6 @@ struct amsg { #define AMSG_HELLO 10 /* say hello, check versions and so ... */ #define AMSG_BYE 11 /* ask server to drop connection */ #define AMSG_AUTH 12 /* send authentication cookie */ -#define AMSG_MIXSUB 13 /* ondesc/onctl subscription */ -#define AMSG_MIXSET 14 /* set mixer control value */ uint32_t cmd; uint32_t __pad; union { @@ -101,37 +92,9 @@ struct amsg { #define AMSG_COOKIELEN 16 uint8_t cookie[AMSG_COOKIELEN]; } auth; - struct amsg_mixsub { - uint8_t desc, val; - } mixsub; - struct amsg_mixset { - uint16_t addr, val; - } mixset; } u; }; -/* - * subset of channels of a stream - */ -struct amsg_mix_chan { - char str[AMSG_MIX_NAMEMAX]; /* stream name */ - char opt[AMSG_MIX_NAMEMAX]; /* stream name */ -}; - -/* - * description of a control (index, value) pair - */ -struct amsg_mix_desc { - struct amsg_mix_chan chan0; /* affected channels */ - struct amsg_mix_chan chan1; /* dito for AMSG_MIX_{SEL,VEC,LIST} */ - char func[AMSG_MIX_NAMEMAX]; /* parameter group name */ - uint8_t type; /* see siomix_desc structure */ - uint8_t __pad[1]; - uint16_t addr; /* control address */ - uint16_t __pad2[1]; - uint16_t curval; -}; - /* * Initialize an amsg structure: fill all fields with 0xff, so the read * can test which fields were set. diff --git a/libsndio/sndio.h b/libsndio/sndio.h index 68e1d83..bd79202 100644 --- a/libsndio/sndio.h +++ b/libsndio/sndio.h @@ -24,21 +24,12 @@ */ #define SIO_DEVANY "default" #define MIO_PORTANY "default" -#define SIOMIX_DEVANY "default" - -/* - * limits - */ -#define SIOMIX_NAMEMAX 12 /* max name length */ -#define SIOMIX_INTMAX 127 /* max channel number */ -#define SIOMIX_HALF 64 /* also bool threshold */ /* * private ``handle'' structure */ struct sio_hdl; struct mio_hdl; -struct siomix_hdl; /* * parameters of a full-duplex stream @@ -93,30 +84,6 @@ struct sio_cap { #define SIO_XSTRINGS { "ignore", "sync", "error" } -/* - * subset of channels of a stream - */ -struct siomix_chan { - char str[SIOMIX_NAMEMAX]; /* stream name */ - char opt[SIOMIX_NAMEMAX]; /* optional (sub-)stream name */ -}; - -/* - * description of a control (index, value) pair - */ -struct siomix_desc { - unsigned int addr; /* control address */ -#define SIOMIX_NUM 2 /* integer in the 0..127 range */ -#define SIOMIX_SW 3 /* on/off switch (0 or 1) */ -#define SIOMIX_VEC 4 /* number, element of vector */ -#define SIOMIX_LIST 5 /* switch, element of a list */ -#define SIOMIX_LABEL 6 /* label attached to chan0 */ - unsigned int type; /* one of above */ - char func[SIOMIX_NAMEMAX]; /* function name or label */ - struct siomix_chan chan0; /* affected channels */ - struct siomix_chan chan1; /* dito for SIOMIX_{VEC,LIST} */ -}; - /* * mode bitmap */ @@ -124,8 +91,6 @@ struct siomix_desc { #define SIO_REC 2 #define MIO_OUT 4 #define MIO_IN 8 -#define SIOMIX_READ 0x100 -#define SIOMIX_WRITE 0x200 /* * default bytes per sample for the given bits per sample @@ -179,18 +144,6 @@ int mio_pollfd(struct mio_hdl *, struct pollfd *, int); int mio_revents(struct mio_hdl *, struct pollfd *); int mio_eof(struct mio_hdl *); -struct siomix_hdl *siomix_open(const char *, unsigned int, int); -void siomix_close(struct siomix_hdl *); -int siomix_ondesc(struct siomix_hdl *, - void (*)(void *, struct siomix_desc *, int), void *); -int siomix_onctl(struct siomix_hdl *, - void (*)(void *, unsigned int, unsigned int), void *); -int siomix_setctl(struct siomix_hdl *, unsigned int, unsigned int); -int siomix_nfds(struct siomix_hdl *); -int siomix_pollfd(struct siomix_hdl *, struct pollfd *, int); -int siomix_revents(struct siomix_hdl *, struct pollfd *); -int siomix_eof(struct siomix_hdl *); - #ifdef __cplusplus } #endif diff --git a/sndiod/Makefile.in b/sndiod/Makefile.in index 4eca20d..43b8172 100644 --- a/sndiod/Makefile.in +++ b/sndiod/Makefile.in @@ -44,7 +44,7 @@ clean: # ---------------------------------------------------------- dependencies --- OBJS = \ -abuf.o utils.o dev.o dev_siomix.o dsp.o file.o listen.o midi.o miofile.o \ +abuf.o utils.o dev.o dsp.o file.o listen.o midi.o miofile.o \ opt.o siofile.o sndiod.o sock.o sndiod: ${OBJS} @@ -56,8 +56,6 @@ sndiod: ${OBJS} abuf.o: abuf.c abuf.h utils.h dev.o: dev.c ../bsd-compat/bsd-compat.h abuf.h defs.h dev.h \ dsp.h siofile.h file.h midi.h miofile.h sysex.h utils.h -dev_siomix.o: dev_siomix.c abuf.h defs.h dev.h dsp.h siofile.h file.h \ - utils.h dsp.o: dsp.c dsp.h defs.h utils.h file.o: file.c file.h utils.h listen.o: listen.c listen.h file.h sock.h ../libsndio/amsg.h \ diff --git a/sndiod/defs.h b/sndiod/defs.h index e98c779..9f43aee 100644 --- a/sndiod/defs.h +++ b/sndiod/defs.h @@ -36,12 +36,9 @@ #define MODE_MIDIOUT 0x04 /* allowed to read midi */ #define MODE_MIDIIN 0x08 /* allowed to write midi */ #define MODE_MON 0x10 /* allowed to monitor */ -#define MODE_MIXREAD 0x100 /* allowed to read mixer settings */ -#define MODE_MIXWRITE 0x200 /* allowed to change mixer settings */ #define MODE_RECMASK (MODE_REC | MODE_MON) #define MODE_AUDIOMASK (MODE_PLAY | MODE_REC | MODE_MON) #define MODE_MIDIMASK (MODE_MIDIIN | MODE_MIDIOUT) -#define MODE_MIXMASK (MODE_MIXREAD | MODE_MIXWRITE) /* * underrun/overrun policies, must be the same as SIO_ constants diff --git a/sndiod/dev.c b/sndiod/dev.c index a6443cf..7b02fae 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -90,10 +90,6 @@ void slot_write(struct slot *); void slot_read(struct slot *); int slot_skip(struct slot *); -void ctl_chan_log(struct ctl_chan *); -void ctl_log(struct ctl *); -void dev_uniqname(struct dev *, char *, char *); - struct midiops dev_midiops = { dev_midi_imsg, dev_midi_omsg, @@ -427,8 +423,6 @@ dev_midi_omsg(void *arg, unsigned char *msg, int len) if (chan >= DEV_NSLOT) return; slot_setvol(d->slot + chan, msg[2]); - dev_onctl(d, - d->ctl_addr + CTLADDR_SLOT_LEVEL(chan), msg[2]); return; } x = (struct sysex *)msg; @@ -439,11 +433,8 @@ dev_midi_omsg(void *arg, unsigned char *msg, int len) switch (x->type) { case SYSEX_TYPE_RT: 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_onctl(d, d->ctl_addr + CTLADDR_MASTER, - x->u.master.coarse); - } return; } if (x->id0 != SYSEX_MMC) @@ -1017,17 +1008,10 @@ dev_new(char *path, struct aparams *par, d->slot[i].serial = d->serial++; d->slot[i].name[0] = '\0'; } - for (i = 0; i < DEV_NCTLSLOT; i++) { - d->ctlslot[i].dev = d; - d->ctlslot[i].mask = 0; - d->ctlslot[i].mode = 0; - d->ctlslot[i].inuse = 0; - } d->slot_list = NULL; d->master = MIDI_MAXCTL; d->mtc.origin = 0; d->tstate = MMC_STOP; - d->ctl_list = NULL; d->next = dev_list; dev_list = d; return d; @@ -1058,10 +1042,6 @@ dev_adjpar(struct dev *d, int mode, int dev_open(struct dev *d) { - char ctlname[CTL_NAMEMAX]; - struct ctl *c; - int i; - d->mode = d->reqmode; d->round = d->reqround; d->bufsz = d->reqbufsz; @@ -1136,29 +1116,6 @@ dev_open(struct dev *d) log_putu(d->round); log_puts(" frames\n"); } - - d->ctl_addr = 0; - for (c = d->ctl_list; c != NULL; c = c->next) { - if (d->ctl_addr < c->addr) - d->ctl_addr = c->addr; - } - d->ctl_addr++; - - for (i = 0; i < DEV_NSLOT; i++) { - dev_uniqname(d, "prog", ctlname); - c = dev_addctl(d, CTL_NUM, - d->ctl_addr + CTLADDR_SLOT_LEVEL(i), - ctlname, "", "level", NULL, NULL); - c->curval = d->slot[i].vol; - dev_addctl(d, CTL_LABEL, - d->ctl_addr + CTLADDR_SLOT_LABEL(i), - ctlname, "", "name", d->slot[i].name, ""); - } - dev_uniqname(d, "sndiod", ctlname); - c = dev_addctl(d, CTL_NUM, - d->ctl_addr + CTLADDR_MASTER, - ctlname, "", "level", NULL, NULL); - c->curval = d->master; return 1; } @@ -1171,7 +1128,6 @@ dev_close(struct dev *d) { int i; struct slot *s; - struct ctl *c; #ifdef DEBUG if (log_level >= 3) { @@ -1179,10 +1135,6 @@ dev_close(struct dev *d) log_puts(": closing\n"); } #endif - while ((c = d->ctl_list) != NULL) { - d->ctl_list = c->next; - xfree(c); - } d->pstate = DEV_CFG; for (s = d->slot, i = DEV_NSLOT; i > 0; i--, s++) { if (s->ops) @@ -1560,7 +1512,6 @@ slot_new(struct dev *d, char *who, struct slotops *ops, void *arg, int mode) found: if (!dev_ref(d)) return NULL; - dev_label(d, s - d->slot); s->dev = d; s->ops = ops; s->arg = arg; @@ -1989,229 +1940,3 @@ slot_read(struct slot *s) { slot_skip_update(s); } - -/* - * allocate at control slot - */ -struct ctlslot * -ctlslot_new(struct dev *d) -{ - struct ctlslot *s; - int i; - - i = 0; - for (;;) { - if (i == DEV_NCTLSLOT) - return NULL; - s = d->ctlslot + i; - if (!s->inuse) - break; - i++; - } - s->dev = d; - s->mask = 1 << i; - if (!dev_ref(d)) - return NULL; - s->inuse = 1; - return s; -} - -/* - * free control slot - */ -void -ctlslot_del(struct ctlslot *s) -{ - s->inuse = 0; - dev_unref(s->dev); -} - -void -ctl_chan_log(struct ctl_chan *c) -{ - log_puts(c->str); - if (strlen(c->opt) > 0) { - log_puts("["); - log_puts(c->opt); - log_puts("]"); - } -} - -void -ctl_log(struct ctl *c) -{ - ctl_chan_log(&c->chan0); - log_puts("."); - log_puts(c->func); - log_puts("="); - switch (c->type) { - case CTL_NUM: - case CTL_SW: - log_putu(c->curval); - break; - case CTL_VEC: - case CTL_LIST: - ctl_chan_log(&c->chan1); - log_puts(":"); - log_putu(c->curval); - break; - case CTL_LABEL: - ctl_chan_log(&c->chan1); - } - log_puts(" at "); - log_putu(c->addr); -} - -void -dev_uniqname(struct dev *d, char *templ, char *name) -{ - int i; - struct ctl *c; - - i = 0; - for (;;) { - snprintf(name, CTL_NAMEMAX, "%s%u", templ, i); - c = d->ctl_list; - for (;;) { - if (c == NULL) - return; - if (strcmp(name, c->chan0.str) == 0 || - strcmp(name, c->chan1.str) == 0) { - i++; - break; - } - c = c->next; - } - } -} - -/* - * add a ctl - */ -struct ctl * -dev_addctl(struct dev *d, int type, int addr, - char *str0, char *opt0, char *func, char *str1, char *opt1) -{ - struct ctl *c; - - c = xmalloc(sizeof(struct ctl)); - c->type = type; - strlcpy(c->func, func, CTL_NAMEMAX); - strlcpy(c->chan0.str, str0, CTL_NAMEMAX); - strlcpy(c->chan0.opt, opt0, CTL_NAMEMAX); - if (c->type == CTL_LABEL || - c->type == CTL_VEC || - c->type == CTL_LIST) { - strlcpy(c->chan1.str, str1, CTL_NAMEMAX); - strlcpy(c->chan1.opt, opt1, CTL_NAMEMAX); - } else - memset(&c->chan1, 0, sizeof(struct ctl_chan)); - c->addr = addr; - c->val_mask = 0; - c->desc_mask = 0; - c->next = d->ctl_list; - d->ctl_list = c; - c->curval = 0; - c->dirty = 0; -#ifdef DEBUG - if (log_level >= 3) { - dev_log(d); - log_puts(": adding "); - ctl_log(c); - log_puts("\n"); - } -#endif - return c; -} - -int -dev_setctl(struct dev *d, int addr, int val, unsigned int mask) -{ - struct ctl *c; - int num; - - if (val < 0 && val >= MIDI_MAXCTL) - return 0; - c = d->ctl_list; - for (;;) { - if (c == NULL) - return 0; - if (c->addr == addr) - break; - c = c->next; - } - if (addr < d->ctl_addr) { - if (log_level >= 3) { - ctl_log(c); - log_puts(": marked as dirty\n"); - } - c->dirty = 1; - dev_ref(d); - } else { - addr -= d->ctl_addr; - if (addr >= CTLADDR_SLOT_LEVEL(0) && - addr <= CTLADDR_SLOT_LEVEL(DEV_NSLOT)) { - num = addr - CTLADDR_SLOT_LEVEL(0); - slot_setvol(d->slot + num, val); - dev_midi_vol(d, d->slot + num); - } else if (addr == CTLADDR_MASTER) { - dev_master(d, val); - dev_midi_master(d); - } else - return 0; - } - c->curval = val; - c->val_mask = ~mask; - return 1; -} - -int -dev_onctl(struct dev *d, int addr, int val) -{ - struct ctl *c; - - c = d->ctl_list; - for (;;) { - if (c == NULL) - return 0; - if (c->addr == addr) - break; - c = c->next; - } - c->curval = val; - c->val_mask = ~0U; - return 1; -} - -void -dev_label(struct dev *d, int i) -{ - struct ctl *c; - int addr; - - addr = d->ctl_addr + CTLADDR_SLOT_LABEL(i); - c = d->ctl_list; - for (;;) { - if (c == NULL) - return; - if (c->addr == addr) - break; - c = c->next; - } - if (strcmp(c->chan1.str, d->slot[i].name) == 0) - return; - strlcpy(c->chan1.str, d->slot[i].name, CTL_NAMEMAX); - c->desc_mask = ~0; -} - -int -dev_nctl(struct dev *d) -{ - struct ctl *c; - int n; - - n = 0; - for (c = d->ctl_list; c != NULL; c = c->next) - n++; - return n; -} diff --git a/sndiod/dev.h b/sndiod/dev.h index 3c14976..5247153 100644 --- a/sndiod/dev.h +++ b/sndiod/dev.h @@ -20,11 +20,6 @@ #include "abuf.h" #include "dsp.h" #include "siofile.h" -#include "dev_siomix.h" - -#define CTLADDR_SLOT_LEVEL(n) (n) -#define CTLADDR_SLOT_LABEL(n) (DEV_NSLOT + n) -#define CTLADDR_MASTER (DEV_NSLOT + DEV_NSLOT) /* * audio stream state structure @@ -101,39 +96,7 @@ struct slot { }; /* - * subset of channels of a stream - */ - -struct ctl { - struct ctl *next; -#define CTL_NUM 2 /* number (aka integer value) */ -#define CTL_SW 3 /* on/off switch, only bit 7 counts */ -#define CTL_VEC 4 /* number, element of vector */ -#define CTL_LIST 5 /* switch, element of a list */ -#define CTL_LABEL 6 /* attach string to stream */ - unsigned int type; /* one of above */ - unsigned int addr; /* control address */ -#define CTL_NAMEMAX 16 /* max name lenght */ - char func[CTL_NAMEMAX]; /* parameter group name */ - struct ctl_chan { - char str[CTL_NAMEMAX]; /* stream name */ - char opt[CTL_NAMEMAX]; - } chan0, chan1; /* affected channels */ - unsigned int val_mask; - unsigned int desc_mask; - unsigned int curval; - int dirty; -}; - -struct ctlslot { - struct dev *dev; - unsigned int mask; - unsigned int mode; - int inuse; -}; - -/* - * audio device with plenty of slots and knobs + * audio device with plenty of slots */ struct dev { struct dev *next; @@ -144,7 +107,6 @@ struct dev { * audio device (while opened) */ struct dev_sio sio; - struct dev_siomix siomix; struct aparams par; /* encoding */ int pchan, rchan; /* play & rec channels */ adata_t *rbuf; /* rec buffer */ @@ -224,15 +186,6 @@ struct dev { #define MMC_RUN 3 /* started */ unsigned int tstate; /* one of above */ unsigned int master; /* master volume controller */ - - /* - * control - */ - - unsigned int ctl_addr; /* offset of own ctls */ - struct ctl *ctl_list; -#define DEV_NCTLSLOT 8 - struct ctlslot ctlslot[DEV_NCTLSLOT]; }; extern struct dev *dev_list; @@ -278,17 +231,4 @@ void slot_stop(struct slot *); void slot_read(struct slot *); void slot_write(struct slot *); -/* - * control related functions - */ -void ctl_log(struct ctl *); -struct ctlslot *ctlslot_new(struct dev *); -void ctlslot_del(struct ctlslot *); -int dev_setctl(struct dev *, int, int, unsigned int); -int dev_onctl(struct dev *, int, int); -int dev_nctl(struct dev *); -void dev_label(struct dev *, int); -struct ctl *dev_addctl(struct dev *, int, int, - char *, char *, char *, char *, char *); - #endif /* !defined(DEV_H) */ diff --git a/sndiod/siofile.c b/sndiod/siofile.c index 5321361..3ddf9ba 100644 --- a/sndiod/siofile.c +++ b/sndiod/siofile.c @@ -26,7 +26,6 @@ #include "abuf.h" #include "defs.h" #include "dev.h" -#include "dev_siomix.h" #include "dsp.h" #include "file.h" #include "siofile.h" @@ -213,7 +212,6 @@ dev_sio_open(struct dev *d) d->mode &= ~MODE_REC; sio_onmove(d->sio.hdl, dev_sio_onmove, d); d->sio.file = file_new(&dev_sio_ops, d, d->path, sio_nfds(d->sio.hdl)); - dev_siomix_open(d); timo_set(&d->sio.watchdog, dev_sio_timeout, d); return 1; bad_close: @@ -231,7 +229,6 @@ dev_sio_close(struct dev *d) } #endif timo_del(&d->sio.watchdog); - dev_siomix_close(d); file_del(d->sio.file); sio_close(d->sio.hdl); } diff --git a/sndiod/sock.c b/sndiod/sock.c index d57b651..f523342 100644 --- a/sndiod/sock.c +++ b/sndiod/sock.c @@ -104,10 +104,7 @@ sock_log(struct sock *f) slot_log(f->slot); else if (f->midi) midi_log(f->midi); - else if (f->ctlslot) { - log_puts("ctlslot"); - log_putu(f->ctlslot - f->ctlslot->dev->ctlslot); - } else + else log_puts("sock"); #ifdef DEBUG if (log_level >= 3) { @@ -154,11 +151,6 @@ sock_close(struct sock *f) port_unref(f->port); f->port = NULL; } - if (f->ctlslot) { - ctlslot_del(f->ctlslot); - f->ctlslot = NULL; - xfree(f->ctldesc); - } file_del(f->file); close(f->fd); xfree(f); @@ -286,7 +278,6 @@ sock_new(int fd) f->slot = NULL; f->port = NULL; f->midi = NULL; - f->ctlslot = NULL; f->tickpending = 0; f->fillpending = 0; f->stoppending = 0; @@ -553,11 +544,6 @@ sock_wdata(struct sock *f) data = abuf_rgetblk(&f->slot->sub.buf, &count); else if (f->midi) data = abuf_rgetblk(&f->midi->obuf, &count); - else { - data = (unsigned char *)f->ctldesc + - (f->wsize - f->wtodo); - count = f->wtodo; - } if (count > f->wtodo) count = f->wtodo; n = sock_fdwrite(f, data, count); @@ -815,9 +801,6 @@ sock_hello(struct sock *f) case MODE_REC: case MODE_PLAY: case MODE_PLAY | MODE_REC: - case MODE_MIXREAD: - case MODE_MIXWRITE: - case MODE_MIXREAD | MODE_MIXWRITE: break; default: #ifdef DEBUG @@ -855,30 +838,6 @@ sock_hello(struct sock *f) return 0; return 1; } - if (mode & MODE_MIXMASK) { - d = dev_bynum(p->devnum); - if (d == NULL) { - if (log_level >= 2) { - sock_log(f); - log_puts(": "); - log_putu(p->devnum); - log_puts(": no such device\n"); - } - return 0; - } - f->ctlslot = ctlslot_new(d); - if (f->ctlslot == NULL) { - if (log_level >= 2) { - sock_log(f); - log_puts(": couldn't get slot\n"); - } - return 0; - } - f->ctldesc = xmalloc(dev_nctl(f->ctlslot->dev) * - sizeof(struct amsg_mix_desc)); - f->ctlops = 0; - return 1; - } f->opt = opt_byname(p->opt, p->devnum); if (f->opt == NULL) return 0; @@ -936,7 +895,6 @@ sock_hello(struct sock *f) int sock_execmsg(struct sock *f) { - struct ctl *c; struct slot *s = f->slot; struct amsg *m = &f->rmsg; unsigned char *data; @@ -1236,83 +1194,8 @@ sock_execmsg(struct sock *f) f->rtodo = sizeof(struct amsg); f->rstate = SOCK_RMSG; f->lastvol = ctl; /* dont trigger feedback message */ - slot_setvol(f->slot, ctl); + slot_setvol(s, ctl); dev_midi_vol(s->dev, s); - dev_onctl(s->dev, s->dev->ctl_addr + - CTLADDR_SLOT_LEVEL(f->slot - s->dev->slot), ctl); - break; - case AMSG_MIXSUB: -#ifdef DEBUG - if (log_level >= 3) { - sock_log(f); - log_puts(": MIXSUB message, desc = "); - log_putx(m->u.mixsub.desc); - log_puts(", val = "); - log_putx(m->u.mixsub.val); - log_puts("\n"); - } -#endif - if (f->pstate != SOCK_INIT || f->ctlslot == NULL) { -#ifdef DEBUG - if (log_level >= 1) { - sock_log(f); - log_puts(": MIXSUB, wrong state\n"); - } -#endif - sock_close(f); - return 0; - } - if (m->u.mixsub.desc) { - if (!(f->ctlops & SOCK_CTLDESC)) { - ctl = f->ctlslot->mask; - c = f->ctlslot->dev->ctl_list; - while (c != NULL) { - c->desc_mask |= ctl; - c = c->next; - } - } - f->ctlops |= SOCK_CTLDESC; - } else - f->ctlops &= ~SOCK_CTLDESC; - if (m->u.mixsub.val) { - f->ctlops |= SOCK_CTLVAL; - } else - f->ctlops &= ~SOCK_CTLVAL; - f->rstate = SOCK_RMSG; - f->rtodo = sizeof(struct amsg); - break; - case AMSG_MIXSET: -#ifdef DEBUG - if (log_level >= 3) { - sock_log(f); - log_puts(": MIXSET message\n"); - } -#endif - if (f->pstate < SOCK_INIT || f->ctlslot == NULL) { -#ifdef DEBUG - if (log_level >= 1) { - sock_log(f); - log_puts(": MIXSET, wrong state\n"); - } -#endif - sock_close(f); - return 0; - } - if (!dev_setctl(f->ctlslot->dev, - ntohs(m->u.mixset.addr), - ntohs(m->u.mixset.val), - f->ctlslot->mask)) { -#ifdef DEBUG - if (log_level >= 1) { - sock_log(f); - log_puts(": MIXSET, wrong addr/val\n"); - } -#endif - sock_close(f); - return 0; - } - f->rtodo = sizeof(struct amsg); - f->rstate = SOCK_RMSG; break; case AMSG_AUTH: #ifdef DEBUG @@ -1401,9 +1284,7 @@ sock_execmsg(struct sock *f) int sock_buildmsg(struct sock *f) { - unsigned int size, mask; - struct amsg_mix_desc *desc; - struct ctl *c; + unsigned int size; /* * If pos changed (or initial tick), build a MOVE message. @@ -1542,66 +1423,6 @@ sock_buildmsg(struct sock *f) f->wstate = SOCK_WMSG; return 1; } - - if (f->ctlslot && (f->ctlops & SOCK_CTLDESC)) { - desc = f->ctldesc; - mask = f->ctlslot->mask; - for (c = f->ctlslot->dev->ctl_list; c != NULL; c = c->next) { - if ((c->desc_mask & mask) == 0) - continue; - c->desc_mask &= ~mask; - c->val_mask &= ~mask; - strlcpy(desc->chan0.str, c->chan0.str, - AMSG_MIX_NAMEMAX); - strlcpy(desc->chan0.opt, c->chan0.opt, - AMSG_MIX_NAMEMAX); - strlcpy(desc->chan1.str, c->chan1.str, - AMSG_MIX_NAMEMAX); - strlcpy(desc->chan1.opt, c->chan1.opt, - AMSG_MIX_NAMEMAX); - desc->type = c->type; - strlcpy(desc->func, c->func, AMSG_MIX_NAMEMAX); - desc->addr = htons(c->addr); - desc->curval = htons(c->curval); - desc++; - } - if (desc != f->ctldesc) { - size = (char *)desc - (char *)f->ctldesc; - AMSG_INIT(&f->wmsg); - f->wmsg.cmd = htonl(AMSG_DATA); - f->wmsg.u.data.size = htonl(size); - f->wtodo = sizeof(struct amsg); - f->wstate = SOCK_WMSG; -#ifdef DEBUG - if (log_level >= 3) { - sock_log(f); - log_puts(": building mixer DATA message\n"); - } -#endif - return 1; - } - } - if (f->ctlslot && (f->ctlops & SOCK_CTLVAL)) { - mask = f->ctlslot->mask; - for (c = f->ctlslot->dev->ctl_list; c != NULL; c = c->next) { - if ((c->val_mask & mask) == 0) - continue; - c->val_mask &= ~mask; - AMSG_INIT(&f->wmsg); - f->wmsg.cmd = htonl(AMSG_MIXSET); - f->wmsg.u.mixset.addr = htons(c->addr); - f->wmsg.u.mixset.val = htons(c->curval); - f->wtodo = sizeof(struct amsg); - f->wstate = SOCK_WMSG; -#ifdef DEBUG - if (log_level >= 3) { - sock_log(f); - log_puts(": building mixer MIXSET message\n"); - } -#endif - return 1; - } - } #ifdef DEBUG if (log_level >= 4) { sock_log(f); diff --git a/sndiod/sock.h b/sndiod/sock.h index 669b88c..dbf27f3 100644 --- a/sndiod/sock.h +++ b/sndiod/sock.h @@ -60,11 +60,6 @@ struct sock { struct slot *slot; /* audio device slot number */ struct midi *midi; /* midi endpoint */ struct port *port; /* midi port */ - struct ctlslot *ctlslot; - struct amsg_mix_desc *ctldesc; -#define SOCK_CTLDESC 1 /* dump desc and send changes */ -#define SOCK_CTLVAL 2 /* send value changes */ - unsigned int ctlops; }; struct sock *sock_new(int fd); From 1e958d6853cce034de62628e941fc8852b906b27 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 28 Aug 2015 08:59:59 +0200 Subject: [PATCH 002/117] move the mixer api to a dedicated "mixer" branch --- sndioctl/Makefile.in | 53 --- sndioctl/sndioctl.1 | 156 -------- sndioctl/sndioctl.c | 926 ------------------------------------------- xvolkeys/Makefile.in | 52 --- xvolkeys/xvolkeys.1 | 54 --- xvolkeys/xvolkeys.c | 319 --------------- 6 files changed, 1560 deletions(-) delete mode 100644 sndioctl/Makefile.in delete mode 100644 sndioctl/sndioctl.1 delete mode 100644 sndioctl/sndioctl.c delete mode 100644 xvolkeys/Makefile.in delete mode 100644 xvolkeys/xvolkeys.1 delete mode 100644 xvolkeys/xvolkeys.c diff --git a/sndioctl/Makefile.in b/sndioctl/Makefile.in deleted file mode 100644 index 463cf2b..0000000 --- a/sndioctl/Makefile.in +++ /dev/null @@ -1,53 +0,0 @@ -# extra includes paths (-I options) -INCLUDE = -I../libsndio -I../bsd-compat - -# extra libraries paths (-L options) -LIB = -L../libsndio - -# extra defines (-D options) -DEFS = -DDEBUG @defs@ - -# extra libraries (-l options) -LDADD = -lsndio @ldadd@ - -# variables defined on configure script command line (if any) -@vars@ - -# -# binaries, documentation, man pages and examples will be installed in -# ${BIN_DIR}, ${MAN1_DIR} -# -BIN_DIR = @bindir@ -MAN1_DIR = @mandir@/man1 - -# -# programs to build -# -PROG = sndioctl -MAN1 = sndioctl.1 - -all: ${PROG} ${MAN1} - -install: - mkdir -p ${DESTDIR}${BIN_DIR} ${DESTDIR}${MAN1_DIR} - cp sndioctl ${DESTDIR}${BIN_DIR} - cp sndioctl.1 ${DESTDIR}${MAN1_DIR} - -uninstall: - cd ${DESTDIR}${BIN_DIR} && rm -f ${PROG} - cd ${DESTDIR}${MAN1_DIR} && rm -f ${MAN1} - -clean: - rm -f -- *.o sndioctl - -# ---------------------------------------------------------- dependencies --- - -OBJS = sndioctl.o - -sndioctl: ${OBJS} - ${CC} ${LDFLAGS} ${LIB} -o sndioctl ${OBJS} ${LDADD} - -.c.o: - ${CC} ${CFLAGS} ${INCLUDE} ${DEFS} -c $< - -sndioctl.o: sndioctl.c diff --git a/sndioctl/sndioctl.1 b/sndioctl/sndioctl.1 deleted file mode 100644 index a189bb1..0000000 --- a/sndioctl/sndioctl.1 +++ /dev/null @@ -1,156 +0,0 @@ -.\" $OpenBSD$ -.\" -.\" Copyright (c) 2007 Alexandre Ratchov -.\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.Dd $Mdocdate: April 8 2011 $ -.Dt SNDIOCTL 1 -.Os -.Sh NAME -.Nm sndioctl -.Nd control audio mixer parameters -.Sh SYNOPSIS -.Nm -.Bk -words -.Op Fl iv -.Op Fl f Ar device -.Op Ar command ... -.Ek -.Nm -.Bk -words -.Fl d -.Ek -.Sh DESCRIPTION -The -.Nm -utility can display or change mixer parameters of -.Xr sndio 7 -audio devices. -The options are as follows: -.Bl -tag -width Ds -.It Fl d -Dump the raw list of available parameters and exit. -Useful to debug device drivers or programs using the -.Xr siomix_open 3 -interface. -.It Fl f Ar device -Use this -.Xr sndio 7 -mixer device. -.It Fl m -Monitor and display mixer changes. -.It Fl n -Don't hide program names associated to audio streams (by -default they are displayed as comments). -.It Fl i -Display characteristics of requested parameters -instead of their values. -.It Fl v -Enable verbose mode, a.k.a. multi-channel mode. -By default parameters affecting different channels -of the same stream are disguised as a single mono -parameter to hide details that are not essential. -.El -.Pp -If no commands are specified all valid parameters are displayed on -.Em stdout . -Unless -.Fl d -or -.Fl i -are used, displayed parameters are valid commands. -The set of available controls depends on the mixer device. -.Pp -Commands use the following two formats to display and set -parameters respectively: -.Pp -.Dl . -.Dl .= -.Pp -On the left-hand side, the affected substream is specified -by the stream name followed by an optional -channel range. -Examples of left-hand side terms: -.Pp -.Dl spkr.level -.Dl spkr[2-5].level -.Dl spkr[6].level -.Pp -There are three parameter types: numbers, selectors and vectors. -.Pp -Numbers are specified in decimal and follow the same semantics -as MIDI controllers. -Values are in the 0..127 range and 64 is the neutral state (if applicable). -Two-state controls (switches) take any value in the 0..63 range or -in the 64..127 range typically to the -.Em off -and -.Em on -states respectively. -.Pp -If a decimal is prefixed by the plus (minus) sign then -the given value is added to (subtracted from) the -current value of the control. -If -.Qq \&! -is used instead of a number, then the switch is toggled. -Examples: -.Pp -.Dl spkr.level=85 -.Dl spkr[4-5].level=+10 -.Dl spkr.mute=0 -.Dl spkr.mute=! -.Pp -.Pp Selectors -Selector values are substreams; they are specified -as the stream name followed by an optional channel -range. -If no channel range is specified, the same -range as the stream specified on the left-hand side is used. -For instance the following are equivalent: -.Pp -.Dl record[1].source=mic -.Dl record[1].source=mic[1] -.Pp -.Pp Vectors -Vectors are arrays of numbers. -Values are specified as comma-separated components. -Each component is a substream, followed by -a colon, followed by a number. -If the colon and the number are omitted, then 127 is -assumed. -If a component is missing, then 0 is assumed. -Example: -.Pp -.Dl monitor.mix=play:120,linein:85 -.Dl record.source=mic,linein -.Pp -Numbers are specified as discussed above. -Note that a vector of switches is equivalent to -a list. -.Sh SEE ALSO -.Xr siomix_open 3 -.Sh EXAMPLES -The following will set all -.Ar level -parameters that control the -.Ar spkr -stream to zero. -.Pp -.Dl $ sndioctl spkr.level=0 -.Pp -The following commands are equivalent: -.Pp -.Dl $ sndioctl record[0].source=mic[0] record[1].source=mic[1] -.Dl $ sndioctl record.source=mic diff --git a/sndioctl/sndioctl.c b/sndioctl/sndioctl.c deleted file mode 100644 index 4961b7c..0000000 --- a/sndioctl/sndioctl.c +++ /dev/null @@ -1,926 +0,0 @@ -/* $OpenBSD$ */ -/* - * Copyright (c) 2007-2011 Alexandre Ratchov - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include - -#define IS_IDENT(c) (((c) >= 'a' && (c) <= 'z') || \ - ((c) >= 'A' && (c) <= 'Z') || \ - ((c) >= '0' && (c) <= '9') || \ - ((c) == '_')) - -struct info { - struct info *next; - struct siomix_desc desc; - unsigned ctladdr; -#define MODE_IGNORE 0 /* ignore this value */ -#define MODE_PRINT 1 /* print-only, don't change value */ -#define MODE_SET 2 /* set to newval value */ -#define MODE_ADD 3 /* increase current value by newval */ -#define MODE_SUB 4 /* decrease current value by newval */ -#define MODE_TOGGLE 5 /* toggle current value */ - unsigned mode; - int curval, newval; -}; - -int cmpdesc(struct siomix_desc *, struct siomix_desc *); -int isdiag(struct info *); -struct info *selpos(struct info *); -struct info *vecent(struct info *, char *, char *); -struct info *nextgrp(struct info *); -struct info *nextpar(struct info *); -struct info *firstent(struct info *, char *); -struct info *nextent(struct info *, int); -int matchpar(struct info *, char *, char *); -int matchent(struct info *, char *, char *); -int ismono(struct info *); -void print_chan(struct siomix_chan *, int); -void print_desc(struct info *, int); -void print_val(struct info *, int); -void print_par(struct info *, int); -int parse_name(char **, char *); -int parse_dec(char **, unsigned *); -int parse_chan(char **, char *, char *); -int parse_modeval(char **, int *, unsigned *); -void dump(void); -int cmd(char *); -void commit(void); -void list(void); -void ondesc(void *, struct siomix_desc *, int); -void onctl(void *, unsigned, unsigned); - -struct siomix_hdl *hdl; -struct info *infolist; -int n_flag = 0, i_flag = 0, v_flag = 0, m_flag = 0; - -/* - * compare two siomix_desc structures, used to sort infolist - */ -int -cmpdesc(struct siomix_desc *d1, struct siomix_desc *d2) -{ - int res; - - res = strcmp(d1->chan0.str, d2->chan0.str); - if (res != 0) - return res; - res = d1->type - d2->type; - if (res != 0) - return res; - res = strcmp(d1->func, d2->func); - if (res != 0) - return res; - res = strcmp(d1->chan0.opt, d2->chan0.opt); - if (d1->type == SIOMIX_VEC || - d1->type == SIOMIX_LIST) { - if (res != 0) - return res; - res = strcmp(d1->chan1.str, d2->chan1.str); - if (res != 0) - return res; - res = strcmp(d1->chan1.opt, d2->chan1.opt); - } - return res; -} - -/* - * return true of the selector or vector entry is diagonal - */ -int -isdiag(struct info *e) -{ - if (strlen(e->desc.chan0.opt) == 0 || - strlen(e->desc.chan1.opt) == 0) - return 1; - return strcmp(e->desc.chan1.opt, e->desc.chan0.opt) == 0; -} - -/* - * find the value of the given selector parameter - */ -struct info * -selpos(struct info *i) -{ - while (i != NULL) { - if (i->curval) - return i; - i = i->next; - } - fprintf(stderr, "selpos: not found, bogus mixer\n"); - abort(); -} - -/* - * find the selector or vector entry with the given name and channels - */ -struct info * -vecent(struct info *i, char *vstr, char *vopt) -{ - while (i != NULL) { - if ((strcmp(i->desc.chan1.str, vstr) == 0) && - (strlen(vopt) == 0 || strcmp(i->desc.chan1.opt, vopt) == 0)) - break; - i = i->next; - } - return i; -} - -/* - * find the next parameter group - */ -struct info * -nextgrp(struct info *i) -{ - char *str, *func; - - func = i->desc.func; - str = i->desc.chan0.str; - for (i = i->next; i != NULL; i = i->next) { - if (strcmp(i->desc.chan0.str, str) != 0 || - strcmp(i->desc.func, func) != 0) - return i; - } - return NULL; -} - -/* - * find the next parameter of the same group - */ -struct info * -nextpar(struct info *i) -{ - char *str, *opt, *func; - - func = i->desc.func; - str = i->desc.chan0.str; - opt = i->desc.chan0.opt; - for (i = i->next; i != NULL; i = i->next) { - if (strcmp(i->desc.chan0.str, str) != 0 || - strcmp(i->desc.func, func) != 0) - break; - if (strcmp(i->desc.chan0.opt, opt) != 0) - return i; - } - return NULL; -} - -/* - * return the first structure having of a selector or vector group - */ -struct info * -firstent(struct info *g, char *vstr) -{ - char *astr, *func; - struct info *i; - - astr = g->desc.chan0.str; - func = g->desc.func; - for (i = g; i != NULL; i = i->next) { - if (strcmp(i->desc.chan0.str, astr) != 0 || - strcmp(i->desc.func, func) != 0) - break; - if (!isdiag(i)) - continue; - if (strcmp(i->desc.chan1.str, vstr) == 0) - return i; - } - return NULL; -} - -/* - * find the next entry of the given selector or vector, if the mono flag - * is set then the whole group is searched and off-diagonal entries are - * skipped - */ -struct info * -nextent(struct info *i, int mono) -{ - char *str, *opt, *func; - - func = i->desc.func; - str = i->desc.chan0.str; - opt = i->desc.chan0.opt; - for (i = i->next; i != NULL; i = i->next) { - if (strcmp(i->desc.chan0.str, str) != 0 || - strcmp(i->desc.func, func) != 0) - return NULL; - if (mono) - return i; - if (strcmp(i->desc.chan0.opt, opt) == 0) - return i; - } - return NULL; -} - -/* - * return true if parameter matches the given name and channel range - */ -int -matchpar(struct info *i, char *astr, char *aopt) -{ - if (strcmp(i->desc.chan0.str, astr) != 0) - return 0; - if (strlen(aopt) == 0) - return 1; - else if (strlen(i->desc.chan0.opt) == 0) { - fprintf(stderr, "opt used for parameter with no opt\n"); - exit(1); - } - return strcmp(i->desc.chan0.opt, aopt) == 0; -} - -/* - * return true if selector or vector entry matches the given name and - * channel range - */ -int -matchent(struct info *i, char *vstr, char *vopt) -{ - if (strcmp(i->desc.chan1.str, vstr) != 0) - return 0; - if (strlen(vopt) == 0) - return 1; - else if (strlen(i->desc.chan1.opt) == 0) { - fprintf(stderr, "opt used for parameter with no opt\n"); - exit(1); - } - return strcmp(i->desc.chan1.opt, vopt) == 0; -} - -/* - * return true if the given group can be represented as a signle mono - * parameter - */ -int -ismono(struct info *g) -{ - struct info *p1, *p2; - struct info *e1, *e2; - - p1 = g; - switch (g->desc.type) { - case SIOMIX_LABEL: - break; - case SIOMIX_NUM: - case SIOMIX_SW: - for (p2 = g; p2 != NULL; p2 = nextpar(p2)) { - if (p2->curval != p1->curval) - return 0; - } - break; - case SIOMIX_VEC: - case SIOMIX_LIST: - for (p2 = g; p2 != NULL; p2 = nextpar(p2)) { - for (e2 = p2; e2 != NULL; e2 = nextent(e2, 0)) { - if (!isdiag(e2)) { - if (e2->curval != 0) - return 0; - } else { - e1 = vecent(p1, - e2->desc.chan1.str, - p1->desc.chan0.opt); - if (e1 == NULL) - continue; - if (e1->curval != e2->curval) - return 0; - } - } - } - break; - } - return 1; -} - -/* - * print a sub-stream, eg. "spkr[4-7]" - */ -void -print_chan(struct siomix_chan *c, int mono) -{ - printf("%s", c->str); - if (!mono && strlen(c->opt) > 0) { - printf("[%s]", c->opt); - } -} - -/* - * print info about the parameter - */ -void -print_desc(struct info *p, int mono) -{ - struct info *e; - int more; - - switch (p->desc.type) { - case SIOMIX_NUM: - case SIOMIX_SW: - printf("*"); - break; - case SIOMIX_VEC: - case SIOMIX_LIST: - more = 0; - for (e = p; e != NULL; e = nextent(e, mono)) { - if (mono) { - if (!isdiag(e)) - continue; - if (e != firstent(p, e->desc.chan1.str)) - continue; - } - if (more) - printf(","); - print_chan(&e->desc.chan1, mono); - printf(":*"); - more = 1; - } - } -} - -/* - * print parameter value - */ -void -print_val(struct info *p, int mono) -{ - struct info *e; - int more; - - switch (p->desc.type) { - case SIOMIX_LABEL: - printf("%s", p->desc.chan1.str); - //print_chan(&e->desc.chan1, mono); - break; - case SIOMIX_NUM: - case SIOMIX_SW: - printf("%u", p->curval); - break; - case SIOMIX_VEC: - case SIOMIX_LIST: - more = 0; - for (e = p; e != NULL; e = nextent(e, mono)) { - if (mono) { - if (!isdiag(e)) - continue; - if (e != firstent(p, e->desc.chan1.str)) - continue; - } - if (more) - printf(","); - print_chan(&e->desc.chan1, mono); - printf(":%u", e->curval); - more = 1; - } - } -} - -/* - * print ``='' string (including '\n') - */ -void -print_par(struct info *p, int mono) -{ - struct info *i; - int more; - - print_chan(&p->desc.chan0, mono); - printf(".%s=", p->desc.func); - if (i_flag) - print_desc(p, mono); - else - print_val(p, mono); - - /* append a comment with the labels (if any) */ - if (!n_flag && p->desc.type != SIOMIX_LABEL) { - more = 0; - for (i = infolist; i != NULL; i = i->next) { - if (i->desc.type != SIOMIX_LABEL) - continue; - if (strcmp(i->desc.chan0.str, p->desc.chan0.str) == 0 && - strcmp(i->desc.chan0.opt, p->desc.chan0.opt) == 0) { - if (!more) { - printf("\t#"); - more = 1; - } - printf(" %s=%s", i->desc.func, i->desc.chan1.str); - } - } - } - printf("\n"); -} - -/* - * parse a stream name or parameter name - */ -int -parse_name(char **line, char *name) -{ - char *p = *line; - unsigned len = 0; - - if (!IS_IDENT(*p)) { - fprintf(stderr, "letter/digit expected near '%s'\n", p); - return 0; - } - while (IS_IDENT(*p)) { - if (len >= SIOMIX_NAMEMAX - 1) { - name[SIOMIX_NAMEMAX - 1] = '\0'; - fprintf(stderr, "%s...: too long\n", name); - return 0; - } - name[len++] = *p; - p++; - } - name[len] = '\0'; - *line = p; - return 1; -} - -/* - * parse a decimal number - */ -int -parse_dec(char **line, unsigned *num) -{ - char *p = *line; - unsigned val = 0; - - if (*p < '0' || *p > '9') { - fprintf(stderr, "number expected near '%s'\n", p); - return 0; - } - while (*p >= '0' && *p <= '9') { - val = 10 * val + (*p - '0'); - if (val > SIOMIX_INTMAX) { - fprintf(stderr, "integer too large\n"); - return 0; - } - p++; - } - *num = val; - *line = p; - return 1; -} - -/* - * parse a sub-stream, eg. "spkr[4-7]" - */ -int -parse_chan(char **line, char *str, char *opt) -{ - char *p = *line; - - if (!parse_name(&p, str)) - return 0; - if (*p != '[') { - *opt = 0; - *line = p; - return 1; - } - p++; - if (!parse_name(&p, opt)) - return 0; - if (*p != ']') { - fprintf(stderr, "']' expected near '%s'\n", p); - return 0; - } - p++; - *line = p; - return 1; -} - -/* - * parse a decimal prefixed by the optional mode - */ -int -parse_modeval(char **line, int *rmode, unsigned *rval) -{ - char *p = *line; - unsigned mode; - - switch (*p) { - case '+': - mode = MODE_ADD; - p++; - break; - case '-': - mode = MODE_SUB; - p++; - break; - case '!': - mode = MODE_TOGGLE; - p++; - break; - default: - mode = MODE_SET; - } - if (mode != MODE_TOGGLE) { - if (!parse_dec(&p, rval)) - return 0; - } - *line = p; - *rmode = mode; - return 1; -} - -/* - * dump the whole mixer, useful for debugging - */ -void -dump(void) -{ - struct info *i; - - for (i = infolist; i != NULL; i = i->next) { - printf("%03u:", i->ctladdr); - print_chan(&i->desc.chan0, 0); - printf(".%s", i->desc.func); - printf("="); - switch (i->desc.type) { - case SIOMIX_LABEL: - print_chan(&i->desc.chan1, 0); - break; - case SIOMIX_NUM: - case SIOMIX_SW: - printf("* (%u)", i->curval); - break; - case SIOMIX_VEC: - case SIOMIX_LIST: - print_chan(&i->desc.chan1, 0); - printf(":* (%u)", i->curval); - } - printf("\n"); - } -} - -/* - * parse and execute a command ``[=]'' - */ -int -cmd(char *line) -{ - char *pos = line; - struct info *i, *e, *g; - char func[SIOMIX_NAMEMAX], astr[SIOMIX_NAMEMAX], vstr[SIOMIX_NAMEMAX]; - char aopt[SIOMIX_NAMEMAX], vopt[SIOMIX_NAMEMAX]; - unsigned val, npar = 0, nent = 0; - int comma, mode; - - if (!parse_chan(&pos, astr, aopt)) - return 0; - if (*pos != '.') { - fprintf(stderr, "'.' expected near '%s'\n", pos); - return 0; - } - pos++; - if (!parse_name(&pos, func)) - return 0; - for (g = infolist;; g = g->next) { - if (g == NULL) { - fprintf(stderr, "%s.%s: no such group\n", astr, func); - return 0; - } - if (strcmp(g->desc.func, func) == 0 && - strcmp(g->desc.chan0.str, astr) == 0) - break; - } - g->mode = MODE_PRINT; - if (*pos != '=') { - if (*pos != '\0') { - fprintf(stderr, "junk at end of command\n"); - return 0; - } - return 1; - } - pos++; - if (i_flag) { - printf("can't set values in info mode\n"); - return 0; - } - npar = 0; - switch (g->desc.type) { - case SIOMIX_NUM: - case SIOMIX_SW: - if (!parse_modeval(&pos, &mode, &val)) - return 0; - for (i = g; i != NULL; i = nextpar(i)) { - if (!matchpar(i, astr, aopt)) - continue; - i->mode = mode; - i->newval = val; - npar++; - } - break; - case SIOMIX_VEC: - case SIOMIX_LIST: - for (i = g; i != NULL; i = nextpar(i)) { - if (!matchpar(i, astr, aopt)) - continue; - for (e = i; e != NULL; e = nextent(e, 0)) { - e->newval = 0; - e->mode = MODE_SET; - } - npar++; - } - comma = 0; - for (;;) { - if (*pos == '\0') - break; - if (comma) { - if (*pos != ',') - break; - pos++; - } - if (!parse_chan(&pos, vstr, vopt)) - return 0; - if (*pos == ':') { - pos++; - if (!parse_modeval(&pos, &mode, &val)) - return 0; - } else { - val = SIOMIX_INTMAX; - mode = MODE_SET; - } - nent = 0; - for (i = g; i != NULL; i = nextpar(i)) { - if (!matchpar(i, astr, aopt)) - continue; - for (e = i; e != NULL; e = nextent(e, 0)) { - if (matchent(e, vstr, vopt)) { - e->newval = val; - e->mode = mode; - nent++; - } - } - } - if (nent == 0) { - fprintf(stderr, "%s[%s]: invalid value\n", vstr, vopt); - print_par(g, 0); - exit(1); - } - comma = 1; - } - } - if (npar == 0) { - fprintf(stderr, "%s: invalid parameter\n", line); - exit(1); - } - if (*pos != '\0') { - printf("%s: junk at end of command\n", pos); - exit(1); - } - return 1; -} - -/* - * write on the mixer device entries with the ``set'' flag - */ -void -commit(void) -{ - struct info *i; - int val; - - for (i = infolist; i != NULL; i = i->next) { - val = 0xdeadbeef; - switch (i->mode) { - case MODE_IGNORE: - case MODE_PRINT: - continue; - case MODE_SET: - val = i->newval; - break; - case MODE_ADD: - val = i->curval + i->newval; - if (val > SIOMIX_INTMAX) - val = SIOMIX_INTMAX; - break; - case MODE_SUB: - val = i->curval - i->newval; - if (val < 0) - val = 0; - break; - case MODE_TOGGLE: - val = (i->curval >= SIOMIX_HALF) ? 0 : SIOMIX_INTMAX; - } - switch (i->desc.type) { - case SIOMIX_NUM: - case SIOMIX_SW: - siomix_setctl(hdl, i->ctladdr, val); - break; - case SIOMIX_VEC: - case SIOMIX_LIST: - siomix_setctl(hdl, i->ctladdr, val); - } - i->curval = val; - } -} - -/* - * print all parameters - */ -void -list(void) -{ - struct info *p, *g; - - for (g = infolist; g != NULL; g = nextgrp(g)) { - if (g->mode == MODE_IGNORE) - continue; - if (i_flag) { - if (v_flag) { - for (p = g; p != NULL; p = nextpar(p)) - print_par(p, 0); - } else - print_par(g, 1); - } else { - if (v_flag || !ismono(g)) { - for (p = g; p != NULL; p = nextpar(p)) - print_par(p, 0); - } else - print_par(g, 1); - } - } -} - -/* - * register a new knob/button, called from the poll() loop. this may be - * called when label string changes, in which case we update the - * existing label widged rather than inserting a new one. - */ -void -ondesc(void *arg, struct siomix_desc *d, int curval) -{ - struct info *i, **pi; - int cmp; - - if (d == NULL) - return; - - /* - * find the right position to insert the new widget - */ - for (pi = &infolist; (i = *pi) != NULL; pi = &i->next) { - cmp = cmpdesc(d, &i->desc); - if (cmp == 0) { - /* label is updated */ - if (i->desc.type == SIOMIX_LABEL) { - memcpy(i->desc.chan1.str, d->chan1.str, - SIOMIX_NAMEMAX); - print_par(i, 0); - return; - } - fprintf(stderr, "fatal: duplicate mixer knob:\n"); - print_par(i, 0); - exit(1); - } - if (cmp < 0) - break; - } - i = malloc(sizeof(struct info)); - if (i == NULL) { - perror("malloc"); - exit(1); - } - i->desc = *d; - i->ctladdr = d->addr; - i->curval = i->newval = curval; - i->mode = MODE_IGNORE; - i->next = *pi; - *pi = i; -} - -/* - * update a knob/button state, called from the poll() loop - */ -void -onctl(void *arg, unsigned addr, unsigned val) -{ - struct info *i; - - if (v_flag >= 1) - fprintf(stderr, "onctl (%d, %d)\n", addr, val); - for (i = infolist; i != NULL; i = i->next) { - if (i->ctladdr != addr) - continue; - i->curval = val; - print_par(i, 0); - } -} - -int -main(int argc, char **argv) -{ - char *devname = SIOMIX_DEVANY; - int i, c, d_flag = 0; - struct info *g; - struct pollfd *pfds; - int nfds, revents; - - while ((c = getopt(argc, argv, "df:imnv")) != -1) { - switch (c) { - case 'd': - d_flag = 1; - break; - case 'f': - devname = optarg; - break; - case 'i': - i_flag = 1; - break; - case 'm': - m_flag = 1; - break; - case 'n': - n_flag = 1; - break; - case 'v': - v_flag = 1; - break; - default: - fprintf(stderr, "usage: sndioctl " - "[-dimnv] [-f device] [command ...]\n"); - exit(1); - } - } - argc -= optind; - argv += optind; - - hdl = siomix_open(devname, SIOMIX_READ | SIOMIX_WRITE, 0); - if (hdl == NULL) { - fprintf(stderr, "%s: can't open mixer device\n", devname); - exit(1); - } - if (!siomix_ondesc(hdl, ondesc, NULL)) { - fprintf(stderr, "%s: can't get mixer description\n", devname); - exit(1); - } - siomix_onctl(hdl, onctl, NULL); - - if (d_flag) { - if (argc > 0) { - fprintf(stderr, - "commands are not allowed with -d option\n"); - exit(1); - } - dump(); - } else { - if (argc == 0) { - for (g = infolist; g != NULL; g = nextgrp(g)) { - if (g->desc.type == SIOMIX_LABEL && !n_flag) - continue; - g->mode = MODE_PRINT; - } - } else { - for (i = 0; i < argc; i++) { - if (!cmd(argv[i])) - return 1; - } - } - commit(); - list(); - } - if (m_flag) { - pfds = malloc(sizeof(struct pollfd) * siomix_nfds(hdl)); - if (pfds == NULL) { - perror("malloc"); - exit(1); - } - for (;;) { - nfds = siomix_pollfd(hdl, pfds, POLLIN); - if (nfds == 0) - break; - while (poll(pfds, nfds, -1) < 0) { - if (errno != EINTR) { - perror("poll"); - exit(1); - } - } - revents = siomix_revents(hdl, pfds); - if (revents & POLLHUP) { - fprintf(stderr, "disconnected\n"); - break; - } - } - free(pfds); - } - siomix_close(hdl); - return 0; -} diff --git a/xvolkeys/Makefile.in b/xvolkeys/Makefile.in deleted file mode 100644 index 3e977f5..0000000 --- a/xvolkeys/Makefile.in +++ /dev/null @@ -1,52 +0,0 @@ -# extra includes paths (-I options) -INCLUDE = -I/usr/X11R6/include -I../libsndio -I../bsd-compat - -# extra libraries paths (-L options) -LIB = -L/usr/X11R6/lib -L../libsndio - -# extra defines (-D options) -DEFS = -DDEBUG @defs@ - -# extra libraries (-l options) -LDADD = -lX11 -lsndio @ldadd@ - -# variables defined on configure script command line (if any) -@vars@ - -# -# binaries, documentation, man pages and examples will be installed in -# ${BIN_DIR}, ${MAN1_DIR} -# -BIN_DIR = @bindir@ -MAN1_DIR = @mandir@/man1 - -# -# programs to build -# -PROG = xvolkeys - -all: ${PROG} - -install: - mkdir -p ${DESTDIR}${BIN_DIR} ${DESTDIR}${MAN1_DIR} - cp ${PROG} ${DESTDIR}${BIN_DIR} - cp ${PROG:=.1} ${DESTDIR}${MAN1_DIR} - -uninstall: - cd ${DESTDIR}${BIN_DIR} && rm -f ${PROG} - cd ${DESTDIR}${MAN1_DIR} && rm -f ${PROG:=.1} - -clean: - rm -f -- *.o xvolkeys - -# ---------------------------------------------------------- dependencies --- - -OBJS = xvolkeys.o - -xvolkeys: ${OBJS} - ${CC} ${LDFLAGS} ${LIB} -o xvolkeys ${OBJS} ${LDADD} - -.c.o: - ${CC} ${CFLAGS} ${INCLUDE} ${DEFS} -c $< - -xvolkeys.o: xvolkeys.c diff --git a/xvolkeys/xvolkeys.1 b/xvolkeys/xvolkeys.1 deleted file mode 100644 index f9c510f..0000000 --- a/xvolkeys/xvolkeys.1 +++ /dev/null @@ -1,54 +0,0 @@ -.\" $OpenBSD$ -.\" -.\" Copyright (c) 2014 Alexandre Ratchov -.\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.Dd $Mdocdate$ -.Dt XVOLKEYS 1 -.Os -.Sh NAME -.Nm xvolkeys -.Nd hot-keys in X to control sndiod master volume -.Sh SYNOPSIS -.Nm xvolkeys -.Op Fl D -.Op Fl v -.Op Fl f Ar device -.Sh DESCRIPTION -The -.Nm -increments or -decrements the -.Xr sndiod 1 -master volume whenever the "+" and "-" keys -are pressed while the Control and Alt keys are held down. -It is meant to be started as background process by -.Xr xinit 1 -or -.Xr xdm 1 -session startup scripts. -It exits when X session terminates. -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl D -Daemonize. -.It Fl f Ar device -Audio device to control volume of. -.It Fl v -Increase log verbosity. -.El -.Sh SEE ALSO -.Xr sndiod 1 -.Xr sndio 7 diff --git a/xvolkeys/xvolkeys.c b/xvolkeys/xvolkeys.c deleted file mode 100644 index d0c7b27..0000000 --- a/xvolkeys/xvolkeys.c +++ /dev/null @@ -1,319 +0,0 @@ -/* $OpenBSD$ */ -/* - * Copyright (c) 2014 Alexandre Ratchov - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * X keysyms to increment / decrement volume: + and - - */ -#define KEY_INC XK_plus -#define KEY_DEC XK_minus - -/* - * modifiers: Alt + Ctrl - */ -#define MODMASK (Mod1Mask | ControlMask) - -/* - * volume increment - */ -#define VOL_INC 9 - -char *dev_name; -struct pollfd pfds[16]; -struct siomix_hdl *hdl; -unsigned int master_addr, master_val = SIOMIX_INTMAX; -int master_found = 0; -int verbose; - -/* - * X bits - */ -Display *dpy; -KeyCode inc_code, dec_code; -KeySym *inc_map, *dec_map; - -/* - * new control - */ -static void -mixer_ondesc(void *unused, struct siomix_desc *desc, int val) -{ - if (desc == NULL) - return; - if (master_found) - return; - if (strcmp(desc->chan0.str, "sndiod0") == 0 && - strcmp(desc->func, "level") == 0) { - master_found = 1; - master_addr = desc->addr; - master_val = val; - if (verbose) - fprintf(stderr, "%s: master at addr %u, value = %u\n", - dev_name, master_addr, master_val); - } -} - -/* - * control value changed - */ -static void -mixer_onctl(void *unused, unsigned int addr, unsigned int val) -{ - if (addr == master_addr) { - if (verbose) - fprintf(stderr, "master changed %u -> %u\n", master_val, val); - master_val = val; - } -} - -/* - * if there's an error, close connection to sndiod - */ -static void -mixer_disconnect(void) -{ - if (!siomix_eof(hdl)) - return; - if (verbose) - fprintf(stderr, "%s: mixer device disconnected\n", dev_name); - siomix_close(hdl); - hdl = NULL; -} - -/* - * connect to sndiod - */ -static int -mixer_connect(void) -{ - if (hdl != NULL) - return 1; - hdl = siomix_open(dev_name, SIOMIX_READ | SIOMIX_WRITE, 0); - if (hdl == NULL) { - if (verbose) - fprintf(stderr, "%s: couldn't open mixer device\n", - dev_name); - return 0; - } - master_found = 0; - siomix_ondesc(hdl, mixer_ondesc, NULL); - siomix_onctl(hdl, mixer_onctl, NULL); - if (!master_found) - fprintf(stderr, "%s: warning, couldn't find master control\n", - dev_name); - return 1; -} - -/* - * send master volume message and to the server - */ -static void -mixer_incrvol(int incr) -{ - int vol; - - if (!mixer_connect()) - return; - vol = master_val + incr; - if (vol > SIOMIX_INTMAX) - vol = SIOMIX_INTMAX; - if (vol < 0) - vol = 0; - if (master_val != (unsigned int)vol) { - master_val = vol; - if (hdl && master_found) { - if (verbose) { - fprintf(stderr, "%s: setting volume to %d\n", - dev_name, vol); - } - siomix_setctl(hdl, master_addr, master_val); - mixer_disconnect(); - } - } -} - -/* - * register hot-keys in X - */ -static void -grab_keys(void) -{ - unsigned int i, scr, nscr; - int nret; - - if (verbose) - fprintf(stderr, "grabbing keys\n"); - inc_code = XKeysymToKeycode(dpy, KEY_INC); - inc_map = XGetKeyboardMapping(dpy, inc_code, 1, &nret); - if (nret <= ShiftMask) { - fprintf(stderr, "couldn't get keymap for '+' key\n"); - exit(1); - } - - dec_code = XKeysymToKeycode(dpy, KEY_DEC); - dec_map = XGetKeyboardMapping(dpy, dec_code, 1, &nret); - if (nret <= ShiftMask) { - fprintf(stderr, "couldn't get keymap for '-' key\n"); - exit(1); - } - - nscr = ScreenCount(dpy); - for (i = 0; i <= 0xff; i++) { - if ((i & MODMASK) != 0) - continue; - for (scr = 0; scr != nscr; scr++) { - - XGrabKey(dpy, inc_code, i | MODMASK, - RootWindow(dpy, scr), 1, - GrabModeAsync, GrabModeAsync); - XGrabKey(dpy, dec_code, i | MODMASK, - RootWindow(dpy, scr), 1, - GrabModeAsync, GrabModeAsync); - } - } -} - -/* - * unregister hot-keys - */ -static void -ungrab_keys(void) -{ - unsigned int scr, nscr; - - if (verbose) - fprintf(stderr, "ungrabbing keys\n"); - - XFree(inc_map); - XFree(dec_map); - - nscr = ScreenCount(dpy); - for (scr = 0; scr != nscr; scr++) - XUngrabKey(dpy, AnyKey, AnyModifier, RootWindow(dpy, scr)); -} - -int -main(int argc, char **argv) -{ - int scr; - XEvent xev; - int c, nfds; - int background, revents; - - /* - * parse command line options - */ - dev_name = SIOMIX_DEVANY; - verbose = 0; - background = 0; - while ((c = getopt(argc, argv, "Df:q:v")) != -1) { - switch (c) { - case 'D': - background = 1; - break; - case 'v': - verbose++; - break; - - case 'q': /* compat */ - case 'f': - dev_name = optarg; - break; - default: - goto bad_usage; - } - } - argc -= optind; - argv += optind; - if (argc > 0) { - bad_usage: - fprintf(stderr, "usage: xvolkeys [-Dv] [-f device]\n"); - } - - dpy = XOpenDisplay(NULL); - if (dpy == 0) { - fprintf(stderr, "Couldn't open display\n"); - exit(1); - } - - /* mask non-key events for each screan */ - for (scr = 0; scr != ScreenCount(dpy); scr++) - XSelectInput(dpy, RootWindow(dpy, scr), KeyPress); - - (void)mixer_connect(); - - grab_keys(); - - if (background) { - verbose = 0; - if (daemon(0, 0) < 0) { - perror("daemon"); - exit(1); - } - } - - while (1) { - while (XPending(dpy)) { - XNextEvent(dpy, &xev); - if (xev.type == MappingNotify) { - if (xev.xmapping.request != MappingKeyboard) - continue; - if (verbose) - fprintf(stderr, "keyboard remapped\n"); - ungrab_keys(); - grab_keys(); - } - if (xev.type != KeyPress) - continue; - if (xev.xkey.keycode == inc_code && - inc_map[xev.xkey.state & ShiftMask] == KEY_INC) { - mixer_incrvol(VOL_INC); - } else if (xev.xkey.keycode == dec_code && - dec_map[xev.xkey.state & ShiftMask] == KEY_DEC) { - mixer_incrvol(-VOL_INC); - } - } - nfds = (hdl != NULL) ? siomix_pollfd(hdl, pfds, 0) : 0; - pfds[nfds].fd = ConnectionNumber(dpy); - pfds[nfds].events = POLLIN; - while (poll(pfds, nfds + 1, -1) < 0 && errno == EINTR) - ; /* nothing */ - if (hdl) { - revents = siomix_revents(hdl, pfds); - if (revents & POLLHUP) - mixer_disconnect(); - else if (revents & POLLIN) { - /* what */ - } - } - } - XFree(inc_map); - XFree(dec_map); - XCloseDisplay(dpy); - if (hdl) - siomix_close(hdl); - return 0; -} From a162cfd9e62426fb430e044d6a1b1b53d08cd972 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 28 Aug 2015 09:03:49 +0200 Subject: [PATCH 003/117] remove mixer api files --- libsndio/siomix.c | 198 -------------- libsndio/siomix_aucat.c | 258 ------------------ libsndio/siomix_open.3 | 261 ------------------ libsndio/siomix_priv.h | 67 ----- libsndio/siomix_sun.c | 573 ---------------------------------------- sndiod/dev_siomix.c | 193 -------------- sndiod/dev_siomix.h | 32 --- 7 files changed, 1582 deletions(-) delete mode 100644 libsndio/siomix.c delete mode 100644 libsndio/siomix_aucat.c delete mode 100644 libsndio/siomix_open.3 delete mode 100644 libsndio/siomix_priv.h delete mode 100644 libsndio/siomix_sun.c delete mode 100644 sndiod/dev_siomix.c delete mode 100644 sndiod/dev_siomix.h diff --git a/libsndio/siomix.c b/libsndio/siomix.c deleted file mode 100644 index dd15522..0000000 --- a/libsndio/siomix.c +++ /dev/null @@ -1,198 +0,0 @@ -/* $OpenBSD$ */ -/* - * Copyright (c) 2008 Alexandre Ratchov - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "siomix_priv.h" -#include "bsd-compat.h" - -struct siomix_hdl * -siomix_open(const char *str, unsigned int mode, int nbio) -{ - static char devany[] = SIOMIX_DEVANY; - struct siomix_hdl *hdl; - const char *p; - -#ifdef DEBUG - _sndio_debug_init(); -#endif - if (str == NULL) /* backward compat */ - str = devany; - if (strcmp(str, devany) == 0 && !issetugid()) { - str = getenv("AUDIODEVICE"); - if (str == NULL) - str = devany; - } - if (strcmp(str, devany) == 0) { - hdl = _siomix_aucat_open("/0", mode, nbio); - if (hdl != NULL) - return hdl; -#if defined(USE_SUN_MIXER) - return _siomix_sun_open("/0", mode, nbio); -#elif defined(USE_ALSA_MIXER) - return _siomix_alsa_open("/0", mode, nbio); -#else - return NULL; -#endif - } - if ((p = _sndio_parsetype(str, "snd")) != NULL) - return _siomix_aucat_open(p, mode, nbio); -#if defined(USE_ALSA_MIXER) || defined(USE_SUN_MIXER) - if ((p = _sndio_parsetype(str, "rsnd")) != NULL) { -#if defined(USE_SUN_MIXER) - return _siomix_sun_open(p, mode, nbio); -#elif defined(USE_ALSA_MIXER) - return _siomix_alsa_open(p, mode, nbio); -#endif - } -#endif - DPRINTF("siomix_open: %s: unknown device type\n", str); - return NULL; -} - -void -_siomix_create(struct siomix_hdl *hdl, struct siomix_ops *ops, - unsigned int mode, int nbio) -{ - hdl->ops = ops; - hdl->mode = mode; - hdl->nbio = nbio; - hdl->eof = 0; - hdl->ctl_cb = NULL; -} - - -int -_siomix_psleep(struct siomix_hdl *hdl, int event) -{ - struct pollfd pfds[SIOMIX_MAXNFDS]; - int revents, nfds; - - for (;;) { - nfds = siomix_pollfd(hdl, pfds, event); - if (nfds == 0) - return 0; - while (poll(pfds, nfds, -1) < 0) { - if (errno == EINTR) - continue; - DPERROR("siomix_psleep: poll"); - hdl->eof = 1; - return 0; - } - revents = siomix_revents(hdl, pfds); - if (revents & POLLHUP) { - DPRINTF("siomix_psleep: hang-up\n"); - return 0; - } - if (event == 0 || (revents & event)) - break; - } - return 1; -} - -void -siomix_close(struct siomix_hdl *hdl) -{ - hdl->ops->close(hdl); -} - -int -siomix_nfds(struct siomix_hdl *hdl) -{ - return hdl->ops->nfds(hdl); -} - -int -siomix_pollfd(struct siomix_hdl *hdl, struct pollfd *pfd, int events) -{ - if (hdl->eof) - return 0; - return hdl->ops->pollfd(hdl, pfd, events); -} - -int -siomix_revents(struct siomix_hdl *hdl, struct pollfd *pfd) -{ - if (hdl->eof) - return POLLHUP; - return hdl->ops->revents(hdl, pfd); -} - -int -siomix_eof(struct siomix_hdl *hdl) -{ - return hdl->eof; -} - -int -siomix_ondesc(struct siomix_hdl *hdl, - void (*cb)(void *, struct siomix_desc *, int), void *arg) -{ - hdl->desc_cb = cb; - hdl->desc_arg = arg; - return hdl->ops->ondesc(hdl); -} - -int -siomix_onctl(struct siomix_hdl *hdl, - void (*cb)(void *, unsigned int, unsigned int), void *arg) -{ - hdl->ctl_cb = cb; - hdl->ctl_arg = arg; - return hdl->ops->onctl(hdl); -} - -void -_siomix_ondesc_cb(struct siomix_hdl *hdl, - struct siomix_desc *desc, unsigned int val) -{ - if (desc) { - DPRINTF("%u -> %s[%s].%s=%s[%s]\n", - desc->addr, - desc->chan0.str, desc->chan0.opt, - desc->func, - desc->chan1.str, desc->chan1.opt); - } - if (hdl->desc_cb) - hdl->desc_cb(hdl->desc_arg, desc, val); -} - -void -_siomix_onctl_cb(struct siomix_hdl *hdl, unsigned int addr, unsigned int val) -{ - if (hdl->ctl_cb) - hdl->ctl_cb(hdl->ctl_arg, addr, val); -} - -int -siomix_setctl(struct siomix_hdl *hdl, unsigned int addr, unsigned int val) -{ - if (!(hdl->mode & SIOMIX_WRITE)) - return 0; - return hdl->ops->setctl(hdl, addr, val); -} diff --git a/libsndio/siomix_aucat.c b/libsndio/siomix_aucat.c deleted file mode 100644 index 43abef8..0000000 --- a/libsndio/siomix_aucat.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) 2010-2011 Alexandre Ratchov - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "debug.h" -#include "aucat.h" -#include "siomix_priv.h" -#include "bsd-compat.h" - -struct siomix_aucat_hdl { - struct siomix_hdl siomix; - struct aucat aucat; - struct siomix_desc desc; - struct amsg_mix_desc *tmp; - int dump_wait; -}; - -static void siomix_aucat_close(struct siomix_hdl *); -static int siomix_aucat_nfds(struct siomix_hdl *); -static int siomix_aucat_pollfd(struct siomix_hdl *, struct pollfd *, int); -static int siomix_aucat_revents(struct siomix_hdl *, struct pollfd *); -static int siomix_aucat_setctl(struct siomix_hdl *, unsigned int, unsigned int); -static int siomix_aucat_onctl(struct siomix_hdl *); -static int siomix_aucat_ondesc(struct siomix_hdl *); - -/* - * operations every device should support - */ -struct siomix_ops siomix_aucat_ops = { - siomix_aucat_close, - siomix_aucat_nfds, - siomix_aucat_pollfd, - siomix_aucat_revents, - siomix_aucat_setctl, - siomix_aucat_onctl, - siomix_aucat_ondesc -}; - -static int -siomix_aucat_rdata(struct siomix_aucat_hdl *hdl) -{ - struct siomix_desc desc; - struct amsg_mix_desc *c; - int n, size; - - size = ntohl(hdl->aucat.rmsg.u.data.size); - for (;;) { - n = _aucat_rdata(&hdl->aucat, - (unsigned char *)hdl->tmp + size - hdl->aucat.rtodo, - hdl->aucat.rtodo, &hdl->siomix.eof); - if (n == 0 || hdl->siomix.eof) - return 0; - if (hdl->aucat.rstate != RSTATE_DATA) - break; - } - c = hdl->tmp; - while (size >= sizeof(struct amsg_mix_desc)) { - strlcpy(desc.chan0.str, c->chan0.str, SIOMIX_NAMEMAX); - strlcpy(desc.chan0.opt, c->chan0.opt, SIOMIX_NAMEMAX); - strlcpy(desc.chan1.str, c->chan1.str, SIOMIX_NAMEMAX); - strlcpy(desc.chan1.opt, c->chan1.opt, SIOMIX_NAMEMAX); - strlcpy(desc.func, c->func, SIOMIX_NAMEMAX); - desc.type = c->type; - desc.addr = ntohs(c->addr); - _siomix_ondesc_cb(&hdl->siomix, &desc, ntohs(c->curval)); - size -= sizeof(struct amsg_mix_desc); - c++; - } - free(hdl->tmp); - hdl->dump_wait = 0; - return 1; -} - -/* - * execute the next message, return 0 if blocked - */ -static int -siomix_aucat_runmsg(struct siomix_aucat_hdl *hdl) -{ - int size; - - if (!_aucat_rmsg(&hdl->aucat, &hdl->siomix.eof)) - return 0; - switch (ntohl(hdl->aucat.rmsg.cmd)) { - case AMSG_DATA: - size = ntohl(hdl->aucat.rmsg.u.data.size); - hdl->tmp = malloc(size); - if (hdl->tmp == NULL) { - DPRINTF("siomix_aucat_runmsg: malloc failed\n"); - hdl->siomix.eof = 1; - return 0; - } - if (!siomix_aucat_rdata(hdl)) - return 0; - break; - case AMSG_MIXSET: - DPRINTF("siomix_aucat_runmsg: got MIXSET\n"); - _siomix_onctl_cb(&hdl->siomix, - ntohs(hdl->aucat.rmsg.u.mixset.addr), - ntohs(hdl->aucat.rmsg.u.mixset.val)); - break; - default: - DPRINTF("sio_aucat_runmsg: unhandled message %u\n", - hdl->aucat.rmsg.cmd); - hdl->siomix.eof = 1; - return 0; - } - hdl->aucat.rstate = RSTATE_MSG; - hdl->aucat.rtodo = sizeof(struct amsg); - return 1; -} - -struct siomix_hdl * -_siomix_aucat_open(const char *str, unsigned int mode, int nbio) -{ - struct siomix_aucat_hdl *hdl; - - hdl = malloc(sizeof(struct siomix_aucat_hdl)); - if (hdl == NULL) - return NULL; - if (!_aucat_open(&hdl->aucat, str, mode, 0)) { - free(hdl); - return NULL; - } - _siomix_create(&hdl->siomix, &siomix_aucat_ops, mode, nbio); - hdl->tmp = NULL; - hdl->dump_wait = 0; - return (struct siomix_hdl *)hdl; -} - -static void -siomix_aucat_close(struct siomix_hdl *addr) -{ - struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr; - - _aucat_close(&hdl->aucat, hdl->siomix.eof); - free(hdl); -} - -static int -siomix_aucat_ondesc(struct siomix_hdl *addr) -{ - struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr; - - while (hdl->aucat.wstate != WSTATE_IDLE) { - if (!_siomix_psleep(&hdl->siomix, POLLOUT)) - return 0; - } - AMSG_INIT(&hdl->aucat.wmsg); - hdl->aucat.wmsg.cmd = htonl(AMSG_MIXSUB); - hdl->aucat.wmsg.u.mixsub.desc = 1; - hdl->aucat.wmsg.u.mixsub.val = 0; - hdl->aucat.wtodo = sizeof(struct amsg); - if (!_aucat_wmsg(&hdl->aucat, &hdl->siomix.eof)) - return 0; - hdl->dump_wait = 1; - while (hdl->dump_wait) { - DPRINTF("psleeping...\n"); - if (!_siomix_psleep(&hdl->siomix, 0)) - return 0; - DPRINTF("psleeping done\n"); - } - DPRINTF("done\n"); - return 1; -} - -static int -siomix_aucat_onctl(struct siomix_hdl *addr) -{ - struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr; - - while (hdl->aucat.wstate != WSTATE_IDLE) { - if (!_siomix_psleep(&hdl->siomix, POLLOUT)) - return 0; - } - AMSG_INIT(&hdl->aucat.wmsg); - hdl->aucat.wmsg.cmd = htonl(AMSG_MIXSUB); - hdl->aucat.wmsg.u.mixsub.desc = 1; - hdl->aucat.wmsg.u.mixsub.val = 1; - hdl->aucat.wtodo = sizeof(struct amsg); - if (!_aucat_wmsg(&hdl->aucat, &hdl->siomix.eof)) - return 0; - return 1; -} - -static int -siomix_aucat_setctl(struct siomix_hdl *addr, unsigned int a, unsigned int v) -{ - struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr; - - hdl->aucat.wstate = WSTATE_MSG; - hdl->aucat.wtodo = sizeof(struct amsg); - hdl->aucat.wmsg.cmd = htonl(AMSG_MIXSET); - hdl->aucat.wmsg.u.mixset.addr = htons(a); - hdl->aucat.wmsg.u.mixset.val = htons(v); - return _aucat_wmsg(&hdl->aucat, &hdl->siomix.eof); -} - -static int -siomix_aucat_nfds(struct siomix_hdl *addr) -{ - //struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr; - - return 1; -} - -static int -siomix_aucat_pollfd(struct siomix_hdl *addr, struct pollfd *pfd, int events) -{ - struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr; - - return _aucat_pollfd(&hdl->aucat, pfd, events | POLLIN); -} - -static int -siomix_aucat_revents(struct siomix_hdl *addr, struct pollfd *pfd) -{ - struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr; - int revents; - - revents = _aucat_revents(&hdl->aucat, pfd); - if (revents & POLLIN) { - do { - if (hdl->aucat.rstate == RSTATE_MSG) { - if (!siomix_aucat_runmsg(hdl)) - break; - } - if (hdl->aucat.rstate == RSTATE_DATA) { - if (!siomix_aucat_rdata(hdl)) - break; - } - } while (0); - revents &= ~POLLIN; - } - if (hdl->siomix.eof) - return POLLHUP; - DPRINTFN(3, "siomix_aucat_revents: revents = 0x%x\n", revents); - return revents; -} diff --git a/libsndio/siomix_open.3 b/libsndio/siomix_open.3 deleted file mode 100644 index 27ce987..0000000 --- a/libsndio/siomix_open.3 +++ /dev/null @@ -1,261 +0,0 @@ -.\" $OpenBSD$ -.\" -.\" Copyright (c) 2011 Alexandre Ratchov -.\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.Dd $Mdocdate: September 29 2012 $ -.Dt SIO_OPEN 3 -.Os -.Sh NAME -.Nm siomix_open , -.Nm siomix_close , -.Nm siomix_ondesc , -.Nm siomix_onctl , -.Nm siomix_setctl , -.Nm siomix_nfds , -.Nm siomix_pollfd , -.Nm siomix_eof -.Nd interface to audio mixer -.Sh SYNOPSIS -.Fd #include -.Ft "struct siomix_hdl *" -.Fn "siomix_open" "const char *name" "unsigned int mode" "int nbio_flag" -.Ft "void" -.Fn "siomix_close" "struct siomix_hdl *hdl" -.Ft "int" -.Fn "siomix_ondesc" "struct siomix_hdl *hdl" "void (*cb)(void *arg, struct siomix_desc *desc, int val)" "void *arg" -.Ft "void" -.Fn "siomix_onctl" "struct siomix_hdl *hdl" "void (*cb)(void *arg, unsigned int addr, unsigned int val)" "void *arg" -.Ft "int" -.Fn "siomix_setctl" "struct siomix_hdl *hdl" "unsigned int addr" "unsigned int val" -.Ft "int" -.Fn "siomix_nfds" "struct siomix_hdl *hdl" -.Ft "int" -.Fn "siomix_pollfd" "struct siomix_hdl *hdl" "struct pollfd *pfd" "int events" -.Ft "int" -.Fn "siomix_revents" "struct siomix_hdl *hdl" "struct pollfd *pfd" -.Ft "int" -.Fn "siomix_eof" "struct siomix_hdl *hdl" -.Sh DESCRIPTION -The audio mixer of a sound device is the set of available controls, -e.g. the volume control. -Each control has an integer -.Em address -and an integer -.Em value . -Depending on the control type, its integer value represents either a -continuous quantity or a boolean. -Any control may be changed by submitting -a new value to its address. -When values change, asynchronous notifications are sent. -.Pp -Controls descriptions are available, allowing them to be grouped and -represented in a human usable form. -.Sh Opening and closing the mixer -First the application must call the -.Fn siomix_open -function to obtain a handle -that will be passed as the -.Ar hdl -argument to other functions. -.Pp -The -.Ar name -parameter gives the device string discussed in -.Xr sndio 7 . -In most cases it should be set to SIOMIX_DEVANY to allow -the user to select it using the -.Ev AUDIODEVICE -environment variable. -The -.Ar mode -parameter is a bitmap of the SIOMIX_READ and SIOMIX_WRITE constants -indicating whether control values can be read and -modified respectively. -.Pp -If the -.Ar nbio_flag -argument is 1, then the -.Fn siomix_setctl -function (see below) may fail instead of blocking and -the -.Fn siomix_ondesc -function doesn't block. -.Pp -The -.Fn siomix_close -function closes the mixer and frees any allocated resources -associated with the handle. -.Sh Mixer description -The -.Fn siomix_ondesc -function can be used to obtain the description of all available mixer controls -and their initial values. -It registers a call-back that is immediately invoked for all -controls. -It's called once with a NULL argument to indicate that the full -description was sent and that the caller has a consistent -representation of the mixer. -.Pp -Then, whenever a mixer control description changes (currently only -label strings may change, see below), the call-back is invoked with the -updated information followed by a call with a NULL argument. -.Pp -Controls are described by the -.Va siomix_ondesc -stucture as follows: -.Bd -literal -struct siomix_chan { - char str[SIOMIX_NAMEMAX]; /* stream name */ - char opt[SIOMIX_NAMEMAX]; /* optional channel */ -}; - -struct siomix_desc { - unsigned int addr; /* control's address */ -#define SIOMIX_NUM 2 /* number in the 0..127 range */ -#define SIOMIX_SW 3 /* on/off switch */ -#define SIOMIX_VEC 4 /* element of array of numbers */ -#define SIOMIX_LIST 5 /* element of array of switches */ -#define SIOMIX_LABEL 6 /* string attached to chan0 */ - unsigned int type; /* one of above */ - char func[SIOMIX_NAMEMAX]; /* parameter group name */ - struct siomix_chan chan0; /* affected channels */ - struct siomix_chan chan1; /* dito for vec, and list */ -}; -.Ed -.Pp -The -.Va addr -attribute is the mixer control address, usable with -.Fn siomix_setval -to set its value. -.Pp -The -.Va type -attribute indicates what the structure describes. -Possible types are: -.Bl -tag -width "SIOMIX_LABEL" -.It SIOMIX_NUM -A continuous control in the 0..SIOMIX_INTMAX range. -For instance the volume of the speaker. -.It SIOMIX_SW -A on/off switch control. -For instance the switch to mute the speaker. -.It SIOMIX_VEC -Element of an array of continuous controls. -For instance the knob to control the amount of signal flowing -from the line input to the speaker. -.It SIOMIX_LIST -An element of an array of on/off switches. -For instance the line-in position of the -speaker source selector. -.It SIOMIX_LABEL -A label attached to the channel. -In mixers exposed by -.Xr sndiod 1 , -they correspond to program names. -The label string is stored in the -.Va chan1 -attribute and is not unique. -Labels may dynamically change, but their -.Va addr -attribute remains the same and can be used to figure out which -label is changing. -.El -.Pp -The -.Va func -attribute is the name of the parameter being controlled. -There may be no parameters of different types with the same name. -.Pp -The -.Va chan0 -and -.Va chan1 -attributes indicate the names of the affected streams, and -an optional channel sub-set. -.Va chan1 -is meaningful for -.Va SIOMIX_VEC -and -.Va SIOMIX_LIST -only. -.Pp -Stream names in the -.Va chan0 -and -.Va chan1 -attributes and -.Va func -are static strings usable as unique identifiers. -.Sh Changing and reading control values -Controls are changed with the -.Fn siomix_setctl -function, by giving the index of the control and the new value. -The -.Fn siomix_onctl -function can be used to register a call-back which will be invoked whenever -a control changes. -Continuous values are in the 0..127 range. -.Sh "Interface to" Xr poll 2 -The -.Fn siomix_pollfd -function fills the array -.Ar pfd -of -.Va pollfd -structures, used by -.Xr poll 2 , -with -.Ar events ; -the latter is a bit-mask of -.Va POLLIN -and -.Va POLLOUT -constants. -.Fn siomix_pollfd -returns the number of -.Va pollfd -structures filled. -The -.Fn siomix_revents -function returns the bit-mask set by -.Xr poll 2 -in the -.Va pfd -array of -.Va pollfd -structures. -If -.Va POLLOUT -is set, -.Fn siomix_setctl -can be called without blocking. -POLLHUP may be set if an error occurs, even if -it is not selected with -.Fn siomix_pollfd . -POLLIN is not used yet. -.Pp -The -.Fn siomix_nfds -function returns the number of -.Va pollfd -structures the caller must preallocate in order to be sure -that -.Fn siomix_pollfd -will never overrun. -.Sh SEE ALSO -.Xr sndioctl 1 , -.Xr poll 2 , -.Xr sndio 7 diff --git a/libsndio/siomix_priv.h b/libsndio/siomix_priv.h deleted file mode 100644 index 9cebeab..0000000 --- a/libsndio/siomix_priv.h +++ /dev/null @@ -1,67 +0,0 @@ -/* $OpenBSD$ */ -/* - * Copyright (c) 2008 Alexandre Ratchov - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef SIOMIX_PRIV_H -#define SIOMIX_PRIV_H - -#include - -#define SIOMIX_MAXNFDS 4 - -/* - * private ``handle'' structure - */ -struct siomix_hdl { - struct siomix_ops *ops; - void (*desc_cb)(void *, struct siomix_desc *, int); - void *desc_arg; - void (*ctl_cb)(void *, unsigned int, unsigned int); - void *ctl_arg; - unsigned int mode; /* SIOMIX_READ | SIOMIX_WRITE */ - int nbio; /* true if non-blocking io */ - int eof; /* true if error occured */ -}; - -/* - * operations every device should support - */ -struct siomix_ops { - void (*close)(struct siomix_hdl *); - int (*nfds)(struct siomix_hdl *); - int (*pollfd)(struct siomix_hdl *, struct pollfd *, int); - int (*revents)(struct siomix_hdl *, struct pollfd *); - int (*setctl)(struct siomix_hdl *, unsigned int, unsigned int); - int (*onctl)(struct siomix_hdl *); - int (*ondesc)(struct siomix_hdl *); -}; - -struct siomix_hdl *_siomix_aucat_open(const char *, unsigned int, int); -struct siomix_hdl *_siomix_obsd_open(const char *, unsigned int, int); -struct siomix_hdl *_siomix_fake_open(const char *, unsigned int, int); -#ifdef USE_SUN_MIXER -struct siomix_hdl *_siomix_sun_open(const char *, unsigned int, int); -#endif -#ifdef USE_ALSA_MIXER -struct siomix_hdl *_siomix_alsa_open(const char *, unsigned int, int); -#endif -void _siomix_create(struct siomix_hdl *, - struct siomix_ops *, unsigned int, int); -void _siomix_ondesc_cb(struct siomix_hdl *, - struct siomix_desc *, unsigned int); -void _siomix_onctl_cb(struct siomix_hdl *, unsigned int, unsigned int); -int _siomix_psleep(struct siomix_hdl *, int); - -#endif /* !defined(SIOMIX_PRIV_H) */ diff --git a/libsndio/siomix_sun.c b/libsndio/siomix_sun.c deleted file mode 100644 index 0c69d15..0000000 --- a/libsndio/siomix_sun.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright (c) 2010-2011 Alexandre Ratchov - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * - * TODO - * - fix ac97 based mixers - * - */ - -#ifdef USE_SUN_MIXER -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "debug.h" -#include "siomix_priv.h" - -struct siomix_sun_hdl { - struct siomix_hdl siomix; - struct mixer_devinfo *info; - struct mixer_ctrl *curval; - int fd, ninfo, events; - int iclass, oclass, rclass; -}; - -static void siomix_sun_close(struct siomix_hdl *); -static int siomix_sun_nfds(struct siomix_hdl *); -static int siomix_sun_pollfd(struct siomix_hdl *, struct pollfd *, int); -static int siomix_sun_revents(struct siomix_hdl *, struct pollfd *); -static int siomix_sun_setctl(struct siomix_hdl *, unsigned int, unsigned int); -static int siomix_sun_onctl(struct siomix_hdl *); -static int siomix_sun_ondesc(struct siomix_hdl *); - -/* - * operations every device should support - */ -struct siomix_ops siomix_sun_ops = { - siomix_sun_close, - siomix_sun_nfds, - siomix_sun_pollfd, - siomix_sun_revents, - siomix_sun_setctl, - siomix_sun_onctl, - siomix_sun_ondesc -}; - -struct siomix_hdl * -_siomix_sun_open(const char *str, unsigned int mode, int nbio) -{ - struct siomix_sun_hdl *hdl; - int i, fd, flags; - char path[PATH_MAX]; - struct mixer_devinfo mi; - - if (*str != '/') { - DPRINTF("siomix_sun_open: %s: '/' expected\n", str); - return NULL; - } - str++; - hdl = malloc(sizeof(struct siomix_sun_hdl)); - if (hdl == NULL) - return NULL; - _siomix_create(&hdl->siomix, &siomix_sun_ops, mode, nbio); - snprintf(path, sizeof(path), "/dev/mixer%s", str); - if (mode == (SIOMIX_READ | SIOMIX_WRITE)) - flags = O_RDWR; - else - flags = (mode & SIOMIX_WRITE) ? O_WRONLY : O_RDONLY; - - while ((fd = open(path, flags)) < 0) { - if (errno == EINTR) - continue; - DPERROR(path); - goto bad_free; - } - if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { - DPERROR("FD_CLOEXEC"); - goto bad_close; - } - hdl->iclass = hdl->oclass = hdl->rclass = -1; - hdl->fd = fd; - - /* - * count the number of mixer knobs, and fetch the full mixer - * description - */ - for (mi.index = 0; ; mi.index++) { - if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mi) < 0) - break; - } - hdl->ninfo = mi.index; - hdl->info = malloc(hdl->ninfo * sizeof(struct mixer_devinfo)); - if (hdl->info == NULL) { - DPERROR("malloc"); - goto bad_close; - } - hdl->curval = malloc(hdl->ninfo * sizeof(struct mixer_ctrl)); - if (hdl->curval == NULL) { - DPERROR("malloc"); - goto bad_freeinfo; - } - for (i = 0; i < hdl->ninfo; i++) { - hdl->info[i].index = i; - if (ioctl(fd, AUDIO_MIXER_DEVINFO, &hdl->info[i]) < 0) { - DPERROR("AUDIO_MIXER_DEVINFO"); - goto bad_freeval; - } - } - return (struct siomix_hdl *)hdl; -bad_freeval: - free(hdl->curval); -bad_freeinfo: - free(hdl->info); -bad_close: - close(fd); -bad_free: - free(hdl); - return NULL; -} - -static void -siomix_sun_close(struct siomix_hdl *addr) -{ - struct siomix_sun_hdl *hdl = (struct siomix_sun_hdl *)addr; - - close(hdl->fd); - free(hdl); -} - -/* - * parse foo-4:5 and convert it to "foo", 4, 2 - */ -static int -copy_ch(struct siomix_sun_hdl *hdl, - int icls, char *istr, char *ostr, int *rmin, int *rnum) -{ - size_t len; - char *sep, *endp; - long cmin, cmax; - - ostr[0] = 0; - - sep = strchr(istr, '-'); - if (sep) { - len = sep - istr; - if (len >= SIOMIX_NAMEMAX - 1) - return 0; - memcpy(ostr, istr, len); - ostr[len] = 0; - istr = sep + 1; - - cmin = strtol(istr, &endp, 10); - if (endp != istr) { - /* - * this a "foo-0:3" style range - */ - istr = endp; - if (*endp == ':') { - istr++; - cmax = strtol(istr, &endp, 10); - if (endp == istr) { - DPRINTF("bad range\n"); - return 0; - } - istr = endp; - } else if (*endp == 0) { - cmax = cmin; - } else { - DPRINTF("unknown range\n"); - return 0; - } - *rmin = cmin; - *rnum = cmax - cmin + 1; - } else { - if (strcmp(ostr, "line") == 0) { - /* rename make "line-foo" to "foo" */ - ostr[0] = 0; - } else { - /* append unknown suffix with '_' */ - strlcat(ostr, "_", SIOMIX_NAMEMAX); - } - strlcat(ostr, istr, SIOMIX_NAMEMAX); - *rmin = 0; - *rnum = 0; - } - } else { - *rmin = 0; - *rnum = 0; - strlcpy(ostr, istr, SIOMIX_NAMEMAX); - } - if (icls == -1) - return 1; - /* - * append "_in" and "_out" suffixes, as nowadays - * most jacks are bidirectional - */ - if (strcmp(ostr, "mic") == 0 || - strcmp(ostr, "spkr") == 0 || - strcmp(ostr, "hp") == 0 || - strcmp(ostr, "line") == 0) { - if (icls == hdl->iclass) - strlcat(ostr, "_in", SIOMIX_NAMEMAX); - if (icls == hdl->oclass) - strlcat(ostr, "_out", SIOMIX_NAMEMAX); - } - - /* - * record class may conflict with input/output - */ - if (icls == hdl->rclass) { - if (strcmp(ostr, "volume") == 0) - strlcpy(ostr, "rec", SIOMIX_NAMEMAX); - } - return 1; -} - -static void -make_opt(char *opt, int min, int num) -{ - switch (num) { - case 0: - opt[0] = 0; - break; - case 1: - snprintf(opt, SIOMIX_NAMEMAX, "%u", min); - break; - default: - snprintf(opt, SIOMIX_NAMEMAX, "%u-%u", min, min + num - 1); - break; - } -} - -static int -copyname_num(struct siomix_sun_hdl *hdl, - struct mixer_devinfo *info, struct siomix_desc *desc, int *rmin, int *rnum) -{ - size_t len; - char *sep, *istr; - - sep = strchr(info->label.name, '_'); - if (sep) { - strlcpy(desc->func, "mix", SIOMIX_NAMEMAX); - desc->type = SIOMIX_VEC; - len = sep - info->label.name; - if (len >= SIOMIX_NAMEMAX - 1) - return 0; - memcpy(desc->chan0.str, info->label.name, len); - desc->chan0.str[len] = 0; - istr = sep + 1; - if (!copy_ch(hdl, info->mixer_class, istr, - desc->chan1.str, rmin, rnum)) - return 0; - } else { - strlcpy(desc->func, "level", SIOMIX_NAMEMAX); - desc->type = SIOMIX_NUM; - istr = info->label.name; - if (!copy_ch(hdl, info->mixer_class, istr, - desc->chan0.str, rmin, rnum)) - return 0; - desc->chan1.str[0] = '\0'; - } - return 1; -} - -static int -copyname_enum(struct siomix_sun_hdl *hdl, - struct mixer_devinfo *info, struct siomix_desc *desc, int *rmin, int *rnum) -{ - char istr[SIOMIX_NAMEMAX], *sep; - size_t len; - - sep = strrchr(info->label.name, '.'); - if (sep == NULL) - sep = strrchr(info->label.name, '_'); - if (sep == NULL) { - if (info->prev < 0) { - fprintf(stderr, "no separator\n"); - return 0; - } - strlcpy(desc->func, info->label.name, SIOMIX_NAMEMAX); - while (info->prev >= 0) - info = hdl->info + info->prev; - if (!copy_ch(hdl, info->mixer_class, info->label.name, - desc->chan0.str, rmin, rnum)) - return 0; - desc->chan1.str[0] = 0; - } else { - strlcpy(desc->func, sep + 1, SIOMIX_NAMEMAX); - len = sep - info->label.name; - if (len >= SIOMIX_NAMEMAX - 1) - return 0; - memcpy(istr, info->label.name, len); - istr[len] = '\0'; - if (!copy_ch(hdl, info->mixer_class, istr, - desc->chan0.str, rmin, rnum)) - return 0; - desc->chan1.str[0] = 0; - } - /* - * certain cards expose adc[0-1].source and adc[2-3].source - * as different types, which we forbid. - */ - if (strcmp(desc->func, "source") == 0) { - if (info->type == AUDIO_MIXER_SET) - strlcpy(desc->func, "sources", SIOMIX_NAMEMAX); - } - return 1; -} - -static int -ord_to_num(struct mixer_devinfo *info, int ord) -{ - int i; - - for (i = 0; i < info->un.e.num_mem; i++) { - if (ord == info->un.e.member[i].ord) - return i; - } - DPRINTF("mixer bug: order not found\n"); - return 0; -} - -static int -mask_to_bit(struct mixer_devinfo *info, int index, int val) -{ - int mask; - - mask = info->un.s.member[index].mask; - if ((mask & val) == mask) - return 1; - else - return 0; - return 0; -} - -static int -enum_to_sw(struct mixer_devinfo *info, struct siomix_desc *desc) -{ - char *v0, *v1; - - if (info->un.e.num_mem != 2) - return 0; - v0 = info->un.e.member[ord_to_num(info, 0)].label.name; - v1 = info->un.e.member[ord_to_num(info, 1)].label.name; - if (strcmp(v0, "off") == 0 && strcmp(v1, "on") == 0) - goto make_sw; - if (strcmp(v0, "unplugged") == 0 && strcmp(v1, "plugged") == 0) { - strlcpy(desc->func, - info->un.e.member[1].label.name, - SIOMIX_NAMEMAX); - goto make_sw; - } - return 0; - make_sw: - desc->chan1.str[0] = 0; - desc->chan1.opt[0] = 0; - desc->type = SIOMIX_SW; - return 1; -} - -static int -siomix_sun_ondesc(struct siomix_hdl *addr) -{ - struct siomix_sun_hdl *hdl = (struct siomix_sun_hdl *)addr; - struct mixer_devinfo *info; - struct mixer_ctrl *ctrl; - struct siomix_desc desc; - char *ostr; - int i, j, v, cmin, cnum; - - for (i = 0; i < hdl->ninfo; i++) { - info = hdl->info + i; - ctrl = hdl->curval + i; - ctrl->dev = i; - ctrl->type = info->type; - if (ctrl->type == AUDIO_MIXER_CLASS) { - if (strcmp(info->label.name, "inputs") == 0) - hdl->iclass = i; - if (strcmp(info->label.name, "outputs") == 0) - hdl->oclass = i; - if (strcmp(info->label.name, "record") == 0) - hdl->rclass = i; - continue; - } - if (ctrl->type == AUDIO_MIXER_VALUE) - ctrl->un.value.num_channels = info->un.v.num_channels; - if (ioctl(hdl->fd, AUDIO_MIXER_READ, ctrl) < 0) { - DPERROR("AUDIO_MIXER_READ"); - hdl->siomix.eof = 1; - return 0; - } - } - - info = hdl->info; - for (i = 0; i < hdl->ninfo; i++) { - DPRINTF("psarsing \"%s\"\n", info->label.name); - switch (info->type) { - case AUDIO_MIXER_VALUE: - desc.addr = i * 32; - if (!copyname_num(hdl, info, &desc, &cmin, &cnum)) - return 0; - make_opt(desc.chan0.opt, cmin, cnum); - desc.chan1.opt[0] = 0; - for (j = 0; j < info->un.v.num_channels; j++) { - v = hdl->curval[i].un.value.level[j] * - 127 / 255; - ostr = desc.type == SIOMIX_NUM ? - desc.chan0.opt : desc.chan1.opt; - if (info->un.v.num_channels > 1) { - make_opt(ostr, cmin + j, 1); - } else { - make_opt(ostr, cmin, cnum); - } - _siomix_ondesc_cb(&hdl->siomix, &desc, v); - desc.addr++; - } - break; - case AUDIO_MIXER_ENUM: - desc.addr = i * 32; - if (info->un.e.num_mem <= 1) - break; - if (!copyname_enum(hdl, info, &desc, &cmin, &cnum)) - return 0; - if (enum_to_sw(info, &desc)) { - make_opt(desc.chan0.opt, cmin, cnum); - _siomix_ondesc_cb(&hdl->siomix, &desc, - ord_to_num(info, hdl->curval[i].un.ord)); - break; - } - for (j = 0; j < info->un.e.num_mem; j++) { - if (!copyname_enum(hdl, info, - &desc, &cmin, &cnum)) - return 0; - make_opt(desc.chan0.opt, cmin, cnum); - if (!copy_ch(hdl, info->mixer_class, - info->un.e.member[j].label.name, - desc.chan1.str, &cmin, &cnum)) - return 0; - make_opt(desc.chan1.opt, cmin, cnum); - desc.type = SIOMIX_LIST; - v = (j == ord_to_num(info, - hdl->curval[i].un.ord)) ? 1 : 0; - _siomix_ondesc_cb(&hdl->siomix, &desc, v); - desc.addr++; - } - break; - case AUDIO_MIXER_SET: - desc.addr = i * 32; - if (info->un.s.num_mem == 0) - break; - if (!copyname_enum(hdl, info, &desc, &cmin, &cnum)) - return 0; - make_opt(desc.chan0.opt, cmin, cnum); - desc.type = SIOMIX_LIST; - for (j = 0; j < info->un.s.num_mem; j++) { - if (!copy_ch(hdl, info->mixer_class, - info->un.s.member[j].label.name, - desc.chan1.str, &cmin, &cnum)) - return 0; - make_opt(desc.chan1.opt, cmin, cnum); - _siomix_ondesc_cb(&hdl->siomix, &desc, - mask_to_bit(info, j, - hdl->curval[i].un.mask)); - desc.addr++; - } - break; - } - info++; - } - _siomix_ondesc_cb(&hdl->siomix, NULL, 0); - return 1; -} - -static int -siomix_sun_onctl(struct siomix_hdl *addr) -{ - //struct siomix_sun_hdl *hdl = (struct siomix_sun_hdl *)addr; - - return 1; -} - -static int -siomix_sun_setctl(struct siomix_hdl *arg, unsigned int addr, unsigned int val) -{ - struct siomix_sun_hdl *hdl = (struct siomix_sun_hdl *)arg; - struct mixer_ctrl *ctrl; - struct mixer_devinfo *info; - int base, offs, oldv; - - DPRINTF("siomix_sun_setctl: %d set to %d\n", addr, val); - base = addr / 32; - offs = addr % 32; - ctrl = hdl->curval + base; - info = hdl->info + base; - - switch (ctrl->type) { - case AUDIO_MIXER_VALUE: - oldv = ctrl->un.value.level[offs]; - ctrl->un.value.level[offs] = (val * 255 + 63) / 127; - break; - case AUDIO_MIXER_ENUM: - if (val == 0) - return 1; - oldv = ord_to_num(info, ctrl->un.ord); - if (oldv == offs) - return 1; - _siomix_onctl_cb(&hdl->siomix, 32 * base + oldv, 0); - ctrl->un.ord = info->un.e.member[offs].ord; - break; - case AUDIO_MIXER_SET: - if (val) - ctrl->un.mask |= info->un.s.member[offs].mask; - else - ctrl->un.mask &= ~info->un.s.member[offs].mask; - break; - default: - DPRINTF("siomix_sun_setctl: wrong addr %d\n", addr); - hdl->siomix.eof = 1; - return 0; - } - if (ioctl(hdl->fd, AUDIO_MIXER_WRITE, ctrl) < 0) { - DPERROR("siomix_sun_setctl"); - hdl->siomix.eof = 1; - return 0; - } - return 1; -} - -static int -siomix_sun_nfds(struct siomix_hdl *addr) -{ - return 0; -} - -static int -siomix_sun_pollfd(struct siomix_hdl *addr, struct pollfd *pfd, int events) -{ - struct siomix_sun_hdl *hdl = (struct siomix_sun_hdl *)addr; - - hdl->events = events; - return 0; -} - -static int -siomix_sun_revents(struct siomix_hdl *addr, struct pollfd *pfd) -{ - struct siomix_sun_hdl *hdl = (struct siomix_sun_hdl *)addr; - - return hdl->events & POLLOUT; -} -#endif diff --git a/sndiod/dev_siomix.c b/sndiod/dev_siomix.c deleted file mode 100644 index 629c695..0000000 --- a/sndiod/dev_siomix.c +++ /dev/null @@ -1,193 +0,0 @@ -/* $OpenBSD$ */ -/* - * Copyright (c) 2014 Alexandre Ratchov - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include -#include - -#include -#include -#include -#include -#include -#include "abuf.h" -#include "defs.h" -#include "dev.h" -#include "dsp.h" -#include "file.h" -#include "dev_siomix.h" -#include "utils.h" -#include "bsd-compat.h" - -void dev_siomix_ondesc(void *, struct siomix_desc *, int); -void dev_siomix_onctl(void *, unsigned int, unsigned int); -int dev_siomix_pollfd(void *, struct pollfd *); -int dev_siomix_revents(void *, struct pollfd *); -void dev_siomix_in(void *); -void dev_siomix_out(void *); -void dev_siomix_hup(void *); - -struct fileops dev_siomix_ops = { - "siomix", - dev_siomix_pollfd, - dev_siomix_revents, - dev_siomix_in, - dev_siomix_out, - dev_siomix_hup -}; - -void -dev_siomix_ondesc(void *arg, struct siomix_desc *desc, int val) -{ - struct dev *d = arg; - struct ctl *c; - - if (desc == NULL) - return; - - for (c = d->ctl_list; c != NULL; c = c->next) { - if (c->addr != desc->addr) - continue; - if (c->type != SIOMIX_LABEL) - continue; - ctl_log(c); - log_puts(": label -> "); - log_puts(desc->chan0.str); - log_puts("\n"); - strlcpy(c->chan0.str, desc->chan0.str, CTL_NAMEMAX); - c->desc_mask = ~0; - return; - } - c = dev_addctl(d, desc->type, desc->addr, - desc->chan0.str, desc->chan0.opt, desc->func, - desc->chan1.str, desc->chan1.opt); - c->curval = val; -#ifdef DEBUG - if (log_level >= 3) { - dev_log(d); - log_puts(": added: "); - ctl_log(c); - log_puts("\n"); - } -#endif -} - -void -dev_siomix_onctl(void *arg, unsigned int addr, unsigned int val) -{ - struct dev *d = arg; - struct ctl *c; - - dev_log(d); - log_puts(": onctl "); - log_putu(addr); - log_puts(", "); - log_putu(val); - log_puts("\n"); - - for (c = d->ctl_list; c != NULL; c = c->next) { - if (c->addr != addr) - continue; - ctl_log(c); - log_puts(": new value -> "); - log_putu(val); - log_puts("\n"); - c->val_mask = ~0U; - c->curval = val; - } -} - -/* - * open the mixer device. - */ -void -dev_siomix_open(struct dev *d) -{ - d->siomix.hdl = siomix_open(d->path, SIOMIX_READ | SIOMIX_WRITE, 0); - if (d->siomix.hdl == NULL) - return; - siomix_ondesc(d->siomix.hdl, dev_siomix_ondesc, d); - siomix_onctl(d->siomix.hdl, dev_siomix_onctl, d); - d->siomix.file = file_new(&dev_siomix_ops, d, d->path, - siomix_nfds(d->siomix.hdl)); -} - -/* - * close the mixer device. - */ -void -dev_siomix_close(struct dev *d) -{ - if (d->siomix.hdl == NULL) - return; - file_del(d->siomix.file); - siomix_close(d->siomix.hdl); - d->siomix.hdl = NULL; -} - -int -dev_siomix_pollfd(void *arg, struct pollfd *pfd) -{ - struct dev *d = arg; - struct ctl *c; - int events = 0; - - for (c = d->ctl_list; c != NULL; c = c->next) { - if (c->dirty) - events |= POLLOUT; - } - return siomix_pollfd(d->siomix.hdl, pfd, events); -} - -int -dev_siomix_revents(void *arg, struct pollfd *pfd) -{ - struct dev *d = arg; - - return siomix_revents(d->siomix.hdl, pfd); -} - -void -dev_siomix_in(void *arg) -{ -} - -void -dev_siomix_out(void *arg) -{ - struct dev *d = arg; - struct ctl *c; - - for (c = d->ctl_list; c != NULL; c = c->next) { - if (!c->dirty) - continue; - if (!siomix_setctl(d->siomix.hdl, c->addr, c->curval)) - break; - if (log_level >= 2) { - ctl_log(c); - log_puts(": changed\n"); - } - c->dirty = 0; - dev_unref(d); - } -} - -void -dev_siomix_hup(void *arg) -{ - struct dev *d = arg; - - dev_siomix_close(d); -} diff --git a/sndiod/dev_siomix.h b/sndiod/dev_siomix.h deleted file mode 100644 index 2c74387..0000000 --- a/sndiod/dev_siomix.h +++ /dev/null @@ -1,32 +0,0 @@ -/* $OpenBSD$ */ -/* - * Copyright (c) 2014 Alexandre Ratchov - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef DEV_SIOMIX_H -#define DEV_SIOMIX_H - -#include "file.h" - -struct dev; - -struct dev_siomix { - struct siomix_hdl *hdl; - struct file *file; -}; - -void dev_siomix_open(struct dev *); -void dev_siomix_close(struct dev *); - -#endif /* !defined(DEV_SIOMIX_H) */ From 7bd2439992ada407952441ae0e3865a02bafdbcf Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sun, 30 Aug 2015 11:39:09 +0200 Subject: [PATCH 004/117] unbreak configure script: missing xvolkeys and sndioctl --- configure | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/configure b/configure index d9ed438..16247b1 100755 --- a/configure +++ b/configure @@ -20,8 +20,6 @@ Usage: configure [options] --disable-sun disable sun audio backend --enable-rmidi enable character device midi backend [$rmidi] --disable-rmidi disable character device midi backend ---enable-xvolkeys build xvolkeys utility (requires X) [$xvolkeys] ---disable-xvolkeys don't build xvolkeys END } @@ -35,7 +33,6 @@ sun=no # do we want sun support ? rmidi=no # do we want support for raw char dev ? precision=16 # aucat/sndiod arithmetic precision user=_sndio # non-privileged user for sndio daemon -xvolkeys=yes # build xvolkeys ? unset vars # variables passed as arguments unset bindir # path where to install binaries unset datadir # path where to install doc @@ -113,12 +110,6 @@ for i; do --privsep-user=*) user="${i#--privsep-user=}" shift;; - --enable-xvolkeys) - xvolkeys=yes - shift;; - --disable-xvolkeys) - xvolkeys=no - shift;; --precision=*) precision="${i#--precision=}" if [ "$precision" != 16 -a "$precision" != 24 ]; then @@ -168,7 +159,7 @@ if [ $rmidi = yes ]; then fi for f in Makefile aucat/Makefile midicat/Makefile sndiod/Makefile \ -libsndio/Makefile sndioctl/Makefile xvolkeys/Makefile \ +libsndio/Makefile \ examples/Makefile \ contrib/init.d.sndiod do @@ -184,7 +175,6 @@ do -e "s:@vars@:${vars}:" \ -e "s:@precision@:$precision:" \ -e "s:@user@:$user:" \ - -e "s:@xvolkeys@:$xvolkeys:" \ < $f.in > $f done @@ -200,7 +190,6 @@ precision................ $precision alsa..................... $alsa sun...................... $sun rmidi.................... $rmidi -xvolkeys................. $xvolkeys Do "make && make install" to compile and install sndio From e0489782f6ea6cbed8c81b6ba799b3ceb288cc64 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sun, 30 Aug 2015 19:36:58 +0200 Subject: [PATCH 005/117] scape "-" with backslash, from Peter Piwowarski --- midicat/midicat.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/midicat/midicat.1 b/midicat/midicat.1 index a95ac0b..a755ada 100644 --- a/midicat/midicat.1 +++ b/midicat/midicat.1 @@ -50,7 +50,7 @@ Dump data received from .Pa rmidi/0 to stderr: .Bd -literal -offset indent -$ midicat -di rmidi/0 +$ midicat \-di rmidi/0 .Ed .Pp Send data from @@ -58,7 +58,7 @@ Send data from to .Pa midithru/0: .Bd -literal -offset indent -$ midicat -i rmidi/0 -o midithru/0 +$ midicat \-i rmidi/0 \-o midithru/0 .Ed .Sh SEE ALSO .Xr midi 4 , From ad93cbcd12ac614f69c330210eafa59cf7d6ff43 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sun, 30 Aug 2015 20:14:58 +0200 Subject: [PATCH 006/117] fix example (>/dev/null required to drop output) --- midicat/midicat.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/midicat/midicat.1 b/midicat/midicat.1 index a755ada..25cfafc 100644 --- a/midicat/midicat.1 +++ b/midicat/midicat.1 @@ -50,7 +50,7 @@ Dump data received from .Pa rmidi/0 to stderr: .Bd -literal -offset indent -$ midicat \-di rmidi/0 +$ midicat \-di rmidi/0 >/dev/null .Ed .Pp Send data from From ebed8a554ccc1e2d6231c24c513453c3f62eea03 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 2 Sep 2015 08:28:10 +0200 Subject: [PATCH 007/117] leave -'s in literals --- midicat/midicat.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/midicat/midicat.1 b/midicat/midicat.1 index 25cfafc..f8eaed1 100644 --- a/midicat/midicat.1 +++ b/midicat/midicat.1 @@ -50,7 +50,7 @@ Dump data received from .Pa rmidi/0 to stderr: .Bd -literal -offset indent -$ midicat \-di rmidi/0 >/dev/null +$ midicat -di rmidi/0 >/dev/null .Ed .Pp Send data from @@ -58,7 +58,7 @@ Send data from to .Pa midithru/0: .Bd -literal -offset indent -$ midicat \-i rmidi/0 \-o midithru/0 +$ midicat -i rmidi/0 -o midithru/0 .Ed .Sh SEE ALSO .Xr midi 4 , From f2b6fd9f4b1c92ca05957ce5dfda514ba5ab7c95 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 5 Sep 2015 13:18:04 +0200 Subject: [PATCH 008/117] s/xfree/free in comments --- sndiod/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sndiod/dev.c b/sndiod/dev.c index 7b02fae..c3d21bd 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -1453,7 +1453,7 @@ slot_new(struct dev *d, char *who, struct slotops *ops, void *arg, int mode) } /* - * find a xfree controller slot with the same name/unit + * find a free controller slot with the same name/unit */ for (i = 0, s = d->slot; i < DEV_NSLOT; i++, s++) { if (s->ops == NULL && @@ -1471,7 +1471,7 @@ slot_new(struct dev *d, char *who, struct slotops *ops, void *arg, int mode) } /* - * couldn't find a matching slot, pick oldest xfree slot + * couldn't find a matching slot, pick oldest free slot * and set its name/unit */ bestser = 0; From ed060a659ef02afdea246b43d0ee0b9246254dab Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 9 Sep 2015 19:32:30 +0200 Subject: [PATCH 009/117] Add --with-libbsd to use libbsd for strlcpy, strlcat and strtonum. From Peter Piwowarski . Thanks. --- configure | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/configure b/configure index 16247b1..91ae816 100755 --- a/configure +++ b/configure @@ -20,6 +20,8 @@ Usage: configure [options] --disable-sun disable sun audio backend --enable-rmidi enable character device midi backend [$rmidi] --disable-rmidi disable character device midi backend +--with-libbsd use the libbsd rather than bsd-compat/* +--without-libbsd don't use libbsd END } @@ -33,6 +35,7 @@ sun=no # do we want sun support ? rmidi=no # do we want support for raw char dev ? precision=16 # aucat/sndiod arithmetic precision user=_sndio # non-privileged user for sndio daemon +libbsd=no # use libbsd? unset vars # variables passed as arguments unset bindir # path where to install binaries unset datadir # path where to install doc @@ -117,6 +120,12 @@ for i; do exit 1 fi shift;; + --with-libbsd) + libbsd=yes + shift;; + --without-libbsd) + libbsd=no + shift;; CC=*|CFLAGS=*|LDFLAGS=*) vars="$vars$i$nl" shift;; @@ -158,6 +167,15 @@ if [ $rmidi = yes ]; then defs="$defs -DUSE_RMIDI" fi +# +# if using libbsd, add corresponding parameters +# +if [ $libbsd = yes ]; then + # no arc4random as libbsd has a questionable implementation + defs="$defs -DHAVE_STRLCPY -DHAVE_STRLCAT -DHAVE_STRTONUM" + ldadd="$ldadd -lbsd" +fi + for f in Makefile aucat/Makefile midicat/Makefile sndiod/Makefile \ libsndio/Makefile \ examples/Makefile \ @@ -186,6 +204,7 @@ includedir............... $includedir libdir................... $libdir mandir................... $mandir user..................... $user +libbsd................... $libbsd precision................ $precision alsa..................... $alsa sun...................... $sun From 7062d226ac0aa397af90af04ecff6f813e163010 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 1 Oct 2015 08:49:47 +0200 Subject: [PATCH 010/117] remove useless quoting and fix typos, from schwarze@ --- libsndio/mio_open.3 | 16 ++++++++-------- libsndio/sio_open.3 | 34 +++++++++++++++++----------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/libsndio/mio_open.3 b/libsndio/mio_open.3 index cbfdff4..ffbcf43 100644 --- a/libsndio/mio_open.3 +++ b/libsndio/mio_open.3 @@ -30,21 +30,21 @@ .Sh SYNOPSIS .In sndio.h .Ft "struct mio_hdl *" -.Fn "mio_open" "const char *name" "unsigned int mode" "int nbio_flag" +.Fn mio_open "const char *name" "unsigned int mode" "int nbio_flag" .Ft "void" -.Fn "mio_close" "struct mio_hdl *hdl" +.Fn mio_close "struct mio_hdl *hdl" .Ft "size_t" -.Fn "mio_read" "struct mio_hdl *hdl" "void *addr" "size_t nbytes" +.Fn mio_read "struct mio_hdl *hdl" "void *addr" "size_t nbytes" .Ft "size_t" -.Fn "mio_write" "struct mio_hdl *hdl" "const void *addr" "size_t nbytes" +.Fn mio_write "struct mio_hdl *hdl" "const void *addr" "size_t nbytes" .Ft "int" -.Fn "mio_nfds" "struct mio_hdl *hdl" +.Fn mio_nfds "struct mio_hdl *hdl" .Ft "int" -.Fn "mio_pollfd" "struct mio_hdl *hdl" "struct pollfd *pfd" "int events" +.Fn mio_pollfd "struct mio_hdl *hdl" "struct pollfd *pfd" "int events" .Ft "int" -.Fn "mio_revents" "struct mio_hdl *hdl" "struct pollfd *pfd" +.Fn mio_revents "struct mio_hdl *hdl" "struct pollfd *pfd" .Ft "int" -.Fn "mio_eof" "struct mio_hdl *hdl" +.Fn mio_eof "struct mio_hdl *hdl" .Sh DESCRIPTION The .Nm sndio diff --git a/libsndio/sio_open.3 b/libsndio/sio_open.3 index cf4f981..620bb56 100644 --- a/libsndio/sio_open.3 +++ b/libsndio/sio_open.3 @@ -39,39 +39,39 @@ .Sh SYNOPSIS .In sndio.h .Ft "struct sio_hdl *" -.Fn "sio_open" "const char *name" "unsigned int mode" "int nbio_flag" +.Fn sio_open "const char *name" "unsigned int mode" "int nbio_flag" .Ft "void" -.Fn "sio_close" "struct sio_hdl *hdl" +.Fn sio_close "struct sio_hdl *hdl" .Ft "int" -.Fn "sio_setpar" "struct sio_hdl *hdl" "struct sio_par *par" +.Fn sio_setpar "struct sio_hdl *hdl" "struct sio_par *par" .Ft "int" -.Fn "sio_getpar" "struct sio_hdl *hdl" "struct sio_par *par" +.Fn sio_getpar "struct sio_hdl *hdl" "struct sio_par *par" .Ft "int" -.Fn "sio_getcap" "struct sio_hdl *hdl" "struct sio_cap *cap" +.Fn sio_getcap "struct sio_hdl *hdl" "struct sio_cap *cap" .Ft "int" -.Fn "sio_start" "struct sio_hdl *hdl" +.Fn sio_start "struct sio_hdl *hdl" .Ft "int" -.Fn "sio_stop" "struct sio_hdl *hdl" +.Fn sio_stop "struct sio_hdl *hdl" .Ft "size_t" -.Fn "sio_read" "struct sio_hdl *hdl" "void *addr" "size_t nbytes" +.Fn sio_read "struct sio_hdl *hdl" "void *addr" "size_t nbytes" .Ft "size_t" -.Fn "sio_write" "struct sio_hdl *hdl" "const void *addr" "size_t nbytes" +.Fn sio_write "struct sio_hdl *hdl" "const void *addr" "size_t nbytes" .Ft "void" -.Fn "sio_onmove" "struct sio_hdl *hdl" "void (*cb)(void *arg, int delta)" "void *arg" +.Fn sio_onmove "struct sio_hdl *hdl" "void (*cb)(void *arg, int delta)" "void *arg" .Ft "int" -.Fn "sio_nfds" "struct sio_hdl *hdl" +.Fn sio_nfds "struct sio_hdl *hdl" .Ft "int" -.Fn "sio_pollfd" "struct sio_hdl *hdl" "struct pollfd *pfd" "int events" +.Fn sio_pollfd "struct sio_hdl *hdl" "struct pollfd *pfd" "int events" .Ft "int" -.Fn "sio_revents" "struct sio_hdl *hdl" "struct pollfd *pfd" +.Fn sio_revents "struct sio_hdl *hdl" "struct pollfd *pfd" .Ft "int" -.Fn "sio_eof" "struct sio_hdl *hdl" +.Fn sio_eof "struct sio_hdl *hdl" .Ft "int" -.Fn "sio_setvol" "struct sio_hdl *hdl" "unsigned int vol" +.Fn sio_setvol "struct sio_hdl *hdl" "unsigned int vol" .Ft "int" -.Fn "sio_onvol" "struct sio_hdl *hdl" "void (*cb)(void *arg, unsigned int vol)" "void *arg" +.Fn sio_onvol "struct sio_hdl *hdl" "void (*cb)(void *arg, unsigned int vol)" "void *arg" .Ft "void" -.Fn "sio_initpar" "struct sio_par *par" +.Fn sio_initpar "struct sio_par *par" .\"Fd #define SIO_BPS(bits) .\"Fd #define SIO_LE_NATIVE .Sh DESCRIPTION From 6ddedf6c9f42e694dabc642bc2f4edec86884441 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 1 Oct 2015 08:50:13 +0200 Subject: [PATCH 011/117] remove unused AUCAT_COOKIE environment variable --- libsndio/aucat.c | 16 ++++++---------- libsndio/sndio.7 | 4 ---- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/libsndio/aucat.c b/libsndio/aucat.c index a56d5e6..6dd88c4 100644 --- a/libsndio/aucat.c +++ b/libsndio/aucat.c @@ -245,21 +245,17 @@ static int aucat_mkcookie(unsigned char *cookie) { struct stat sb; - char buf[PATH_MAX], tmp[PATH_MAX], *path; + char *home, path[PATH_MAX], tmp[PATH_MAX]; ssize_t len; int fd; /* * try to load the cookie */ - path = issetugid() ? NULL : getenv("AUCAT_COOKIE"); - if (path == NULL) { - path = issetugid() ? NULL : getenv("HOME"); - if (path == NULL) - goto bad_gen; - snprintf(buf, PATH_MAX, "%s/.aucat_cookie", path); - path = buf; - } + home = issetugid() ? NULL : getenv("HOME"); + if (home == NULL) + goto bad_gen; + snprintf(path, PATH_MAX, "%s/.aucat_cookie", home); fd = open(path, O_RDONLY); if (fd < 0) { if (errno != ENOENT) @@ -301,7 +297,7 @@ bad_gen: /* * try to save the cookie */ - if (path == NULL) + if (home == NULL) return 1; if (strlcpy(tmp, path, PATH_MAX) >= PATH_MAX || strlcat(tmp, ".XXXXXXXX", PATH_MAX) >= PATH_MAX) { diff --git a/libsndio/sndio.7 b/libsndio/sndio.7 index 654c820..e5cb53c 100644 --- a/libsndio/sndio.7 +++ b/libsndio/sndio.7 @@ -198,10 +198,6 @@ If a session needs to be shared between multiple users, they can connect to the server using the same cookie. .Sh ENVIRONMENT .Bl -tag -width "AUDIODEVICEXXX" -compact -.It Ev AUCAT_COOKIE -Path to file containing the session cookie to be used -when connecting to -.Xr sndiod 1 . .It Ev AUDIODEVICE Audio device to use if the application provides no device chooser. From d91596856bae1c59ddefd6980341f8e82a37d77a Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 1 Oct 2015 08:51:48 +0200 Subject: [PATCH 012/117] typo --- aucat/aucat.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aucat/aucat.1 b/aucat/aucat.1 index f0d3818..dab4e91 100644 --- a/aucat/aucat.1 +++ b/aucat/aucat.1 @@ -75,7 +75,7 @@ Start, stop and relocate playback and recording. .Pp The options are as follows: .Bl -tag -width Ds -.It Fl Ar b size +.It Fl b Ar size The buffer size of the audio device in frames. Default is 7680. .It Xo From 0a39548f4d431f0d756362a050f870e920802cd2 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 2 Oct 2015 14:26:46 +0200 Subject: [PATCH 013/117] use SOCKPATH_xxx macros --- sndiod/sndiod.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index 51214fd..f3e2d1d 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -261,10 +261,10 @@ getbasepath(char *base, size_t size) uid = geteuid(); if (uid == 0) { mask = 022; - snprintf(base, PATH_MAX, "/tmp/aucat"); + snprintf(base, SOCKPATH_MAX, SOCKPATH_DIR); } else { mask = 077; - snprintf(base, PATH_MAX, "/tmp/aucat-%u", uid); + snprintf(base, SOCKPATH_MAX, SOCKPATH_DIR "-%u", uid); } if (mkdir(base, 0777 & ~mask) < 0) { if (errno != EEXIST) @@ -334,7 +334,7 @@ main(int argc, char **argv) { int c, background, unit; int pmin, pmax, rmin, rmax; - char base[PATH_MAX], path[PATH_MAX]; + char base[SOCKPATH_MAX], path[SOCKPATH_MAX]; unsigned int mode, dup, mmc, vol; unsigned int hold, autovol, bufsz, round, rate; const char *str; @@ -467,7 +467,7 @@ main(int argc, char **argv) mode, vol, mmc, dup); } getbasepath(base, sizeof(base)); - snprintf(path, PATH_MAX, "%s/%s%u", base, AUCAT_PATH, unit); + snprintf(path, SOCKPATH_MAX, "%s/" SOCKPATH_FILE "%u", base, unit); listen_new_un(path); if (geteuid() == 0) privdrop(); From 5d431d3616292289696d6d8378863808b66c0c88 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 2 Oct 2015 14:28:17 +0200 Subject: [PATCH 014/117] Replace hard-coded strings with macros, replace PATH_MAX with actual string length, validate audio and midi device numbers --- libsndio/amsg.h | 24 ++++++++++++++++++---- libsndio/aucat.c | 48 +++++++++++++++++++++++++++++--------------- libsndio/debug.c | 24 ++++++++++++++++++++++ libsndio/debug.h | 3 ++- libsndio/mio_alsa.c | 19 +++++++++++++++--- libsndio/mio_rmidi.c | 18 +++++++++++++---- libsndio/sio_alsa.c | 22 ++++++++++++++------ libsndio/sio_sun.c | 15 ++++++++++++-- 8 files changed, 137 insertions(+), 36 deletions(-) diff --git a/libsndio/amsg.h b/libsndio/amsg.h index 0b3c2e9..fa276a5 100644 --- a/libsndio/amsg.h +++ b/libsndio/amsg.h @@ -19,12 +19,28 @@ #include -/* - * socket and option names +/* + * unix-domain socket name is: + * + * DIR [ '-' UID ] '/' FILE UNIT + * + * example: "/tmp/aucat-1000/aucat0" + * + */ +#define SOCKPATH_DIR "/tmp/aucat" +#define SOCKPATH_FILE "aucat" +#define SOCKPATH_MAX (1 + \ + sizeof(SOCKPATH_DIR) - 1 + \ + sizeof(char) + \ + sizeof(int) * 3 + \ + sizeof(char) + \ + sizeof(SOCKPATH_FILE) - 1 + \ + sizeof(int) * 3) + +/* + * server TCP base port number */ -#define AUCAT_PATH "aucat" #define AUCAT_PORT 11025 -#define DEFAULT_OPT "default" /* * WARNING: since the protocol may be simultaneously used by static diff --git a/libsndio/aucat.c b/libsndio/aucat.c index 6dd88c4..c6a3ac2 100644 --- a/libsndio/aucat.c +++ b/libsndio/aucat.c @@ -244,10 +244,12 @@ _aucat_wdata(struct aucat *hdl, const void *buf, size_t len, static int aucat_mkcookie(unsigned char *cookie) { +#define COOKIE_SUFFIX "/.aucat_cookie" +#define TEMPL_SUFFIX ".XXXXXXXX" struct stat sb; - char *home, path[PATH_MAX], tmp[PATH_MAX]; - ssize_t len; - int fd; + char *home, *path = NULL, *tmp = NULL; + size_t home_len, path_len; + int fd, len; /* * try to load the cookie @@ -255,7 +257,13 @@ aucat_mkcookie(unsigned char *cookie) home = issetugid() ? NULL : getenv("HOME"); if (home == NULL) goto bad_gen; - snprintf(path, PATH_MAX, "%s/.aucat_cookie", home); + home_len = strlen(home); + path = malloc(home_len + sizeof(COOKIE_SUFFIX)); + if (path == NULL) + goto bad_gen; + memcpy(path, home, home_len); + memcpy(path + home_len, COOKIE_SUFFIX, sizeof(COOKIE_SUFFIX)); + path_len = home_len + sizeof(COOKIE_SUFFIX) - 1; fd = open(path, O_RDONLY); if (fd < 0) { if (errno != ENOENT) @@ -280,7 +288,7 @@ aucat_mkcookie(unsigned char *cookie) goto bad_close; } close(fd); - return 1; + goto done; bad_close: close(fd); bad_gen: @@ -290,36 +298,44 @@ bad_gen: #ifdef HAVE_ARC4RANDOM arc4random_buf(cookie, AMSG_COOKIELEN); #else - if (!random_bytes(cookie, AMSG_COOKIELEN)) + if (!random_bytes(cookie, AMSG_COOKIELEN)) { + if (path) + free(path); return 0; + } #endif /* * try to save the cookie */ if (home == NULL) - return 1; - if (strlcpy(tmp, path, PATH_MAX) >= PATH_MAX || - strlcat(tmp, ".XXXXXXXX", PATH_MAX) >= PATH_MAX) { - DPRINTF("%s: too long\n", path); - return 1; - } + goto done; + tmp = malloc(path_len + sizeof(TEMPL_SUFFIX)); + if (tmp == NULL) + goto done; + memcpy(tmp, path, path_len); + memcpy(tmp + path_len, TEMPL_SUFFIX, sizeof(TEMPL_SUFFIX)); fd = mkstemp(tmp); if (fd < 0) { DPERROR(tmp); - return 1; + goto done; } if (write(fd, cookie, AMSG_COOKIELEN) < 0) { DPERROR(tmp); unlink(tmp); close(fd); - return 1; + goto done; } close(fd); if (rename(tmp, path) < 0) { DPERROR(tmp); unlink(tmp); } +done: + if (tmp) + free(tmp); + if (path) + free(path); return 1; } @@ -381,7 +397,7 @@ aucat_connect_un(struct aucat *hdl, unsigned int unit) uid = geteuid(); snprintf(ca.sun_path, sizeof(ca.sun_path), - "/tmp/aucat-%u/%s%u", uid, AUCAT_PATH, unit); + SOCKPATH_DIR "-%u/" SOCKPATH_FILE "%u", uid, unit); ca.sun_family = AF_UNIX; s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); if (s < 0) @@ -392,7 +408,7 @@ aucat_connect_un(struct aucat *hdl, unsigned int unit) DPERROR(ca.sun_path); /* try shared server */ snprintf(ca.sun_path, sizeof(ca.sun_path), - "/tmp/aucat/%s%u", AUCAT_PATH, unit); + SOCKPATH_DIR "/" SOCKPATH_FILE "%u", unit); while (connect(s, (struct sockaddr *)&ca, len) < 0) { if (errno == EINTR) continue; diff --git a/libsndio/debug.c b/libsndio/debug.c index c02508c..eebf2bc 100644 --- a/libsndio/debug.c +++ b/libsndio/debug.c @@ -54,3 +54,27 @@ _sndio_parsetype(const char *str, char *type) return NULL; return str; } + +const char * +_sndio_parsenum(const char *str, unsigned int *num, unsigned int max) +{ + const char *p = str; + unsigned int dig, maxq, maxr, val; + + val = 0; + maxq = max / 10; + maxr = max % 10; + for (;;) { + dig = *p - '0'; + if (dig >= 10) + break; + if (val > maxq || (val == maxq && dig > maxr)) + return NULL; + val = val * 10 + dig; + p++; + } + if (p == str) + return NULL; + *num = val; + return p; +} diff --git a/libsndio/debug.h b/libsndio/debug.h index 7594784..2433ace 100644 --- a/libsndio/debug.h +++ b/libsndio/debug.h @@ -22,7 +22,7 @@ #define DPRINTFN(n, ...) \ do { \ - if (_sndio_debug >= (n)) \ + if (_sndio_debug >= (n)) \ fprintf(stderr, __VA_ARGS__); \ } while(0) @@ -47,5 +47,6 @@ extern int _sndio_debug; #endif const char *_sndio_parsetype(const char *, char *); +const char *_sndio_parsenum(const char *, unsigned int *, unsigned int); #endif diff --git a/libsndio/mio_alsa.c b/libsndio/mio_alsa.c index b88ba9a..fa74d4a 100644 --- a/libsndio/mio_alsa.c +++ b/libsndio/mio_alsa.c @@ -31,6 +31,8 @@ #include "debug.h" #include "mio_priv.h" +#define DEVNAME_PREFIX "hw:" + #ifdef DEBUG static snd_output_t *output = NULL; #define DALSA(str, err) fprintf(stderr, "%s: %s\n", str, snd_strerror(err)) @@ -40,6 +42,7 @@ static snd_output_t *output = NULL; struct mio_alsa_hdl { struct mio_hdl mio; + char *devname; snd_rawmidi_t *in, *out; int infds, onfds, nfds, events; }; @@ -64,7 +67,7 @@ struct mio_hdl * mio_alsa_open(const char *str, unsigned int mode, int nbio) { struct mio_alsa_hdl *hdl; - char path[PATH_MAX]; + size_t len; int rc; switch (*str) { @@ -84,11 +87,20 @@ mio_alsa_open(const char *str, unsigned int mode, int nbio) if (rc < 0) DALSA("couldn't attach to stderr", rc); #endif - snprintf(path, sizeof(path), "hw:%s", str); + len = strlen(str); + hdl->devname = malloc(len + sizeof(DEVNAME_PREFIX)); + if (hdl->devname == NULL) { + free(hdl); + return NULL; + } + memcpy(hdl->devname, DEVNAME_PREFIX, sizeof(DEVNAME_PREFIX) - 1); + memcpy(hdl->devname + sizeof(DEVNAME_PREFIX) - 1, str, len + 1); hdl->in = hdl->out = NULL; - rc = snd_rawmidi_open(&hdl->in, &hdl->out, path, SND_RAWMIDI_NONBLOCK); + rc = snd_rawmidi_open(&hdl->in, &hdl->out, + hdl->devname, SND_RAWMIDI_NONBLOCK); if (rc) { DALSA("could't open port", rc); + free(hdl->devname); free(hdl); return NULL; } @@ -111,6 +123,7 @@ mio_alsa_close(struct mio_hdl *sh) snd_rawmidi_drain(hdl->out); snd_rawmidi_close(hdl->out); } + free(hdl->devname); free(hdl); } diff --git a/libsndio/mio_rmidi.c b/libsndio/mio_rmidi.c index 7020f73..6d88976 100644 --- a/libsndio/mio_rmidi.c +++ b/libsndio/mio_rmidi.c @@ -30,6 +30,11 @@ #include "debug.h" #include "mio_priv.h" +#define DEVPATH_PREFIX "/dev/rmidi" +#define DEVPATH_MAX (1 + \ + sizeof(DEVPATH_PREFIX) - 1 + \ + sizeof(int) * 3) + struct mio_rmidi_hdl { struct mio_hdl mio; int fd; @@ -56,22 +61,27 @@ _mio_rmidi_open(const char *str, unsigned int mode, int nbio) { int fd, flags; struct mio_rmidi_hdl *hdl; - char path[PATH_MAX]; + char path[DEVPATH_MAX]; + unsigned int devnum; switch (*str) { case '/': str++; break; default: - DPRINTF("_sio_sun_open: %s: '/' expected\n", str); + DPRINTF("_mio_rmidi_open: %s: '/' expected\n", str); + return NULL; + } + str = _sndio_parsenum(str, &devnum, 255); + if (str == NULL || *str != '\0') { + DPRINTF("_mio_rmidi_open: can't determine device number\n"); return NULL; } hdl = malloc(sizeof(struct mio_rmidi_hdl)); if (hdl == NULL) return NULL; _mio_create(&hdl->mio, &mio_rmidi_ops, mode, nbio); - - snprintf(path, sizeof(path), "/dev/rmidi%s", str); + snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum); if (mode == (MIO_OUT | MIO_IN)) flags = O_RDWR; else diff --git a/libsndio/sio_alsa.c b/libsndio/sio_alsa.c index 29e1696..66b858f 100644 --- a/libsndio/sio_alsa.c +++ b/libsndio/sio_alsa.c @@ -35,6 +35,8 @@ #include "sio_priv.h" #include "bsd-compat.h" +#define DEVNAME_PREFIX "hw:" + #ifdef DEBUG static snd_output_t *output = NULL; #define DALSA(str, err) fprintf(stderr, "%s: %s\n", str, snd_strerror(err)) @@ -45,6 +47,7 @@ static snd_output_t *output = NULL; struct sio_alsa_hdl { struct sio_hdl sio; struct sio_par par; + char *devname; snd_pcm_t *opcm; snd_pcm_t *ipcm; unsigned ibpf, obpf; /* bytes per frame */ @@ -273,8 +276,8 @@ struct sio_hdl * _sio_alsa_open(const char *str, unsigned mode, int nbio) { struct sio_alsa_hdl *hdl; - char path[PATH_MAX]; struct sio_par par; + size_t len; int err; switch (*str) { @@ -282,7 +285,7 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio) str++; break; default: - DPRINTF("_sio_sun_open: %s: '/' expected\n", str); + DPRINTF("_sio_alsa_open: %s: '/' expected\n", str); return NULL; } hdl = malloc(sizeof(struct sio_alsa_hdl)); @@ -295,10 +298,14 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio) if (err < 0) DALSA("couldn't attach to stderr", err); #endif - - snprintf(path, sizeof(path), "hw:%s", str); + len = strlen(str); + hdl->devname = malloc(len + sizeof(DEVNAME_PREFIX)); + if (hdl->devname == NULL) + goto bad_free_hdl; + memcpy(hdl->devname, DEVNAME_PREFIX, sizeof(DEVNAME_PREFIX) - 1); + memcpy(hdl->devname + sizeof(DEVNAME_PREFIX) - 1, str, len + 1); if (mode & SIO_PLAY) { - err = snd_pcm_open(&hdl->opcm, path, + err = snd_pcm_open(&hdl->opcm, hdl->devname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (err < 0) { DALSA("couldn't open play stream", err); @@ -306,7 +313,7 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio) } } if (mode & SIO_REC) { - err = snd_pcm_open(&hdl->ipcm, path, + err = snd_pcm_open(&hdl->ipcm, hdl->devname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); if (err < 0) { DALSA("couldn't open rec stream", err); @@ -345,6 +352,8 @@ bad_free_opcm: if (mode & SIO_PLAY) snd_pcm_close(hdl->opcm); bad_free: + free(hdl->devname); +bad_free_hdl: free(hdl); return NULL; } @@ -358,6 +367,7 @@ sio_alsa_close(struct sio_hdl *sh) snd_pcm_close(hdl->opcm); if (hdl->sio.mode & SIO_REC) snd_pcm_close(hdl->ipcm); + free(hdl->devname); free(hdl); } diff --git a/libsndio/sio_sun.c b/libsndio/sio_sun.c index db44f3c..db32661 100644 --- a/libsndio/sio_sun.c +++ b/libsndio/sio_sun.c @@ -34,6 +34,11 @@ #include "sio_priv.h" #include "bsd-compat.h" +#define DEVPATH_PREFIX "/dev/audio" +#define DEVPATH_MAX (1 + \ + sizeof(DEVPATH_PREFIX) - 1 + \ + sizeof(int) * 3) + struct sio_sun_hdl { struct sio_hdl sio; int fd; @@ -332,7 +337,8 @@ _sio_sun_open(const char *str, unsigned int mode, int nbio) struct audio_info aui; struct sio_sun_hdl *hdl; struct sio_par par; - char path[PATH_MAX]; + char path[DEVPATH_MAX]; + unsigned int devnum; switch (*str) { case '/': @@ -342,12 +348,17 @@ _sio_sun_open(const char *str, unsigned int mode, int nbio) DPRINTF("_sio_sun_open: %s: '/' expected\n", str); return NULL; } + str = _sndio_parsenum(str, &devnum, 255); + if (str == NULL || *str != '\0') { + DPRINTF("_sio_sun_open: can't determine device number\n"); + return NULL; + } hdl = malloc(sizeof(struct sio_sun_hdl)); if (hdl == NULL) return NULL; _sio_create(&hdl->sio, &sio_sun_ops, mode, nbio); - snprintf(path, sizeof(path), "/dev/audio%s", str); + snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum); if (mode == (SIO_PLAY | SIO_REC)) flags = O_RDWR; else From 8575b870d1414e696b7165a371955a36abe9e4b6 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 2 Oct 2015 15:05:43 +0200 Subject: [PATCH 015/117] spacing --- sndiod/sock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sndiod/sock.h b/sndiod/sock.h index dbf27f3..3cda405 100644 --- a/sndiod/sock.h +++ b/sndiod/sock.h @@ -50,7 +50,7 @@ struct sock { #define SOCK_START 3 /* filling play buffers */ #define SOCK_STOP 4 /* draining rec buffers */ unsigned int pstate; /* one of the above */ - int tickpending; /* tick waiting to be transmitted */ + int tickpending; /* tick waiting to be transmitted */ int fillpending; /* flowctl waiting to be transmitted */ int stoppending; /* last STOP ack to be sent */ unsigned int walign; /* align written data to this */ From 4d72d01c2c14238c54f86d79421c9d91a0c4135b Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 20 Oct 2015 09:11:34 +0200 Subject: [PATCH 016/117] remove unnecessary macros from michael reed --- aucat/aucat.1 | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/aucat/aucat.1 b/aucat/aucat.1 index dab4e91..77985b4 100644 --- a/aucat/aucat.1 +++ b/aucat/aucat.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD$ +.\" $OpenBSD: aucat.1,v 1.110 2015/10/17 21:11:42 jmc Exp $ .\" .\" Copyright (c) 2006 Alexandre Ratchov .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate$ +.Dd $Mdocdate: October 17 2015 $ .Dt AUCAT 1 .Os .Sh NAME @@ -22,7 +22,6 @@ .Nd audio files manipulation tool .Sh SYNOPSIS .Nm aucat -.Bk -words .Op Fl dn .Op Fl b Ar size .Op Fl c Ar min : Ns Ar max @@ -35,7 +34,6 @@ .Op Fl q Ar port .Op Fl r Ar rate .Op Fl v Ar volume -.Ek .Sh DESCRIPTION The .Nm @@ -78,9 +76,7 @@ The options are as follows: .It Fl b Ar size The buffer size of the audio device in frames. Default is 7680. -.It Xo -.Fl c Ar min : Ns Ar max -.Xc +.It Fl c Ar min : Ns Ar max The range of audio file channel numbers. The default is .Cm 0:1 , @@ -124,16 +120,17 @@ Default is .It Fl h Ar fmt Audio file type. The following file types are supported: -.Bl -tag -width auto -.It Ar raw +.Pp +.Bl -tag -width auto -compact +.It Cm raw Headerless file. -.It Ar wav +.It Cm wav Microsoft WAV file format. -.It Ar aiff +.It Cm aiff Apple's audio interchange file format. -.It Ar au +.It Cm au Sun/NeXT audio file format. -.It Ar auto +.It Cm auto Try to guess, depending on the file name. This is the default. .El From bbfde0362153e505476403bba2966f1160508d06 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 20 Oct 2015 09:15:09 +0200 Subject: [PATCH 017/117] please gcc --- libsndio/aucat.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsndio/aucat.c b/libsndio/aucat.c index c6a3ac2..40c7a0d 100644 --- a/libsndio/aucat.c +++ b/libsndio/aucat.c @@ -251,6 +251,9 @@ aucat_mkcookie(unsigned char *cookie) size_t home_len, path_len; int fd, len; + /* please gcc */ + path_len = 0xdeadbeef; + /* * try to load the cookie */ From 56540a0d18af2373a84807ad9562a01e139e4e36 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 20 Oct 2015 09:16:31 +0200 Subject: [PATCH 018/117] unexpand $OpenBSD$ --- aucat/aucat.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aucat/aucat.1 b/aucat/aucat.1 index 77985b4..fea552f 100644 --- a/aucat/aucat.1 +++ b/aucat/aucat.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: aucat.1,v 1.110 2015/10/17 21:11:42 jmc Exp $ +.\" $OpenBSD$ .\" .\" Copyright (c) 2006 Alexandre Ratchov .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: October 17 2015 $ +.Dd $Mdocdate$ .Dt AUCAT 1 .Os .Sh NAME From 8bb88f248ff8780b0432ad9bee76e6bc982c0388 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 20 Oct 2015 15:25:54 +0200 Subject: [PATCH 019/117] if no -f or -q are used, attach rsnd/[0-3] and rmidi/[0-7] --- libsndio/sndio.7 | 2 +- sndiod/dev.c | 3 ++- sndiod/midi.c | 3 ++- sndiod/sndiod.1 | 23 ++++++++--------------- sndiod/sndiod.c | 46 ++++++++++++++++++++++++++++++++++------------ 5 files changed, 47 insertions(+), 30 deletions(-) diff --git a/libsndio/sndio.7 b/libsndio/sndio.7 index e5cb53c..c37ff74 100644 --- a/libsndio/sndio.7 +++ b/libsndio/sndio.7 @@ -120,7 +120,7 @@ the character device minor number. For audio devices or MIDI ports created with .Xr sndiod 1 it corresponds to the number of the corresponding -.Fl fM +.Fl fq option on the command line. .It Pa option Corresponds to the sub-device string registered using the diff --git a/sndiod/dev.c b/sndiod/dev.c index c3d21bd..9dc032f 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -977,6 +977,7 @@ dev_new(char *path, struct aparams *par, return NULL; } d = xmalloc(sizeof(struct dev)); + d->path = xstrdup(path); d->num = dev_sndnum++; /* @@ -988,7 +989,6 @@ dev_new(char *path, struct aparams *par, */ d->midi = midi_new(&dev_midiops, d, MODE_MIDIIN | MODE_MIDIOUT); midi_tag(d->midi, d->num); - d->path = path; d->reqpar = *par; d->reqmode = mode; d->reqpchan = d->reqrchan = 0; @@ -1257,6 +1257,7 @@ dev_del(struct dev *d) } midi_del(d->midi); *p = d->next; + xfree(d->path); xfree(d); } diff --git a/sndiod/midi.c b/sndiod/midi.c index a52a77b..ac055a2 100644 --- a/sndiod/midi.c +++ b/sndiod/midi.c @@ -430,7 +430,7 @@ port_new(char *path, unsigned int mode, int hold) struct port *c, **pc; c = xmalloc(sizeof(struct port)); - c->path = path; + c->path = xstrdup(path); c->state = PORT_CFG; c->hold = hold; c->midi = midi_new(&port_midiops, c, mode); @@ -462,6 +462,7 @@ port_del(struct port *c) #endif } *p = c->next; + xfree(c->path); xfree(c); } diff --git a/sndiod/sndiod.1 b/sndiod/sndiod.1 index 97a6268..fd15e86 100644 --- a/sndiod/sndiod.1 +++ b/sndiod/sndiod.1 @@ -350,29 +350,22 @@ to which they are attached. .Pp If no audio devices .Pq Fl f -are specified, -settings are applied as if -the default device is specified. +are specified, first 4 audio devices are added and +settings are applied to all of them. +Similarly, if no MIDI ports +.Pq Fl q +are specified, first 8 MIDI ports are added and +settings are applied to all of them. If no sub-devices .Pq Fl s are specified for a device, a default sub-device is created attached to it. -If a device -.Pq Fl f +If a device or MIDI port +.Pq Fl fq is defined twice, both definitions are merged: parameters of the first one are used but sub-devices .Pq Fl s of both definitions are created. -The default -.Xr sndio 7 -device used by -.Nm -is -.Pa rsnd/0 , -and the default sub-device exposed by -.Nm -is -.Pa snd/0 . .Pp If .Nm diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index f3e2d1d..12685f2 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -314,6 +314,21 @@ mkdev(char *path, struct aparams *par, return d; } +struct port * +mkport(char *path, int hold) +{ + struct port *c; + + for (c = port_list; c != NULL; c = c->next) { + if (strcmp(c->path, path) == 0) + return c; + } + c = port_new(path, MODE_MIDIMASK, hold); + if (c == NULL) + exit(1); + return c; +} + struct opt * mkopt(char *path, struct dev *d, int pmin, int pmax, int rmin, int rmax, @@ -335,7 +350,8 @@ main(int argc, char **argv) int c, background, unit; int pmin, pmax, rmin, rmax; char base[SOCKPATH_MAX], path[SOCKPATH_MAX]; - unsigned int mode, dup, mmc, vol; + char loc[32]; + unsigned int mode, dup, mmc, vol, i; unsigned int hold, autovol, bufsz, round, rate; const char *str; struct aparams par; @@ -414,16 +430,14 @@ main(int argc, char **argv) break; case 's': if ((d = dev_list) == NULL) { - d = mkdev(DEFAULT_DEV, &par, 0, bufsz, round, rate, - hold, autovol); + d = mkdev(DEFAULT_DEV, &par, 0, bufsz, round, + rate, hold, autovol); } mkopt(optarg, d, pmin, pmax, rmin, rmax, mode, vol, mmc, dup); break; case 'q': - p = port_new(optarg, MODE_MIDIMASK, hold); - if (!p) - errx(1, "%s: can't open port", optarg); + mkport(optarg, hold); break; case 'a': hold = opt_onoff(); @@ -442,10 +456,8 @@ main(int argc, char **argv) errx(1, "%s: block size is %s", optarg, str); break; case 'f': - mkdev(optarg, &par, 0, bufsz, round, rate, hold, autovol); - break; - case 'M': - /* XXX: for compatibility with aucat, remove this */ + mkdev(optarg, &par, 0, bufsz, round, + rate, hold, autovol); break; default: fputs(usagestr, stderr); @@ -458,8 +470,18 @@ main(int argc, char **argv) fputs(usagestr, stderr); return 1; } - if (dev_list == NULL) - mkdev(DEFAULT_DEV, &par, 0, bufsz, round, rate, hold, autovol); + if (dev_list == NULL) { + for (i = 0; i < 4; i++) { + snprintf(loc, sizeof(loc), "rsnd/%u", i); + mkdev(loc, &par, 0, bufsz, round, rate, hold, autovol); + } + } + if (port_list == NULL) { + for (i = 0; i < 8; i++) { + snprintf(loc, sizeof(loc), "rmidi/%u", i); + mkport(loc, hold); + } + } for (d = dev_list; d != NULL; d = d->next) { if (opt_byname("default", d->num)) continue; From 66ca92689ee547aede91571c387f00d10b145ee9 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 25 Nov 2015 20:46:03 +0100 Subject: [PATCH 020/117] stop mmc in dev_done, releasing ref to the device --- sndiod/dev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sndiod/dev.c b/sndiod/dev.c index 9dc032f..7720e39 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -1214,6 +1214,8 @@ dev_done(struct dev *d) log_puts(": draining\n"); } #endif + if (d->tstate != MMC_STOP) + dev_mmcstop(d); if (d->hold) dev_unref(d); } From a17c9dfc55e21f8a81aa1c6654edd97ccaf704d5 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 25 Nov 2015 20:47:52 +0100 Subject: [PATCH 021/117] missing prototype --- sndiod/sndiod.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index 12685f2..a8381ae 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -98,6 +98,7 @@ void unsetsig(void); void privdrop(void); struct dev *mkdev(char *, struct aparams *, int, int, int, int, int, int); +struct port *mkport(char *, int); struct opt *mkopt(char *, struct dev *, int, int, int, int, int, int, int, int); From d4cea96993875c44bda591ab53802e5e40a0601e Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 25 Nov 2015 20:48:47 +0100 Subject: [PATCH 022/117] use stored d->num, in search for devices --- sndiod/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sndiod/dev.c b/sndiod/dev.c index 7720e39..04da363 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -1226,7 +1226,7 @@ dev_bynum(int num) struct dev *d; for (d = dev_list; d != NULL; d = d->next) { - if (num-- == 0) + if (d->num == num) return d; } return NULL; From c8a50a21ea52b5768cc41cfa6fd25b95a2352bf1 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 25 Nov 2015 20:49:09 +0100 Subject: [PATCH 023/117] add port numbers --- sndiod/midi.c | 12 +++++------- sndiod/midi.h | 1 + 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/sndiod/midi.c b/sndiod/midi.c index ac055a2..cd2b41f 100644 --- a/sndiod/midi.c +++ b/sndiod/midi.c @@ -427,18 +427,16 @@ port_exit(void *arg) struct port * port_new(char *path, unsigned int mode, int hold) { - struct port *c, **pc; + struct port *c; c = xmalloc(sizeof(struct port)); c->path = xstrdup(path); c->state = PORT_CFG; c->hold = hold; c->midi = midi_new(&port_midiops, c, mode); - midi_portnum++; - for (pc = &port_list; *pc != NULL; pc = &(*pc)->next) - ; /* nothing */ - c->next = NULL; - *pc = c; + c->num = midi_portnum++; + c->next = port_list; + port_list = c; return c; } @@ -504,7 +502,7 @@ port_bynum(int num) struct port *p; for (p = port_list; p != NULL; p = p->next) { - if (num-- == 0) + if (p->num == num) return p; } return NULL; diff --git a/sndiod/midi.h b/sndiod/midi.h index b7daa62..5ef72de 100644 --- a/sndiod/midi.h +++ b/sndiod/midi.h @@ -87,6 +87,7 @@ struct port { #define PORT_INIT 1 #define PORT_DRAIN 2 unsigned int state; + unsigned int num; /* port serial number */ char *path; /* hold the port open ? */ int hold; struct midi *midi; From 276b44ece4a303e37e5f22fe8a5c5acf7b0ec973 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 25 Nov 2015 20:50:17 +0100 Subject: [PATCH 024/117] save & restore umask when creating socket dir --- sndiod/sndiod.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index a8381ae..e4cabae 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -257,7 +257,7 @@ getbasepath(char *base, size_t size) { uid_t uid; struct stat sb; - mode_t mask; + mode_t mask, omask; uid = geteuid(); if (uid == 0) { @@ -267,10 +267,12 @@ getbasepath(char *base, size_t size) mask = 077; snprintf(base, SOCKPATH_MAX, SOCKPATH_DIR "-%u", uid); } - if (mkdir(base, 0777 & ~mask) < 0) { + omask = umask(mask); + if (mkdir(base, 0777) < 0) { if (errno != EEXIST) err(1, "mkdir(\"%s\")", base); } + umask(omask); if (stat(base, &sb) < 0) err(1, "stat(\"%s\")", base); if (sb.st_uid != uid || (sb.st_mode & mask) != 0) From 3100560d0138084ada1c916091fa30305456a90c Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 25 Nov 2015 20:51:50 +0100 Subject: [PATCH 025/117] listen -> listen on; from Jan Stary --- sndiod/sndiod.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sndiod/sndiod.1 b/sndiod/sndiod.1 index fd15e86..5782f73 100644 --- a/sndiod/sndiod.1 +++ b/sndiod/sndiod.1 @@ -213,7 +213,7 @@ The default is .It Fl L Ar addr Specify a local network address .Nm -should listen; +should listen on; .Nm will listen on TCP port 11025+n, where n is the unit number specified with From 8e6aa1db1ff7acacb6a697bec22183aad324c5b4 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 25 Nov 2015 20:52:31 +0100 Subject: [PATCH 026/117] say -L is unencrypted --- sndiod/sndiod.1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sndiod/sndiod.1 b/sndiod/sndiod.1 index 5782f73..4f1c035 100644 --- a/sndiod/sndiod.1 +++ b/sndiod/sndiod.1 @@ -228,6 +228,9 @@ If the option argument is then .Nm will accept connections from any address. +As the communication is not secure, this +option is only suitable for local networks where all hosts +and users are trusted. .It Fl m Ar mode Set the sub-device mode. Valid modes are From a04c34288eda4783280585348baf7c2147918304 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 25 Nov 2015 20:54:22 +0100 Subject: [PATCH 027/117] define port_log() if no -DDEBUG is defined --- sndiod/midi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sndiod/midi.c b/sndiod/midi.c index cd2b41f..6c0bd34 100644 --- a/sndiod/midi.c +++ b/sndiod/midi.c @@ -376,13 +376,11 @@ midi_out(struct midi *oep, unsigned char *idata, int icount) } } -#ifdef DEBUG void port_log(struct port *p) { midi_log(p->midi); } -#endif void port_imsg(void *arg, unsigned char *msg, int size) From 7530bbf6d24df167709fcc41dc33831785cbb004 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 9 Dec 2015 11:13:11 +0100 Subject: [PATCH 028/117] Pass full device name to audio/midi backends. --- libsndio/aucat.c | 19 +++++++--- libsndio/aucat.h | 2 +- libsndio/mio.c | 31 +++++++--------- libsndio/mio_alsa.c | 18 ++++++--- libsndio/mio_aucat.c | 5 +-- libsndio/mio_priv.h | 4 +- libsndio/mio_rmidi.c | 69 ++++++++++++++++++++++++---------- libsndio/sio.c | 24 +++++------- libsndio/sio_alsa.c | 16 +++++--- libsndio/sio_aucat.c | 2 +- libsndio/sio_sun.c | 88 +++++++++++++++++++++++++------------------- 11 files changed, 166 insertions(+), 112 deletions(-) diff --git a/libsndio/aucat.c b/libsndio/aucat.c index 40c7a0d..7778f3a 100644 --- a/libsndio/aucat.c +++ b/libsndio/aucat.c @@ -468,15 +468,24 @@ parsestr(const char *str, char *rstr, unsigned int max) } int -_aucat_open(struct aucat *hdl, const char *str, unsigned int mode, - unsigned int type) +_aucat_open(struct aucat *hdl, const char *str, unsigned int mode) { extern char *__progname; int eof; char host[NI_MAXHOST], opt[AMSG_OPTMAX]; - const char *p = str; - unsigned int unit, devnum; + const char *p; + unsigned int unit, devnum, type; + if ((p = _sndio_parsetype(str, "snd")) != NULL) + type = 0; + else if ((p = _sndio_parsetype(str, "midithru")) != NULL) + type = 1; + else if ((p = _sndio_parsetype(str, "midi")) != NULL) + type = 2; + else { + DPRINTF("%s: unsupported device type\n", str); + return -1; + } if (*p == '@') { p = parsestr(++p, host, NI_MAXHOST); if (p == NULL) @@ -489,7 +498,7 @@ _aucat_open(struct aucat *hdl, const char *str, unsigned int mode, return 0; } else unit = 0; - if (*p != '/' && *p != ':') { + if (*p != '/') { DPRINTF("%s: '/' expected\n", str); return 0; } diff --git a/libsndio/aucat.h b/libsndio/aucat.h index 8c3966c..e9d8e69 100644 --- a/libsndio/aucat.h +++ b/libsndio/aucat.h @@ -21,7 +21,7 @@ int _aucat_rmsg(struct aucat *, int *); int _aucat_wmsg(struct aucat *, int *); size_t _aucat_rdata(struct aucat *, void *, size_t, int *); size_t _aucat_wdata(struct aucat *, const void *, size_t, unsigned, int *); -int _aucat_open(struct aucat *, const char *, unsigned, unsigned); +int _aucat_open(struct aucat *, const char *, unsigned); void _aucat_close(struct aucat *, int); int _aucat_pollfd(struct aucat *, struct pollfd *, int); int _aucat_revents(struct aucat *, struct pollfd *); diff --git a/libsndio/mio.c b/libsndio/mio.c index 6f4b7b5..0d8456f 100644 --- a/libsndio/mio.c +++ b/libsndio/mio.c @@ -36,7 +36,6 @@ mio_open(const char *str, unsigned int mode, int nbio) { static char portany[] = MIO_PORTANY; struct mio_hdl *hdl; - const char *p; #ifdef DEBUG _sndio_debug_init(); @@ -51,32 +50,28 @@ mio_open(const char *str, unsigned int mode, int nbio) str = portany; } if (strcmp(str, portany) == 0) { - hdl = _mio_aucat_open("/0", mode, nbio, 1); + hdl = _mio_aucat_open("midithru/0", mode, nbio); if (hdl != NULL) return hdl; #if defined(USE_RMIDI) - return _mio_rmidi_open("/0", mode, nbio); + return _mio_rmidi_open("rmidi/0", mode, nbio); #elif defined(USE_ALSA) - return mio_alsa_open("/0", mode, nbio); + return _mio_alsa_open("rmidi/0", mode, nbio); #else return NULL; #endif } - if ((p = _sndio_parsetype(str, "snd")) != NULL || - (p = _sndio_parsetype(str, "aucat")) != NULL) - return _mio_aucat_open(p, mode, nbio, 0); - if ((p = _sndio_parsetype(str, "midithru")) != NULL) - return _mio_aucat_open(p, mode, nbio, 1); - if ((p = _sndio_parsetype(str, "midi")) != NULL) - return _mio_aucat_open(p, mode, nbio, 2); -#if defined(USE_RMIDI) || defined(USE_ALSA) - if ((p = _sndio_parsetype(str, "rmidi")) != NULL) { -#if defined(USE_SUN) - return _mio_rmidi_open(p, mode, nbio); + if (_sndio_parsetype(str, "snd") || + _sndio_parsetype(str, "midithru") || + _sndio_parsetype(str, "midi")) + return _mio_aucat_open(str, mode, nbio); + if (_sndio_parsetype(str, "rmidi")) +#if defined(USE_RMIDI) + return _mio_rmidi_open(str, mode, nbio); #elif defined(USE_ALSA) - return mio_alsa_open(p, mode, nbio); -#endif - } + return _mio_alsa_open(str, mode, nbio); +#else + return NULL; #endif DPRINTF("mio_open: %s: unknown device type\n", str); return NULL; diff --git a/libsndio/mio_alsa.c b/libsndio/mio_alsa.c index fa74d4a..4753d72 100644 --- a/libsndio/mio_alsa.c +++ b/libsndio/mio_alsa.c @@ -64,18 +64,24 @@ static struct mio_ops mio_alsa_ops = { }; struct mio_hdl * -mio_alsa_open(const char *str, unsigned int mode, int nbio) +_mio_alsa_open(const char *_str, unsigned int mode, int nbio) { + const char *p; struct mio_alsa_hdl *hdl; size_t len; int rc; - switch (*str) { + p = _sndio_parsetype(_str, "rmidi"); + if (p == NULL) { + DPRINTF("_mio_alsa_open: %s: \"rsnd\" expected\n", _str); + return NULL; + } + switch (*p) { case '/': - str++; + p++; break; default: - DPRINTF("mio_alsa_open: %s: '/' expected\n", str); + DPRINTF("_mio_alsa_open: %s: '/' expected\n", _str); return NULL; } hdl = malloc(sizeof(struct mio_alsa_hdl)); @@ -87,14 +93,14 @@ mio_alsa_open(const char *str, unsigned int mode, int nbio) if (rc < 0) DALSA("couldn't attach to stderr", rc); #endif - len = strlen(str); + len = strlen(p); hdl->devname = malloc(len + sizeof(DEVNAME_PREFIX)); if (hdl->devname == NULL) { free(hdl); return NULL; } memcpy(hdl->devname, DEVNAME_PREFIX, sizeof(DEVNAME_PREFIX) - 1); - memcpy(hdl->devname + sizeof(DEVNAME_PREFIX) - 1, str, len + 1); + memcpy(hdl->devname + sizeof(DEVNAME_PREFIX) - 1, p, len + 1); hdl->in = hdl->out = NULL; rc = snd_rawmidi_open(&hdl->in, &hdl->out, hdl->devname, SND_RAWMIDI_NONBLOCK); diff --git a/libsndio/mio_aucat.c b/libsndio/mio_aucat.c index 00a164f..896e31b 100644 --- a/libsndio/mio_aucat.c +++ b/libsndio/mio_aucat.c @@ -85,15 +85,14 @@ mio_aucat_runmsg(struct mio_aucat_hdl *hdl) } struct mio_hdl * -_mio_aucat_open(const char *str, unsigned int mode, - int nbio, unsigned int type) +_mio_aucat_open(const char *str, unsigned int mode, int nbio) { struct mio_aucat_hdl *hdl; hdl = malloc(sizeof(struct mio_aucat_hdl)); if (hdl == NULL) return NULL; - if (!_aucat_open(&hdl->aucat, str, mode, type)) + if (!_aucat_open(&hdl->aucat, str, mode)) goto bad; _mio_create(&hdl->mio, &mio_aucat_ops, mode, nbio); if (!_aucat_setfl(&hdl->aucat, 1, &hdl->mio.eof)) diff --git a/libsndio/mio_priv.h b/libsndio/mio_priv.h index 546e63f..eaec4db 100644 --- a/libsndio/mio_priv.h +++ b/libsndio/mio_priv.h @@ -45,9 +45,9 @@ struct mio_ops { struct mio_hdl *_mio_rmidi_open(const char *, unsigned, int); #ifdef USE_ALSA -struct mio_hdl *mio_alsa_open(const char *, unsigned, int); +struct mio_hdl *_mio_alsa_open(const char *, unsigned, int); #endif -struct mio_hdl *_mio_aucat_open(const char *, unsigned, int, unsigned); +struct mio_hdl *_mio_aucat_open(const char *, unsigned, int); void _mio_create(struct mio_hdl *, struct mio_ops *, unsigned, int); void _mio_destroy(struct mio_hdl *); diff --git a/libsndio/mio_rmidi.c b/libsndio/mio_rmidi.c index 6d88976..9fd7a6f 100644 --- a/libsndio/mio_rmidi.c +++ b/libsndio/mio_rmidi.c @@ -15,6 +15,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef USE_RMIDI #include #include @@ -56,33 +57,34 @@ static struct mio_ops mio_rmidi_ops = { mio_rmidi_revents }; -struct mio_hdl * -_mio_rmidi_open(const char *str, unsigned int mode, int nbio) +static int +mio_rmidi_getfd(const char *str, unsigned int mode, int nbio) { - int fd, flags; - struct mio_rmidi_hdl *hdl; + const char *p; char path[DEVPATH_MAX]; unsigned int devnum; + int fd, flags; - switch (*str) { + p = _sndio_parsetype(str, "rmidi"); + if (p == NULL) { + DPRINTF("mio_rmidi_getfd: %s: \"rsnd\" expected\n", str); + return -1; + } + switch (*p) { case '/': - str++; + p++; break; default: - DPRINTF("_mio_rmidi_open: %s: '/' expected\n", str); - return NULL; + DPRINTF("mio_rmidi_getfd: %s: '/' expected\n", str); + return -1; } - str = _sndio_parsenum(str, &devnum, 255); - if (str == NULL || *str != '\0') { - DPRINTF("_mio_rmidi_open: can't determine device number\n"); - return NULL; + p = _sndio_parsenum(p, &devnum, 255); + if (p == NULL || *p != '\0') { + DPRINTF("mio_rmidi_getfd: %s: number expected after '/'\n", str); + return -1; } - hdl = malloc(sizeof(struct mio_rmidi_hdl)); - if (hdl == NULL) - return NULL; - _mio_create(&hdl->mio, &mio_rmidi_ops, mode, nbio); snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum); - if (mode == (MIO_OUT | MIO_IN)) + if (mode == (MIO_IN | MIO_OUT)) flags = O_RDWR; else flags = (mode & MIO_OUT) ? O_WRONLY : O_RDONLY; @@ -90,12 +92,38 @@ _mio_rmidi_open(const char *str, unsigned int mode, int nbio) if (errno == EINTR) continue; DPERROR(path); - goto bad_free; + return -1; } + return fd; +} + +static struct mio_hdl * +mio_rmidi_fdopen(int fd, unsigned int mode, int nbio) +{ + struct mio_rmidi_hdl *hdl; + + hdl = malloc(sizeof(struct mio_rmidi_hdl)); + if (hdl == NULL) + return NULL; + _mio_create(&hdl->mio, &mio_rmidi_ops, mode, nbio); hdl->fd = fd; return (struct mio_hdl *)hdl; - bad_free: - free(hdl); +} + +struct mio_hdl * +_mio_rmidi_open(const char *str, unsigned int mode, int nbio) +{ + struct mio_hdl *hdl; + int fd; + + fd = mio_rmidi_getfd(str, mode, nbio); + if (fd < 0) + return NULL; + hdl = mio_rmidi_fdopen(fd, mode, nbio); + if (hdl != NULL) + return hdl; + while (close(fd) < 0 && errno == EINTR) + ; /* retry */ return NULL; } @@ -173,3 +201,4 @@ mio_rmidi_revents(struct mio_hdl *sh, struct pollfd *pfd) { return pfd->revents; } +#endif /* defined USE_RMIDI */ diff --git a/libsndio/sio.c b/libsndio/sio.c index f582048..415530e 100644 --- a/libsndio/sio.c +++ b/libsndio/sio.c @@ -45,7 +45,6 @@ sio_open(const char *str, unsigned int mode, int nbio) { static char devany[] = SIO_DEVANY; struct sio_hdl *hdl; - const char *p; #ifdef DEBUG _sndio_debug_init(); @@ -60,29 +59,26 @@ sio_open(const char *str, unsigned int mode, int nbio) str = devany; } if (strcmp(str, devany) == 0) { - hdl = _sio_aucat_open("/0", mode, nbio); + hdl = _sio_aucat_open("snd/0", mode, nbio); if (hdl != NULL) return hdl; #if defined(USE_SUN) - return _sio_sun_open("/0", mode, nbio); + return _sio_sun_open("rsnd/0", mode, nbio); #elif defined(USE_ALSA) - return _sio_alsa_open("/0", mode, nbio); + return _sio_alsa_open("rsnd/0", mode, nbio); #else return NULL; #endif } - if ((p = _sndio_parsetype(str, "snd")) != NULL || - (p = _sndio_parsetype(str, "aucat")) != NULL) - return _sio_aucat_open(p, mode, nbio); -#if defined(USE_ALSA) || defined(USE_SUN) - if ((p = _sndio_parsetype(str, "rsnd")) != NULL || - (p = _sndio_parsetype(str, "sun")) != NULL) { + if (_sndio_parsetype(str, "snd")) + return _sio_aucat_open(str, mode, nbio); + if (_sndio_parsetype(str, "rsnd")) #if defined(USE_SUN) - return _sio_sun_open(p, mode, nbio); + return _sio_sun_open(str, mode, nbio); #elif defined(USE_ALSA) - return _sio_alsa_open(p, mode, nbio); -#endif - } + return _sio_alsa_open(str, mode, nbio); +#else + return NULL; #endif DPRINTF("sio_open: %s: unknown device type\n", str); return NULL; diff --git a/libsndio/sio_alsa.c b/libsndio/sio_alsa.c index 66b858f..2697a51 100644 --- a/libsndio/sio_alsa.c +++ b/libsndio/sio_alsa.c @@ -275,17 +275,23 @@ sio_alsa_enctofmt(struct sio_alsa_hdl *hdl, snd_pcm_format_t *rfmt, struct sio_hdl * _sio_alsa_open(const char *str, unsigned mode, int nbio) { + const char *p; struct sio_alsa_hdl *hdl; struct sio_par par; size_t len; int err; - switch (*str) { + p = _sndio_parsetype(str, "rsnd"); + if (p == NULL) { + DPRINTF("_sio_alsa_open: %s: \"rsnd\" expected\n", str); + return NULL; + } + switch (*p) { case '/': - str++; + p++; break; default: - DPRINTF("_sio_alsa_open: %s: '/' expected\n", str); + DPRINTF("_sio_alsa_open: %s: '/' expected\n", str); return NULL; } hdl = malloc(sizeof(struct sio_alsa_hdl)); @@ -298,12 +304,12 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio) if (err < 0) DALSA("couldn't attach to stderr", err); #endif - len = strlen(str); + len = strlen(p); hdl->devname = malloc(len + sizeof(DEVNAME_PREFIX)); if (hdl->devname == NULL) goto bad_free_hdl; memcpy(hdl->devname, DEVNAME_PREFIX, sizeof(DEVNAME_PREFIX) - 1); - memcpy(hdl->devname + sizeof(DEVNAME_PREFIX) - 1, str, len + 1); + memcpy(hdl->devname + sizeof(DEVNAME_PREFIX) - 1, p, len + 1); if (mode & SIO_PLAY) { err = snd_pcm_open(&hdl->opcm, hdl->devname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); diff --git a/libsndio/sio_aucat.c b/libsndio/sio_aucat.c index c64f2f5..54bc58c 100644 --- a/libsndio/sio_aucat.c +++ b/libsndio/sio_aucat.c @@ -156,7 +156,7 @@ _sio_aucat_open(const char *str, unsigned int mode, int nbio) hdl = malloc(sizeof(struct sio_aucat_hdl)); if (hdl == NULL) return NULL; - if (!_aucat_open(&hdl->aucat, str, mode, 0)) { + if (!_aucat_open(&hdl->aucat, str, mode)) { free(hdl); return NULL; } diff --git a/libsndio/sio_sun.c b/libsndio/sio_sun.c index db32661..4d3f750 100644 --- a/libsndio/sio_sun.c +++ b/libsndio/sio_sun.c @@ -330,46 +330,57 @@ sio_sun_getcap(struct sio_hdl *sh, struct sio_cap *cap) #undef NRATES } -struct sio_hdl * -_sio_sun_open(const char *str, unsigned int mode, int nbio) +static int +sio_sun_getfd(const char *str, unsigned int mode, int nbio) { - int fd, flags, fullduplex; - struct audio_info aui; - struct sio_sun_hdl *hdl; - struct sio_par par; + const char *p; char path[DEVPATH_MAX]; unsigned int devnum; + int fd, flags; - switch (*str) { + p = _sndio_parsetype(str, "rsnd"); + if (p == NULL) { + DPRINTF("sio_sun_getfd: %s: \"rsnd\" expected\n", str); + return -1; + } + switch (*p) { case '/': - str++; + p++; break; default: - DPRINTF("_sio_sun_open: %s: '/' expected\n", str); - return NULL; + DPRINTF("sio_sun_getfd: %s: '/' expected\n", str); + return -1; } - str = _sndio_parsenum(str, &devnum, 255); - if (str == NULL || *str != '\0') { - DPRINTF("_sio_sun_open: can't determine device number\n"); - return NULL; + p = _sndio_parsenum(p, &devnum, 255); + if (p == NULL || *p != '\0') { + DPRINTF("sio_sun_getfd: %s: number expected after '/'\n", str); + return -1; } - hdl = malloc(sizeof(struct sio_sun_hdl)); - if (hdl == NULL) - return NULL; - _sio_create(&hdl->sio, &sio_sun_ops, mode, nbio); - snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum); if (mode == (SIO_PLAY | SIO_REC)) flags = O_RDWR; else flags = (mode & SIO_PLAY) ? O_WRONLY : O_RDONLY; - while ((fd = open(path, flags | O_NONBLOCK | O_CLOEXEC)) < 0) { if (errno == EINTR) continue; DPERROR(path); - goto bad_free; + return -1; } + return fd; +} + +static struct sio_hdl * +sio_sun_fdopen(int fd, unsigned int mode, int nbio) +{ + struct audio_info aui; + struct sio_sun_hdl *hdl; + struct sio_par par; + + hdl = malloc(sizeof(struct sio_sun_hdl)); + if (hdl == NULL) + return NULL; + _sio_create(&hdl->sio, &sio_sun_ops, mode, nbio); /* * pause the device @@ -381,18 +392,7 @@ _sio_sun_open(const char *str, unsigned int mode, int nbio) aui.record.pause = 1; if (ioctl(fd, AUDIO_SETINFO, &aui) < 0) { DPERROR("sio_open_sun: setinfo"); - goto bad_close; - } - /* - * If both play and record are requested then - * set full duplex mode. - */ - if (mode == (SIO_PLAY | SIO_REC)) { - fullduplex = 1; - if (ioctl(fd, AUDIO_SETFD, &fullduplex) < 0) { - DPRINTF("sio_open_sun: %s: can't set full-duplex\n", path); - goto bad_close; - } + goto bad_free; } hdl->fd = fd; @@ -410,16 +410,30 @@ _sio_sun_open(const char *str, unsigned int mode, int nbio) par.bits = 16; par.appbufsz = 1200; if (!sio_setpar(&hdl->sio, &par)) - goto bad_close; + goto bad_free; return (struct sio_hdl *)hdl; - bad_close: - while (close(fd) < 0 && errno == EINTR) - ; /* retry */ bad_free: free(hdl); return NULL; } +struct sio_hdl * +_sio_sun_open(const char *str, unsigned int mode, int nbio) +{ + struct sio_hdl *hdl; + int fd; + + fd = sio_sun_getfd(str, mode, nbio); + if (fd < 0) + return NULL; + hdl = sio_sun_fdopen(fd, mode, nbio); + if (hdl != NULL) + return hdl; + while (close(fd) < 0 && errno == EINTR) + ; /* retry */ + return NULL; +} + static void sio_sun_close(struct sio_hdl *sh) { From 91166d3abff62afdc6924b849b2adab8adbab7bb Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 9 Dec 2015 11:16:35 +0100 Subject: [PATCH 029/117] remove -M from getopt() string --- sndiod/sndiod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index e4cabae..2ece5a9 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -387,7 +387,7 @@ main(int argc, char **argv) setsig(); filelist_init(); - while ((c = getopt(argc, argv, "a:b:c:C:de:f:j:L:m:Mq:r:s:t:U:v:w:x:z:")) != -1) { + while ((c = getopt(argc, argv, "a:b:c:C:de:f:j:L:m:q:r:s:t:U:v:w:x:z:")) != -1) { switch (c) { case 'd': log_level++; From fc179fb0c0fbb0a5631764f538f590d1468ed183 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 9 Dec 2015 11:23:55 +0100 Subject: [PATCH 030/117] inline privdrop() --- sndiod/sndiod.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index 2ece5a9..19a32f5 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -95,7 +95,6 @@ unsigned int opt_mode(void); void getbasepath(char *, size_t); void setsig(void); void unsetsig(void); -void privdrop(void); struct dev *mkdev(char *, struct aparams *, int, int, int, int, int, int); struct port *mkport(char *, int); @@ -279,21 +278,6 @@ getbasepath(char *base, size_t size) errx(1, "%s has wrong permissions", base); } -void -privdrop(void) -{ - struct passwd *pw; - - if ((pw = getpwnam(SNDIO_USER)) == NULL) - errx(1, "unknown user %s", SNDIO_USER); - if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) < 0) - err(1, "setpriority"); - if (setgroups(1, &pw->pw_gid) || - setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || - setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) - err(1, "cannot drop privileges"); -} - struct dev * mkdev(char *path, struct aparams *par, int mode, int bufsz, int round, int rate, int hold, int autovol) @@ -361,6 +345,7 @@ main(int argc, char **argv) struct dev *d; struct port *p; struct listen *l; + struct passwd *pw; atexit(log_flush); @@ -494,8 +479,16 @@ main(int argc, char **argv) getbasepath(base, sizeof(base)); snprintf(path, SOCKPATH_MAX, "%s/" SOCKPATH_FILE "%u", base, unit); listen_new_un(path); - if (geteuid() == 0) - privdrop(); + if (geteuid() == 0) { + if ((pw = getpwnam(SNDIO_USER)) == NULL) + errx(1, "unknown user %s", SNDIO_USER); + if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) < 0) + err(1, "setpriority"); + if (setgroups(1, &pw->pw_gid) || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) + err(1, "cannot drop privileges"); + } midi_init(); for (p = port_list; p != NULL; p = p->next) { if (!port_init(p)) @@ -515,10 +508,6 @@ main(int argc, char **argv) if (daemon(0, 0) < 0) err(1, "daemon"); } - - /* - * Loop, start audio. - */ for (;;) { if (quit_flag) break; @@ -542,8 +531,8 @@ main(int argc, char **argv) dev_del(dev_list); while (port_list) port_del(port_list); - filelist_done(); rmdir(base); + filelist_done(); unsetsig(); return 0; } From 2327821cf00cb0723cddfde7cc3c8a0191d22f41 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 9 Dec 2015 11:24:15 +0100 Subject: [PATCH 031/117] reset slowaccept upon socket close --- sndiod/sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sndiod/sock.c b/sndiod/sock.c index f523342..d5f14a6 100644 --- a/sndiod/sock.c +++ b/sndiod/sock.c @@ -153,6 +153,7 @@ sock_close(struct sock *f) } file_del(f->file); close(f->fd); + file_slowaccept = 0; xfree(f); } From c77ea933449f737c56c989581630a05fca3f5e37 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 15 Dec 2015 06:28:05 +0100 Subject: [PATCH 032/117] Make sndio buildable on NetBSD, from Kamil Rytarowski --- configure | 8 ++++++++ sndiod/sndiod.c | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 91ae816..8fa76ac 100755 --- a/configure +++ b/configure @@ -56,6 +56,14 @@ case `uname` in so="$so libsndio.so" defs='-D_GNU_SOURCE -DDEV_RANDOM=\\"/dev/urandom\\"' ;; + NetBSD) + sun=no + rmidi=yes + user=_sndio + so="$so libsndio.so" + defs='-DHAVE_ARC4RANDOM -DHAVE_ISSETUGID \\\ + -DHAVE_STRLCAT -DHAVE_STRLCPY' + ;; OpenBSD) sun=yes rmidi=yes diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index 19a32f5..66353e2 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -485,8 +485,8 @@ main(int argc, char **argv) if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) < 0) err(1, "setpriority"); if (setgroups(1, &pw->pw_gid) || - setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || - setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) + setgid(pw->pw_gid) || + setuid(pw->pw_uid)) err(1, "cannot drop privileges"); } midi_init(); From cac23d61dcf94ea1e566d3556341c94ea8ff8be4 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 15 Dec 2015 12:28:23 +0100 Subject: [PATCH 033/117] use a copy of the slowaccept flag, as it may change within the poll() loop --- sndiod/listen.c | 7 ++++++- sndiod/listen.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/sndiod/listen.c b/sndiod/listen.c index 5f0ee1c..ee06643 100644 --- a/sndiod/listen.c +++ b/sndiod/listen.c @@ -217,7 +217,8 @@ listen_pollfd(void *arg, struct pollfd *pfd) { struct listen *f = arg; - if (file_slowaccept) + f->slowaccept = file_slowaccept; + if (f->slowaccept) return 0; pfd->fd = f->fd; pfd->events = POLLIN; @@ -227,6 +228,10 @@ listen_pollfd(void *arg, struct pollfd *pfd) int listen_revents(void *arg, struct pollfd *pfd) { + struct listen *f = arg; + + if (f->slowaccept) + return 0; return pfd->revents; } diff --git a/sndiod/listen.h b/sndiod/listen.h index c64aeca..d53e9f3 100644 --- a/sndiod/listen.h +++ b/sndiod/listen.h @@ -24,6 +24,7 @@ struct listen { struct file *file; char *path; int fd; + int slowaccept; }; extern struct listen *listen_list; From 2009e44d9d8a63a6956cc75f610bd708fad67404 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 15 Dec 2015 12:49:31 +0100 Subject: [PATCH 034/117] don't require -U to precede -L --- sndiod/sndiod.1 | 3 --- sndiod/sndiod.c | 13 ++++++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/sndiod/sndiod.1 b/sndiod/sndiod.1 index 4f1c035..ca0e84f 100644 --- a/sndiod/sndiod.1 +++ b/sndiod/sndiod.1 @@ -291,9 +291,6 @@ used in .Xr sndio 7 device names. The default is 0. -The unit number must be set before any -.Fl L -is used. .It Fl v Ar volume Software volume attenuation of playback. The value must be between 1 and 127, diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index 66353e2..812bf2c 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -346,6 +346,10 @@ main(int argc, char **argv) struct port *p; struct listen *l; struct passwd *pw; + struct tcpaddr { + char *host; + struct tcpaddr *next; + } *tcpaddr_list = NULL, *ta; atexit(log_flush); @@ -379,14 +383,15 @@ main(int argc, char **argv) background = 0; break; case 'U': - if (listen_list) - errx(1, "-U must come before -L"); unit = strtonum(optarg, 0, 15, &str); if (str) errx(1, "%s: unit number is %s", optarg, str); break; case 'L': - listen_new_tcp(optarg, AUCAT_PORT + unit); + ta = xmalloc(sizeof(struct tcpaddr)); + ta->host = optarg; + ta->next = tcpaddr_list; + tcpaddr_list = ta; break; case 'm': mode = opt_mode(); @@ -479,6 +484,8 @@ main(int argc, char **argv) getbasepath(base, sizeof(base)); snprintf(path, SOCKPATH_MAX, "%s/" SOCKPATH_FILE "%u", base, unit); listen_new_un(path); + for (ta = tcpaddr_list; ta != NULL; ta = ta->next) + listen_new_tcp(ta->host, AUCAT_PORT + unit); if (geteuid() == 0) { if ((pw = getpwnam(SNDIO_USER)) == NULL) errx(1, "unknown user %s", SNDIO_USER); From 44eae7129c082682b99d1a5a1400a9608ffd4ff0 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 17 Dec 2015 12:56:25 +0100 Subject: [PATCH 035/117] use log_xxx() in opt.c, use simple list --- sndiod/opt.c | 30 ++++++++++++++---------------- sndiod/sndiod.c | 12 +++++++----- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/sndiod/opt.c b/sndiod/opt.c index 61586d2..bf25d12 100644 --- a/sndiod/opt.c +++ b/sndiod/opt.c @@ -14,8 +14,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include #include #include "dev.h" @@ -32,20 +30,27 @@ opt_new(char *name, struct dev *dev, int pmin, int pmax, int rmin, int rmax, int maxweight, int mmc, int dup, unsigned int mode) { - struct opt *o, **po; + struct opt *o; unsigned int len; char c; + if (opt_byname(name, dev->num)) { + log_puts(name); + log_puts(": already defined\n"); + return NULL; + } for (len = 0; name[len] != '\0'; len++) { if (len == OPT_NAMEMAX) { - fprintf(stderr, "%s: name too long\n", name); - exit(1); + log_puts(name); + log_puts(": too long\n"); + return NULL; } c = name[len]; if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z')) { - fprintf(stderr, "%s: '%c' not allowed\n", name, c); - exit(1); + log_puts(name); + log_puts(": only alphabetic chars allowed\n"); + return NULL; } } o = xmalloc(sizeof(struct opt)); @@ -63,15 +68,8 @@ opt_new(char *name, struct dev *dev, o->mode = mode; o->dev = dev; memcpy(o->name, name, len + 1); - for (po = &opt_list; *po != NULL; po = &(*po)->next) { - if (o->dev->num == (*po)->dev->num && - strcmp(o->name, (*po)->name) == 0) { - fprintf(stderr, "%s: already defined\n", o->name); - exit(1); - } - } - o->next = NULL; - *po = o; + o->next = opt_list; + opt_list = o; if (log_level >= 2) { dev_log(o->dev); log_puts("."); diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index 812bf2c..d381da6 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -326,7 +326,7 @@ mkopt(char *path, struct dev *d, o = opt_new(path, d, pmin, pmax, rmin, rmax, MIDI_TO_ADATA(vol), mmc, dup, mode); if (o == NULL) - errx(1, "%s: couldn't create subdev", path); + return NULL; dev_adjpar(d, o->mode, o->pmin, o->pmax, o->rmin, o->rmax); return o; } @@ -426,8 +426,9 @@ main(int argc, char **argv) d = mkdev(DEFAULT_DEV, &par, 0, bufsz, round, rate, hold, autovol); } - mkopt(optarg, d, pmin, pmax, rmin, rmax, - mode, vol, mmc, dup); + if (mkopt(optarg, d, pmin, pmax, rmin, rmax, + mode, vol, mmc, dup) == NULL) + return 1; break; case 'q': mkport(optarg, hold); @@ -478,8 +479,9 @@ main(int argc, char **argv) for (d = dev_list; d != NULL; d = d->next) { if (opt_byname("default", d->num)) continue; - mkopt("default", d, pmin, pmax, rmin, rmax, - mode, vol, mmc, dup); + if (mkopt("default", d, pmin, pmax, rmin, rmax, + mode, vol, mmc, dup) == NULL) + return 1; } getbasepath(base, sizeof(base)); snprintf(path, SOCKPATH_MAX, "%s/" SOCKPATH_FILE "%u", base, unit); From 18105ebb4cf874666c60dd622f9f07085d795eb0 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 17 Dec 2015 15:50:37 +0100 Subject: [PATCH 036/117] allow listen_new_xxx() to return error, use log_xxx() --- sndiod/listen.c | 59 ++++++++++++++++++++++++++----------------------- sndiod/listen.h | 4 ++-- sndiod/sndiod.c | 9 +++++--- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/sndiod/listen.c b/sndiod/listen.c index ee06643..6331305 100644 --- a/sndiod/listen.c +++ b/sndiod/listen.c @@ -24,12 +24,10 @@ #include #include -#include #include #include #include #include -#include #include #include @@ -80,7 +78,7 @@ listen_close(struct listen *f) xfree(f); } -void +int listen_new_un(char *path) { int sock, oldumask; @@ -89,11 +87,13 @@ listen_new_un(char *path) sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { - perror("socket"); - exit(1); + log_puts(path); + log_puts(": failed to create socket\n"); + return 0; } if (unlink(path) < 0 && errno != ENOENT) { - perror("unlink"); + log_puts(path); + log_puts(": failed to unlink socket\n"); goto bad_close; } sockname.sun_family = AF_UNIX; @@ -101,11 +101,13 @@ listen_new_un(char *path) oldumask = umask(0111); if (bind(sock, (struct sockaddr *)&sockname, sizeof(struct sockaddr_un)) < 0) { - perror("bind"); + log_puts(path); + log_puts(": failed to bind socket\n"); goto bad_close; } if (listen(sock, 1) < 0) { - perror("listen"); + log_puts(path); + log_puts(": failed to listen\n"); goto bad_close; } umask(oldumask); @@ -114,20 +116,16 @@ listen_new_un(char *path) if (f->file == NULL) goto bad_close; f->path = xstrdup(path); - if (f->path == NULL) { - perror("strdup"); - exit(1); - } f->fd = sock; f->next = listen_list; listen_list = f; - return; + return 1; bad_close: close(sock); - exit(1); + return 0; } -void +int listen_new_tcp(char *addr, unsigned int port) { char *host, serv[sizeof(unsigned int) * 3 + 1]; @@ -146,8 +144,9 @@ listen_new_tcp(char *addr, unsigned int port) aihints.ai_protocol = IPPROTO_TCP; error = getaddrinfo(host, serv, &aihints, &ailist); if (error) { - fprintf(stderr, "%s: %s\n", addr, gai_strerror(error)); - exit(1); + log_puts(addr); + log_puts(": failed to resolve address\n"); + return 0; } /* @@ -157,13 +156,15 @@ listen_new_tcp(char *addr, unsigned int port) for (ai = ailist; ai != NULL; ai = ai->ai_next) { s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (s < 0) { - perror("socket"); + log_puts(addr); + log_puts(": failed to create socket\n"); continue; } opt = 1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) < 0) { - perror("setsockopt"); + log_puts(addr); + log_puts(": failed to set SO_REUSEADDR\n"); goto bad_close; } if (ai->ai_family == AF_INET6) { @@ -175,17 +176,20 @@ listen_new_tcp(char *addr, unsigned int port) opt = 1; if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(int)) < 0) { - perror("setsockopt"); + log_puts(addr); + log_puts(": failed to set IPV6_V6ONLY\n"); goto bad_close; } } if (bind(s, ai->ai_addr, ai->ai_addrlen) < 0) { - perror("bind"); + log_puts(addr); + log_puts(": failed to bind socket\n"); goto bad_close; } if (listen(s, 1) < 0) { - perror("listen"); + log_puts(addr); + log_puts(": failed to listen\n"); goto bad_close; } f = xmalloc(sizeof(struct listen)); @@ -202,8 +206,7 @@ listen_new_tcp(char *addr, unsigned int port) n++; } freeaddrinfo(ailist); - if (n == 0) - exit(1); + return n; } int @@ -249,12 +252,11 @@ listen_in(void *arg) continue; if (errno == ENFILE || errno == EMFILE) file_slowaccept = 1; - else if (errno != ECONNABORTED && errno != EWOULDBLOCK) - perror("accept"); return; } if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { - perror("fcntl(sock, O_NONBLOCK)"); + file_log(f->file); + log_puts(": failed to set non-blocking mode\n"); close(sock); return; } @@ -262,7 +264,8 @@ listen_in(void *arg) opt = 1; if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int)) < 0) { - perror("setsockopt"); + file_log(f->file); + log_puts(": failed to set TCP_NODELAY flag\n"); close(sock); return; } diff --git a/sndiod/listen.h b/sndiod/listen.h index d53e9f3..c93c11a 100644 --- a/sndiod/listen.h +++ b/sndiod/listen.h @@ -29,8 +29,8 @@ struct listen { extern struct listen *listen_list; -void listen_new_un(char *); -void listen_new_tcp(char *, unsigned int); +int listen_new_un(char *); +int listen_new_tcp(char *, unsigned int); int listen_init(struct listen *); void listen_close(struct listen *); diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index d381da6..e054e17 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -485,9 +485,12 @@ main(int argc, char **argv) } getbasepath(base, sizeof(base)); snprintf(path, SOCKPATH_MAX, "%s/" SOCKPATH_FILE "%u", base, unit); - listen_new_un(path); - for (ta = tcpaddr_list; ta != NULL; ta = ta->next) - listen_new_tcp(ta->host, AUCAT_PORT + unit); + if (!listen_new_un(path)) + return 1; + for (ta = tcpaddr_list; ta != NULL; ta = ta->next) { + if (!listen_new_tcp(ta->host, AUCAT_PORT + unit)) + return 1; + } if (geteuid() == 0) { if ((pw = getpwnam(SNDIO_USER)) == NULL) errx(1, "unknown user %s", SNDIO_USER); From 02a873aace671d79fb24f58432526f7dd96859c6 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 17 Dec 2015 15:59:03 +0100 Subject: [PATCH 037/117] use err() on init and log_xxx() at runtime --- sndiod/file.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sndiod/file.c b/sndiod/file.c index b6b9d42..d5baacf 100644 --- a/sndiod/file.c +++ b/sndiod/file.c @@ -399,8 +399,10 @@ file_poll(void) timo = -1; res = poll(pfds, nfds, timo); if (res < 0) { - if (errno != EINTR) - err(1, "poll"); + if (errno != EINTR) { + log_puts("poll failed"); + panic(); + } return 1; } @@ -450,8 +452,7 @@ filelist_init(void) err(1, "sigprocmask"); file_list = NULL; if (clock_gettime(CLOCK_MONOTONIC, &file_ts) < 0) { - perror("clock_gettime"); - exit(1); + err(1, "clock_gettime"); } log_sync = 0; timo_init(); From 8af6aa7130997dafb7b06f3cd3b38995f3e76c0d Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 22 Dec 2015 13:17:00 +0100 Subject: [PATCH 038/117] panic if CLOCK_MONOTONIC is unsupported --- sndiod/file.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sndiod/file.c b/sndiod/file.c index d5baacf..a00698b 100644 --- a/sndiod/file.c +++ b/sndiod/file.c @@ -46,7 +46,6 @@ #include -#include #include #include #include @@ -446,14 +445,14 @@ filelist_init(void) { sigset_t set; - sigemptyset(&set); - (void)sigaddset(&set, SIGPIPE); - if (sigprocmask(SIG_BLOCK, &set, NULL)) - err(1, "sigprocmask"); - file_list = NULL; if (clock_gettime(CLOCK_MONOTONIC, &file_ts) < 0) { - err(1, "clock_gettime"); + log_puts("filelist_init: CLOCK_MONOTONIC unsupported\n"); + panic(); } + sigemptyset(&set); + sigaddset(&set, SIGPIPE); + sigprocmask(SIG_BLOCK, &set, NULL); + file_list = NULL; log_sync = 0; timo_init(); } From 37cdacd0aa66ba5736f7bc133872aa4dca215024 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 30 Dec 2015 12:54:40 +0100 Subject: [PATCH 039/117] crank major (openbsd specific changes) --- libsndio/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsndio/Makefile.in b/libsndio/Makefile.in index 8ddf3fd..c888574 100644 --- a/libsndio/Makefile.in +++ b/libsndio/Makefile.in @@ -43,7 +43,7 @@ MAN7 = sndio.7 # libraries to build and install # MAJ = 6 -MIN = 0 +MIN = 1 SO = @so@ all: ${SO} From 67bf8b778604a984bdbba76c78456553d2186dcd Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 30 Dec 2015 12:55:18 +0100 Subject: [PATCH 040/117] sys/queue.h isn't used --- sndiod/sndiod.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index e054e17..9a72209 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -14,7 +14,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include #include #include From aa3d0b1ca1ae2fe0e77406a235743e7319b16b6c Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 30 Dec 2015 12:56:11 +0100 Subject: [PATCH 041/117] assert xfree() doesn't get NULL arg --- sndiod/utils.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sndiod/utils.c b/sndiod/utils.c index 67f6670..580b94c 100644 --- a/sndiod/utils.c +++ b/sndiod/utils.c @@ -163,6 +163,12 @@ xmalloc(size_t size) void xfree(void *p) { +#ifdef DEBUG + if (p == NULL) { + log_puts("xfree with NULL arg\n"); + panic(); + } +#endif free(p); } From 5219e9d39df809e9718b238bdc197ed77a7b82de Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 5 Jan 2016 09:43:13 +0100 Subject: [PATCH 042/117] Warn about huge clock ticks only if there are time-outs --- sndiod/file.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sndiod/file.c b/sndiod/file.c index a00698b..b9a4625 100644 --- a/sndiod/file.c +++ b/sndiod/file.c @@ -419,12 +419,14 @@ file_poll(void) if (delta_nsec < 0) log_puts("file_poll: negative time interval\n"); #endif - file_ts = ts; - if (delta_nsec >= 0 && delta_nsec < 1000000000LL) - timo_update(delta_nsec / 1000); - else { - if (log_level >= 2) - log_puts("ignored huge clock delta\n"); + file_ts = ts; + if (timo_queue) { + if (delta_nsec >= 0 && delta_nsec < 1000000000LL) + timo_update(delta_nsec / 1000); + else { + if (log_level >= 2) + log_puts("ignored huge clock delta\n"); + } } /* From aa4fc43964c21f175ddc3a88ec0f76a3350b0376 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 7 Jan 2016 17:48:47 +0100 Subject: [PATCH 043/117] move sndiod manual to sec 8 --- aucat/aucat.1 | 8 +++---- libsndio/mio_open.3 | 6 ++--- libsndio/sio_open.3 | 8 +++---- libsndio/sndio.7 | 44 +++++++++++++++++------------------ sndiod/{sndiod.1 => sndiod.8} | 4 ++-- 5 files changed, 35 insertions(+), 35 deletions(-) rename sndiod/{sndiod.1 => sndiod.8} (99%) diff --git a/aucat/aucat.1 b/aucat/aucat.1 index fea552f..446311d 100644 --- a/aucat/aucat.1 +++ b/aucat/aucat.1 @@ -87,7 +87,7 @@ Increase log verbosity. Encoding of the audio file. The default is .Va s16 . -Encoding names use the follwing scheme: signedness +Encoding names use the following scheme: signedness .Po .Va s or @@ -223,7 +223,7 @@ back to the starting position. .El .Pp MIDI control is intended to be used together with -.Xr sndiod 1 . +.Xr sndiod 8 . For instance, the following command will create two devices: the default .Va snd/0 @@ -280,9 +280,9 @@ $ aucat -n -i stereo.wav -c 0:0 -o left.wav \e .Xr audioctl 1 , .Xr cdio 1 , .Xr mixerctl 1 , -.Xr sndiod 1 , .Xr audio 4 , -.Xr sndio 7 +.Xr sndio 7 , +.Xr sndiod 8 .Sh BUGS Resampling is low quality. .Pp diff --git a/libsndio/mio_open.3 b/libsndio/mio_open.3 index ffbcf43..06a854d 100644 --- a/libsndio/mio_open.3 +++ b/libsndio/mio_open.3 @@ -51,7 +51,7 @@ The library allows user processes to access .Xr midi 4 hardware and -.Xr sndiod 1 +.Xr sndiod 8 MIDI thru boxes and control ports in a uniform way. .Ss Opening and closing an MIDI stream First the application must call the @@ -243,7 +243,7 @@ The debug level: may be a value between 0 and 2. .El .Sh SEE ALSO -.Xr sndiod 1 , .Xr poll 2 , .Xr midi 4 , -.Xr sndio 7 +.Xr sndio 7 , +.Xr sndiod 8 diff --git a/libsndio/sio_open.3 b/libsndio/sio_open.3 index 620bb56..a1e2b6c 100644 --- a/libsndio/sio_open.3 +++ b/libsndio/sio_open.3 @@ -80,7 +80,7 @@ The library allows user processes to access .Xr audio 4 hardware and the -.Xr sndiod 1 +.Xr sndiod 8 audio server in a uniform way. .Ss Opening and closing an audio device First the application must call the @@ -255,7 +255,7 @@ has been called, must be called before parameters can be changed. .Pp If the device is exposed by the -.Xr sndiod 1 +.Xr sndiod 8 server, which is the default configuration, a transparent emulation layer will automatically be set up, and in this case any combination of @@ -709,9 +709,9 @@ The debug level: may be a value between 0 and 2. .El .Sh SEE ALSO -.Xr sndiod 1 , .Xr audio 4 , .Xr sndio 7 , +.Xr sndiod 8 , .Xr audio 9 .Sh BUGS The @@ -727,7 +727,7 @@ function will stop playback immediately. If the application doesn't consume recorded data fast enough then .Dq "control messages" from the -.Xr sndiod 1 +.Xr sndiod 8 server are delayed and consequently .Fn sio_onmove callback or volume changes may be delayed. diff --git a/libsndio/sndio.7 b/libsndio/sndio.7 index c37ff74..72af2e0 100644 --- a/libsndio/sndio.7 +++ b/libsndio/sndio.7 @@ -25,7 +25,7 @@ The .Nm sndio audio and MIDI system provides access to audio and MIDI hardware and to services provided by -.Xr sndiod 1 , +.Xr sndiod 8 , summarized below. .Pp Hardware @@ -38,7 +38,7 @@ audio programs. .Pp To overcome hardware limitations and to allow multiple applications to share the hardware, -.Xr sndiod 1 +.Xr sndiod 8 can be used. It exposes one or more software sub-devices backed by the underlying hardware, while doing all necessary conversions on the fly. @@ -57,15 +57,15 @@ Software MIDI thru boxes allow one application to send MIDI data to other applications connected to the thru box (for instance a software sequencer can send events to multiple software synthesizers). There's no hardware involved: thru boxes are created by -.Xr sndiod 1 . +.Xr sndiod 8 . .Pp Additionally, -.Xr sndiod 1 +.Xr sndiod 8 exposes a MIDI port used to control and monitor audio streams in real time using MIDI. .Sh DEVICE NAMES From the user's perspective every audio interface, MIDI port, and -.Xr sndiod 1 +.Xr sndiod 8 service has a name of the form: .Bd -literal -offset center type[@hostname][,unit]/devnum[.option] @@ -89,36 +89,36 @@ Raw port. .It Pa snd Audio device exposed by -.Xr sndiod 1 . +.Xr sndiod 8 . .It Pa midithru MIDI thru box created with -.Xr sndiod 1 . +.Xr sndiod 8 . .It Pa midi MIDI port exposed by -.Xr sndiod 1 . +.Xr sndiod 8 . .It Pa default Default audio device or MIDI port (see below). .El .It Pa hostname The hostname or address where the remote -.Xr sndiod 1 +.Xr sndiod 8 server to connect to is running. .It Pa unit The number of the -.Xr sndiod 1 +.Xr sndiod 8 server to connect to, corresponding to the integer specified using the .Fl U option of -.Xr sndiod 1 . +.Xr sndiod 8 . Useful only if multiple -.Xr sndiod 1 +.Xr sndiod 8 servers are running on the same system. .It Pa devnum Device number. For hardware audio or MIDI ports, this corresponds to the character device minor number. For audio devices or MIDI ports created with -.Xr sndiod 1 +.Xr sndiod 8 it corresponds to the number of the corresponding .Fl fq option on the command line. @@ -126,7 +126,7 @@ option on the command line. Corresponds to the sub-device string registered using the .Fl s option of -.Xr sndiod 1 . +.Xr sndiod 8 . .El .Pp For example: @@ -138,13 +138,13 @@ First hardware audio device. Hardware MIDI port number 5. .It Pa snd/0 First audio device exposed by -.Xr sndiod 1 . +.Xr sndiod 8 . .It Pa snd/0.rear Sub-device registered with .Fl s Fa rear . .It Pa midithru/0 First MIDI thru box created with -.Xr sndiod 1 . +.Xr sndiod 8 . .El .Sh DEFAULTS If @@ -158,10 +158,10 @@ If it is not set, the program first tries to connect to If that fails, it then tries to use .Pa rsnd/0 . This allows the -.Xr sndiod 1 +.Xr sndiod 8 audio server to be used by default and the bare hardware as fallback; programs don't have to be reconfigured when -.Xr sndiod 1 +.Xr sndiod 8 is started or stopped. .Pp If @@ -175,14 +175,14 @@ If it is not set, the program first tries to connect to If that fails, it then tries to use .Pa rmidi/0 . As long as -.Xr sndiod 1 +.Xr sndiod 8 is running, this allows programs to exchange MIDI data on machines with no MIDI hardware by default, e.g. a MIDI player could use a software synthesizer with no manual configuration required. .Sh AUTHENTICATION If a shared -.Xr sndiod 1 +.Xr sndiod 8 server is running, for privacy reasons only one user may have connections to it at a given time (though the same user could have multiple connections to it). @@ -216,8 +216,8 @@ Audio devices. MIDI ports. .El .Sh SEE ALSO -.Xr sndiod 1 , .Xr mio_open 3 , .Xr sio_open 3 , .Xr audio 4 , -.Xr midi 4 +.Xr midi 4 , +.Xr sndiod 8 diff --git a/sndiod/sndiod.1 b/sndiod/sndiod.8 similarity index 99% rename from sndiod/sndiod.1 rename to sndiod/sndiod.8 index ca0e84f..488d5b0 100644 --- a/sndiod/sndiod.1 +++ b/sndiod/sndiod.8 @@ -15,7 +15,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .Dd $Mdocdate$ -.Dt SNDIOD 1 +.Dt SNDIOD 8 .Os .Sh NAME .Nm sndiod @@ -160,7 +160,7 @@ logs on Attempt to configure the device to use this encoding. The default is .Va s16 . -Encoding names use the follwing scheme: signedness +Encoding names use the following scheme: signedness .Po .Va s or From 3b3a64a4fca22327c89506482770b9f08d4d67ca Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 8 Jan 2016 11:45:01 +0100 Subject: [PATCH 044/117] Don't calculate clock deltas is there are no time-outs. Removes (harmless) warnings about out-of-bounds clock deltas. --- sndiod/file.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sndiod/file.c b/sndiod/file.c index b9a4625..61b472d 100644 --- a/sndiod/file.c +++ b/sndiod/file.c @@ -413,21 +413,21 @@ file_poll(void) file_wtime += 1000000000LL * (ts.tv_sec - sleepts.tv_sec); file_wtime += ts.tv_nsec - sleepts.tv_nsec; #endif - delta_nsec = 1000000000LL * (ts.tv_sec - file_ts.tv_sec); - delta_nsec += ts.tv_nsec - file_ts.tv_nsec; -#ifdef DEBUG - if (delta_nsec < 0) - log_puts("file_poll: negative time interval\n"); -#endif - file_ts = ts; if (timo_queue) { + delta_nsec = 1000000000LL * (ts.tv_sec - file_ts.tv_sec); + delta_nsec += ts.tv_nsec - file_ts.tv_nsec; +#ifdef DEBUG + if (delta_nsec < 0) + log_puts("file_poll: negative time interval\n"); +#endif if (delta_nsec >= 0 && delta_nsec < 1000000000LL) timo_update(delta_nsec / 1000); else { if (log_level >= 2) - log_puts("ignored huge clock delta\n"); + log_puts("out-of-bounds clock delta\n"); } } + file_ts = ts; /* * process files that rely on poll From 9a493931b56e5dfc949a9b6c4df37938b4c6b6e8 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 8 Jan 2016 11:48:05 +0100 Subject: [PATCH 045/117] fix installation path of man page --- sndiod/Makefile.in | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sndiod/Makefile.in b/sndiod/Makefile.in index 43b8172..eff4bf7 100644 --- a/sndiod/Makefile.in +++ b/sndiod/Makefile.in @@ -15,28 +15,28 @@ LDADD = -lsndio @ldadd@ # # binaries, documentation, man pages and examples will be installed in -# ${BIN_DIR}, ${MAN1_DIR} +# ${BIN_DIR}, ${MAN8_DIR} # BIN_DIR = @bindir@ -MAN1_DIR = @mandir@/man1 +MAN8_DIR = @mandir@/man8 # # programs to build # PROG = sndiod -MAN1 = sndiod.1 +MAN8 = sndiod.8 -all: ${PROG} ${MAN1} +all: ${PROG} install: - mkdir -p ${DESTDIR}${BIN_DIR} ${DESTDIR}${MAN1_DIR} - rm -f ${DESTDIR}${BIN_DIR}/${PROG} ${DESTDIR}${MAN1_DIR}/${MAN1} + mkdir -p ${DESTDIR}${BIN_DIR} ${DESTDIR}${MAN8_DIR} + rm -f ${DESTDIR}${BIN_DIR}/${PROG} ${DESTDIR}${MAN8_DIR}/${MAN8} cp ${PROG} ${DESTDIR}${BIN_DIR} - cp ${MAN1} ${DESTDIR}${MAN1_DIR} + cp ${MAN8} ${DESTDIR}${MAN8_DIR} uninstall: cd ${DESTDIR}${BIN_DIR} && rm -f ${PROG} - cd ${DESTDIR}${MAN1_DIR} && rm -f ${MAN1} + cd ${DESTDIR}${MAN8_DIR} && rm -f ${MAN8} clean: rm -f -- *.o ${PROG} From 4fdefa70d7e5e054e28ee01ec848707d51244b6b Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 8 Jan 2016 11:48:26 +0100 Subject: [PATCH 046/117] remove redundant debug message --- sndiod/file.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sndiod/file.c b/sndiod/file.c index 61b472d..5a9b454 100644 --- a/sndiod/file.c +++ b/sndiod/file.c @@ -416,10 +416,6 @@ file_poll(void) if (timo_queue) { delta_nsec = 1000000000LL * (ts.tv_sec - file_ts.tv_sec); delta_nsec += ts.tv_nsec - file_ts.tv_nsec; -#ifdef DEBUG - if (delta_nsec < 0) - log_puts("file_poll: negative time interval\n"); -#endif if (delta_nsec >= 0 && delta_nsec < 1000000000LL) timo_update(delta_nsec / 1000); else { From 400600af2e78a017661ad0c4b1990bed30b5a60d Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 8 Jan 2016 14:39:55 +0100 Subject: [PATCH 047/117] free tcpaddr structures --- sndiod/sndiod.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index 9a72209..7833250 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -348,7 +348,7 @@ main(int argc, char **argv) struct tcpaddr { char *host; struct tcpaddr *next; - } *tcpaddr_list = NULL, *ta; + } *tcpaddr_list, *ta; atexit(log_flush); @@ -371,6 +371,7 @@ main(int argc, char **argv) rmax = 1; aparams_init(&par); mode = MODE_PLAY | MODE_REC; + tcpaddr_list = NULL; setsig(); filelist_init(); @@ -542,6 +543,11 @@ main(int argc, char **argv) dev_del(dev_list); while (port_list) port_del(port_list); + while (tcpaddr_list) { + ta = tcpaddr_list; + tcpaddr_list = ta->next; + xfree(ta); + } rmdir(base); filelist_done(); unsetsig(); From e22e6a1b2625ad3feb504b385cdff37a4eddcf2c Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 8 Jan 2016 17:24:48 +0100 Subject: [PATCH 048/117] fix trailing spaces --- sndiod/Makefile.in | 2 +- sndiod/abuf.c | 2 +- sndiod/dev.c | 32 ++++++++++++++++---------------- sndiod/dev.h | 4 ++-- sndiod/dsp.c | 4 ++-- sndiod/file.c | 6 +++--- sndiod/file.h | 4 ++-- sndiod/listen.c | 10 +++++----- sndiod/midi.c | 10 +++++----- sndiod/siofile.c | 6 +++--- sndiod/sndiod.c | 2 +- sndiod/sock.c | 12 ++++++------ sndiod/utils.c | 4 ++-- 13 files changed, 49 insertions(+), 49 deletions(-) diff --git a/sndiod/Makefile.in b/sndiod/Makefile.in index eff4bf7..77a9de7 100644 --- a/sndiod/Makefile.in +++ b/sndiod/Makefile.in @@ -14,7 +14,7 @@ LDADD = -lsndio @ldadd@ @vars@ # -# binaries, documentation, man pages and examples will be installed in +# binaries, documentation, man pages and examples will be installed in # ${BIN_DIR}, ${MAN8_DIR} # BIN_DIR = @bindir@ diff --git a/sndiod/abuf.c b/sndiod/abuf.c index 0c3cf0d..0e34cbb 100644 --- a/sndiod/abuf.c +++ b/sndiod/abuf.c @@ -53,7 +53,7 @@ abuf_init(struct abuf *buf, unsigned int len) void abuf_done(struct abuf *buf) { -#ifdef DEBUG +#ifdef DEBUG if (buf->used > 0) { if (log_level >= 3) { log_puts("deleting non-empty buffer, used = "); diff --git a/sndiod/dev.c b/sndiod/dev.c index 04da363..b8fb0f4 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -548,12 +548,12 @@ slot_skip(struct slot *s) if (s->mode & MODE_PLAY) { abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf); } - s->skip--; + s->skip--; } return max - s->skip; } -int +int play_filt_resamp(struct slot *s, void *res_in, void *out, int todo) { int i, offs, vol, nch; @@ -583,7 +583,7 @@ play_filt_resamp(struct slot *s, void *res_in, void *out, int todo) return todo; } -int +int play_filt_dec(struct slot *s, void *in, void *out, int todo) { void *tmp; @@ -664,7 +664,7 @@ dev_mix_adjvol(struct dev *d) } } -int +int rec_filt_resamp(struct slot *s, void *in, void *res_out, int todo) { int i, vol, offs, nch; @@ -693,7 +693,7 @@ rec_filt_resamp(struct slot *s, void *in, void *res_out, int todo) return todo; } -int +int rec_filt_enc(struct slot *s, void *in, void *out, int todo) { void *tmp; @@ -848,11 +848,11 @@ dev_cycle(struct dev *d) dev_mix_adjvol(d); continue; } - + /* * check for xruns */ - if (((s->mode & MODE_PLAY) && + if (((s->mode & MODE_PLAY) && s->mix.buf.used < s->round * s->mix.bpf) || ((s->mode & MODE_RECMASK) && s->sub.buf.len - s->sub.buf.used < @@ -918,7 +918,7 @@ void dev_onmove(struct dev *d, int delta) { long long pos; - struct slot *s, *snext; + struct slot *s, *snext; d->delta += delta; @@ -1287,11 +1287,11 @@ dev_wakeup(struct dev *d) } d->poffs = 0; - /* + /* * empty cycles don't increment delta, so it's ok to * start at 0 **/ - d->delta = 0; + d->delta = 0; d->pstate = DEV_RUN; dev_sio_start(d); @@ -1609,7 +1609,7 @@ slot_attach(struct slot *s) * start the device if not started */ dev_wakeup(d); - + /* * get the current position, the origin is when the first sample * played and/or recorded @@ -1711,7 +1711,7 @@ slot_attach(struct slot *s) s->sub.encbuf = xmalloc(s->round * slot_nch * sizeof(adata_t)); } - + /* * N-th recorded block is the N-th played block */ @@ -1729,7 +1729,7 @@ slot_ready(struct slot *s) /* * device may be disconnected, and if so we're called from * slot->ops->exit() on a closed device - */ + */ if (s->dev->pstate == DEV_CFG) return; if (s->tstate == MMC_OFF) @@ -1770,7 +1770,7 @@ slot_start(struct slot *s) log_puts("\n"); } #endif - s->mix.bpf = s->par.bps * + s->mix.bpf = s->par.bps * (s->mix.slot_cmax - s->mix.slot_cmin + 1); abuf_init(&s->mix.buf, bufsz * s->mix.bpf); } @@ -1785,7 +1785,7 @@ slot_start(struct slot *s) log_puts("\n"); } #endif - s->sub.bpf = s->par.bps * + s->sub.bpf = s->par.bps * (s->sub.slot_cmax - s->sub.slot_cmin + 1); abuf_init(&s->sub.buf, bufsz * s->sub.bpf); } @@ -1830,7 +1830,7 @@ slot_detach(struct slot *s) panic(); } #endif - } + } *ps = s->next; if (s->mode & MODE_RECMASK) { if (s->sub.encbuf) diff --git a/sndiod/dev.h b/sndiod/dev.h index 5247153..15b40f4 100644 --- a/sndiod/dev.h +++ b/sndiod/dev.h @@ -42,7 +42,7 @@ struct slot { void *arg; /* user data for callbacks */ struct aparams par; /* socket side params */ struct { - int weight; /* dynamic range */ + int weight; /* dynamic range */ int maxweight; /* max dynamic range allowed */ unsigned int vol; /* volume within the vol */ struct abuf buf; /* socket side buffer */ @@ -105,7 +105,7 @@ struct dev { /* * audio device (while opened) - */ + */ struct dev_sio sio; struct aparams par; /* encoding */ int pchan, rchan; /* play & rec channels */ diff --git a/sndiod/dsp.c b/sndiod/dsp.c index 58a352e..44d84ce 100644 --- a/sndiod/dsp.c +++ b/sndiod/dsp.c @@ -446,7 +446,7 @@ enc_init(struct conv *p, struct aparams *par, int nch) p->bias = (1U << 31) >> p->shift; } else { p->bias = 0; - } + } if (!par->le) { p->bfirst = par->bps - 1; p->bnext = -1; @@ -539,7 +539,7 @@ dec_init(struct conv *p, struct aparams *par, int nch) p->bias = (1U << 31) >> p->shift; } else { p->bias = 0; - } + } if (par->le) { p->bfirst = par->bps - 1; p->bnext = -1; diff --git a/sndiod/file.c b/sndiod/file.c index 5a9b454..dc98d1b 100644 --- a/sndiod/file.c +++ b/sndiod/file.c @@ -258,7 +258,7 @@ file_del(struct file *f) log_puts("bad state in file_del()\n"); panic(); } -#endif +#endif file_nfds -= f->max_nfds; f->state = FILE_ZOMB; #ifdef DEBUG @@ -282,7 +282,7 @@ file_process(struct file *f, struct pollfd *pfd) if (log_level >= 3) clock_gettime(CLOCK_MONOTONIC, &ts0); #endif - revents = (f->state != FILE_ZOMB) ? + revents = (f->state != FILE_ZOMB) ? f->ops->revents(f->arg, pfd) : 0; if ((revents & POLLHUP) && (f->state != FILE_ZOMB)) f->ops->hup(f->arg); @@ -423,7 +423,7 @@ file_poll(void) log_puts("out-of-bounds clock delta\n"); } } - file_ts = ts; + file_ts = ts; /* * process files that rely on poll diff --git a/sndiod/file.h b/sndiod/file.h index 968ca54..271d894 100644 --- a/sndiod/file.h +++ b/sndiod/file.h @@ -34,7 +34,7 @@ struct fileops { char *name; int (*pollfd)(void *, struct pollfd *); int (*revents)(void *, struct pollfd *); - /* + /* * we have to handle POLLIN and POLLOUT events * in separate handles, since handling POLLIN can * close the file, and continuing (to handle POLLOUT) @@ -52,7 +52,7 @@ struct file { #define FILE_INIT 0 /* ready */ #define FILE_ZOMB 1 /* closed, but not free()d yet */ unsigned int state; /* one of above */ - unsigned int max_nfds; /* max number of descriptors */ + unsigned int max_nfds; /* max number of descriptors */ unsigned int nfds; /* number of descriptors polled */ char *name; /* for debug purposes */ }; diff --git a/sndiod/listen.c b/sndiod/listen.c index 6331305..aa9071f 100644 --- a/sndiod/listen.c +++ b/sndiod/listen.c @@ -132,9 +132,9 @@ listen_new_tcp(char *addr, unsigned int port) struct addrinfo *ailist, *ai, aihints; struct listen *f; int s, error, opt = 1, n = 0; - - /* - * obtain a list of possible addresses for the host/port + + /* + * obtain a list of possible addresses for the host/port */ memset(&aihints, 0, sizeof(struct addrinfo)); snprintf(serv, sizeof(serv), "%u", port); @@ -149,7 +149,7 @@ listen_new_tcp(char *addr, unsigned int port) return 0; } - /* + /* * for each address, try create a listening socket bound on * that address */ @@ -181,7 +181,7 @@ listen_new_tcp(char *addr, unsigned int port) goto bad_close; } } - + if (bind(s, ai->ai_addr, ai->ai_addrlen) < 0) { log_puts(addr); log_puts(": failed to bind socket\n"); diff --git a/sndiod/midi.c b/sndiod/midi.c index 6c0bd34..b9eeb4c 100644 --- a/sndiod/midi.c +++ b/sndiod/midi.c @@ -250,7 +250,7 @@ midi_tickets(struct midi *iep) } /* - * in the worst case output message is twice the + * in the worst case output message is twice the * input message (2-byte messages with running status) */ tickets = maxavail / 2 - iep->tickets; @@ -333,14 +333,14 @@ midi_in(struct midi *iep, unsigned char *idata, int icount) * store the given message in the output buffer */ void -midi_out(struct midi *oep, unsigned char *idata, int icount) +midi_out(struct midi *oep, unsigned char *idata, int icount) { unsigned char *odata; int ocount; #ifdef DEBUG int i; #endif - + while (icount > 0) { if (oep->obuf.used == oep->obuf.len) { #ifdef DEBUG @@ -532,9 +532,9 @@ port_close(struct port *c) panic(); } #endif - c->state = PORT_CFG; + c->state = PORT_CFG; port_mio_close(c); - + for (i = 0; i < MIDI_NEP; i++) { ep = midi_ep + i; if ((ep->txmask & c->midi->self) || diff --git a/sndiod/siofile.c b/sndiod/siofile.c index 3ddf9ba..a624614 100644 --- a/sndiod/siofile.c +++ b/sndiod/siofile.c @@ -162,7 +162,7 @@ dev_sio_open(struct dev *d) log_putu(par.pchan); log_puts(": unsupported number of play channels\n"); goto bad_close; - } + } if ((mode & SIO_REC) && par.rchan > NCHAN_MAX) { log_puts(d->path); log_puts(": "); @@ -230,7 +230,7 @@ dev_sio_close(struct dev *d) #endif timo_del(&d->sio.watchdog); file_del(d->sio.file); - sio_close(d->sio.hdl); + sio_close(d->sio.hdl); } void @@ -293,7 +293,7 @@ dev_sio_pollfd(void *arg, struct pollfd *pfd) { struct dev *d = arg; int events; - + events = (d->sio.cstate == DEV_SIO_READ) ? POLLIN : POLLOUT; return sio_pollfd(d->sio.hdl, pfd, events); } diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index 7833250..7123789 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -270,7 +270,7 @@ getbasepath(char *base, size_t size) if (errno != EEXIST) err(1, "mkdir(\"%s\")", base); } - umask(omask); + umask(omask); if (stat(base, &sb) < 0) err(1, "stat(\"%s\")", base); if (sb.st_uid != uid || (sb.st_mode & mask) != 0) diff --git a/sndiod/sock.c b/sndiod/sock.c index d5f14a6..b840cec 100644 --- a/sndiod/sock.c +++ b/sndiod/sock.c @@ -338,7 +338,7 @@ sock_fdwrite(struct sock *f, void *data, int count) } sock_close(f); } else { -#ifdef DEBUG +#ifdef DEBUG if (log_level >= 4) { sock_log(f); log_puts(": write blocked\n"); @@ -379,7 +379,7 @@ sock_fdread(struct sock *f, void *data, int count) } sock_close(f); } else { -#ifdef DEBUG +#ifdef DEBUG if (log_level >= 4) { sock_log(f); log_puts(": read blocked\n"); @@ -1097,7 +1097,7 @@ sock_execmsg(struct sock *f) f->ralign = s->round * s->mix.bpf; } } - slot_stop(s); + slot_stop(s); break; case AMSG_SETPAR: #ifdef DEBUG @@ -1285,7 +1285,7 @@ sock_execmsg(struct sock *f) int sock_buildmsg(struct sock *f) { - unsigned int size; + unsigned int size; /* * If pos changed (or initial tick), build a MOVE message. @@ -1315,7 +1315,7 @@ sock_buildmsg(struct sock *f) if (f->fillpending > 0) { AMSG_INIT(&f->wmsg); - f->wmsg.cmd = htonl(AMSG_FLOWCTL); + f->wmsg.cmd = htonl(AMSG_FLOWCTL); f->wmsg.u.ts.delta = htonl(f->fillpending); size = f->fillpending; if (f->slot) @@ -1359,7 +1359,7 @@ sock_buildmsg(struct sock *f) } if (f->midi != NULL && f->midi->obuf.used > 0) { - size = f->midi->obuf.used; + size = f->midi->obuf.used; if (size > AMSG_DATAMAX) size = AMSG_DATAMAX; AMSG_INIT(&f->wmsg); diff --git a/sndiod/utils.c b/sndiod/utils.c index 580b94c..dafe6f3 100644 --- a/sndiod/utils.c +++ b/sndiod/utils.c @@ -91,7 +91,7 @@ log_putx(unsigned long num) c += (c < 10) ? '0' : 'a' - 10; LOG_PUTC(c); } - } else + } else LOG_PUTC('0'); } @@ -146,7 +146,7 @@ void * xmalloc(size_t size) { void *p; - + p = malloc(size); if (p == NULL) { log_puts("failed to allocate "); From 105db99d30392eb8e7895381cdfeb904a2c2af38 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 8 Jan 2016 17:26:47 +0100 Subject: [PATCH 049/117] fit in 80 columns --- sndiod/dsp.c | 3 ++- sndiod/dsp.h | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sndiod/dsp.c b/sndiod/dsp.c index 44d84ce..1b58159 100644 --- a/sndiod/dsp.c +++ b/sndiod/dsp.c @@ -296,7 +296,8 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo) * initialize resampler with ibufsz/obufsz factor and "nch" channels */ void -resamp_init(struct resamp *p, unsigned int iblksz, unsigned int oblksz, int nch) +resamp_init(struct resamp *p, unsigned int iblksz, + unsigned int oblksz, int nch) { unsigned int i; diff --git a/sndiod/dsp.h b/sndiod/dsp.h index 53ad4ea..0e278dd 100644 --- a/sndiod/dsp.h +++ b/sndiod/dsp.h @@ -105,9 +105,9 @@ typedef int adata_t; struct aparams { unsigned int bps; /* bytes per sample */ unsigned int bits; /* actually used bits */ - unsigned int le; /* 1 if little endian, 0 if big endian */ + unsigned int le; /* 1 if little endian, else be */ unsigned int sig; /* 1 if signed, 0 if unsigned */ - unsigned int msb; /* 1 if msb justified, 0 if lsb justified */ + unsigned int msb; /* 1 if msb justified, else lsb */ }; struct resamp { @@ -124,7 +124,7 @@ struct conv { int bfirst; /* bytes to skip at startup */ unsigned int bps; /* bytes per sample */ unsigned int shift; /* shift to get 32bit MSB */ - unsigned int bias; /* bias of unsigned samples */ + unsigned int bias; /* bias of unsigned samples */ int bnext; /* to reach the next byte */ int snext; /* to reach the next sample */ int nch; From 99cfc040049fe6e26e5abc149d0a6fa7386a7a55 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 8 Jan 2016 21:51:12 +0100 Subject: [PATCH 050/117] fit code in 80 columns, remove traing spaces --- libsndio/amsg.h | 2 +- libsndio/mio_alsa.c | 2 +- libsndio/mio_aucat.c | 3 ++- libsndio/sio.c | 6 +++--- libsndio/sio_alsa.c | 26 +++++++++++++------------- libsndio/sio_aucat.c | 3 ++- libsndio/sio_sun.c | 9 +++++---- 7 files changed, 27 insertions(+), 24 deletions(-) diff --git a/libsndio/amsg.h b/libsndio/amsg.h index fa276a5..9c4bced 100644 --- a/libsndio/amsg.h +++ b/libsndio/amsg.h @@ -19,7 +19,7 @@ #include -/* +/* * unix-domain socket name is: * * DIR [ '-' UID ] '/' FILE UNIT diff --git a/libsndio/mio_alsa.c b/libsndio/mio_alsa.c index 4753d72..a2b2d0b 100644 --- a/libsndio/mio_alsa.c +++ b/libsndio/mio_alsa.c @@ -35,7 +35,7 @@ #ifdef DEBUG static snd_output_t *output = NULL; -#define DALSA(str, err) fprintf(stderr, "%s: %s\n", str, snd_strerror(err)) +#define DALSA(str, err) fprintf(stderr, "%s: %s\n", str, snd_strerror(err)) #else #define DALSA(str, err) do {} while (0) #endif diff --git a/libsndio/mio_aucat.c b/libsndio/mio_aucat.c index 896e31b..15c30ee 100644 --- a/libsndio/mio_aucat.c +++ b/libsndio/mio_aucat.c @@ -75,7 +75,8 @@ mio_aucat_runmsg(struct mio_aucat_hdl *hdl) delta, hdl->aucat.maxwrite); break; default: - DPRINTF("mio_aucat_runmsg: unhandled message %u\n", hdl->aucat.rmsg.cmd); + DPRINTF("mio_aucat_runmsg: unhandled message %u\n", + hdl->aucat.rmsg.cmd); hdl->mio.eof = 1; return 0; } diff --git a/libsndio/sio.c b/libsndio/sio.c index 415530e..456426f 100644 --- a/libsndio/sio.c +++ b/libsndio/sio.c @@ -165,7 +165,7 @@ sio_setpar(struct sio_hdl *hdl, struct sio_par *par) return 0; } if (par->__magic != SIO_PAR_MAGIC) { - DPRINTF("sio_setpar: use of uninitialized sio_par structure\n"); + DPRINTF("sio_setpar: uninitialized sio_par structure\n"); hdl->eof = 1; return 0; } @@ -448,7 +448,7 @@ sio_onmove(struct sio_hdl *hdl, void (*cb)(void *, int), void *addr) #ifdef DEBUG void _sio_printpos(struct sio_hdl *hdl) -{ +{ struct timespec ts; long long rpos, rdiff; long long cpos, cdiff; @@ -461,7 +461,7 @@ _sio_printpos(struct sio_hdl *hdl) rround = hdl->par.round * rbpf; wround = hdl->par.round * wbpf; - rpos = (hdl->mode & SIO_REC) ? + rpos = (hdl->mode & SIO_REC) ? hdl->cpos * rbpf - hdl->rused : 0; wpos = (hdl->mode & SIO_PLAY) ? hdl->cpos * wbpf + hdl->wused : 0; diff --git a/libsndio/sio_alsa.c b/libsndio/sio_alsa.c index 2697a51..c4b0d23 100644 --- a/libsndio/sio_alsa.c +++ b/libsndio/sio_alsa.c @@ -39,7 +39,7 @@ #ifdef DEBUG static snd_output_t *output = NULL; -#define DALSA(str, err) fprintf(stderr, "%s: %s\n", str, snd_strerror(err)) +#define DALSA(str, err) fprintf(stderr, "%s: %s\n", str, snd_strerror(err)) #else #define DALSA(str, err) do {} while (0) #endif @@ -103,9 +103,9 @@ static unsigned int cap_rates[] = { }; static snd_pcm_format_t cap_fmts[] = { /* XXX add s24le3 and s24be3 */ - SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_BE, - SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_BE, - SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE, + SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_BE, + SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_BE, + SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE, SND_PCM_FORMAT_U8 }; @@ -498,11 +498,11 @@ sio_alsa_xrun(struct sio_alsa_hdl *hdl) * * to understand the formula, draw a picture :) */ - rbpf = (hdl->sio.mode & SIO_REC) ? + rbpf = (hdl->sio.mode & SIO_REC) ? hdl->sio.par.bps * hdl->sio.par.rchan : 1; wbpf = (hdl->sio.mode & SIO_PLAY) ? hdl->sio.par.bps * hdl->sio.par.pchan : 1; - rround = hdl->sio.par.round * rbpf; + rround = hdl->sio.par.round * rbpf; clk = hdl->sio.cpos % hdl->sio.par.round; rdrop = (clk * rbpf - hdl->sio.rused) % rround; @@ -537,12 +537,12 @@ sio_alsa_setpar_hw(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwp, snd_pcm_uframes_t *round, unsigned int *periods) { static snd_pcm_format_t fmts[] = { - SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_BE, + SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_BE, SND_PCM_FORMAT_U32_LE, SND_PCM_FORMAT_U32_BE, - SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_BE, + SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_BE, SND_PCM_FORMAT_U24_LE, SND_PCM_FORMAT_U24_BE, - SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE, - SND_PCM_FORMAT_U16_LE, SND_PCM_FORMAT_U16_BE, + SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE, + SND_PCM_FORMAT_U16_LE, SND_PCM_FORMAT_U16_BE, SND_PCM_FORMAT_U8, SND_PCM_FORMAT_S8 }; int i, err, dir = 0; @@ -699,7 +699,7 @@ sio_alsa_getcap(struct sio_hdl *sh, struct sio_cap *cap) sio_alsa_fmttopar(hdl, cap_fmts[i], &cap->enc[i].bits, &cap->enc[i].sig, - &cap->enc[i].le); + &cap->enc[i].le); cap->enc[i].bps = SIO_BPS(cap->enc[0].bits); cap->enc[i].msb = 1; } @@ -796,7 +796,7 @@ sio_alsa_setpar(struct sio_hdl *sh, struct sio_par *par) ofmt, orate, (unsigned int)oround, operiods); DPRINTFN(2, "ifmt = %u, irate = %u, iround = %u, iperiods = %u\n", ifmt, irate, (unsigned int)iround, iperiods); - + if (ifmt != ofmt) { DPRINTF("play and rec formats differ\n"); hdl->sio.eof = 1; @@ -1122,7 +1122,7 @@ sio_alsa_revents(struct sio_hdl *sh, struct pollfd *pfd) if (hdl->sio.eof) return POLLHUP; - + for (i = 0; i < hdl->onfds + hdl->infds; i++) { DPRINTFN(4, "sio_alsa_revents: pfds[%d].revents = %x\n", i, pfd[i].revents); diff --git a/libsndio/sio_aucat.c b/libsndio/sio_aucat.c index 54bc58c..7bb3baa 100644 --- a/libsndio/sio_aucat.c +++ b/libsndio/sio_aucat.c @@ -125,7 +125,8 @@ sio_aucat_runmsg(struct sio_aucat_hdl *hdl) hdl->pstate = PSTATE_INIT; break; default: - DPRINTF("sio_aucat_runmsg: unhandled message %u\n", hdl->aucat.rmsg.cmd); + DPRINTF("sio_aucat_runmsg: unhandled message %u\n", + hdl->aucat.rmsg.cmd); hdl->sio.eof = 1; return 0; } diff --git a/libsndio/sio_sun.c b/libsndio/sio_sun.c index 4d3f750..be93063 100644 --- a/libsndio/sio_sun.c +++ b/libsndio/sio_sun.c @@ -560,7 +560,8 @@ sio_sun_setpar(struct sio_hdl *sh, struct sio_par *par) } DPRINTFN(2, "sio_sun_setpar: %i: trying pars = %u/%u/%u\n", i, rate, prec, enc); - if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0 && errno != EINVAL) { + if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0 && + errno != EINVAL) { DPERROR("sio_sun_setpar: setinfo(pars)"); hdl->sio.eof = 1; return 0; @@ -581,7 +582,7 @@ sio_sun_setpar(struct sio_hdl *sh, struct sio_par *par) case AUDIO_ENCODING_ULINEAR: break; default: - DPRINTF("sio_sun_setpar: couldn't set linear encoding\n"); + DPRINTF("sio_sun_setpar: couldn't set encoding\n"); hdl->sio.eof = 1; return 0; } @@ -672,7 +673,7 @@ sio_sun_setpar(struct sio_hdl *sh, struct sio_par *par) } infr = aui.record.block_size / ibpf; onfr = aui.play.block_size / obpf; - DPRINTFN(2, "sio_sun_setpar: %i: trying round = %u -> (%u, %u)\n", + DPRINTFN(2, "sio_sun_setpar: %i: round = %u -> (%u, %u)\n", i, round, infr, onfr); /* @@ -847,7 +848,7 @@ sio_sun_revents(struct sio_hdl *sh, struct pollfd *pfd) doerr = (ap.play_xrun - hdl->oerr) / hdl->obpf; hdl->obytes = ap.play_pos; hdl->oerr = ap.play_xrun; - hdl->odelta += delta; + hdl->odelta += delta; if (!(hdl->sio.mode & SIO_REC)) { hdl->idelta += delta; dierr = doerr; From cbaa92d4d869efbcf765992087c59fdbce510d0f Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 9 Jan 2016 09:20:46 +0100 Subject: [PATCH 051/117] better debug mesg --- libsndio/sio_sun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsndio/sio_sun.c b/libsndio/sio_sun.c index be93063..51155d5 100644 --- a/libsndio/sio_sun.c +++ b/libsndio/sio_sun.c @@ -582,7 +582,7 @@ sio_sun_setpar(struct sio_hdl *sh, struct sio_par *par) case AUDIO_ENCODING_ULINEAR: break; default: - DPRINTF("sio_sun_setpar: couldn't set encoding\n"); + DPRINTF("sio_sun_setpar: couldn't find encoding\n"); hdl->sio.eof = 1; return 0; } From b5a1760af3cfde7ec57fedd5f9a5efacde8805fa Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 9 Jan 2016 09:23:56 +0100 Subject: [PATCH 052/117] unexpand tabs --- libsndio/aucat.c | 4 ++-- libsndio/mio_rmidi.c | 2 +- libsndio/sio_sun.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libsndio/aucat.c b/libsndio/aucat.c index 7778f3a..10ddce4 100644 --- a/libsndio/aucat.c +++ b/libsndio/aucat.c @@ -478,9 +478,9 @@ _aucat_open(struct aucat *hdl, const char *str, unsigned int mode) if ((p = _sndio_parsetype(str, "snd")) != NULL) type = 0; - else if ((p = _sndio_parsetype(str, "midithru")) != NULL) + else if ((p = _sndio_parsetype(str, "midithru")) != NULL) type = 1; - else if ((p = _sndio_parsetype(str, "midi")) != NULL) + else if ((p = _sndio_parsetype(str, "midi")) != NULL) type = 2; else { DPRINTF("%s: unsupported device type\n", str); diff --git a/libsndio/mio_rmidi.c b/libsndio/mio_rmidi.c index 9fd7a6f..8e6116a 100644 --- a/libsndio/mio_rmidi.c +++ b/libsndio/mio_rmidi.c @@ -175,7 +175,7 @@ mio_rmidi_write(struct mio_hdl *sh, const void *buf, size_t len) DPERROR("mio_rmidi_write: write"); hdl->mio.eof = 1; } - return 0; + return 0; } return n; } diff --git a/libsndio/sio_sun.c b/libsndio/sio_sun.c index 51155d5..67cf33f 100644 --- a/libsndio/sio_sun.c +++ b/libsndio/sio_sun.c @@ -803,7 +803,7 @@ sio_sun_write(struct sio_hdl *sh, const void *buf, size_t len) DPERROR("sio_sun_write: write"); hdl->sio.eof = 1; } - return 0; + return 0; } if (hdl->filling) { if (!sio_sun_autostart(hdl)) From 97bf6606909cbb58050e74fbfd95579083d0a5cf Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 9 Jan 2016 09:35:54 +0100 Subject: [PATCH 053/117] fit in 80 columns, trailing spaces, tabs --- aucat/Makefile.in | 4 ++-- aucat/abuf.c | 2 +- aucat/afile.c | 2 +- aucat/aucat.c | 14 +++++++------- aucat/dsp.c | 6 +++--- aucat/utils.c | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/aucat/Makefile.in b/aucat/Makefile.in index 378fcdf..16c7b93 100644 --- a/aucat/Makefile.in +++ b/aucat/Makefile.in @@ -14,7 +14,7 @@ LDADD = -lsndio @ldadd@ @vars@ # -# binaries, documentation, man pages and examples will be installed in +# binaries, documentation, man pages and examples will be installed in # ${BIN_DIR}, ${MAN1_DIR} # BIN_DIR = @bindir@ @@ -45,7 +45,7 @@ clean: OBJS = abuf.o afile.o aucat.o dsp.o utils.o aucat: ${OBJS} - ${CC} ${LDFLAGS} ${LIB} -o aucat ${OBJS} ${LDADD} + ${CC} ${LDFLAGS} ${LIB} -o aucat ${OBJS} ${LDADD} .c.o: ${CC} ${CFLAGS} ${INCLUDE} ${DEFS} -c $< diff --git a/aucat/abuf.c b/aucat/abuf.c index 0c3cf0d..0e34cbb 100644 --- a/aucat/abuf.c +++ b/aucat/abuf.c @@ -53,7 +53,7 @@ abuf_init(struct abuf *buf, unsigned int len) void abuf_done(struct abuf *buf) { -#ifdef DEBUG +#ifdef DEBUG if (buf->used > 0) { if (log_level >= 3) { log_puts("deleting non-empty buffer, used = "); diff --git a/aucat/afile.c b/aucat/afile.c index cc34cd1..7d49e55 100644 --- a/aucat/afile.c +++ b/aucat/afile.c @@ -563,7 +563,7 @@ afile_aiff_readhdr(struct afile *f) log_puts(f->path); log_puts(": failed to read chunk header\n"); return 0; - } + } csize = be32_get(&chunk.size); if (memcmp(chunk.id, aiff_id_comm, 4) == 0) { if (!afile_aiff_readcomm(f, csize, comp, &nfr)) diff --git a/aucat/aucat.c b/aucat/aucat.c index 336a96d..1f9ac30 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -425,7 +425,7 @@ slot_del(struct slot *s) xfree(s); } -static int +static int play_filt_resamp(struct slot *s, void *res_in, void *out, int todo) { int i, offs, vol, nch; @@ -455,7 +455,7 @@ play_filt_resamp(struct slot *s, void *res_in, void *out, int todo) return todo; } -static int +static int play_filt_dec(struct slot *s, void *in, void *out, int todo) { void *tmp; @@ -506,7 +506,7 @@ slot_mix_badd(struct slot *s, adata_t *odata) return done; } -static int +static int rec_filt_resamp(struct slot *s, void *in, void *res_out, int todo) { int i, vol, offs, nch; @@ -535,7 +535,7 @@ rec_filt_resamp(struct slot *s, void *in, void *res_out, int todo) return todo; } -static int +static int rec_filt_enc(struct slot *s, void *in, void *out, int todo) { void *tmp; @@ -1114,7 +1114,7 @@ playrec(char *dev, int mode, int bufsz, char *port) continue; log_puts("poll failed\n"); panic(); - } + } if (dev_pstate == DEV_START) { ev = sio_revents(dev_sh, pfds); if (ev & POLLHUP) { @@ -1276,7 +1276,7 @@ main(int argc, char **argv) port = NULL; dev = NULL; mode = 0; - + while ((c = getopt(argc, argv, "b:c:de:f:h:i:j:no:q:r:t:v:")) != -1) { switch (c) { case 'b': @@ -1359,7 +1359,7 @@ main(int argc, char **argv) if (mode == 0) { log_puts("at least -i or -o required\n"); return 1; - } + } if (!playrec(dev, mode, bufsz, port)) return 1; } diff --git a/aucat/dsp.c b/aucat/dsp.c index 54128fc..b31084e 100644 --- a/aucat/dsp.c +++ b/aucat/dsp.c @@ -222,7 +222,7 @@ aparams_strtoenc(struct aparams *par, char *istr) return 0; done: - par->msb = msb; + par->msb = msb; par->sig = sig; par->bits = bits; par->bps = bps; @@ -516,7 +516,7 @@ enc_init(struct conv *p, struct aparams *par, int nch) p->bias = (1U << 31) >> p->shift; } else { p->bias = 0; - } + } if (!par->le) { p->bfirst = par->bps - 1; p->bnext = -1; @@ -711,7 +711,7 @@ dec_init(struct conv *p, struct aparams *par, int nch) p->bias = (1U << 31) >> p->shift; } else { p->bias = 0; - } + } if (par->le) { p->bfirst = par->bps - 1; p->bnext = -1; diff --git a/aucat/utils.c b/aucat/utils.c index 67f6670..28a2fd6 100644 --- a/aucat/utils.c +++ b/aucat/utils.c @@ -91,7 +91,7 @@ log_putx(unsigned long num) c += (c < 10) ? '0' : 'a' - 10; LOG_PUTC(c); } - } else + } else LOG_PUTC('0'); } @@ -146,7 +146,7 @@ void * xmalloc(size_t size) { void *p; - + p = malloc(size); if (p == NULL) { log_puts("failed to allocate "); From e2be625ebdf65976ef3dc7e703d6acb618fd351e Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 9 Jan 2016 09:49:48 +0100 Subject: [PATCH 054/117] unexpand --- sndiod/dev.c | 2 +- sndiod/dsp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sndiod/dev.c b/sndiod/dev.c index b8fb0f4..ed6b961 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -1643,7 +1643,7 @@ slot_attach(struct slot *s) #ifdef DEBUG if ((s->mode & d->mode) != s->mode) { slot_log(s); - log_puts(": mode beyond device mode, not attaching\n"); + log_puts(": mode beyond device mode, not attaching\n"); panic(); } #endif diff --git a/sndiod/dsp.c b/sndiod/dsp.c index 1b58159..731d8c1 100644 --- a/sndiod/dsp.c +++ b/sndiod/dsp.c @@ -152,7 +152,7 @@ aparams_strtoenc(struct aparams *par, char *istr) return 0; done: - par->msb = msb; + par->msb = msb; par->sig = sig; par->bits = bits; par->bps = bps; From 6436780b57c662a5e175a622406968a2fa0f411d Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 9 Jan 2016 09:49:55 +0100 Subject: [PATCH 055/117] fit in 80 columns, trailing spaces, tabs --- aucat/afile.c | 9 ++++++--- aucat/aucat.c | 6 ++++-- aucat/dsp.c | 6 ++++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/aucat/afile.c b/aucat/afile.c index 7d49e55..ca24d28 100644 --- a/aucat/afile.c +++ b/aucat/afile.c @@ -572,7 +572,8 @@ afile_aiff_readhdr(struct afile *f) } else if (memcmp(chunk.id, aiff_id_data, 4) == 0) { if (!afile_aiff_readdata(f, csize, &offs)) return 0; - f->startpos = sizeof(form) + pos + sizeof(chunk) + offs; + f->startpos = sizeof(form) + pos + + sizeof(chunk) + offs; break; } else { #ifdef DEBUG @@ -927,7 +928,8 @@ afile_open(struct afile *f, char *path, int hdr, int flags, f->fd = STDOUT_FILENO; } else { f->path = path; - f->fd = open(f->path, O_WRONLY | O_TRUNC | O_CREAT, 0666); + f->fd = open(f->path, + O_WRONLY | O_TRUNC | O_CREAT, 0666); if (f->fd < 0) { log_puts(f->path); log_puts(": failed to create file\n"); @@ -956,7 +958,8 @@ afile_open(struct afile *f, char *path, int hdr, int flags, f->par.msb = 1; f->endpos = f->startpos = sizeof(struct aiff_hdr); f->maxpos = 0x7fffffff; - if (!afile_writehdr(f, &dummy, sizeof(struct aiff_hdr))) + if (!afile_writehdr(f, &dummy, + sizeof(struct aiff_hdr))) goto bad_close; } else if (f->hdr == AFILE_HDR_AU) { f->par.bits = (f->par.bits + 7) & ~7; diff --git a/aucat/aucat.c b/aucat/aucat.c index 1f9ac30..ab534d9 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -308,7 +308,8 @@ slot_init(struct slot *s) s->cmin, s->cmax, 0, dev_pchan - 1, 0, dev_pchan - 1); - if (s->afile.fmt != AFILE_FMT_PCM || !aparams_native(&s->afile.par)) { + if (s->afile.fmt != AFILE_FMT_PCM || + !aparams_native(&s->afile.par)) { dec_init(&s->conv, &s->afile.par, slot_nch); s->convbuf = xmalloc(s->round * slot_nch * sizeof(adata_t)); @@ -1032,7 +1033,8 @@ playrec_cycle(void) n = sio_read(dev_sh, p, todo); if (n == 0) { log_puts(dev_name); - log_puts(": failed to read from device\n"); + log_puts(": failed to read " + "from device\n"); return 0; } p += n; diff --git a/aucat/dsp.c b/aucat/dsp.c index b31084e..f118d64 100644 --- a/aucat/dsp.c +++ b/aucat/dsp.c @@ -366,7 +366,8 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo) * initialize resampler with ibufsz/obufsz factor and "nch" channels */ void -resamp_init(struct resamp *p, unsigned int iblksz, unsigned int oblksz, int nch) +resamp_init(struct resamp *p, unsigned int iblksz, + unsigned int oblksz, int nch) { unsigned int i; @@ -673,7 +674,8 @@ dec_do_float(struct conv *p, unsigned char *in, unsigned char *out, int todo) * convert samples from ulaw/alaw to adata_t */ void -dec_do_ulaw(struct conv *p, unsigned char *in, unsigned char *out, int todo, int is_alaw) +dec_do_ulaw(struct conv *p, unsigned char *in, + unsigned char *out, int todo, int is_alaw) { unsigned int f; unsigned char *idata; From e20bb8997d3e5a5ea929e5b6104e3b96abcbc18b Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 9 Jan 2016 09:56:28 +0100 Subject: [PATCH 056/117] remove trailing \n from string passed to err() --- sndiod/sndiod.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index 7123789..b8c78a0 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -243,11 +243,11 @@ unsetsig(void) sa.sa_flags = SA_RESTART; sa.sa_handler = SIG_DFL; if (sigaction(SIGHUP, &sa, NULL) < 0) - err(1, "unsetsig(hup): sigaction failed\n"); + err(1, "unsetsig(hup): sigaction failed"); if (sigaction(SIGTERM, &sa, NULL) < 0) - err(1, "unsetsig(term): sigaction failed\n"); + err(1, "unsetsig(term): sigaction failed"); if (sigaction(SIGINT, &sa, NULL) < 0) - err(1, "unsetsig(int): sigaction failed\n"); + err(1, "unsetsig(int): sigaction failed"); } void From 12dccf8463c7f35da77be4b3bcb1c20f19a2ef0a Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 9 Jan 2016 11:08:18 +0100 Subject: [PATCH 057/117] check that socket path is a directory --- sndiod/sndiod.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index b8c78a0..ca55e32 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -273,6 +273,8 @@ getbasepath(char *base, size_t size) umask(omask); if (stat(base, &sb) < 0) err(1, "stat(\"%s\")", base); + if (!S_ISDIR(sb.st_mode)) + errx(1, "%s is not a directory", base); if (sb.st_uid != uid || (sb.st_mode & mask) != 0) errx(1, "%s has wrong permissions", base); } From cf1ebc72d340a178ea3cc67475b985256f84f3f4 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 9 Jan 2016 14:33:10 +0100 Subject: [PATCH 058/117] make midi->tickets signed (sign is needed for arithmetics). Found by David Coppa. Thanks. --- sndiod/midi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sndiod/midi.h b/sndiod/midi.h index 5ef72de..565cf21 100644 --- a/sndiod/midi.h +++ b/sndiod/midi.h @@ -73,7 +73,7 @@ struct midi { unsigned int len; /* expected ``msg'' length */ unsigned int txmask; /* list of ep we send to */ unsigned int self; /* equal (1 << index) */ - unsigned int tickets; /* max bytes we can process */ + int tickets; /* max bytes we can process */ struct abuf obuf; /* output buffer */ }; From f745d4103202d37f13e9a275d764d43908f5575d Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sun, 10 Jan 2016 12:05:17 +0100 Subject: [PATCH 059/117] revert back to single device by default --- sndiod/sndiod.8 | 23 +++++++++++++++-------- sndiod/sndiod.c | 17 +++-------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/sndiod/sndiod.8 b/sndiod/sndiod.8 index 488d5b0..74ac1f0 100644 --- a/sndiod/sndiod.8 +++ b/sndiod/sndiod.8 @@ -350,22 +350,29 @@ to which they are attached. .Pp If no audio devices .Pq Fl f -are specified, first 4 audio devices are added and -settings are applied to all of them. -Similarly, if no MIDI ports -.Pq Fl q -are specified, first 8 MIDI ports are added and -settings are applied to all of them. +are specified, +settings are applied as if +the default device is specified. If no sub-devices .Pq Fl s are specified for a device, a default sub-device is created attached to it. -If a device or MIDI port -.Pq Fl fq +If a device +.Pq Fl f is defined twice, both definitions are merged: parameters of the first one are used but sub-devices .Pq Fl s of both definitions are created. +The default +.Xr sndio 7 +device used by +.Nm +is +.Pa rsnd/0 , +and the default sub-device exposed by +.Nm +is +.Pa snd/0 . .Pp If .Nm diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index ca55e32..e0b6672 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -338,8 +338,7 @@ main(int argc, char **argv) int c, background, unit; int pmin, pmax, rmin, rmax; char base[SOCKPATH_MAX], path[SOCKPATH_MAX]; - char loc[32]; - unsigned int mode, dup, mmc, vol, i; + unsigned int mode, dup, mmc, vol; unsigned int hold, autovol, bufsz, round, rate; const char *str; struct aparams par; @@ -466,18 +465,8 @@ main(int argc, char **argv) fputs(usagestr, stderr); return 1; } - if (dev_list == NULL) { - for (i = 0; i < 4; i++) { - snprintf(loc, sizeof(loc), "rsnd/%u", i); - mkdev(loc, &par, 0, bufsz, round, rate, hold, autovol); - } - } - if (port_list == NULL) { - for (i = 0; i < 8; i++) { - snprintf(loc, sizeof(loc), "rmidi/%u", i); - mkport(loc, hold); - } - } + if (dev_list == NULL) + mkdev(DEFAULT_DEV, &par, 0, bufsz, round, rate, hold, autovol); for (d = dev_list; d != NULL; d = d->next) { if (opt_byname("default", d->num)) continue; From f1cde9ea14f29a7b07eec8505fdd8ad01f656fab Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 20 Jan 2016 11:57:59 +0100 Subject: [PATCH 060/117] crank max timeout to 60s --- sndiod/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sndiod/file.c b/sndiod/file.c index dc98d1b..ef7e5d4 100644 --- a/sndiod/file.c +++ b/sndiod/file.c @@ -416,7 +416,7 @@ file_poll(void) if (timo_queue) { delta_nsec = 1000000000LL * (ts.tv_sec - file_ts.tv_sec); delta_nsec += ts.tv_nsec - file_ts.tv_nsec; - if (delta_nsec >= 0 && delta_nsec < 1000000000LL) + if (delta_nsec >= 0 && delta_nsec < 60000000000LL) timo_update(delta_nsec / 1000); else { if (log_level >= 2) From bf7d74393697558fa7cbb96e2e75d2bfaac7028c Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 20 Jan 2016 11:58:45 +0100 Subject: [PATCH 061/117] better -d description, from Michael Reed --- sndiod/sndiod.8 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sndiod/sndiod.8 b/sndiod/sndiod.8 index 74ac1f0..7c26b0b 100644 --- a/sndiod/sndiod.8 +++ b/sndiod/sndiod.8 @@ -152,10 +152,9 @@ respectively any client is allowed to use. This is a subset of the audio device channels. The default is 0:1, i.e. stereo. .It Fl d -Increase log verbosity. -.Nm -logs on -.Em stderr . +Enable debugging to standard error, and do not disassociate from the +controlling terminal. +Can be specified multiple times to further increase log verbosity. .It Fl e Ar enc Attempt to configure the device to use this encoding. The default is From fcbcfd089a59f755d809010d89f3d1650298a1fa Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 29 Jan 2016 12:11:23 +0100 Subject: [PATCH 062/117] use "prog" as default prog name --- sndiod/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sndiod/dev.c b/sndiod/dev.c index ed6b961..2c9f549 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -1006,7 +1006,7 @@ dev_new(char *path, struct aparams *par, d->slot[i].vol = MIDI_MAXCTL; d->slot[i].tstate = MMC_OFF; d->slot[i].serial = d->serial++; - d->slot[i].name[0] = '\0'; + strlcpy(d->slot[i].name, "prog", SLOT_NAMEMAX); } d->slot_list = NULL; d->master = MIDI_MAXCTL; From 96e51185e01136f7400d1569f06477b7168b2a91 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 29 Jan 2016 12:12:03 +0100 Subject: [PATCH 063/117] warn about blocking at log level 3 --- sndiod/siofile.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sndiod/siofile.c b/sndiod/siofile.c index a624614..eb40528 100644 --- a/sndiod/siofile.c +++ b/sndiod/siofile.c @@ -353,7 +353,8 @@ dev_sio_run(void *arg) n = sio_read(d->sio.hdl, data, d->sio.todo); d->sio.todo -= n; #ifdef DEBUG - if (n == 0 && data == base && !sio_eof(d->sio.hdl)) { + if (log_level >= 3 && + n == 0 && data == base && !sio_eof(d->sio.hdl)) { dev_log(d); log_puts(": read blocked at cycle start\n"); } @@ -436,7 +437,8 @@ dev_sio_run(void *arg) n = sio_write(d->sio.hdl, data, d->sio.todo); d->sio.todo -= n; #ifdef DEBUG - if (n == 0 && data == base && !sio_eof(d->sio.hdl)) { + if (log_level >= 3 && + n == 0 && data == base && !sio_eof(d->sio.hdl)) { dev_log(d); log_puts(": write blocked at cycle start\n"); } From 74bbedaf28058c9f10c853a2947ace28c975c89a Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 29 Jan 2016 12:12:19 +0100 Subject: [PATCH 064/117] better poll logging --- sndiod/file.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sndiod/file.c b/sndiod/file.c index ef7e5d4..4eadb15 100644 --- a/sndiod/file.c +++ b/sndiod/file.c @@ -318,8 +318,6 @@ file_poll(void) long long delta_nsec; int nfds, res, timo; - log_flush(); - /* * cleanup zombies */ @@ -355,8 +353,6 @@ file_poll(void) log_puts("poll:"); pfd = pfds; for (f = file_list; f != NULL; f = f->next) { - if (f->nfds == 0) - continue; log_puts(" "); log_puts(f->ops->name); log_puts(":"); @@ -396,6 +392,7 @@ file_poll(void) timo = TIMER_MSEC; } else timo = -1; + log_flush(); res = poll(pfds, nfds, timo); if (res < 0) { if (errno != EINTR) { From d6bc5ae04fe098d18261b5d55067e05feb3e7ae9 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 29 Jan 2016 17:20:34 +0100 Subject: [PATCH 065/117] Check that byte order is native only if we're using more than one byte per sample, check the samples are lsb-aligned only if there's padding. --- aucat/aucat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index ab534d9..0605ff7 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -625,8 +625,8 @@ dev_open(char *dev, int mode, int bufsz, char *port) } if (par.bits != ADATA_BITS || par.bps != sizeof(adata_t) || - par.le != SIO_LE_NATIVE || - (par.bps != SIO_BPS(par.bits) && par.msb)) { + (par.bps > 1 && par.le != SIO_LE_NATIVE) || + (par.bps * 8 > par.bits && par.msb)) { log_puts(dev_name); log_puts(": unsupported audio params\n"); return 0; From 85c75911dcc986d11518f06606979f0ab6354082 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 16 Mar 2016 07:48:13 +0100 Subject: [PATCH 066/117] switch to new obsd audio api --- libsndio/sio_sun.c | 600 ++++++++++++--------------------------------- 1 file changed, 152 insertions(+), 448 deletions(-) diff --git a/libsndio/sio_sun.c b/libsndio/sio_sun.c index 67cf33f..901dca5 100644 --- a/libsndio/sio_sun.c +++ b/libsndio/sio_sun.c @@ -42,7 +42,7 @@ struct sio_sun_hdl { struct sio_hdl sio; int fd; - int filling; + int filltodo; unsigned int ibpf, obpf; /* bytes per frame */ unsigned int ibytes, obytes; /* bytes the hw transferred */ unsigned int ierr, oerr; /* frames the hw dropped */ @@ -77,127 +77,68 @@ static struct sio_ops sio_sun_ops = { NULL, /* getvol */ }; -/* - * convert sun encoding to sio_par encoding - */ static int -sio_sun_infotoenc(struct sio_sun_hdl *hdl, struct audio_prinfo *ai, - struct sio_par *par) +sio_sun_adjpar(struct sio_sun_hdl *hdl, struct audio_swpar *ap) { - par->msb = ai->msb; - par->bits = ai->precision; - par->bps = ai->bps; - switch (ai->encoding) { - case AUDIO_ENCODING_SLINEAR_LE: - par->le = 1; - par->sig = 1; - break; - case AUDIO_ENCODING_SLINEAR_BE: - par->le = 0; - par->sig = 1; - break; - case AUDIO_ENCODING_ULINEAR_LE: - par->le = 1; - par->sig = 0; - break; - case AUDIO_ENCODING_ULINEAR_BE: - par->le = 0; - par->sig = 0; - break; - case AUDIO_ENCODING_SLINEAR: - par->le = SIO_LE_NATIVE; - par->sig = 1; - break; - case AUDIO_ENCODING_ULINEAR: - par->le = SIO_LE_NATIVE; - par->sig = 0; - break; - default: - DPRINTF("sio_sun_infotoenc: unsupported encoding\n"); + if (hdl->sio.eof) + return 0; + if (ioctl(hdl->fd, AUDIO_SETPAR, ap)) { + DPERROR("AUDIO_SETPAR"); + hdl->sio.eof = 1; + return 0; + } + if (ioctl(hdl->fd, AUDIO_GETPAR, ap)) { + DPERROR("AUDIO_GETPAR"); hdl->sio.eof = 1; return 0; } return 1; } -/* - * convert sio_par encoding to sun encoding - */ -static void -sio_sun_enctoinfo(struct sio_sun_hdl *hdl, - unsigned int *renc, struct sio_par *par) -{ - if (par->le == ~0U && par->sig == ~0U) { - *renc = ~0U; - } else if (par->le == ~0U || par->sig == ~0U) { - *renc = AUDIO_ENCODING_SLINEAR; - } else if (par->le && par->sig) { - *renc = AUDIO_ENCODING_SLINEAR_LE; - } else if (!par->le && par->sig) { - *renc = AUDIO_ENCODING_SLINEAR_BE; - } else if (par->le && !par->sig) { - *renc = AUDIO_ENCODING_ULINEAR_LE; - } else { - *renc = AUDIO_ENCODING_ULINEAR_BE; - } -} - /* * try to set the device to the given parameters and check that the * device can use them; return 1 on success, 0 on failure or error */ static int -sio_sun_tryinfo(struct sio_sun_hdl *hdl, struct sio_enc *enc, +sio_sun_testpar(struct sio_sun_hdl *hdl, struct sio_enc *enc, unsigned int pchan, unsigned int rchan, unsigned int rate) { - struct audio_info aui; - struct audio_prinfo *pr; + struct audio_swpar ap; - pr = (hdl->sio.mode & SIO_PLAY) ? &aui.play : &aui.record; - - AUDIO_INITINFO(&aui); - if (enc) { - if (enc->le && enc->sig) { - pr->encoding = AUDIO_ENCODING_SLINEAR_LE; - } else if (!enc->le && enc->sig) { - pr->encoding = AUDIO_ENCODING_SLINEAR_BE; - } else if (enc->le && !enc->sig) { - pr->encoding = AUDIO_ENCODING_ULINEAR_LE; - } else { - pr->encoding = AUDIO_ENCODING_ULINEAR_BE; - } - pr->precision = enc->bits; + AUDIO_INITPAR(&ap); + if (enc != NULL) { + ap.sig = enc->sig; + ap.bits = enc->bits; + ap.bps = enc->bps; + if (ap.bps > 1) + ap.le = enc->le; + if (ap.bps * 8 > ap.bits) + ap.msb = enc->msb; } if (rate) - pr->sample_rate = rate; - if ((hdl->sio.mode & (SIO_PLAY | SIO_REC)) == (SIO_PLAY | SIO_REC)) - aui.record = aui.play; + ap.rate = rate; if (pchan && (hdl->sio.mode & SIO_PLAY)) - aui.play.channels = pchan; + ap.pchan = pchan; if (rchan && (hdl->sio.mode & SIO_REC)) - aui.record.channels = rchan; - if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0) { - if (errno == EINVAL) + ap.rchan = rchan; + if (!sio_sun_adjpar(hdl, &ap)) + return 0; + if (pchan && ap.pchan != pchan) + return 0; + if (rchan && ap.rchan != rchan) + return 0; + if (rate && ap.rate != rate) + return 0; + if (enc) { + if (ap.sig != enc->sig) return 0; - DPERROR("sio_sun_tryinfo: setinfo"); - hdl->sio.eof = 1; - return 0; - } - if (ioctl(hdl->fd, AUDIO_GETINFO, &aui) < 0) { - DPERROR("sio_sun_tryinfo: getinfo"); - hdl->sio.eof = 1; - return 0; - } - if (pchan && aui.play.channels != pchan) - return 0; - if (rchan && aui.record.channels != rchan) - return 0; - if (rate) { - if ((hdl->sio.mode & SIO_PLAY) && - (aui.play.sample_rate != rate)) + if (ap.bits != enc->bits) return 0; - if ((hdl->sio.mode & SIO_REC) && - (aui.record.sample_rate != rate)) + if (ap.bps != enc->bps) + return 0; + if (ap.bps > 1 && ap.le != enc->le) + return 0; + if (ap.bits < ap.bps * 8 && ap.msb != enc->msb) return 0; } return 1; @@ -209,8 +150,6 @@ sio_sun_tryinfo(struct sio_sun_hdl *hdl, struct sio_enc *enc, static int sio_sun_getcap(struct sio_hdl *sh, struct sio_cap *cap) { -#define NCHANS (sizeof(chans) / sizeof(chans[0])) -#define NRATES (sizeof(rates) / sizeof(rates[0])) static unsigned int chans[] = { 1, 2, 4, 6, 8, 10, 12 }; @@ -218,56 +157,38 @@ sio_sun_getcap(struct sio_hdl *sh, struct sio_cap *cap) 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000 }; + static unsigned int encs[] = { + 8, 16, 24, 32 + }; struct sio_sun_hdl *hdl = (struct sio_sun_hdl *)sh; - struct sio_par savepar; - struct audio_encoding ae; - unsigned int nenc = 0, nconf = 0; + struct audio_swpar savepar, ap; + unsigned int nconf = 0; unsigned int enc_map = 0, rchan_map = 0, pchan_map = 0, rate_map; unsigned int i, j, conf; - if (!sio_sun_getpar(&hdl->sio, &savepar)) + if (ioctl(hdl->fd, AUDIO_GETPAR, &savepar)) { + DPERROR("AUDIO_GETPAR"); + hdl->sio.eof = 1; return 0; + } /* - * fill encoding list + * get a subset of supported encodings */ - for (ae.index = 0; nenc < SIO_NENC; ae.index++) { - if (ioctl(hdl->fd, AUDIO_GETENC, &ae) < 0) { - if (errno == EINVAL) - break; - DPERROR("sio_sun_getcap: getenc"); - hdl->sio.eof = 1; + for (i = 0; i < sizeof(encs) / sizeof(encs[0]); i++) { + AUDIO_INITPAR(&ap); + ap.bits = encs[i]; + ap.sig = (ap.bits > 8) ? 1 : 0; + if (!sio_sun_adjpar(hdl, &ap)) return 0; + if (ap.bits == encs[i]) { + cap->enc[i].sig = ap.sig; + cap->enc[i].bits = ap.bits; + cap->enc[i].le = ap.le; + cap->enc[i].bps = ap.bps; + cap->enc[i].msb = ap.msb; + enc_map |= 1 << i; } - if (ae.flags & AUDIO_ENCODINGFLAG_EMULATED) - continue; - if (ae.encoding == AUDIO_ENCODING_SLINEAR_LE) { - cap->enc[nenc].le = 1; - cap->enc[nenc].sig = 1; - } else if (ae.encoding == AUDIO_ENCODING_SLINEAR_BE) { - cap->enc[nenc].le = 0; - cap->enc[nenc].sig = 1; - } else if (ae.encoding == AUDIO_ENCODING_ULINEAR_LE) { - cap->enc[nenc].le = 1; - cap->enc[nenc].sig = 0; - } else if (ae.encoding == AUDIO_ENCODING_ULINEAR_BE) { - cap->enc[nenc].le = 0; - cap->enc[nenc].sig = 0; - } else if (ae.encoding == AUDIO_ENCODING_SLINEAR) { - cap->enc[nenc].le = SIO_LE_NATIVE; - cap->enc[nenc].sig = 1; - } else if (ae.encoding == AUDIO_ENCODING_ULINEAR) { - cap->enc[nenc].le = SIO_LE_NATIVE; - cap->enc[nenc].sig = 0; - } else { - /* unsipported encoding */ - continue; - } - cap->enc[nenc].bits = ae.precision; - cap->enc[nenc].bps = ae.bps; - cap->enc[nenc].msb = ae.msb; - enc_map |= (1 << nenc); - nenc++; } /* @@ -278,17 +199,27 @@ sio_sun_getcap(struct sio_hdl *sh, struct sio_cap *cap) * use the current encoding and try various channels. */ if (hdl->sio.mode & SIO_PLAY) { - memcpy(&cap->pchan, chans, NCHANS * sizeof(unsigned int)); - for (i = 0; i < NCHANS; i++) { - if (sio_sun_tryinfo(hdl, NULL, chans[i], 0, 0)) + for (i = 0; i < sizeof(chans) / sizeof(chans[0]); i++) { + AUDIO_INITPAR(&ap); + ap.pchan = chans[i]; + if (!sio_sun_adjpar(hdl, &ap)) + return 0; + if (ap.pchan == chans[i]) { + cap->pchan[i] = chans[i]; pchan_map |= (1 << i); + } } } if (hdl->sio.mode & SIO_REC) { - memcpy(&cap->rchan, chans, NCHANS * sizeof(unsigned int)); - for (i = 0; i < NCHANS; i++) { - if (sio_sun_tryinfo(hdl, NULL, 0, chans[i], 0)) + for (i = 0; i < sizeof(chans) / sizeof(chans[0]); i++) { + AUDIO_INITPAR(&ap); + ap.pchan = chans[i]; + if (!sio_sun_adjpar(hdl, &ap)) + return 0; + if (ap.rchan == chans[i]) { + cap->rchan[i] = chans[i]; rchan_map |= (1 << i); + } } } @@ -299,12 +230,16 @@ sio_sun_getcap(struct sio_hdl *sh, struct sio_cap *cap) * uaudio devices), so certain rates may not be allowed with * certain encodings. We have to check rates for all encodings */ - memcpy(&cap->rate, rates, NRATES * sizeof(unsigned int)); - for (j = 0; j < nenc; j++) { + for (j = 0; j < sizeof(encs) / sizeof(encs[0]); j++) { rate_map = 0; - for (i = 0; i < NRATES; i++) { - if (sio_sun_tryinfo(hdl, &cap->enc[j], 0, 0, rates[i])) + if ((enc_map & (1 << j)) == 0) + continue; + for (i = 0; i < sizeof(rates) / sizeof(rates[0]); i++) { + if (sio_sun_testpar(hdl, + &cap->enc[j], 0, 0, rates[i])) { + cap->rate[i] = rates[i]; rate_map |= (1 << i); + } } for (conf = 0; conf < nconf; conf++) { if (cap->confs[conf].rate == rate_map) { @@ -323,11 +258,13 @@ sio_sun_getcap(struct sio_hdl *sh, struct sio_cap *cap) } } cap->nconf = nconf; - if (!sio_sun_setpar(&hdl->sio, &savepar)) + + if (ioctl(hdl->fd, AUDIO_SETPAR, &savepar)) { + DPERROR("AUDIO_SETPAR"); + hdl->sio.eof = 1; return 0; + } return 1; -#undef NCHANS -#undef NRATES } static int @@ -373,9 +310,7 @@ sio_sun_getfd(const char *str, unsigned int mode, int nbio) static struct sio_hdl * sio_sun_fdopen(int fd, unsigned int mode, int nbio) { - struct audio_info aui; struct sio_sun_hdl *hdl; - struct sio_par par; hdl = malloc(sizeof(struct sio_sun_hdl)); if (hdl == NULL) @@ -385,36 +320,13 @@ sio_sun_fdopen(int fd, unsigned int mode, int nbio) /* * pause the device */ - AUDIO_INITINFO(&aui); - if (mode & SIO_PLAY) - aui.play.pause = 1; - if (mode & SIO_REC) - aui.record.pause = 1; - if (ioctl(fd, AUDIO_SETINFO, &aui) < 0) { - DPERROR("sio_open_sun: setinfo"); - goto bad_free; + if (ioctl(fd, AUDIO_STOP) < 0) { + DPERROR("AUDIO_STOP"); + free(hdl); + return NULL; } hdl->fd = fd; - - /* - * Default parameters may not be compatible with libsndio (eg. mulaw - * encodings, different playback and recording parameters, etc...), so - * set parameters to a random value. If the requested parameters are - * not supported by the device, then sio_setpar() will pick supported - * ones. - */ - sio_initpar(&par); - par.rate = 48000; - par.le = SIO_LE_NATIVE; - par.sig = 1; - par.bits = 16; - par.appbufsz = 1200; - if (!sio_setpar(&hdl->sio, &par)) - goto bad_free; return (struct sio_hdl *)hdl; - bad_free: - free(hdl); - return NULL; } struct sio_hdl * @@ -448,7 +360,6 @@ static int sio_sun_start(struct sio_hdl *sh) { struct sio_sun_hdl *hdl = (struct sio_sun_hdl *)sh; - struct audio_info aui; hdl->obpf = hdl->sio.par.pchan * hdl->sio.par.bps; hdl->ibpf = hdl->sio.par.rchan * hdl->sio.par.bps; @@ -464,20 +375,17 @@ sio_sun_start(struct sio_hdl *sh) * keep the device paused and let sio_sun_write() trigger the * start later, to avoid buffer underruns */ - hdl->filling = 1; + hdl->filltodo = hdl->sio.par.bufsz * hdl->obpf; } else { /* * no play buffers to fill, start now! */ - AUDIO_INITINFO(&aui); - if (hdl->sio.mode & SIO_REC) - aui.record.pause = 0; - if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0) { - DPERROR("sio_sun_start: setinfo"); + if (ioctl(hdl->fd, AUDIO_START) < 0) { + DPERROR("AUDIO_START"); hdl->sio.eof = 1; return 0; } - hdl->filling = 0; + hdl->filltodo = 0; _sio_onmove_cb(&hdl->sio, 0); } return 1; @@ -487,35 +395,11 @@ static int sio_sun_stop(struct sio_hdl *sh) { struct sio_sun_hdl *hdl = (struct sio_sun_hdl *)sh; - struct audio_info aui; - int mode; - if (ioctl(hdl->fd, AUDIO_GETINFO, &aui) < 0) { - DPERROR("sio_sun_stop: getinfo"); - hdl->sio.eof = 1; - return 0; - } - mode = aui.mode; - - /* - * there's no way to drain the device without blocking, so just - * stop it until the kernel driver get fixed - */ - AUDIO_INITINFO(&aui); - aui.mode = 0; - if (hdl->sio.mode & SIO_PLAY) - aui.play.pause = 1; - if (hdl->sio.mode & SIO_REC) - aui.record.pause = 1; - if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0) { - DPERROR("sio_sun_stop: setinfo1"); - hdl->sio.eof = 1; - return 0; - } - AUDIO_INITINFO(&aui); - aui.mode = mode; - if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0) { - DPERROR("sio_sun_stop: setinfo2"); + if (hdl->filltodo > 0) + return 1; + if (ioctl(hdl->fd, AUDIO_STOP) < 0) { + DPERROR("AUDIO_STOP"); hdl->sio.eof = 1; return 0; } @@ -525,210 +409,59 @@ sio_sun_stop(struct sio_hdl *sh) static int sio_sun_setpar(struct sio_hdl *sh, struct sio_par *par) { -#define NRETRIES 8 struct sio_sun_hdl *hdl = (struct sio_sun_hdl *)sh; - struct audio_info aui; - unsigned int i, infr, ibpf, onfr, obpf; - unsigned int bufsz, round; - unsigned int rate, req_rate, prec, enc; + struct audio_swpar ap; - /* - * try to set parameters until the device accepts - * a common encoding and rate for play and record - */ - rate = par->rate; - prec = par->bits; - sio_sun_enctoinfo(hdl, &enc, par); - for (i = 0;; i++) { - if (i == NRETRIES) { - DPRINTF("sio_sun_setpar: couldn't set parameters\n"); - hdl->sio.eof = 1; - return 0; - } - AUDIO_INITINFO(&aui); - if (hdl->sio.mode & SIO_PLAY) { - aui.play.sample_rate = rate; - aui.play.precision = prec; - aui.play.encoding = enc; - aui.play.channels = par->pchan; - } - if (hdl->sio.mode & SIO_REC) { - aui.record.sample_rate = rate; - aui.record.precision = prec; - aui.record.encoding = enc; - aui.record.channels = par->rchan; - } - DPRINTFN(2, "sio_sun_setpar: %i: trying pars = %u/%u/%u\n", - i, rate, prec, enc); - if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0 && - errno != EINVAL) { - DPERROR("sio_sun_setpar: setinfo(pars)"); - hdl->sio.eof = 1; - return 0; - } - if (ioctl(hdl->fd, AUDIO_GETINFO, &aui) < 0) { - DPERROR("sio_sun_setpar: getinfo(pars)"); - hdl->sio.eof = 1; - return 0; - } - enc = (hdl->sio.mode & SIO_REC) ? - aui.record.encoding : aui.play.encoding; - switch (enc) { - case AUDIO_ENCODING_SLINEAR_LE: - case AUDIO_ENCODING_SLINEAR_BE: - case AUDIO_ENCODING_ULINEAR_LE: - case AUDIO_ENCODING_ULINEAR_BE: - case AUDIO_ENCODING_SLINEAR: - case AUDIO_ENCODING_ULINEAR: - break; - default: - DPRINTF("sio_sun_setpar: couldn't find encoding\n"); - hdl->sio.eof = 1; - return 0; - } - if (hdl->sio.mode != (SIO_REC | SIO_PLAY)) - break; - if (aui.play.sample_rate == aui.record.sample_rate && - aui.play.precision == aui.record.precision && - aui.play.encoding == aui.record.encoding) - break; - if (i < NRETRIES / 2) { - rate = aui.play.sample_rate; - prec = aui.play.precision; - enc = aui.play.encoding; - } else { - rate = aui.record.sample_rate; - prec = aui.record.precision; - enc = aui.record.encoding; - } + AUDIO_INITPAR(&ap); + ap.sig = par->sig; + ap.le = par->le; + ap.bits = par->bits; + ap.bps = par->bps; + ap.msb = par->msb; + ap.rate = par->rate; + if (hdl->sio.mode & SIO_PLAY) + ap.pchan = par->pchan; + if (hdl->sio.mode & SIO_REC) + ap.rchan = par->rchan; + if (par->round != ~0U && par->appbufsz != ~0U) { + ap.round = par->round; + ap.nblks = par->appbufsz / par->round; + } else if (par->round != ~0U) { + ap.round = par->round; + ap.nblks = 2; + } else if (par->appbufsz != ~0U) { + ap.round = par->appbufsz / 2; + ap.nblks = 2; } - - /* - * If the rate that the hardware is using is different than - * the requested rate, scale buffer sizes so they will be the - * same time duration as what was requested. This just gets - * the rates to use for scaling, that actual scaling is done - * later. - */ - rate = (hdl->sio.mode & SIO_REC) ? aui.record.sample_rate : - aui.play.sample_rate; - req_rate = rate; - if (par->rate && par->rate != ~0U) - req_rate = par->rate; - - /* - * if block size and buffer size are not both set then - * set the blocksize to half the buffer size - */ - bufsz = par->appbufsz; - round = par->round; - if (bufsz != ~0U) { - bufsz = bufsz * rate / req_rate; - if (round == ~0U) - round = (bufsz + 1) / 2; - else - round = round * rate / req_rate; - } else if (round != ~0U) { - round = round * rate / req_rate; - bufsz = round * 2; - } else - return 1; - - /* - * get the play/record frame size in bytes - */ - if (ioctl(hdl->fd, AUDIO_GETINFO, &aui) < 0) { - DPERROR("sio_sun_setpar: GETINFO"); + if (ioctl(hdl->fd, AUDIO_SETPAR, &ap) < 0) { + DPERROR("AUDIO_SETPAR"); hdl->sio.eof = 1; return 0; } - ibpf = (hdl->sio.mode & SIO_REC) ? - aui.record.channels * aui.record.bps : 1; - obpf = (hdl->sio.mode & SIO_PLAY) ? - aui.play.channels * aui.play.bps : 1; - - DPRINTFN(2, "sio_sun_setpar: bpf = (%u, %u)\n", ibpf, obpf); - - /* - * try to set parameters until the device accepts - * a common block size for play and record - */ - for (i = 0; i < NRETRIES; i++) { - AUDIO_INITINFO(&aui); - aui.hiwat = (bufsz + round - 1) / round; - aui.lowat = aui.hiwat; - if (hdl->sio.mode & SIO_REC) - aui.record.block_size = round * ibpf; - if (hdl->sio.mode & SIO_PLAY) - aui.play.block_size = round * obpf; - if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0) { - DPERROR("sio_sun_setpar2: SETINFO"); - hdl->sio.eof = 1; - return 0; - } - if (ioctl(hdl->fd, AUDIO_GETINFO, &aui) < 0) { - DPERROR("sio_sun_setpar2: GETINFO"); - hdl->sio.eof = 1; - return 0; - } - infr = aui.record.block_size / ibpf; - onfr = aui.play.block_size / obpf; - DPRINTFN(2, "sio_sun_setpar: %i: round = %u -> (%u, %u)\n", - i, round, infr, onfr); - - /* - * if half-duplex or both block sizes match, we're done - */ - if (hdl->sio.mode != (SIO_REC | SIO_PLAY) || infr == onfr) { - DPRINTFN(2, "sio_sun_setpar: blocksize ok\n"); - return 1; - } - - /* - * half of the retries, retry with the smaller value, - * then with the larger returned value - */ - if (i < NRETRIES / 2) - round = infr < onfr ? infr : onfr; - else - round = infr < onfr ? onfr : infr; - } - DPRINTFN(2, "sio_sun_setpar: couldn't find a working blocksize\n"); - hdl->sio.eof = 1; - return 0; -#undef NRETRIES + return 1; } static int sio_sun_getpar(struct sio_hdl *sh, struct sio_par *par) { struct sio_sun_hdl *hdl = (struct sio_sun_hdl *)sh; - struct audio_info aui; + struct audio_swpar ap; - if (ioctl(hdl->fd, AUDIO_GETINFO, &aui) < 0) { - DPERROR("sio_sun_getpar: getinfo"); + if (ioctl(hdl->fd, AUDIO_GETPAR, &ap) < 0) { + DPERROR("AUDIO_GETPAR"); hdl->sio.eof = 1; return 0; } - if (hdl->sio.mode & SIO_PLAY) { - par->rate = aui.play.sample_rate; - if (!sio_sun_infotoenc(hdl, &aui.play, par)) - return 0; - } else if (hdl->sio.mode & SIO_REC) { - par->rate = aui.record.sample_rate; - if (!sio_sun_infotoenc(hdl, &aui.record, par)) - return 0; - } else - return 0; - par->pchan = (hdl->sio.mode & SIO_PLAY) ? - aui.play.channels : 0; - par->rchan = (hdl->sio.mode & SIO_REC) ? - aui.record.channels : 0; - par->round = (hdl->sio.mode & SIO_REC) ? - aui.record.block_size / (par->bps * par->rchan) : - aui.play.block_size / (par->bps * par->pchan); - par->appbufsz = aui.hiwat * par->round; - par->bufsz = par->appbufsz; + par->sig = ap.sig; + par->le = ap.le; + par->bits = ap.bits; + par->bps = ap.bps; + par->msb = ap.msb; + par->rate = ap.rate; + par->pchan = ap.pchan; + par->rchan = ap.rchan; + par->round = ap.round; + par->appbufsz = par->bufsz = ap.nblks * ap.round; par->xrun = SIO_IGNORE; return 1; } @@ -756,38 +489,6 @@ sio_sun_read(struct sio_hdl *sh, void *buf, size_t len) return n; } -static size_t -sio_sun_autostart(struct sio_sun_hdl *hdl) -{ - struct audio_info aui; - struct pollfd pfd; - - pfd.fd = hdl->fd; - pfd.events = POLLOUT; - while (poll(&pfd, 1, 0) < 0) { - if (errno == EINTR) - continue; - DPERROR("sio_sun_autostart: poll"); - hdl->sio.eof = 1; - return 0; - } - if (!(pfd.revents & POLLOUT)) { - hdl->filling = 0; - AUDIO_INITINFO(&aui); - if (hdl->sio.mode & SIO_PLAY) - aui.play.pause = 0; - if (hdl->sio.mode & SIO_REC) - aui.record.pause = 0; - if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0) { - DPERROR("sio_sun_autostart: setinfo"); - hdl->sio.eof = 1; - return 0; - } - _sio_onmove_cb(&hdl->sio, 0); - } - return 1; -} - static size_t sio_sun_write(struct sio_hdl *sh, const void *buf, size_t len) { @@ -805,10 +506,6 @@ sio_sun_write(struct sio_hdl *sh, const void *buf, size_t len) } return 0; } - if (hdl->filling) { - if (!sio_sun_autostart(hdl)) - return 0; - } return n; } @@ -825,6 +522,15 @@ sio_sun_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events) pfd->fd = hdl->fd; pfd->events = events; + if (hdl->filltodo > 0 && hdl->sio.wused == hdl->filltodo) { + hdl->filltodo = 0; + if (ioctl(hdl->fd, AUDIO_START) < 0) { + DPERROR("AUDIO_START"); + hdl->sio.eof = 1; + return 0; + } + _sio_onmove_cb(&hdl->sio, 0); + } return 1; } @@ -836,7 +542,8 @@ sio_sun_revents(struct sio_hdl *sh, struct pollfd *pfd) int dierr = 0, doerr = 0, offset, delta; int revents = pfd->revents; - if (!hdl->sio.started) + if ((pfd->revents & POLLHUP) || + (pfd->revents & (POLLIN | POLLOUT)) == 0) return pfd->revents; if (ioctl(hdl->fd, AUDIO_GETPOS, &ap) < 0) { DPERROR("sio_sun_revents: GETPOS"); @@ -894,9 +601,6 @@ sio_sun_revents(struct sio_hdl *sh, struct pollfd *pfd) hdl->idelta -= delta; hdl->odelta -= delta; } - - if (hdl->filling) - revents |= POLLOUT; /* XXX: is this necessary ? */ return revents; } #endif /* defined USE_SUN */ From 8070eb627270adddbd0a11b0ba1c111ea73eb7f8 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 23 Mar 2016 07:40:46 +0100 Subject: [PATCH 067/117] Remove unused arguments of dev_adjpar(), getbasepath() and all slotops->onvol() implementations. From David CARLIER . Thanks. --- sndiod/abuf.h | 6 +++--- sndiod/dev.c | 8 ++++---- sndiod/dev.h | 4 ++-- sndiod/sndiod.c | 8 ++++---- sndiod/sock.c | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/sndiod/abuf.h b/sndiod/abuf.h index 45d74d9..8a52ebd 100644 --- a/sndiod/abuf.h +++ b/sndiod/abuf.h @@ -18,9 +18,9 @@ #define ABUF_H struct abuf { - int start; /* offset (frames) where stored data starts */ - int used; /* frames stored in the buffer */ - int len; /* total size of the buffer (frames) */ + int start; /* offset (frames) where stored data starts */ + int used; /* frames stored in the buffer */ + unsigned int len; /* total size of the buffer (frames) */ unsigned char *data; }; diff --git a/sndiod/dev.c b/sndiod/dev.c index 2c9f549..6285dd8 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -28,7 +28,7 @@ #include "utils.h" void zomb_onmove(void *); -void zomb_onvol(void *, unsigned int); +void zomb_onvol(void *); void zomb_fill(void *); void zomb_flush(void *); void zomb_eof(void *); @@ -60,7 +60,7 @@ void dev_cycle(struct dev *); int dev_getpos(struct dev *); struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); -void dev_adjpar(struct dev *, int, int, int, int, int); +void dev_adjpar(struct dev *, int, int, int); int dev_open(struct dev *); void dev_close(struct dev *); int dev_ref(struct dev *); @@ -160,7 +160,7 @@ zomb_onmove(void *arg) } void -zomb_onvol(void *arg, unsigned int vol) +zomb_onvol(void *arg) { } @@ -1022,7 +1022,7 @@ dev_new(char *path, struct aparams *par, */ void dev_adjpar(struct dev *d, int mode, - int pmin, int pmax, int rmin, int rmax) + int pmax, int rmax) { d->reqmode |= mode & MODE_AUDIOMASK; if (mode & MODE_PLAY) { diff --git a/sndiod/dev.h b/sndiod/dev.h index 15b40f4..2e35838 100644 --- a/sndiod/dev.h +++ b/sndiod/dev.h @@ -28,7 +28,7 @@ struct slotops { void (*onmove)(void *); /* clock tick */ - void (*onvol)(void *, unsigned int); /* tell client vol changed */ + void (*onvol)(void *); /* tell client vol changed */ void (*fill)(void *); /* request to fill a play block */ void (*flush)(void *); /* request to flush a rec block */ void (*eof)(void *); /* notify that play drained */ @@ -196,7 +196,7 @@ struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); struct dev *dev_bynum(int); void dev_del(struct dev *); -void dev_adjpar(struct dev *, int, int, int, int, int); +void dev_adjpar(struct dev *, int, int, int); int dev_init(struct dev *); void dev_done(struct dev *); int dev_ref(struct dev *); diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index e0b6672..2d1a897 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -91,7 +91,7 @@ int opt_mmc(void); int opt_onoff(void); int getword(char *, char **); unsigned int opt_mode(void); -void getbasepath(char *, size_t); +void getbasepath(char *); void setsig(void); void unsetsig(void); struct dev *mkdev(char *, struct aparams *, @@ -251,7 +251,7 @@ unsetsig(void) } void -getbasepath(char *base, size_t size) +getbasepath(char *base) { uid_t uid; struct stat sb; @@ -328,7 +328,7 @@ mkopt(char *path, struct dev *d, MIDI_TO_ADATA(vol), mmc, dup, mode); if (o == NULL) return NULL; - dev_adjpar(d, o->mode, o->pmin, o->pmax, o->rmin, o->rmax); + dev_adjpar(d, o->mode, o->pmax, o->rmax); return o; } @@ -474,7 +474,7 @@ main(int argc, char **argv) mode, vol, mmc, dup) == NULL) return 1; } - getbasepath(base, sizeof(base)); + getbasepath(base); snprintf(path, SOCKPATH_MAX, "%s/" SOCKPATH_FILE "%u", base, unit); if (!listen_new_un(path)) return 1; diff --git a/sndiod/sock.c b/sndiod/sock.c index b840cec..a6bf1ea 100644 --- a/sndiod/sock.c +++ b/sndiod/sock.c @@ -39,7 +39,7 @@ void sock_slot_fill(void *); void sock_slot_flush(void *); void sock_slot_eof(void *); void sock_slot_onmove(void *); -void sock_slot_onvol(void *, unsigned int); +void sock_slot_onvol(void *); void sock_midi_imsg(void *, unsigned char *, int); void sock_midi_omsg(void *, unsigned char *, int); void sock_midi_fill(void *, int); @@ -227,7 +227,7 @@ sock_slot_onmove(void *arg) } void -sock_slot_onvol(void *arg, unsigned int delta) +sock_slot_onvol(void *arg) { struct sock *f = (struct sock *)arg; struct slot *s = f->slot; From 20a7e3c46e3b9ee9eb35afb248e5932473de36bf Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Mon, 16 May 2016 07:53:05 +0200 Subject: [PATCH 068/117] switch back into using a single "filling" flag to determine whether playback is started --- libsndio/sio_sun.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libsndio/sio_sun.c b/libsndio/sio_sun.c index 901dca5..e32cf40 100644 --- a/libsndio/sio_sun.c +++ b/libsndio/sio_sun.c @@ -42,7 +42,7 @@ struct sio_sun_hdl { struct sio_hdl sio; int fd; - int filltodo; + int filling; unsigned int ibpf, obpf; /* bytes per frame */ unsigned int ibytes, obytes; /* bytes the hw transferred */ unsigned int ierr, oerr; /* frames the hw dropped */ @@ -326,6 +326,7 @@ sio_sun_fdopen(int fd, unsigned int mode, int nbio) return NULL; } hdl->fd = fd; + hdl->filling = 0; return (struct sio_hdl *)hdl; } @@ -372,10 +373,10 @@ sio_sun_start(struct sio_hdl *sh) if (hdl->sio.mode & SIO_PLAY) { /* - * keep the device paused and let sio_sun_write() trigger the + * keep the device paused and let sio_sun_pollfd() trigger the * start later, to avoid buffer underruns */ - hdl->filltodo = hdl->sio.par.bufsz * hdl->obpf; + hdl->filling = 1; } else { /* * no play buffers to fill, start now! @@ -385,7 +386,6 @@ sio_sun_start(struct sio_hdl *sh) hdl->sio.eof = 1; return 0; } - hdl->filltodo = 0; _sio_onmove_cb(&hdl->sio, 0); } return 1; @@ -396,8 +396,10 @@ sio_sun_stop(struct sio_hdl *sh) { struct sio_sun_hdl *hdl = (struct sio_sun_hdl *)sh; - if (hdl->filltodo > 0) + if (hdl->filling) { + hdl->filling = 0; return 1; + } if (ioctl(hdl->fd, AUDIO_STOP) < 0) { DPERROR("AUDIO_STOP"); hdl->sio.eof = 1; @@ -522,8 +524,9 @@ sio_sun_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events) pfd->fd = hdl->fd; pfd->events = events; - if (hdl->filltodo > 0 && hdl->sio.wused == hdl->filltodo) { - hdl->filltodo = 0; + if (hdl->filling && hdl->sio.wused == hdl->sio.par.bufsz * + hdl->sio.par.pchan * hdl->sio.par.bps) { + hdl->filling = 0; if (ioctl(hdl->fd, AUDIO_START) < 0) { DPERROR("AUDIO_START"); hdl->sio.eof = 1; From d08df26185a7f88f773546af38f5400da75fe6dd Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Mon, 16 May 2016 08:37:40 +0200 Subject: [PATCH 069/117] make init.d.sndiod executable --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index 8fa76ac..a06d7f5 100755 --- a/configure +++ b/configure @@ -204,6 +204,8 @@ do < $f.in > $f done +chmod +x contrib/init.d.sndiod + cat < Date: Wed, 25 May 2016 12:17:48 +0200 Subject: [PATCH 070/117] Don't log blocked read or write. --- sndiod/siofile.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sndiod/siofile.c b/sndiod/siofile.c index eb40528..0127d07 100644 --- a/sndiod/siofile.c +++ b/sndiod/siofile.c @@ -353,11 +353,6 @@ dev_sio_run(void *arg) n = sio_read(d->sio.hdl, data, d->sio.todo); d->sio.todo -= n; #ifdef DEBUG - if (log_level >= 3 && - n == 0 && data == base && !sio_eof(d->sio.hdl)) { - dev_log(d); - log_puts(": read blocked at cycle start\n"); - } if (log_level >= 4) { dev_log(d); log_puts(": read "); @@ -437,11 +432,6 @@ dev_sio_run(void *arg) n = sio_write(d->sio.hdl, data, d->sio.todo); d->sio.todo -= n; #ifdef DEBUG - if (log_level >= 3 && - n == 0 && data == base && !sio_eof(d->sio.hdl)) { - dev_log(d); - log_puts(": write blocked at cycle start\n"); - } if (log_level >= 4) { dev_log(d); log_puts(": wrote "); From a6ea35ebb3875d988ed2165cef45db6e80877837 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 26 May 2016 08:16:17 +0200 Subject: [PATCH 071/117] Make format conversion routines return the number of frames consumed on both input and output. No behaviour change. --- aucat/aucat.c | 90 +++++++++++++++++++++++++-------------------------- aucat/dsp.c | 15 +++++---- aucat/dsp.h | 2 +- 3 files changed, 55 insertions(+), 52 deletions(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index 0605ff7..46ae099 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -426,38 +426,36 @@ slot_del(struct slot *s) xfree(s); } -static int -play_filt_resamp(struct slot *s, void *res_in, void *out, int todo) +static void +play_filt_resamp(struct slot *s, void *res_in, void *out, int *icnt, int *ocnt) { int i, offs, vol, nch; void *in; if (s->resampbuf) { - todo = resamp_do(&s->resamp, - res_in, s->resampbuf, todo); + resamp_do(&s->resamp, res_in, s->resampbuf, icnt, ocnt); in = s->resampbuf; } else in = res_in; nch = s->cmap.nch; vol = s->vol / s->join; /* XXX */ - cmap_add(&s->cmap, in, out, vol, todo); + cmap_add(&s->cmap, in, out, vol, *ocnt); offs = 0; for (i = s->join - 1; i > 0; i--) { offs += nch; - cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, todo); + cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, *ocnt); } offs = 0; for (i = s->expand - 1; i > 0; i--) { offs += nch; - cmap_add(&s->cmap, in, (adata_t *)out + offs, vol, todo); + cmap_add(&s->cmap, in, (adata_t *)out + offs, vol, *ocnt); } - return todo; } -static int -play_filt_dec(struct slot *s, void *in, void *out, int todo) +static void +play_filt_dec(struct slot *s, void *in, void *out, int *icnt, int *ocnt) { void *tmp; @@ -465,20 +463,21 @@ play_filt_dec(struct slot *s, void *in, void *out, int todo) if (tmp) { switch (s->afile.fmt) { case AFILE_FMT_PCM: - dec_do(&s->conv, in, tmp, todo); + dec_do(&s->conv, in, tmp, *icnt); break; case AFILE_FMT_ULAW: - dec_do_ulaw(&s->conv, in, tmp, todo, 0); + dec_do_ulaw(&s->conv, in, tmp, *icnt, 0); break; case AFILE_FMT_ALAW: - dec_do_ulaw(&s->conv, in, tmp, todo, 1); + dec_do_ulaw(&s->conv, in, tmp, *icnt, 1); break; case AFILE_FMT_FLOAT: - dec_do_float(&s->conv, in, tmp, todo); + dec_do_float(&s->conv, in, tmp, *icnt); break; } - } - return play_filt_resamp(s, tmp ? tmp : in, out, todo); + } else + tmp = in; + play_filt_resamp(s, tmp, out, icnt, ocnt); } /* @@ -490,25 +489,26 @@ static int slot_mix_badd(struct slot *s, adata_t *odata) { adata_t *idata; - int icount, todo, done; + int len, icnt, ocnt; - idata = (adata_t *)abuf_rgetblk(&s->buf, &icount); - todo = icount / s->bpf; - if (todo > s->round) - todo = s->round; + idata = (adata_t *)abuf_rgetblk(&s->buf, &len); + icnt = len / s->bpf; + if (icnt > s->round) + icnt = s->round; #ifdef DEBUG - if (todo == 0) { + if (icnt == 0) { log_puts("slot_mix_badd: not enough data\n"); panic(); } #endif - done = play_filt_dec(s, idata, odata, todo); - abuf_rdiscard(&s->buf, todo * s->bpf); - return done; + ocnt = dev_round; + play_filt_dec(s, idata, odata, &icnt, &ocnt); + abuf_rdiscard(&s->buf, icnt * s->bpf); + return ocnt; } -static int -rec_filt_resamp(struct slot *s, void *in, void *res_out, int todo) +static void +rec_filt_resamp(struct slot *s, void *in, void *res_out, int *icnt, int *ocnt) { int i, vol, offs, nch; void *out = res_out; @@ -517,35 +517,33 @@ rec_filt_resamp(struct slot *s, void *in, void *res_out, int todo) nch = s->cmap.nch; vol = ADATA_UNIT / s->join; - cmap_copy(&s->cmap, in, out, vol, todo); + cmap_copy(&s->cmap, in, out, vol, *icnt); offs = 0; for (i = s->join - 1; i > 0; i--) { offs += nch; - cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, todo); + cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, *icnt); } offs = 0; for (i = s->expand - 1; i > 0; i--) { offs += nch; - cmap_copy(&s->cmap, in, (adata_t *)out + offs, vol, todo); + cmap_copy(&s->cmap, in, (adata_t *)out + offs, vol, *icnt); } - if (s->resampbuf) { - todo = resamp_do(&s->resamp, - s->resampbuf, res_out, todo); - } - return todo; + if (s->resampbuf) + resamp_do(&s->resamp, s->resampbuf, res_out, icnt, ocnt); + else + *ocnt = *icnt; } -static int -rec_filt_enc(struct slot *s, void *in, void *out, int todo) +static void +rec_filt_enc(struct slot *s, void *in, void *out, int *icnt, int *ocnt) { void *tmp; tmp = s->convbuf; - todo = rec_filt_resamp(s, in, tmp ? tmp : out, todo); + rec_filt_resamp(s, in, tmp ? tmp : out, icnt, ocnt); if (tmp) - enc_do(&s->conv, tmp, out, todo); - return todo; + enc_do(&s->conv, tmp, out, *ocnt); } /* @@ -556,17 +554,19 @@ static void slot_sub_bcopy(struct slot *s, adata_t *idata, int todo) { adata_t *odata; - int ocount; + int len, icnt, ocnt; - odata = (adata_t *)abuf_wgetblk(&s->buf, &ocount); + odata = (adata_t *)abuf_wgetblk(&s->buf, &len); #ifdef DEBUG - if (ocount < s->round * s->bpf) { + if (len < s->round * s->bpf) { log_puts("slot_sub_bcopy: not enough space\n"); panic(); } #endif - ocount = rec_filt_enc(s, idata, odata, todo); - abuf_wcommit(&s->buf, ocount * s->bpf); + icnt = todo; + ocnt = len / s->bpf; + rec_filt_enc(s, idata, odata, &icnt, &ocnt); + abuf_wcommit(&s->buf, ocnt * s->bpf); } static int diff --git a/aucat/dsp.c b/aucat/dsp.c index f118d64..840abe4 100644 --- a/aucat/dsp.c +++ b/aucat/dsp.c @@ -270,8 +270,8 @@ aparams_native(struct aparams *par) /* * resample the given number of frames */ -int -resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo) +void +resamp_do(struct resamp *p, adata_t *in, adata_t *out, int *icnt, int *ocnt) { unsigned int nch; adata_t *idata; @@ -298,8 +298,8 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo) ctxbuf = p->ctx; ctx_start = p->ctx_start; nch = p->nch; - ifr = todo; - ofr = oblksz; + ifr = *icnt; + ofr = *ocnt; /* * Start conversion. @@ -307,9 +307,11 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo) #ifdef DEBUG if (log_level >= 4) { log_puts("resamp: copying "); - log_puti(todo); + log_puti(ifr); log_puts(" frames, diff = "); log_putu(diff); + log_puts(", max = "); + log_putu(ofr); log_puts("\n"); } #endif @@ -359,7 +361,8 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo) } p->diff = diff; p->ctx_start = ctx_start; - return oblksz - ofr; + *icnt -= ifr; + *ocnt -= ofr; } /* diff --git a/aucat/dsp.h b/aucat/dsp.h index f790466..7582cd3 100644 --- a/aucat/dsp.h +++ b/aucat/dsp.h @@ -147,7 +147,7 @@ int aparams_strtoenc(struct aparams *, char *); int aparams_enctostr(struct aparams *, char *); int aparams_native(struct aparams *); -int resamp_do(struct resamp *, adata_t *, adata_t *, int); +void resamp_do(struct resamp *, adata_t *, adata_t *, int *, int *); void resamp_init(struct resamp *, unsigned int, unsigned int, int); void enc_do(struct conv *, unsigned char *, unsigned char *, int); void enc_sil_do(struct conv *, unsigned char *, int); From 4772005ac1b930cdfaa228652b0bc02463dd1e03 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 27 May 2016 17:36:53 +0200 Subject: [PATCH 072/117] Give the resamp_do() the exact number input and output samples and provide routines to calculate them. This way we don't rely on it anymore to calculate the bytes procuded/consumed. No behaviour change. --- aucat/aucat.c | 105 ++++++++++++++++++++++++++++++-------------------- aucat/dsp.c | 58 +++++++++++++++++++++++----- aucat/dsp.h | 4 +- 3 files changed, 116 insertions(+), 51 deletions(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index 46ae099..b8729d0 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -426,8 +426,20 @@ slot_del(struct slot *s) xfree(s); } +static int +slot_ocnt(struct slot *s, int icnt) +{ + return s->resampbuf ? resamp_ocnt(&s->resamp, icnt) : icnt; +} + +static int +slot_icnt(struct slot *s, int ocnt) +{ + return s->resampbuf ? resamp_icnt(&s->resamp, ocnt) : ocnt; +} + static void -play_filt_resamp(struct slot *s, void *res_in, void *out, int *icnt, int *ocnt) +play_filt_resamp(struct slot *s, void *res_in, void *out, int icnt, int ocnt) { int i, offs, vol, nch; void *in; @@ -440,22 +452,22 @@ play_filt_resamp(struct slot *s, void *res_in, void *out, int *icnt, int *ocnt) nch = s->cmap.nch; vol = s->vol / s->join; /* XXX */ - cmap_add(&s->cmap, in, out, vol, *ocnt); + cmap_add(&s->cmap, in, out, vol, ocnt); offs = 0; for (i = s->join - 1; i > 0; i--) { offs += nch; - cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, *ocnt); + cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, ocnt); } offs = 0; for (i = s->expand - 1; i > 0; i--) { offs += nch; - cmap_add(&s->cmap, in, (adata_t *)out + offs, vol, *ocnt); + cmap_add(&s->cmap, in, (adata_t *)out + offs, vol, ocnt); } } static void -play_filt_dec(struct slot *s, void *in, void *out, int *icnt, int *ocnt) +play_filt_dec(struct slot *s, void *in, void *out, int icnt, int ocnt) { void *tmp; @@ -463,16 +475,16 @@ play_filt_dec(struct slot *s, void *in, void *out, int *icnt, int *ocnt) if (tmp) { switch (s->afile.fmt) { case AFILE_FMT_PCM: - dec_do(&s->conv, in, tmp, *icnt); + dec_do(&s->conv, in, tmp, icnt); break; case AFILE_FMT_ULAW: - dec_do_ulaw(&s->conv, in, tmp, *icnt, 0); + dec_do_ulaw(&s->conv, in, tmp, icnt, 0); break; case AFILE_FMT_ALAW: - dec_do_ulaw(&s->conv, in, tmp, *icnt, 1); + dec_do_ulaw(&s->conv, in, tmp, icnt, 1); break; case AFILE_FMT_FLOAT: - dec_do_float(&s->conv, in, tmp, *icnt); + dec_do_float(&s->conv, in, tmp, icnt); break; } } else @@ -489,26 +501,32 @@ static int slot_mix_badd(struct slot *s, adata_t *odata) { adata_t *idata; - int len, icnt, ocnt; + int len, icnt, ocnt, otodo, odone; - idata = (adata_t *)abuf_rgetblk(&s->buf, &len); - icnt = len / s->bpf; - if (icnt > s->round) - icnt = s->round; -#ifdef DEBUG - if (icnt == 0) { - log_puts("slot_mix_badd: not enough data\n"); - panic(); + odone = 0; + otodo = dev_round; + while (otodo > 0) { + idata = (adata_t *)abuf_rgetblk(&s->buf, &len); + + icnt = len / s->bpf; + ocnt = slot_ocnt(s, icnt); + if (ocnt > otodo) { + ocnt = otodo; + icnt = slot_icnt(s, ocnt); + } + if (icnt == 0) + break; + play_filt_dec(s, idata, odata, icnt, ocnt); + abuf_rdiscard(&s->buf, icnt * s->bpf); + otodo -= ocnt; + odone += ocnt; + odata += ocnt * dev_pchan; } -#endif - ocnt = dev_round; - play_filt_dec(s, idata, odata, &icnt, &ocnt); - abuf_rdiscard(&s->buf, icnt * s->bpf); - return ocnt; + return odone; } static void -rec_filt_resamp(struct slot *s, void *in, void *res_out, int *icnt, int *ocnt) +rec_filt_resamp(struct slot *s, void *in, void *res_out, int icnt, int ocnt) { int i, vol, offs, nch; void *out = res_out; @@ -517,33 +535,33 @@ rec_filt_resamp(struct slot *s, void *in, void *res_out, int *icnt, int *ocnt) nch = s->cmap.nch; vol = ADATA_UNIT / s->join; - cmap_copy(&s->cmap, in, out, vol, *icnt); + cmap_copy(&s->cmap, in, out, vol, icnt); offs = 0; for (i = s->join - 1; i > 0; i--) { offs += nch; - cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, *icnt); + cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, icnt); } offs = 0; for (i = s->expand - 1; i > 0; i--) { offs += nch; - cmap_copy(&s->cmap, in, (adata_t *)out + offs, vol, *icnt); + cmap_copy(&s->cmap, in, (adata_t *)out + offs, vol, icnt); } if (s->resampbuf) resamp_do(&s->resamp, s->resampbuf, res_out, icnt, ocnt); else - *ocnt = *icnt; + ocnt = icnt; } static void -rec_filt_enc(struct slot *s, void *in, void *out, int *icnt, int *ocnt) +rec_filt_enc(struct slot *s, void *in, void *out, int icnt, int ocnt) { void *tmp; tmp = s->convbuf; rec_filt_resamp(s, in, tmp ? tmp : out, icnt, ocnt); if (tmp) - enc_do(&s->conv, tmp, out, *ocnt); + enc_do(&s->conv, tmp, out, ocnt); } /* @@ -551,22 +569,27 @@ rec_filt_enc(struct slot *s, void *in, void *out, int *icnt, int *ocnt) * but not more than a block. */ static void -slot_sub_bcopy(struct slot *s, adata_t *idata, int todo) +slot_sub_bcopy(struct slot *s, adata_t *idata, int itodo) { adata_t *odata; int len, icnt, ocnt; - odata = (adata_t *)abuf_wgetblk(&s->buf, &len); -#ifdef DEBUG - if (len < s->round * s->bpf) { - log_puts("slot_sub_bcopy: not enough space\n"); - panic(); + while (itodo > 0) { + odata = (adata_t *)abuf_wgetblk(&s->buf, &len); + + ocnt = len / s->bpf; + icnt = slot_icnt(s, ocnt); + if (icnt > itodo) { + icnt = itodo; + ocnt = slot_ocnt(s, icnt); + } + if (ocnt == 0) + break; + rec_filt_enc(s, idata, odata, icnt, ocnt); + abuf_wcommit(&s->buf, ocnt * s->bpf); + itodo -= icnt; + idata += icnt * dev_rchan; } -#endif - icnt = todo; - ocnt = len / s->bpf; - rec_filt_enc(s, idata, odata, &icnt, &ocnt); - abuf_wcommit(&s->buf, ocnt * s->bpf); } static int diff --git a/aucat/dsp.c b/aucat/dsp.c index 840abe4..a1479d5 100644 --- a/aucat/dsp.c +++ b/aucat/dsp.c @@ -268,10 +268,38 @@ aparams_native(struct aparams *par) } /* - * resample the given number of frames + * return the number of output frames resamp_do() would produce with + * the given number of input frames + */ +int +resamp_ocnt(struct resamp *p, int icnt) +{ + return ((long long)p->oblksz * icnt + p->diff) / p->iblksz; +} + +/* + * return the number of input frames resamp_do() needs in order to + * produce the given number of output frames + */ +int +resamp_icnt(struct resamp *p, int ocnt) +{ + return ((long long)p->iblksz * ocnt - p->diff + + p->oblksz - 1) / p->oblksz; +} + +/* + * Resample the given number of frames. The number of output frames + * must match the coresponding number the input frames. Either + * use: + * + * icnt * orate = ocnt * irate + * + * or use resamp_icnt() or resamp_ocnt() to calculate the proper + * numbers. */ void -resamp_do(struct resamp *p, adata_t *in, adata_t *out, int *icnt, int *ocnt) +resamp_do(struct resamp *p, adata_t *in, adata_t *out, int icnt, int ocnt) { unsigned int nch; adata_t *idata; @@ -298,8 +326,8 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int *icnt, int *ocnt) ctxbuf = p->ctx; ctx_start = p->ctx_start; nch = p->nch; - ifr = *icnt; - ofr = *ocnt; + ifr = icnt; + ofr = ocnt; /* * Start conversion. @@ -308,10 +336,10 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int *icnt, int *ocnt) if (log_level >= 4) { log_puts("resamp: copying "); log_puti(ifr); - log_puts(" frames, diff = "); - log_putu(diff); - log_puts(", max = "); + log_puts(" -> "); log_putu(ofr); + log_puts(" frames, diff = "); + log_puti(diff); log_puts("\n"); } #endif @@ -361,8 +389,20 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int *icnt, int *ocnt) } p->diff = diff; p->ctx_start = ctx_start; - *icnt -= ifr; - *ocnt -= ofr; +#ifdef DEBUG + if (ifr != 0) { + log_puts("resamp_do: "); + log_puti(ifr); + log_puts(": too many input frames\n"); + panic(); + } + if (ofr != 0) { + log_puts("resamp_do: "); + log_puti(ofr); + log_puts(": too many output frames\n"); + panic(); + } +#endif } /* diff --git a/aucat/dsp.h b/aucat/dsp.h index 7582cd3..5a1df5e 100644 --- a/aucat/dsp.h +++ b/aucat/dsp.h @@ -147,7 +147,9 @@ int aparams_strtoenc(struct aparams *, char *); int aparams_enctostr(struct aparams *, char *); int aparams_native(struct aparams *); -void resamp_do(struct resamp *, adata_t *, adata_t *, int *, int *); +int resamp_ocnt(struct resamp *, int); +int resamp_icnt(struct resamp *, int); +void resamp_do(struct resamp *, adata_t *, adata_t *, int, int); void resamp_init(struct resamp *, unsigned int, unsigned int, int); void enc_do(struct conv *, unsigned char *, unsigned char *, int); void enc_sil_do(struct conv *, unsigned char *, int); From 06c8f4e89f9705f05e4b6d1b301370db62e2fa94 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 27 May 2016 17:46:09 +0200 Subject: [PATCH 073/117] Simplify slot_fill() and slot_flush(). No behaviour change --- aucat/aucat.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index b8729d0..29f171f 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -158,14 +158,13 @@ slot_log(struct slot *s) static void slot_flush(struct slot *s) { - int todo, count, n; + int count, n; unsigned char *data; - todo = s->buf.used; - while (todo > 0) { + for (;;) { data = abuf_rgetblk(&s->buf, &count); - if (count > todo) - count = todo; + if (count == 0) + break; n = afile_write(&s->afile, data, count); if (n == 0) { slot_log(s); @@ -174,21 +173,19 @@ slot_flush(struct slot *s) return; } abuf_rdiscard(&s->buf, n); - todo -= n; } } static void slot_fill(struct slot *s) { - int todo, count, n; + int count, n; unsigned char *data; - todo = s->buf.len; - while (todo > 0) { + for (;;) { data = abuf_wgetblk(&s->buf, &count); - if (count > todo) - count = todo; + if (count == 0) + break; n = afile_read(&s->afile, data, count); if (n == 0) { #ifdef DEBUG @@ -201,7 +198,6 @@ slot_fill(struct slot *s) break; } abuf_wcommit(&s->buf, n); - todo -= n; } } From b347c528699dbbf77ab3b697371243d69d5e7dba Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 27 May 2016 18:00:23 +0200 Subject: [PATCH 074/117] Flush rec buffer if there's less than one block space left and fill play buffer if there's less than one block of data left. No behaviour change, as all input/output are still block-aligned. --- aucat/aucat.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index 29f171f..d1ac25b 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -978,9 +978,11 @@ slot_list_iodo(void) for (s = slot_list; s != NULL; s = s->next) { if (s->pstate != SLOT_RUN) continue; - if ((s->mode & SIO_PLAY) && (s->buf.used == 0)) + if ((s->mode & SIO_PLAY) && + (s->buf.used < s->round * s->bpf)) slot_fill(s); - if ((s->mode & SIO_REC) && (s->buf.used == s->buf.len)) + if ((s->mode & SIO_REC) && + (s->buf.len - s->buf.used < s->round * s->bpf)) slot_flush(s); } } From 028bb6e60da6d97217224171996f8c6d07614468 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 27 May 2016 18:17:05 +0200 Subject: [PATCH 075/117] When resampling, use the exact resampling factor instead of the ration between input and output block sizes. This was inherited from sndion, but is not required for files because they are continuous streams of samples and do not need to be split in blocks of equal duration. This change makes playback/recording rate match exactly the requested sample rate. --- aucat/aucat.c | 4 ++-- aucat/dsp.c | 30 +++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index d1ac25b..4a866ab 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -311,7 +311,7 @@ slot_init(struct slot *s) xmalloc(s->round * slot_nch * sizeof(adata_t)); } if (s->afile.rate != dev_rate) { - resamp_init(&s->resamp, s->round, dev_round, + resamp_init(&s->resamp, s->afile.rate, dev_rate, slot_nch); s->resampbuf = xmalloc(dev_round * slot_nch * sizeof(adata_t)); @@ -330,7 +330,7 @@ slot_init(struct slot *s) s->cmin, s->cmax, s->cmin, s->cmax); if (s->afile.rate != dev_rate) { - resamp_init(&s->resamp, dev_round, s->round, + resamp_init(&s->resamp, dev_rate, s->afile.rate, slot_nch); s->resampbuf = xmalloc(dev_round * slot_nch * sizeof(adata_t)); diff --git a/aucat/dsp.c b/aucat/dsp.c index a1479d5..b525632 100644 --- a/aucat/dsp.c +++ b/aucat/dsp.c @@ -405,6 +405,19 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int icnt, int ocnt) #endif } +static unsigned int +uint_gcd(unsigned int a, unsigned int b) +{ + unsigned int r; + + while (b > 0) { + r = a % b; + a = b; + b = r; + } + return a; +} + /* * initialize resampler with ibufsz/obufsz factor and "nch" channels */ @@ -412,7 +425,22 @@ void resamp_init(struct resamp *p, unsigned int iblksz, unsigned int oblksz, int nch) { - unsigned int i; + unsigned int i, g; + + /* + * reduice iblksz/oblksz fraction + */ + g = uint_gcd(iblksz, oblksz); + iblksz /= g; + oblksz /= g; + + /* + * ensure weired rates dont cause integer overflows + */ + while (iblksz > ADATA_UNIT || oblksz > ADATA_UNIT) { + iblksz >>= 1; + oblksz >>= 1; + } p->iblksz = iblksz; p->oblksz = oblksz; From e6063514216d14ae70a1bfe470a805bd3e9d5907 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 28 May 2016 09:28:57 +0200 Subject: [PATCH 076/117] Fix file block size rounding and ensure it's large enough to store a full audio block. --- aucat/aucat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index 4a866ab..7a5e2f6 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -271,7 +271,7 @@ slot_init(struct slot *s) } #endif s->bpf = s->afile.par.bps * (s->cmax - s->cmin + 1); - s->round = (dev_round * s->afile.rate + dev_rate / 2) / dev_rate; + s->round = (dev_round * s->afile.rate + dev_rate - 1) / dev_rate; bufsz = s->round * (dev_bufsz / dev_round); bufsz -= bufsz % s->round; From 0798868306693119dd509fbce6707b89aa8ad5a9 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 31 May 2016 10:37:17 +0200 Subject: [PATCH 077/117] To store MMC position, use samples (at device rate) as time units instead of 2400-ths of second. No behaviour change. --- aucat/aucat.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index 7a5e2f6..8c68b06 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -103,7 +103,7 @@ unsigned int dev_round; /* device block size */ int dev_rate; /* device sample rate (Hz) */ unsigned int dev_pchan, dev_rchan; /* play & rec channels count */ adata_t *dev_pbuf, *dev_rbuf; /* play & rec buffers */ -unsigned int dev_mmcpos; /* last MMC position */ +long long dev_pos; /* last MMC position in frames */ #define DEV_STOP 0 /* stopped */ #define DEV_START 1 /* started */ unsigned int dev_pstate; /* one of above */ @@ -351,10 +351,8 @@ slot_init(struct slot *s) } static void -slot_start(struct slot *s, unsigned int mmc) +slot_start(struct slot *s, long long pos) { - off_t mmcpos; - #ifdef DEBUG if (s->pstate != SLOT_INIT) { slot_log(s); @@ -362,8 +360,15 @@ slot_start(struct slot *s, unsigned int mmc) panic(); } #endif - mmcpos = ((off_t)mmc * s->afile.rate / MTC_SEC) * s->bpf; - if (!afile_seek(&s->afile, mmcpos)) { + /* + * convert pos to slot sample rate + * + * At this stage, we could adjust s->resamp.diff to get + * sub-frame accuracy. + */ + pos = pos * s->afile.rate / dev_rate; + + if (!afile_seek(&s->afile, pos * s->bpf)) { s->pstate = SLOT_INIT; return; } @@ -662,7 +667,7 @@ dev_open(char *dev, int mode, int bufsz, char *port) dev_rchan = par.rchan; dev_rbuf = xmalloc(sizeof(adata_t) * dev_rchan * dev_round); } - dev_mmcpos = 0; + dev_pos = 0; dev_pstate = DEV_STOP; if (log_level >= 2) { log_puts(dev_name); @@ -753,7 +758,7 @@ dev_mmcstart(void) if (dev_pstate == DEV_STOP) { dev_pstate = DEV_START; for (s = slot_list; s != NULL; s = s->next) - slot_start(s, dev_mmcpos); + slot_start(s, dev_pos); dev_prime = (dev_mode & SIO_PLAY) ? dev_bufsz / dev_round : 0; sio_start(dev_sh); if (log_level >= 2) @@ -795,18 +800,23 @@ dev_mmcstop(void) static void dev_mmcloc(unsigned int mmc) { - if (dev_mmcpos == mmc) + long long pos; + + pos = mmc * dev_rate / MTC_SEC; + if (dev_pos == pos) return; - dev_mmcpos = mmc; + dev_pos = pos; if (log_level >= 2) { log_puts("relocated to "); - log_putu((dev_mmcpos / (MTC_SEC * 3600)) % 24); + log_putu((mmc / (MTC_SEC * 3600)) % 24); log_puts(":"); - log_putu((dev_mmcpos / (MTC_SEC * 60)) % 60); + log_putu((mmc / (MTC_SEC * 60)) % 60); log_puts(":"); - log_putu((dev_mmcpos / (MTC_SEC)) % 60); + log_putu((mmc / (MTC_SEC)) % 60); log_puts("."); - log_putu((dev_mmcpos / (MTC_SEC / 100)) % 100); + log_putu((mmc / (MTC_SEC / 100)) % 100); + log_puts("."); + log_putu((mmc / (MTC_SEC / 100)) % 100); log_puts("\n"); } if (dev_pstate == DEV_START) { @@ -1010,7 +1020,7 @@ offline(void) dev_pchan = dev_rchan = cmax + 1; dev_pbuf = dev_rbuf = xmalloc(sizeof(adata_t) * dev_pchan * dev_round); dev_pstate = DEV_STOP; - dev_mmcpos = 0; + dev_pos = 0; for (s = slot_list; s != NULL; s = s->next) slot_init(s); for (s = slot_list; s != NULL; s = s->next) From 2ce73a1421f8a5ca122c6119c7642b1497439508 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 31 May 2016 11:24:42 +0200 Subject: [PATCH 078/117] Pass hr:min:sec:frame.cent to dev_mmcloc() and remove useless intermediate conversion to 2400-th of second. --- aucat/aucat.c | 35 +++++++++++++++++++++++------------ aucat/defs.h | 5 ----- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index 8c68b06..308bcef 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -798,25 +798,35 @@ dev_mmcstop(void) * relocate all slots simultaneously */ static void -dev_mmcloc(unsigned int mmc) +dev_mmcloc(int hr, int min, int sec, int fr, int cent, int fps) { long long pos; - pos = mmc * dev_rate / MTC_SEC; + pos = dev_rate * hr * 3600 + + dev_rate * min * 60 + + dev_rate * sec + + dev_rate * fr / fps + + dev_rate * cent / (100 * fps); if (dev_pos == pos) return; dev_pos = pos; if (log_level >= 2) { log_puts("relocated to "); - log_putu((mmc / (MTC_SEC * 3600)) % 24); + log_putu(hr); log_puts(":"); - log_putu((mmc / (MTC_SEC * 60)) % 60); + log_putu(min); log_puts(":"); - log_putu((mmc / (MTC_SEC)) % 60); + log_putu(sec); log_puts("."); - log_putu((mmc / (MTC_SEC / 100)) % 100); + log_putu(fr); log_puts("."); - log_putu((mmc / (MTC_SEC / 100)) % 100); + log_putu(cent); + log_puts(" at "); + log_putu(fps); + log_puts("fps\n"); + + log_puts("pos: "); + log_putu(pos); log_puts("\n"); } if (dev_pstate == DEV_START) { @@ -880,11 +890,12 @@ dev_imsg(unsigned char *msg, unsigned int len) dev_mmcstop(); return; } - dev_mmcloc((x->u.loc.hr & 0x1f) * 3600 * MTC_SEC + - x->u.loc.min * 60 * MTC_SEC + - x->u.loc.sec * MTC_SEC + - x->u.loc.fr * (MTC_SEC / fps) + - x->u.loc.cent * (MTC_SEC / 100 / fps)); + dev_mmcloc(x->u.loc.hr & 0x1f, + x->u.loc.min, + x->u.loc.sec, + x->u.loc.fr, + x->u.loc.cent, + fps); break; } } diff --git a/aucat/defs.h b/aucat/defs.h index 0820cf5..6cfc877 100644 --- a/aucat/defs.h +++ b/aucat/defs.h @@ -17,11 +17,6 @@ #ifndef DEFS_H #define DEFS_H -/* - * units used for MTC clock. - */ -#define MTC_SEC 2400 /* 1 second is 2400 ticks */ - /* * limits */ From 751fe73f18941c2edf54dccbc7a2677f4bb05f6f Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 31 May 2016 23:21:15 +0200 Subject: [PATCH 079/117] backout mtc units removal --- aucat/aucat.1 | 10 ++++++++ aucat/aucat.c | 63 +++++++++++++++++---------------------------------- aucat/defs.h | 5 ++++ 3 files changed, 36 insertions(+), 42 deletions(-) diff --git a/aucat/aucat.1 b/aucat/aucat.1 index 446311d..94b658e 100644 --- a/aucat/aucat.1 +++ b/aucat/aucat.1 @@ -27,10 +27,12 @@ .Op Fl c Ar min : Ns Ar max .Op Fl e Ar enc .Op Fl f Ar device +.Op Fl g Ar position .Op Fl h Ar fmt .Op Fl i Ar file .Op Fl j Ar flag .Op Fl o Ar file +.Op Fl p Ar position .Op Fl q Ar port .Op Fl r Ar rate .Op Fl v Ar volume @@ -117,6 +119,10 @@ audio device. Device mode and parameters are determined from audio files. Default is .Pa default . +.It Fl g Ar position +Go to the given time position and start playback or recording there. +This option is equivalent to an incoming MMC relocate message +with the same position. .It Fl h Ar fmt Audio file type. The following file types are supported: @@ -169,6 +175,10 @@ Record into this audio file. If the option argument is .Sq - then standard output will be used. +.It Fl p Ar position +Time offset where the beginning of the file belongs. +The first sample of the file will be played or recorded when the current +position reaches the given postion. .It Fl q Ar port Control audio device properties through this MIDI port. This includes per-stream volumes and the ability to diff --git a/aucat/aucat.c b/aucat/aucat.c index 308bcef..7a5e2f6 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -103,7 +103,7 @@ unsigned int dev_round; /* device block size */ int dev_rate; /* device sample rate (Hz) */ unsigned int dev_pchan, dev_rchan; /* play & rec channels count */ adata_t *dev_pbuf, *dev_rbuf; /* play & rec buffers */ -long long dev_pos; /* last MMC position in frames */ +unsigned int dev_mmcpos; /* last MMC position */ #define DEV_STOP 0 /* stopped */ #define DEV_START 1 /* started */ unsigned int dev_pstate; /* one of above */ @@ -351,8 +351,10 @@ slot_init(struct slot *s) } static void -slot_start(struct slot *s, long long pos) +slot_start(struct slot *s, unsigned int mmc) { + off_t mmcpos; + #ifdef DEBUG if (s->pstate != SLOT_INIT) { slot_log(s); @@ -360,15 +362,8 @@ slot_start(struct slot *s, long long pos) panic(); } #endif - /* - * convert pos to slot sample rate - * - * At this stage, we could adjust s->resamp.diff to get - * sub-frame accuracy. - */ - pos = pos * s->afile.rate / dev_rate; - - if (!afile_seek(&s->afile, pos * s->bpf)) { + mmcpos = ((off_t)mmc * s->afile.rate / MTC_SEC) * s->bpf; + if (!afile_seek(&s->afile, mmcpos)) { s->pstate = SLOT_INIT; return; } @@ -667,7 +662,7 @@ dev_open(char *dev, int mode, int bufsz, char *port) dev_rchan = par.rchan; dev_rbuf = xmalloc(sizeof(adata_t) * dev_rchan * dev_round); } - dev_pos = 0; + dev_mmcpos = 0; dev_pstate = DEV_STOP; if (log_level >= 2) { log_puts(dev_name); @@ -758,7 +753,7 @@ dev_mmcstart(void) if (dev_pstate == DEV_STOP) { dev_pstate = DEV_START; for (s = slot_list; s != NULL; s = s->next) - slot_start(s, dev_pos); + slot_start(s, dev_mmcpos); dev_prime = (dev_mode & SIO_PLAY) ? dev_bufsz / dev_round : 0; sio_start(dev_sh); if (log_level >= 2) @@ -798,35 +793,20 @@ dev_mmcstop(void) * relocate all slots simultaneously */ static void -dev_mmcloc(int hr, int min, int sec, int fr, int cent, int fps) +dev_mmcloc(unsigned int mmc) { - long long pos; - - pos = dev_rate * hr * 3600 + - dev_rate * min * 60 + - dev_rate * sec + - dev_rate * fr / fps + - dev_rate * cent / (100 * fps); - if (dev_pos == pos) + if (dev_mmcpos == mmc) return; - dev_pos = pos; + dev_mmcpos = mmc; if (log_level >= 2) { log_puts("relocated to "); - log_putu(hr); + log_putu((dev_mmcpos / (MTC_SEC * 3600)) % 24); log_puts(":"); - log_putu(min); + log_putu((dev_mmcpos / (MTC_SEC * 60)) % 60); log_puts(":"); - log_putu(sec); + log_putu((dev_mmcpos / (MTC_SEC)) % 60); log_puts("."); - log_putu(fr); - log_puts("."); - log_putu(cent); - log_puts(" at "); - log_putu(fps); - log_puts("fps\n"); - - log_puts("pos: "); - log_putu(pos); + log_putu((dev_mmcpos / (MTC_SEC / 100)) % 100); log_puts("\n"); } if (dev_pstate == DEV_START) { @@ -890,12 +870,11 @@ dev_imsg(unsigned char *msg, unsigned int len) dev_mmcstop(); return; } - dev_mmcloc(x->u.loc.hr & 0x1f, - x->u.loc.min, - x->u.loc.sec, - x->u.loc.fr, - x->u.loc.cent, - fps); + dev_mmcloc((x->u.loc.hr & 0x1f) * 3600 * MTC_SEC + + x->u.loc.min * 60 * MTC_SEC + + x->u.loc.sec * MTC_SEC + + x->u.loc.fr * (MTC_SEC / fps) + + x->u.loc.cent * (MTC_SEC / 100 / fps)); break; } } @@ -1031,7 +1010,7 @@ offline(void) dev_pchan = dev_rchan = cmax + 1; dev_pbuf = dev_rbuf = xmalloc(sizeof(adata_t) * dev_pchan * dev_round); dev_pstate = DEV_STOP; - dev_pos = 0; + dev_mmcpos = 0; for (s = slot_list; s != NULL; s = s->next) slot_init(s); for (s = slot_list; s != NULL; s = s->next) diff --git a/aucat/defs.h b/aucat/defs.h index 6cfc877..0820cf5 100644 --- a/aucat/defs.h +++ b/aucat/defs.h @@ -17,6 +17,11 @@ #ifndef DEFS_H #define DEFS_H +/* + * units used for MTC clock. + */ +#define MTC_SEC 2400 /* 1 second is 2400 ticks */ + /* * limits */ From aaf9583451ab38742f41ddcf9ab552465fdc120b Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 31 May 2016 23:25:38 +0200 Subject: [PATCH 080/117] backout latest --- aucat/aucat.1 | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/aucat/aucat.1 b/aucat/aucat.1 index 94b658e..446311d 100644 --- a/aucat/aucat.1 +++ b/aucat/aucat.1 @@ -27,12 +27,10 @@ .Op Fl c Ar min : Ns Ar max .Op Fl e Ar enc .Op Fl f Ar device -.Op Fl g Ar position .Op Fl h Ar fmt .Op Fl i Ar file .Op Fl j Ar flag .Op Fl o Ar file -.Op Fl p Ar position .Op Fl q Ar port .Op Fl r Ar rate .Op Fl v Ar volume @@ -119,10 +117,6 @@ audio device. Device mode and parameters are determined from audio files. Default is .Pa default . -.It Fl g Ar position -Go to the given time position and start playback or recording there. -This option is equivalent to an incoming MMC relocate message -with the same position. .It Fl h Ar fmt Audio file type. The following file types are supported: @@ -175,10 +169,6 @@ Record into this audio file. If the option argument is .Sq - then standard output will be used. -.It Fl p Ar position -Time offset where the beginning of the file belongs. -The first sample of the file will be played or recorded when the current -position reaches the given postion. .It Fl q Ar port Control audio device properties through this MIDI port. This includes per-stream volumes and the ability to From c22cfa6294b28e628a0a7607a58dd369e158cc36 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 2 Jun 2016 06:55:59 +0200 Subject: [PATCH 081/117] sync to openbsd: remove again intermediate conversion to mtc time --- aucat/aucat.c | 63 ++++++++++++++++++++++++++++++++++----------------- aucat/defs.h | 5 ---- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index 7a5e2f6..308bcef 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -103,7 +103,7 @@ unsigned int dev_round; /* device block size */ int dev_rate; /* device sample rate (Hz) */ unsigned int dev_pchan, dev_rchan; /* play & rec channels count */ adata_t *dev_pbuf, *dev_rbuf; /* play & rec buffers */ -unsigned int dev_mmcpos; /* last MMC position */ +long long dev_pos; /* last MMC position in frames */ #define DEV_STOP 0 /* stopped */ #define DEV_START 1 /* started */ unsigned int dev_pstate; /* one of above */ @@ -351,10 +351,8 @@ slot_init(struct slot *s) } static void -slot_start(struct slot *s, unsigned int mmc) +slot_start(struct slot *s, long long pos) { - off_t mmcpos; - #ifdef DEBUG if (s->pstate != SLOT_INIT) { slot_log(s); @@ -362,8 +360,15 @@ slot_start(struct slot *s, unsigned int mmc) panic(); } #endif - mmcpos = ((off_t)mmc * s->afile.rate / MTC_SEC) * s->bpf; - if (!afile_seek(&s->afile, mmcpos)) { + /* + * convert pos to slot sample rate + * + * At this stage, we could adjust s->resamp.diff to get + * sub-frame accuracy. + */ + pos = pos * s->afile.rate / dev_rate; + + if (!afile_seek(&s->afile, pos * s->bpf)) { s->pstate = SLOT_INIT; return; } @@ -662,7 +667,7 @@ dev_open(char *dev, int mode, int bufsz, char *port) dev_rchan = par.rchan; dev_rbuf = xmalloc(sizeof(adata_t) * dev_rchan * dev_round); } - dev_mmcpos = 0; + dev_pos = 0; dev_pstate = DEV_STOP; if (log_level >= 2) { log_puts(dev_name); @@ -753,7 +758,7 @@ dev_mmcstart(void) if (dev_pstate == DEV_STOP) { dev_pstate = DEV_START; for (s = slot_list; s != NULL; s = s->next) - slot_start(s, dev_mmcpos); + slot_start(s, dev_pos); dev_prime = (dev_mode & SIO_PLAY) ? dev_bufsz / dev_round : 0; sio_start(dev_sh); if (log_level >= 2) @@ -793,20 +798,35 @@ dev_mmcstop(void) * relocate all slots simultaneously */ static void -dev_mmcloc(unsigned int mmc) +dev_mmcloc(int hr, int min, int sec, int fr, int cent, int fps) { - if (dev_mmcpos == mmc) + long long pos; + + pos = dev_rate * hr * 3600 + + dev_rate * min * 60 + + dev_rate * sec + + dev_rate * fr / fps + + dev_rate * cent / (100 * fps); + if (dev_pos == pos) return; - dev_mmcpos = mmc; + dev_pos = pos; if (log_level >= 2) { log_puts("relocated to "); - log_putu((dev_mmcpos / (MTC_SEC * 3600)) % 24); + log_putu(hr); log_puts(":"); - log_putu((dev_mmcpos / (MTC_SEC * 60)) % 60); + log_putu(min); log_puts(":"); - log_putu((dev_mmcpos / (MTC_SEC)) % 60); + log_putu(sec); log_puts("."); - log_putu((dev_mmcpos / (MTC_SEC / 100)) % 100); + log_putu(fr); + log_puts("."); + log_putu(cent); + log_puts(" at "); + log_putu(fps); + log_puts("fps\n"); + + log_puts("pos: "); + log_putu(pos); log_puts("\n"); } if (dev_pstate == DEV_START) { @@ -870,11 +890,12 @@ dev_imsg(unsigned char *msg, unsigned int len) dev_mmcstop(); return; } - dev_mmcloc((x->u.loc.hr & 0x1f) * 3600 * MTC_SEC + - x->u.loc.min * 60 * MTC_SEC + - x->u.loc.sec * MTC_SEC + - x->u.loc.fr * (MTC_SEC / fps) + - x->u.loc.cent * (MTC_SEC / 100 / fps)); + dev_mmcloc(x->u.loc.hr & 0x1f, + x->u.loc.min, + x->u.loc.sec, + x->u.loc.fr, + x->u.loc.cent, + fps); break; } } @@ -1010,7 +1031,7 @@ offline(void) dev_pchan = dev_rchan = cmax + 1; dev_pbuf = dev_rbuf = xmalloc(sizeof(adata_t) * dev_pchan * dev_round); dev_pstate = DEV_STOP; - dev_mmcpos = 0; + dev_pos = 0; for (s = slot_list; s != NULL; s = s->next) slot_init(s); for (s = slot_list; s != NULL; s = s->next) diff --git a/aucat/defs.h b/aucat/defs.h index 0820cf5..6cfc877 100644 --- a/aucat/defs.h +++ b/aucat/defs.h @@ -17,11 +17,6 @@ #ifndef DEFS_H #define DEFS_H -/* - * units used for MTC clock. - */ -#define MTC_SEC 2400 /* 1 second is 2400 ticks */ - /* * limits */ From 474f0ce00948125dc705d898a3976bda8bf207db Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 2 Jun 2016 07:07:58 +0200 Subject: [PATCH 082/117] set exit status to 1 if -n is used without -i and -o --- aucat/aucat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index 308bcef..e0d6d5f 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -1393,7 +1393,7 @@ main(int argc, char **argv) } if (mode != (SIO_PLAY | SIO_REC)) { log_puts("both -i and -o required\n"); - return 0; + return 1; } if (!offline()) return 1; From a6fdc3b5ed5d4a492899e60b7d0c31491b10fcfb Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 2 Jun 2016 07:30:30 +0200 Subject: [PATCH 083/117] remove forgotten debug printfs --- aucat/aucat.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index e0d6d5f..2b7b48d 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -824,10 +824,6 @@ dev_mmcloc(int hr, int min, int sec, int fr, int cent, int fps) log_puts(" at "); log_putu(fps); log_puts("fps\n"); - - log_puts("pos: "); - log_putu(pos); - log_puts("\n"); } if (dev_pstate == DEV_START) { dev_mmcstop(); From 2562fa7eb4ec3145be3d2c044b8eb29e11874e1a Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 2 Jun 2016 18:14:10 +0200 Subject: [PATCH 084/117] add -g and -p option to control device and file start position --- aucat/aucat.1 | 12 +++++++++ aucat/aucat.c | 69 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/aucat/aucat.1 b/aucat/aucat.1 index 446311d..ed0b162 100644 --- a/aucat/aucat.1 +++ b/aucat/aucat.1 @@ -27,10 +27,12 @@ .Op Fl c Ar min : Ns Ar max .Op Fl e Ar enc .Op Fl f Ar device +.Op Fl g Ar position .Op Fl h Ar fmt .Op Fl i Ar file .Op Fl j Ar flag .Op Fl o Ar file +.Op Fl p Ar position .Op Fl q Ar port .Op Fl r Ar rate .Op Fl v Ar volume @@ -117,6 +119,11 @@ audio device. Device mode and parameters are determined from audio files. Default is .Pa default . +.It Fl g Ar position +Go to the given time position and start playback or recording there. +This option is equivalent to an incoming MMC relocate message +with the same position. +The position is expressed as the number of samples (at device sample rate). .It Fl h Ar fmt Audio file type. The following file types are supported: @@ -169,6 +176,11 @@ Record into this audio file. If the option argument is .Sq - then standard output will be used. +.It Fl p Ar position +Time offset where the beginning of the file belongs. +The first sample of the file will be played or recorded when the device +reaches the given postion. +The position is expressed as the number of samples (at device sample rate). .It Fl q Ar port Control audio device properties through this MIDI port. This includes per-stream volumes and the ability to diff --git a/aucat/aucat.c b/aucat/aucat.c index 2b7b48d..caaf9a2 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -91,6 +92,8 @@ struct slot { #define SLOT_RUN 2 /* playing/recording */ #define SLOT_STOP 3 /* draining (play only) */ int pstate; /* one of above */ + long long skip; /* frames to skip at the beginning */ + long long pos; /* start position (at device rate) */ struct afile afile; /* file desc & friends */ }; @@ -135,8 +138,9 @@ unsigned int voice_len[] = { 3, 3, 3, 3, 2, 2, 3 }; unsigned int common_len[] = { 0, 2, 3, 2, 0, 0, 1, 1 }; char usagestr[] = "usage: aucat [-dn] [-b size] " - "[-c min:max] [-e enc] [-f device] [-h fmt]\n\t" - "[-i file] [-j flag] [-o file] [-q port] [-r rate] [-v volume]\n"; + "[-c min:max] [-e enc] [-f device] [-g position]\n\t" + "[-h fmt] [-i file] [-j flag] [-o file] [-p position] [-q port]\n\t" + "[-r rate] [-v volume]\n"; static void slot_log(struct slot *s) @@ -203,7 +207,7 @@ slot_fill(struct slot *s) static int slot_new(char *path, int mode, struct aparams *par, int hdr, - int cmin, int cmax, int rate, int dup, int vol) + int cmin, int cmax, int rate, int dup, int vol, long long pos) { struct slot *s; @@ -220,6 +224,7 @@ slot_new(char *path, int mode, struct aparams *par, int hdr, s->vol = MIDI_TO_ADATA(vol); s->mode = mode; s->pstate = SLOT_CFG; + s->pos = pos; if (log_level >= 2) { slot_log(s); log_puts(": "); @@ -360,6 +365,13 @@ slot_start(struct slot *s, long long pos) panic(); } #endif + pos -= s->pos; + if (pos < 0) { + s->skip = -pos; + pos = 0; + } else + s->skip = 0; + /* * convert pos to slot sample rate * @@ -506,6 +518,15 @@ slot_mix_badd(struct slot *s, adata_t *odata) odone = 0; otodo = dev_round; + if (s->skip > 0) { + ocnt = otodo; + if (ocnt > s->skip) + ocnt = s->skip; + s->skip -= ocnt; + odata += dev_pchan * ocnt; + otodo -= ocnt; + odone += ocnt; + } while (otodo > 0) { idata = (adata_t *)abuf_rgetblk(&s->buf, &len); @@ -575,6 +596,15 @@ slot_sub_bcopy(struct slot *s, adata_t *idata, int itodo) adata_t *odata; int len, icnt, ocnt; + if (s->skip > 0) { + icnt = itodo; + if (icnt > s->skip) + icnt = s->skip; + s->skip -= icnt; + idata += dev_rchan * icnt; + itodo -= icnt; + } + while (itodo > 0) { odata = (adata_t *)abuf_wgetblk(&s->buf, &len); @@ -667,7 +697,6 @@ dev_open(char *dev, int mode, int bufsz, char *port) dev_rchan = par.rchan; dev_rbuf = xmalloc(sizeof(adata_t) * dev_rchan * dev_round); } - dev_pos = 0; dev_pstate = DEV_STOP; if (log_level >= 2) { log_puts(dev_name); @@ -1027,7 +1056,6 @@ offline(void) dev_pchan = dev_rchan = cmax + 1; dev_pbuf = dev_rbuf = xmalloc(sizeof(adata_t) * dev_pchan * dev_round); dev_pstate = DEV_STOP; - dev_pos = 0; for (s = slot_list; s != NULL; s = s->next) slot_init(s); for (s = slot_list; s != NULL; s = s->next) @@ -1296,6 +1324,20 @@ opt_num(char *s, int min, int max, int *num) return 1; } +static int +opt_pos(char *s, long long *pos) +{ + const char *errstr; + + *pos = strtonum(s, 0, LLONG_MAX, &errstr); + if (errstr) { + log_puts(s); + log_puts(": positive number of samples expected\n"); + return 0; + } + return 1; +} + int main(int argc, char **argv) { @@ -1303,6 +1345,7 @@ main(int argc, char **argv) char *port, *dev; struct aparams par; int n_flag, c; + long long pos; vol = 127; dup = 0; @@ -1316,8 +1359,10 @@ main(int argc, char **argv) port = NULL; dev = NULL; mode = 0; + pos = 0; - while ((c = getopt(argc, argv, "b:c:de:f:h:i:j:no:q:r:t:v:")) != -1) { + while ((c = getopt(argc, argv, + "b:c:de:f:g:h:i:j:no:p:q:r:t:v:")) != -1) { switch (c) { case 'b': if (!opt_num(optarg, 1, RATE_MAX, &bufsz)) @@ -1337,13 +1382,17 @@ main(int argc, char **argv) case 'f': dev = optarg; break; + case 'g': + if (!opt_pos(optarg, &dev_pos)) + return 1; + break; case 'h': if (!opt_hdr(optarg, &hdr)) return 1; break; case 'i': if (!slot_new(optarg, SIO_PLAY, - &par, hdr, cmin, cmax, rate, dup, vol)) + &par, hdr, cmin, cmax, rate, dup, vol, pos)) return 1; mode |= SIO_PLAY; break; @@ -1356,10 +1405,14 @@ main(int argc, char **argv) break; case 'o': if (!slot_new(optarg, SIO_REC, - &par, hdr, cmin, cmax, rate, dup, 0)) + &par, hdr, cmin, cmax, rate, dup, 0, pos)) return 1; mode |= SIO_REC; break; + case 'p': + if (!opt_pos(optarg, &pos)) + return 1; + break; case 'q': port = optarg; break; From 00ffc8f5ab2f08705d4bea33f61ffeb256cc84ba Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 7 Jun 2016 08:11:46 +0200 Subject: [PATCH 085/117] Add resamp_getcnt() routine to calculate the exact number of samples that would be consumed and produced by the sampler rate converter. Use it to avoid partial samples that are not properly handled. Fixes last samples of certain files causing aucat to abort. --- aucat/aucat.c | 34 +++++++++++++------------------ aucat/dsp.c | 55 ++++++++++++++++++++++++++++++++------------------- aucat/dsp.h | 3 +-- 3 files changed, 50 insertions(+), 42 deletions(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index caaf9a2..429c444 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -439,16 +439,18 @@ slot_del(struct slot *s) xfree(s); } -static int -slot_ocnt(struct slot *s, int icnt) +static void +slot_getcnt(struct slot *s, int *icnt, int *ocnt) { - return s->resampbuf ? resamp_ocnt(&s->resamp, icnt) : icnt; -} + int cnt; -static int -slot_icnt(struct slot *s, int ocnt) -{ - return s->resampbuf ? resamp_icnt(&s->resamp, ocnt) : ocnt; + if (s->resampbuf) + resamp_getcnt(&s->resamp, icnt, ocnt); + else { + cnt = (*icnt < *ocnt) ? *icnt : *ocnt; + *icnt = cnt; + *ocnt = cnt; + } } static void @@ -529,13 +531,9 @@ slot_mix_badd(struct slot *s, adata_t *odata) } while (otodo > 0) { idata = (adata_t *)abuf_rgetblk(&s->buf, &len); - icnt = len / s->bpf; - ocnt = slot_ocnt(s, icnt); - if (ocnt > otodo) { - ocnt = otodo; - icnt = slot_icnt(s, ocnt); - } + ocnt = otodo; + slot_getcnt(s, &icnt, &ocnt); if (icnt == 0) break; play_filt_dec(s, idata, odata, icnt, ocnt); @@ -607,13 +605,9 @@ slot_sub_bcopy(struct slot *s, adata_t *idata, int itodo) while (itodo > 0) { odata = (adata_t *)abuf_wgetblk(&s->buf, &len); - ocnt = len / s->bpf; - icnt = slot_icnt(s, ocnt); - if (icnt > itodo) { - icnt = itodo; - ocnt = slot_ocnt(s, icnt); - } + icnt = itodo; + slot_getcnt(s, &icnt, &ocnt); if (ocnt == 0) break; rec_filt_enc(s, idata, odata, icnt, ocnt); diff --git a/aucat/dsp.c b/aucat/dsp.c index b525632..034333c 100644 --- a/aucat/dsp.c +++ b/aucat/dsp.c @@ -268,35 +268,50 @@ aparams_native(struct aparams *par) } /* - * return the number of output frames resamp_do() would produce with - * the given number of input frames + * return the number of input and output frame that would + * be consumed */ -int -resamp_ocnt(struct resamp *p, int icnt) +void +resamp_getcnt(struct resamp *p, int *icnt, int *ocnt) { - return ((long long)p->oblksz * icnt + p->diff) / p->iblksz; -} + int diff, ifr, ofr; -/* - * return the number of input frames resamp_do() needs in order to - * produce the given number of output frames - */ -int -resamp_icnt(struct resamp *p, int ocnt) -{ - return ((long long)p->iblksz * ocnt - p->diff + - p->oblksz - 1) / p->oblksz; + diff = p->diff; + ifr = *icnt; + ofr = *ocnt; + + for (;;) { + if (diff < 0) { + if (ifr == 0) + break; + diff += p->oblksz; + ifr--; + } else if (diff > 0) { + if (ofr == 0) + break; + diff -= p->iblksz; + ofr--; + } else { + if (ifr == 0 || ofr == 0) + break; + diff -= p->iblksz; + diff += p->oblksz; + ifr--; + ofr--; + } + } + *icnt -= ifr; + *ocnt -= ofr; } /* * Resample the given number of frames. The number of output frames - * must match the coresponding number the input frames. Either - * use: + * must match the coresponding number the input frames. Either always + * use icnt and ocnt such that: * - * icnt * orate = ocnt * irate + * icnt * oblksz = ocnt * iblksz * - * or use resamp_icnt() or resamp_ocnt() to calculate the proper - * numbers. + * or use resamp_getcnt() to calculate the proper numbers. */ void resamp_do(struct resamp *p, adata_t *in, adata_t *out, int icnt, int ocnt) diff --git a/aucat/dsp.h b/aucat/dsp.h index 5a1df5e..fa07f42 100644 --- a/aucat/dsp.h +++ b/aucat/dsp.h @@ -147,8 +147,7 @@ int aparams_strtoenc(struct aparams *, char *); int aparams_enctostr(struct aparams *, char *); int aparams_native(struct aparams *); -int resamp_ocnt(struct resamp *, int); -int resamp_icnt(struct resamp *, int); +void resamp_getcnt(struct resamp *, int *, int *); void resamp_do(struct resamp *, adata_t *, adata_t *, int, int); void resamp_init(struct resamp *, unsigned int, unsigned int, int); void enc_do(struct conv *, unsigned char *, unsigned char *, int); From b5ed7425595714b383778ee7b9b86064760edf4f Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 8 Jun 2016 06:41:08 +0200 Subject: [PATCH 086/117] remove forgotten debug printfs --- sndiod/dsp.c | 2 -- sndiod/dsp.h | 1 - 2 files changed, 3 deletions(-) diff --git a/sndiod/dsp.c b/sndiod/dsp.c index 731d8c1..f47907a 100644 --- a/sndiod/dsp.c +++ b/sndiod/dsp.c @@ -304,8 +304,6 @@ resamp_init(struct resamp *p, unsigned int iblksz, p->iblksz = iblksz; p->oblksz = oblksz; p->diff = 0; - p->idelta = 0; - p->odelta = 0; p->nch = nch; p->ctx_start = 0; for (i = 0; i < NCHAN_MAX * RESAMP_NCTX; i++) diff --git a/sndiod/dsp.h b/sndiod/dsp.h index 0e278dd..2344b65 100644 --- a/sndiod/dsp.h +++ b/sndiod/dsp.h @@ -116,7 +116,6 @@ struct resamp { adata_t ctx[NCHAN_MAX * RESAMP_NCTX]; unsigned int iblksz, oblksz; int diff; - int idelta, odelta; /* remainder of ipos/opos */ int nch; }; From 10f6027f0fedc01531b3a7539784ac308cb833e9 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 9 Jun 2016 16:43:47 +0200 Subject: [PATCH 087/117] remove unused fields of resamp structure --- aucat/dsp.c | 2 -- aucat/dsp.h | 1 - 2 files changed, 3 deletions(-) diff --git a/aucat/dsp.c b/aucat/dsp.c index 034333c..f71ca51 100644 --- a/aucat/dsp.c +++ b/aucat/dsp.c @@ -460,8 +460,6 @@ resamp_init(struct resamp *p, unsigned int iblksz, p->iblksz = iblksz; p->oblksz = oblksz; p->diff = 0; - p->idelta = 0; - p->odelta = 0; p->nch = nch; p->ctx_start = 0; for (i = 0; i < NCHAN_MAX * RESAMP_NCTX; i++) diff --git a/aucat/dsp.h b/aucat/dsp.h index fa07f42..d057d37 100644 --- a/aucat/dsp.h +++ b/aucat/dsp.h @@ -116,7 +116,6 @@ struct resamp { adata_t ctx[NCHAN_MAX * RESAMP_NCTX]; unsigned int iblksz, oblksz; int diff; - int idelta, odelta; /* remainder of ipos/opos */ int nch; }; From 61005799d97e3dd4f180e37dd0ec96723761049a Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 9 Jun 2016 16:50:56 +0200 Subject: [PATCH 088/117] simpler resampler --- aucat/dsp.c | 70 +++++++++++++---------------------------------------- 1 file changed, 17 insertions(+), 53 deletions(-) diff --git a/aucat/dsp.c b/aucat/dsp.c index f71ca51..1c2b344 100644 --- a/aucat/dsp.c +++ b/aucat/dsp.c @@ -268,40 +268,22 @@ aparams_native(struct aparams *par) } /* - * return the number of input and output frame that would - * be consumed + * Return the number of input and output frame that would be consumed + * by resamp_do(p, *icnt, *ocnt). */ void resamp_getcnt(struct resamp *p, int *icnt, int *ocnt) { - int diff, ifr, ofr; + long long idiff, odiff; + int cdiff; - diff = p->diff; - ifr = *icnt; - ofr = *ocnt; - - for (;;) { - if (diff < 0) { - if (ifr == 0) - break; - diff += p->oblksz; - ifr--; - } else if (diff > 0) { - if (ofr == 0) - break; - diff -= p->iblksz; - ofr--; - } else { - if (ifr == 0 || ofr == 0) - break; - diff -= p->iblksz; - diff += p->oblksz; - ifr--; - ofr--; - } - } - *icnt -= ifr; - *ocnt -= ofr; + cdiff = p->oblksz - p->diff; + idiff = (long long)*icnt * p->oblksz; + odiff = (long long)*ocnt * p->iblksz; + if (odiff - idiff >= cdiff) + *ocnt = (idiff + cdiff + p->iblksz - 1) / p->iblksz; + else + *icnt = (odiff + p->diff) / p->oblksz; } /* @@ -359,7 +341,7 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int icnt, int ocnt) } #endif for (;;) { - if (diff < 0) { + if (diff >= oblksz) { if (ifr == 0) break; ctx_start ^= 1; @@ -368,37 +350,19 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int icnt, int ocnt) *ctx = *idata++; ctx += RESAMP_NCTX; } - diff += oblksz; + diff -= oblksz; ifr--; - } else if (diff > 0) { + } else { if (ofr == 0) break; ctx = ctxbuf; for (c = nch; c > 0; c--) { - s = ctx[ctx_start]; - ds = ctx[ctx_start ^ 1] - s; + s = ctx[ctx_start ^ 1]; + ds = ctx[ctx_start] - s; ctx += RESAMP_NCTX; *odata++ = s + ADATA_MULDIV(ds, diff, oblksz); } - diff -= iblksz; - ofr--; - } else { - if (ifr == 0 || ofr == 0) - break; - ctx = ctxbuf + ctx_start; - for (c = nch; c > 0; c--) { - *odata++ = *ctx; - ctx += RESAMP_NCTX; - } - ctx_start ^= 1; - ctx = ctxbuf + ctx_start; - for (c = nch; c > 0; c--) { - *ctx = *idata++; - ctx += RESAMP_NCTX; - } - diff -= iblksz; - diff += oblksz; - ifr--; + diff += iblksz; ofr--; } } From 02ff6b20fbf863f2a54ed99f958256ff605d434f Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 11 Aug 2016 08:17:57 +0200 Subject: [PATCH 089/117] add braces to reduce diff with mixer bits --- sndiod/dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sndiod/dev.c b/sndiod/dev.c index 6285dd8..ac8110c 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -433,8 +433,9 @@ dev_midi_omsg(void *arg, unsigned char *msg, int len) switch (x->type) { case SYSEX_TYPE_RT: 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); + } return; } if (x->id0 != SYSEX_MMC) From 7ddb1a5fe50d05e4f14348faa3234e9c2cac2dc5 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 27 Sep 2016 09:01:21 +0200 Subject: [PATCH 090/117] Don't rely on the resampling code to calculate the number of samples to process, as it may produce one extra sample (to handle accumulation of fractional samples), which would cause access to one sample past the end of the buffer and crash aucat. Fix this by limiting the number of samples processed to a single block. Found by and help from Michael W. Bombardieri . Thanks. --- aucat/aucat.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aucat/aucat.c b/aucat/aucat.c index 429c444..a3aa212 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -532,6 +532,8 @@ slot_mix_badd(struct slot *s, adata_t *odata) while (otodo > 0) { idata = (adata_t *)abuf_rgetblk(&s->buf, &len); icnt = len / s->bpf; + if (icnt > s->round) + icnt = s->round; ocnt = otodo; slot_getcnt(s, &icnt, &ocnt); if (icnt == 0) @@ -606,6 +608,8 @@ slot_sub_bcopy(struct slot *s, adata_t *idata, int itodo) while (itodo > 0) { odata = (adata_t *)abuf_wgetblk(&s->buf, &len); ocnt = len / s->bpf; + if (ocnt > s->round) + ocnt = s->round; icnt = itodo; slot_getcnt(s, &icnt, &ocnt); if (ocnt == 0) From 2a451f96237dd288b0b651d604c9cdd8ed82c19e Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 27 Sep 2016 14:18:43 +0200 Subject: [PATCH 091/117] Fix many typos, from Michael W. Bombardieri , thanks --- aucat/dsp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aucat/dsp.c b/aucat/dsp.c index 1c2b344..a8ae1ba 100644 --- a/aucat/dsp.c +++ b/aucat/dsp.c @@ -288,7 +288,7 @@ resamp_getcnt(struct resamp *p, int *icnt, int *ocnt) /* * Resample the given number of frames. The number of output frames - * must match the coresponding number the input frames. Either always + * must match the coresponding number of input frames. Either always * use icnt and ocnt such that: * * icnt * oblksz = ocnt * iblksz @@ -407,14 +407,14 @@ resamp_init(struct resamp *p, unsigned int iblksz, unsigned int i, g; /* - * reduice iblksz/oblksz fraction + * reduce iblksz/oblksz fraction */ g = uint_gcd(iblksz, oblksz); iblksz /= g; oblksz /= g; /* - * ensure weired rates dont cause integer overflows + * ensure weird rates don't cause integer overflow */ while (iblksz > ADATA_UNIT || oblksz > ADATA_UNIT) { iblksz >>= 1; @@ -587,7 +587,7 @@ enc_init(struct conv *p, struct aparams *par, int nch) } /* - * decode "todo" frames from from foreign to native encoding + * decode "todo" frames from foreign to native encoding */ void dec_do(struct conv *p, unsigned char *in, unsigned char *out, int todo) @@ -829,7 +829,7 @@ cmap_add(struct cmap *p, void *in, void *out, int vol, int todo) } /* - * overwrite output with "todo" input frames with with the given volume + * overwrite output with "todo" input frames with the given volume */ void cmap_copy(struct cmap *p, void *in, void *out, int vol, int todo) From 7061de025008dfc83dd105da9fe4ba209a77a8d9 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 29 Sep 2016 18:20:18 +0200 Subject: [PATCH 092/117] Set device rate to calculated rate. --- aucat/aucat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/aucat/aucat.c b/aucat/aucat.c index a3aa212..0cee83e 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -665,6 +665,7 @@ dev_open(char *dev, int mode, int bufsz, char *port) par.bps = sizeof(adata_t); par.msb = 0; par.le = SIO_LE_NATIVE; + par.rate = rate; if (mode & SIO_PLAY) par.pchan = pmax + 1; if (mode & SIO_REC) From 33bbca59993c73c66a058049a3f6baf805ca880b Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 20 Oct 2016 07:27:36 +0200 Subject: [PATCH 093/117] drop privs after daemonizing, reorder clean-up --- sndiod/sndiod.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index 2d1a897..3d89cb4 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -374,9 +374,6 @@ main(int argc, char **argv) mode = MODE_PLAY | MODE_REC; tcpaddr_list = NULL; - setsig(); - filelist_init(); - while ((c = getopt(argc, argv, "a:b:c:C:de:f:j:L:m:q:r:s:t:U:v:w:x:z:")) != -1) { switch (c) { case 'd': @@ -474,6 +471,15 @@ main(int argc, char **argv) mode, vol, mmc, dup) == NULL) return 1; } + + setsig(); + filelist_init(); + + if (geteuid() == 0) { + if ((pw = getpwnam(SNDIO_USER)) == NULL) + errx(1, "unknown user %s", SNDIO_USER); + } else + pw = NULL; getbasepath(base); snprintf(path, SOCKPATH_MAX, "%s/" SOCKPATH_FILE "%u", base, unit); if (!listen_new_un(path)) @@ -482,15 +488,9 @@ main(int argc, char **argv) if (!listen_new_tcp(ta->host, AUCAT_PORT + unit)) return 1; } - if (geteuid() == 0) { - if ((pw = getpwnam(SNDIO_USER)) == NULL) - errx(1, "unknown user %s", SNDIO_USER); - if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) < 0) - err(1, "setpriority"); - if (setgroups(1, &pw->pw_gid) || - setgid(pw->pw_gid) || - setuid(pw->pw_uid)) - err(1, "cannot drop privileges"); + for (l = listen_list; l != NULL; l = l->next) { + if (!listen_init(l)) + return 1; } midi_init(); for (p = port_list; p != NULL; p = p->next) { @@ -501,16 +501,20 @@ main(int argc, char **argv) if (!dev_init(d)) return 1; } - for (l = listen_list; l != NULL; l = l->next) { - if (!listen_init(l)) - return 1; - } if (background) { log_flush(); log_level = 0; if (daemon(0, 0) < 0) err(1, "daemon"); } + if (pw != NULL) { + if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) < 0) + err(1, "setpriority"); + if (setgroups(1, &pw->pw_gid) || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) + err(1, "cannot drop privileges"); + } for (;;) { if (quit_flag) break; @@ -521,15 +525,16 @@ main(int argc, char **argv) listen_close(listen_list); while (sock_list != NULL) sock_close(sock_list); - while (opt_list != NULL) - opt_del(opt_list); for (d = dev_list; d != NULL; d = d->next) dev_done(d); for (p = port_list; p != NULL; p = p->next) port_done(p); - midi_done(); while (file_poll()) ; /* nothing */ + midi_done(); + + while (opt_list != NULL) + opt_del(opt_list); while (dev_list) dev_del(dev_list); while (port_list) From 4dcfed9dce5e7c9cd45eaa1428b255089dae1d66 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 20 Oct 2016 07:32:27 +0200 Subject: [PATCH 094/117] remove braces around single-statement block --- sndiod/dev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sndiod/dev.c b/sndiod/dev.c index ac8110c..6285dd8 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -433,9 +433,8 @@ dev_midi_omsg(void *arg, unsigned char *msg, int len) switch (x->type) { case SYSEX_TYPE_RT: 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); - } return; } if (x->id0 != SYSEX_MMC) From 017e60c967cc42fe879a67d693e4dd7d603b57ff Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Mon, 24 Oct 2016 17:05:47 +0200 Subject: [PATCH 095/117] use setgid() and setuid() --- sndiod/sndiod.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index 3d89cb4..83f1cfa 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -511,8 +511,8 @@ main(int argc, char **argv) if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) < 0) err(1, "setpriority"); if (setgroups(1, &pw->pw_gid) || - setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || - setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) + setgid(pw->pw_gid) || + setuid(pw->pw_uid)) err(1, "cannot drop privileges"); } for (;;) { From bcb3014206fbb8dc80f45de8dd6db11c0d4984dd Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 27 Oct 2016 06:38:21 +0200 Subject: [PATCH 096/117] Fix many typos in comments, from Michael W. Bombardieri --- sndiod/dsp.c | 4 ++-- sndiod/file.c | 4 ++-- sndiod/siofile.c | 2 +- sndiod/sock.c | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sndiod/dsp.c b/sndiod/dsp.c index f47907a..c2c6feb 100644 --- a/sndiod/dsp.c +++ b/sndiod/dsp.c @@ -467,7 +467,7 @@ enc_init(struct conv *p, struct aparams *par, int nch) } /* - * decode "todo" frames from from foreign to native encoding + * decode "todo" frames from foreign to native encoding */ void dec_do(struct conv *p, unsigned char *in, unsigned char *out, int todo) @@ -606,7 +606,7 @@ cmap_add(struct cmap *p, void *in, void *out, int vol, int todo) } /* - * overwrite output with "todo" input frames with with the given volume + * overwrite output with "todo" input frames with the given volume */ void cmap_copy(struct cmap *p, void *in, void *out, int vol, int todo) diff --git a/sndiod/file.c b/sndiod/file.c index 4eadb15..4153a6c 100644 --- a/sndiod/file.c +++ b/sndiod/file.c @@ -376,8 +376,8 @@ file_poll(void) } /* - * Sleep. Calculate the number off milliseconds poll(2) must - * wait before the timo_update() needs to be called. If there're + * Sleep. Calculate the number of milliseconds poll(2) must + * wait before the timo_update() needs to be called. If there are * no timeouts scheduled, then call poll(2) with infinite * timeout (i.e -1). */ diff --git a/sndiod/siofile.c b/sndiod/siofile.c index 0127d07..afb762b 100644 --- a/sndiod/siofile.c +++ b/sndiod/siofile.c @@ -135,7 +135,7 @@ dev_sio_open(struct dev *d) #ifdef DEBUG /* - * We support any parameters combination exposed by the kernel, + * We support any parameter combination exposed by the kernel, * and we have no other choice than trusting the kernel for * returning correct parameters. But let's check parameters * early and nicely report kernel bugs rather than crashing diff --git a/sndiod/sock.c b/sndiod/sock.c index a6bf1ea..feac458 100644 --- a/sndiod/sock.c +++ b/sndiod/sock.c @@ -314,7 +314,7 @@ sock_exit(void *arg) } /* - * write on the socke fd and handle errors + * write on the socket fd and handle errors */ int sock_fdwrite(struct sock *f, void *data, int count) @@ -355,7 +355,7 @@ sock_fdwrite(struct sock *f, void *data, int count) } /* - * read from the socke fd and handle errors + * read from the socket fd and handle errors */ int sock_fdread(struct sock *f, void *data, int count) @@ -509,7 +509,7 @@ sock_rdata(struct sock *f) } /* - * read data into the slot/midi ring buffer + * write data to the slot/midi ring buffer */ int sock_wdata(struct sock *f) From d396d690d160e93458fac35a5f46c6215d7b238c Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 3 Nov 2016 08:04:47 +0100 Subject: [PATCH 097/117] Add support for OSS/FreeBSD. From Tobias Kortkamp . --- configure | 23 ++ libsndio/Makefile.in | 4 +- libsndio/sio.c | 4 + libsndio/sio_oss.c | 644 +++++++++++++++++++++++++++++++++++++++++++ libsndio/sio_priv.h | 3 + 5 files changed, 677 insertions(+), 1 deletion(-) create mode 100644 libsndio/sio_oss.c diff --git a/configure b/configure index a06d7f5..13a0394 100755 --- a/configure +++ b/configure @@ -32,6 +32,7 @@ prefix=/usr/local # where to install sndio so="libsndio.so.\${MAJ}.\${MIN}" # shared libs to build alsa=no # do we want alsa support ? sun=no # do we want sun support ? +oss=no # do we want oss support ? rmidi=no # do we want support for raw char dev ? precision=16 # aucat/sndiod arithmetic precision user=_sndio # non-privileged user for sndio daemon @@ -71,6 +72,14 @@ case `uname` in defs='-DHAVE_ARC4RANDOM -DHAVE_ISSETUGID \\\ -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRTONUM' ;; + DragonFly|FreeBSD) + user=_sndio + so="$so libsndio.so" + defs='-DHAVE_ARC4RANDOM -DHAVE_ISSETUGID \\\ + -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRTONUM' + oss=yes + mandir=${prefix}/man + ;; esac # shell word separator (none) @@ -106,6 +115,12 @@ for i; do --disable-alsa) alsa=no shift;; + --enable-oss) + oss=yes + shift;; + --disable-oss) + oss=no + shift;; --enable-sun) sun=yes shift;; @@ -161,6 +176,13 @@ if [ $alsa = yes ]; then ldadd="$ldadd -lasound" fi +# +# if using OSS, add corresponding parameters +# +if [ $oss = yes ]; then + defs="$defs -DUSE_OSS" +fi + # # if using Sun API, add corresponding parameters # @@ -217,6 +239,7 @@ user..................... $user libbsd................... $libbsd precision................ $precision alsa..................... $alsa +oss...................... $oss sun...................... $sun rmidi.................... $rmidi diff --git a/libsndio/Makefile.in b/libsndio/Makefile.in index c888574..4b5f8a7 100644 --- a/libsndio/Makefile.in +++ b/libsndio/Makefile.in @@ -99,7 +99,7 @@ clean: # OBJS = debug.o aucat.o \ mio.o mio_rmidi.o mio_alsa.o mio_aucat.o \ -sio.o sio_alsa.o sio_aucat.o sio_sun.o \ +sio.o sio_alsa.o sio_aucat.o sio_oss.o sio_sun.o \ issetugid.o strlcat.o strlcpy.o strtonum.o .c.o: @@ -140,3 +140,5 @@ sio_aucat.o: sio_aucat.c aucat.h amsg.h debug.h sio_priv.h sndio.h \ ../bsd-compat/bsd-compat.h sio_sun.o: sio_sun.c debug.h sio_priv.h sndio.h \ ../bsd-compat/bsd-compat.h +sio_oss.o: sio_oss.c debug.h sio_priv.h sndio.h \ + ../bsd-compat/bsd-compat.h diff --git a/libsndio/sio.c b/libsndio/sio.c index 456426f..acb7a74 100644 --- a/libsndio/sio.c +++ b/libsndio/sio.c @@ -64,6 +64,8 @@ sio_open(const char *str, unsigned int mode, int nbio) return hdl; #if defined(USE_SUN) return _sio_sun_open("rsnd/0", mode, nbio); +#elif defined(USE_OSS) + return _sio_oss_open("rsnd/0", mode, nbio); #elif defined(USE_ALSA) return _sio_alsa_open("rsnd/0", mode, nbio); #else @@ -75,6 +77,8 @@ sio_open(const char *str, unsigned int mode, int nbio) if (_sndio_parsetype(str, "rsnd")) #if defined(USE_SUN) return _sio_sun_open(str, mode, nbio); +#elif defined(USE_OSS) + return _sio_oss_open(str, mode, nbio); #elif defined(USE_ALSA) return _sio_alsa_open(str, mode, nbio); #else diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c new file mode 100644 index 0000000..b625a4b --- /dev/null +++ b/libsndio/sio_oss.c @@ -0,0 +1,644 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2008 Alexandre Ratchov + * Copyright (c) 2016 Tobias Kortkamp + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef USE_OSS +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "sio_priv.h" +#include "bsd-compat.h" + +#define DEVPATH_PREFIX "/dev/dsp" +#define DEVPATH_MAX (1 + \ + sizeof(DEVPATH_PREFIX) - 1 + \ + sizeof(int) * 3) + +struct sio_oss_fmt { + int fmt; + unsigned int bits; + unsigned int bps; + unsigned int sig; + unsigned int le; + unsigned int msb; +}; +static struct sio_oss_fmt formats[] = { + /* See http://manuals.opensound.com/developer/formats.html. + * AFMT_{S8,U16}_* are marked as obsolete so are missing here. + */ + + /* le+msb not important */ + { AFMT_U8, 8, 1, 0, 0, 0 }, + { AFMT_U8, 8, 1, 0, 1, 0 }, + { AFMT_U8, 8, 1, 0, 0, 1 }, + { AFMT_U8, 8, 1, 0, 1, 1 }, + + /* msb not important */ + { AFMT_S16_BE, 16, 2, 1, 0, 0 }, + { AFMT_S16_BE, 16, 2, 1, 0, 1 }, + { AFMT_S16_LE, 16, 2, 1, 1, 0 }, + { AFMT_S16_LE, 16, 2, 1, 1, 1 }, + { AFMT_S24_BE, 24, 3, 1, 0, 0 }, + { AFMT_S24_BE, 24, 3, 1, 0, 1 }, + { AFMT_S24_LE, 24, 3, 1, 1, 0 }, + { AFMT_S24_LE, 24, 3, 1, 1, 1 }, + { AFMT_U24_BE, 24, 3, 0, 0, 0 }, + { AFMT_U24_BE, 24, 3, 0, 0, 1 }, + { AFMT_U24_LE, 24, 3, 0, 1, 0 }, + { AFMT_U24_LE, 24, 3, 0, 1, 1 }, + + { AFMT_S32_BE, 32, 4, 1, 0, 1 }, + { AFMT_S32_LE, 32, 4, 1, 1, 1 }, + { AFMT_U32_BE, 32, 4, 0, 0, 1 }, + { AFMT_U32_LE, 32, 4, 0, 1, 1 }, +}; + +struct sio_oss_hdl { + struct sio_hdl sio; + int fd; + unsigned int isamples; + unsigned int osamples; + int idelta, odelta; + + int fmt; + unsigned int rate; + unsigned int chan; + unsigned int appbufsz; + unsigned int round; +}; + +static struct sio_hdl *sio_oss_fdopen(const char *, int, unsigned int, int); +static int sio_oss_getcap(struct sio_hdl *, struct sio_cap *); +static int sio_oss_getfd(const char *, unsigned int, int); +static int sio_oss_getpar(struct sio_hdl *, struct sio_par *); +static int sio_oss_nfds(struct sio_hdl *); +static int sio_oss_pollfd(struct sio_hdl *, struct pollfd *, int); +static int sio_oss_revents(struct sio_hdl *, struct pollfd *); +static int sio_oss_setpar(struct sio_hdl *, struct sio_par *); +static int sio_oss_start(struct sio_hdl *); +static int sio_oss_stop(struct sio_hdl *); +static int sio_oss_xrun(struct sio_oss_hdl *); +static size_t sio_oss_read(struct sio_hdl *, void *, size_t); +static size_t sio_oss_write(struct sio_hdl *, const void *, size_t); +static void sio_oss_close(struct sio_hdl *); + +static struct sio_ops sio_oss_ops = { + sio_oss_close, + sio_oss_setpar, + sio_oss_getpar, + sio_oss_getcap, + sio_oss_write, + sio_oss_read, + sio_oss_start, + sio_oss_stop, + sio_oss_nfds, + sio_oss_pollfd, + sio_oss_revents, + NULL, /* setvol */ + NULL, /* getvol */ +}; + +/* + * guess device capabilities + */ +static int +sio_oss_getcap(struct sio_hdl *sh, struct sio_cap *cap) +{ + /* From sound(4): + * The FreeBSD multichannel matrix processor supports up to 18 + * interleaved channels, but the limit is currently set to 8 + * channels (as commonly used for 7.1 surround sound). + */ + static unsigned int chans[] = { + 1, 2, 4, 6, 8 + }; + static unsigned int rates[] = { + 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, + 48000, 64000, 88200, 96000, 192000 + }; + static int afmts[] = { + AFMT_U8, AFMT_S16_LE, AFMT_S16_BE, AFMT_S24_LE, AFMT_U24_LE, + AFMT_S32_LE, AFMT_U32_LE + }; + struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; + unsigned int nconf = 0; + unsigned int enc_map = 0, rchan_map = 0, pchan_map = 0, rate_map; + unsigned int i, j, k, conf; + int fmts; + + if (ioctl(hdl->fd, SNDCTL_DSP_GETFMTS, &fmts) < 0) { + DPERROR("sio_oss_getcap: GETFMTS"); + hdl->sio.eof = 1; + return 0; + } + + /* + * get a subset of supported encodings + */ + for (j = 0, i = 0; i < sizeof(afmts) / sizeof(afmts[0]); i++) { + if (fmts & afmts[i]) { + for (k = 0; k < sizeof(formats) / sizeof(formats[0]); k++) { + if (formats[k].fmt == afmts[i]) { + cap->enc[j].sig = formats[k].sig; + cap->enc[j].bits = formats[k].bits; + cap->enc[j].bps = formats[k].bps; + cap->enc[j].le = formats[k].le; + cap->enc[j].msb = formats[k].msb; + enc_map |= 1 << j; + j++; + break; + } + } + } + } + + /* + * fill channels + */ + if (hdl->sio.mode & SIO_PLAY) { + for (i = 0; i < sizeof(chans) / sizeof(chans[0]); i++) { + cap->pchan[i] = chans[i]; + pchan_map |= (1 << i); + } + } + if (hdl->sio.mode & SIO_REC) { + for (i = 0; i < sizeof(chans) / sizeof(chans[0]); i++) { + cap->rchan[i] = chans[i]; + rchan_map |= (1 << i); + } + } + + /* + * fill rates + */ + for (j = 0; j < sizeof(formats) / sizeof(formats[0]); j++) { + rate_map = 0; + if ((enc_map & (1 << j)) == 0) + continue; + for (i = 0; i < sizeof(rates) / sizeof(rates[0]); i++) { + cap->rate[i] = rates[i]; + rate_map |= (1 << i); + } + for (conf = 0; conf < nconf; conf++) { + if (cap->confs[conf].rate == rate_map) { + cap->confs[conf].enc |= (1 << j); + break; + } + } + if (conf == nconf) { + if (nconf == SIO_NCONF) + break; + cap->confs[nconf].enc = (1 << j); + cap->confs[nconf].pchan = pchan_map; + cap->confs[nconf].rchan = rchan_map; + cap->confs[nconf].rate = rate_map; + nconf++; + } + } + cap->nconf = nconf; + + return 1; +} + +static int +sio_oss_getfd(const char *str, unsigned int mode, int nbio) +{ + const char *p; + char path[DEVPATH_MAX]; + unsigned int devnum; + int fd, flags; + + p = _sndio_parsetype(str, "rsnd"); + if (p == NULL) { + DPRINTF("sio_oss_getfd: %s: \"rsnd\" expected\n", str); + return -1; + } + switch (*p) { + case '/': + p++; + break; + default: + DPRINTF("sio_oss_getfd: %s: '/' expected\n", str); + return -1; + } + p = _sndio_parsenum(p, &devnum, 255); + if (p == NULL || *p != '\0') { + DPRINTF("sio_oss_getfd: %s: number expected after '/'\n", str); + return -1; + } + snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum); + if (mode == (SIO_PLAY | SIO_REC)) + flags = O_RDWR; + else + flags = (mode & SIO_PLAY) ? O_WRONLY : O_RDONLY; + while ((fd = open(path, flags | O_NONBLOCK | O_CLOEXEC)) < 0) { + if (errno == EINTR) + continue; + DPERROR(path); + return -1; + } + return fd; +} + +static struct sio_hdl * +sio_oss_fdopen(const char *str, int fd, unsigned int mode, int nbio) +{ + struct sio_oss_hdl *hdl; + + hdl = malloc(sizeof(struct sio_oss_hdl)); + if (hdl == NULL) + return NULL; + _sio_create(&hdl->sio, &sio_oss_ops, mode, nbio); + + /* Set default device parameters */ + hdl->fmt = AFMT_S16_LE; + hdl->rate = 48000; + hdl->chan = 2; + hdl->round = 960; + hdl->appbufsz = 8 * 960; + + hdl->fd = fd; + + return (struct sio_hdl *)hdl; +} + +struct sio_hdl * +_sio_oss_open(const char *str, unsigned int mode, int nbio) +{ + struct sio_oss_hdl *hdl; + int fd; + + fd = sio_oss_getfd(str, mode, nbio); + if (fd < 0) + return NULL; + + hdl = (struct sio_oss_hdl *)sio_oss_fdopen(str, fd, mode, nbio); + if (hdl != NULL) + return (struct sio_hdl*)hdl; + + while (close(fd) < 0 && errno == EINTR) + ; /* retry */ + + return NULL; +} + +static void +sio_oss_close(struct sio_hdl *sh) +{ + struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; + + while (close(hdl->fd) < 0 && errno == EINTR) + ; /* retry */ + free(hdl); +} + +static int +sio_oss_start(struct sio_hdl *sh) +{ + struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; + + hdl->isamples = 0; + hdl->osamples = 0; + hdl->idelta = 0; + hdl->odelta = 0; + + /* Nothing else to do here. OSS starts playing/recording + * on first write/read. + */ + _sio_onmove_cb(&hdl->sio, 0); + + return 1; +} + +static int +sio_oss_stop(struct sio_hdl *sh) +{ + struct sio_oss_hdl *hdl = (struct sio_oss_hdl*)sh; + + if (ioctl(hdl->fd, SNDCTL_DSP_SYNC, NULL) < 0) { + DPERROR("sio_oss_stop: SYNC"); + hdl->sio.eof = 1; + return 0; + } + if (ioctl(hdl->fd, SNDCTL_DSP_HALT, NULL) < 0) { + DPERROR("sio_oss_stop: HALT"); + hdl->sio.eof = 1; + return 0; + } + + /* Reset device parameters. When we do not do this, resuming + * playback/recording will trigger poll with revents=POLLIN + * too often, which leads to sndiod using 100 % CPU. + */ + return sio_oss_setpar(sh, &hdl->sio.par); +} + +static int +sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par) +{ + struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; + unsigned int i; + int policy; + + hdl->fmt = AFMT_S16_LE; + for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { + if (formats[i].bits == par->bits + && formats[i].le == par->le + && formats[i].sig == par->sig + && formats[i].msb == par->msb) { + hdl->fmt = formats[i].fmt; + break; + } + } + + if (par->rate != ~0U) + hdl->rate = par->rate; + if (hdl->rate < 8000) + hdl->rate = 8000; + if (hdl->rate > 192000) + hdl->rate = 192000; + + if (hdl->sio.mode & SIO_PLAY) + hdl->chan = par->pchan; + else if (hdl->sio.mode & SIO_REC) + hdl->chan = par->rchan; + + if (par->round != ~0U && par->appbufsz != ~0U) { + hdl->round = par->round; + hdl->appbufsz = par->appbufsz; + } else if (par->round != ~0U) { + hdl->round = par->round; + hdl->appbufsz = 2 * par->round; + } else if (par->appbufsz != ~0U) { + hdl->round = par->appbufsz / 2; + hdl->appbufsz = par->appbufsz; + } + + /* Set timing policy to 5 which is OSS' default. The + * user-settable hw.snd.latency sysctl influences the default + * policy. + */ + policy = 5; + if (ioctl(hdl->fd, SNDCTL_DSP_POLICY, &policy) < 0) { + DPERROR("sio_oss_setpar: POLICY"); + hdl->sio.eof = 1; + return 0; + } + + if (ioctl(hdl->fd, SNDCTL_DSP_SETFMT, &hdl->fmt) < 0) { + DPERROR("sio_oss_setpar: SETFMT"); + hdl->sio.eof = 1; + return 0; + } + + if (ioctl(hdl->fd, SNDCTL_DSP_SPEED, &hdl->rate) < 0) { + DPERROR("sio_oss_setpar: SPEED"); + hdl->sio.eof = 1; + return 0; + } + + if (ioctl(hdl->fd, SNDCTL_DSP_CHANNELS, &hdl->chan) < 0) { + DPERROR("sio_oss_setpar: CHANNELS"); + hdl->sio.eof = 1; + return 0; + } + + return 1; +} + +static int +sio_oss_getpar(struct sio_hdl *sh, struct sio_par *par) +{ + struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; + unsigned int i, found = 0; + + for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { + if (formats[i].fmt == hdl->fmt) { + par->sig = formats[i].sig; + par->le = formats[i].le; + par->bits = formats[i].bits; + par->bps = formats[i].bps; + par->msb = formats[i].msb; + found = 1; + break; + } + } + if (!found) { + DPRINTF("sio_oss_getpar: unknown format %d\n", hdl->fmt); + hdl->sio.eof = 1; + return 0; + } + + par->rate = hdl->rate; + par->pchan = hdl->chan; + par->rchan = hdl->chan; + par->round = hdl->round; + par->appbufsz = par->bufsz = hdl->appbufsz; + par->xrun = SIO_IGNORE; + + return 1; +} + +static size_t +sio_oss_read(struct sio_hdl *sh, void *buf, size_t len) +{ + struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; + ssize_t n; + + while ((n = read(hdl->fd, buf, len)) < 0) { + if (errno == EINTR) + continue; + if (errno != EAGAIN) { + DPERROR("sio_oss_read: read"); + hdl->sio.eof = 1; + } + return 0; + } + if (n == 0) { + DPRINTF("sio_oss_read: eof\n"); + hdl->sio.eof = 1; + return 0; + } + + return n; +} + +static size_t +sio_oss_write(struct sio_hdl *sh, const void *buf, size_t len) +{ + struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; + const unsigned char *data = buf; + ssize_t n, todo; + + todo = len; + while ((n = write(hdl->fd, data, todo)) < 0) { + if (errno == EINTR) + continue; + if (errno != EAGAIN) { + DPERROR("sio_oss_write: write"); + hdl->sio.eof = 1; + } + return 0; + } + + return n; +} + +static int +sio_oss_nfds(struct sio_hdl *hdl) +{ + return 1; +} + +static int +sio_oss_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events) +{ + struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; + + pfd->fd = hdl->fd; + pfd->events = events; + + return 1; +} + +static int +sio_oss_xrun(struct sio_oss_hdl *hdl) +{ + int clk; + int wsil, rdrop, cmove; + int rbpf, rround; + int wbpf; + + DPRINTFN(2, "sio_oss_xrun:\n"); + if (_sndio_debug >= 2) + _sio_printpos(&hdl->sio); + + /* + * we assume rused/wused are zero if rec/play modes are not + * selected. This allows us to keep the same formula for all + * modes, provided we set rbpf/wbpf to 1 to avoid division by + * zero. + * + * to understand the formula, draw a picture :) + */ + rbpf = (hdl->sio.mode & SIO_REC) ? + hdl->sio.par.bps * hdl->sio.par.rchan : 1; + wbpf = (hdl->sio.mode & SIO_PLAY) ? + hdl->sio.par.bps * hdl->sio.par.pchan : 1; + rround = hdl->sio.par.round * rbpf; + + clk = hdl->sio.cpos % hdl->sio.par.round; + rdrop = (clk * rbpf - hdl->sio.rused) % rround; + if (rdrop < 0) + rdrop += rround; + cmove = (rdrop + hdl->sio.rused) / rbpf; + wsil = cmove * wbpf + hdl->sio.wused; + + DPRINTFN(2, "wsil = %d, cmove = %d, rdrop = %d\n", wsil, cmove, rdrop); + + if (!sio_oss_stop(&hdl->sio)) + return 0; + if (!sio_oss_start(&hdl->sio)) + return 0; + if (hdl->sio.mode & SIO_PLAY) { + hdl->odelta -= cmove; + hdl->sio.wsil = wsil; + } + if (hdl->sio.mode & SIO_REC) { + hdl->idelta -= cmove; + hdl->sio.rdrop = rdrop; + } + DPRINTFN(2, "xrun: corrected\n"); + DPRINTFN(2, "wsil = %d, rdrop = %d, odelta = %d, idelta = %d\n", + wsil, rdrop, hdl->odelta, hdl->idelta); + return 1; +} + +static int +sio_oss_revents(struct sio_hdl *sh, struct pollfd *pfd) +{ + struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; + audio_errinfo ei; + int delta; + int revents = pfd->revents; + long long play_pos, rec_pos; + oss_count_t optr, iptr; + + if ((pfd->revents & POLLHUP) || + (pfd->revents & (POLLIN | POLLOUT)) == 0) + return pfd->revents; + + /* Hide xruns from clients */ + if (ioctl(hdl->fd, SNDCTL_DSP_GETERROR, &ei) < 0) { + DPERROR("sio_oss_revents: GETERROR"); + hdl->sio.eof = 1; + return POLLHUP; + } + if (ei.play_underruns > 0 || ei.rec_overruns > 0) { + if (!sio_oss_xrun(hdl)) + return POLLHUP; + return 0; + } + + if (hdl->sio.mode & SIO_PLAY) { + if (ioctl(hdl->fd, SNDCTL_DSP_CURRENT_OPTR, &optr) < 0) { + DPERROR("sio_oss_revents: CURRENT_OPTR"); + hdl->sio.eof = 1; + return POLLHUP; + } + play_pos = optr.samples - optr.fifo_samples; + delta = play_pos - hdl->osamples; + hdl->osamples = play_pos; + hdl->odelta += delta; + if (!(hdl->sio.mode & SIO_REC)) { + hdl->idelta += delta; + } + } + if (hdl->sio.mode & SIO_REC) { + if (ioctl(hdl->fd, SNDCTL_DSP_CURRENT_IPTR, &iptr) < 0) { + DPERROR("sio_oss_revents: CURRENT_IPTR"); + hdl->sio.eof = 1; + return POLLHUP; + } + rec_pos = iptr.samples - iptr.fifo_samples; + delta = rec_pos - hdl->isamples; + hdl->isamples = rec_pos; + hdl->idelta += delta; + if (!(hdl->sio.mode & SIO_PLAY)) { + hdl->odelta += delta; + } + } + + delta = (hdl->idelta > hdl->odelta) ? hdl->idelta : hdl->odelta; + if (delta > 0) { + _sio_onmove_cb(&hdl->sio, delta); + hdl->idelta -= delta; + hdl->odelta -= delta; + } + return revents; +} + +#endif /* defined USE_OSS */ diff --git a/libsndio/sio_priv.h b/libsndio/sio_priv.h index 09e3b1f..8a8f161 100644 --- a/libsndio/sio_priv.h +++ b/libsndio/sio_priv.h @@ -69,6 +69,9 @@ struct sio_hdl *_sio_aucat_open(const char *, unsigned, int); #ifdef USE_SUN struct sio_hdl *_sio_sun_open(const char *, unsigned, int); #endif +#ifdef USE_OSS +struct sio_hdl *_sio_oss_open(const char *, unsigned, int); +#endif #ifdef USE_ALSA struct sio_hdl *_sio_alsa_open(const char *, unsigned, int); #endif From e867d773fac2722e081b0e2f5e2daeb2e3fd632b Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 3 Nov 2016 08:09:11 +0100 Subject: [PATCH 098/117] Tweak spacing of sio_oss.c to look more like other files. --- libsndio/sio_oss.c | 47 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c index b625a4b..0e8e9f2 100644 --- a/libsndio/sio_oss.c +++ b/libsndio/sio_oss.c @@ -45,16 +45,17 @@ struct sio_oss_fmt { unsigned int le; unsigned int msb; }; + static struct sio_oss_fmt formats[] = { /* See http://manuals.opensound.com/developer/formats.html. * AFMT_{S8,U16}_* are marked as obsolete so are missing here. */ /* le+msb not important */ - { AFMT_U8, 8, 1, 0, 0, 0 }, - { AFMT_U8, 8, 1, 0, 1, 0 }, - { AFMT_U8, 8, 1, 0, 0, 1 }, - { AFMT_U8, 8, 1, 0, 1, 1 }, + { AFMT_U8, 8, 1, 0, 0, 0 }, + { AFMT_U8, 8, 1, 0, 1, 0 }, + { AFMT_U8, 8, 1, 0, 0, 1 }, + { AFMT_U8, 8, 1, 0, 1, 1 }, /* msb not important */ { AFMT_S16_BE, 16, 2, 1, 0, 0 }, @@ -338,22 +339,22 @@ sio_oss_stop(struct sio_hdl *sh) { struct sio_oss_hdl *hdl = (struct sio_oss_hdl*)sh; - if (ioctl(hdl->fd, SNDCTL_DSP_SYNC, NULL) < 0) { - DPERROR("sio_oss_stop: SYNC"); - hdl->sio.eof = 1; - return 0; - } - if (ioctl(hdl->fd, SNDCTL_DSP_HALT, NULL) < 0) { - DPERROR("sio_oss_stop: HALT"); - hdl->sio.eof = 1; - return 0; - } + if (ioctl(hdl->fd, SNDCTL_DSP_SYNC, NULL) < 0) { + DPERROR("sio_oss_stop: SYNC"); + hdl->sio.eof = 1; + return 0; + } + if (ioctl(hdl->fd, SNDCTL_DSP_HALT, NULL) < 0) { + DPERROR("sio_oss_stop: HALT"); + hdl->sio.eof = 1; + return 0; + } - /* Reset device parameters. When we do not do this, resuming - * playback/recording will trigger poll with revents=POLLIN - * too often, which leads to sndiod using 100 % CPU. - */ - return sio_oss_setpar(sh, &hdl->sio.par); + /* Reset device parameters. When we do not do this, resuming + * playback/recording will trigger poll with revents=POLLIN + * too often, which leads to sndiod using 100 % CPU. + */ + return sio_oss_setpar(sh, &hdl->sio.par); } static int @@ -365,10 +366,10 @@ sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par) hdl->fmt = AFMT_S16_LE; for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { - if (formats[i].bits == par->bits - && formats[i].le == par->le - && formats[i].sig == par->sig - && formats[i].msb == par->msb) { + if (formats[i].bits == par->bits && + formats[i].le == par->le && + formats[i].sig == par->sig && + formats[i].msb == par->msb) { hdl->fmt = formats[i].fmt; break; } From 4d6d7700a4123a7ee883ee58bb2f7ca0d7ee1df9 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 4 Nov 2016 08:05:47 +0100 Subject: [PATCH 099/117] Make sio_getpar() on OSS/FreeBSD return the device block size/count instead of saved ones. Fixes busy loops caused by poll(2) returning POLLOUT after the program has filled its play buffer. --- libsndio/sio_oss.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c index 0e8e9f2..a348797 100644 --- a/libsndio/sio_oss.c +++ b/libsndio/sio_oss.c @@ -435,6 +435,7 @@ sio_oss_getpar(struct sio_hdl *sh, struct sio_par *par) { struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; unsigned int i, found = 0; + audio_buf_info pbi, rbi; for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { if (formats[i].fmt == hdl->fmt) { @@ -456,10 +457,41 @@ sio_oss_getpar(struct sio_hdl *sh, struct sio_par *par) par->rate = hdl->rate; par->pchan = hdl->chan; par->rchan = hdl->chan; - par->round = hdl->round; - par->appbufsz = par->bufsz = hdl->appbufsz; par->xrun = SIO_IGNORE; + if (hdl->sio.mode & SIO_PLAY) { + if (ioctl(hdl->fd, SNDCTL_DSP_GETOSPACE, &pbi) < 0) { + DPERROR("sio_oss_getpar: SNDCTL_DSP_GETOSPACE"); + hdl->sio.eof = 1; + return 0; + } + par->round = pbi.fragsize / (par->pchan * par->bps); + par->bufsz = pbi.fragstotal * par->round; + } + if (hdl->sio.mode & SIO_REC) { + if (ioctl(hdl->fd, SNDCTL_DSP_GETISPACE, &rbi) < 0) { + DPERROR("sio_oss_getpar: SNDCTL_DSP_GETISPACE"); + hdl->sio.eof = 1; + return 0; + } + par->round = rbi.fragsize / (par->rchan * par->bps); + par->bufsz = rbi.fragstotal * par->round; + } + par->appbufsz = par->bufsz; +#ifdef DEBUG + if ((hdl->sio.mode & (SIO_REC | SIO_PLAY)) == (SIO_REC | SIO_PLAY)) { + if (pbi.fragstotal != rbi.fragstotal || + pbi.fragsize != rbi.fragsize) { + DPRINTF("sio_oss_getpar: frag size/count mismatch\n" + "play: size = %d, count = %d\n" + "rec: size = %d, count = %d\n", + pbi.fragstotal, pbi.fragsize, + rbi.fragstotal, rbi.fragsize); + hdl->sio.eof = 1; + return 0; + } + } +#endif return 1; } From a282420a4938879fe1f09717fdbf2bfff105370d Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 4 Nov 2016 09:18:04 +0100 Subject: [PATCH 100/117] In OSS/FreeBSD sio_setpar(), validate the encoding, ensuring we never end-up with an unknown one. --- libsndio/sio_oss.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c index a348797..2c96622 100644 --- a/libsndio/sio_oss.c +++ b/libsndio/sio_oss.c @@ -415,6 +415,16 @@ sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par) return 0; } + for (i = 0; ; i++) { + if (i == sizeof(formats) / sizeof(formats[0])) { + DPRINTF("sio_oss_setpar: unknown fmt %d\n", hdl->fmt); + hdl->sio.eof = 1; + return 0; + } + if (formats[i].fmt == hdl->fmt) + break; + } + if (ioctl(hdl->fd, SNDCTL_DSP_SPEED, &hdl->rate) < 0) { DPERROR("sio_oss_setpar: SPEED"); hdl->sio.eof = 1; From 9be2c65600b8e89414723b17903cf0bb51f6f37f Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 4 Nov 2016 11:03:41 +0100 Subject: [PATCH 101/117] Allow programs using OSS/FreeBSD backend to select the buffer size. According to kernel sources, SNDCTL_DSP_POLICY ioctl doesn't seem to always set play and rec buffer sizes to the same value. That's why we use the SNDCTL_DSP_SETFRAGMENT ioctl instead. --- libsndio/sio_oss.c | 63 ++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c index 2c96622..083093b 100644 --- a/libsndio/sio_oss.c +++ b/libsndio/sio_oss.c @@ -361,8 +361,8 @@ static int sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par) { struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; - unsigned int i; - int policy; + unsigned int i, round, bufsz; + int frag_max, frag_shift, frag_count, frag; hdl->fmt = AFMT_S16_LE; for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { @@ -387,28 +387,6 @@ sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par) else if (hdl->sio.mode & SIO_REC) hdl->chan = par->rchan; - if (par->round != ~0U && par->appbufsz != ~0U) { - hdl->round = par->round; - hdl->appbufsz = par->appbufsz; - } else if (par->round != ~0U) { - hdl->round = par->round; - hdl->appbufsz = 2 * par->round; - } else if (par->appbufsz != ~0U) { - hdl->round = par->appbufsz / 2; - hdl->appbufsz = par->appbufsz; - } - - /* Set timing policy to 5 which is OSS' default. The - * user-settable hw.snd.latency sysctl influences the default - * policy. - */ - policy = 5; - if (ioctl(hdl->fd, SNDCTL_DSP_POLICY, &policy) < 0) { - DPERROR("sio_oss_setpar: POLICY"); - hdl->sio.eof = 1; - return 0; - } - if (ioctl(hdl->fd, SNDCTL_DSP_SETFMT, &hdl->fmt) < 0) { DPERROR("sio_oss_setpar: SETFMT"); hdl->sio.eof = 1; @@ -437,6 +415,43 @@ sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par) return 0; } + if (par->round != ~0U && par->appbufsz != ~0U) { + round = par->round; + bufsz = par->appbufsz; + } else if (par->round != ~0U) { + round = par->round; + bufsz = 2 * par->round; + } else if (par->appbufsz != ~0U) { + round = par->appbufsz / 2; + bufsz = par->appbufsz; + } else { + /* + * even if it's not specified, we have to set the + * block size to ensure that both play and record + * direction get the same block size. Pick an + * arbitrary value that would work for most players at + * 48kHz, stereo, 16-bit. + */ + round = 512; + bufsz = 1024; + } + + frag_max = round * hdl->chan * formats[i].bps; + frag_shift = 0; + while (1 << (frag_shift + 1) < frag_max) + frag_shift++; + + frag_count = bufsz / round; + if (frag_count < 2) + frag_count = 2; + + frag = frag_count << 16 | frag_shift; + if (ioctl(hdl->fd, SNDCTL_DSP_SETFRAGMENT, &frag) < 0) { + DPERROR("sio_oss_setpar: SETFRAGMENT"); + hdl->sio.eof = 1; + return 0; + } + return 1; } From db2029846880c5f65960d94f701259f42c1f9c13 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 4 Nov 2016 14:09:42 +0100 Subject: [PATCH 102/117] Use the SNDCTL_DSP_SETTRIGGER interface to start/stop the device, this allows the "onmove" callback to be called whenever the DMA actually starts (and not on the first write). This also removes the need for sio_osee_setpar() call every time the device is stopped. --- libsndio/sio_oss.c | 69 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c index 083093b..18521c8 100644 --- a/libsndio/sio_oss.c +++ b/libsndio/sio_oss.c @@ -89,6 +89,8 @@ struct sio_oss_hdl { unsigned int chan; unsigned int appbufsz; unsigned int round; + + int filling; }; static struct sio_hdl *sio_oss_fdopen(const char *, int, unsigned int, int); @@ -280,7 +282,7 @@ sio_oss_fdopen(const char *str, int fd, unsigned int mode, int nbio) hdl->chan = 2; hdl->round = 960; hdl->appbufsz = 8 * 960; - + hdl->filling = 0; hdl->fd = fd; return (struct sio_hdl *)hdl; @@ -320,17 +322,33 @@ static int sio_oss_start(struct sio_hdl *sh) { struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; + int trig; hdl->isamples = 0; hdl->osamples = 0; hdl->idelta = 0; hdl->odelta = 0; - /* Nothing else to do here. OSS starts playing/recording - * on first write/read. - */ - _sio_onmove_cb(&hdl->sio, 0); - + if (hdl->sio.mode & SIO_PLAY) { + /* + * keep the device paused and let sio_oss_pollfd() trigger the + * start later, to avoid buffer underruns + */ + hdl->filling = 1; + trig = 0; + } else { + /* + * no play buffers to fill, start now! + */ + trig = PCM_ENABLE_INPUT; + _sio_onmove_cb(&hdl->sio, 0); + } + DPRINTF("trig = 0x%x\n", trig); + if (ioctl(hdl->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { + DPERROR("sio_oss_start: SETTRIGGER"); + hdl->sio.eof = 1; + return 0; + } return 1; } @@ -338,23 +356,19 @@ static int sio_oss_stop(struct sio_hdl *sh) { struct sio_oss_hdl *hdl = (struct sio_oss_hdl*)sh; + int trig; - if (ioctl(hdl->fd, SNDCTL_DSP_SYNC, NULL) < 0) { - DPERROR("sio_oss_stop: SYNC"); + if (hdl->filling) { + hdl->filling = 0; + return 1; + } + trig = 0; + if (ioctl(hdl->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { + DPERROR("sio_oss_stop: SETTRIGGER"); hdl->sio.eof = 1; return 0; } - if (ioctl(hdl->fd, SNDCTL_DSP_HALT, NULL) < 0) { - DPERROR("sio_oss_stop: HALT"); - hdl->sio.eof = 1; - return 0; - } - - /* Reset device parameters. When we do not do this, resuming - * playback/recording will trigger poll with revents=POLLIN - * too often, which leads to sndiod using 100 % CPU. - */ - return sio_oss_setpar(sh, &hdl->sio.par); + return 1; } static int @@ -575,10 +589,25 @@ static int sio_oss_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events) { struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; + int trig; pfd->fd = hdl->fd; pfd->events = events; - + if (hdl->filling && hdl->sio.wused == hdl->sio.par.bufsz * + hdl->sio.par.pchan * hdl->sio.par.bps) { + hdl->filling = 0; + trig = 0; + if (hdl->sio.mode & SIO_PLAY) + trig |= PCM_ENABLE_OUTPUT; + if (hdl->sio.mode & SIO_REC) + trig |= PCM_ENABLE_INPUT; + if (ioctl(hdl->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { + DPERROR("sio_oss_pollfd: SETTRIGGER"); + hdl->sio.eof = 1; + return 0; + } + _sio_onmove_cb(&hdl->sio, 0); + } return 1; } From 2b58ec0677041c2685e7a62f76b1861d2b98aaa3 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 4 Nov 2016 14:14:52 +0100 Subject: [PATCH 103/117] Remove forgotten debug printf in sio_oss.c --- libsndio/sio_oss.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c index 18521c8..85045a9 100644 --- a/libsndio/sio_oss.c +++ b/libsndio/sio_oss.c @@ -343,7 +343,6 @@ sio_oss_start(struct sio_hdl *sh) trig = PCM_ENABLE_INPUT; _sio_onmove_cb(&hdl->sio, 0); } - DPRINTF("trig = 0x%x\n", trig); if (ioctl(hdl->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { DPERROR("sio_oss_start: SETTRIGGER"); hdl->sio.eof = 1; From c5daeee2949d10372f94dd6f85aa61f337986cfd Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 4 Nov 2016 19:12:07 +0100 Subject: [PATCH 104/117] On OSS/FreeBSD, set poll(2) threshold to 1 byte, so that it returs POLLIN/POLLOUT whenever read/write can be called without blocking. By default OSS use 1 block of threshold. --- libsndio/sio_oss.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c index 85045a9..75b5124 100644 --- a/libsndio/sio_oss.c +++ b/libsndio/sio_oss.c @@ -232,7 +232,7 @@ sio_oss_getfd(const char *str, unsigned int mode, int nbio) const char *p; char path[DEVPATH_MAX]; unsigned int devnum; - int fd, flags; + int fd, flags, val; p = _sndio_parsetype(str, "rsnd"); if (p == NULL) { @@ -263,6 +263,12 @@ sio_oss_getfd(const char *str, unsigned int mode, int nbio) DPERROR(path); return -1; } + val = 1; + if (ioctl(fd, SNDCTL_DSP_LOW_WATER, &val) < 0) { + DPERROR("sio_oss_start: LOW_WATER"); + close(fd); + return -1; + } return fd; } From 4f56ff61814e1f928f645bb91eb45e35eebdf327 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 5 Nov 2016 07:02:39 +0100 Subject: [PATCH 105/117] In sio_oss_revents() use the fifo_samples counter returned by SNDCTL_DSP_CURRENT_{I,O}PTR to determine the device current position. Besides being simpler than using the absolute position, this fixes hangs in record-only mode. --- libsndio/sio_oss.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c index 75b5124..d8959d2 100644 --- a/libsndio/sio_oss.c +++ b/libsndio/sio_oss.c @@ -80,9 +80,10 @@ static struct sio_oss_fmt formats[] = { struct sio_oss_hdl { struct sio_hdl sio; int fd; - unsigned int isamples; - unsigned int osamples; int idelta, odelta; + int iused; + int oused; + int bpf; int fmt; unsigned int rate; @@ -330,8 +331,8 @@ sio_oss_start(struct sio_hdl *sh) struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; int trig; - hdl->isamples = 0; - hdl->osamples = 0; + hdl->iused = 0; + hdl->oused = 0; hdl->idelta = 0; hdl->odelta = 0; @@ -434,6 +435,8 @@ sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par) return 0; } + hdl->bpf = formats[i].bps * hdl->chan; + if (par->round != ~0U && par->appbufsz != ~0U) { round = par->round; bufsz = par->appbufsz; @@ -560,6 +563,7 @@ sio_oss_read(struct sio_hdl *sh, void *buf, size_t len) return 0; } + hdl->idelta += n; return n; } @@ -581,6 +585,7 @@ sio_oss_write(struct sio_hdl *sh, const void *buf, size_t len) return 0; } + hdl->odelta += n; return n; } @@ -656,11 +661,11 @@ sio_oss_xrun(struct sio_oss_hdl *hdl) if (!sio_oss_start(&hdl->sio)) return 0; if (hdl->sio.mode & SIO_PLAY) { - hdl->odelta -= cmove; + hdl->odelta -= cmove * hdl->bpf; hdl->sio.wsil = wsil; } if (hdl->sio.mode & SIO_REC) { - hdl->idelta -= cmove; + hdl->idelta -= cmove * hdl->bpf; hdl->sio.rdrop = rdrop; } DPRINTFN(2, "xrun: corrected\n"); @@ -674,9 +679,8 @@ sio_oss_revents(struct sio_hdl *sh, struct pollfd *pfd) { struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; audio_errinfo ei; - int delta; + int delta, iused, oused; int revents = pfd->revents; - long long play_pos, rec_pos; oss_count_t optr, iptr; if ((pfd->revents & POLLHUP) || @@ -701,12 +705,11 @@ sio_oss_revents(struct sio_hdl *sh, struct pollfd *pfd) hdl->sio.eof = 1; return POLLHUP; } - play_pos = optr.samples - optr.fifo_samples; - delta = play_pos - hdl->osamples; - hdl->osamples = play_pos; - hdl->odelta += delta; + oused = optr.fifo_samples * hdl->bpf; + hdl->odelta -= oused - hdl->oused; + hdl->oused = oused; if (!(hdl->sio.mode & SIO_REC)) { - hdl->idelta += delta; + hdl->idelta = hdl->odelta; } } if (hdl->sio.mode & SIO_REC) { @@ -715,18 +718,17 @@ sio_oss_revents(struct sio_hdl *sh, struct pollfd *pfd) hdl->sio.eof = 1; return POLLHUP; } - rec_pos = iptr.samples - iptr.fifo_samples; - delta = rec_pos - hdl->isamples; - hdl->isamples = rec_pos; - hdl->idelta += delta; + iused = iptr.fifo_samples * hdl->bpf; + hdl->idelta += iused - hdl->iused; + hdl->iused = iused; if (!(hdl->sio.mode & SIO_PLAY)) { - hdl->odelta += delta; + hdl->odelta = hdl->idelta; } } delta = (hdl->idelta > hdl->odelta) ? hdl->idelta : hdl->odelta; if (delta > 0) { - _sio_onmove_cb(&hdl->sio, delta); + _sio_onmove_cb(&hdl->sio, delta / hdl->bpf); hdl->idelta -= delta; hdl->odelta -= delta; } From c25d86c7db9d6ea04cf95d56bff776b235c8c677 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 5 Nov 2016 07:11:08 +0100 Subject: [PATCH 106/117] sio_oss.c: if the requrested block size is a power of two make the oss block size calculation return the requested value. --- libsndio/sio_oss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c index d8959d2..22f4b47 100644 --- a/libsndio/sio_oss.c +++ b/libsndio/sio_oss.c @@ -460,7 +460,7 @@ sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par) frag_max = round * hdl->chan * formats[i].bps; frag_shift = 0; - while (1 << (frag_shift + 1) < frag_max) + while (1 << (frag_shift + 1) <= frag_max) frag_shift++; frag_count = bufsz / round; From 8c9553769847bf69561fa5c421cb92afdca84380 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 5 Nov 2016 07:14:46 +0100 Subject: [PATCH 107/117] sio_oss.c: Disallow tiny fragment sizes, as they may overload the system. And as sndiod runs with increased priority, it would consume all the cpu and could in turn hang the system. --- libsndio/sio_oss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c index 22f4b47..4ba910c 100644 --- a/libsndio/sio_oss.c +++ b/libsndio/sio_oss.c @@ -459,7 +459,7 @@ sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par) } frag_max = round * hdl->chan * formats[i].bps; - frag_shift = 0; + frag_shift = 8; while (1 << (frag_shift + 1) <= frag_max) frag_shift++; From 9cb5193ca7e47484e3c02f6e6ed6294f0e309dbe Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sat, 5 Nov 2016 07:21:28 +0100 Subject: [PATCH 108/117] sio_oss.c: In full duplex-mode, don't require play and rec buffer sizes to be the same. Only the block sizes need to be the same. --- libsndio/sio_oss.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libsndio/sio_oss.c b/libsndio/sio_oss.c index 4ba910c..7199782 100644 --- a/libsndio/sio_oss.c +++ b/libsndio/sio_oss.c @@ -521,17 +521,18 @@ sio_oss_getpar(struct sio_hdl *sh, struct sio_par *par) hdl->sio.eof = 1; return 0; } - par->round = rbi.fragsize / (par->rchan * par->bps); - par->bufsz = rbi.fragstotal * par->round; + if (!(hdl->sio.mode & SIO_PLAY)) { + par->round = rbi.fragsize / (par->rchan * par->bps); + par->bufsz = rbi.fragstotal * par->round; + } } par->appbufsz = par->bufsz; #ifdef DEBUG if ((hdl->sio.mode & (SIO_REC | SIO_PLAY)) == (SIO_REC | SIO_PLAY)) { - if (pbi.fragstotal != rbi.fragstotal || - pbi.fragsize != rbi.fragsize) { + if (pbi.fragsize != rbi.fragsize) { DPRINTF("sio_oss_getpar: frag size/count mismatch\n" - "play: size = %d, count = %d\n" - "rec: size = %d, count = %d\n", + "play: count = %d, size = %d\n" + "rec: count = %d, size = %d\n", pbi.fragstotal, pbi.fragsize, rbi.fragstotal, rbi.fragsize); hdl->sio.eof = 1; From 2606d3f24eca3d7a29db3d183640524590e93e26 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sun, 6 Nov 2016 12:21:59 +0100 Subject: [PATCH 109/117] Add support for FreeBSD raw usb-midi devices. Bits from Tobias Kortkamp plus configure script tweaks. --- configure | 25 +++++++++++++++++++++++++ libsndio/mio_rmidi.c | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 13a0394..21a546b 100755 --- a/configure +++ b/configure @@ -20,6 +20,8 @@ Usage: configure [options] --disable-sun disable sun audio backend --enable-rmidi enable character device midi backend [$rmidi] --disable-rmidi disable character device midi backend +--enable-umidi enable usb-midi backend [$umidi] +--disable-umidi disable usb-midi backend --with-libbsd use the libbsd rather than bsd-compat/* --without-libbsd don't use libbsd END @@ -34,6 +36,7 @@ alsa=no # do we want alsa support ? sun=no # do we want sun support ? oss=no # do we want oss support ? rmidi=no # do we want support for raw char dev ? +umidi=no # do we want support for umidi ? precision=16 # aucat/sndiod arithmetic precision user=_sndio # non-privileged user for sndio daemon libbsd=no # use libbsd? @@ -73,6 +76,7 @@ case `uname` in -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRTONUM' ;; DragonFly|FreeBSD) + umidi=yes user=_sndio so="$so libsndio.so" defs='-DHAVE_ARC4RANDOM -DHAVE_ISSETUGID \\\ @@ -133,6 +137,12 @@ for i; do --disable-rmidi) rmidi=no shift;; + --enable-umidi) + umidi=yes + shift;; + --disable-umidi) + umidi=no + shift;; --privsep-user=*) user="${i#--privsep-user=}" shift;; @@ -168,6 +178,13 @@ includedir="${includedir:-$prefix/include}" libdir="${libdir:-$prefix/lib}" mandir="${mandir:-$prefix/share/man}" +# +# umidi implies rmidi +# +if [ $umidi = yes ]; then + rmidi=yes +fi + # # if using ALSA, add corresponding parameters # @@ -197,6 +214,13 @@ if [ $rmidi = yes ]; then defs="$defs -DUSE_RMIDI" fi +# +# if using usb-midi raw devices for midi, add corresponding parameters +# +if [ $umidi = yes ]; then + defs="$defs -DUSE_UMIDI" +fi + # # if using libbsd, add corresponding parameters # @@ -242,6 +266,7 @@ alsa..................... $alsa oss...................... $oss sun...................... $sun rmidi.................... $rmidi +umidi.................... $umidi Do "make && make install" to compile and install sndio diff --git a/libsndio/mio_rmidi.c b/libsndio/mio_rmidi.c index 8e6116a..6ffef85 100644 --- a/libsndio/mio_rmidi.c +++ b/libsndio/mio_rmidi.c @@ -31,10 +31,19 @@ #include "debug.h" #include "mio_priv.h" +#ifdef USE_UMIDI +#define DEVPATH_PREFIX "/dev/umidi" +#define DEVPATH_MAX (1 + \ + sizeof(DEVPATH_PREFIX) - 1 + \ + sizeof(int) * 3 + \ + 1 + \ + sizeof(int) * 3) +#else #define DEVPATH_PREFIX "/dev/rmidi" #define DEVPATH_MAX (1 + \ sizeof(DEVPATH_PREFIX) - 1 + \ sizeof(int) * 3) +#endif struct mio_rmidi_hdl { struct mio_hdl mio; @@ -63,6 +72,9 @@ mio_rmidi_getfd(const char *str, unsigned int mode, int nbio) const char *p; char path[DEVPATH_MAX]; unsigned int devnum; +#ifdef USE_UMIDI + unsigned int subdevnum = 0; +#endif int fd, flags; p = _sndio_parsetype(str, "rmidi"); @@ -79,11 +91,37 @@ mio_rmidi_getfd(const char *str, unsigned int mode, int nbio) return -1; } p = _sndio_parsenum(p, &devnum, 255); - if (p == NULL || *p != '\0') { + if (p == NULL) { DPRINTF("mio_rmidi_getfd: %s: number expected after '/'\n", str); return -1; } +#ifdef USE_UMIDI + switch (*p) { + case '.': + p++; + p = _sndio_parsenum(p, &subdevnum, 255); + if (p == NULL) { + DPRINTF("mio_rmidi_getfd: %s: " + "number expected after '.'\n", str); + return -1; + } + break; + case '\0': + break; + default: + DPRINTF("mio_rmidi_getfd: %s: '.' expected\n", str); + return -1; + } +#endif + if (*p != '\0') { + DPRINTF("mio_rmidi_getfd: junk at end of string: %s\n", p); + return -1; + } +#ifdef USE_UMIDI + snprintf(path, sizeof(path), DEVPATH_PREFIX "%u.%u", devnum, subdevnum); +#else snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum); +#endif if (mode == (MIO_IN | MIO_OUT)) flags = O_RDWR; else From 474ac8d4262d2d0290a927f716c2fb80b4f79e00 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 3 Jan 2017 07:28:52 +0100 Subject: [PATCH 110/117] log file volume --- aucat/aucat.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aucat/aucat.c b/aucat/aucat.c index 0cee83e..d0a57ed 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -256,6 +256,10 @@ slot_new(char *path, int mode, struct aparams *par, int hdr, log_puts(".."); log_puti(s->afile.endpos); } + if (s->mode == SIO_PLAY) { + log_puts(", vol "); + log_puti(s->vol); + } log_puts("\n"); } s->next = slot_list; From 6c1c0d3ff64ac359508be5937249a85d06f99e58 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 3 Jan 2017 08:05:41 +0100 Subject: [PATCH 111/117] Remove unnecessary includes. From Michael W. Bombardieri . --- aucat/abuf.c | 2 -- aucat/afile.c | 2 -- aucat/aucat.c | 2 -- aucat/dsp.c | 1 - aucat/utils.c | 1 - 5 files changed, 8 deletions(-) diff --git a/aucat/abuf.c b/aucat/abuf.c index 0e34cbb..06d0f0d 100644 --- a/aucat/abuf.c +++ b/aucat/abuf.c @@ -22,9 +22,7 @@ * as follows: the write starts filling at offset (start + used), once the data * is ready, the writer adds to used the count of bytes available. */ -#include #include -#include #include "abuf.h" #include "utils.h" diff --git a/aucat/afile.c b/aucat/afile.c index ca24d28..ec41c9b 100644 --- a/aucat/afile.c +++ b/aucat/afile.c @@ -15,8 +15,6 @@ */ #include -#include -#include #include #include #include "afile.h" diff --git a/aucat/aucat.c b/aucat/aucat.c index d0a57ed..1bf7a38 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -14,13 +14,11 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include #include #include #include #include -#include #include #include #include diff --git a/aucat/dsp.c b/aucat/dsp.c index a8ae1ba..e4669a2 100644 --- a/aucat/dsp.c +++ b/aucat/dsp.c @@ -14,7 +14,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include "dsp.h" #include "utils.h" diff --git a/aucat/utils.c b/aucat/utils.c index 28a2fd6..6598c6f 100644 --- a/aucat/utils.c +++ b/aucat/utils.c @@ -24,7 +24,6 @@ #include #include #include -#include #include "utils.h" /* From 22a64d18458ed6af9021260d93f0aa924d58d5e9 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 3 Jan 2017 08:08:17 +0100 Subject: [PATCH 112/117] Many typos in comments. From Michael W. Bombardieri. Thanks. --- sndiod/dev.c | 2 +- sndiod/midi.c | 4 ++-- sndiod/utils.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sndiod/dev.c b/sndiod/dev.c index 6285dd8..494f074 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -1427,7 +1427,7 @@ slot_new(struct dev *d, char *who, struct slotops *ops, void *arg, int mode) struct slot *s; /* - * create a ``valid'' control name (lowcase, remove [^a-z], trucate) + * create a ``valid'' control name (lowcase, remove [^a-z], truncate) */ for (i = 0, p = who; ; p++) { if (i == SLOT_NAMEMAX - 1 || *p == '\0') { diff --git a/sndiod/midi.c b/sndiod/midi.c index b9eeb4c..b879f7d 100644 --- a/sndiod/midi.c +++ b/sndiod/midi.c @@ -98,7 +98,7 @@ midi_new(struct midiops *ops, void *arg, int mode) ep->mode = mode; /* - * the output buffer is the client intput + * the output buffer is the client input */ if (ep->mode & MODE_MIDIIN) abuf_init(&ep->obuf, MIDI_BUFSZ); @@ -148,7 +148,7 @@ midi_link(struct midi *ep, struct midi *peer) panic(); } #endif - /* ep has empry buffer, so no need to call midi_tickets() */ + /* ep has empty buffer, so no need to call midi_tickets() */ peer->txmask |= ep->self; } } diff --git a/sndiod/utils.c b/sndiod/utils.c index dafe6f3..a1cfa8a 100644 --- a/sndiod/utils.c +++ b/sndiod/utils.c @@ -96,7 +96,7 @@ log_putx(unsigned long num) } /* - * store a unsigned decimal in the log + * store an unsigned decimal in the log */ void log_putu(unsigned long num) @@ -140,7 +140,7 @@ panic(void) } /* - * allocate a (small) abount of memory, and abort if it fails + * allocate a (small) amount of memory, and abort if it fails */ void * xmalloc(size_t size) From 209e88bbde2442e1eb100893214316760b10b3b7 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 3 Jan 2017 08:10:11 +0100 Subject: [PATCH 113/117] Use a goto to factor all calls to close() when listen_in() returns an error. From Michael W. Bombardieri. Thanks. --- sndiod/listen.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sndiod/listen.c b/sndiod/listen.c index aa9071f..9bfeb88 100644 --- a/sndiod/listen.c +++ b/sndiod/listen.c @@ -257,8 +257,7 @@ listen_in(void *arg) if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { file_log(f->file); log_puts(": failed to set non-blocking mode\n"); - close(sock); - return; + goto bad_close; } if (f->path == NULL) { opt = 1; @@ -266,14 +265,14 @@ listen_in(void *arg) &opt, sizeof(int)) < 0) { file_log(f->file); log_puts(": failed to set TCP_NODELAY flag\n"); - close(sock); - return; + goto bad_close; } } - if (sock_new(sock) == NULL) { - close(sock); - return; - } + if (sock_new(sock) == NULL) + goto bad_close; + return; +bad_close: + close(sock); } void From 2f5165d92f080f622c33b450068c7ed616df3ef5 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 3 Jan 2017 08:20:49 +0100 Subject: [PATCH 114/117] sync utils.c to sndiod one --- aucat/utils.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/aucat/utils.c b/aucat/utils.c index 6598c6f..a1cfa8a 100644 --- a/aucat/utils.c +++ b/aucat/utils.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "utils.h" /* @@ -95,7 +96,7 @@ log_putx(unsigned long num) } /* - * store a unsigned decimal in the log + * store an unsigned decimal in the log */ void log_putu(unsigned long num) @@ -139,7 +140,7 @@ panic(void) } /* - * allocate a (small) abount of memory, and abort if it fails + * allocate a (small) amount of memory, and abort if it fails */ void * xmalloc(size_t size) @@ -162,6 +163,12 @@ xmalloc(size_t size) void xfree(void *p) { +#ifdef DEBUG + if (p == NULL) { + log_puts("xfree with NULL arg\n"); + panic(); + } +#endif free(p); } From 044421aad75fee5fa66d617e6867c3e6d0604b66 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 3 Jan 2017 08:50:48 +0100 Subject: [PATCH 115/117] Include sys/socket.h to minimize differences with pledged code --- sndiod/sndiod.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sndiod/sndiod.c b/sndiod/sndiod.c index 83f1cfa..b2c6e4c 100644 --- a/sndiod/sndiod.c +++ b/sndiod/sndiod.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include From 3d710ac72152eed2703dc5e785b80037345a4f73 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 18 Jan 2017 10:26:27 +0100 Subject: [PATCH 116/117] Use -io options to specify files and -q option to specify one or two ports, allowing port-to-port transfers. --- midicat/midicat.1 | 42 ++++++++---- midicat/midicat.c | 164 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 153 insertions(+), 53 deletions(-) diff --git a/midicat/midicat.1 b/midicat/midicat.1 index f8eaed1..bb95e1b 100644 --- a/midicat/midicat.1 +++ b/midicat/midicat.1 @@ -24,8 +24,9 @@ .Nm midicat .Bk -words .Op Fl d -.Op Fl i Ar port -.Op Fl o Ar port +.Op Fl i Ar file +.Op Fl o Ar file +.Op Fl q Ar port .Ek .Sh DESCRIPTION The @@ -36,21 +37,39 @@ The options are as follows: .Bl -tag -width Ds .It Fl d Dump transferred data in hex on stderr. -.It Fl i Ar port +.It Fl i Ar file +Read MIDI data from this file instead of receiving it from the MIDI port. +If the option argument is +.Sq - +then standard input will be used. +.It Fl o Ar file +Write MIDI data to this file instead of sending it to the MIDI port. +If the option argument is +.Sq - +then standard output will be used. +.It Fl q Ar port Use this .Xr sndio 7 -MIDI port as input instead of stdin. -.It Fl o Ar port -Use this -.Xr sndio 7 -MIDI port as output instead of stdout. +MIDI port for input/output. +If the option is used twice, the first one specifies +the input port and the second one the output port. .El +.Pp +If no files are specified, then +.Nm +transfers data from the MIDI input port to the MIDI output port. .Sh EXAMPLES +Send the given file to +.Pa rmidi/0 : +.Bd -literal -offset indent +$ midicat -i file.syx -q rmidi/0 +.Ed +.Pp Dump data received from .Pa rmidi/0 to stderr: .Bd -literal -offset indent -$ midicat -di rmidi/0 >/dev/null +$ midicat -d -q rmidi/0 -o /dev/null .Ed .Pp Send data from @@ -58,8 +77,9 @@ Send data from to .Pa midithru/0: .Bd -literal -offset indent -$ midicat -i rmidi/0 -o midithru/0 +$ midicat -q rmidi/0 -q midithru/0 .Ed .Sh SEE ALSO .Xr midi 4 , -.Xr sndio 7 +.Xr sndio 7 , +.Xr sndiod 8 diff --git a/midicat/midicat.c b/midicat/midicat.c index 5848276..2cc8bd7 100644 --- a/midicat/midicat.c +++ b/midicat/midicat.c @@ -18,9 +18,11 @@ #include #include #include +#include #include "bsd-compat.h" -char usagestr[] = "usage: midicat [-d] [-i port] [-o port]\n"; +char usagestr[] = "usage: midicat [-d] [-i in-file] [-o out-file] " + "[-q in-port] [-q out-port]\n"; int main(int argc, char **argv) @@ -28,25 +30,35 @@ main(int argc, char **argv) #define MIDI_BUFSZ 1024 unsigned char buf[MIDI_BUFSZ]; struct mio_hdl *ih, *oh; - char *in, *out; - int dump, c, i, len, sep; + char *port0, *port1, *ifile, *ofile; + int ifd, ofd; + int dump, c, i, len, n, sep, mode; dump = 0; - in = NULL; - out = NULL; - ih = NULL; - oh = NULL; - - while ((c = getopt(argc, argv, "di:o:")) != -1) { + port0 = port1 = ifile = ofile = NULL; + ih = oh = NULL; + ifd = ofd = -1; + + while ((c = getopt(argc, argv, "di:o:q:")) != -1) { switch (c) { case 'd': dump = 1; break; + case 'q': + if (port0 == NULL) + port0 = optarg; + else if (port1 == NULL) + port1 = optarg; + else { + fputs("too many -q options\n", stderr); + return 1; + } + break; case 'i': - in = optarg; + ifile = optarg; break; case 'o': - out = optarg; + ofile = optarg; break; default: goto bad_usage; @@ -59,44 +71,106 @@ main(int argc, char **argv) fputs(usagestr, stderr); return 1; } - if (in == NULL && out == NULL) { - fputs("either -i or -o required\n", stderr); - exit(1); + + /* we don't support more than one data flow */ + if (ifile != NULL && ofile != NULL) { + fputs("-i and -o are exclusive\n", stderr); + return 1; } - if (in) { - ih = mio_open(in, MIO_IN, 0); - if (ih == NULL) { - fprintf(stderr, "%s: couldn't open MIDI in\n", in); - exit(1); - } + + /* second port makes sense only for port-to-port transfers */ + if (port1 != NULL && !(ifile == NULL && ofile == NULL)) { + fputs("too many -q options\n", stderr); + return 1; } - if (out) { - oh = mio_open(out, MIO_OUT, 0); - if (oh == NULL) { - fprintf(stderr, "%s: couldn't open MIDI out\n", out); - exit(1); - } - } - for (;;) { - if (in) { - len = mio_read(ih, buf, sizeof(buf)); - if (len == 0) { - fprintf(stderr, "%s: disconnected\n", in); - break; + + /* if there're neither files nor ports, then we've nothing to do */ + if (port0 == NULL && ifile == NULL && ofile == NULL) + goto bad_usage; + + /* if no port specified, use default one */ + if (port0 == NULL) + port0 = MIO_PORTANY; + + /* open input or output file (if any) */ + if (ifile) { + if (strcmp(ifile, "-") == 0) + ifd = STDIN_FILENO; + else { + ifd = open(ifile, O_RDONLY, 0); + if (ifd < 0) { + perror(ifile); + return 1; } - } else { - len = read(STDIN_FILENO, buf, sizeof(buf)); + } + } else if (ofile) { + if (strcmp(ofile, "-") == 0) + ofd = STDOUT_FILENO; + else { + ofd = open(ofile, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (ofd < 0) { + perror(ofile); + return 1; + } + } + } + + /* open first port for input and output (if output needed) */ + if (ofile) + mode = MIO_IN; + else if (ifile) + mode = MIO_OUT; + else if (port1 == NULL) + mode = MIO_IN | MIO_OUT; + else + mode = MIO_IN; + ih = mio_open(port0, mode, 0); + if (ih == NULL) { + fprintf(stderr, "%s: couldn't open port\n", port0); + return 1; + } + + /* open second port, output only */ + if (port1 == NULL) + oh = ih; + else { + oh = mio_open(port1, MIO_OUT, 0); + if (oh == NULL) { + fprintf(stderr, "%s: couldn't open port\n", port1); + exit(1); + } + } + + /* transfer until end-of-file or error */ + for (;;) { + if (ifile != NULL) { + len = read(ifd, buf, sizeof(buf)); if (len == 0) break; if (len < 0) { perror("stdin"); - exit(1); + break; + } + } else { + len = mio_read(ih, buf, sizeof(buf)); + if (len == 0) { + fprintf(stderr, "%s: disconnected\n", port0); + break; + } + } + if (ofile != NULL) { + n = write(ofd, buf, len); + if (n != len) { + fprintf(stderr, "%s: short write\n", ofile); + break; + } + } else { + n = mio_write(oh, buf, len); + if (n != len) { + fprintf(stderr, "%s: disconnected\n", port1); + break; } } - if (out) - mio_write(oh, buf, len); - else - write(STDOUT_FILENO, buf, len); if (dump) { for (i = 0; i < len; i++) { sep = (i % 16 == 15 || i == len - 1) ? @@ -105,9 +179,15 @@ main(int argc, char **argv) } } } - if (in) + + /* clean-up */ + if (port0) mio_close(ih); - if (out) + if (port1) mio_close(oh); + if (ifile) + close(ifd); + if (ofile) + close(ofd); return 0; } From ca24b960e485eb7e4d910e347135f484e35cb4fe Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 14 Feb 2017 14:34:28 +0100 Subject: [PATCH 117/117] reorder deps in Makefile.in --- libsndio/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsndio/Makefile.in b/libsndio/Makefile.in index 4b5f8a7..8b63da2 100644 --- a/libsndio/Makefile.in +++ b/libsndio/Makefile.in @@ -138,7 +138,7 @@ sio_alsa.o: sio_alsa.c debug.h sio_priv.h sndio.h \ ../bsd-compat/bsd-compat.h sio_aucat.o: sio_aucat.c aucat.h amsg.h debug.h sio_priv.h sndio.h \ ../bsd-compat/bsd-compat.h -sio_sun.o: sio_sun.c debug.h sio_priv.h sndio.h \ - ../bsd-compat/bsd-compat.h sio_oss.o: sio_oss.c debug.h sio_priv.h sndio.h \ ../bsd-compat/bsd-compat.h +sio_sun.o: sio_sun.c debug.h sio_priv.h sndio.h \ + ../bsd-compat/bsd-compat.h