Edit

IABSD.fr/src/usr.bin/sndiod/dev.h

Branch :

  • Show log

    Commit

  • Author : ratchov
    Date : 2026-05-26 14:50:52
    Hash : 05c105ac
    Message : sndiod: Make the device sample rate and buffer sizes global

  • usr.bin/sndiod/dev.h
  • /*	$OpenBSD: dev.h,v 1.55 2026/05/26 14:50:52 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	32
    
    /*
     * preallocated control clients
     */
    #define DEV_NCTLSLOT 8
    
    /*
     * audio stream state structure
     */
    
    struct slotops
    {
    	void (*onmove)(void *);			/* clock tick */
    	void (*onxrun)(void *);			/* xrun */
    	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_rec;		/* rec channel mapper state */
    		struct cmap cmap_mon;		/* mon channel mapper state */
    		struct resamp resamp;		/* buffer for resampling */
    		struct conv enc;		/* buffer for encoding */
    		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;
    	int paused;				/* paused because of xrun */
    
    	struct app *app;
    };
    
    /*
     * 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_APP_LEVEL	3
    #define CTL_OPT_MODE	4
    	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 opt *opt;
    			struct app *app;
    		} app_level;
    		struct {
    			struct opt *opt;
    			struct dev *dev;
    		} opt_dev;
    		struct {
    			struct opt *opt;
    			int idx;
    		} opt_mode;
    	} u;
    
    	unsigned int addr;		/* slot side control address */
    #define CTL_NAMEMAX	12		/* max name length */
    #define CTL_DISPLAYMAX	24		/* max name length */
    	char func[CTL_NAMEMAX];		/* parameter function name */
    	char group[CTL_NAMEMAX];	/* group aka namespace */
    	char display[CTL_DISPLAYMAX];	/* free-format hint */
    	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
    	 */
    	struct aparams reqpar;			/* parameters */
    	int reqpchan, reqrchan;			/* play & rec chans */
    	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];
    extern int dev_rate, dev_bufsz, dev_round;
    
    size_t chans_fmt(char *, size_t, int, int, int, int, int);
    int dev_open(struct dev *);
    void dev_close(struct dev *);
    void dev_abort(struct dev *);
    void dev_migrate(struct dev *);
    struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int);
    struct dev *dev_bynum(int);
    void dev_del(struct dev *);
    void dev_adjpar(struct dev *, int, int);
    int  dev_init(struct dev *);
    void dev_done(struct dev *);
    int dev_ref(struct dev *);
    void dev_unref(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_master(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
     */
    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 *, char *, int, char *, char *, int, int, int);
    int ctl_del(int, void *, void *);
    size_t ctl_node_fmt(char *, size_t, struct ctl_node *);
    size_t ctl_scope_fmt(char *, size_t, struct ctl *);
    size_t ctl_fmt(char *, size_t, 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 *);
    
    char *dev_getdisplay(struct dev *);
    void dev_ctlsync(struct dev *);
    
    #endif /* !defined(DEV_H) */