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 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 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 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 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 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 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