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 cras_alsa_mixer_destroy(c);
171 }
172
TEST(AlsaMixer,CreateFailAttach)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
TEST(AlsaMixer,CreateFailSelemRegister)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
TEST(AlsaMixer,CreateFailLoad)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
TEST(AlsaMixer,CreateNoElements)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
TEST(AlsaMixer,CreateOneUnknownElementWithoutVolume)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
TEST(AlsaMixer,CreateOneUnknownElementWithVolume)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
TEST(AlsaMixer,CreateOneMasterElement)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
TEST(AlsaMixer,CreateTwoMainVolumeElements)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
TEST(AlsaMixer,CreateTwoMainCaptureElements)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:
SetUp()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
TearDown()858 virtual void TearDown() {
859 cras_alsa_mixer_destroy(cras_mixer_);
860 EXPECT_EQ(1, snd_mixer_close_called);
861 }
862
OutputCallback(struct mixer_control * out,void * arg)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
TEST_F(AlsaMixerOutputs,CheckFourOutputs)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
TEST_F(AlsaMixerOutputs,CheckFindOutputByNameNoMatch)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
TEST_F(AlsaMixerOutputs,CheckFindOutputByName)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
TEST_F(AlsaMixerOutputs,CheckFindOutputHDMIByName)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
TEST_F(AlsaMixerOutputs,CheckFindInputNameWorkaround)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
TEST_F(AlsaMixerOutputs,ActivateDeactivate)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
TEST_F(AlsaMixerOutputs,MinMaxCaptureGain)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
TEST_F(AlsaMixerOutputs,MinMaxCaptureGainWithActiveInput)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
TEST(AlsaMixer,CreateWithCoupledOutputControls)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
TEST(AlsaMixer,CoupledOutputHasMuteNoVolume)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
TEST(AlsaMixer,CoupledOutputHasVolumeNoMute)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
TEST(AlsaMixer,MixerName)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:
SetUp()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
TearDown()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
Callback(struct mixer_control * control,void * arg)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
TEST_F(AlsaMixerFullySpeced,CheckControlCounts)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
TEST_F(AlsaMixerFullySpeced,CheckFindOutputByNameNoMatch)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
TEST_F(AlsaMixerFullySpeced,CheckFindOutputByName)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
TEST_F(AlsaMixerFullySpeced,CheckFindControlForSection)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" {
snd_mixer_open(snd_mixer_t ** mixer,int mode)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 }
snd_mixer_attach(snd_mixer_t * mixer,const char * name)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 }
snd_mixer_selem_register(snd_mixer_t * mixer,struct snd_mixer_selem_regopt * options,snd_mixer_class_t ** classp)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 }
snd_mixer_load(snd_mixer_t * mixer)1551 int snd_mixer_load(snd_mixer_t *mixer) {
1552 snd_mixer_load_called++;
1553 return snd_mixer_load_return_value;
1554 }
snd_mixer_selem_get_name(snd_mixer_elem_t * elem)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 }
snd_mixer_selem_get_index(snd_mixer_elem_t * elem)1563 unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem) {
1564 return 0;
1565 }
snd_mixer_selem_has_playback_volume(snd_mixer_elem_t * elem)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 }
snd_mixer_selem_has_playback_switch(snd_mixer_elem_t * elem)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 }
snd_mixer_selem_has_capture_volume(snd_mixer_elem_t * elem)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 }
snd_mixer_selem_has_capture_switch(snd_mixer_elem_t * elem)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 }
snd_mixer_first_elem(snd_mixer_t * mixer)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 }
snd_mixer_elem_next(snd_mixer_elem_t * elem)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 }
snd_mixer_close(snd_mixer_t * mixer)1611 int snd_mixer_close(snd_mixer_t *mixer) {
1612 snd_mixer_close_called++;
1613 return 0;
1614 }
snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t * elem,long value,int dir)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 }
snd_mixer_selem_get_playback_dB(snd_mixer_elem_t * elem,snd_mixer_selem_channel_id_t channel,long * value)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 }
snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t * elem,int value)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 }
snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t * elem,long value,int dir)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 }
snd_mixer_selem_get_capture_dB(snd_mixer_elem_t * elem,snd_mixer_selem_channel_id_t channel,long * value)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 }
snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t * elem,int value)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 }
snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t * elem,long * min,long * max)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 }
snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t * elem,long * min,long * max)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
snd_mixer_find_selem(snd_mixer_t * mixer,const snd_mixer_selem_id_t * id)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.
get_dBFS_default(const struct cras_volume_curve * curve,size_t volume)1707 static long get_dBFS_default(const struct cras_volume_curve *curve,
1708 size_t volume)
1709 {
1710 return 100 * (volume - 100);
1711 }
1712
cras_volume_curve_create_default()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
cras_volume_curve_destroy(struct cras_volume_curve * curve)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.
cras_card_config_get_volume_curve_for_control(const struct cras_card_config * card_config,const char * control_name)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
main(int argc,char ** argv)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