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