1 // Copyright (c) 2012 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 #include <stdio.h> 6 #include <gtest/gtest.h> 7 #include <map> 8 #include <string> 9 #include <syslog.h> 10 #include <vector> 11 12 extern "C" { 13 #include "cras_alsa_mixer.h" 14 #include "cras_alsa_mixer_name.h" 15 #include "cras_types.h" 16 #include "cras_util.h" 17 #include "cras_volume_curve.h" 18 #include "utlist.h" 19 20 // Include C file to test static functions and use the definition of some 21 // structure. 22 #include "cras_alsa_mixer.c" 23 } 24 25 namespace { 26 27 static size_t snd_mixer_open_called; 28 static int snd_mixer_open_return_value; 29 static size_t snd_mixer_close_called; 30 static size_t snd_mixer_attach_called; 31 static int snd_mixer_attach_return_value; 32 const char *snd_mixer_attach_mixdev; 33 static size_t snd_mixer_selem_register_called; 34 static int snd_mixer_selem_register_return_value; 35 static size_t snd_mixer_load_called; 36 static int snd_mixer_load_return_value; 37 static size_t snd_mixer_first_elem_called; 38 static snd_mixer_elem_t *snd_mixer_first_elem_return_value; 39 static int snd_mixer_elem_next_called; 40 static snd_mixer_elem_t **snd_mixer_elem_next_return_values; 41 static int snd_mixer_elem_next_return_values_index; 42 static int snd_mixer_elem_next_return_values_length; 43 static int snd_mixer_selem_set_playback_dB_all_called; 44 static long *snd_mixer_selem_set_playback_dB_all_values; 45 static int snd_mixer_selem_set_playback_dB_all_values_length; 46 static int snd_mixer_selem_set_playback_switch_all_called; 47 static int snd_mixer_selem_set_playback_switch_all_value; 48 static int snd_mixer_selem_has_playback_volume_called; 49 static int *snd_mixer_selem_has_playback_volume_return_values; 50 static int snd_mixer_selem_has_playback_volume_return_values_length; 51 static int snd_mixer_selem_has_playback_switch_called; 52 static int *snd_mixer_selem_has_playback_switch_return_values; 53 static int snd_mixer_selem_has_playback_switch_return_values_length; 54 static int snd_mixer_selem_set_capture_dB_all_called; 55 static long *snd_mixer_selem_set_capture_dB_all_values; 56 static int snd_mixer_selem_set_capture_dB_all_values_length; 57 static int snd_mixer_selem_set_capture_switch_all_called; 58 static int snd_mixer_selem_set_capture_switch_all_value; 59 static int snd_mixer_selem_has_capture_volume_called; 60 static int *snd_mixer_selem_has_capture_volume_return_values; 61 static int snd_mixer_selem_has_capture_volume_return_values_length; 62 static int snd_mixer_selem_has_capture_switch_called; 63 static int *snd_mixer_selem_has_capture_switch_return_values; 64 static int snd_mixer_selem_has_capture_switch_return_values_length; 65 static int snd_mixer_selem_get_name_called; 66 static const char **snd_mixer_selem_get_name_return_values; 67 static int snd_mixer_selem_get_name_return_values_length; 68 static int snd_mixer_selem_get_playback_dB_called; 69 static long *snd_mixer_selem_get_playback_dB_return_values; 70 static int snd_mixer_selem_get_playback_dB_return_values_length; 71 static int snd_mixer_selem_get_capture_dB_called; 72 static long *snd_mixer_selem_get_capture_dB_return_values; 73 static int snd_mixer_selem_get_capture_dB_return_values_length; 74 static size_t cras_volume_curve_destroy_called; 75 static size_t snd_mixer_selem_get_playback_dB_range_called; 76 static size_t snd_mixer_selem_get_playback_dB_range_values_length; 77 static const long *snd_mixer_selem_get_playback_dB_range_min_values; 78 static const long *snd_mixer_selem_get_playback_dB_range_max_values; 79 static size_t snd_mixer_selem_get_capture_dB_range_called; 80 static size_t snd_mixer_selem_get_capture_dB_range_values_length; 81 static const long *snd_mixer_selem_get_capture_dB_range_min_values; 82 static const long *snd_mixer_selem_get_capture_dB_range_max_values; 83 static size_t iniparser_getstring_return_index; 84 static size_t iniparser_getstring_return_length; 85 static char **iniparser_getstring_returns; 86 static size_t snd_mixer_find_selem_called; 87 static std::map<std::string, snd_mixer_elem_t*> snd_mixer_find_elem_map; 88 static std::string snd_mixer_find_elem_id_name; 89 90 static void ResetStubData() { 91 iniparser_getstring_return_index = 0; 92 iniparser_getstring_return_length = 0; 93 snd_mixer_open_called = 0; 94 snd_mixer_open_return_value = 0; 95 snd_mixer_close_called = 0; 96 snd_mixer_attach_called = 0; 97 snd_mixer_attach_return_value = 0; 98 snd_mixer_attach_mixdev = static_cast<const char *>(NULL); 99 snd_mixer_selem_register_called = 0; 100 snd_mixer_selem_register_return_value = 0; 101 snd_mixer_load_called = 0; 102 snd_mixer_load_return_value = 0; 103 snd_mixer_first_elem_called = 0; 104 snd_mixer_first_elem_return_value = static_cast<snd_mixer_elem_t *>(NULL); 105 snd_mixer_elem_next_called = 0; 106 snd_mixer_elem_next_return_values = static_cast<snd_mixer_elem_t **>(NULL); 107 snd_mixer_elem_next_return_values_index = 0; 108 snd_mixer_elem_next_return_values_length = 0; 109 snd_mixer_selem_set_playback_dB_all_called = 0; 110 snd_mixer_selem_set_playback_dB_all_values = static_cast<long *>(NULL); 111 snd_mixer_selem_set_playback_dB_all_values_length = 0; 112 snd_mixer_selem_set_playback_switch_all_called = 0; 113 snd_mixer_selem_has_playback_volume_called = 0; 114 snd_mixer_selem_has_playback_volume_return_values = static_cast<int *>(NULL); 115 snd_mixer_selem_has_playback_volume_return_values_length = 0; 116 snd_mixer_selem_has_playback_switch_called = 0; 117 snd_mixer_selem_has_playback_switch_return_values = static_cast<int *>(NULL); 118 snd_mixer_selem_has_playback_switch_return_values_length = 0; 119 snd_mixer_selem_set_capture_dB_all_called = 0; 120 snd_mixer_selem_set_capture_dB_all_values = static_cast<long *>(NULL); 121 snd_mixer_selem_set_capture_dB_all_values_length = 0; 122 snd_mixer_selem_set_capture_switch_all_called = 0; 123 snd_mixer_selem_has_capture_volume_called = 0; 124 snd_mixer_selem_has_capture_volume_return_values = static_cast<int *>(NULL); 125 snd_mixer_selem_has_capture_volume_return_values_length = 0; 126 snd_mixer_selem_has_capture_switch_called = 0; 127 snd_mixer_selem_has_capture_switch_return_values = static_cast<int *>(NULL); 128 snd_mixer_selem_has_capture_switch_return_values_length = 0; 129 snd_mixer_selem_get_name_called = 0; 130 snd_mixer_selem_get_name_return_values = static_cast<const char **>(NULL); 131 snd_mixer_selem_get_name_return_values_length = 0; 132 snd_mixer_selem_get_playback_dB_called = 0; 133 snd_mixer_selem_get_playback_dB_return_values = static_cast<long *>(NULL); 134 snd_mixer_selem_get_playback_dB_return_values_length = 0; 135 snd_mixer_selem_get_capture_dB_called = 0; 136 snd_mixer_selem_get_capture_dB_return_values = static_cast<long *>(NULL); 137 snd_mixer_selem_get_capture_dB_return_values_length = 0; 138 cras_volume_curve_destroy_called = 0; 139 snd_mixer_selem_get_playback_dB_range_called = 0; 140 snd_mixer_selem_get_playback_dB_range_values_length = 0; 141 snd_mixer_selem_get_playback_dB_range_min_values = static_cast<long *>(NULL); 142 snd_mixer_selem_get_playback_dB_range_max_values = static_cast<long *>(NULL); 143 snd_mixer_selem_get_capture_dB_range_called = 0; 144 snd_mixer_selem_get_capture_dB_range_values_length = 0; 145 snd_mixer_selem_get_capture_dB_range_min_values = static_cast<long *>(NULL); 146 snd_mixer_selem_get_capture_dB_range_max_values = static_cast<long *>(NULL); 147 snd_mixer_find_selem_called = 0; 148 snd_mixer_find_elem_map.clear(); 149 snd_mixer_find_elem_id_name.clear(); 150 } 151 152 struct cras_alsa_mixer *create_mixer_and_add_controls_by_name_matching( 153 const char *card_name, 154 struct mixer_name *extra_controls, 155 struct mixer_name *coupled_controls) { 156 struct cras_alsa_mixer *cmix = cras_alsa_mixer_create(card_name); 157 cras_alsa_mixer_add_controls_by_name_matching( 158 cmix, extra_controls, coupled_controls); 159 return cmix; 160 } 161 162 TEST(AlsaMixer, CreateFailOpen) { 163 struct cras_alsa_mixer *c; 164 165 ResetStubData(); 166 snd_mixer_open_return_value = -1; 167 c = cras_alsa_mixer_create("hw:0"); 168 EXPECT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 169 EXPECT_EQ(1, snd_mixer_open_called); 170 } 171 172 TEST(AlsaMixer, CreateFailAttach) { 173 struct cras_alsa_mixer *c; 174 175 ResetStubData(); 176 snd_mixer_attach_return_value = -1; 177 c = cras_alsa_mixer_create("hw:0"); 178 EXPECT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 179 EXPECT_EQ(1, snd_mixer_open_called); 180 EXPECT_EQ(1, snd_mixer_attach_called); 181 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 182 EXPECT_EQ(1, snd_mixer_close_called); 183 } 184 185 TEST(AlsaMixer, CreateFailSelemRegister) { 186 struct cras_alsa_mixer *c; 187 188 ResetStubData(); 189 snd_mixer_selem_register_return_value = -1; 190 c = cras_alsa_mixer_create("hw:0"); 191 EXPECT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 192 EXPECT_EQ(1, snd_mixer_open_called); 193 EXPECT_EQ(1, snd_mixer_attach_called); 194 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 195 EXPECT_EQ(1, snd_mixer_selem_register_called); 196 EXPECT_EQ(1, snd_mixer_close_called); 197 } 198 199 TEST(AlsaMixer, CreateFailLoad) { 200 struct cras_alsa_mixer *c; 201 202 ResetStubData(); 203 snd_mixer_load_return_value = -1; 204 c = cras_alsa_mixer_create("hw:0"); 205 EXPECT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 206 EXPECT_EQ(1, snd_mixer_open_called); 207 EXPECT_EQ(1, snd_mixer_attach_called); 208 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 209 EXPECT_EQ(1, snd_mixer_selem_register_called); 210 EXPECT_EQ(1, snd_mixer_load_called); 211 EXPECT_EQ(1, snd_mixer_close_called); 212 } 213 214 TEST(AlsaMixer, CreateNoElements) { 215 struct cras_alsa_mixer *c; 216 217 ResetStubData(); 218 c = create_mixer_and_add_controls_by_name_matching( 219 "hw:0", NULL, NULL); 220 ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 221 EXPECT_EQ(1, snd_mixer_open_called); 222 EXPECT_EQ(1, snd_mixer_attach_called); 223 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 224 EXPECT_EQ(1, snd_mixer_selem_register_called); 225 EXPECT_EQ(1, snd_mixer_load_called); 226 EXPECT_EQ(0, snd_mixer_close_called); 227 228 /* set mute shouldn't call anything. */ 229 cras_alsa_mixer_set_mute(c, 0, NULL); 230 EXPECT_EQ(0, snd_mixer_selem_set_playback_switch_all_called); 231 /* set volume shouldn't call anything. */ 232 cras_alsa_mixer_set_dBFS(c, 0, NULL); 233 EXPECT_EQ(0, snd_mixer_selem_set_playback_dB_all_called); 234 235 cras_alsa_mixer_destroy(c); 236 EXPECT_EQ(1, snd_mixer_close_called); 237 } 238 239 TEST(AlsaMixer, CreateOneUnknownElementWithoutVolume) { 240 struct cras_alsa_mixer *c; 241 int element_playback_volume[] = { 242 0, 243 }; 244 int element_playback_switches[] = { 245 1, 246 }; 247 const char *element_names[] = { 248 "Unknown", 249 }; 250 struct mixer_control *mixer_output; 251 int rc; 252 253 ResetStubData(); 254 snd_mixer_first_elem_return_value = reinterpret_cast<snd_mixer_elem_t *>(1); 255 snd_mixer_selem_has_playback_volume_return_values = element_playback_volume; 256 snd_mixer_selem_has_playback_volume_return_values_length = 257 ARRAY_SIZE(element_playback_volume); 258 snd_mixer_selem_get_name_return_values = element_names; 259 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 260 c = create_mixer_and_add_controls_by_name_matching( 261 "hw:0", NULL, NULL); 262 ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 263 EXPECT_EQ(1, snd_mixer_open_called); 264 EXPECT_EQ(1, snd_mixer_attach_called); 265 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 266 EXPECT_EQ(1, snd_mixer_selem_register_called); 267 EXPECT_EQ(1, snd_mixer_load_called); 268 EXPECT_EQ(0, snd_mixer_close_called); 269 EXPECT_EQ(1, snd_mixer_selem_has_playback_volume_called); 270 EXPECT_EQ(1, snd_mixer_selem_get_name_called); 271 EXPECT_EQ(0, snd_mixer_selem_get_playback_dB_range_called); 272 273 /* set mute shouldn't call anything. */ 274 cras_alsa_mixer_set_mute(c, 0, NULL); 275 EXPECT_EQ(0, snd_mixer_selem_set_playback_switch_all_called); 276 277 ResetStubData(); 278 snd_mixer_selem_has_playback_switch_return_values = element_playback_switches; 279 snd_mixer_selem_has_playback_switch_return_values_length = 280 ARRAY_SIZE(element_playback_switches); 281 snd_mixer_selem_get_name_return_values = element_names; 282 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 283 rc = mixer_control_create(&mixer_output, NULL, 284 reinterpret_cast<snd_mixer_elem_t *>(1), 285 CRAS_STREAM_OUTPUT); 286 EXPECT_EQ(0, rc); 287 EXPECT_EQ(1, snd_mixer_selem_get_name_called); 288 EXPECT_EQ(1, snd_mixer_selem_has_playback_volume_called); 289 EXPECT_EQ(1, snd_mixer_selem_has_playback_switch_called); 290 EXPECT_EQ(1, snd_mixer_selem_get_playback_dB_range_called); 291 292 /* if passed a mixer output then it should mute that. */ 293 cras_alsa_mixer_set_mute(c, 0, mixer_output); 294 EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_called); 295 /* set volume shouldn't call anything. */ 296 cras_alsa_mixer_set_dBFS(c, 0, NULL); 297 EXPECT_EQ(0, snd_mixer_selem_set_playback_dB_all_called); 298 299 cras_alsa_mixer_destroy(c); 300 EXPECT_EQ(1, snd_mixer_close_called); 301 mixer_control_destroy(mixer_output); 302 } 303 304 TEST(AlsaMixer, CreateOneUnknownElementWithVolume) { 305 struct cras_alsa_mixer *c; 306 static const long min_volumes[] = {-500}; 307 static const long max_volumes[] = {40}; 308 int element_playback_volume[] = { 309 1, 310 0, 311 }; 312 int element_playback_switches[] = { 313 0, 314 1, 315 }; 316 const char *element_names[] = { 317 "Unknown", 318 "Playback", 319 }; 320 struct mixer_control *mixer_output; 321 int rc; 322 323 ResetStubData(); 324 snd_mixer_first_elem_return_value = reinterpret_cast<snd_mixer_elem_t *>(1); 325 snd_mixer_selem_has_playback_volume_return_values = element_playback_volume; 326 snd_mixer_selem_has_playback_volume_return_values_length = 327 ARRAY_SIZE(element_playback_volume); 328 snd_mixer_selem_get_name_return_values = element_names; 329 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 330 snd_mixer_selem_get_playback_dB_range_min_values = min_volumes; 331 snd_mixer_selem_get_playback_dB_range_max_values = max_volumes; 332 snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes); 333 c = create_mixer_and_add_controls_by_name_matching( 334 "hw:0", NULL, NULL); 335 ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 336 EXPECT_EQ(1, snd_mixer_open_called); 337 EXPECT_EQ(1, snd_mixer_attach_called); 338 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 339 EXPECT_EQ(1, snd_mixer_selem_register_called); 340 EXPECT_EQ(1, snd_mixer_load_called); 341 EXPECT_EQ(0, snd_mixer_close_called); 342 EXPECT_EQ(3, snd_mixer_selem_has_playback_volume_called); 343 EXPECT_EQ(2, snd_mixer_selem_get_playback_dB_range_called); 344 EXPECT_EQ(3, snd_mixer_selem_get_name_called); 345 346 /* Should use "Playback" since it has playback switch. */ 347 cras_alsa_mixer_set_mute(c, 0, NULL); 348 EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_called); 349 350 ResetStubData(); 351 snd_mixer_selem_has_playback_volume_return_values = element_playback_volume; 352 snd_mixer_selem_has_playback_volume_return_values_length = 353 ARRAY_SIZE(element_playback_volume); 354 snd_mixer_selem_has_playback_switch_return_values = element_playback_switches; 355 snd_mixer_selem_has_playback_switch_return_values_length = 356 ARRAY_SIZE(element_playback_switches); 357 snd_mixer_selem_get_name_return_values = element_names; 358 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 359 rc = mixer_control_create(&mixer_output, NULL, 360 reinterpret_cast<snd_mixer_elem_t *>(2), 361 CRAS_STREAM_OUTPUT); 362 EXPECT_EQ(0, rc); 363 EXPECT_EQ(1, snd_mixer_selem_get_name_called); 364 EXPECT_EQ(1, snd_mixer_selem_has_playback_volume_called); 365 EXPECT_EQ(1, snd_mixer_selem_has_playback_switch_called); 366 EXPECT_EQ(0, snd_mixer_selem_get_playback_dB_range_called); 367 368 /* 369 * If passed a mixer output then it should mute both "Playback" and that 370 * mixer_output. 371 */ 372 cras_alsa_mixer_set_mute(c, 0, mixer_output); 373 EXPECT_EQ(2, snd_mixer_selem_set_playback_switch_all_called); 374 cras_alsa_mixer_set_dBFS(c, 0, NULL); 375 EXPECT_EQ(1, snd_mixer_selem_set_playback_dB_all_called); 376 377 cras_alsa_mixer_destroy(c); 378 EXPECT_EQ(1, snd_mixer_close_called); 379 mixer_control_destroy(mixer_output); 380 } 381 382 TEST(AlsaMixer, CreateOneMasterElement) { 383 struct cras_alsa_mixer *c; 384 int element_playback_volume[] = { 385 1, 386 1, 387 }; 388 int element_playback_switches[] = { 389 1, 390 1, 391 }; 392 const char *element_names[] = { 393 "Master", 394 "Playback" 395 }; 396 struct mixer_control *mixer_output; 397 int rc; 398 long set_dB_values[3]; 399 static const long min_volumes[] = {0, 0}; 400 static const long max_volumes[] = {950, 950}; 401 402 ResetStubData(); 403 snd_mixer_first_elem_return_value = reinterpret_cast<snd_mixer_elem_t *>(1); 404 snd_mixer_selem_has_playback_volume_return_values = element_playback_volume; 405 snd_mixer_selem_has_playback_volume_return_values_length = 406 ARRAY_SIZE(element_playback_volume); 407 snd_mixer_selem_has_playback_switch_return_values = element_playback_switches; 408 snd_mixer_selem_has_playback_switch_return_values_length = 409 ARRAY_SIZE(element_playback_switches); 410 snd_mixer_selem_get_name_return_values = element_names; 411 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 412 c = create_mixer_and_add_controls_by_name_matching( 413 "hw:0", NULL, NULL); 414 ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 415 EXPECT_EQ(1, snd_mixer_open_called); 416 EXPECT_EQ(1, snd_mixer_attach_called); 417 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 418 EXPECT_EQ(1, snd_mixer_selem_register_called); 419 EXPECT_EQ(1, snd_mixer_load_called); 420 EXPECT_EQ(0, snd_mixer_close_called); 421 EXPECT_EQ(3, snd_mixer_selem_get_name_called); 422 EXPECT_EQ(1, snd_mixer_elem_next_called); 423 424 /* set mute should be called for Master. */ 425 cras_alsa_mixer_set_mute(c, 0, NULL); 426 EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_called); 427 /* set volume should be called for Master. */ 428 cras_alsa_mixer_set_dBFS(c, 0, NULL); 429 EXPECT_EQ(1, snd_mixer_selem_set_playback_dB_all_called); 430 431 ResetStubData(); 432 snd_mixer_selem_set_playback_dB_all_values = set_dB_values; 433 snd_mixer_selem_set_playback_dB_all_values_length = 434 ARRAY_SIZE(set_dB_values); 435 snd_mixer_selem_get_playback_dB_range_min_values = min_volumes; 436 snd_mixer_selem_get_playback_dB_range_max_values = max_volumes; 437 snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes); 438 snd_mixer_selem_has_playback_volume_return_values = element_playback_volume; 439 snd_mixer_selem_has_playback_volume_return_values_length = 440 ARRAY_SIZE(element_playback_volume); 441 snd_mixer_selem_get_name_return_values = element_names; 442 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 443 rc = mixer_control_create(&mixer_output, NULL, 444 reinterpret_cast<snd_mixer_elem_t *>(2), 445 CRAS_STREAM_OUTPUT); 446 EXPECT_EQ(0, rc); 447 EXPECT_EQ(1, snd_mixer_selem_get_name_called); 448 EXPECT_EQ(1, snd_mixer_selem_has_playback_volume_called); 449 EXPECT_EQ(1, snd_mixer_selem_has_playback_switch_called); 450 EXPECT_EQ(1, snd_mixer_selem_get_playback_dB_range_called); 451 452 /* if passed a mixer output then it should set the volume for that too. */ 453 cras_alsa_mixer_set_dBFS(c, 0, mixer_output); 454 EXPECT_EQ(2, snd_mixer_selem_set_playback_dB_all_called); 455 EXPECT_EQ(950, set_dB_values[0]); 456 EXPECT_EQ(950, set_dB_values[1]); 457 458 cras_alsa_mixer_destroy(c); 459 EXPECT_EQ(1, snd_mixer_close_called); 460 mixer_control_destroy(mixer_output); 461 } 462 463 TEST(AlsaMixer, CreateTwoMainVolumeElements) { 464 struct cras_alsa_mixer *c; 465 snd_mixer_elem_t *elements[] = { 466 reinterpret_cast<snd_mixer_elem_t *>(2), 467 }; 468 int element_playback_volume[] = { 469 1, 470 1, 471 1, 472 }; 473 int element_playback_switches[] = { 474 1, 475 1, 476 1, 477 }; 478 const char *element_names[] = { 479 "Master", 480 "PCM", 481 "Other", 482 }; 483 struct mixer_control *mixer_output; 484 int rc; 485 static const long min_volumes[] = {-500, -1250, -500}; 486 static const long max_volumes[] = {40, 40, 0}; 487 long get_dB_returns[] = {0, 0, 0}; 488 long set_dB_values[3]; 489 490 ResetStubData(); 491 snd_mixer_first_elem_return_value = reinterpret_cast<snd_mixer_elem_t *>(1); 492 snd_mixer_elem_next_return_values = elements; 493 snd_mixer_elem_next_return_values_length = ARRAY_SIZE(elements); 494 snd_mixer_selem_has_playback_volume_return_values = element_playback_volume; 495 snd_mixer_selem_has_playback_volume_return_values_length = 496 ARRAY_SIZE(element_playback_volume); 497 snd_mixer_selem_has_playback_switch_return_values = element_playback_switches; 498 snd_mixer_selem_has_playback_switch_return_values_length = 499 ARRAY_SIZE(element_playback_switches); 500 snd_mixer_selem_get_name_return_values = element_names; 501 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 502 snd_mixer_selem_get_playback_dB_range_called = 0; 503 snd_mixer_selem_get_playback_dB_range_min_values = min_volumes; 504 snd_mixer_selem_get_playback_dB_range_max_values = max_volumes; 505 snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes); 506 snd_mixer_selem_set_playback_dB_all_values = set_dB_values; 507 snd_mixer_selem_set_playback_dB_all_values_length = 508 ARRAY_SIZE(set_dB_values); 509 c = create_mixer_and_add_controls_by_name_matching( 510 "hw:0", NULL, NULL); 511 ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 512 EXPECT_EQ(2, snd_mixer_selem_get_playback_dB_range_called); 513 EXPECT_EQ(1, snd_mixer_open_called); 514 EXPECT_EQ(1, snd_mixer_attach_called); 515 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 516 EXPECT_EQ(1, snd_mixer_selem_register_called); 517 EXPECT_EQ(1, snd_mixer_load_called); 518 EXPECT_EQ(0, snd_mixer_close_called); 519 EXPECT_EQ(2, snd_mixer_elem_next_called); 520 EXPECT_EQ(5, snd_mixer_selem_get_name_called); 521 EXPECT_EQ(3, snd_mixer_selem_has_playback_switch_called); 522 523 /* Set mute should be called for Master only. */ 524 cras_alsa_mixer_set_mute(c, 0, NULL); 525 EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_called); 526 527 /* Set volume should be called for Master and PCM. If Master doesn't set to 528 * anything but zero then the entire volume should be passed to the PCM 529 * control.*/ 530 531 /* Set volume should be called for Master and PCM. (without mixer_output) */ 532 snd_mixer_selem_get_playback_dB_return_values = get_dB_returns; 533 snd_mixer_selem_get_playback_dB_return_values_length = 534 ARRAY_SIZE(get_dB_returns); 535 cras_alsa_mixer_set_dBFS(c, -50, NULL); 536 EXPECT_EQ(2, snd_mixer_selem_set_playback_dB_all_called); 537 EXPECT_EQ(2, snd_mixer_selem_get_playback_dB_called); 538 /* volume should be set relative to max volume (40 + 40). */ 539 EXPECT_EQ(30, set_dB_values[0]); 540 EXPECT_EQ(30, set_dB_values[1]); 541 542 ResetStubData(); 543 snd_mixer_selem_set_playback_dB_all_values = set_dB_values; 544 snd_mixer_selem_set_playback_dB_all_values_length = ARRAY_SIZE(set_dB_values); 545 snd_mixer_selem_get_playback_dB_range_min_values = min_volumes; 546 snd_mixer_selem_get_playback_dB_range_max_values = max_volumes; 547 snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes); 548 snd_mixer_selem_has_playback_volume_return_values = element_playback_volume; 549 snd_mixer_selem_has_playback_volume_return_values_length = 550 ARRAY_SIZE(element_playback_volume); 551 snd_mixer_selem_has_playback_switch_return_values = element_playback_switches; 552 snd_mixer_selem_has_playback_switch_return_values_length = 553 ARRAY_SIZE(element_playback_switches); 554 snd_mixer_selem_get_name_return_values = element_names; 555 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 556 rc = mixer_control_create(&mixer_output, NULL, 557 reinterpret_cast<snd_mixer_elem_t *>(3), 558 CRAS_STREAM_OUTPUT); 559 EXPECT_EQ(0, rc); 560 EXPECT_EQ(1, snd_mixer_selem_get_name_called); 561 EXPECT_EQ(1, snd_mixer_selem_has_playback_volume_called); 562 EXPECT_EQ(1, snd_mixer_selem_has_playback_switch_called); 563 EXPECT_EQ(1, snd_mixer_selem_get_playback_dB_range_called); 564 565 /* Set volume should be called for Master, PCM, and the mixer_output passed 566 * in. If Master doesn't set to anything but zero then the entire volume 567 * should be passed to the PCM control.*/ 568 cras_alsa_mixer_set_dBFS(c, -50, mixer_output); 569 EXPECT_EQ(3, snd_mixer_selem_set_playback_dB_all_called); 570 EXPECT_EQ(2, snd_mixer_selem_get_playback_dB_called); 571 EXPECT_EQ(30, set_dB_values[0]); 572 EXPECT_EQ(30, set_dB_values[1]); 573 EXPECT_EQ(30, set_dB_values[2]); 574 /* Set volume should be called for Master and PCM. Since the controls were 575 * sorted, Master should get the volume remaining after PCM is set, in this 576 * case -50 - -24 = -26. */ 577 long get_dB_returns2[] = { 578 -25, 579 -24, 580 }; 581 snd_mixer_selem_get_playback_dB_return_values = get_dB_returns2; 582 snd_mixer_selem_get_playback_dB_return_values_length = 583 ARRAY_SIZE(get_dB_returns2); 584 snd_mixer_selem_set_playback_dB_all_called = 0; 585 snd_mixer_selem_get_playback_dB_called = 0; 586 mixer_output->has_volume = 0; 587 mixer_output->min_volume_dB = MIXER_CONTROL_VOLUME_DB_INVALID; 588 mixer_output->max_volume_dB = MIXER_CONTROL_VOLUME_DB_INVALID; 589 cras_alsa_mixer_set_dBFS(c, -50, mixer_output); 590 EXPECT_EQ(2, snd_mixer_selem_set_playback_dB_all_called); 591 EXPECT_EQ(2, snd_mixer_selem_get_playback_dB_called); 592 EXPECT_EQ(54, set_dB_values[0]); // Master 593 EXPECT_EQ(30, set_dB_values[1]); // PCM 594 595 cras_alsa_mixer_destroy(c); 596 EXPECT_EQ(1, snd_mixer_close_called); 597 mixer_control_destroy(mixer_output); 598 } 599 600 TEST(AlsaMixer, CreateTwoMainCaptureElements) { 601 struct cras_alsa_mixer *c; 602 snd_mixer_elem_t *elements[] = { 603 reinterpret_cast<snd_mixer_elem_t *>(2), 604 }; 605 int element_capture_volume[] = { 606 1, 607 1, 608 1, 609 }; 610 int element_capture_switches[] = { 611 1, 612 1, 613 1, 614 }; 615 const char *element_names[] = { 616 "Capture", 617 "Digital Capture", 618 "Mic", 619 }; 620 struct mixer_control *mixer_input; 621 int rc; 622 623 ResetStubData(); 624 snd_mixer_first_elem_return_value = reinterpret_cast<snd_mixer_elem_t *>(1); 625 snd_mixer_elem_next_return_values = elements; 626 snd_mixer_elem_next_return_values_length = ARRAY_SIZE(elements); 627 snd_mixer_selem_has_capture_volume_return_values = element_capture_volume; 628 snd_mixer_selem_has_capture_volume_return_values_length = 629 ARRAY_SIZE(element_capture_volume); 630 snd_mixer_selem_has_capture_switch_return_values = element_capture_switches; 631 snd_mixer_selem_has_capture_switch_return_values_length = 632 ARRAY_SIZE(element_capture_switches); 633 snd_mixer_selem_get_name_return_values = element_names; 634 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 635 c = create_mixer_and_add_controls_by_name_matching( 636 "hw:0", NULL, NULL); 637 ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 638 EXPECT_EQ(1, snd_mixer_open_called); 639 EXPECT_EQ(1, snd_mixer_attach_called); 640 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 641 EXPECT_EQ(1, snd_mixer_selem_register_called); 642 EXPECT_EQ(1, snd_mixer_load_called); 643 EXPECT_EQ(0, snd_mixer_close_called); 644 EXPECT_EQ(2, snd_mixer_elem_next_called); 645 EXPECT_EQ(5, snd_mixer_selem_get_name_called); 646 EXPECT_EQ(3, snd_mixer_selem_has_capture_switch_called); 647 648 /* Set mute should be called for Master only. */ 649 cras_alsa_mixer_set_capture_mute(c, 0, NULL); 650 EXPECT_EQ(1, snd_mixer_selem_set_capture_switch_all_called); 651 /* Set volume should be called for Capture and Digital Capture. If Capture 652 * doesn't set to anything but zero then the entire volume should be passed to 653 * the Digital Capture control. */ 654 long get_dB_returns[] = { 655 0, 656 0, 657 }; 658 long set_dB_values[2]; 659 snd_mixer_selem_get_capture_dB_return_values = get_dB_returns; 660 snd_mixer_selem_get_capture_dB_return_values_length = 661 ARRAY_SIZE(get_dB_returns); 662 snd_mixer_selem_set_capture_dB_all_values = set_dB_values; 663 snd_mixer_selem_set_capture_dB_all_values_length = 664 ARRAY_SIZE(set_dB_values); 665 cras_alsa_mixer_set_capture_dBFS(c, -10, NULL); 666 EXPECT_EQ(2, snd_mixer_selem_set_capture_dB_all_called); 667 EXPECT_EQ(2, snd_mixer_selem_get_capture_dB_called); 668 EXPECT_EQ(-10, set_dB_values[0]); 669 EXPECT_EQ(-10, set_dB_values[1]); 670 /* Set volume should be called for Capture and Digital Capture. Capture should 671 * get the gain remaining after Mic Boos is set, in this case 20 - 25 = -5. */ 672 long get_dB_returns2[] = { 673 25, 674 -5, 675 }; 676 snd_mixer_selem_get_capture_dB_return_values = get_dB_returns2; 677 snd_mixer_selem_get_capture_dB_return_values_length = 678 ARRAY_SIZE(get_dB_returns2); 679 snd_mixer_selem_set_capture_dB_all_values = set_dB_values; 680 snd_mixer_selem_set_capture_dB_all_values_length = 681 ARRAY_SIZE(set_dB_values); 682 snd_mixer_selem_set_capture_dB_all_called = 0; 683 snd_mixer_selem_get_capture_dB_called = 0; 684 cras_alsa_mixer_set_capture_dBFS(c, 20, NULL); 685 EXPECT_EQ(2, snd_mixer_selem_set_capture_dB_all_called); 686 EXPECT_EQ(2, snd_mixer_selem_get_capture_dB_called); 687 EXPECT_EQ(20, set_dB_values[0]); 688 EXPECT_EQ(-5, set_dB_values[1]); 689 690 /* Set volume to the two main controls plus additional specific input 691 * volume control */ 692 693 long get_dB_returns3[] = { 694 0, 695 0, 696 0, 697 }; 698 long set_dB_values3[3]; 699 700 snd_mixer_selem_get_capture_dB_return_values = get_dB_returns3; 701 snd_mixer_selem_get_capture_dB_return_values_length = 702 ARRAY_SIZE(get_dB_returns3); 703 snd_mixer_selem_get_capture_dB_called = 0; 704 snd_mixer_selem_set_capture_dB_all_values = set_dB_values3; 705 snd_mixer_selem_set_capture_dB_all_values_length = 706 ARRAY_SIZE(set_dB_values3); 707 snd_mixer_selem_set_capture_dB_all_called = 0; 708 snd_mixer_selem_has_capture_volume_return_values = element_capture_volume; 709 snd_mixer_selem_has_capture_volume_return_values_length = 710 ARRAY_SIZE(element_capture_volume); 711 snd_mixer_selem_has_capture_switch_return_values = element_capture_switches; 712 snd_mixer_selem_has_capture_switch_return_values_length = 713 ARRAY_SIZE(element_capture_switches); 714 snd_mixer_selem_get_name_return_values = element_names; 715 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 716 snd_mixer_selem_get_name_called = 0; 717 snd_mixer_selem_has_capture_volume_called = 0; 718 snd_mixer_selem_has_capture_switch_called = 0; 719 snd_mixer_selem_get_capture_dB_range_called = 0; 720 rc = mixer_control_create(&mixer_input, NULL, 721 reinterpret_cast<snd_mixer_elem_t *>(3), 722 CRAS_STREAM_INPUT); 723 EXPECT_EQ(0, rc); 724 EXPECT_EQ(1, snd_mixer_selem_get_name_called); 725 EXPECT_EQ(1, snd_mixer_selem_has_capture_volume_called); 726 EXPECT_EQ(1, snd_mixer_selem_has_capture_switch_called); 727 EXPECT_EQ(1, snd_mixer_selem_get_capture_dB_range_called); 728 EXPECT_EQ(1, mixer_input->has_volume); 729 730 cras_alsa_mixer_set_capture_dBFS(c, 20, mixer_input); 731 732 EXPECT_EQ(3, snd_mixer_selem_set_capture_dB_all_called); 733 EXPECT_EQ(2, snd_mixer_selem_get_capture_dB_called); 734 EXPECT_EQ(20, set_dB_values3[0]); 735 EXPECT_EQ(20, set_dB_values3[1]); 736 EXPECT_EQ(20, set_dB_values3[2]); 737 738 cras_alsa_mixer_destroy(c); 739 EXPECT_EQ(1, snd_mixer_close_called); 740 mixer_control_destroy(mixer_input); 741 } 742 743 class AlsaMixerOutputs : public testing::Test { 744 protected: 745 virtual void SetUp() { 746 output_called_values_.clear(); 747 output_callback_called_ = 0; 748 static snd_mixer_elem_t *elements[] = { 749 reinterpret_cast<snd_mixer_elem_t *>(2), // PCM 750 reinterpret_cast<snd_mixer_elem_t *>(3), // Headphone 751 reinterpret_cast<snd_mixer_elem_t *>(4), // Speaker 752 reinterpret_cast<snd_mixer_elem_t *>(5), // HDMI 753 reinterpret_cast<snd_mixer_elem_t *>(6), // IEC958 754 reinterpret_cast<snd_mixer_elem_t *>(7), // Mic Boost 755 reinterpret_cast<snd_mixer_elem_t *>(8), // Capture 756 }; 757 static int element_playback_volume[] = { 758 1, 759 1, 760 1, 761 0, 762 0, 763 1, 764 1, 765 }; 766 static int element_playback_switches[] = { 767 1, 768 1, 769 1, 770 0, 771 1, 772 1, 773 1, 774 }; 775 static int element_capture_volume[] = {0, 0, 0, 0, 0, 0, 776 1, 777 1, 778 }; 779 static int element_capture_switches[] = {0, 0, 0, 0, 0, 0, 780 1, 781 1, 782 }; 783 static const long min_volumes[] = {0, 0, 0, 0, 0, 0, 500, -1250}; 784 static const long max_volumes[] = {0, 0, 0, 0, 0, 0, 3000, 400}; 785 static const char *element_names[] = { 786 "Master", 787 "PCM", 788 "Headphone", 789 "Speaker", 790 "HDMI", 791 "IEC958", 792 "Capture", 793 "Digital Capture", 794 }; 795 static const char *output_names_extra[] = { 796 "IEC958" 797 }; 798 static char *iniparser_returns[] = { 799 NULL, 800 }; 801 struct mixer_name *extra_controls = 802 mixer_name_add_array(NULL, output_names_extra, 803 ARRAY_SIZE(output_names_extra), 804 CRAS_STREAM_OUTPUT, 805 MIXER_NAME_VOLUME); 806 807 ResetStubData(); 808 snd_mixer_first_elem_return_value = 809 reinterpret_cast<snd_mixer_elem_t *>(1); // Master 810 snd_mixer_elem_next_return_values = elements; 811 snd_mixer_elem_next_return_values_length = ARRAY_SIZE(elements); 812 snd_mixer_selem_has_playback_volume_return_values = 813 element_playback_volume; 814 snd_mixer_selem_has_playback_volume_return_values_length = 815 ARRAY_SIZE(element_playback_volume); 816 snd_mixer_selem_has_playback_switch_return_values = 817 element_playback_switches; 818 snd_mixer_selem_has_playback_switch_return_values_length = 819 ARRAY_SIZE(element_playback_switches); 820 snd_mixer_selem_has_capture_volume_return_values = 821 element_capture_volume; 822 snd_mixer_selem_has_capture_volume_return_values_length = 823 ARRAY_SIZE(element_capture_volume); 824 snd_mixer_selem_has_capture_switch_return_values = 825 element_capture_switches; 826 snd_mixer_selem_has_capture_switch_return_values_length = 827 ARRAY_SIZE(element_capture_switches); 828 snd_mixer_selem_get_name_return_values = element_names; 829 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 830 snd_mixer_selem_get_capture_dB_range_called = 0; 831 snd_mixer_selem_get_capture_dB_range_min_values = min_volumes; 832 snd_mixer_selem_get_capture_dB_range_max_values = max_volumes; 833 snd_mixer_selem_get_capture_dB_range_values_length = 834 ARRAY_SIZE(min_volumes); 835 iniparser_getstring_returns = iniparser_returns; 836 iniparser_getstring_return_length = ARRAY_SIZE(iniparser_returns); 837 cras_mixer_ = create_mixer_and_add_controls_by_name_matching( 838 "hw:0", extra_controls, NULL); 839 ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), cras_mixer_); 840 EXPECT_EQ(1, snd_mixer_open_called); 841 EXPECT_EQ(1, snd_mixer_attach_called); 842 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 843 EXPECT_EQ(1, snd_mixer_selem_register_called); 844 EXPECT_EQ(1, snd_mixer_load_called); 845 EXPECT_EQ(0, snd_mixer_close_called); 846 EXPECT_EQ(ARRAY_SIZE(elements) + 1, snd_mixer_elem_next_called); 847 EXPECT_EQ(8, snd_mixer_selem_has_playback_volume_called); 848 EXPECT_EQ(7, snd_mixer_selem_has_playback_switch_called); 849 EXPECT_EQ(4, snd_mixer_selem_has_capture_volume_called); 850 EXPECT_EQ(3, snd_mixer_selem_has_capture_switch_called); 851 mixer_name_free(extra_controls); 852 } 853 854 virtual void TearDown() { 855 cras_alsa_mixer_destroy(cras_mixer_); 856 EXPECT_EQ(1, snd_mixer_close_called); 857 } 858 859 static void OutputCallback(struct mixer_control *out, void *arg) { 860 output_callback_called_++; 861 output_called_values_.push_back(out); 862 } 863 864 struct cras_alsa_mixer *cras_mixer_; 865 static size_t output_callback_called_; 866 static std::vector<struct mixer_control *> output_called_values_; 867 }; 868 869 size_t AlsaMixerOutputs::output_callback_called_; 870 std::vector<struct mixer_control *> 871 AlsaMixerOutputs::output_called_values_; 872 873 TEST_F(AlsaMixerOutputs, CheckFourOutputs) { 874 cras_alsa_mixer_list_outputs(cras_mixer_, 875 AlsaMixerOutputs::OutputCallback, 876 reinterpret_cast<void*>(555)); 877 EXPECT_EQ(4, output_callback_called_); 878 } 879 880 TEST_F(AlsaMixerOutputs, CheckFindOutputByNameNoMatch) { 881 struct mixer_control *out; 882 883 out = cras_alsa_mixer_get_output_matching_name(cras_mixer_, 884 "AAAAA Jack"); 885 EXPECT_EQ(static_cast<struct mixer_control *>(NULL), out); 886 } 887 888 TEST_F(AlsaMixerOutputs, CheckFindOutputByName) { 889 struct mixer_control *out; 890 891 out = cras_alsa_mixer_get_output_matching_name(cras_mixer_, 892 "Headphone Jack"); 893 EXPECT_NE(static_cast<struct mixer_control *>(NULL), out); 894 } 895 896 TEST_F(AlsaMixerOutputs, CheckFindOutputHDMIByName) { 897 struct mixer_control *out; 898 899 out = cras_alsa_mixer_get_output_matching_name(cras_mixer_, 900 "HDMI Jack"); 901 EXPECT_NE(static_cast<struct mixer_control *>(NULL), out); 902 } 903 904 TEST_F(AlsaMixerOutputs, CheckFindInputNameWorkaround) { 905 struct mixer_control *control; 906 snd_mixer_elem_t *elements[] = { 907 reinterpret_cast<snd_mixer_elem_t *>(1), // Speaker 908 reinterpret_cast<snd_mixer_elem_t *>(2), // Headphone 909 reinterpret_cast<snd_mixer_elem_t *>(3), // MIC 910 }; 911 const char *element_names[] = { 912 "Speaker", 913 "Headphone", 914 "MIC", 915 }; 916 size_t i; 917 918 ResetStubData(); 919 for (i = 0; i < ARRAY_SIZE(elements); i++) 920 snd_mixer_find_elem_map[element_names[i]] = elements[i]; 921 922 snd_mixer_selem_get_name_called = 0; 923 snd_mixer_selem_get_name_return_values = element_names; 924 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 925 control = cras_alsa_mixer_get_input_matching_name(cras_mixer_, 926 "MIC"); 927 EXPECT_NE(static_cast<struct mixer_control *>(NULL), control); 928 /* This exercises the 'workaround' where the control is added if it was 929 * previouly missing in cras_alsa_mixer_get_input_matching_name(). 930 * snd_mixer_find_selem is called once for the missing control. */ 931 EXPECT_EQ(1, snd_mixer_find_selem_called); 932 EXPECT_EQ(1, snd_mixer_selem_has_capture_volume_called); 933 EXPECT_EQ(1, snd_mixer_selem_has_capture_switch_called); 934 } 935 936 TEST_F(AlsaMixerOutputs, ActivateDeactivate) { 937 int rc; 938 939 cras_alsa_mixer_list_outputs(cras_mixer_, 940 AlsaMixerOutputs::OutputCallback, 941 reinterpret_cast<void*>(555)); 942 EXPECT_EQ(4, output_callback_called_); 943 EXPECT_EQ(4, output_called_values_.size()); 944 945 rc = cras_alsa_mixer_set_output_active_state(output_called_values_[0], 0); 946 ASSERT_EQ(0, rc); 947 EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_called); 948 cras_alsa_mixer_set_output_active_state(output_called_values_[0], 1); 949 EXPECT_EQ(2, snd_mixer_selem_set_playback_switch_all_called); 950 } 951 952 TEST_F(AlsaMixerOutputs, MinMaxCaptureGain) { 953 long min, max; 954 min = cras_alsa_mixer_get_minimum_capture_gain(cras_mixer_, 955 NULL); 956 EXPECT_EQ(-750, min); 957 max = cras_alsa_mixer_get_maximum_capture_gain(cras_mixer_, 958 NULL); 959 EXPECT_EQ(3400, max); 960 } 961 962 TEST_F(AlsaMixerOutputs, MinMaxCaptureGainWithActiveInput) { 963 struct mixer_control *mixer_input; 964 long min, max; 965 966 mixer_input = (struct mixer_control *)calloc(1, sizeof(*mixer_input)); 967 mixer_input->min_volume_dB = 50; 968 mixer_input->max_volume_dB = 60; 969 mixer_input->has_volume = 1; 970 min = cras_alsa_mixer_get_minimum_capture_gain(cras_mixer_, mixer_input); 971 max = cras_alsa_mixer_get_maximum_capture_gain(cras_mixer_, mixer_input); 972 EXPECT_EQ(-700, min); 973 EXPECT_EQ(3460, max); 974 975 free((void *)mixer_input); 976 } 977 978 TEST(AlsaMixer, CreateWithCoupledOutputControls) { 979 struct cras_alsa_mixer *c; 980 struct mixer_control *output_control; 981 struct mixer_control_element *c1, *c2, *c3, *c4; 982 983 static const long min_volumes[] = {-70, -70}; 984 static const long max_volumes[] = {30, 30}; 985 986 long set_dB_values[2]; 987 988 const char *coupled_output_names[] = {"Left Master", 989 "Right Master", 990 "Left Speaker", 991 "Right Speaker"}; 992 struct mixer_name *coupled_controls = 993 mixer_name_add_array(NULL, coupled_output_names, 994 ARRAY_SIZE(coupled_output_names), 995 CRAS_STREAM_OUTPUT, 996 MIXER_NAME_VOLUME); 997 int element_playback_volume[] = {1, 1, 0, 0}; 998 int element_playback_switches[] = {0, 0, 1, 1}; 999 1000 long target_dBFS = -30; 1001 long expected_dB_value = target_dBFS + max_volumes[0]; 1002 1003 ResetStubData(); 1004 1005 snd_mixer_find_elem_map[std::string("Left Master")] = 1006 reinterpret_cast<snd_mixer_elem_t *>(1); 1007 snd_mixer_find_elem_map[std::string("Right Master")] = 1008 reinterpret_cast<snd_mixer_elem_t *>(2); 1009 snd_mixer_find_elem_map[std::string("Left Speaker")] = 1010 reinterpret_cast<snd_mixer_elem_t *>(3); 1011 snd_mixer_find_elem_map[std::string("Right Speaker")] = 1012 reinterpret_cast<snd_mixer_elem_t *>(4); 1013 1014 snd_mixer_selem_has_playback_volume_return_values = element_playback_volume; 1015 snd_mixer_selem_has_playback_volume_return_values_length = 1016 ARRAY_SIZE(element_playback_volume); 1017 snd_mixer_selem_has_playback_switch_return_values = element_playback_switches; 1018 snd_mixer_selem_has_playback_switch_return_values_length = 1019 ARRAY_SIZE(element_playback_switches); 1020 1021 snd_mixer_selem_get_playback_dB_range_min_values = min_volumes; 1022 snd_mixer_selem_get_playback_dB_range_max_values = max_volumes; 1023 snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes); 1024 1025 c = create_mixer_and_add_controls_by_name_matching( 1026 "hw:0", NULL, coupled_controls); 1027 1028 ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 1029 EXPECT_EQ(1, snd_mixer_open_called); 1030 EXPECT_EQ(1, snd_mixer_attach_called); 1031 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 1032 EXPECT_EQ(1, snd_mixer_selem_register_called); 1033 EXPECT_EQ(1, snd_mixer_load_called); 1034 EXPECT_EQ(0, snd_mixer_close_called); 1035 1036 output_control = c->output_controls; 1037 EXPECT_EQ(NULL, output_control->next); 1038 c1 = output_control->elements; 1039 c2 = c1->next; 1040 c3 = c2->next; 1041 c4 = c3->next; 1042 EXPECT_EQ(c1->elem, reinterpret_cast<snd_mixer_elem_t *>(1)); 1043 EXPECT_EQ(c2->elem, reinterpret_cast<snd_mixer_elem_t *>(2)); 1044 EXPECT_EQ(c3->elem, reinterpret_cast<snd_mixer_elem_t *>(3)); 1045 EXPECT_EQ(c4->elem, reinterpret_cast<snd_mixer_elem_t *>(4)); 1046 EXPECT_EQ(c4->next, reinterpret_cast<mixer_control_element *>(NULL)); 1047 EXPECT_EQ(c1->has_volume, 1); 1048 EXPECT_EQ(c1->has_mute, 0); 1049 EXPECT_EQ(c2->has_volume, 1); 1050 EXPECT_EQ(c2->has_mute, 0); 1051 EXPECT_EQ(c3->has_volume, 0); 1052 EXPECT_EQ(c3->has_mute, 1); 1053 EXPECT_EQ(c4->has_volume, 0); 1054 EXPECT_EQ(c4->has_mute, 1); 1055 EXPECT_EQ(output_control->max_volume_dB, max_volumes[0]); 1056 EXPECT_EQ(output_control->min_volume_dB, min_volumes[0]); 1057 1058 snd_mixer_selem_set_playback_dB_all_values = set_dB_values; 1059 snd_mixer_selem_set_playback_dB_all_values_length = 1060 ARRAY_SIZE(set_dB_values); 1061 1062 cras_alsa_mixer_set_dBFS(c, target_dBFS, output_control); 1063 1064 /* Set volume should set playback dB on two of the coupled controls. */ 1065 EXPECT_EQ(2, snd_mixer_selem_set_playback_dB_all_called); 1066 EXPECT_EQ(set_dB_values[0], expected_dB_value); 1067 EXPECT_EQ(set_dB_values[1], expected_dB_value); 1068 1069 /* Mute should set playback switch on two of the coupled controls. */ 1070 cras_alsa_mixer_set_mute(c, 1, output_control); 1071 EXPECT_EQ(2, snd_mixer_selem_set_playback_switch_all_called); 1072 EXPECT_EQ(0, snd_mixer_selem_set_playback_switch_all_value); 1073 1074 /* Unmute should set playback switch on two of the coupled controls. */ 1075 cras_alsa_mixer_set_mute(c, 0, output_control); 1076 EXPECT_EQ(4, snd_mixer_selem_set_playback_switch_all_called); 1077 EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_value); 1078 1079 EXPECT_EQ(max_volumes[0] - min_volumes[0], 1080 cras_alsa_mixer_get_output_dB_range(output_control)); 1081 1082 cras_alsa_mixer_destroy(c); 1083 EXPECT_EQ(1, snd_mixer_close_called); 1084 mixer_name_free(coupled_controls); 1085 } 1086 1087 TEST(AlsaMixer, CoupledOutputHasMuteNoVolume) { 1088 struct cras_alsa_mixer *c; 1089 struct mixer_control *output_control; 1090 struct mixer_control_element *c1, *c2, *c3, *c4; 1091 1092 static const long min_volumes[] = {-70}; 1093 static const long max_volumes[] = {30}; 1094 1095 const char *coupled_output_names[] = {"Left Master", 1096 "Right Master", 1097 "Left Speaker", 1098 "Right Speaker"}; 1099 struct mixer_name *coupled_controls = 1100 mixer_name_add_array(NULL, coupled_output_names, 1101 ARRAY_SIZE(coupled_output_names), 1102 CRAS_STREAM_OUTPUT, 1103 MIXER_NAME_VOLUME); 1104 int element_playback_volume[] = {0, 0, 0, 0}; 1105 int element_playback_switches[] = {0, 0, 1, 1}; 1106 1107 ResetStubData(); 1108 1109 snd_mixer_find_elem_map[std::string("Left Master")] = 1110 reinterpret_cast<snd_mixer_elem_t *>(1); 1111 snd_mixer_find_elem_map[std::string("Right Master")] = 1112 reinterpret_cast<snd_mixer_elem_t *>(2); 1113 snd_mixer_find_elem_map[std::string("Left Speaker")] = 1114 reinterpret_cast<snd_mixer_elem_t *>(3); 1115 snd_mixer_find_elem_map[std::string("Right Speaker")] = 1116 reinterpret_cast<snd_mixer_elem_t *>(4); 1117 1118 snd_mixer_selem_has_playback_volume_return_values = element_playback_volume; 1119 snd_mixer_selem_has_playback_volume_return_values_length = 1120 ARRAY_SIZE(element_playback_volume); 1121 snd_mixer_selem_has_playback_switch_return_values = element_playback_switches; 1122 snd_mixer_selem_has_playback_switch_return_values_length = 1123 ARRAY_SIZE(element_playback_switches); 1124 1125 snd_mixer_selem_get_playback_dB_range_min_values = min_volumes; 1126 snd_mixer_selem_get_playback_dB_range_max_values = max_volumes; 1127 snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes); 1128 1129 c = create_mixer_and_add_controls_by_name_matching( 1130 "hw:0", NULL, coupled_controls); 1131 1132 ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 1133 EXPECT_EQ(1, snd_mixer_open_called); 1134 EXPECT_EQ(1, snd_mixer_attach_called); 1135 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 1136 EXPECT_EQ(1, snd_mixer_selem_register_called); 1137 EXPECT_EQ(1, snd_mixer_load_called); 1138 EXPECT_EQ(0, snd_mixer_close_called); 1139 1140 output_control = c->output_controls; 1141 EXPECT_EQ(NULL, output_control->next); 1142 c1 = output_control->elements; 1143 c2 = c1->next; 1144 c3 = c2->next; 1145 c4 = c3->next; 1146 EXPECT_EQ(c1->elem, reinterpret_cast<snd_mixer_elem_t *>(1)); 1147 EXPECT_EQ(c2->elem, reinterpret_cast<snd_mixer_elem_t *>(2)); 1148 EXPECT_EQ(c3->elem, reinterpret_cast<snd_mixer_elem_t *>(3)); 1149 EXPECT_EQ(c4->elem, reinterpret_cast<snd_mixer_elem_t *>(4)); 1150 EXPECT_EQ(c4->next, reinterpret_cast<mixer_control_element *>(NULL)); 1151 EXPECT_EQ(c1->has_volume, 0); 1152 EXPECT_EQ(c1->has_mute, 0); 1153 EXPECT_EQ(c2->has_volume, 0); 1154 EXPECT_EQ(c2->has_mute, 0); 1155 EXPECT_EQ(c3->has_volume, 0); 1156 EXPECT_EQ(c3->has_mute, 1); 1157 EXPECT_EQ(c4->has_volume, 0); 1158 EXPECT_EQ(c4->has_mute, 1); 1159 1160 EXPECT_EQ(0, cras_alsa_mixer_has_volume(output_control)); 1161 EXPECT_EQ(1, output_control->has_mute); 1162 1163 cras_alsa_mixer_destroy(c); 1164 EXPECT_EQ(1, snd_mixer_close_called); 1165 mixer_name_free(coupled_controls); 1166 } 1167 1168 TEST(AlsaMixer, CoupledOutputHasVolumeNoMute) { 1169 struct cras_alsa_mixer *c; 1170 struct mixer_control *output_control; 1171 struct mixer_control_element *c1, *c2, *c3, *c4; 1172 1173 static const long min_volumes[] = {-70, -70}; 1174 static const long max_volumes[] = {30, 30}; 1175 1176 const char *coupled_output_names[] = {"Left Master", 1177 "Right Master", 1178 "Left Speaker", 1179 "Right Speaker"}; 1180 struct mixer_name *coupled_controls = 1181 mixer_name_add_array(NULL, coupled_output_names, 1182 ARRAY_SIZE(coupled_output_names), 1183 CRAS_STREAM_OUTPUT, 1184 MIXER_NAME_VOLUME); 1185 int element_playback_volume[] = {1, 1, 0, 0}; 1186 int element_playback_switches[] = {0, 0, 0, 0}; 1187 1188 ResetStubData(); 1189 1190 snd_mixer_find_elem_map[std::string("Left Master")] = 1191 reinterpret_cast<snd_mixer_elem_t *>(1); 1192 snd_mixer_find_elem_map[std::string("Right Master")] = 1193 reinterpret_cast<snd_mixer_elem_t *>(2); 1194 snd_mixer_find_elem_map[std::string("Left Speaker")] = 1195 reinterpret_cast<snd_mixer_elem_t *>(3); 1196 snd_mixer_find_elem_map[std::string("Right Speaker")] = 1197 reinterpret_cast<snd_mixer_elem_t *>(4); 1198 1199 snd_mixer_selem_has_playback_volume_return_values = element_playback_volume; 1200 snd_mixer_selem_has_playback_volume_return_values_length = 1201 ARRAY_SIZE(element_playback_volume); 1202 snd_mixer_selem_has_playback_switch_return_values = element_playback_switches; 1203 snd_mixer_selem_has_playback_switch_return_values_length = 1204 ARRAY_SIZE(element_playback_switches); 1205 1206 snd_mixer_selem_get_playback_dB_range_min_values = min_volumes; 1207 snd_mixer_selem_get_playback_dB_range_max_values = max_volumes; 1208 snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes); 1209 1210 c = create_mixer_and_add_controls_by_name_matching( 1211 "hw:0", NULL, coupled_controls); 1212 1213 ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c); 1214 EXPECT_EQ(1, snd_mixer_open_called); 1215 EXPECT_EQ(1, snd_mixer_attach_called); 1216 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 1217 EXPECT_EQ(1, snd_mixer_selem_register_called); 1218 EXPECT_EQ(1, snd_mixer_load_called); 1219 EXPECT_EQ(0, snd_mixer_close_called); 1220 1221 output_control = c->output_controls; 1222 EXPECT_EQ(NULL, output_control->next); 1223 c1 = output_control->elements; 1224 c2 = c1->next; 1225 c3 = c2->next; 1226 c4 = c3->next; 1227 EXPECT_EQ(c1->elem, reinterpret_cast<snd_mixer_elem_t *>(1)); 1228 EXPECT_EQ(c2->elem, reinterpret_cast<snd_mixer_elem_t *>(2)); 1229 EXPECT_EQ(c3->elem, reinterpret_cast<snd_mixer_elem_t *>(3)); 1230 EXPECT_EQ(c4->elem, reinterpret_cast<snd_mixer_elem_t *>(4)); 1231 EXPECT_EQ(c4->next, reinterpret_cast<mixer_control_element *>(NULL)); 1232 EXPECT_EQ(c1->has_volume, 1); 1233 EXPECT_EQ(c1->has_mute, 0); 1234 EXPECT_EQ(c2->has_volume, 1); 1235 EXPECT_EQ(c2->has_mute, 0); 1236 EXPECT_EQ(c3->has_volume, 0); 1237 EXPECT_EQ(c3->has_mute, 0); 1238 EXPECT_EQ(c4->has_volume, 0); 1239 EXPECT_EQ(c4->has_mute, 0); 1240 1241 EXPECT_EQ(1, cras_alsa_mixer_has_volume(output_control)); 1242 EXPECT_EQ(0, output_control->has_mute); 1243 1244 cras_alsa_mixer_destroy(c); 1245 EXPECT_EQ(1, snd_mixer_close_called); 1246 mixer_name_free(coupled_controls); 1247 } 1248 1249 TEST(AlsaMixer, MixerName) { 1250 struct mixer_name *names; 1251 struct mixer_name *control; 1252 size_t mixer_name_count; 1253 static const char *element_names[] = { 1254 "Master", 1255 "PCM", 1256 "Headphone", 1257 "Speaker", 1258 "HDMI", 1259 "IEC958", 1260 }; 1261 1262 names = mixer_name_add_array(NULL, element_names, 1263 ARRAY_SIZE(element_names), 1264 CRAS_STREAM_OUTPUT, MIXER_NAME_VOLUME); 1265 names = mixer_name_add(names, "Playback", 1266 CRAS_STREAM_OUTPUT, MIXER_NAME_VOLUME); 1267 names = mixer_name_add(names, "Main", 1268 CRAS_STREAM_OUTPUT, MIXER_NAME_MAIN_VOLUME); 1269 names = mixer_name_add(names, "Mic", 1270 CRAS_STREAM_INPUT, MIXER_NAME_VOLUME); 1271 names = mixer_name_add(names, "Capture", 1272 CRAS_STREAM_INPUT, MIXER_NAME_MAIN_VOLUME); 1273 1274 /* Number of items (test mixer_name_add(_array)). */ 1275 mixer_name_count = 0; 1276 DL_FOREACH(names, control) { 1277 mixer_name_count++; 1278 } 1279 EXPECT_EQ(10, mixer_name_count); 1280 1281 /* Item not in the list: mismatch direction. */ 1282 control = mixer_name_find(names, "Main", 1283 CRAS_STREAM_INPUT, MIXER_NAME_UNDEFINED); 1284 EXPECT_EQ(1, control == NULL); 1285 1286 /* Item not in the list: mismatch type. */ 1287 control = mixer_name_find(names, "Main", 1288 CRAS_STREAM_OUTPUT, MIXER_NAME_VOLUME); 1289 EXPECT_EQ(1, control == NULL); 1290 1291 /* Find by name and direction. */ 1292 control = mixer_name_find(names, "Main", 1293 CRAS_STREAM_OUTPUT, MIXER_NAME_UNDEFINED); 1294 EXPECT_EQ(0, strcmp("Main", control->name)); 1295 1296 /* Find by type and direction. */ 1297 control = mixer_name_find(names, NULL, 1298 CRAS_STREAM_INPUT, MIXER_NAME_VOLUME); 1299 EXPECT_EQ(0, strcmp("Mic", control->name)); 1300 1301 mixer_name_free(names); 1302 } 1303 1304 class AlsaMixerFullySpeced : public testing::Test { 1305 protected: 1306 virtual void SetUp() { 1307 callback_values_.clear(); 1308 callback_called_ = 0; 1309 static snd_mixer_elem_t *elements[] = { 1310 reinterpret_cast<snd_mixer_elem_t *>(1), // HP-L 1311 reinterpret_cast<snd_mixer_elem_t *>(2), // HP-R 1312 reinterpret_cast<snd_mixer_elem_t *>(3), // SPK-L 1313 reinterpret_cast<snd_mixer_elem_t *>(4), // SPK-R 1314 reinterpret_cast<snd_mixer_elem_t *>(5), // HDMI 1315 reinterpret_cast<snd_mixer_elem_t *>(6), // CAPTURE 1316 reinterpret_cast<snd_mixer_elem_t *>(7), // MIC-L 1317 reinterpret_cast<snd_mixer_elem_t *>(8), // MIC-R 1318 reinterpret_cast<snd_mixer_elem_t *>(0), // Unknown 1319 }; 1320 static int element_playback_volume[] = { 1321 1, 1322 1, 1323 1, 1324 1, 1325 1, 1326 0, 0, 0, 1327 }; 1328 static int element_playback_switches[] = { 1329 0, 1330 0, 1331 0, 1332 0, 1333 1, 1334 0, 0, 0, 1335 }; 1336 static int element_capture_volume[] = {0, 0, 0, 0, 0, 1337 0, 1338 1, 1339 1, 1340 }; 1341 static int element_capture_switches[] = {0, 0, 0, 0, 0, 1342 1, 1343 0, 1344 0, 1345 }; 1346 static const long min_volumes[] = {-84, -84, -84, -84, -84, 0, 0, 0}; 1347 static const long max_volumes[] = {0, 0, 0, 0, 0, 0, 84, 84}; 1348 static const char *element_names[] = { 1349 "HP-L", 1350 "HP-R", 1351 "SPK-L", 1352 "SPK-R", 1353 "HDMI", 1354 "CAPTURE", 1355 "MIC-L", 1356 "MIC-R", 1357 "Unknown" 1358 }; 1359 struct ucm_section *sections = NULL; 1360 struct ucm_section *section; 1361 size_t i; 1362 1363 ResetStubData(); 1364 1365 for (i = 0; i < ARRAY_SIZE(elements); i++) 1366 snd_mixer_find_elem_map[element_names[i]] = elements[i]; 1367 1368 section = ucm_section_create("NullElement", 0, CRAS_STREAM_OUTPUT, 1369 NULL, NULL); 1370 ucm_section_set_mixer_name(section, "Unknown"); 1371 DL_APPEND(sections, section); 1372 section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT, 1373 "my-sound-card Headset Jack", "gpio"); 1374 ucm_section_add_coupled(section, "HP-L", MIXER_NAME_VOLUME); 1375 ucm_section_add_coupled(section, "HP-R", MIXER_NAME_VOLUME); 1376 DL_APPEND(sections, section); 1377 section = ucm_section_create("Speaker", 0, CRAS_STREAM_OUTPUT, 1378 NULL, NULL); 1379 ucm_section_add_coupled(section, "SPK-L", MIXER_NAME_VOLUME); 1380 ucm_section_add_coupled(section, "SPK-R", MIXER_NAME_VOLUME); 1381 DL_APPEND(sections, section); 1382 section = ucm_section_create("Mic", 0, CRAS_STREAM_INPUT, 1383 "my-sound-card Headset Jack", "gpio"); 1384 ucm_section_set_mixer_name(section, "CAPTURE"); 1385 DL_APPEND(sections, section); 1386 section = ucm_section_create("Internal Mic", 0, CRAS_STREAM_INPUT, 1387 NULL, NULL); 1388 ucm_section_add_coupled(section, "MIC-L", MIXER_NAME_VOLUME); 1389 ucm_section_add_coupled(section, "MIC-R", MIXER_NAME_VOLUME); 1390 DL_APPEND(sections, section); 1391 section = ucm_section_create("HDMI", 0, CRAS_STREAM_OUTPUT, 1392 NULL, NULL); 1393 ucm_section_set_mixer_name(section, "HDMI"); 1394 DL_APPEND(sections, section); 1395 ASSERT_NE(sections, (struct ucm_section *)NULL); 1396 1397 snd_mixer_selem_has_playback_volume_return_values = 1398 element_playback_volume; 1399 snd_mixer_selem_has_playback_volume_return_values_length = 1400 ARRAY_SIZE(element_playback_volume); 1401 snd_mixer_selem_has_playback_switch_return_values = 1402 element_playback_switches; 1403 snd_mixer_selem_has_playback_switch_return_values_length = 1404 ARRAY_SIZE(element_playback_switches); 1405 snd_mixer_selem_has_capture_volume_return_values = 1406 element_capture_volume; 1407 snd_mixer_selem_has_capture_volume_return_values_length = 1408 ARRAY_SIZE(element_capture_volume); 1409 snd_mixer_selem_has_capture_switch_return_values = 1410 element_capture_switches; 1411 snd_mixer_selem_has_capture_switch_return_values_length = 1412 ARRAY_SIZE(element_capture_switches); 1413 snd_mixer_selem_get_name_return_values = element_names; 1414 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names); 1415 snd_mixer_selem_get_capture_dB_range_min_values = min_volumes; 1416 snd_mixer_selem_get_capture_dB_range_max_values = max_volumes; 1417 snd_mixer_selem_get_capture_dB_range_values_length = 1418 ARRAY_SIZE(min_volumes); 1419 1420 cras_mixer_ = cras_alsa_mixer_create("hw:0"); 1421 ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), cras_mixer_); 1422 EXPECT_EQ(1, snd_mixer_open_called); 1423 EXPECT_EQ(1, snd_mixer_attach_called); 1424 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0")); 1425 EXPECT_EQ(1, snd_mixer_selem_register_called); 1426 EXPECT_EQ(1, snd_mixer_load_called); 1427 EXPECT_EQ(0, snd_mixer_close_called); 1428 1429 section = sections; 1430 EXPECT_EQ(-ENOENT,\ 1431 cras_alsa_mixer_add_controls_in_section(cras_mixer_, section)); 1432 ASSERT_NE((struct ucm_section *)NULL, section->next); 1433 section = section->next; 1434 EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section(cras_mixer_, section)); 1435 ASSERT_NE((struct ucm_section *)NULL, section->next); 1436 section = section->next; 1437 EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section(cras_mixer_, section)); 1438 ASSERT_NE((struct ucm_section *)NULL, section->next); 1439 section = section->next; 1440 EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section(cras_mixer_, section)); 1441 ASSERT_NE((struct ucm_section *)NULL, section->next); 1442 section = section->next; 1443 EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section(cras_mixer_, section)); 1444 ASSERT_NE((struct ucm_section *)NULL, section->next); 1445 section = section->next; 1446 EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section(cras_mixer_, section)); 1447 EXPECT_EQ(section->next, (struct ucm_section*)NULL); 1448 1449 EXPECT_EQ(9, snd_mixer_find_selem_called); 1450 EXPECT_EQ(5, snd_mixer_selem_has_playback_volume_called); 1451 EXPECT_EQ(5, snd_mixer_selem_has_playback_switch_called); 1452 EXPECT_EQ(3, snd_mixer_selem_has_capture_volume_called); 1453 EXPECT_EQ(3, snd_mixer_selem_has_capture_switch_called); 1454 EXPECT_EQ(5, snd_mixer_selem_get_playback_dB_range_called); 1455 EXPECT_EQ(2, snd_mixer_selem_get_capture_dB_range_called); 1456 1457 sections_ = sections; 1458 } 1459 1460 virtual void TearDown() { 1461 ucm_section_free_list(sections_); 1462 cras_alsa_mixer_destroy(cras_mixer_); 1463 EXPECT_EQ(1, snd_mixer_close_called); 1464 } 1465 1466 static void Callback(struct mixer_control *control, void *arg) { 1467 callback_called_++; 1468 callback_values_.push_back(control); 1469 } 1470 1471 struct cras_alsa_mixer *cras_mixer_; 1472 static size_t callback_called_; 1473 static std::vector<struct mixer_control *> callback_values_; 1474 struct ucm_section *sections_; 1475 }; 1476 1477 size_t AlsaMixerFullySpeced::callback_called_; 1478 std::vector<struct mixer_control *> AlsaMixerFullySpeced::callback_values_; 1479 1480 TEST_F(AlsaMixerFullySpeced, CheckControlCounts) { 1481 cras_alsa_mixer_list_outputs(cras_mixer_, 1482 AlsaMixerFullySpeced::Callback, 1483 reinterpret_cast<void*>(555)); 1484 EXPECT_EQ(3, callback_called_); 1485 callback_called_ = 0; 1486 cras_alsa_mixer_list_inputs(cras_mixer_, 1487 AlsaMixerFullySpeced::Callback, 1488 reinterpret_cast<void*>(555)); 1489 EXPECT_EQ(2, callback_called_); 1490 } 1491 1492 TEST_F(AlsaMixerFullySpeced, CheckFindOutputByNameNoMatch) { 1493 struct mixer_control *out; 1494 1495 out = cras_alsa_mixer_get_output_matching_name(cras_mixer_, 1496 "AAAAA Jack"); 1497 EXPECT_EQ(static_cast<struct mixer_control *>(NULL), out); 1498 } 1499 1500 TEST_F(AlsaMixerFullySpeced, CheckFindOutputByName) { 1501 struct mixer_control *out; 1502 1503 out = cras_alsa_mixer_get_output_matching_name(cras_mixer_, 1504 "Headphone Jack"); 1505 EXPECT_NE(static_cast<struct mixer_control *>(NULL), out); 1506 } 1507 1508 TEST_F(AlsaMixerFullySpeced, CheckFindControlForSection) { 1509 struct mixer_control *control; 1510 struct ucm_section *section = sections_; 1511 1512 // Look for the control for the Headphone section. 1513 // We've already asserted that section != NULL above. 1514 // Matching the control created by CoupledMixers. 1515 section = section->next; 1516 control = cras_alsa_mixer_get_control_for_section(cras_mixer_, section); 1517 ASSERT_NE(static_cast<struct mixer_control *>(NULL), control); 1518 EXPECT_EQ(0, strcmp(control->name, "Headphone")); 1519 1520 // Look for the control for the Mic section. 1521 // Matching the control created by MixerName. 1522 section = section->next->next; 1523 control = cras_alsa_mixer_get_control_for_section(cras_mixer_, section); 1524 ASSERT_NE(static_cast<struct mixer_control *>(NULL), control); 1525 EXPECT_EQ(0, strcmp(control->name, "CAPTURE")); 1526 } 1527 1528 /* Stubs */ 1529 1530 extern "C" { 1531 int snd_mixer_open(snd_mixer_t **mixer, int mode) { 1532 snd_mixer_open_called++; 1533 *mixer = reinterpret_cast<snd_mixer_t *>(2); 1534 return snd_mixer_open_return_value; 1535 } 1536 int snd_mixer_attach(snd_mixer_t *mixer, const char *name) { 1537 snd_mixer_attach_called++; 1538 snd_mixer_attach_mixdev = name; 1539 return snd_mixer_attach_return_value; 1540 } 1541 int snd_mixer_selem_register(snd_mixer_t *mixer, 1542 struct snd_mixer_selem_regopt *options, 1543 snd_mixer_class_t **classp) { 1544 snd_mixer_selem_register_called++; 1545 return snd_mixer_selem_register_return_value; 1546 } 1547 int snd_mixer_load(snd_mixer_t *mixer) { 1548 snd_mixer_load_called++; 1549 return snd_mixer_load_return_value; 1550 } 1551 const char *snd_mixer_selem_get_name(snd_mixer_elem_t *elem) { 1552 int index = reinterpret_cast<size_t>(elem) - 1; 1553 snd_mixer_selem_get_name_called++; 1554 if (index >= snd_mixer_selem_get_name_return_values_length) 1555 return static_cast<char *>(NULL); 1556 1557 return snd_mixer_selem_get_name_return_values[index]; 1558 } 1559 unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem) { 1560 return 0; 1561 } 1562 int snd_mixer_selem_has_playback_volume(snd_mixer_elem_t *elem) { 1563 int index = reinterpret_cast<size_t>(elem) - 1; 1564 snd_mixer_selem_has_playback_volume_called++; 1565 if (index >= snd_mixer_selem_has_playback_volume_return_values_length) 1566 return -1; 1567 1568 return snd_mixer_selem_has_playback_volume_return_values[index]; 1569 } 1570 int snd_mixer_selem_has_playback_switch(snd_mixer_elem_t *elem) { 1571 int index = reinterpret_cast<size_t>(elem) - 1; 1572 snd_mixer_selem_has_playback_switch_called++; 1573 if (index >= snd_mixer_selem_has_playback_switch_return_values_length) 1574 return -1; 1575 1576 return snd_mixer_selem_has_playback_switch_return_values[index]; 1577 } 1578 int snd_mixer_selem_has_capture_volume(snd_mixer_elem_t *elem) { 1579 int index = reinterpret_cast<size_t>(elem) - 1; 1580 snd_mixer_selem_has_capture_volume_called++; 1581 if (index >= snd_mixer_selem_has_capture_volume_return_values_length) 1582 return -1; 1583 1584 return snd_mixer_selem_has_capture_volume_return_values[index]; 1585 } 1586 int snd_mixer_selem_has_capture_switch(snd_mixer_elem_t *elem) { 1587 int index = reinterpret_cast<size_t>(elem) - 1; 1588 snd_mixer_selem_has_capture_switch_called++; 1589 if (index >= snd_mixer_selem_has_capture_switch_return_values_length) 1590 return -1; 1591 1592 return snd_mixer_selem_has_capture_switch_return_values[index]; 1593 } 1594 snd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer) { 1595 snd_mixer_first_elem_called++; 1596 return snd_mixer_first_elem_return_value; 1597 } 1598 snd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem) { 1599 snd_mixer_elem_next_called++; 1600 if (snd_mixer_elem_next_return_values_index >= 1601 snd_mixer_elem_next_return_values_length) 1602 return static_cast<snd_mixer_elem_t *>(NULL); 1603 1604 return snd_mixer_elem_next_return_values[ 1605 snd_mixer_elem_next_return_values_index++]; 1606 } 1607 int snd_mixer_close(snd_mixer_t *mixer) { 1608 snd_mixer_close_called++; 1609 return 0; 1610 } 1611 int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *elem, 1612 long value, 1613 int dir) { 1614 int index = reinterpret_cast<size_t>(elem) - 1; 1615 snd_mixer_selem_set_playback_dB_all_called++; 1616 if (index < snd_mixer_selem_set_playback_dB_all_values_length) 1617 snd_mixer_selem_set_playback_dB_all_values[index] = value; 1618 return 0; 1619 } 1620 int snd_mixer_selem_get_playback_dB(snd_mixer_elem_t *elem, 1621 snd_mixer_selem_channel_id_t channel, 1622 long *value) { 1623 int index = reinterpret_cast<size_t>(elem) - 1; 1624 snd_mixer_selem_get_playback_dB_called++; 1625 if (index >= snd_mixer_selem_get_playback_dB_return_values_length) 1626 *value = 0; 1627 else 1628 *value = snd_mixer_selem_get_playback_dB_return_values[index]; 1629 return 0; 1630 } 1631 int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t *elem, int value) { 1632 snd_mixer_selem_set_playback_switch_all_called++; 1633 snd_mixer_selem_set_playback_switch_all_value = value; 1634 return 0; 1635 } 1636 int snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t *elem, 1637 long value, 1638 int dir) { 1639 int index = reinterpret_cast<size_t>(elem) - 1; 1640 snd_mixer_selem_set_capture_dB_all_called++; 1641 if (index < snd_mixer_selem_set_capture_dB_all_values_length) 1642 snd_mixer_selem_set_capture_dB_all_values[index] = value; 1643 return 0; 1644 } 1645 int snd_mixer_selem_get_capture_dB(snd_mixer_elem_t *elem, 1646 snd_mixer_selem_channel_id_t channel, 1647 long *value) { 1648 int index = reinterpret_cast<size_t>(elem) - 1; 1649 snd_mixer_selem_get_capture_dB_called++; 1650 if (index >= snd_mixer_selem_get_capture_dB_return_values_length) 1651 *value = 0; 1652 else 1653 *value = snd_mixer_selem_get_capture_dB_return_values[index]; 1654 return 0; 1655 } 1656 int snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t *elem, int value) { 1657 snd_mixer_selem_set_capture_switch_all_called++; 1658 snd_mixer_selem_set_capture_switch_all_value = value; 1659 return 0; 1660 } 1661 int snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t *elem, long *min, 1662 long *max) { 1663 size_t index = reinterpret_cast<size_t>(elem) - 1; 1664 snd_mixer_selem_get_capture_dB_range_called++; 1665 if (index >= snd_mixer_selem_get_capture_dB_range_values_length) { 1666 *min = 0; 1667 *max = 0; 1668 } else { 1669 *min = snd_mixer_selem_get_capture_dB_range_min_values[index]; 1670 *max = snd_mixer_selem_get_capture_dB_range_max_values[index]; 1671 } 1672 return 0; 1673 } 1674 int snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t *elem, 1675 long *min, 1676 long *max) { 1677 size_t index = reinterpret_cast<size_t>(elem) - 1; 1678 snd_mixer_selem_get_playback_dB_range_called++; 1679 if (index >= snd_mixer_selem_get_playback_dB_range_values_length) { 1680 *min = 0; 1681 *max = 0; 1682 } else { 1683 *min = snd_mixer_selem_get_playback_dB_range_min_values[index]; 1684 *max = snd_mixer_selem_get_playback_dB_range_max_values[index]; 1685 } 1686 return 0; 1687 } 1688 1689 snd_mixer_elem_t *snd_mixer_find_selem( 1690 snd_mixer_t *mixer, const snd_mixer_selem_id_t *id) { 1691 std::string name(snd_mixer_selem_id_get_name(id)); 1692 unsigned int index = snd_mixer_selem_id_get_index(id); 1693 snd_mixer_find_selem_called++; 1694 if (index != 0) 1695 return NULL; 1696 if (snd_mixer_find_elem_map.find(name) == snd_mixer_find_elem_map.end()) { 1697 return NULL; 1698 } 1699 return snd_mixer_find_elem_map[name]; 1700 } 1701 1702 // From cras_volume_curve. 1703 static long get_dBFS_default(const struct cras_volume_curve *curve, 1704 size_t volume) 1705 { 1706 return 100 * (volume - 100); 1707 } 1708 1709 struct cras_volume_curve *cras_volume_curve_create_default() 1710 { 1711 struct cras_volume_curve *curve; 1712 curve = (struct cras_volume_curve *)calloc(1, sizeof(*curve)); 1713 if (curve) 1714 curve->get_dBFS = get_dBFS_default; 1715 return curve; 1716 } 1717 1718 void cras_volume_curve_destroy(struct cras_volume_curve *curve) 1719 { 1720 cras_volume_curve_destroy_called++; 1721 free(curve); 1722 } 1723 1724 // From libiniparser. 1725 struct cras_volume_curve *cras_card_config_get_volume_curve_for_control( 1726 const struct cras_card_config *card_config, 1727 const char *control_name) 1728 { 1729 struct cras_volume_curve *curve; 1730 curve = (struct cras_volume_curve *)calloc(1, sizeof(*curve)); 1731 if (curve != NULL) 1732 curve->get_dBFS = get_dBFS_default; 1733 return curve; 1734 } 1735 1736 } /* extern "C" */ 1737 1738 } // namespace 1739 1740 int main(int argc, char **argv) { 1741 ::testing::InitGoogleTest(&argc, argv); 1742 openlog(NULL, LOG_PERROR, LOG_USER); 1743 return RUN_ALL_TESTS(); 1744 } 1745