diff options
Diffstat (limited to 'cras/src/server/cras_observer.c')
-rw-r--r-- | cras/src/server/cras_observer.c | 634 |
1 files changed, 0 insertions, 634 deletions
diff --git a/cras/src/server/cras_observer.c b/cras/src/server/cras_observer.c deleted file mode 100644 index 0f17dc92..00000000 --- a/cras/src/server/cras_observer.c +++ /dev/null @@ -1,634 +0,0 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "cras_observer.h" - -#include "cras_alert.h" -#include "cras_iodev_list.h" -#include "cras_types.h" -#include "utlist.h" - -struct cras_observer_client { - struct cras_observer_ops ops; - void *context; - struct cras_observer_client *next, *prev; -}; - -struct cras_observer_alerts { - struct cras_alert *output_volume; - struct cras_alert *output_mute; - struct cras_alert *capture_gain; - struct cras_alert *capture_mute; - struct cras_alert *nodes; - struct cras_alert *active_node; - struct cras_alert *output_node_volume; - struct cras_alert *node_left_right_swapped; - struct cras_alert *input_node_gain; - struct cras_alert *suspend_changed; - struct cras_alert *hotword_triggered; - /* If all events for active streams went through a single alert then - * we might miss some because the alert code does not send every - * alert message. To ensure that the event sent contains the correct - * number of active streams per direction, make the alerts - * per-direciton. */ - struct cras_alert *num_active_streams[CRAS_NUM_DIRECTIONS]; - struct cras_alert *non_empty_audio_state_changed; - struct cras_alert *bt_battery_changed; - struct cras_alert *num_input_streams_with_permission; -}; - -struct cras_observer_server { - struct cras_observer_alerts alerts; - struct cras_observer_client *clients; -}; - -struct cras_observer_alert_data_volume { - int32_t volume; -}; - -struct cras_observer_alert_data_mute { - int muted; - int user_muted; - int mute_locked; -}; - -struct cras_observer_alert_data_active_node { - enum CRAS_STREAM_DIRECTION direction; - cras_node_id_t node_id; -}; - -struct cras_observer_alert_data_node_volume { - cras_node_id_t node_id; - int32_t volume; -}; - -struct cras_observer_alert_data_node_lr_swapped { - cras_node_id_t node_id; - int swapped; -}; - -struct cras_observer_alert_data_suspend { - int suspended; -}; - -struct cras_observer_alert_data_streams { - enum CRAS_STREAM_DIRECTION direction; - uint32_t num_active_streams; -}; - -struct cras_observer_alert_data_input_streams { - uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE]; -}; - -struct cras_observer_alert_data_hotword_triggered { - int64_t tv_sec; - int64_t tv_nsec; -}; - -struct cras_observer_non_empty_audio_state { - int non_empty; -}; - -struct cras_observer_alert_data_bt_battery_changed { - const char *address; - uint32_t level; -}; - -/* Global observer instance. */ -static struct cras_observer_server *g_observer; - -/* Empty observer ops. */ -static struct cras_observer_ops g_empty_ops; - -/* - * Alert handlers for delayed callbacks. - */ - -static void output_volume_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_volume *volume_data = - (struct cras_observer_alert_data_volume *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.output_volume_changed) - client->ops.output_volume_changed(client->context, - volume_data->volume); - } -} - -static void output_mute_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_mute *mute_data = - (struct cras_observer_alert_data_mute *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.output_mute_changed) - client->ops.output_mute_changed(client->context, - mute_data->muted, - mute_data->user_muted, - mute_data->mute_locked); - } -} - -static void capture_gain_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_volume *volume_data = - (struct cras_observer_alert_data_volume *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.capture_gain_changed) - client->ops.capture_gain_changed(client->context, - volume_data->volume); - } -} - -static void capture_mute_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_mute *mute_data = - (struct cras_observer_alert_data_mute *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.capture_mute_changed) - client->ops.capture_mute_changed( - client->context, mute_data->muted, - mute_data->mute_locked); - } -} - -static void nodes_prepare(struct cras_alert *alert) -{ - cras_iodev_list_update_device_list(); -} - -static void nodes_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.nodes_changed) - client->ops.nodes_changed(client->context); - } -} - -static void active_node_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_active_node *node_data = - (struct cras_observer_alert_data_active_node *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.active_node_changed) - client->ops.active_node_changed(client->context, - node_data->direction, - node_data->node_id); - } -} - -static void output_node_volume_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_node_volume *node_data = - (struct cras_observer_alert_data_node_volume *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.output_node_volume_changed) - client->ops.output_node_volume_changed( - client->context, node_data->node_id, - node_data->volume); - } -} - -static void node_left_right_swapped_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_node_lr_swapped *node_data = - (struct cras_observer_alert_data_node_lr_swapped *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.node_left_right_swapped_changed) - client->ops.node_left_right_swapped_changed( - client->context, node_data->node_id, - node_data->swapped); - } -} - -static void input_node_gain_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_node_volume *node_data = - (struct cras_observer_alert_data_node_volume *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.input_node_gain_changed) - client->ops.input_node_gain_changed(client->context, - node_data->node_id, - node_data->volume); - } -} - -static void suspend_changed_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_suspend *suspend_data = - (struct cras_observer_alert_data_suspend *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.suspend_changed) - client->ops.suspend_changed(client->context, - suspend_data->suspended); - } -} - -static void num_active_streams_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_streams *streams_data = - (struct cras_observer_alert_data_streams *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.num_active_streams_changed) - client->ops.num_active_streams_changed( - client->context, streams_data->direction, - streams_data->num_active_streams); - } -} - -static void num_input_streams_with_permission_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_input_streams *input_streams_data = - (struct cras_observer_alert_data_input_streams *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.num_input_streams_with_permission_changed) - client->ops.num_input_streams_with_permission_changed( - client->context, - input_streams_data->num_input_streams); - } -} - -static void hotword_triggered_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_hotword_triggered *triggered_data = - (struct cras_observer_alert_data_hotword_triggered *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.hotword_triggered) - client->ops.hotword_triggered(client->context, - triggered_data->tv_sec, - triggered_data->tv_nsec); - } -} - -static void non_empty_audio_state_changed_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_non_empty_audio_state *non_empty_audio_data = - (struct cras_observer_non_empty_audio_state *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.non_empty_audio_state_changed) { - client->ops.non_empty_audio_state_changed( - client->context, - non_empty_audio_data->non_empty); - } - } -} - -static void bt_battery_changed_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_bt_battery_changed *triggered_data = - (struct cras_observer_alert_data_bt_battery_changed *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.bt_battery_changed) - client->ops.bt_battery_changed(client->context, - triggered_data->address, - triggered_data->level); - } -} - -static int cras_observer_server_set_alert(struct cras_alert **alert, - cras_alert_cb cb, - cras_alert_prepare prepare, - unsigned int flags) -{ - *alert = cras_alert_create(prepare, flags); - if (!*alert) - return -ENOMEM; - return cras_alert_add_callback(*alert, cb, NULL); -} - -#define CRAS_OBSERVER_SET_ALERT(alert, prepare, flags) \ - do { \ - rc = cras_observer_server_set_alert(&g_observer->alerts.alert, \ - alert##_alert, prepare, \ - flags); \ - if (rc) \ - goto error; \ - } while (0) - -#define CRAS_OBSERVER_SET_ALERT_WITH_DIRECTION(alert, direction) \ - do { \ - rc = cras_observer_server_set_alert( \ - &g_observer->alerts.alert[direction], alert##_alert, \ - NULL, 0); \ - if (rc) \ - goto error; \ - } while (0) - -/* - * Public interface - */ - -int cras_observer_server_init() -{ - int rc; - - memset(&g_empty_ops, 0, sizeof(g_empty_ops)); - g_observer = (struct cras_observer_server *)calloc( - 1, sizeof(struct cras_observer_server)); - if (!g_observer) - return -ENOMEM; - - CRAS_OBSERVER_SET_ALERT(output_volume, NULL, 0); - CRAS_OBSERVER_SET_ALERT(output_mute, NULL, 0); - CRAS_OBSERVER_SET_ALERT(capture_gain, NULL, 0); - CRAS_OBSERVER_SET_ALERT(capture_mute, NULL, 0); - CRAS_OBSERVER_SET_ALERT(nodes, nodes_prepare, 0); - CRAS_OBSERVER_SET_ALERT(active_node, nodes_prepare, - CRAS_ALERT_FLAG_KEEP_ALL_DATA); - CRAS_OBSERVER_SET_ALERT(output_node_volume, NULL, 0); - CRAS_OBSERVER_SET_ALERT(node_left_right_swapped, NULL, 0); - CRAS_OBSERVER_SET_ALERT(input_node_gain, NULL, 0); - CRAS_OBSERVER_SET_ALERT(suspend_changed, NULL, 0); - CRAS_OBSERVER_SET_ALERT(hotword_triggered, NULL, 0); - CRAS_OBSERVER_SET_ALERT(non_empty_audio_state_changed, NULL, 0); - CRAS_OBSERVER_SET_ALERT(bt_battery_changed, NULL, 0); - CRAS_OBSERVER_SET_ALERT(num_input_streams_with_permission, NULL, 0); - - CRAS_OBSERVER_SET_ALERT_WITH_DIRECTION(num_active_streams, - CRAS_STREAM_OUTPUT); - CRAS_OBSERVER_SET_ALERT_WITH_DIRECTION(num_active_streams, - CRAS_STREAM_INPUT); - CRAS_OBSERVER_SET_ALERT_WITH_DIRECTION(num_active_streams, - CRAS_STREAM_POST_MIX_PRE_DSP); - - return 0; - -error: - cras_observer_server_free(); - return rc; -} - -void cras_observer_server_free() -{ - if (!g_observer) - return; - cras_alert_destroy(g_observer->alerts.output_volume); - cras_alert_destroy(g_observer->alerts.output_mute); - cras_alert_destroy(g_observer->alerts.capture_gain); - cras_alert_destroy(g_observer->alerts.capture_mute); - cras_alert_destroy(g_observer->alerts.nodes); - cras_alert_destroy(g_observer->alerts.active_node); - cras_alert_destroy(g_observer->alerts.output_node_volume); - cras_alert_destroy(g_observer->alerts.node_left_right_swapped); - cras_alert_destroy(g_observer->alerts.input_node_gain); - cras_alert_destroy(g_observer->alerts.suspend_changed); - cras_alert_destroy(g_observer->alerts.hotword_triggered); - cras_alert_destroy(g_observer->alerts.non_empty_audio_state_changed); - cras_alert_destroy(g_observer->alerts.bt_battery_changed); - cras_alert_destroy( - g_observer->alerts.num_input_streams_with_permission); - cras_alert_destroy( - g_observer->alerts.num_active_streams[CRAS_STREAM_OUTPUT]); - cras_alert_destroy( - g_observer->alerts.num_active_streams[CRAS_STREAM_INPUT]); - cras_alert_destroy( - g_observer->alerts - .num_active_streams[CRAS_STREAM_POST_MIX_PRE_DSP]); - free(g_observer); - g_observer = NULL; -} - -int cras_observer_ops_are_empty(const struct cras_observer_ops *ops) -{ - return memcmp(ops, &g_empty_ops, sizeof(*ops)) == 0; -} - -void cras_observer_get_ops(const struct cras_observer_client *client, - struct cras_observer_ops *ops) -{ - if (!ops) - return; - if (!client) - memset(ops, 0, sizeof(*ops)); - else - memcpy(ops, &client->ops, sizeof(*ops)); -} - -void cras_observer_set_ops(struct cras_observer_client *client, - const struct cras_observer_ops *ops) -{ - if (!client) - return; - if (!ops) - memset(&client->ops, 0, sizeof(client->ops)); - else - memcpy(&client->ops, ops, sizeof(client->ops)); -} - -struct cras_observer_client * -cras_observer_add(const struct cras_observer_ops *ops, void *context) -{ - struct cras_observer_client *client; - - client = (struct cras_observer_client *)calloc(1, sizeof(*client)); - if (!client) - return NULL; - client->context = context; - DL_APPEND(g_observer->clients, client); - cras_observer_set_ops(client, ops); - return client; -} - -void cras_observer_remove(struct cras_observer_client *client) -{ - if (!client) - return; - DL_DELETE(g_observer->clients, client); - free(client); -} - -/* - * Public interface for notifiers. - */ - -void cras_observer_notify_output_volume(int32_t volume) -{ - struct cras_observer_alert_data_volume data; - - data.volume = volume; - cras_alert_pending_data(g_observer->alerts.output_volume, &data, - sizeof(data)); -} - -void cras_observer_notify_output_mute(int muted, int user_muted, - int mute_locked) -{ - struct cras_observer_alert_data_mute data; - - data.muted = muted; - data.user_muted = user_muted; - data.mute_locked = mute_locked; - cras_alert_pending_data(g_observer->alerts.output_mute, &data, - sizeof(data)); -} - -void cras_observer_notify_capture_gain(int32_t gain) -{ - struct cras_observer_alert_data_volume data; - - data.volume = gain; - cras_alert_pending_data(g_observer->alerts.capture_gain, &data, - sizeof(data)); -} - -void cras_observer_notify_capture_mute(int muted, int mute_locked) -{ - struct cras_observer_alert_data_mute data; - - data.muted = muted; - data.user_muted = 0; - data.mute_locked = mute_locked; - cras_alert_pending_data(g_observer->alerts.capture_mute, &data, - sizeof(data)); -} - -void cras_observer_notify_nodes(void) -{ - cras_alert_pending(g_observer->alerts.nodes); -} - -void cras_observer_notify_active_node(enum CRAS_STREAM_DIRECTION dir, - cras_node_id_t node_id) -{ - struct cras_observer_alert_data_active_node data; - - data.direction = dir; - data.node_id = node_id; - cras_alert_pending_data(g_observer->alerts.active_node, &data, - sizeof(data)); -} - -void cras_observer_notify_output_node_volume(cras_node_id_t node_id, - int32_t volume) -{ - struct cras_observer_alert_data_node_volume data; - - data.node_id = node_id; - data.volume = volume; - cras_alert_pending_data(g_observer->alerts.output_node_volume, &data, - sizeof(data)); -} - -void cras_observer_notify_node_left_right_swapped(cras_node_id_t node_id, - int swapped) -{ - struct cras_observer_alert_data_node_lr_swapped data; - - data.node_id = node_id; - data.swapped = swapped; - cras_alert_pending_data(g_observer->alerts.node_left_right_swapped, - &data, sizeof(data)); -} - -void cras_observer_notify_input_node_gain(cras_node_id_t node_id, int32_t gain) -{ - struct cras_observer_alert_data_node_volume data; - - data.node_id = node_id; - data.volume = gain; - cras_alert_pending_data(g_observer->alerts.input_node_gain, &data, - sizeof(data)); -} - -void cras_observer_notify_suspend_changed(int suspended) -{ - struct cras_observer_alert_data_suspend data; - - data.suspended = suspended; - cras_alert_pending_data(g_observer->alerts.suspend_changed, &data, - sizeof(data)); -} - -void cras_observer_notify_num_active_streams(enum CRAS_STREAM_DIRECTION dir, - uint32_t num_active_streams) -{ - struct cras_observer_alert_data_streams data; - struct cras_alert *alert; - - data.direction = dir; - data.num_active_streams = num_active_streams; - alert = g_observer->alerts.num_active_streams[dir]; - if (!alert) - return; - - cras_alert_pending_data(alert, &data, sizeof(data)); -} - -void cras_observer_notify_input_streams_with_permission( - uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE]) -{ - struct cras_observer_alert_data_input_streams data; - struct cras_alert *alert; - - memcpy(&data.num_input_streams, num_input_streams, - sizeof(*num_input_streams) * CRAS_NUM_CLIENT_TYPE); - alert = g_observer->alerts.num_input_streams_with_permission; - if (!alert) - return; - - cras_alert_pending_data(alert, &data, sizeof(data)); -} - -void cras_observer_notify_hotword_triggered(int64_t tv_sec, int64_t tv_nsec) -{ - struct cras_observer_alert_data_hotword_triggered data; - - data.tv_sec = tv_sec; - data.tv_nsec = tv_nsec; - cras_alert_pending_data(g_observer->alerts.hotword_triggered, &data, - sizeof(data)); -} - -void cras_observer_notify_non_empty_audio_state_changed(int non_empty) -{ - struct cras_observer_non_empty_audio_state data; - - data.non_empty = non_empty; - - cras_alert_pending_data( - g_observer->alerts.non_empty_audio_state_changed, &data, - sizeof(data)); -} - -void cras_observer_notify_bt_battery_changed(const char *address, - uint32_t level) -{ - struct cras_observer_alert_data_bt_battery_changed data; - - data.address = address; - data.level = level; - - cras_alert_pending_data(g_observer->alerts.bt_battery_changed, &data, - sizeof(data)); -} |