1 /* Copyright 2016 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
6 #include "cras_observer.h"
7
8 #include "cras_alert.h"
9 #include "cras_iodev_list.h"
10 #include "cras_types.h"
11 #include "utlist.h"
12
13 struct cras_observer_client {
14 struct cras_observer_ops ops;
15 void *context;
16 struct cras_observer_client *next, *prev;
17 };
18
19 struct cras_observer_alerts {
20 struct cras_alert *output_volume;
21 struct cras_alert *output_mute;
22 struct cras_alert *capture_gain;
23 struct cras_alert *capture_mute;
24 struct cras_alert *nodes;
25 struct cras_alert *active_node;
26 struct cras_alert *output_node_volume;
27 struct cras_alert *node_left_right_swapped;
28 struct cras_alert *input_node_gain;
29 struct cras_alert *suspend_changed;
30 struct cras_alert *hotword_triggered;
31 /* If all events for active streams went through a single alert then
32 * we might miss some because the alert code does not send every
33 * alert message. To ensure that the event sent contains the correct
34 * number of active streams per direction, make the alerts
35 * per-direciton. */
36 struct cras_alert *num_active_streams[CRAS_NUM_DIRECTIONS];
37 struct cras_alert *non_empty_audio_state_changed;
38 struct cras_alert *bt_battery_changed;
39 struct cras_alert *num_input_streams_with_permission;
40 };
41
42 struct cras_observer_server {
43 struct cras_observer_alerts alerts;
44 struct cras_observer_client *clients;
45 };
46
47 struct cras_observer_alert_data_volume {
48 int32_t volume;
49 };
50
51 struct cras_observer_alert_data_mute {
52 int muted;
53 int user_muted;
54 int mute_locked;
55 };
56
57 struct cras_observer_alert_data_active_node {
58 enum CRAS_STREAM_DIRECTION direction;
59 cras_node_id_t node_id;
60 };
61
62 struct cras_observer_alert_data_node_volume {
63 cras_node_id_t node_id;
64 int32_t volume;
65 };
66
67 struct cras_observer_alert_data_node_lr_swapped {
68 cras_node_id_t node_id;
69 int swapped;
70 };
71
72 struct cras_observer_alert_data_suspend {
73 int suspended;
74 };
75
76 struct cras_observer_alert_data_streams {
77 enum CRAS_STREAM_DIRECTION direction;
78 uint32_t num_active_streams;
79 };
80
81 struct cras_observer_alert_data_input_streams {
82 uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE];
83 };
84
85 struct cras_observer_alert_data_hotword_triggered {
86 int64_t tv_sec;
87 int64_t tv_nsec;
88 };
89
90 struct cras_observer_non_empty_audio_state {
91 int non_empty;
92 };
93
94 struct cras_observer_alert_data_bt_battery_changed {
95 const char *address;
96 uint32_t level;
97 };
98
99 /* Global observer instance. */
100 static struct cras_observer_server *g_observer;
101
102 /* Empty observer ops. */
103 static struct cras_observer_ops g_empty_ops;
104
105 /*
106 * Alert handlers for delayed callbacks.
107 */
108
output_volume_alert(void * arg,void * data)109 static void output_volume_alert(void *arg, void *data)
110 {
111 struct cras_observer_client *client;
112 struct cras_observer_alert_data_volume *volume_data =
113 (struct cras_observer_alert_data_volume *)data;
114
115 DL_FOREACH (g_observer->clients, client) {
116 if (client->ops.output_volume_changed)
117 client->ops.output_volume_changed(client->context,
118 volume_data->volume);
119 }
120 }
121
output_mute_alert(void * arg,void * data)122 static void output_mute_alert(void *arg, void *data)
123 {
124 struct cras_observer_client *client;
125 struct cras_observer_alert_data_mute *mute_data =
126 (struct cras_observer_alert_data_mute *)data;
127
128 DL_FOREACH (g_observer->clients, client) {
129 if (client->ops.output_mute_changed)
130 client->ops.output_mute_changed(client->context,
131 mute_data->muted,
132 mute_data->user_muted,
133 mute_data->mute_locked);
134 }
135 }
136
capture_gain_alert(void * arg,void * data)137 static void capture_gain_alert(void *arg, void *data)
138 {
139 struct cras_observer_client *client;
140 struct cras_observer_alert_data_volume *volume_data =
141 (struct cras_observer_alert_data_volume *)data;
142
143 DL_FOREACH (g_observer->clients, client) {
144 if (client->ops.capture_gain_changed)
145 client->ops.capture_gain_changed(client->context,
146 volume_data->volume);
147 }
148 }
149
capture_mute_alert(void * arg,void * data)150 static void capture_mute_alert(void *arg, void *data)
151 {
152 struct cras_observer_client *client;
153 struct cras_observer_alert_data_mute *mute_data =
154 (struct cras_observer_alert_data_mute *)data;
155
156 DL_FOREACH (g_observer->clients, client) {
157 if (client->ops.capture_mute_changed)
158 client->ops.capture_mute_changed(
159 client->context, mute_data->muted,
160 mute_data->mute_locked);
161 }
162 }
163
nodes_prepare(struct cras_alert * alert)164 static void nodes_prepare(struct cras_alert *alert)
165 {
166 cras_iodev_list_update_device_list();
167 }
168
nodes_alert(void * arg,void * data)169 static void nodes_alert(void *arg, void *data)
170 {
171 struct cras_observer_client *client;
172
173 DL_FOREACH (g_observer->clients, client) {
174 if (client->ops.nodes_changed)
175 client->ops.nodes_changed(client->context);
176 }
177 }
178
active_node_alert(void * arg,void * data)179 static void active_node_alert(void *arg, void *data)
180 {
181 struct cras_observer_client *client;
182 struct cras_observer_alert_data_active_node *node_data =
183 (struct cras_observer_alert_data_active_node *)data;
184
185 DL_FOREACH (g_observer->clients, client) {
186 if (client->ops.active_node_changed)
187 client->ops.active_node_changed(client->context,
188 node_data->direction,
189 node_data->node_id);
190 }
191 }
192
output_node_volume_alert(void * arg,void * data)193 static void output_node_volume_alert(void *arg, void *data)
194 {
195 struct cras_observer_client *client;
196 struct cras_observer_alert_data_node_volume *node_data =
197 (struct cras_observer_alert_data_node_volume *)data;
198
199 DL_FOREACH (g_observer->clients, client) {
200 if (client->ops.output_node_volume_changed)
201 client->ops.output_node_volume_changed(
202 client->context, node_data->node_id,
203 node_data->volume);
204 }
205 }
206
node_left_right_swapped_alert(void * arg,void * data)207 static void node_left_right_swapped_alert(void *arg, void *data)
208 {
209 struct cras_observer_client *client;
210 struct cras_observer_alert_data_node_lr_swapped *node_data =
211 (struct cras_observer_alert_data_node_lr_swapped *)data;
212
213 DL_FOREACH (g_observer->clients, client) {
214 if (client->ops.node_left_right_swapped_changed)
215 client->ops.node_left_right_swapped_changed(
216 client->context, node_data->node_id,
217 node_data->swapped);
218 }
219 }
220
input_node_gain_alert(void * arg,void * data)221 static void input_node_gain_alert(void *arg, void *data)
222 {
223 struct cras_observer_client *client;
224 struct cras_observer_alert_data_node_volume *node_data =
225 (struct cras_observer_alert_data_node_volume *)data;
226
227 DL_FOREACH (g_observer->clients, client) {
228 if (client->ops.input_node_gain_changed)
229 client->ops.input_node_gain_changed(client->context,
230 node_data->node_id,
231 node_data->volume);
232 }
233 }
234
suspend_changed_alert(void * arg,void * data)235 static void suspend_changed_alert(void *arg, void *data)
236 {
237 struct cras_observer_client *client;
238 struct cras_observer_alert_data_suspend *suspend_data =
239 (struct cras_observer_alert_data_suspend *)data;
240
241 DL_FOREACH (g_observer->clients, client) {
242 if (client->ops.suspend_changed)
243 client->ops.suspend_changed(client->context,
244 suspend_data->suspended);
245 }
246 }
247
num_active_streams_alert(void * arg,void * data)248 static void num_active_streams_alert(void *arg, void *data)
249 {
250 struct cras_observer_client *client;
251 struct cras_observer_alert_data_streams *streams_data =
252 (struct cras_observer_alert_data_streams *)data;
253
254 DL_FOREACH (g_observer->clients, client) {
255 if (client->ops.num_active_streams_changed)
256 client->ops.num_active_streams_changed(
257 client->context, streams_data->direction,
258 streams_data->num_active_streams);
259 }
260 }
261
num_input_streams_with_permission_alert(void * arg,void * data)262 static void num_input_streams_with_permission_alert(void *arg, void *data)
263 {
264 struct cras_observer_client *client;
265 struct cras_observer_alert_data_input_streams *input_streams_data =
266 (struct cras_observer_alert_data_input_streams *)data;
267
268 DL_FOREACH (g_observer->clients, client) {
269 if (client->ops.num_input_streams_with_permission_changed)
270 client->ops.num_input_streams_with_permission_changed(
271 client->context,
272 input_streams_data->num_input_streams);
273 }
274 }
275
hotword_triggered_alert(void * arg,void * data)276 static void hotword_triggered_alert(void *arg, void *data)
277 {
278 struct cras_observer_client *client;
279 struct cras_observer_alert_data_hotword_triggered *triggered_data =
280 (struct cras_observer_alert_data_hotword_triggered *)data;
281
282 DL_FOREACH (g_observer->clients, client) {
283 if (client->ops.hotword_triggered)
284 client->ops.hotword_triggered(client->context,
285 triggered_data->tv_sec,
286 triggered_data->tv_nsec);
287 }
288 }
289
non_empty_audio_state_changed_alert(void * arg,void * data)290 static void non_empty_audio_state_changed_alert(void *arg, void *data)
291 {
292 struct cras_observer_client *client;
293 struct cras_observer_non_empty_audio_state *non_empty_audio_data =
294 (struct cras_observer_non_empty_audio_state *)data;
295
296 DL_FOREACH (g_observer->clients, client) {
297 if (client->ops.non_empty_audio_state_changed) {
298 client->ops.non_empty_audio_state_changed(
299 client->context,
300 non_empty_audio_data->non_empty);
301 }
302 }
303 }
304
bt_battery_changed_alert(void * arg,void * data)305 static void bt_battery_changed_alert(void *arg, void *data)
306 {
307 struct cras_observer_client *client;
308 struct cras_observer_alert_data_bt_battery_changed *triggered_data =
309 (struct cras_observer_alert_data_bt_battery_changed *)data;
310
311 DL_FOREACH (g_observer->clients, client) {
312 if (client->ops.bt_battery_changed)
313 client->ops.bt_battery_changed(client->context,
314 triggered_data->address,
315 triggered_data->level);
316 }
317 }
318
cras_observer_server_set_alert(struct cras_alert ** alert,cras_alert_cb cb,cras_alert_prepare prepare,unsigned int flags)319 static int cras_observer_server_set_alert(struct cras_alert **alert,
320 cras_alert_cb cb,
321 cras_alert_prepare prepare,
322 unsigned int flags)
323 {
324 *alert = cras_alert_create(prepare, flags);
325 if (!*alert)
326 return -ENOMEM;
327 return cras_alert_add_callback(*alert, cb, NULL);
328 }
329
330 #define CRAS_OBSERVER_SET_ALERT(alert, prepare, flags) \
331 do { \
332 rc = cras_observer_server_set_alert(&g_observer->alerts.alert, \
333 alert##_alert, prepare, \
334 flags); \
335 if (rc) \
336 goto error; \
337 } while (0)
338
339 #define CRAS_OBSERVER_SET_ALERT_WITH_DIRECTION(alert, direction) \
340 do { \
341 rc = cras_observer_server_set_alert( \
342 &g_observer->alerts.alert[direction], alert##_alert, \
343 NULL, 0); \
344 if (rc) \
345 goto error; \
346 } while (0)
347
348 /*
349 * Public interface
350 */
351
cras_observer_server_init()352 int cras_observer_server_init()
353 {
354 int rc;
355
356 memset(&g_empty_ops, 0, sizeof(g_empty_ops));
357 g_observer = (struct cras_observer_server *)calloc(
358 1, sizeof(struct cras_observer_server));
359 if (!g_observer)
360 return -ENOMEM;
361
362 CRAS_OBSERVER_SET_ALERT(output_volume, NULL, 0);
363 CRAS_OBSERVER_SET_ALERT(output_mute, NULL, 0);
364 CRAS_OBSERVER_SET_ALERT(capture_gain, NULL, 0);
365 CRAS_OBSERVER_SET_ALERT(capture_mute, NULL, 0);
366 CRAS_OBSERVER_SET_ALERT(nodes, nodes_prepare, 0);
367 CRAS_OBSERVER_SET_ALERT(active_node, nodes_prepare,
368 CRAS_ALERT_FLAG_KEEP_ALL_DATA);
369 CRAS_OBSERVER_SET_ALERT(output_node_volume, NULL, 0);
370 CRAS_OBSERVER_SET_ALERT(node_left_right_swapped, NULL, 0);
371 CRAS_OBSERVER_SET_ALERT(input_node_gain, NULL, 0);
372 CRAS_OBSERVER_SET_ALERT(suspend_changed, NULL, 0);
373 CRAS_OBSERVER_SET_ALERT(hotword_triggered, NULL, 0);
374 CRAS_OBSERVER_SET_ALERT(non_empty_audio_state_changed, NULL, 0);
375 CRAS_OBSERVER_SET_ALERT(bt_battery_changed, NULL, 0);
376 CRAS_OBSERVER_SET_ALERT(num_input_streams_with_permission, NULL, 0);
377
378 CRAS_OBSERVER_SET_ALERT_WITH_DIRECTION(num_active_streams,
379 CRAS_STREAM_OUTPUT);
380 CRAS_OBSERVER_SET_ALERT_WITH_DIRECTION(num_active_streams,
381 CRAS_STREAM_INPUT);
382 CRAS_OBSERVER_SET_ALERT_WITH_DIRECTION(num_active_streams,
383 CRAS_STREAM_POST_MIX_PRE_DSP);
384
385 return 0;
386
387 error:
388 cras_observer_server_free();
389 return rc;
390 }
391
cras_observer_server_free()392 void cras_observer_server_free()
393 {
394 if (!g_observer)
395 return;
396 cras_alert_destroy(g_observer->alerts.output_volume);
397 cras_alert_destroy(g_observer->alerts.output_mute);
398 cras_alert_destroy(g_observer->alerts.capture_gain);
399 cras_alert_destroy(g_observer->alerts.capture_mute);
400 cras_alert_destroy(g_observer->alerts.nodes);
401 cras_alert_destroy(g_observer->alerts.active_node);
402 cras_alert_destroy(g_observer->alerts.output_node_volume);
403 cras_alert_destroy(g_observer->alerts.node_left_right_swapped);
404 cras_alert_destroy(g_observer->alerts.input_node_gain);
405 cras_alert_destroy(g_observer->alerts.suspend_changed);
406 cras_alert_destroy(g_observer->alerts.hotword_triggered);
407 cras_alert_destroy(g_observer->alerts.non_empty_audio_state_changed);
408 cras_alert_destroy(g_observer->alerts.bt_battery_changed);
409 cras_alert_destroy(
410 g_observer->alerts.num_input_streams_with_permission);
411 cras_alert_destroy(
412 g_observer->alerts.num_active_streams[CRAS_STREAM_OUTPUT]);
413 cras_alert_destroy(
414 g_observer->alerts.num_active_streams[CRAS_STREAM_INPUT]);
415 cras_alert_destroy(
416 g_observer->alerts
417 .num_active_streams[CRAS_STREAM_POST_MIX_PRE_DSP]);
418 free(g_observer);
419 g_observer = NULL;
420 }
421
cras_observer_ops_are_empty(const struct cras_observer_ops * ops)422 int cras_observer_ops_are_empty(const struct cras_observer_ops *ops)
423 {
424 return memcmp(ops, &g_empty_ops, sizeof(*ops)) == 0;
425 }
426
cras_observer_get_ops(const struct cras_observer_client * client,struct cras_observer_ops * ops)427 void cras_observer_get_ops(const struct cras_observer_client *client,
428 struct cras_observer_ops *ops)
429 {
430 if (!ops)
431 return;
432 if (!client)
433 memset(ops, 0, sizeof(*ops));
434 else
435 memcpy(ops, &client->ops, sizeof(*ops));
436 }
437
cras_observer_set_ops(struct cras_observer_client * client,const struct cras_observer_ops * ops)438 void cras_observer_set_ops(struct cras_observer_client *client,
439 const struct cras_observer_ops *ops)
440 {
441 if (!client)
442 return;
443 if (!ops)
444 memset(&client->ops, 0, sizeof(client->ops));
445 else
446 memcpy(&client->ops, ops, sizeof(client->ops));
447 }
448
449 struct cras_observer_client *
cras_observer_add(const struct cras_observer_ops * ops,void * context)450 cras_observer_add(const struct cras_observer_ops *ops, void *context)
451 {
452 struct cras_observer_client *client;
453
454 client = (struct cras_observer_client *)calloc(1, sizeof(*client));
455 if (!client)
456 return NULL;
457 client->context = context;
458 DL_APPEND(g_observer->clients, client);
459 cras_observer_set_ops(client, ops);
460 return client;
461 }
462
cras_observer_remove(struct cras_observer_client * client)463 void cras_observer_remove(struct cras_observer_client *client)
464 {
465 if (!client)
466 return;
467 DL_DELETE(g_observer->clients, client);
468 free(client);
469 }
470
471 /*
472 * Public interface for notifiers.
473 */
474
cras_observer_notify_output_volume(int32_t volume)475 void cras_observer_notify_output_volume(int32_t volume)
476 {
477 struct cras_observer_alert_data_volume data;
478
479 data.volume = volume;
480 cras_alert_pending_data(g_observer->alerts.output_volume, &data,
481 sizeof(data));
482 }
483
cras_observer_notify_output_mute(int muted,int user_muted,int mute_locked)484 void cras_observer_notify_output_mute(int muted, int user_muted,
485 int mute_locked)
486 {
487 struct cras_observer_alert_data_mute data;
488
489 data.muted = muted;
490 data.user_muted = user_muted;
491 data.mute_locked = mute_locked;
492 cras_alert_pending_data(g_observer->alerts.output_mute, &data,
493 sizeof(data));
494 }
495
cras_observer_notify_capture_gain(int32_t gain)496 void cras_observer_notify_capture_gain(int32_t gain)
497 {
498 struct cras_observer_alert_data_volume data;
499
500 data.volume = gain;
501 cras_alert_pending_data(g_observer->alerts.capture_gain, &data,
502 sizeof(data));
503 }
504
cras_observer_notify_capture_mute(int muted,int mute_locked)505 void cras_observer_notify_capture_mute(int muted, int mute_locked)
506 {
507 struct cras_observer_alert_data_mute data;
508
509 data.muted = muted;
510 data.user_muted = 0;
511 data.mute_locked = mute_locked;
512 cras_alert_pending_data(g_observer->alerts.capture_mute, &data,
513 sizeof(data));
514 }
515
cras_observer_notify_nodes(void)516 void cras_observer_notify_nodes(void)
517 {
518 cras_alert_pending(g_observer->alerts.nodes);
519 }
520
cras_observer_notify_active_node(enum CRAS_STREAM_DIRECTION dir,cras_node_id_t node_id)521 void cras_observer_notify_active_node(enum CRAS_STREAM_DIRECTION dir,
522 cras_node_id_t node_id)
523 {
524 struct cras_observer_alert_data_active_node data;
525
526 data.direction = dir;
527 data.node_id = node_id;
528 cras_alert_pending_data(g_observer->alerts.active_node, &data,
529 sizeof(data));
530 }
531
cras_observer_notify_output_node_volume(cras_node_id_t node_id,int32_t volume)532 void cras_observer_notify_output_node_volume(cras_node_id_t node_id,
533 int32_t volume)
534 {
535 struct cras_observer_alert_data_node_volume data;
536
537 data.node_id = node_id;
538 data.volume = volume;
539 cras_alert_pending_data(g_observer->alerts.output_node_volume, &data,
540 sizeof(data));
541 }
542
cras_observer_notify_node_left_right_swapped(cras_node_id_t node_id,int swapped)543 void cras_observer_notify_node_left_right_swapped(cras_node_id_t node_id,
544 int swapped)
545 {
546 struct cras_observer_alert_data_node_lr_swapped data;
547
548 data.node_id = node_id;
549 data.swapped = swapped;
550 cras_alert_pending_data(g_observer->alerts.node_left_right_swapped,
551 &data, sizeof(data));
552 }
553
cras_observer_notify_input_node_gain(cras_node_id_t node_id,int32_t gain)554 void cras_observer_notify_input_node_gain(cras_node_id_t node_id, int32_t gain)
555 {
556 struct cras_observer_alert_data_node_volume data;
557
558 data.node_id = node_id;
559 data.volume = gain;
560 cras_alert_pending_data(g_observer->alerts.input_node_gain, &data,
561 sizeof(data));
562 }
563
cras_observer_notify_suspend_changed(int suspended)564 void cras_observer_notify_suspend_changed(int suspended)
565 {
566 struct cras_observer_alert_data_suspend data;
567
568 data.suspended = suspended;
569 cras_alert_pending_data(g_observer->alerts.suspend_changed, &data,
570 sizeof(data));
571 }
572
cras_observer_notify_num_active_streams(enum CRAS_STREAM_DIRECTION dir,uint32_t num_active_streams)573 void cras_observer_notify_num_active_streams(enum CRAS_STREAM_DIRECTION dir,
574 uint32_t num_active_streams)
575 {
576 struct cras_observer_alert_data_streams data;
577 struct cras_alert *alert;
578
579 data.direction = dir;
580 data.num_active_streams = num_active_streams;
581 alert = g_observer->alerts.num_active_streams[dir];
582 if (!alert)
583 return;
584
585 cras_alert_pending_data(alert, &data, sizeof(data));
586 }
587
cras_observer_notify_input_streams_with_permission(uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE])588 void cras_observer_notify_input_streams_with_permission(
589 uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE])
590 {
591 struct cras_observer_alert_data_input_streams data;
592 struct cras_alert *alert;
593
594 memcpy(&data.num_input_streams, num_input_streams,
595 sizeof(*num_input_streams) * CRAS_NUM_CLIENT_TYPE);
596 alert = g_observer->alerts.num_input_streams_with_permission;
597 if (!alert)
598 return;
599
600 cras_alert_pending_data(alert, &data, sizeof(data));
601 }
602
cras_observer_notify_hotword_triggered(int64_t tv_sec,int64_t tv_nsec)603 void cras_observer_notify_hotword_triggered(int64_t tv_sec, int64_t tv_nsec)
604 {
605 struct cras_observer_alert_data_hotword_triggered data;
606
607 data.tv_sec = tv_sec;
608 data.tv_nsec = tv_nsec;
609 cras_alert_pending_data(g_observer->alerts.hotword_triggered, &data,
610 sizeof(data));
611 }
612
cras_observer_notify_non_empty_audio_state_changed(int non_empty)613 void cras_observer_notify_non_empty_audio_state_changed(int non_empty)
614 {
615 struct cras_observer_non_empty_audio_state data;
616
617 data.non_empty = non_empty;
618
619 cras_alert_pending_data(
620 g_observer->alerts.non_empty_audio_state_changed, &data,
621 sizeof(data));
622 }
623
cras_observer_notify_bt_battery_changed(const char * address,uint32_t level)624 void cras_observer_notify_bt_battery_changed(const char *address,
625 uint32_t level)
626 {
627 struct cras_observer_alert_data_bt_battery_changed data;
628
629 data.address = address;
630 data.level = level;
631
632 cras_alert_pending_data(g_observer->alerts.bt_battery_changed, &data,
633 sizeof(data));
634 }
635