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,CreateOneMasterElement)384 TEST(AlsaMixer, CreateOneMasterElement) {
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 Master. */
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 Master. */
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 Master 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 Master and PCM. If Master 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 Master 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 Master, PCM, and the mixer_output passed
561 * in. If Master 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 Master and PCM. Since the controls were
570 * sorted, Master 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]); // Master
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 Master 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); // Master
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 =
1279 ucm_section_create("NullElement", 0, CRAS_STREAM_OUTPUT, NULL, NULL);
1280 ucm_section_set_mixer_name(section, "Unknown");
1281 DL_APPEND(sections, section);
1282 section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT,
1283 "my-sound-card Headset Jack", "gpio");
1284 ucm_section_add_coupled(section, "HP-L", MIXER_NAME_VOLUME);
1285 ucm_section_add_coupled(section, "HP-R", MIXER_NAME_VOLUME);
1286 DL_APPEND(sections, section);
1287 section = ucm_section_create("Speaker", 0, CRAS_STREAM_OUTPUT, NULL, NULL);
1288 ucm_section_add_coupled(section, "SPK-L", MIXER_NAME_VOLUME);
1289 ucm_section_add_coupled(section, "SPK-R", MIXER_NAME_VOLUME);
1290 DL_APPEND(sections, section);
1291 section = ucm_section_create("Mic", 0, CRAS_STREAM_INPUT,
1292 "my-sound-card Headset Jack", "gpio");
1293 ucm_section_set_mixer_name(section, "CAPTURE");
1294 DL_APPEND(sections, section);
1295 section =
1296 ucm_section_create("Internal Mic", 0, CRAS_STREAM_INPUT, NULL, NULL);
1297 ucm_section_add_coupled(section, "MIC-L", MIXER_NAME_VOLUME);
1298 ucm_section_add_coupled(section, "MIC-R", MIXER_NAME_VOLUME);
1299 DL_APPEND(sections, section);
1300 section = ucm_section_create("HDMI", 0, CRAS_STREAM_OUTPUT, NULL, NULL);
1301 ucm_section_set_mixer_name(section, "HDMI");
1302 DL_APPEND(sections, section);
1303 ASSERT_NE(sections, (struct ucm_section*)NULL);
1304
1305 snd_mixer_selem_has_playback_volume_return_values = element_playback_volume;
1306 snd_mixer_selem_has_playback_volume_return_values_length =
1307 ARRAY_SIZE(element_playback_volume);
1308 snd_mixer_selem_has_playback_switch_return_values =
1309 element_playback_switches;
1310 snd_mixer_selem_has_playback_switch_return_values_length =
1311 ARRAY_SIZE(element_playback_switches);
1312 snd_mixer_selem_has_capture_volume_return_values = element_capture_volume;
1313 snd_mixer_selem_has_capture_volume_return_values_length =
1314 ARRAY_SIZE(element_capture_volume);
1315 snd_mixer_selem_has_capture_switch_return_values = element_capture_switches;
1316 snd_mixer_selem_has_capture_switch_return_values_length =
1317 ARRAY_SIZE(element_capture_switches);
1318 snd_mixer_selem_get_name_return_values = element_names;
1319 snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
1320 snd_mixer_selem_get_capture_dB_range_min_values = min_volumes;
1321 snd_mixer_selem_get_capture_dB_range_max_values = max_volumes;
1322 snd_mixer_selem_get_capture_dB_range_values_length =
1323 ARRAY_SIZE(min_volumes);
1324
1325 cras_mixer_ = cras_alsa_mixer_create("hw:0");
1326 ASSERT_NE(static_cast<struct cras_alsa_mixer*>(NULL), cras_mixer_);
1327 EXPECT_EQ(1, snd_mixer_open_called);
1328 EXPECT_EQ(1, snd_mixer_attach_called);
1329 EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
1330 EXPECT_EQ(1, snd_mixer_selem_register_called);
1331 EXPECT_EQ(1, snd_mixer_load_called);
1332 EXPECT_EQ(0, snd_mixer_close_called);
1333
1334 section = sections;
1335 EXPECT_EQ(-ENOENT,
1336 cras_alsa_mixer_add_controls_in_section(cras_mixer_, section));
1337 ASSERT_NE((struct ucm_section*)NULL, section->next);
1338 section = section->next;
1339 EXPECT_EQ(0, 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 EXPECT_EQ(section->next, (struct ucm_section*)NULL);
1353
1354 EXPECT_EQ(9, snd_mixer_find_selem_called);
1355 EXPECT_EQ(5, snd_mixer_selem_has_playback_volume_called);
1356 EXPECT_EQ(5, snd_mixer_selem_has_playback_switch_called);
1357 EXPECT_EQ(3, snd_mixer_selem_has_capture_volume_called);
1358 EXPECT_EQ(3, snd_mixer_selem_has_capture_switch_called);
1359 EXPECT_EQ(5, snd_mixer_selem_get_playback_dB_range_called);
1360 EXPECT_EQ(2, snd_mixer_selem_get_capture_dB_range_called);
1361
1362 sections_ = sections;
1363 }
1364
TearDown()1365 virtual void TearDown() {
1366 ucm_section_free_list(sections_);
1367 cras_alsa_mixer_destroy(cras_mixer_);
1368 EXPECT_EQ(1, snd_mixer_close_called);
1369 }
1370
Callback(struct mixer_control * control,void * arg)1371 static void Callback(struct mixer_control* control, void* arg) {
1372 callback_called_++;
1373 callback_values_.push_back(control);
1374 }
1375
1376 struct cras_alsa_mixer* cras_mixer_;
1377 static size_t callback_called_;
1378 static std::vector<struct mixer_control*> callback_values_;
1379 struct ucm_section* sections_;
1380 };
1381
1382 size_t AlsaMixerFullySpeced::callback_called_;
1383 std::vector<struct mixer_control*> AlsaMixerFullySpeced::callback_values_;
1384
TEST_F(AlsaMixerFullySpeced,CheckControlCounts)1385 TEST_F(AlsaMixerFullySpeced, CheckControlCounts) {
1386 cras_alsa_mixer_list_outputs(cras_mixer_, AlsaMixerFullySpeced::Callback,
1387 reinterpret_cast<void*>(555));
1388 EXPECT_EQ(3, callback_called_);
1389 callback_called_ = 0;
1390 cras_alsa_mixer_list_inputs(cras_mixer_, AlsaMixerFullySpeced::Callback,
1391 reinterpret_cast<void*>(555));
1392 EXPECT_EQ(2, callback_called_);
1393 }
1394
TEST_F(AlsaMixerFullySpeced,CheckFindOutputByNameNoMatch)1395 TEST_F(AlsaMixerFullySpeced, CheckFindOutputByNameNoMatch) {
1396 struct mixer_control* out;
1397
1398 out = cras_alsa_mixer_get_output_matching_name(cras_mixer_, "AAAAA Jack");
1399 EXPECT_EQ(static_cast<struct mixer_control*>(NULL), out);
1400 }
1401
TEST_F(AlsaMixerFullySpeced,CheckFindOutputByName)1402 TEST_F(AlsaMixerFullySpeced, CheckFindOutputByName) {
1403 struct mixer_control* out;
1404
1405 out = cras_alsa_mixer_get_output_matching_name(cras_mixer_, "Headphone Jack");
1406 EXPECT_NE(static_cast<struct mixer_control*>(NULL), out);
1407 }
1408
TEST_F(AlsaMixerFullySpeced,CheckFindControlForSection)1409 TEST_F(AlsaMixerFullySpeced, CheckFindControlForSection) {
1410 struct mixer_control* control;
1411 struct ucm_section* section = sections_;
1412
1413 // Look for the control for the Headphone section.
1414 // We've already asserted that section != NULL above.
1415 // Matching the control created by CoupledMixers.
1416 section = section->next;
1417 control = cras_alsa_mixer_get_control_for_section(cras_mixer_, section);
1418 ASSERT_NE(static_cast<struct mixer_control*>(NULL), control);
1419 EXPECT_EQ(0, strcmp(control->name, "Headphone"));
1420
1421 // Look for the control for the Mic section.
1422 // Matching the control created by MixerName.
1423 section = section->next->next;
1424 control = cras_alsa_mixer_get_control_for_section(cras_mixer_, section);
1425 ASSERT_NE(static_cast<struct mixer_control*>(NULL), control);
1426 EXPECT_EQ(0, strcmp(control->name, "CAPTURE"));
1427 }
1428
1429 /* Stubs */
1430
1431 extern "C" {
snd_mixer_open(snd_mixer_t ** mixer,int mode)1432 int snd_mixer_open(snd_mixer_t** mixer, int mode) {
1433 snd_mixer_open_called++;
1434 *mixer = reinterpret_cast<snd_mixer_t*>(2);
1435 return snd_mixer_open_return_value;
1436 }
snd_mixer_attach(snd_mixer_t * mixer,const char * name)1437 int snd_mixer_attach(snd_mixer_t* mixer, const char* name) {
1438 snd_mixer_attach_called++;
1439 snd_mixer_attach_mixdev = name;
1440 return snd_mixer_attach_return_value;
1441 }
snd_mixer_selem_register(snd_mixer_t * mixer,struct snd_mixer_selem_regopt * options,snd_mixer_class_t ** classp)1442 int snd_mixer_selem_register(snd_mixer_t* mixer,
1443 struct snd_mixer_selem_regopt* options,
1444 snd_mixer_class_t** classp) {
1445 snd_mixer_selem_register_called++;
1446 return snd_mixer_selem_register_return_value;
1447 }
snd_mixer_load(snd_mixer_t * mixer)1448 int snd_mixer_load(snd_mixer_t* mixer) {
1449 snd_mixer_load_called++;
1450 return snd_mixer_load_return_value;
1451 }
snd_mixer_selem_get_name(snd_mixer_elem_t * elem)1452 const char* snd_mixer_selem_get_name(snd_mixer_elem_t* elem) {
1453 int index = reinterpret_cast<size_t>(elem) - 1;
1454 snd_mixer_selem_get_name_called++;
1455 if (index >= snd_mixer_selem_get_name_return_values_length)
1456 return static_cast<char*>(NULL);
1457
1458 return snd_mixer_selem_get_name_return_values[index];
1459 }
snd_mixer_selem_get_index(snd_mixer_elem_t * elem)1460 unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t* elem) {
1461 return 0;
1462 }
snd_mixer_selem_has_playback_volume(snd_mixer_elem_t * elem)1463 int snd_mixer_selem_has_playback_volume(snd_mixer_elem_t* elem) {
1464 int index = reinterpret_cast<size_t>(elem) - 1;
1465 snd_mixer_selem_has_playback_volume_called++;
1466 if (index >= snd_mixer_selem_has_playback_volume_return_values_length)
1467 return -1;
1468
1469 return snd_mixer_selem_has_playback_volume_return_values[index];
1470 }
snd_mixer_selem_has_playback_switch(snd_mixer_elem_t * elem)1471 int snd_mixer_selem_has_playback_switch(snd_mixer_elem_t* elem) {
1472 int index = reinterpret_cast<size_t>(elem) - 1;
1473 snd_mixer_selem_has_playback_switch_called++;
1474 if (index >= snd_mixer_selem_has_playback_switch_return_values_length)
1475 return -1;
1476
1477 return snd_mixer_selem_has_playback_switch_return_values[index];
1478 }
snd_mixer_selem_has_capture_volume(snd_mixer_elem_t * elem)1479 int snd_mixer_selem_has_capture_volume(snd_mixer_elem_t* elem) {
1480 int index = reinterpret_cast<size_t>(elem) - 1;
1481 snd_mixer_selem_has_capture_volume_called++;
1482 if (index >= snd_mixer_selem_has_capture_volume_return_values_length)
1483 return -1;
1484
1485 return snd_mixer_selem_has_capture_volume_return_values[index];
1486 }
snd_mixer_selem_has_capture_switch(snd_mixer_elem_t * elem)1487 int snd_mixer_selem_has_capture_switch(snd_mixer_elem_t* elem) {
1488 int index = reinterpret_cast<size_t>(elem) - 1;
1489 snd_mixer_selem_has_capture_switch_called++;
1490 if (index >= snd_mixer_selem_has_capture_switch_return_values_length)
1491 return -1;
1492
1493 return snd_mixer_selem_has_capture_switch_return_values[index];
1494 }
snd_mixer_first_elem(snd_mixer_t * mixer)1495 snd_mixer_elem_t* snd_mixer_first_elem(snd_mixer_t* mixer) {
1496 snd_mixer_first_elem_called++;
1497 return snd_mixer_first_elem_return_value;
1498 }
snd_mixer_elem_next(snd_mixer_elem_t * elem)1499 snd_mixer_elem_t* snd_mixer_elem_next(snd_mixer_elem_t* elem) {
1500 snd_mixer_elem_next_called++;
1501 if (snd_mixer_elem_next_return_values_index >=
1502 snd_mixer_elem_next_return_values_length)
1503 return static_cast<snd_mixer_elem_t*>(NULL);
1504
1505 return snd_mixer_elem_next_return_values
1506 [snd_mixer_elem_next_return_values_index++];
1507 }
snd_mixer_close(snd_mixer_t * mixer)1508 int snd_mixer_close(snd_mixer_t* mixer) {
1509 snd_mixer_close_called++;
1510 return 0;
1511 }
snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t * elem,long value,int dir)1512 int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t* elem,
1513 long value,
1514 int dir) {
1515 int index = reinterpret_cast<size_t>(elem) - 1;
1516 snd_mixer_selem_set_playback_dB_all_called++;
1517 if (index < snd_mixer_selem_set_playback_dB_all_values_length)
1518 snd_mixer_selem_set_playback_dB_all_values[index] = value;
1519 return 0;
1520 }
snd_mixer_selem_get_playback_dB(snd_mixer_elem_t * elem,snd_mixer_selem_channel_id_t channel,long * value)1521 int snd_mixer_selem_get_playback_dB(snd_mixer_elem_t* elem,
1522 snd_mixer_selem_channel_id_t channel,
1523 long* value) {
1524 int index = reinterpret_cast<size_t>(elem) - 1;
1525 snd_mixer_selem_get_playback_dB_called++;
1526 if (index >= snd_mixer_selem_get_playback_dB_return_values_length)
1527 *value = 0;
1528 else
1529 *value = snd_mixer_selem_get_playback_dB_return_values[index];
1530 return 0;
1531 }
snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t * elem,int value)1532 int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t* elem, int value) {
1533 snd_mixer_selem_set_playback_switch_all_called++;
1534 snd_mixer_selem_set_playback_switch_all_value = value;
1535 return 0;
1536 }
snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t * elem,long value,int dir)1537 int snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t* elem,
1538 long value,
1539 int dir) {
1540 int index = reinterpret_cast<size_t>(elem) - 1;
1541 snd_mixer_selem_set_capture_dB_all_called++;
1542 if (index < snd_mixer_selem_set_capture_dB_all_values_length)
1543 snd_mixer_selem_set_capture_dB_all_values[index] = value;
1544 return 0;
1545 }
snd_mixer_selem_get_capture_dB(snd_mixer_elem_t * elem,snd_mixer_selem_channel_id_t channel,long * value)1546 int snd_mixer_selem_get_capture_dB(snd_mixer_elem_t* elem,
1547 snd_mixer_selem_channel_id_t channel,
1548 long* value) {
1549 int index = reinterpret_cast<size_t>(elem) - 1;
1550 snd_mixer_selem_get_capture_dB_called++;
1551 if (index >= snd_mixer_selem_get_capture_dB_return_values_length)
1552 *value = 0;
1553 else
1554 *value = snd_mixer_selem_get_capture_dB_return_values[index];
1555 return 0;
1556 }
snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t * elem,int value)1557 int snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t* elem, int value) {
1558 snd_mixer_selem_set_capture_switch_all_called++;
1559 snd_mixer_selem_set_capture_switch_all_value = value;
1560 return 0;
1561 }
snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t * elem,long * min,long * max)1562 int snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t* elem,
1563 long* min,
1564 long* max) {
1565 size_t index = reinterpret_cast<size_t>(elem) - 1;
1566 snd_mixer_selem_get_capture_dB_range_called++;
1567 if (index >= snd_mixer_selem_get_capture_dB_range_values_length) {
1568 *min = 0;
1569 *max = 0;
1570 } else {
1571 *min = snd_mixer_selem_get_capture_dB_range_min_values[index];
1572 *max = snd_mixer_selem_get_capture_dB_range_max_values[index];
1573 }
1574 return 0;
1575 }
snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t * elem,long * min,long * max)1576 int snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t* elem,
1577 long* min,
1578 long* max) {
1579 size_t index = reinterpret_cast<size_t>(elem) - 1;
1580 snd_mixer_selem_get_playback_dB_range_called++;
1581 if (index >= snd_mixer_selem_get_playback_dB_range_values_length) {
1582 *min = 0;
1583 *max = 0;
1584 } else {
1585 *min = snd_mixer_selem_get_playback_dB_range_min_values[index];
1586 *max = snd_mixer_selem_get_playback_dB_range_max_values[index];
1587 }
1588 return 0;
1589 }
1590
snd_mixer_find_selem(snd_mixer_t * mixer,const snd_mixer_selem_id_t * id)1591 snd_mixer_elem_t* snd_mixer_find_selem(snd_mixer_t* mixer,
1592 const snd_mixer_selem_id_t* id) {
1593 std::string name(snd_mixer_selem_id_get_name(id));
1594 unsigned int index = snd_mixer_selem_id_get_index(id);
1595 snd_mixer_find_selem_called++;
1596 if (index != 0)
1597 return NULL;
1598 if (snd_mixer_find_elem_map.find(name) == snd_mixer_find_elem_map.end()) {
1599 return NULL;
1600 }
1601 return snd_mixer_find_elem_map[name];
1602 }
1603
1604 // From cras_volume_curve.
get_dBFS_default(const struct cras_volume_curve * curve,size_t volume)1605 static long get_dBFS_default(const struct cras_volume_curve* curve,
1606 size_t volume) {
1607 return 100 * (volume - 100);
1608 }
1609
cras_volume_curve_create_default()1610 struct cras_volume_curve* cras_volume_curve_create_default() {
1611 struct cras_volume_curve* curve;
1612 curve = (struct cras_volume_curve*)calloc(1, sizeof(*curve));
1613 if (curve)
1614 curve->get_dBFS = get_dBFS_default;
1615 return curve;
1616 }
1617
cras_volume_curve_destroy(struct cras_volume_curve * curve)1618 void cras_volume_curve_destroy(struct cras_volume_curve* curve) {
1619 cras_volume_curve_destroy_called++;
1620 free(curve);
1621 }
1622
1623 // From libiniparser.
cras_card_config_get_volume_curve_for_control(const struct cras_card_config * card_config,const char * control_name)1624 struct cras_volume_curve* cras_card_config_get_volume_curve_for_control(
1625 const struct cras_card_config* card_config,
1626 const char* control_name) {
1627 struct cras_volume_curve* curve;
1628 curve = (struct cras_volume_curve*)calloc(1, sizeof(*curve));
1629 if (curve != NULL)
1630 curve->get_dBFS = get_dBFS_default;
1631 return curve;
1632 }
1633
1634 } /* extern "C" */
1635
1636 } // namespace
1637
main(int argc,char ** argv)1638 int main(int argc, char** argv) {
1639 ::testing::InitGoogleTest(&argc, argv);
1640 openlog(NULL, LOG_PERROR, LOG_USER);
1641 return RUN_ALL_TESTS();
1642 }
1643