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
ResetStubData()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
create_mixer_and_add_controls_by_name_matching(const char * card_name,struct mixer_name * extra_controls,struct mixer_name * coupled_controls)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
TEST(AlsaMixer,CreateFailOpen)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
TEST(AlsaMixer,CreateFailAttach)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
TEST(AlsaMixer,CreateFailSelemRegister)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
TEST(AlsaMixer,CreateFailLoad)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
TEST(AlsaMixer,CreateNoElements)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
TEST(AlsaMixer,CreateOneUnknownElementWithoutVolume)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
TEST(AlsaMixer,CreateOneUnknownElementWithVolume)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
TEST(AlsaMixer,CreateOneMasterElement)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
TEST(AlsaMixer,CreateTwoMainVolumeElements)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
TEST(AlsaMixer,CreateTwoMainCaptureElements)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:
SetUp()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
TearDown()854 virtual void TearDown() {
855 cras_alsa_mixer_destroy(cras_mixer_);
856 EXPECT_EQ(1, snd_mixer_close_called);
857 }
858
OutputCallback(struct mixer_control * out,void * arg)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
TEST_F(AlsaMixerOutputs,CheckFourOutputs)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
TEST_F(AlsaMixerOutputs,CheckFindOutputByNameNoMatch)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
TEST_F(AlsaMixerOutputs,CheckFindOutputByName)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
TEST_F(AlsaMixerOutputs,CheckFindOutputHDMIByName)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
TEST_F(AlsaMixerOutputs,CheckFindInputNameWorkaround)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
TEST_F(AlsaMixerOutputs,ActivateDeactivate)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
TEST_F(AlsaMixerOutputs,MinMaxCaptureGain)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
TEST_F(AlsaMixerOutputs,MinMaxCaptureGainWithActiveInput)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
TEST(AlsaMixer,CreateWithCoupledOutputControls)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
TEST(AlsaMixer,CoupledOutputHasMuteNoVolume)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
TEST(AlsaMixer,CoupledOutputHasVolumeNoMute)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
TEST(AlsaMixer,MixerName)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:
SetUp()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
TearDown()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
Callback(struct mixer_control * control,void * arg)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
TEST_F(AlsaMixerFullySpeced,CheckControlCounts)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
TEST_F(AlsaMixerFullySpeced,CheckFindOutputByNameNoMatch)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
TEST_F(AlsaMixerFullySpeced,CheckFindOutputByName)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
TEST_F(AlsaMixerFullySpeced,CheckFindControlForSection)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" {
snd_mixer_open(snd_mixer_t ** mixer,int mode)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 }
snd_mixer_attach(snd_mixer_t * mixer,const char * name)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 }
snd_mixer_selem_register(snd_mixer_t * mixer,struct snd_mixer_selem_regopt * options,snd_mixer_class_t ** classp)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 }
snd_mixer_load(snd_mixer_t * mixer)1547 int snd_mixer_load(snd_mixer_t *mixer) {
1548 snd_mixer_load_called++;
1549 return snd_mixer_load_return_value;
1550 }
snd_mixer_selem_get_name(snd_mixer_elem_t * elem)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 }
snd_mixer_selem_get_index(snd_mixer_elem_t * elem)1559 unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem) {
1560 return 0;
1561 }
snd_mixer_selem_has_playback_volume(snd_mixer_elem_t * elem)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 }
snd_mixer_selem_has_playback_switch(snd_mixer_elem_t * elem)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 }
snd_mixer_selem_has_capture_volume(snd_mixer_elem_t * elem)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 }
snd_mixer_selem_has_capture_switch(snd_mixer_elem_t * elem)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 }
snd_mixer_first_elem(snd_mixer_t * mixer)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 }
snd_mixer_elem_next(snd_mixer_elem_t * elem)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 }
snd_mixer_close(snd_mixer_t * mixer)1607 int snd_mixer_close(snd_mixer_t *mixer) {
1608 snd_mixer_close_called++;
1609 return 0;
1610 }
snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t * elem,long value,int dir)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 }
snd_mixer_selem_get_playback_dB(snd_mixer_elem_t * elem,snd_mixer_selem_channel_id_t channel,long * value)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 }
snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t * elem,int value)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 }
snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t * elem,long value,int dir)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 }
snd_mixer_selem_get_capture_dB(snd_mixer_elem_t * elem,snd_mixer_selem_channel_id_t channel,long * value)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 }
snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t * elem,int value)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 }
snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t * elem,long * min,long * max)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 }
snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t * elem,long * min,long * max)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
snd_mixer_find_selem(snd_mixer_t * mixer,const snd_mixer_selem_id_t * id)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.
get_dBFS_default(const struct cras_volume_curve * curve,size_t volume)1703 static long get_dBFS_default(const struct cras_volume_curve *curve,
1704 size_t volume)
1705 {
1706 return 100 * (volume - 100);
1707 }
1708
cras_volume_curve_create_default()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
cras_volume_curve_destroy(struct cras_volume_curve * curve)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.
cras_card_config_get_volume_curve_for_control(const struct cras_card_config * card_config,const char * control_name)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
main(int argc,char ** argv)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