sndio/sndiod/dev.h

363 lines
10 KiB
C

/* $OpenBSD$ */
/*
* 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_DEV_ALT 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 dev *dev;
unsigned int idx;
} dev_alt;
struct {
struct slot *slot;
} slot_level;
} u;
unsigned int addr; /* slot side control address */
#define CTL_NAMEMAX 16 /* max name lenght */
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];
/*
* 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 */
struct dev_alt {
struct dev_alt *next;
char *name;
unsigned int idx;
} *alt_list;
int alt_num;
/*
* 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 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 *);
void dev_abort(struct dev *);
int dev_reopen(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);
int dev_addname(struct dev *, char *);
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);
/*
* 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_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);
void 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 dev_label(struct dev *, int);
void dev_ctlsync(struct dev *);
#endif /* !defined(DEV_H) */