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