1 1.13 christos /* $NetBSD: audio.c,v 1.14 2024/08/18 20:47:13 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.14 christos NONEMPTY_TRANSLATION_UNIT 523 1.1 kardel #endif /* HAVE_{SYS_AUDIOIO,SUN_AUDIOIO,MACHINE_SOUNDCARD,SYS_SOUNDCARD}_H */ 524