parse.c revision 1.2 1 1.2 nia /* $NetBSD: parse.c,v 1.2 2021/05/08 12:53:15 nia Exp $ */
2 1.1 nia /*-
3 1.1 nia * Copyright (c) 2021 The NetBSD Foundation, Inc.
4 1.1 nia * All rights reserved.
5 1.1 nia *
6 1.1 nia * This code is derived from software contributed to The NetBSD Foundation
7 1.1 nia * by Nia Alarie.
8 1.1 nia *
9 1.1 nia * Redistribution and use in source and binary forms, with or without
10 1.1 nia * modification, are permitted provided that the following conditions
11 1.1 nia * are met:
12 1.1 nia * 1. Redistributions of source code must retain the above copyright
13 1.1 nia * notice, this list of conditions and the following disclaimer.
14 1.1 nia * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 nia * notice, this list of conditions and the following disclaimer in the
16 1.1 nia * documentation and/or other materials provided with the distribution.
17 1.1 nia *
18 1.1 nia * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 1.1 nia * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 1.1 nia * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 1.1 nia * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 1.1 nia * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 1.1 nia * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 1.1 nia * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 1.1 nia * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 1.1 nia * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 1.1 nia * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 1.1 nia * POSSIBILITY OF SUCH DAMAGE.
29 1.1 nia */
30 1.1 nia #include <sys/audioio.h>
31 1.1 nia #include <sys/ioctl.h>
32 1.1 nia #include <curses.h>
33 1.1 nia #include <stdlib.h>
34 1.1 nia #include "app.h"
35 1.1 nia #include "parse.h"
36 1.1 nia
37 1.1 nia static struct aiomixer_class *get_class(struct aiomixer *, int);
38 1.1 nia static int compare_control(const void *, const void *);
39 1.1 nia
40 1.1 nia static struct aiomixer_class *
41 1.1 nia get_class(struct aiomixer *aio, int class)
42 1.1 nia {
43 1.1 nia size_t i;
44 1.1 nia
45 1.1 nia for (i = 0; i < aio->numclasses; ++i) {
46 1.1 nia if (aio->classes[i].index == class) {
47 1.1 nia return &aio->classes[i];
48 1.1 nia }
49 1.1 nia }
50 1.1 nia return NULL;
51 1.1 nia }
52 1.1 nia
53 1.1 nia static int
54 1.1 nia compare_control(const void *pa, const void *pb)
55 1.1 nia {
56 1.1 nia const struct aiomixer_control *a = (const struct aiomixer_control *)pa;
57 1.1 nia const struct aiomixer_control *b = (const struct aiomixer_control *)pb;
58 1.1 nia
59 1.2 nia if (a->info.prev != AUDIO_MIXER_LAST ||
60 1.1 nia b->info.prev != AUDIO_MIXER_LAST) {
61 1.1 nia if (b->info.prev == a->info.index)
62 1.1 nia return -1;
63 1.1 nia if (a->info.prev == b->info.index)
64 1.1 nia return 1;
65 1.2 nia } else {
66 1.2 nia return strcmp(a->info.label.name, b->info.label.name);
67 1.1 nia }
68 1.2 nia return 0;
69 1.1 nia }
70 1.1 nia
71 1.1 nia int
72 1.1 nia aiomixer_parse(struct aiomixer *aio)
73 1.1 nia {
74 1.1 nia size_t i;
75 1.1 nia struct mixer_devinfo info;
76 1.1 nia struct aiomixer_class *class;
77 1.1 nia struct aiomixer_control *control;
78 1.1 nia
79 1.1 nia for (info.index = 0;
80 1.1 nia ioctl(aio->fd, AUDIO_MIXER_DEVINFO, &info) != -1; ++info.index) {
81 1.1 nia if (info.type != AUDIO_MIXER_CLASS)
82 1.1 nia continue;
83 1.1 nia if (aio->numclasses >= __arraycount(aio->classes))
84 1.1 nia break;
85 1.1 nia class = &aio->classes[aio->numclasses++];
86 1.1 nia memcpy(class->name, info.label.name, MAX_AUDIO_DEV_LEN);
87 1.1 nia class->index = info.index;
88 1.1 nia class->numcontrols = 0;
89 1.1 nia }
90 1.1 nia for (info.index = 0;
91 1.1 nia ioctl(aio->fd, AUDIO_MIXER_DEVINFO, &info) != -1; ++info.index) {
92 1.1 nia if (info.type == AUDIO_MIXER_CLASS)
93 1.1 nia continue;
94 1.1 nia if (info.type == AUDIO_MIXER_VALUE) {
95 1.1 nia /* XXX workaround for hdaudio(4) bugs */
96 1.1 nia if (info.un.v.delta > AUDIO_MAX_GAIN)
97 1.1 nia continue;
98 1.1 nia if (info.un.v.num_channels == 0)
99 1.1 nia continue;
100 1.1 nia }
101 1.1 nia class = get_class(aio, info.mixer_class);
102 1.1 nia if (class == NULL)
103 1.1 nia break;
104 1.1 nia if (class->numcontrols >= __arraycount(class->controls))
105 1.1 nia break;
106 1.1 nia control = &class->controls[class->numcontrols++];
107 1.1 nia control->info = info;
108 1.1 nia }
109 1.1 nia for (i = 0; i < aio->numclasses; ++i) {
110 1.1 nia class = &aio->classes[i];
111 1.1 nia qsort(class->controls, class->numcontrols,
112 1.1 nia sizeof(struct aiomixer_control),
113 1.1 nia compare_control);
114 1.1 nia }
115 1.1 nia return 0;
116 1.1 nia }
117 1.1 nia
118