373 lines
11 KiB
C
373 lines
11 KiB
C
/* $OpenBSD: dev.h,v 1.44 2024/04/22 10:39:51 ratchov Exp $ */
|
|
/*
|
|
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
|
|
*
|
|
* 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_H
|
|
#define DEV_H
|
|
|
|
#include "abuf.h"
|
|
#include "dsp.h"
|
|
#include "siofile.h"
|
|
#include "dev_sioctl.h"
|
|
#include "opt.h"
|
|
|
|
/*
|
|
* preallocated audio clients
|
|
*/
|
|
#define DEV_NSLOT 8
|
|
|
|
/*
|
|
* preallocated control clients
|
|
*/
|
|
#define DEV_NCTLSLOT 8
|
|
|
|
/*
|
|
* audio stream state structure
|
|
*/
|
|
|
|
struct slotops
|
|
{
|
|
void (*onmove)(void *); /* clock tick */
|
|
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 */
|
|
void (*exit)(void *); /* delete client */
|
|
};
|
|
|
|
struct ctlops
|
|
{
|
|
void (*exit)(void *); /* delete client */
|
|
void (*sync)(void *); /* description ready */
|
|
};
|
|
|
|
struct slot {
|
|
struct slotops *ops; /* client callbacks */
|
|
struct slot *next; /* next on the play list */
|
|
struct opt *opt; /* config used */
|
|
void *arg; /* user data for callbacks */
|
|
struct aparams par; /* socket side params */
|
|
struct {
|
|
int weight; /* dynamic range */
|
|
unsigned int vol; /* volume within the vol */
|
|
struct abuf buf; /* socket side buffer */
|
|
int bpf; /* byte per frame */
|
|
int nch; /* number of play chans */
|
|
struct cmap cmap; /* channel mapper state */
|
|
struct resamp resamp; /* resampler state */
|
|
struct conv dec; /* format decoder params */
|
|
int join; /* channel join factor */
|
|
int expand; /* channel expand factor */
|
|
void *resampbuf, *decbuf; /* tmp buffers */
|
|
} mix;
|
|
struct {
|
|
struct abuf buf; /* socket side buffer */
|
|
int prime; /* initial cycles to skip */
|
|
int bpf; /* byte per frame */
|
|
int nch; /* number of rec chans */
|
|
struct cmap cmap; /* channel mapper state */
|
|
struct resamp resamp; /* buffer for resampling */
|
|
struct conv enc; /* buffer for encoding */
|
|
int join; /* channel join factor */
|
|
int expand; /* channel expand factor */
|
|
void *resampbuf, *encbuf; /* tmp buffers */
|
|
} sub;
|
|
int xrun; /* underrun policy */
|
|
int skip; /* cycles to skip (for xrun) */
|
|
#define SLOT_BUFSZ(s) \
|
|
((s)->appbufsz + (s)->opt->dev->bufsz / (s)->opt->dev->round * (s)->round)
|
|
int appbufsz; /* slot-side buffer size */
|
|
int round; /* slot-side block size */
|
|
int rate; /* slot-side sample rate */
|
|
int delta; /* pending clock ticks */
|
|
int delta_rem; /* remainder for delta */
|
|
int mode; /* MODE_{PLAY,REC} */
|
|
#define SLOT_INIT 0 /* not trying to do anything */
|
|
#define SLOT_START 1 /* buffer allocated */
|
|
#define SLOT_READY 2 /* buffer filled enough */
|
|
#define SLOT_RUN 3 /* buffer attached to device */
|
|
#define SLOT_STOP 4 /* draining */
|
|
int pstate;
|
|
|
|
#define SLOT_NAMEMAX 8
|
|
char name[SLOT_NAMEMAX]; /* name matching [a-z]+ */
|
|
unsigned int unit; /* instance of name */
|
|
unsigned int serial; /* global unique number */
|
|
unsigned int vol; /* current (midi) volume */
|
|
unsigned int id; /* process id */
|
|
};
|
|
|
|
/*
|
|
* subset of channels of a stream
|
|
*/
|
|
|
|
struct ctl {
|
|
struct ctl *next;
|
|
|
|
#define CTL_NONE 0 /* deleted */
|
|
#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_SEL 6 /* element of a selector */
|
|
unsigned int type; /* one of above */
|
|
|
|
#define CTL_HW 0
|
|
#define CTL_DEV_MASTER 1
|
|
#define CTL_OPT_DEV 2
|
|
#define CTL_SLOT_LEVEL 3
|
|
unsigned int scope;
|
|
union {
|
|
struct {
|
|
void *arg0;
|
|
void *arg1;
|
|
} any;
|
|
struct {
|
|
struct dev *dev;
|
|
unsigned int addr;
|
|
} hw;
|
|
struct {
|
|
struct dev *dev;
|
|
} dev_master;
|
|
struct {
|
|
struct slot *slot;
|
|
} slot_level;
|
|
struct {
|
|
struct slot *slot;
|
|
struct opt *opt;
|
|
} slot_opt;
|
|
struct {
|
|
struct opt *opt;
|
|
struct dev *dev;
|
|
} opt_dev;
|
|
} u;
|
|
|
|
unsigned int addr; /* slot side control address */
|
|
#define CTL_NAMEMAX 16 /* max name length */
|
|
char func[CTL_NAMEMAX]; /* parameter function name */
|
|
char group[CTL_NAMEMAX]; /* group aka namespace */
|
|
struct ctl_node {
|
|
char name[CTL_NAMEMAX]; /* stream name */
|
|
int unit;
|
|
} node0, node1; /* affected channels */
|
|
#define CTL_DEVMASK (1 << 31)
|
|
#define CTL_SLOTMASK(i) (1 << (i))
|
|
unsigned int val_mask;
|
|
unsigned int desc_mask;
|
|
unsigned int refs_mask;
|
|
unsigned int maxval;
|
|
unsigned int curval;
|
|
int dirty;
|
|
};
|
|
|
|
struct ctlslot {
|
|
struct ctlops *ops;
|
|
void *arg;
|
|
struct opt *opt;
|
|
unsigned int self; /* equal to (1 << index) */
|
|
unsigned int mode;
|
|
};
|
|
|
|
/*
|
|
* MIDI time code (MTC)
|
|
*/
|
|
struct mtc {
|
|
/*
|
|
* MIDI time code (MTC) states
|
|
*/
|
|
#define MTC_STOP 1 /* stopped, can't start */
|
|
#define MTC_START 2 /* attempting to start */
|
|
#define MTC_RUN 3 /* started */
|
|
unsigned int tstate; /* one of MTC_* constants */
|
|
struct dev *dev;
|
|
|
|
unsigned int origin; /* MTC start time */
|
|
unsigned int fps; /* MTC frames per second */
|
|
#define MTC_FPS_24 0
|
|
#define MTC_FPS_25 1
|
|
#define MTC_FPS_30 3
|
|
unsigned int fps_id; /* one of above */
|
|
unsigned int hr; /* MTC hours */
|
|
unsigned int min; /* MTC minutes */
|
|
unsigned int sec; /* MTC seconds */
|
|
unsigned int fr; /* MTC frames */
|
|
unsigned int qfr; /* MTC quarter frames */
|
|
int delta; /* rel. to the last MTC tick */
|
|
int refs;
|
|
};
|
|
|
|
/*
|
|
* audio device with plenty of slots
|
|
*/
|
|
struct dev {
|
|
struct dev *next;
|
|
struct slot *slot_list; /* audio streams attached */
|
|
|
|
/*
|
|
* name used for various controls
|
|
*/
|
|
char name[CTL_NAMEMAX];
|
|
|
|
/*
|
|
* next to try if this fails
|
|
*/
|
|
struct dev *alt_next;
|
|
|
|
/*
|
|
* audio device (while opened)
|
|
*/
|
|
struct dev_sio sio;
|
|
struct dev_sioctl sioctl;
|
|
struct aparams par; /* encoding */
|
|
int pchan, rchan; /* play & rec channels */
|
|
adata_t *rbuf; /* rec buffer */
|
|
adata_t *pbuf; /* array of play buffers */
|
|
#define DEV_PBUF(d) ((d)->pbuf + (d)->poffs * (d)->pchan)
|
|
int poffs; /* index of current play buf */
|
|
int psize; /* size of play buffer */
|
|
struct conv enc; /* native->device format */
|
|
struct conv dec; /* device->native format */
|
|
unsigned char *encbuf; /* buffer for encoding */
|
|
unsigned char *decbuf; /* buffer for decoding */
|
|
|
|
/*
|
|
* current position, relative to the current cycle
|
|
*/
|
|
int delta;
|
|
|
|
/*
|
|
* desired parameters
|
|
*/
|
|
unsigned int reqmode; /* mode */
|
|
struct aparams reqpar; /* parameters */
|
|
int reqpchan, reqrchan; /* play & rec chans */
|
|
unsigned int reqbufsz; /* buffer size */
|
|
unsigned int reqround; /* block size */
|
|
unsigned int reqrate; /* sample rate */
|
|
unsigned int hold; /* hold the device open ? */
|
|
unsigned int autovol; /* auto adjust playvol ? */
|
|
unsigned int refcnt; /* number of openers */
|
|
#define DEV_NMAX 16 /* max number of devices */
|
|
unsigned int num; /* device serial number */
|
|
#define DEV_CFG 0 /* closed */
|
|
#define DEV_INIT 1 /* stopped */
|
|
#define DEV_RUN 2 /* playin & recording */
|
|
unsigned int pstate; /* one of above */
|
|
char *path;
|
|
|
|
/*
|
|
* actual parameters and runtime state (i.e. once opened)
|
|
*/
|
|
unsigned int mode; /* bitmap of MODE_xxx */
|
|
unsigned int bufsz, round, rate;
|
|
unsigned int prime;
|
|
unsigned int idle; /* cycles with no client */
|
|
|
|
unsigned int master; /* software vol. knob */
|
|
unsigned int master_enabled; /* 1 if h/w has no vo. knob */
|
|
};
|
|
|
|
extern struct dev *dev_list;
|
|
extern struct ctl *ctl_list;
|
|
extern struct slot slot_array[DEV_NSLOT];
|
|
extern struct ctlslot ctlslot_array[DEV_NCTLSLOT];
|
|
extern struct mtc mtc_array[1];
|
|
|
|
void slot_array_init(void);
|
|
|
|
void dev_log(struct dev *);
|
|
int dev_open(struct dev *);
|
|
void dev_close(struct dev *);
|
|
void dev_abort(struct dev *);
|
|
struct dev *dev_migrate(struct dev *);
|
|
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 dev_init(struct dev *);
|
|
void dev_done(struct dev *);
|
|
int dev_ref(struct dev *);
|
|
void dev_unref(struct dev *);
|
|
int dev_getpos(struct dev *);
|
|
unsigned int dev_roundof(struct dev *, unsigned int);
|
|
int dev_iscompat(struct dev *, struct dev *);
|
|
|
|
/*
|
|
* interface to hardware device
|
|
*/
|
|
void dev_onmove(struct dev *, int);
|
|
void dev_cycle(struct dev *);
|
|
|
|
/*
|
|
* midi & midi call-backs
|
|
*/
|
|
void dev_master(struct dev *, unsigned int);
|
|
void dev_midi_send(struct dev *, void *, int);
|
|
void dev_midi_vol(struct dev *, struct slot *);
|
|
void dev_midi_master(struct dev *);
|
|
void dev_midi_slotdesc(struct dev *, struct slot *);
|
|
void dev_midi_dump(struct dev *);
|
|
|
|
void mtc_midi_qfr(struct mtc *, int);
|
|
void mtc_midi_full(struct mtc *);
|
|
void mtc_trigger(struct mtc *);
|
|
void mtc_start(struct mtc *);
|
|
void mtc_stop(struct mtc *);
|
|
void mtc_loc(struct mtc *, unsigned int);
|
|
void mtc_setdev(struct mtc *, struct dev *);
|
|
|
|
/*
|
|
* sio_open(3) like interface for clients
|
|
*/
|
|
void slot_log(struct slot *);
|
|
struct slot *slot_new(struct opt *, unsigned int, char *,
|
|
struct slotops *, void *, int);
|
|
void slot_del(struct slot *);
|
|
void slot_setvol(struct slot *, unsigned int);
|
|
void slot_setopt(struct slot *, struct opt *);
|
|
void slot_start(struct slot *);
|
|
void slot_stop(struct slot *, int);
|
|
void slot_read(struct slot *);
|
|
void slot_write(struct slot *);
|
|
void slot_initconv(struct slot *);
|
|
void slot_attach(struct slot *);
|
|
void slot_detach(struct slot *);
|
|
|
|
/*
|
|
* control related functions
|
|
*/
|
|
|
|
struct ctl *ctl_new(int, void *, void *,
|
|
int, char *, char *, int, char *, char *, int, int, int);
|
|
int ctl_del(int, void *, void *);
|
|
void ctl_log(struct ctl *);
|
|
int ctl_setval(struct ctl *c, int val);
|
|
int ctl_match(struct ctl *, int, void *, void *);
|
|
struct ctl *ctl_find(int, void *, void *);
|
|
void ctl_update(struct ctl *);
|
|
int ctl_onval(int, void *, void *, int);
|
|
|
|
struct ctlslot *ctlslot_new(struct opt *, struct ctlops *, void *);
|
|
void ctlslot_del(struct ctlslot *);
|
|
int ctlslot_visible(struct ctlslot *, struct ctl *);
|
|
struct ctl *ctlslot_lookup(struct ctlslot *, int);
|
|
void ctlslot_update(struct ctlslot *);
|
|
|
|
void dev_label(struct dev *, int);
|
|
void dev_ctlsync(struct dev *);
|
|
|
|
#endif /* !defined(DEV_H) */
|