Home | History | Annotate | Line # | Download | only in libntp
audio.c revision 1.5.4.2.2.3
      1  1.5.4.2.2.3       snj /*	$NetBSD: audio.c,v 1.5.4.2.2.3 2017/04/20 06:42:18 snj Exp $	*/
      2          1.1    kardel 
      3          1.1    kardel /*
      4          1.1    kardel  * audio.c - audio interface for reference clock audio drivers
      5          1.1    kardel  */
      6          1.1    kardel #ifdef HAVE_CONFIG_H
      7          1.1    kardel # include <config.h>
      8          1.1    kardel #endif
      9          1.1    kardel 
     10          1.1    kardel #if defined(HAVE_SYS_AUDIOIO_H) || defined(HAVE_SUN_AUDIOIO_H) || \
     11          1.1    kardel     defined(HAVE_SYS_SOUNDCARD_H) || defined(HAVE_MACHINE_SOUNDCARD_H)
     12          1.1    kardel 
     13          1.1    kardel #include "audio.h"
     14          1.1    kardel #include "ntp_stdlib.h"
     15          1.1    kardel #include "ntp_syslog.h"
     16          1.1    kardel #ifdef HAVE_UNISTD_H
     17          1.1    kardel # include <unistd.h>
     18          1.1    kardel #endif
     19          1.1    kardel #include <stdio.h>
     20          1.1    kardel #include "ntp_string.h"
     21          1.1    kardel 
     22          1.1    kardel #ifdef HAVE_SYS_AUDIOIO_H
     23          1.1    kardel # include <sys/audioio.h>
     24          1.1    kardel #endif /* HAVE_SYS_AUDIOIO_H */
     25          1.1    kardel 
     26          1.1    kardel #ifdef HAVE_SUN_AUDIOIO_H
     27          1.1    kardel # include <sys/ioccom.h>
     28          1.1    kardel # include <sun/audioio.h>
     29          1.1    kardel #endif /* HAVE_SUN_AUDIOIO_H */
     30          1.1    kardel 
     31          1.1    kardel #ifdef HAVE_SYS_IOCTL_H
     32          1.1    kardel # include <sys/ioctl.h>
     33          1.1    kardel #endif /* HAVE_SYS_IOCTL_H */
     34          1.1    kardel 
     35          1.1    kardel #include <fcntl.h>
     36          1.1    kardel 
     37          1.1    kardel #ifdef HAVE_MACHINE_SOUNDCARD_H
     38          1.1    kardel # include <machine/soundcard.h>
     39          1.1    kardel # define PCM_STYLE_SOUND
     40          1.1    kardel #else
     41          1.1    kardel # ifdef HAVE_SYS_SOUNDCARD_H
     42          1.1    kardel #  include <sys/soundcard.h>
     43          1.1    kardel #  define PCM_STYLE_SOUND
     44          1.1    kardel # endif
     45          1.1    kardel #endif
     46          1.1    kardel 
     47          1.1    kardel #ifdef PCM_STYLE_SOUND
     48          1.1    kardel # include <ctype.h>
     49          1.1    kardel #endif
     50          1.1    kardel 
     51  1.5.4.2.2.3       snj 
     52  1.5.4.2.2.3       snj /*
     53  1.5.4.2.2.3       snj  * 4.4BSD-Lite switched to an unsigned long ioctl arg.  Detect common
     54  1.5.4.2.2.3       snj  * derivatives here, and apply that type. To make the following code
     55  1.5.4.2.2.3       snj  * less verbose we make a proper typedef.
     56  1.5.4.2.2.3       snj  * The joy of IOCTL programming...
     57  1.5.4.2.2.3       snj  */
     58  1.5.4.2.2.3       snj # if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__) || defined __OpenBSD__
     59  1.5.4.2.2.3       snj typedef unsigned long ioctl_arg_T;
     60  1.5.4.2.2.3       snj #else
     61  1.5.4.2.2.3       snj typedef int ioctl_arg_T;
     62  1.5.4.2.2.3       snj #endif
     63  1.5.4.2.2.3       snj 
     64          1.1    kardel /*
     65          1.1    kardel  * Global variables
     66          1.1    kardel  */
     67          1.1    kardel #ifdef HAVE_SYS_AUDIOIO_H
     68          1.1    kardel static struct audio_device device; /* audio device ident */
     69          1.1    kardel #endif /* HAVE_SYS_AUDIOIO_H */
     70          1.1    kardel #ifdef PCM_STYLE_SOUND
     71          1.1    kardel # define INIT_FILE "/etc/ntp.audio"
     72          1.1    kardel 
     73  1.5.4.2.2.3       snj static ioctl_arg_T agc		= SOUND_MIXER_WRITE_RECLEV; /* or IGAIN or LINE */
     74  1.5.4.2.2.3       snj static ioctl_arg_T audiomonitor	= SOUND_MIXER_WRITE_VOLUME; /* or OGAIN */
     75  1.5.4.2.2.3       snj static int devmask = 0;
     76  1.5.4.2.2.3       snj static int recmask = 0;
     77  1.5.4.2.2.3       snj static char cf_c_dev[100], cf_i_dev[100], cf_agc[100], cf_monitor[100];
     78  1.5.4.2.2.3       snj 
     79  1.5.4.2.2.3       snj static const char *m_names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
     80          1.1    kardel #else /* not PCM_STYLE_SOUND */
     81          1.1    kardel static struct audio_info info;	/* audio device info */
     82          1.1    kardel #endif /* not PCM_STYLE_SOUND */
     83          1.1    kardel static int ctl_fd;		/* audio control file descriptor */
     84          1.1    kardel 
     85          1.1    kardel #ifdef PCM_STYLE_SOUND
     86      1.5.4.2       snj static void audio_config_read (int, const char **, const char **);
     87          1.1    kardel static int  mixer_name (const char *, int);
     88          1.1    kardel 
     89          1.1    kardel 
     90          1.1    kardel int
     91          1.1    kardel mixer_name(
     92          1.1    kardel 	const char *m_name,
     93          1.1    kardel 	int m_mask
     94          1.1    kardel 	)
     95          1.1    kardel {
     96          1.1    kardel 	int i;
     97          1.1    kardel 
     98          1.1    kardel 	for (i = 0; i < SOUND_MIXER_NRDEVICES; ++i)
     99          1.1    kardel 		if (((1 << i) & m_mask)
    100          1.1    kardel 		    && !strcmp(m_names[i], m_name))
    101          1.1    kardel 			break;
    102          1.1    kardel 
    103          1.1    kardel 	return (SOUND_MIXER_NRDEVICES == i)
    104          1.1    kardel 	    ? -1
    105          1.1    kardel 	    : i
    106          1.1    kardel 	    ;
    107          1.1    kardel }
    108          1.1    kardel 
    109          1.1    kardel 
    110          1.1    kardel /*
    111          1.1    kardel  * Check:
    112          1.1    kardel  *
    113          1.1    kardel  * /etc/ntp.audio#	where # is the unit number
    114          1.1    kardel  * /etc/ntp.audio.#	where # is the unit number
    115          1.1    kardel  * /etc/ntp.audio
    116          1.1    kardel  *
    117          1.1    kardel  * for contents of the form:
    118          1.1    kardel  *
    119          1.1    kardel  * idev /dev/input_device
    120          1.1    kardel  * cdev /dev/control_device
    121          1.1    kardel  * agc pcm_input_device {igain,line,line1,...}
    122          1.1    kardel  * monitor pcm_monitor_device {ogain,...}
    123          1.1    kardel  *
    124          1.1    kardel  * The device names for the "agc" and "monitor" keywords
    125          1.1    kardel  * can be found by running either the "mixer" program or the
    126          1.1    kardel  * util/audio-pcm program.
    127          1.1    kardel  *
    128          1.1    kardel  * Great hunks of this subroutine were swiped from refclock_oncore.c
    129          1.1    kardel  */
    130          1.1    kardel static void
    131          1.1    kardel audio_config_read(
    132          1.1    kardel 	int unit,
    133      1.5.4.2       snj 	const char **c_dev,	/* Control device */
    134      1.5.4.2       snj 	const char **i_dev	/* input device */
    135          1.1    kardel 	)
    136          1.1    kardel {
    137          1.1    kardel 	FILE *fd;
    138          1.1    kardel 	char device[20], line[100], ab[100];
    139          1.1    kardel 
    140          1.4    kardel 	snprintf(device, sizeof(device), "%s%d", INIT_FILE, unit);
    141          1.1    kardel 	if ((fd = fopen(device, "r")) == NULL) {
    142          1.1    kardel 		printf("audio_config_read: <%s> NO\n", device);
    143          1.4    kardel 		snprintf(device, sizeof(device), "%s.%d", INIT_FILE,
    144          1.4    kardel 			 unit);
    145          1.1    kardel 		if ((fd = fopen(device, "r")) == NULL) {
    146          1.1    kardel 			printf("audio_config_read: <%s> NO\n", device);
    147          1.4    kardel 			snprintf(device, sizeof(device), "%s",
    148          1.4    kardel 				 INIT_FILE);
    149          1.1    kardel 			if ((fd = fopen(device, "r")) == NULL) {
    150          1.4    kardel 				printf("audio_config_read: <%s> NO\n",
    151          1.4    kardel 				       device);
    152          1.1    kardel 				return;
    153          1.1    kardel 			}
    154          1.1    kardel 		}
    155          1.1    kardel 	}
    156          1.1    kardel 	printf("audio_config_read: reading <%s>\n", device);
    157          1.1    kardel 	while (fgets(line, sizeof line, fd)) {
    158          1.1    kardel 		char *cp, *cc, *ca;
    159          1.1    kardel 		int i;
    160          1.1    kardel 
    161          1.1    kardel 		/* Remove comments */
    162          1.1    kardel 		if ((cp = strchr(line, '#')))
    163          1.1    kardel 			*cp = '\0';
    164          1.1    kardel 
    165          1.1    kardel 		/* Remove any trailing spaces */
    166          1.1    kardel 		for (i = strlen(line);
    167          1.2  christos 		     i > 0 && isascii((unsigned char)line[i - 1]) && isspace((unsigned char)line[i - 1]);
    168          1.1    kardel 			)
    169          1.1    kardel 			line[--i] = '\0';
    170          1.1    kardel 
    171          1.1    kardel 		/* Remove leading space */
    172          1.2  christos 		for (cc = line; *cc && isascii((unsigned char)*cc) && isspace((unsigned char)*cc); cc++)
    173          1.1    kardel 			continue;
    174          1.1    kardel 
    175          1.1    kardel 		/* Stop if nothing left */
    176          1.1    kardel 		if (!*cc)
    177          1.1    kardel 			continue;
    178          1.1    kardel 
    179          1.1    kardel 		/* Uppercase the command and find the arg */
    180          1.1    kardel 		for (ca = cc; *ca; ca++) {
    181          1.2  christos 			if (isascii((unsigned char)*ca)) {
    182          1.2  christos 				if (islower((unsigned char)*ca)) {
    183          1.2  christos 					*ca = toupper((unsigned char)*ca);
    184          1.2  christos 				} else if (isspace((unsigned char)*ca) || (*ca == '='))
    185          1.1    kardel 					break;
    186          1.1    kardel 			}
    187          1.1    kardel 		}
    188          1.1    kardel 
    189          1.1    kardel 		/* Remove space (and possible =) leading the arg */
    190          1.2  christos 		for (; *ca && isascii((unsigned char)*ca) && (isspace((unsigned char)*ca) || (*ca == '=')); ca++)
    191          1.1    kardel 			continue;
    192          1.1    kardel 
    193          1.4    kardel 		if (!strncmp(cc, "IDEV", 4) &&
    194          1.4    kardel 		    1 == sscanf(ca, "%99s", ab)) {
    195          1.5  christos 			strlcpy(cf_i_dev, ab, sizeof(cf_i_dev));
    196          1.1    kardel 			printf("idev <%s>\n", ab);
    197          1.4    kardel 		} else if (!strncmp(cc, "CDEV", 4) &&
    198          1.4    kardel 			   1 == sscanf(ca, "%99s", ab)) {
    199          1.5  christos 			strlcpy(cf_c_dev, ab, sizeof(cf_c_dev));
    200          1.1    kardel 			printf("cdev <%s>\n", ab);
    201          1.4    kardel 		} else if (!strncmp(cc, "AGC", 3) &&
    202          1.4    kardel 			   1 == sscanf(ca, "%99s", ab)) {
    203          1.5  christos 			strlcpy(cf_agc, ab, sizeof(cf_agc));
    204          1.1    kardel 			printf("agc <%s> %d\n", ab, i);
    205          1.4    kardel 		} else if (!strncmp(cc, "MONITOR", 7) &&
    206          1.4    kardel 			   1 == sscanf(ca, "%99s", ab)) {
    207          1.5  christos 			strlcpy(cf_monitor, ab, sizeof(cf_monitor));
    208          1.1    kardel 			printf("monitor <%s> %d\n", ab, mixer_name(ab, -1));
    209          1.1    kardel 		}
    210          1.1    kardel 	}
    211          1.1    kardel 	fclose(fd);
    212          1.1    kardel 	return;
    213          1.1    kardel }
    214          1.1    kardel #endif /* PCM_STYLE_SOUND */
    215          1.1    kardel 
    216          1.1    kardel /*
    217          1.1    kardel  * audio_init - open and initialize audio device
    218          1.1    kardel  *
    219          1.1    kardel  * This code works with SunOS 4.x, Solaris 2.x, and PCM; however, it is
    220          1.1    kardel  * believed generic and applicable to other systems with a minor twid
    221          1.1    kardel  * or two. All it does is open the device, set the buffer size (Solaris
    222          1.1    kardel  * only), preset the gain and set the input port. It assumes that the
    223          1.1    kardel  * codec sample rate (8000 Hz), precision (8 bits), number of channels
    224          1.1    kardel  * (1) and encoding (ITU-T G.711 mu-law companded) have been set by
    225          1.1    kardel  * default.
    226          1.1    kardel  */
    227          1.1    kardel int
    228          1.1    kardel audio_init(
    229          1.3  christos 	const char *dname,	/* device name */
    230          1.1    kardel 	int	bufsiz,		/* buffer size */
    231          1.1    kardel 	int	unit		/* device unit (0-3) */
    232          1.1    kardel 	)
    233          1.1    kardel {
    234          1.1    kardel #ifdef PCM_STYLE_SOUND
    235          1.1    kardel # define ACTL_DEV	"/dev/mixer%d"
    236          1.1    kardel 	char actl_dev[30];
    237          1.1    kardel # ifdef HAVE_STRUCT_SND_SIZE
    238          1.1    kardel 	struct snd_size s_size;
    239          1.1    kardel # endif
    240          1.1    kardel # ifdef AIOGFMT
    241          1.1    kardel 	snd_chan_param s_c_p;
    242          1.1    kardel # endif
    243          1.1    kardel #endif
    244          1.1    kardel 	int fd;
    245          1.1    kardel 	int rval;
    246          1.3  christos 	const char *actl =
    247          1.1    kardel #ifdef PCM_STYLE_SOUND
    248          1.1    kardel 		actl_dev
    249          1.1    kardel #else
    250          1.1    kardel 		"/dev/audioctl"
    251          1.1    kardel #endif
    252          1.1    kardel 		;
    253          1.1    kardel 
    254          1.1    kardel #ifdef PCM_STYLE_SOUND
    255          1.4    kardel 	snprintf(actl_dev, sizeof(actl_dev), ACTL_DEV, unit);
    256          1.1    kardel 
    257          1.1    kardel 	audio_config_read(unit, &actl, &dname);
    258          1.1    kardel 	/* If we have values for cf_c_dev or cf_i_dev, use them. */
    259          1.1    kardel 	if (*cf_c_dev)
    260          1.1    kardel 		actl = cf_c_dev;
    261          1.1    kardel 	if (*cf_i_dev)
    262          1.1    kardel 		dname = cf_i_dev;
    263          1.1    kardel #endif
    264          1.1    kardel 
    265          1.1    kardel 	/*
    266          1.1    kardel 	 * Open audio device
    267          1.1    kardel 	 */
    268          1.1    kardel 	fd = open(dname, O_RDWR | O_NONBLOCK, 0777);
    269          1.1    kardel 	if (fd < 0) {
    270          1.5  christos 		msyslog(LOG_ERR, "audio_init: %s %m", dname);
    271          1.1    kardel 		return (fd);
    272          1.1    kardel 	}
    273          1.1    kardel 
    274          1.1    kardel 	/*
    275          1.1    kardel 	 * Open audio control device.
    276          1.1    kardel 	 */
    277          1.1    kardel 	ctl_fd = open(actl, O_RDWR);
    278          1.1    kardel 	if (ctl_fd < 0) {
    279          1.5  christos 		msyslog(LOG_ERR, "audio_init: invalid control device <%s>",
    280          1.1    kardel 		    actl);
    281          1.1    kardel 		close(fd);
    282          1.1    kardel 		return(ctl_fd);
    283          1.1    kardel 	}
    284          1.1    kardel 
    285          1.1    kardel 	/*
    286          1.1    kardel 	 * Set audio device parameters.
    287          1.1    kardel 	 */
    288          1.1    kardel #ifdef PCM_STYLE_SOUND
    289          1.1    kardel 	printf("audio_init: <%s> bufsiz %d\n", dname, bufsiz);
    290          1.1    kardel 	rval = fd;
    291          1.1    kardel 
    292          1.1    kardel # ifdef HAVE_STRUCT_SND_SIZE
    293          1.1    kardel 	if (ioctl(fd, AIOGSIZE, &s_size) == -1)
    294          1.1    kardel 	    printf("audio_init: AIOGSIZE: %s\n", strerror(errno));
    295          1.1    kardel 	else
    296          1.1    kardel 	    printf("audio_init: orig: play_size %d, rec_size %d\n",
    297          1.1    kardel 		s_size.play_size, s_size.rec_size);
    298          1.1    kardel 
    299          1.1    kardel 	s_size.play_size = s_size.rec_size = bufsiz;
    300          1.1    kardel 	printf("audio_init: want: play_size %d, rec_size %d\n",
    301          1.1    kardel 	       s_size.play_size, s_size.rec_size);
    302          1.1    kardel 
    303          1.1    kardel 	if (ioctl(fd, AIOSSIZE, &s_size) == -1)
    304          1.1    kardel 	    printf("audio_init: AIOSSIZE: %s\n", strerror(errno));
    305          1.1    kardel 	else
    306          1.1    kardel 	    printf("audio_init: set:  play_size %d, rec_size %d\n",
    307          1.1    kardel 		s_size.play_size, s_size.rec_size);
    308          1.1    kardel # endif /* HAVE_STRUCT_SND_SIZE */
    309          1.1    kardel 
    310          1.1    kardel # ifdef SNDCTL_DSP_SETFRAGMENT
    311          1.1    kardel 	{
    312          1.1    kardel 		int tmp = (16 << 16) + 6; /* 16 fragments, each 2^6 bytes */
    313          1.1    kardel 		if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
    314          1.1    kardel 		    printf("audio_init: SNDCTL_DSP_SETFRAGMENT: %s\n",
    315          1.1    kardel 			   strerror(errno));
    316          1.1    kardel 	}
    317          1.1    kardel # endif /* SNDCTL_DSP_SETFRAGMENT */
    318          1.1    kardel 
    319          1.1    kardel # ifdef AIOGFMT
    320          1.1    kardel 	if (ioctl(fd, AIOGFMT, &s_c_p) == -1)
    321          1.1    kardel 	    printf("audio_init: AIOGFMT: %s\n", strerror(errno));
    322          1.1    kardel 	else
    323          1.1    kardel 	    printf("audio_init: play_rate %lu, rec_rate %lu, play_format %#lx, rec_format %#lx\n",
    324          1.1    kardel 		s_c_p.play_rate, s_c_p.rec_rate, s_c_p.play_format, s_c_p.rec_format);
    325          1.1    kardel # endif
    326          1.1    kardel 
    327          1.1    kardel 	/* Grab the device and record masks */
    328          1.1    kardel 
    329          1.1    kardel 	if (ioctl(ctl_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1)
    330          1.1    kardel 	    printf("SOUND_MIXER_READ_DEVMASK: %s\n", strerror(errno));
    331          1.1    kardel 	if (ioctl(ctl_fd, SOUND_MIXER_READ_RECMASK, &recmask) == -1)
    332          1.1    kardel 	    printf("SOUND_MIXER_READ_RECMASK: %s\n", strerror(errno));
    333          1.1    kardel 
    334          1.1    kardel 	/* validate and set any specified config file stuff */
    335          1.4    kardel 	if (cf_agc[0] != '\0') {
    336          1.1    kardel 		int i;
    337          1.1    kardel 
    338          1.5  christos 		/* recmask */
    339          1.5  christos 		i = mixer_name(cf_agc, recmask);
    340          1.1    kardel 		if (i >= 0)
    341          1.1    kardel 			agc = MIXER_WRITE(i);
    342          1.1    kardel 		else
    343          1.1    kardel 			printf("input %s not in recmask %#x\n",
    344          1.1    kardel 			       cf_agc, recmask);
    345          1.1    kardel 	}
    346          1.1    kardel 
    347          1.4    kardel 	if (cf_monitor[0] != '\0') {
    348          1.1    kardel 		int i;
    349          1.1    kardel 
    350          1.1    kardel 		/* devmask */
    351          1.1    kardel 		i = mixer_name(cf_monitor, devmask);
    352          1.1    kardel 		if (i >= 0)
    353  1.5.4.2.2.2    martin                        audiomonitor = MIXER_WRITE(i);
    354          1.1    kardel 		else
    355          1.1    kardel 			printf("monitor %s not in devmask %#x\n",
    356          1.1    kardel 			       cf_monitor, devmask);
    357          1.1    kardel 	}
    358          1.1    kardel 
    359          1.1    kardel #else /* not PCM_STYLE_SOUND */
    360          1.1    kardel 	AUDIO_INITINFO(&info);
    361          1.1    kardel 	info.play.gain = AUDIO_MAX_GAIN;
    362          1.1    kardel 	info.play.port = AUDIO_SPEAKER;
    363          1.1    kardel # ifdef HAVE_SYS_AUDIOIO_H
    364          1.1    kardel 	info.record.buffer_size = bufsiz;
    365          1.1    kardel # endif /* HAVE_SYS_AUDIOIO_H */
    366  1.5.4.2.2.3       snj 	rval = ioctl(ctl_fd, AUDIO_SETINFO, (char *)&info);
    367          1.1    kardel 	if (rval < 0) {
    368          1.5  christos 		msyslog(LOG_ERR, "audio: invalid control device parameters");
    369          1.1    kardel 		close(ctl_fd);
    370          1.1    kardel 		close(fd);
    371          1.1    kardel 		return(rval);
    372          1.1    kardel 	}
    373          1.1    kardel 	rval = fd;
    374          1.1    kardel #endif /* not PCM_STYLE_SOUND */
    375          1.1    kardel 	return (rval);
    376          1.1    kardel }
    377          1.1    kardel 
    378          1.1    kardel 
    379          1.1    kardel /*
    380          1.1    kardel  * audio_gain - adjust codec gains and port
    381          1.1    kardel  */
    382          1.1    kardel int
    383          1.1    kardel audio_gain(
    384          1.1    kardel 	int gain,		/* volume level (gain) 0-255 */
    385          1.1    kardel 	int mongain,		/* input to output mix (monitor gain) 0-255 */
    386          1.1    kardel 	int port		/* selected I/O port: 1 mic/2 line in */
    387          1.1    kardel 	)
    388          1.1    kardel {
    389          1.1    kardel 	int rval;
    390          1.1    kardel 	static int o_mongain = -1;
    391          1.1    kardel 	static int o_port = -1;
    392          1.1    kardel 
    393          1.1    kardel #ifdef PCM_STYLE_SOUND
    394          1.1    kardel 	int l, r;
    395          1.1    kardel 
    396  1.5.4.2.2.1       riz # ifdef GCC
    397  1.5.4.2.2.1       riz 	rval = 0;		/* GCC thinks rval is used uninitialized */
    398  1.5.4.2.2.1       riz # endif
    399          1.1    kardel 
    400          1.1    kardel 	r = l = 100 * gain / 255;	/* Normalize to 0-100 */
    401          1.1    kardel # ifdef DEBUG
    402          1.1    kardel 	if (debug > 1)
    403          1.1    kardel 		printf("audio_gain: gain %d/%d\n", gain, l);
    404          1.1    kardel # endif
    405          1.1    kardel #if 0	/* not a good idea to do this; connector wiring dependency */
    406          1.1    kardel 	/* figure out what channel(s) to use. just nuke right for now. */
    407          1.1    kardel 	r = 0 ; /* setting to zero nicely mutes the channel */
    408          1.1    kardel #endif
    409          1.1    kardel 	l |= r << 8;
    410          1.4    kardel 	if (cf_agc[0] != '\0')
    411          1.4    kardel 		rval = ioctl(ctl_fd, agc, &l);
    412          1.4    kardel 	else
    413  1.5.4.2.2.1       riz 		rval = ioctl(ctl_fd
    414  1.5.4.2.2.1       riz 			    , (2 == port)
    415  1.5.4.2.2.1       riz 				? SOUND_MIXER_WRITE_LINE
    416  1.5.4.2.2.1       riz 				: SOUND_MIXER_WRITE_MIC
    417  1.5.4.2.2.1       riz 			    , &l);
    418          1.4    kardel 	if (-1 == rval) {
    419          1.1    kardel 		printf("audio_gain: agc write: %s\n", strerror(errno));
    420          1.4    kardel 		return rval;
    421          1.1    kardel 	}
    422          1.1    kardel 
    423          1.1    kardel 	if (o_mongain != mongain) {
    424          1.1    kardel 		r = l = 100 * mongain / 255;    /* Normalize to 0-100 */
    425          1.1    kardel # ifdef DEBUG
    426          1.1    kardel 		if (debug > 1)
    427          1.1    kardel 			printf("audio_gain: mongain %d/%d\n", mongain, l);
    428          1.1    kardel # endif
    429          1.1    kardel 		l |= r << 8;
    430          1.4    kardel 		if (cf_monitor[0] != '\0')
    431  1.5.4.2.2.2    martin                        rval = ioctl(ctl_fd, audiomonitor, &l );
    432          1.4    kardel 		else
    433          1.4    kardel 			rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_VOLUME,
    434          1.4    kardel 				     &l);
    435          1.4    kardel 		if (-1 == rval) {
    436          1.1    kardel 			printf("audio_gain: mongain write: %s\n",
    437          1.1    kardel 			       strerror(errno));
    438          1.1    kardel 			return (rval);
    439          1.1    kardel 		}
    440          1.1    kardel 		o_mongain = mongain;
    441          1.1    kardel 	}
    442          1.1    kardel 
    443          1.1    kardel 	if (o_port != port) {
    444          1.1    kardel # ifdef DEBUG
    445          1.1    kardel 		if (debug > 1)
    446          1.1    kardel 			printf("audio_gain: port %d\n", port);
    447          1.1    kardel # endif
    448          1.1    kardel 		l = (1 << ((port == 2) ? SOUND_MIXER_LINE : SOUND_MIXER_MIC));
    449          1.1    kardel 		rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_RECSRC, &l);
    450          1.1    kardel 		if (rval == -1) {
    451          1.1    kardel 			printf("SOUND_MIXER_WRITE_RECSRC: %s\n",
    452          1.1    kardel 			       strerror(errno));
    453          1.1    kardel 			return (rval);
    454          1.1    kardel 		}
    455          1.1    kardel # ifdef DEBUG
    456          1.1    kardel 		if (debug > 1) {
    457          1.1    kardel 			if (ioctl(ctl_fd, SOUND_MIXER_READ_RECSRC, &l) == -1)
    458          1.1    kardel 				printf("SOUND_MIXER_WRITE_RECSRC: %s\n",
    459          1.1    kardel 				       strerror(errno));
    460          1.1    kardel 			else
    461          1.1    kardel 				printf("audio_gain: recsrc is %d\n", l);
    462          1.1    kardel 		}
    463          1.1    kardel # endif
    464          1.1    kardel 		o_port = port;
    465          1.1    kardel 	}
    466          1.1    kardel #else /* not PCM_STYLE_SOUND */
    467  1.5.4.2.2.3       snj 	ioctl(ctl_fd, AUDIO_GETINFO, (char *)&info);
    468          1.1    kardel 	info.record.encoding = AUDIO_ENCODING_ULAW;
    469          1.1    kardel 	info.record.error = 0;
    470          1.1    kardel 	info.record.gain = gain;
    471          1.1    kardel 	if (o_mongain != mongain)
    472          1.1    kardel 		o_mongain = info.monitor_gain = mongain;
    473          1.1    kardel 	if (o_port != port)
    474          1.1    kardel 		o_port = info.record.port = port;
    475  1.5.4.2.2.3       snj 	rval = ioctl(ctl_fd, AUDIO_SETINFO, (char *)&info);
    476          1.1    kardel 	if (rval < 0) {
    477          1.1    kardel 		msyslog(LOG_ERR, "audio_gain: %m");
    478          1.1    kardel 		return (rval);
    479          1.1    kardel 	}
    480          1.1    kardel 	rval = info.record.error;
    481          1.1    kardel #endif /* not PCM_STYLE_SOUND */
    482          1.1    kardel 	return (rval);
    483          1.1    kardel }
    484          1.1    kardel 
    485          1.1    kardel 
    486          1.1    kardel /*
    487          1.1    kardel  * audio_show - display audio parameters
    488          1.1    kardel  *
    489          1.1    kardel  * This code doesn't really do anything, except satisfy curiousity and
    490          1.1    kardel  * verify the ioctl's work.
    491          1.1    kardel  */
    492          1.1    kardel void
    493          1.1    kardel audio_show(void)
    494          1.1    kardel {
    495          1.1    kardel #ifdef PCM_STYLE_SOUND
    496          1.1    kardel 	int recsrc = 0;
    497          1.1    kardel 
    498          1.1    kardel 	printf("audio_show: ctl_fd %d\n", ctl_fd);
    499          1.1    kardel 	if (ioctl(ctl_fd, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
    500          1.1    kardel 	    printf("SOUND_MIXER_READ_RECSRC: %s\n", strerror(errno));
    501          1.1    kardel 
    502          1.1    kardel #else /* not PCM_STYLE_SOUND */
    503          1.1    kardel # ifdef HAVE_SYS_AUDIOIO_H
    504  1.5.4.2.2.3       snj 	ioctl(ctl_fd, AUDIO_GETDEV, &device);
    505          1.1    kardel 	printf("audio: name %s, version %s, config %s\n",
    506          1.1    kardel 	    device.name, device.version, device.config);
    507          1.1    kardel # endif /* HAVE_SYS_AUDIOIO_H */
    508  1.5.4.2.2.3       snj 	ioctl(ctl_fd, AUDIO_GETINFO, (char *)&info);
    509          1.1    kardel 	printf(
    510          1.1    kardel 	    "audio: rate %d, chan %d, prec %d, code %d, gain %d, mon %d, port %d\n",
    511          1.1    kardel 	    info.record.sample_rate, info.record.channels,
    512          1.1    kardel 	    info.record.precision, info.record.encoding,
    513          1.1    kardel 	    info.record.gain, info.monitor_gain, info.record.port);
    514          1.1    kardel 	printf(
    515          1.1    kardel 	    "audio: samples %d, eof %d, pause %d, error %d, waiting %d, balance %d\n",
    516          1.1    kardel 	    info.record.samples, info.record.eof,
    517          1.1    kardel 	    info.record.pause, info.record.error,
    518          1.1    kardel 	    info.record.waiting, info.record.balance);
    519          1.1    kardel #endif /* not PCM_STYLE_SOUND */
    520          1.1    kardel }
    521          1.1    kardel #else
    522          1.1    kardel int audio_bs;
    523          1.1    kardel #endif /* HAVE_{SYS_AUDIOIO,SUN_AUDIOIO,MACHINE_SOUNDCARD,SYS_SOUNDCARD}_H */
    524