1 /* $NetBSD: main.c,v 1.17 2023/04/01 12:41:02 mlelstv Exp $ */
2 
3 /*
4  * Copyright (c) 2010 Jared D. McNeill <jmcneill@invisible.ca>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <assert.h>
30 #include <err.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <limits.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 
38 #include "audiodev.h"
39 #include "drvctl.h"
40 
41 __dead static void
usage(void)42 usage(void)
43 {
44           const char *p = getprogname();
45 
46           fprintf(stderr, "usage: %s list [<index>]\n", p);
47           fprintf(stderr, "       %s default <index>\n", p);
48           fprintf(stderr, "       %s set  <index> [p|r] <enc> <prec> <ch> <freq>\n",
49               p);
50           fprintf(stderr, "       %s test <index>\n", p);
51           exit(EXIT_FAILURE);
52 }
53 
54 const char *encoding_names[] = {
55           "none",
56           AudioEmulaw,
57           AudioEalaw,
58           "pcm16",
59           "pcm8",
60           AudioEadpcm,
61           AudioEslinear_le,
62           AudioEslinear_be,
63           AudioEulinear_le,
64           AudioEulinear_be,
65           AudioEslinear,
66           AudioEulinear,
67           AudioEmpeg_l1_stream,
68           AudioEmpeg_l1_packets,
69           AudioEmpeg_l1_system,
70           AudioEmpeg_l2_stream,
71           AudioEmpeg_l2_packets,
72           AudioEmpeg_l2_system,
73           AudioEac3,
74 };
75 u_int encoding_max = __arraycount(encoding_names);
76 
77 static void
print_audiodev(struct audiodev * adev,int i)78 print_audiodev(struct audiodev *adev, int i)
79 {
80           struct audiofmt *f;
81           int j;
82 
83           assert(adev != NULL);
84 
85           printf("%u: [%c] %s @ %s: ",
86               i, adev->defaultdev ? '*' : ' ',
87               adev->xname, adev->pxname);
88           printf("%s", adev->audio_device.name);
89           if (strlen(adev->audio_device.version) > 0)
90                     printf(" %s", adev->audio_device.version);
91           printf("\n");
92           printf("       playback: ");
93           if ((adev->hwinfo.mode & AUMODE_PLAY)) {
94                     printf("%u, %uch, %uHz\n",
95                         adev->hwinfo.play.precision,
96                         adev->hwinfo.play.channels,
97                         adev->hwinfo.play.sample_rate);
98           } else {
99                     printf("unavailable\n");
100           }
101           printf("       record:   ");
102           if ((adev->hwinfo.mode & AUMODE_RECORD)) {
103                     printf("%u, %uch, %uHz\n",
104                         adev->hwinfo.record.precision,
105                         adev->hwinfo.record.channels,
106                         adev->hwinfo.record.sample_rate);
107           } else {
108                     printf("unavailable\n");
109           }
110 
111           TAILQ_FOREACH(f, &adev->formats, next) {
112                     printf("       ");
113                     if (f->fmt.priority < 0)
114                               printf("(  ) ");
115                     else if ((f->fmt.mode & (AUMODE_PLAY | AUMODE_RECORD))
116                         == (AUMODE_PLAY | AUMODE_RECORD))
117                               printf("(PR) ");
118                     else if ((f->fmt.mode & AUMODE_PLAY))
119                               printf("(P-) ");
120                     else if ((f->fmt.mode & AUMODE_RECORD))
121                               printf("(-R) ");
122 
123                     if (f->fmt.encoding < encoding_max)
124                               printf("%s", encoding_names[f->fmt.encoding]);
125                     else
126                               printf("unknown_encoding_%d", f->fmt.encoding);
127                     printf(" %d/%d, %dch, ",
128                         f->fmt.validbits,
129                         f->fmt.precision,
130                         f->fmt.channels);
131                     if (f->fmt.frequency_type == 0) {
132                               printf("%d-%dHz",
133                                   f->fmt.frequency[0],
134                                   f->fmt.frequency[1]);
135                     } else {
136                               for (j = 0; j < (int)f->fmt.frequency_type; j++) {
137                                         printf("%s%d",
138                                             (j == 0) ? "{ " : ", ",
139                                             f->fmt.frequency[j]);
140                               }
141                               printf(" }");
142                     }
143                     printf("\n");
144           }
145 }
146 
147 int
main(int argc,char * argv[])148 main(int argc, char *argv[])
149 {
150           struct audiodev *adev;
151           unsigned int n, i;
152           unsigned int j;
153           const char *enc;
154           unsigned int prec;
155           unsigned int ch;
156           unsigned int freq;
157           int mode;
158 
159           if (audiodev_refresh() == -1)
160                     return EXIT_FAILURE;
161 
162           if (argc < 2)
163                     usage();
164                     /* NOTREACHED */
165 
166           if (strcmp(argv[1], "list") == 0 && argc == 2) {
167                     n = audiodev_count();
168                     for (i = 0; i < n; i++)
169                               print_audiodev(audiodev_get(i), i);
170           } else if (strcmp(argv[1], "list") == 0 && argc == 3) {
171                     if (*argv[2] < '0' || *argv[2] > '9')
172                               usage();
173                               /* NOTREACHED */
174                     errno = 0;
175                     i = strtoul(argv[2], NULL, 10);
176                     if (errno)
177                               usage();
178                               /* NOTREACHED */
179                     adev = audiodev_get(i);
180                     if (adev == NULL) {
181                               errx(EXIT_FAILURE, "no such device");
182                     }
183                     print_audiodev(adev, i);
184           } else if (strcmp(argv[1], "default") == 0 && argc == 3) {
185                     if (*argv[2] < '0' || *argv[2] > '9')
186                               usage();
187                               /* NOTREACHED */
188                     errno = 0;
189                     i = strtoul(argv[2], NULL, 10);
190                     if (errno)
191                               usage();
192                               /* NOTREACHED */
193                     adev = audiodev_get(i);
194                     if (adev == NULL) {
195                               errx(EXIT_FAILURE, "no such device");
196                     }
197                     printf("setting default audio device to %s\n", adev->xname);
198                     if (audiodev_set_default(adev) == -1) {
199                               errx(EXIT_FAILURE, "couldn't set default device");
200                     }
201           } else if (strcmp(argv[1], "set") == 0 && argc == 8) {
202                     /* XXX bad commandline... */
203                     /* audiocfg set <index> [p|r] <enc> <prec> <ch> <freq> */
204                     if (*argv[2] < '0' || *argv[2] > '9')
205                               usage();
206                               /* NOTREACHED */
207                     errno = 0;
208                     i = strtoul(argv[2], NULL, 10);
209                     if (errno)
210                               usage();
211                               /* NOTREACHED */
212                     adev = audiodev_get(i);
213                     if (adev == NULL) {
214                               errx(EXIT_FAILURE, "no such device");
215                     }
216 
217                     mode = 0;
218                     for (j = 0; j < strlen(argv[3]); j++) {
219                               if (argv[3][j] == 'p')
220                                         mode |= AUMODE_PLAY;
221                               else if (argv[3][j] == 'r')
222                                         mode |= AUMODE_RECORD;
223                               else
224                                         usage();
225                     }
226                     if (mode == 0)
227                               usage();
228                               /* NOTREACHED */
229                     enc = argv[4];
230                     prec = strtoul(argv[5], NULL, 10);
231                     if (errno)
232                               usage();
233                     errno = 0;
234                     ch = strtoul(argv[6], NULL, 10);
235                     if (errno)
236                               usage();
237                               /* NOTREACHED */
238                     errno = 0;
239                     freq = strtoul(argv[7], NULL, 10);
240                     if (errno)
241                               usage();
242                               /* NOTREACHED */
243 
244                     if (audiodev_set_param(adev, mode, enc, prec, ch, freq) == -1) {
245                               errx(EXIT_FAILURE, "couldn't set parameter");
246                     }
247           } else if (strcmp(argv[1], "test") == 0 && argc == 3) {
248                     if (*argv[2] < '0' || *argv[2] > '9')
249                               usage();
250                               /* NOTREACHED */
251                     errno = 0;
252                     i = strtoul(argv[2], NULL, 10);
253                     if (errno)
254                               usage();
255                               /* NOTREACHED */
256                     adev = audiodev_get(i);
257                     if (adev == NULL) {
258                               errx(EXIT_FAILURE, "no such device");
259                     }
260                     print_audiodev(adev, i);
261                     if (audiodev_test(adev) == -1)
262                               return EXIT_FAILURE;
263           } else
264                     usage();
265                     /* NOTREACHED */
266 
267           return EXIT_SUCCESS;
268 }
269