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