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