123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- #include <errno.h>
- #include <limits.h>
- #include <stdarg.h>
- #include <stddef.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sndio.h>
- #include "au.h"
- #include "adev.h"
- #include "common.h"
- enum {
- A_NULL,
- A_ENC,
- A_RATE,
- A_CHAN
- };
- struct adev {
- struct sio_hdl *sio;
- int needstart;
- };
- const struct a_lookup stab[] = {
- { "enc", A_ENC },
- { "encoding", A_ENC },
- { "rate", A_RATE },
- { "chan", A_CHAN },
- { "channel", A_CHAN },
- { "channels", A_CHAN },
- { NULL, A_NULL }
- };
- struct adev *
- ad_open(const char *dev, int mode)
- {
- struct adev *a;
- if ((a = malloc(sizeof(struct adev))) == NULL)
- return (NULL);
- if ((a->sio = sio_open(dev != NULL ? dev : SIO_DEVANY,
- (mode & A_WRITE) ? SIO_PLAY : SIO_REC, 0)) == NULL) {
- free(a);
- return (NULL);
- }
- a->needstart = 1;
- return (a);
- }
- struct adev *
- ad_fpopen(FILE *fp, int mode)
- {
- ERR(EOPNOTSUPP, NULL);
- }
- void
- ad_close(struct adev *a)
- {
- if (a == NULL)
- return;
- if (!a->needstart)
- (void)sio_stop(a->sio);
- sio_close(a->sio);
- free(a);
- }
- int
- ad_limit(struct adev *a)
- {
- #ifdef USE_PLEDGE
- return (pledge("audio stdio", NULL));
- #else
- ERR(ENOSYS, -1);
- #endif
- }
- int
- ad_get(struct adev *a, const char *s, ...)
- {
- ERR(EOPNOTSUPP, -1);
- }
- int
- ad_set(struct adev *a, const char *s, ...)
- {
- struct sio_par p;
- va_list ap;
- ssize_t r;
- int n;
- int v;
- if (a == NULL || s == NULL)
- ERR(EINVAL, -1);
- if (!a->needstart && !sio_stop(a->sio))
- ERR(EOPNOTSUPP, -1);
- a->needstart = 1;
- sio_initpar(&p);
- p.le = 0;
- p.sig = 1;
- p.msb = 1;
- va_start(ap, s);
- for (n = 0; (r = a_lookup(stab, s, &v)) > 0; n++, s += r)
- switch (v) {
- case A_ENC:
- switch (va_arg(ap, uint32_t)) {
- case AU_PCM8:
- p.bits = 8;
- break;
- case AU_PCM16:
- p.bits = 16;
- break;
- case AU_PCM24:
- p.bits = 24;
- break;
- case AU_PCM32:
- p.bits = 32;
- break;
- default:
- ERR(EINVAL, -1);
- }
- p.bps = SIO_BPS(p.bits);
- break;
- case A_RATE:
- p.rate = va_arg(ap, uint32_t);
- break;
- case A_CHAN:
- p.rchan = p.pchan = va_arg(ap, uint32_t);
- break;
- default:
- goto err;
- }
- if (r == 0) {
- if (!sio_setpar(a->sio, &p))
- goto err;
- va_end(ap);
- return (n);
- }
- err:
- va_end(ap);
- ERR(EINVAL, n);
- }
- ssize_t
- ad_write(struct adev *a, const void *b, size_t size)
- {
- size_t r;
- if (a == NULL || b == NULL)
- ERR(EFAULT, -1);
- if (a->needstart) {
- if (!sio_start(a->sio))
- ERR(EINVAL, -1);
- a->needstart = 0;
- }
- while ((r = sio_write(a->sio, b, size)) == 0 &&
- !sio_eof(a->sio))
- /* do nothing */;
- return (r);
- }
- ssize_t
- ad_read(struct adev *a, void *b, size_t size)
- {
- size_t r;
- if (a == NULL || b == NULL)
- ERR(EFAULT, -1);
- if (a->needstart) {
- if (!sio_start(a->sio))
- ERR(EINVAL, -1);
- a->needstart = 0;
- }
- while ((r = sio_read(a->sio, b, size)) == 0 && !sio_eof(a->sio))
- /* do nothing */;
- return (r);
- }
|