1 /* Copyright 2016 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6 #include <stdlib.h>
7 #include <string.h>
8 #include <syslog.h>
9
10 #include "cras_alsa_mixer_name.h"
11 #include "utlist.h"
12
mixer_name_add(struct mixer_name * names,const char * name,enum CRAS_STREAM_DIRECTION dir,mixer_name_type type)13 struct mixer_name *mixer_name_add(struct mixer_name *names, const char *name,
14 enum CRAS_STREAM_DIRECTION dir,
15 mixer_name_type type)
16 {
17 struct mixer_name *m_name;
18
19 if (!name)
20 return names;
21
22 m_name = (struct mixer_name *)calloc(1, sizeof(struct mixer_name));
23 if (!m_name)
24 return names;
25
26 m_name->name = strdup(name);
27 if (!m_name->name) {
28 free(m_name);
29 return names;
30 }
31 m_name->dir = dir;
32 m_name->type = type;
33
34 DL_APPEND(names, m_name);
35 return names;
36 }
37
mixer_name_add_array(struct mixer_name * names,const char * const * name_array,size_t name_array_size,enum CRAS_STREAM_DIRECTION dir,mixer_name_type type)38 struct mixer_name *mixer_name_add_array(struct mixer_name *names,
39 const char *const *name_array,
40 size_t name_array_size,
41 enum CRAS_STREAM_DIRECTION dir,
42 mixer_name_type type)
43 {
44 size_t i;
45 for (i = 0; i < name_array_size; i++)
46 names = mixer_name_add(names, name_array[i], dir, type);
47 return names;
48 }
49
mixer_name_free(struct mixer_name * names)50 void mixer_name_free(struct mixer_name *names)
51 {
52 struct mixer_name *m_name;
53 DL_FOREACH (names, m_name) {
54 DL_DELETE(names, m_name);
55 free((void *)m_name->name);
56 free(m_name);
57 }
58 }
59
mixer_name_find(struct mixer_name * names,const char * name,enum CRAS_STREAM_DIRECTION dir,mixer_name_type type)60 struct mixer_name *mixer_name_find(struct mixer_name *names, const char *name,
61 enum CRAS_STREAM_DIRECTION dir,
62 mixer_name_type type)
63 {
64 if (!name && type == MIXER_NAME_UNDEFINED)
65 return NULL;
66
67 struct mixer_name *m_name;
68 DL_FOREACH (names, m_name) {
69 /* Match the direction. */
70 if (dir != m_name->dir)
71 continue;
72 /* Match the type unless the type is UNDEFINED. */
73 if (type != MIXER_NAME_UNDEFINED && type != m_name->type)
74 continue;
75 /* Match the name if it is non-NULL, or return the first
76 * item with the correct type when the name is not defined. */
77 if ((type != MIXER_NAME_UNDEFINED && !name) ||
78 (name && !strcmp(m_name->name, name)))
79 return m_name;
80 }
81 return NULL;
82 }
83
mixer_name_type_str(enum CRAS_STREAM_DIRECTION dir,mixer_name_type type)84 static const char *mixer_name_type_str(enum CRAS_STREAM_DIRECTION dir,
85 mixer_name_type type)
86 {
87 switch (dir) {
88 case CRAS_STREAM_OUTPUT:
89 switch (type) {
90 case MIXER_NAME_VOLUME:
91 return "output volume";
92 case MIXER_NAME_MAIN_VOLUME:
93 return "main volume";
94 case MIXER_NAME_UNDEFINED:
95 break;
96 }
97 break;
98 case CRAS_STREAM_INPUT:
99 switch (type) {
100 case MIXER_NAME_VOLUME:
101 return "input volume";
102 case MIXER_NAME_MAIN_VOLUME:
103 return "main capture";
104 case MIXER_NAME_UNDEFINED:
105 break;
106 }
107 break;
108 case CRAS_STREAM_UNDEFINED:
109 case CRAS_STREAM_POST_MIX_PRE_DSP:
110 case CRAS_NUM_DIRECTIONS:
111 break;
112 }
113 return "undefined";
114 }
115
mixer_name_dump(struct mixer_name * names,const char * message)116 void mixer_name_dump(struct mixer_name *names, const char *message)
117 {
118 struct mixer_name *m_name;
119
120 if (!names) {
121 syslog(LOG_DEBUG, "%s: empty", message);
122 return;
123 }
124
125 syslog(LOG_DEBUG, "%s:", message);
126 DL_FOREACH (names, m_name) {
127 const char *type_str =
128 mixer_name_type_str(m_name->dir, m_name->type);
129 syslog(LOG_DEBUG, " %s %s", m_name->name, type_str);
130 }
131 }
132