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