audio.c revision 1.13 1 1.13 christos /* $NetBSD: audio.c,v 1.13 2020/05/25 20:47:24 christos 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.12 christos
52 1.12 christos /*
53 1.12 christos * 4.4BSD-Lite switched to an unsigned long ioctl arg. Detect common
54 1.12 christos * derivatives here, and apply that type. To make the following code
55 1.12 christos * less verbose we make a proper typedef.
56 1.12 christos * The joy of IOCTL programming...
57 1.12 christos */
58 1.12 christos # if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__) || defined __OpenBSD__
59 1.12 christos typedef unsigned long ioctl_arg_T;
60 1.12 christos #else
61 1.12 christos typedef int ioctl_arg_T;
62 1.12 christos #endif
63 1.12 christos
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.12 christos static ioctl_arg_T agc = SOUND_MIXER_WRITE_RECLEV; /* or IGAIN or LINE */
74 1.12 christos static ioctl_arg_T audiomonitor = SOUND_MIXER_WRITE_VOLUME; /* or OGAIN */
75 1.12 christos static int devmask = 0;
76 1.12 christos static int recmask = 0;
77 1.12 christos static char cf_c_dev[100], cf_i_dev[100], cf_agc[100], cf_monitor[100];
78 1.12 christos
79 1.12 christos 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.7 christos 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.7 christos const char **c_dev, /* Control device */
134 1.7 christos 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.11 christos 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.12 christos 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.9 christos # ifdef GCC
397 1.9 christos rval = 0; /* GCC thinks rval is used uninitialized */
398 1.9 christos # 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.9 christos rval = ioctl(ctl_fd
414 1.9 christos , (2 == port)
415 1.9 christos ? SOUND_MIXER_WRITE_LINE
416 1.9 christos : SOUND_MIXER_WRITE_MIC
417 1.9 christos , &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.11 christos 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.12 christos 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.12 christos 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.12 christos 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.12 christos 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