Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/audiocfg Update respond to isaki-audio2 branch.



details:   https://anonhg.NetBSD.org/src/rev/f9ac97a43f87
branches:  trunk
changeset: 451173:f9ac97a43f87
user:      isaki <isaki%NetBSD.org@localhost>
date:      Wed May 08 14:36:12 2019 +0000

description:
Update respond to isaki-audio2 branch.
- Extend list command to display supported hardware formats.
- Add set command to set hardware format.
- Use correct /dev/audioctl instead of /dev/audio.

diffstat:

 usr.bin/audiocfg/audiocfg.1 |   29 ++++++-
 usr.bin/audiocfg/audiodev.c |  178 ++++++++++++++++++++++++++++++-------------
 usr.bin/audiocfg/audiodev.h |   18 +++-
 usr.bin/audiocfg/main.c     |  144 ++++++++++++++++++++++++++++++++++-
 4 files changed, 304 insertions(+), 65 deletions(-)

diffs (truncated from 591 to 300 lines):

diff -r 475fd2777afb -r f9ac97a43f87 usr.bin/audiocfg/audiocfg.1
--- a/usr.bin/audiocfg/audiocfg.1       Wed May 08 14:25:38 2019 +0000
+++ b/usr.bin/audiocfg/audiocfg.1       Wed May 08 14:36:12 2019 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: audiocfg.1,v 1.3 2010/09/01 09:17:31 wiz Exp $
+.\"    $NetBSD: audiocfg.1,v 1.4 2019/05/08 14:36:12 isaki Exp $
 .\"
 .\" Copyright (c) 2010 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -40,6 +40,14 @@
 .Cm default
 .Ar index
 .Nm
+.Cm set
+.Ar index
+.Ar direction
+.Ar encoding
+.Ar precision
+.Ar channels
+.Ar sample_rate
+.Nm
 .Cm test
 .Ar index
 .Sh DESCRIPTION
@@ -51,6 +59,25 @@
 .Dq Cm list ,
 it lists the available audio devices and shows the currently selected
 default audio device.
+.Pp
+Run with
+.Dq Cm set ,
+if sets the hardware format.
+The
+.Ar direction
+is represented by either of 'p'(playback) or 'r'(record), or both of them,
+indicates direction you want to set to.
+The remaining parameters
+.Ar encoding ,
+.Ar precision ,
+.Ar channels
+and
+.Ar sample_rate
+indicate the hardware format you want to set to.
+These parameters must be selected from the candidates displayed by
+.Nm
+.Cm list .
+.Pp
 Called with
 .Dq Cm test ,
 it plays a tone of 2 seconds for each channel of the device with the index
diff -r 475fd2777afb -r f9ac97a43f87 usr.bin/audiocfg/audiodev.c
--- a/usr.bin/audiocfg/audiodev.c       Wed May 08 14:25:38 2019 +0000
+++ b/usr.bin/audiocfg/audiodev.c       Wed May 08 14:36:12 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: audiodev.c,v 1.6 2016/03/05 22:10:39 mrg Exp $ */
+/* $NetBSD: audiodev.c,v 1.7 2019/05/08 14:36:12 isaki Exp $ */
 
 /*
  * Copyright (c) 2010 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -31,6 +31,7 @@
 #include <sys/stat.h>
 #include <sys/drvctlio.h>
 
+#include <errno.h>
 #include <fcntl.h>
 #include <paths.h>
 #include <stdio.h>
@@ -47,51 +48,23 @@
 
 #define AUDIODEV_SAMPLE_RATE   44100
 
-static unsigned int
-audiodev_probe_pchans(struct audiodev *adev)
-{
-       audio_info_t info;
-       unsigned int nchans = 0, n;
-       int error;
-
-       AUDIO_INITINFO(&info);
-       info.play.sample_rate = AUDIODEV_SAMPLE_RATE;
-       info.play.precision = 16;
-       info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
-       info.play.channels = 1;
-       info.mode = AUMODE_PLAY;
-       error = ioctl(adev->fd, AUDIO_SETINFO, &info);
-       if (error == -1)
-               return 0;
-       nchans = 1;
-
-       for (n = 2; n <= 16; n += 2) {
-               info.play.channels = n;
-               error = ioctl(adev->fd, AUDIO_SETINFO, &info);
-               if (error == -1)
-                       break;
-               nchans = info.play.channels;
-       }
-
-       return nchans;
-}
-
 static int
 audiodev_getinfo(struct audiodev *adev)
 {
        struct stat st;
+       struct audiofmt *f;
+       audio_format_query_t query;
+       int i;
 
-       if (stat(adev->path, &st) == -1)
+       if (stat(adev->ctlpath, &st) == -1)
                return -1;
        adev->dev = st.st_rdev;
 
-       if (stat(_PATH_AUDIO, &st) != -1 && st.st_rdev == adev->dev)
+       if (stat(_PATH_AUDIOCTL, &st) != -1 && st.st_rdev == adev->dev)
                adev->defaultdev = true;
 
-       adev->fd = open(adev->path, O_RDWR);
+       adev->fd = open(adev->ctlpath, O_RDONLY);
        if (adev->fd == -1) {
-               adev->fd = open(adev->path, O_WRONLY);
-               if (adev->fd == -1)
                        return -1;
        }
        if (ioctl(adev->fd, AUDIO_GETDEV, &adev->audio_device) == -1) {
@@ -99,7 +72,29 @@
                return -1;
        }
 
-       adev->pchan = audiodev_probe_pchans(adev);
+       for (i = 0; ;i++) {
+               memset(&query, 0, sizeof(query));
+               query.index = i;
+               if (ioctl(adev->fd, AUDIO_QUERYFORMAT, &query) == -1) {
+                       if (errno == ENODEV) {
+                               /* QUERYFORMAT not supported. */
+                               break;
+                       }
+                       if (errno == EINVAL)
+                               break;
+                       close(adev->fd);
+                       return -1;
+               }
+
+               f = calloc(1, sizeof(*f));
+               f->fmt = query.fmt;
+               TAILQ_INSERT_TAIL(&adev->formats, f, next);
+       }
+
+       if (ioctl(adev->fd, AUDIO_GETFORMAT, &adev->info) == -1) {
+               close(adev->fd);
+               return -1;
+       }
 
        return 0;
 }
@@ -115,8 +110,10 @@
 
        strlcpy(adev->pxname, pdev, sizeof(adev->pxname));
        strlcpy(adev->xname, dev, sizeof(adev->xname));
-       snprintf(adev->path, sizeof(adev->path) - 1, "/dev/%s", dev);
+       snprintf(adev->path, sizeof(adev->path), "/dev/%s", dev);
+       snprintf(adev->ctlpath, sizeof(adev->ctlpath), "/dev/audioctl%d", unit);
        adev->unit = unit;
+       TAILQ_INIT(&adev->formats);
 
        if (audiodev_getinfo(adev) == -1) {
                free(adev);
@@ -124,8 +121,16 @@
        }
 
 #ifdef DEBUG
-       printf("[%c] %s: %s\n", adev->defaultdev ? '*' : ' ',
-           adev->path, adev->audio_device.name);
+       printf("DEBUG: [%c] %s(%s): %s\n", adev->defaultdev ? '*' : ' ',
+           adev->path, adev->ctlpath, adev->audio_device.name);
+       struct audiofmt *f;
+       TAILQ_FOREACH(f, &adev->formats, next) {
+               printf("DEBUG: enc%d, %d/%d, %dch\n",
+                   f->fmt.encoding,
+                   f->fmt.validbits,
+                   f->fmt.precision,
+                   f->fmt.channels);
+       }
 #endif
 
        TAILQ_INSERT_TAIL(&audiodevlist, adev, next);
@@ -207,13 +212,13 @@
        char audioctlpath[PATH_MAX+1];
        char mixerpath[PATH_MAX+1];
 
-       snprintf(audiopath, sizeof(audiopath) - 1,
+       snprintf(audiopath, sizeof(audiopath),
            _PATH_AUDIO "%u", adev->unit);
-       snprintf(soundpath, sizeof(soundpath) - 1,
+       snprintf(soundpath, sizeof(soundpath),
            _PATH_SOUND "%u", adev->unit);
-       snprintf(audioctlpath, sizeof(audioctlpath) - 1,
+       snprintf(audioctlpath, sizeof(audioctlpath),
            _PATH_AUDIOCTL "%u", adev->unit);
-       snprintf(mixerpath, sizeof(mixerpath) - 1,
+       snprintf(mixerpath, sizeof(mixerpath),
            _PATH_MIXER "%u", adev->unit);
 
        unlink(_PATH_AUDIO);
@@ -242,33 +247,92 @@
 }
 
 int
+audiodev_set_param(struct audiodev *adev, int mode,
+       const char *encname, unsigned int prec, unsigned int ch, unsigned int freq)
+{
+       struct audio_info ai;
+       int setmode;
+       u_int enc;
+
+       setmode = 0;
+       ai = adev->info;
+
+       for (enc = 0; enc < encoding_max; enc++) {
+               if (strcmp(encname, encoding_names[enc]) == 0)
+                       break;
+       }
+       if (enc >= encoding_max) {
+               fprintf(stderr, "unknown encoding name: %s\n", encname);
+               errno = EINVAL;
+               return -1;
+       }
+
+       if ((ai.mode & mode & AUMODE_PLAY)) {
+               setmode |= AUMODE_PLAY;
+               ai.play.encoding = enc;
+               ai.play.precision = prec;
+               ai.play.channels = ch;
+               ai.play.sample_rate = freq;
+       }
+       if ((ai.mode & mode & AUMODE_RECORD)) {
+               setmode |= AUMODE_RECORD;
+               ai.record.encoding = enc;
+               ai.record.precision = prec;
+               ai.record.channels = ch;
+               ai.record.sample_rate = freq;
+       }
+
+       if (setmode == 0) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       ai.mode = setmode;
+       printf("setting %s to %s:%u, %uch, %uHz\n",
+           adev->xname, encname, prec, ch, freq);
+       if (ioctl(adev->fd, AUDIO_SETFORMAT, &ai) == -1) {
+               perror("ioctl AUDIO_SETFORMAT");
+               return -1;
+       }
+       return 0;
+}
+
+int
 audiodev_test(struct audiodev *adev, unsigned int chanmask)
 {
        audio_info_t info;
        int16_t *buf;
        size_t buflen;
        off_t off;
-       int rv = 0;
+       int fd;
+       int rv = -1;
+
+       fd = open(adev->path, O_WRONLY);
+       if (fd == -1) {
+               perror("open");
+               return -1;
+       }
 
        AUDIO_INITINFO(&info);
        info.play.sample_rate = AUDIODEV_SAMPLE_RATE;
-       info.play.channels = adev->pchan;
+       info.play.channels = adev->info.play.channels;
        info.play.precision = 16;
        info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
        info.mode = AUMODE_PLAY;
-       if (ioctl(adev->fd, AUDIO_SETINFO, &info) == -1) {
+       if (ioctl(fd, AUDIO_SETINFO, &info) == -1) {
                perror("ioctl AUDIO_SETINFO");
-               return -1;
+               goto abort;
        }
-       if (ioctl(adev->fd, AUDIO_GETINFO, &info) == -1) {
+       if (ioctl(fd, AUDIO_GETINFO, &info) == -1) {
                perror("ioctl AUDIO_GETINFO");
-               return -1;
+               goto abort;
        }
 
        dtmf_new(&buf, &buflen, info.play.sample_rate, 2,
-           adev->pchan, chanmask, 350.0, 440.0);
-       if (buf == NULL)
-               return -1;



Home | Main Index | Thread Index | Old Index