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